Android 支払いアプリから配送情報と連絡先情報を提供する

Web Payments API を使用して、Android 決済アプリを更新し、配送先住所と支払人の連絡先情報を提供する方法。

Sahel Sharify
Sahel Sharify

ウェブフォームから配送先住所や連絡先情報を入力する場合は、 顧客にとって煩雑な作業になりますエラーが発生してコンバージョン率が低下する可能性がある 。

そのため、Payment Request API では、配送をリクエストする機能をサポートしています。 住所と連絡先情報を入力します。これには、次のような複数のメリットがあります。

  • 数回タップするだけで正しい住所を選択できます。
  • 住所は常に標準化された標準 形式
  • 間違った住所を送信する可能性は低くなります。

ブラウザは、配送先住所と連絡先情報の収集を 決済アプリで統一された 支払いエクスペリエンスを提供しますこの機能は 委任と呼ばれます。

可能な場合は常に、Chrome が購入者の配送の集荷を委任する 呼び出される Android 決済アプリに住所と連絡先情報を渡す必要があります。「 委任によって購入手続きのわずらわしさを軽減できます。

販売者のウェブサイトで配送オプションと合計金額が動的に更新される お客様が選択した配送先住所と配送方法によって異なる 選択します。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
配送オプションと配送先住所の変更。配送オプションと合計金額に動的にどのように影響するかを確認します。
で確認できます。

既存の Android 決済アプリに委任サポートを追加するには: 次の手順を実施します

  1. サポートされている委任を宣言する
  2. PAY インテント エクストラを解析して支払いを求める オプションをご覧ください。
  3. お支払いに必要な情報を提供する レスポンス
  4. [省略可] 動的フローをサポートする: <ph type="x-smartling-placeholder">
      </ph>
    1. ユーザーが選択した支払い方法の変更について販売者に通知する 配送先住所、配送先住所 オプション
    2. 販売者から最新のお支払い情報を受け取る(例: 選択した配送オプションに基づいて調整された合計金額 費用)が表示されます。

サポートされている委任を宣言する

ブラウザは、支払いに使用する追加情報のリストを認識する必要があります に委任できるようにする必要があります。その情報の収集を 。サポートされている委任をアプリの <meta-data> として宣言します。 AndroidManifest.xml

<activity
  android:name=".PaymentActivity"
    <meta-data
    android:name="org.chromium.payment_supported_delegations"
    android:resource="@array/supported_delegations" />
</activity>

<resource> には、次の有効な値から選択した文字列のリストを指定する必要があります。

[ "payerName", "payerEmail", "payerPhone", "shippingAddress" ]

次の例では、配送先住所と支払人のメールアドレスのみを指定できます あります。

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string-array name="supported_delegations">
    <item>payerEmail</item>
    <item>shippingAddress</item>
  </string-array>
</resources>

PAY インテント エクストラを解析して必要な支払いオプションを取得

販売者は、 paymentOptions 使用します。アプリで使用できる必須オプションのリストが Chrome に表示されます。 次のパラメータを Intent として PAY アクティビティに渡して提供します。 あります。

paymentOptions

paymentOptions は、販売者が指定した支払いオプションのサブセットです。 アプリで委任サポートが宣言されています。

val paymentOptions: Bundle? = extras.getBundle("paymentOptions")
val requestPayerName: Boolean? = paymentOptions?.getBoolean("requestPayerName")
val requestPayerPhone: Boolean? = paymentOptions?.getBoolean("requestPayerPhone")
val requestPayerEmail: Boolean? = paymentOptions?.getBoolean("requestPayerEmail")
val requestShipping: Boolean? = paymentOptions?.getBoolean("requestShipping")
val shippingType: String? = paymentOptions?.getString("shippingType")

次のパラメータを含めることができます。

  • requestPayerName - 支払人の名前があるかどうかを示すブール値 は必須です。
  • requestPayerPhone - 購入者のスマートフォンが購入元かどうかを示すブール値 は必須です。
  • requestPayerEmail - 支払人のメールアドレスの有無を示すブール値 は必須です。
  • requestShipping - 配送情報かどうかを示すブール値 は必須です。
  • shippingType - 送料のタイプを示す文字列です。配送タイプは次のいずれかです。 "shipping""delivery"、または "pickup"。アプリはこのヒントを ユーザーの住所または配送オプションの選択を尋ねるときの UI。

shippingOptions

shippingOptions は、販売者が指定した送料の Parcelable 配列です。 。このパラメータは、paymentOptions.requestShipping == true の場合にのみ存在します。

val shippingOptions: List<ShippingOption>? =
    extras.getParcelableArray("shippingOptions")?.mapNotNull {
        p -> from(p as Bundle)
    }

各配送オプションは、次のキーを含む Bundle です。

  • id - 配送オプションの ID。
  • label - ユーザーに表示される配送オプションのラベル。
  • amount - キーと値を含む currency キーと value キーを含む送料セット 使用します。
  • selected - 配送オプションが 決済アプリに配送オプションが表示されている。

selected 以外のキーはすべて文字列値を持ちます。selected はブール値です あります。

val id: String = bundle.getString("id")
val label: String = bundle.getString("label")
val amount: Bundle = bundle.getBundle("amount")
val selected: Boolean = bundle.getBoolean("selected", false)

支払いレスポンスで必要な情報を提供する

アプリは、 PAY アクティビティ。

そのためには、以下のパラメータをインテント エクストラとして指定する必要があります。

  • payerName - 支払人の氏名。次の場合は空でない文字列にする必要があります。 paymentOptions.requestPayerName は true です。
  • payerPhone - 支払人の電話番号。次の場合は空でない文字列にする必要があります。 paymentOptions.requestPayerPhone は true です。
  • payerEmail - 支払人のメールアドレス。空でない文字列を指定してください paymentOptions.requestPayerEmail が true の場合。
  • shippingAddress - ユーザー指定の配送先住所。これは paymentOptions.requestShipping が true の場合は空でないバンドルを返します。バンドル 物理ハードウェアのさまざまな部分を表す、
    • city
    • countryCode
    • dependentLocality
    • organization
    • phone
    • postalCode
    • recipient
    • region
    • sortingCode
    • addressLine addressLine 以外のキーはすべて文字列値を持ちます。addressLine 文字列の配列です。
  • shippingOptionId - ユーザーが選択した配送オプションの ID。この paymentOptions.requestShipping が true の場合は、空でない文字列にする必要があります。

支払いレスポンスを検証する

呼び出された支払いから受信した支払いレスポンスのアクティビティの結果 アプリが RESULT_OK に設定されている場合、Chrome は必要な追加の 追加で指定できます。検証で不合格だと、Chrome は不承認の 次のいずれかのデベロッパー向けエラーを含む request.show() からの Promise メッセージ:

'Payment app returned invalid response. Missing field "payerEmail".'
'Payment app returned invalid response. Missing field "payerName".'
'Payment app returned invalid response. Missing field "payerPhone".'
'Payment app returned invalid shipping address in response.'
'... is not a valid CLDR country code, should be 2 upper case letters [A-Z]'
'Payment app returned invalid response. Missing field "shipping option".'

次のコードサンプルは、有効なレスポンスの例です。

fun Intent.populateRequestedPaymentOptions() {
    if (requestPayerName) {
        putExtra("payerName", "John Smith")
    }
    if (requestPayerPhone) {
        putExtra("payerPhone", "4169158200")
    }
    if (requestPayerEmail) {
        putExtra("payerEmail", "john.smith@gmail.com")
    }
    if(requestShipping) {
        val address: Bundle = Bundle()
        address.putString("countryCode", "CA")
        val addressLines: Array<String> =
                arrayOf<String>("111 Richmond st. West")
        address.putStringArray("addressLines", addressLines)
        address.putString("region", "Ontario")
        address.putString("city", "Toronto")
        address.putString("postalCode", "M5H2G4")
        address.putString("recipient", "John Smith")
        address.putString("phone", "4169158200")
        putExtra("shippingAddress", address)
        putExtra("shippingOptionId", "standard")
    }
}

省略可: 動的フローをサポートする

トランザクションの総費用が増加することもあります。たとえば、ユーザーが エクスプレス配送オプションを選択した場合、または利用可能な配送リストが ユーザーが海外配送を選択したときに配送オプションが変わったり、価格が変更されたりします。 あります。ユーザーが選択した配送先住所やオプションをアプリが提供すると、 配送先住所や配送オプションを販売者に通知できる 変更されたお支払い情報がユーザーに表示されます。 含まれます。

AIDL

新しい変更を販売者に通知するには、PaymentDetailsUpdateService を使用します Chrome の AndroidManifest.xml で宣言されているサービス。このサービスを使用するには、2 つの 次のコンテンツを含む AIDL ファイル:

app/src/main/aidl/org/chromium/components/payments/IPaymentDetailsUpdateService

package org.chromium.components.payments;
import android.os.Bundle;

interface IPaymentDetailsUpdateServiceCallback {
    oneway void updateWith(in Bundle updatedPaymentDetails);

    oneway void paymentDetailsNotUpdated();
}

app/src/main/aidl/org/chromium/components/payments/IPaymentDetailsUpdateServiceCallback

package org.chromium.components.payments;
import android.os.Bundle;
import org.chromium.components.payments.IPaymentDetailsUpdateServiceCallback;

interface IPaymentDetailsUpdateService {
    oneway void changePaymentMethod(in Bundle paymentHandlerMethodData,
            IPaymentDetailsUpdateServiceCallback callback);

    oneway void changeShippingOption(in String shippingOptionId,
            IPaymentDetailsUpdateServiceCallback callback);

    oneway void changeShippingAddress(in Bundle shippingAddress,
            IPaymentDetailsUpdateServiceCallback callback);
}

ユーザーが選択したお支払い方法、配送先住所、配送オプションの変更について販売者に通知する

private fun bind() {
    // The action is introduced in Chrome version 92, which supports the service in Chrome
    // and other browsers (e.g., WebLayer).
    val newIntent = Intent("org.chromium.intent.action.UPDATE_PAYMENT_DETAILS")
        .setPackage(callingBrowserPackage)
    if (packageManager.resolveService(newIntent, PackageManager.GET_RESOLVED_FILTER) == null) {
        // Fallback to Chrome-only approach.
        newIntent.setClassName(
            callingBrowserPackage,
            "org.chromium.components.payments.PaymentDetailsUpdateService")
        newIntent.action = IPaymentDetailsUpdateService::class.java.name
    }
    isBound = bindService(newIntent, connection, Context.BIND_AUTO_CREATE)
}

private val connection = object : ServiceConnection {
    override fun onServiceConnected(className: ComponentName, service: IBinder) {
        val service = IPaymentDetailsUpdateService.Stub.asInterface(service)
        try {
            if (isOptionChange) {
                service?.changeShippingOption(selectedOptionId, callback)
            } else (isAddressChange) {
                service?.changeShippingAddress(selectedAddress, callback)
            } else {
                service?.changePaymentMethod(methodData, callback)
            }
        } catch (e: RemoteException) {
            // Handle the remote exception
        }
    }
}

サービスの開始インテントに使用される callingPackageName には、次のいずれかを指定できます。 支払いを開始したブラウザに応じて、 リクエストできます。

Chrome チャンネル パッケージ名
Stable "com.android.chrome"
Beta "com.chrome.beta"
開発 "com.chrome.dev"
Canary "com.chrome.canary"
Chromium "org.chromium.chrome"
Google クイック検索ボックス(WebLayer 埋め込み機能) "com.google.android.googlequicksearchbox"

changePaymentMethod

ユーザーが選択したお支払い方法の変更を販売者に通知します。「 「paymentHandlerMethodData」バンドルには methodName とオプションの details が含まれています 両方を文字列値にすることができます。Chrome は、 空でない methodName を指定し、次のいずれかを含む updatePaymentDetails を送信します。 検証で不合格だった場合、callback.updateWith で次のエラー メッセージが表示されます。

'Method data required.'
'Method name required.'

changeShippingOption

ユーザーが選択した配送方法の変更を販売者に通知します。 shippingOptionId は、販売者が指定したいずれかの ID にする必要があります。 配送方法を設定しますChrome は空でない shippingOptionId を確認して、 次のエラー メッセージを含む updatePaymentDetails 検証が失敗した場合は callback.updateWith

'Shipping option identifier required.'

changeShippingAddress

ユーザーが指定した配送先住所が変更されたことを販売者に通知します。Chrome 有効な countryCode を持つ空でない shippingAddress バンドルがあるかどうかを確認します。 次のエラー メッセージとともに updatePaymentDetails を送信します。 検証が失敗した場合は callback.updateWith

'Payment app returned invalid shipping address in response.'

無効な状態のエラー メッセージ

変更リクエストの受信時に Chrome が無効な状態になった場合 秘匿化された updatePaymentDetailscallback.updateWith を呼び出します。 あります。バンドルには、"Invalid state" が指定された error キーのみが含まれます。 無効な状態の例を次に示します。

  • Chrome が以前の変更に対する販売者の応答を待機している場合 (進行中の変更イベントなど)。
  • 支払いアプリから提供された配送オプションの ID が、 販売者が指定した配送オプション

更新されたお支払い情報を販売者から受け取る

private fun unbind() {
    if (isBound) {
        unbindService(connection)
        isBound = false
    }
}

private val callback: IPaymentDetailsUpdateServiceCallback =
    object : IPaymentDetailsUpdateServiceCallback.Stub() {
        override fun paymentDetailsNotUpdated() {
            // Payment request details have not changed.
            unbind()
        }

        override fun updateWith(updatedPaymentDetails: Bundle) {
            newPaymentDetails = updatedPaymentDetails
            unbind()
        }
    }

updatePaymentDetails は、次と同等のバンドルです。 PaymentRequestDetailsUpdate WebIDL ディクショナリ( modifiers フィールドなど)で定義され、次のオプションのキーが含まれます。

  • total - currency 鍵と value 鍵を含むバンドル。両方の鍵があります。 文字列値
  • shippingOptions - 送料の Parcelable 配列 オプション
  • error - 一般的なエラー メッセージ( changeShippingOption で有効な配送オプション ID が指定されていません)
  • stringifiedPaymentMethodErrors - 検証を表す JSON 文字列 お支払い方法のエラー
  • addressErrors - 送料と同一のオプション キーを含むバンドル address と string 使用できます。各キーは、対応する検証エラーを表す 住所の一部と見なされます。

キーが存在しない場合、その値は変更されていません。