Android 결제 앱이 웹 결제와 호환되도록 조정하고 고객에게 더 나은 사용자 환경을 제공하는 방법을 알아보세요.
Payment Request API는 웹 기반 기본 제공 브라우저 기반 인터페이스를 통해 사용자가 결제 금액을 입력할 수 있습니다. 훨씬 더 쉽게 정보를 얻을 수 있습니다. API는 플랫폼별 결제를 호출할 수도 있습니다. 있습니다.
브라우저 지원
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
Android 인텐트만 사용하는 것에 비해 웹 결제는 더 나은 통합 가능 사용자 환경을 개선할 수 있습니다.
- 결제 앱이 판매자 웹사이트의 컨텍스트에서 모달로 실행됩니다.
- 구현은 기존 결제 앱을 보완하는 것으로, 다음 작업을 할 수 있습니다. 활용할 수 있습니다
- 결제 앱의 서명이 사이드로드입니다.
- 결제 앱은 여러 결제 수단을 지원할 수 있습니다.
- 암호화폐, 은행 송금 등 모든 결제 수단을 통합되었습니다. Android 기기의 결제 앱은 기기의 하드웨어 칩에 액세스해야 합니다.
Android 결제 앱에서 웹 결제를 구현하려면 네 단계를 거쳐야 합니다.
- 판매자가 내 결제 앱을 찾을 수 있도록 허용합니다.
- 고객에게 등록된 결제 수단 (예: 크레딧)이 있는지 판매자에게 알려주세요. 카드)가 표시됩니다.
- 고객이 결제할 수 있도록 합니다.
- 호출자의 서명 인증서를 확인합니다.
웹 결제가 어떻게 작동하는지 확인하려면 android-web-payment 데모를 들을 수 있습니다.
1단계: 판매자가 결제 앱을 찾을 수 있도록 허용하기
판매자가 결제 앱을 사용하려면 Payment(결제) API 요청 및 결제 수단을 사용하여 지원하는 결제 수단 지정 사용됩니다.
결제 앱 고유의 결제 수단 식별자가 있는 경우 직접 결제 수단을 설정할 수 있음 매니페스트를 사용하여 브라우저가 찾을 수 있습니다.
2단계: 고객에게 결제 준비가 된 결제 수단이 등록되어 있는지 판매자에게 알림
판매자는 hasEnrolledInstrument()
를 호출하여 고객이
결제할 수 있습니다. 다음과 같은 작업을 할 수 있습니다.
이 쿼리에 답하기 위한 Android 서비스로 IS_READY_TO_PAY
를 구현합니다.
AndroidManifest.xml
작업이 있는 인텐트 필터로 서비스 선언
org.chromium.intent.action.IS_READY_TO_PAY
<service
android:name=".SampleIsReadyToPayService"
android:exported="true">
<intent-filter>
<action android:name="org.chromium.intent.action.IS_READY_TO_PAY" />
</intent-filter>
</service>
IS_READY_TO_PAY
서비스는 선택사항입니다.
웹 브라우저는 앱이 항상
있습니다.
AIDL
IS_READY_TO_PAY
서비스의 API는 AIDL로 정의됩니다. 두 개의 AIDL 만들기
다음 콘텐츠가 포함된 파일:
app/src/main/aidl/org/chromium/IsReadyToPayServiceCallback.aidl
package org.chromium;
interface IsReadyToPayServiceCallback {
oneway void handleIsReadyToPay(boolean isReadyToPay);
}
app/src/main/aidl/org/chromium/IsReadyToPayService.aidl
package org.chromium;
import org.chromium.IsReadyToPayServiceCallback;
interface IsReadyToPayService {
oneway void isReadyToPay(IsReadyToPayServiceCallback callback);
}
IsReadyToPayService
구현
IsReadyToPayService
의 가장 간단한 구현은 다음과 같습니다.
예:
class SampleIsReadyToPayService : Service() {
private val binder = object : IsReadyToPayService.Stub() {
override fun isReadyToPay(callback: IsReadyToPayServiceCallback?) {
callback?.handleIsReadyToPay(true)
}
}
override fun onBind(intent: Intent?): IBinder? {
return binder
}
}
응답
서비스는 handleIsReadyToPay(Boolean)
메서드를 통해 응답을 전송할 수 있습니다.
callback?.handleIsReadyToPay(true)
권한
Binder.getCallingUid()
를 사용하여 발신자를 확인할 수 있습니다. 참고:
onBind
메서드가 아닌 isReadyToPay
메서드에서 이 작업을 실행해야 합니다.
override fun isReadyToPay(callback: IsReadyToPayServiceCallback?) {
try {
val callingPackage = packageManager.getNameForUid(Binder.getCallingUid())
// …
자세한 내용은 발신자 서명 인증서 확인을 참조하세요. 호출 패키지의 서명이 올바른지 확인합니다.
3단계: 고객이 결제하도록 허용하기
판매자가 show()
를 호출하여 결제를 시작합니다.
앱
그래야 고객이 결제할 수 있습니다. 결제 앱이 Android
인텐트 매개변수에 트랜잭션 정보가 있는 인텐트 PAY
결제 앱이 결제 앱인 methodName
및 details
로 응답합니다.
브라우저에 대해 불투명합니다. 브라우저가 details
문자열을 JSON 역직렬화를 통해 판매자에 대한 자바스크립트 객체로 변환하지만
그 이상의 유효성을 적용하지 않습니다. 브라우저는
details
이 매개변수의 값이 판매자에게 직접 전달됩니다.
AndroidManifest.xml
인텐트 필터가 PAY
포함된 활동에는 <meta-data>
태그가 있어야
기본 결제 수단 식별자를 식별합니다.
앱을 엽니다.
여러 결제 수단을 지원하려면 <meta-data>
태그를 추가하고
<string-array>
리소스.
<activity
android:name=".PaymentActivity"
android:theme="@style/Theme.SamplePay.Dialog">
<intent-filter>
<action android:name="org.chromium.intent.action.PAY" />
</intent-filter>
<meta-data
android:name="org.chromium.default_payment_method_name"
android:value="https://bobbucks.dev/pay" />
<meta-data
android:name="org.chromium.payment_method_names"
android:resource="@array/method_names" />
</activity>
resource
는 문자열 목록이어야 하며 각각 유효한
절대 URL을 입력합니다.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="method_names">
<item>https://alicepay.com/put/optional/path/here</item>
<item>https://charliepay.com/put/optional/path/here</item>
</string-array>
</resources>
매개변수
다음 매개변수는 활동에 인텐트 추가 항목으로 전달됩니다.
methodNames
methodData
topLevelOrigin
topLevelCertificateChain
paymentRequestOrigin
total
modifiers
paymentRequestId
val extras: Bundle? = intent?.extras
methodNames
사용 중인 메서드의 이름입니다. 요소는
methodData
사전. 결제 앱에서 지원하는 결제 수단은 다음과 같습니다.
val methodNames: List<String>? = extras.getStringArrayList("methodNames")
methodData
각 methodNames
에서
methodData
val methodData: Bundle? = extras.getBundle("methodData")
merchantName
판매자의 결제 페이지에 있는 <title>
HTML 태그의 콘텐츠(
브라우저 최상위 탐색 컨텍스트)에 전달합니다.
val merchantName: String? = extras.getString("merchantName")
topLevelOrigin
스키마가 없는 판매자의 출처 (스키마 없는
최상위 탐색 컨텍스트) 예를 들어 https://mystore.com/checkout
는 다음과 같습니다.
mystore.com
로 전달됨
val topLevelOrigin: String? = extras.getString("topLevelOrigin")
topLevelCertificateChain
판매자의 인증서 체인 (최상위 도메인의 인증서 체인)
탐색 컨텍스트) localhost 및 디스크의 파일(모두 안전함)의 경우 Null
컨텍스트와 연동됩니다 각 Parcelable
은
certificate
키 및 바이트 배열 값.
val topLevelCertificateChain: Array<Parcelable>? =
extras.getParcelableArray("topLevelCertificateChain")
val list: List<ByteArray>? = topLevelCertificateChain?.mapNotNull { p ->
(p as Bundle).getByteArray("certificate")
}
paymentRequestOrigin
JavaScript에서 new
PaymentRequest(methodData, details, options)
생성자를 호출한 iframe 탐색 컨텍스트의 스키마가 없는 출처입니다. 만약
생성자가 최상위 컨텍스트에서 호출되면 이
매개변수는 topLevelOrigin
매개변수의 값과 같습니다.
val paymentRequestOrigin: String? = extras.getString("paymentRequestOrigin")
total
총 거래 금액을 나타내는 JSON 문자열입니다.
val total: String? = extras.getString("total")
다음은 문자열의 콘텐츠 예입니다.
{"currency":"USD","value":"25.00"}
modifiers
JSON.stringify(details.modifiers)
의 출력(여기서 details.modifiers
)
supportedMethods
및 total
만 포함합니다.
paymentRequestId
'푸시-결제'를 수행하는 PaymentRequest.id
필드 앱과 연결해야 하는 경우
트랜잭션 상태입니다. 판매자 웹사이트는 이 필드를 사용하여
"push-payment" 앱의 대역 외 거래 상태를 확인할 수 있습니다.
val paymentRequestId: String? = extras.getString("paymentRequestId")
응답
활동은 RESULT_OK
를 사용하여 setResult
를 통해 응답을 다시 보낼 수 있습니다.
setResult(Activity.RESULT_OK, Intent().apply {
putExtra("methodName", "https://bobbucks.dev/pay")
putExtra("details", "{\"token\": \"put-some-data-here\"}")
})
finish()
인텐트 추가 항목으로 두 매개변수를 지정해야 합니다.
methodName
: 사용 중인 메서드의 이름입니다.details
: 판매자가 거래를 완료할 수 있습니다 성공이true
인 경우details
는 구성되어야 합니다.JSON.parse(details)
다음에서 거래가 완료되지 않은 경우 RESULT_CANCELED
를 전달할 수 있습니다.
예를 들어 사용자가 결제 앱에서 사용할 수 있는 올바른 PIN 코드를
결제할 수 있습니다 브라우저에서 사용자가
확인할 수 있습니다.
setResult(RESULT_CANCELED)
finish()
호출된 결제로부터 결제 응답의 활동 결과가 수신된 경우
앱이 RESULT_OK
로 설정된 경우 Chrome은 비어 있지 않은 methodName
를 확인하고
details
입니다. 확인에 실패하면 Chrome에서 거부된
다음 개발자 중 하나에 오류가 발생한 request.show()
의 프로미스
메시지:
'Payment app returned invalid response. Missing field "details".'
'Payment app returned invalid response. Missing field "methodName".'
권한
활동은 getCallingPackage()
메서드로 호출자를 확인할 수 있습니다.
val caller: String? = callingPackage
마지막 단계는 호출자의 서명 인증서를 확인하여 호출 패키지의 서명이 올바른지 확인합니다.
4단계: 호출자의 서명 인증서 확인
Binder.getCallingUid()
를 사용하여 호출자의 패키지 이름을 확인할 수 있습니다.
IS_READY_TO_PAY
및 PAY
에서 Activity.getCallingPackage()
와(과) 공유 목표:
호출자가 염두에 두고 있는 브라우저인지 실제로 확인하면
서명 인증서가 올바른
값으로 사용됩니다.
API 수준 28 이상을 타겟팅하고 브라우저와 통합하는 경우
단일 서명 인증서가 있는 경우
PackageManager.hasSigningCertificate()
val packageName: String = … // The caller's package name
val certificate: ByteArray = … // The correct signing certificate.
val verified = packageManager.hasSigningCertificate(
callingPackage,
certificate,
PackageManager.CERT_INPUT_SHA256
)
단일 인증서에는 PackageManager.hasSigningCertificate()
를 사용하는 것이 좋습니다.
인증서 순환을 올바르게 처리하기 때문입니다. (Chrome에는
단일 서명 인증서로 교체할 수 있습니다.) 여러 서명 인증서가 있는 앱은
회전할 수도 있습니다.
이전 API 수준 27 이하를 지원해야 하거나
여러 서명 인증서가 있는 브라우저라면
PackageManager.GET_SIGNATURES
val packageName: String = … // The caller's package name
val certificates: Set<ByteArray> = … // The correct set of signing certificates
val packageInfo = getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
val sha256 = MessageDigest.getInstance("SHA-256")
val signatures = packageInfo.signatures.map { sha256.digest(it.toByteArray()) }
val verified = signatures.size == certificates.size &&
signatures.all { s -> certificates.any { it.contentEquals(s) } }