透過 Android 付款應用程式提供運送和聯絡資訊

如何更新 Android 付款應用程式,以便使用 Web Payments API 提供運送地址和付款人聯絡資訊。

Sahel Sharify
Sahel Sharify

透過網路表單輸入運送地址和聯絡資訊可以是 帶給客戶麻煩這可能會造成錯誤並降低轉換 頻率。

因此,Payment Request API 支援要求運送服務的功能 地址和聯絡資訊這麼做有許多好處:

  • 使用者只要輕觸幾下,就能選擇正確的地址。
  • 系統一律會以標準化形式傳回地址 格式。
  • 提交錯誤的地址較不容易。

瀏覽器可以將運送地址和聯絡資訊延遲收集, 付款應用程式,提供整合式付款體驗。這項功能 稱為「委派」

Chrome 在可能的情況下,會委派消費者的運送作業 傳送地址和聯絡資訊給叫用的 Android 付款應用程式。 委派功能可減少結帳程序。

商家網站可以動態更新運送選項和總價 視消費者選擇的運送地址和運送包裹而定 如果有需要 SQL 指令的分析工作負載 則 BigQuery 可能是最佳選擇

運送選項和運送地址變更正在運作。瞭解這項異動對運送選項和總價有何影響。
,瞭解如何調查及移除這項存取權。

如要為既有的 Android 付款應用程式新增委派支援,請按照下列步驟操作: 實作下列步驟:

  1. 宣告支援的委派
  2. 剖析所需付款的 PAY 意圖額外項目
  3. 在付款中提供必要資訊 回應
  4. [選用] 支援動態流程
    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" ]

以下範例只能提供運送地址和付款人的電子郵件地址 讓我們看看 DNS 解析 進一步探索內部和外部位址

<?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 當做 IntentPAY 額外項目

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"。您的應用程式可以在 要求使用者地址或選擇運送選項時的使用者介面。

shippingOptions

shippingOptions 是商家指定運費的可包裝陣列 只要設定成「自動重新啟動」 和「在主機維護期間」選項即可這個參數只會在 paymentOptions.requestShipping == true 時存在。

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

每個運送選項都是含有下列索引鍵的 Bundle

  • id:運送選項 ID。
  • label:向使用者顯示的運送選項標籤。
  • amount - 運費組合包含 currencyvalue 組以及 字串值。
  • 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套裝組合 應具備下列代表實體物件中不同部分的鍵 電子郵件地址
    • city
    • countryCode
    • dependentLocality
    • organization
    • phone
    • postalCode
    • recipient
    • region
    • sortingCode
    • addressLine addressLine 以外的所有索引鍵都有字串值。addressLine 是字串陣列。
  • shippingOptionId:使用者所選運送選項的 ID。這個 當 paymentOptions.requestShipping 為 true 時,應該是非空白字串。

驗證付款回應

如果所叫用付款收到的付款回應活動結果 應用程式已設為「RESULT_OK」,Chrome 就會檢查是否有必要額外設定 資訊如果驗證失敗,Chrome 會傳回遭拒 request.show() 的承諾,但發生下列其中一項錯誤 訊息:

'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")
    }
}

選用:支援動態流程

有時交易的總費用會增加,例如使用者 選擇快速出貨選項,或選擇運送清單時 選項或其價格會在使用者選擇國際運送時變更 讓我們看看 DNS 解析 進一步探索內部和外部位址應用程式向使用者提供的運送地址或選項時, 應該要能通知商家任何運送地址或選項 並向使用者顯示更新後的付款資料 ( 商家)。

AIDL

如要通知商家有新的變更,請使用 PaymentDetailsUpdateService 服務。如要使用這項服務,請建立兩個 含有以下內容的 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 版本 套件名稱
穩定 "com.android.chrome"
Beta 版 "com.chrome.beta"
開發 "com.chrome.dev"
Canary 版 "com.chrome.canary"
"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 組合 然後透過以下方式傳送含有以下錯誤訊息的 updatePaymentDetailscallback.updateWith 表示驗證失敗。

'Payment app returned invalid shipping address in response.'

無效的狀態錯誤訊息

如果 Chrome 在收到任何變更請求時進入無效狀態 系統會呼叫 callback.updateWith 並顯示遮蓋的 updatePaymentDetails 軟體包。組合只會包含有 "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()
        }
    }

updatePaymentDetailsPaymentRequestDetailsUpdate WebIDL 字典 (在遮蓋 modifiers 欄位),並包含下列選用鍵:

  • total - 包含 currencyvalue 鍵的組合,兩個鍵都有 字串值
  • shippingOptions - shipping 的可包裝陣列 選項
  • error:包含一般錯誤訊息的字串 (例如 changeShippingOption 未提供有效的運送選項 ID)
  • stringifiedPaymentMethodErrors - 代表驗證的 JSON 字串 付款方式錯誤
  • addressErrors - 包含選用金鑰與運送相同 address 和字串 輕鬆分配獎金每個金鑰都代表一個與其相對應的驗證錯誤相關的驗證錯誤 。

如果缺少索引鍵,則代表該值未變更。