Android 決済アプリを Web Payments と連携させ、お客様のユーザー エクスペリエンスを向上させる方法について説明します。
Payment Request API は、 必要な支払いを入力できる、組み込みのブラウザベースのインターフェース 情報を簡単に入手できます。この API では、プラットフォーム固有の支払いサービスも 。
対応ブラウザ
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
Web Payments を使用すると、Android のインテントのみを使用する場合に比べて、 ブラウザ、セキュリティ、ユーザー エクスペリエンスのバランスを取ります。
- 決済アプリが販売者のウェブサイトのコンテキスト内でモーダルとして起動される。
- 実装は既存の決済アプリを補完するもので、以下のことが可能になります。 ユーザーベースを活用できます
- 決済アプリの署名は、 サイドローディング。
- 決済アプリは複数のお支払い方法に対応できます。
- 仮想通貨や銀行振込など、あらゆる支払い方法が 統合されていますAndroid デバイスの決済アプリには、 デバイスのハードウェア チップにアクセスする必要がある。
Android 決済アプリにウェブ決済を実装するには、次の 4 つのステップを行います。
- 販売者が決済アプリを検出できるようにします。
- お客様がお支払い方法(クレジットなど)を登録しているかどうかを販売者に知らせます。 カード)が表示されます。
- お客様に支払いを行ってもらいます。
- 呼び出し元の署名証明書を検証します。
Web Payments の実際の動作については、 android-web-payment 説明します。
ステップ 1: 販売者が決済アプリを検出できるようにする
販売者がお客様の決済アプリを使用するには、Google Pay Request API と ご利用いただけるお支払い方法を指定します。 できます。
決済アプリに固有のお支払い方法 ID がある場合、 独自の支払い方法を設定できる マニフェストを使用して、ブラウザが 表示されます。
ステップ 2: お客様のお支払い方法が支払い可能な状態になっているかどうかを販売者に知らせる
販売者は hasEnrolledInstrument()
を呼び出して、顧客が
ユーザーが支払いを行うことができます。Google Chat では
このクエリに応答するために、IS_READY_TO_PAY
を Android サービスとして実装します。
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 で定義されています。2 つの 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 逆シリアル化によって販売者の JavaScript オブジェクトに変換しますが、
それ以外はいかなる有効性も強制しません。ブラウザは、
details
、パラメータの値が販売者に直接渡されます。
AndroidManifest.xml
PAY
インテント フィルタが設定されたアクティビティには、<meta-data>
タグ
デフォルトの支払い方法 ID を識別します。
アプリ。
複数のお支払い方法をサポートするには、<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
は文字列のリストにする必要があります。各文字列は有効な文字列である必要があります。
HTTPS スキームを使用した絶対 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>
ブラウザのトップレベルのブラウジング コンテキストなど)が、
val merchantName: String? = extras.getString("merchantName")
topLevelOrigin
スキームのない販売者のオリジン(スキームのないオリジン
。たとえば、https://mystore.com/checkout
は次のようになります。
mystore.com
として渡されます。
val topLevelOrigin: String? = extras.getString("topLevelOrigin")
topLevelCertificateChain
販売者の証明書チェーン(最上位の
閲覧コンテキストなど)が含まれます。ローカルホストとディスク上のファイルには null(どちらも安全)
SSL 証明書なしのコンテキストで識別されます。各 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
「push-payment」の 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()
インテント エクストラとして次の 2 つのパラメータを指定する必要があります。
methodName
: 使用されているメソッドの名前。details
: 販売者が行うために必要な情報を含む JSON 文字列。 トランザクションを完了します。成功がtrue
の場合、details
はJSON.parse(details)
が成功するように構築します。
トランザクションが完了していない場合は RESULT_CANCELED
を渡すことができます。
たとえば、ユーザーが Google Pay で PIN コードの正しい入力に失敗した場合などです。
。ブラウザでは、ユーザーがリクエストする内容を
別の決済アプリを使用していました
setResult(RESULT_CANCELED)
finish()
呼び出された支払いから受信した支払いレスポンスのアクティビティの結果
アプリが RESULT_OK
に設定されている場合、Chrome は空でない methodName
の有無を確認し、
エクストラで details
。検証で不合格だと、Chrome は不承認の
次のいずれかのデベロッパー向けエラーを含む request.show()
からの Promise
メッセージ:
'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 以降をターゲットとし、ブラウザと統合する場合
署名証明書が 1 つしかない場合は、
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 には
単一の署名証明書を使用します)。複数の署名証明書があるアプリの場合、
回転させます。
27 以前の古い API レベルをサポートする必要がある場合、または
複数の署名証明書を持つブラウザでは、
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) } }