Web Payments API を使用して配送先住所と支払者の連絡先情報を提供するように Android の支払いアプリを更新する方法。
公開日: 2020 年 7 月 17 日、最終更新日: 2025 年 5 月 27 日
ウェブフォームで配送先住所と連絡先情報を入力するのは、お客様にとって手間がかかります。エラーが発生し、コンバージョン率が低下する可能性があります。
そのため、Payment Request API は、配送先住所と連絡先情報をリクエストする機能をサポートしています。これには複数のメリットがあります。
- ユーザーは数回タップするだけで正しい住所を選択できます。
- 住所は常に標準化された形式で返されます。
- 間違った住所を送信する可能性は低くなります。
ブラウザは、支払いアプリへの配送先住所と連絡先情報の収集を延期して、統合された支払いエクスペリエンスを提供できます。この機能は委任と呼ばれます。
可能であれば、Chrome は、お客様の配送先住所と連絡先情報の収集を、呼び出された Android 支払いアプリに委任します。委任により、購入手続き時の手間を軽減できます。
販売者のウェブサイトでは、お客様が選択した配送先住所と配送オプションに応じて、配送オプションと合計金額を動的に更新できます。
既存の Android 支払いアプリに委任のサポートを追加するには、次の手順を実施します。
サポートされている委任を宣言する
ブラウザは、支払いアプリが提供できる追加情報のリストを把握して、その情報の収集をアプリに委任する必要があります。サポートされている委任を、アプリの AndroidManifest.xml で <meta-data>
として宣言します。
<activity
android:name=".PaymentActivity"
…
<meta-data
android:name="org.chromium.payment_supported_delegations"
android:resource="@array/chromium_payment_supported_delegations" />
</activity>
android:resource
は、次の値のすべてまたは一部を含む <string-array>
を参照する必要があります。
payerName
payerEmail
payerPhone
shippingAddress
次の例では、配送先住所と支払者のメールアドレスのみを指定できます。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="chromium_payment_supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
必要なお支払い方法の PAY
インテント エクストラを解析する
販売者は、paymentOptions
ディクショナリを使用して、必要な追加情報を指定できます。Chrome は、paymentOptions
インテントの追加情報を PAY
アクティビティに渡すことで、アプリが提供できる必須オプションのリストを取得します。
paymentOptions
paymentOptions
は、アプリが委任サポートを宣言している販売者指定の支払いオプションのサブセットです。
Kotlin
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")
Java
Bundle paymentOptions = extras.getBundle("paymentOptions");
if (paymentOptions != null) {
Boolean requestPayerName = paymentOptions.getBoolean("requestPayerName");
Boolean requestPayerPhone = paymentOptions.getBoolean("requestPayerPhone");
Boolean requestPayerEmail = paymentOptions.getBoolean("requestPayerEmail");
Boolean requestShipping = paymentOptions.getBoolean("requestShipping");
String shippingType = paymentOptions.getString("shippingType");
}
次のパラメータを含めることができます。
requestPayerName
- 支払人の氏名が必須かどうかを示すブール値。requestPayerPhone
- 支払者のスマートフォンが必要かどうかを示すブール値。requestPayerEmail
- 支払者のメールアドレスが必須かどうかを示すブール値。requestShipping
- 配送情報が必要かどうかを示すブール値。shippingType
- 配送の種類を示す文字列。配送のタイプは、"shipping"
、"delivery"
、"pickup"
のいずれかです。アプリは、ユーザーの住所や配送オプションの選択を求める際に、UI でこのヒントを使用できます。
shippingOptions
shippingOptions
は、販売者が指定した配送オプションの Parcelable 配列です。このパラメータは、paymentOptions.requestShipping ==
true
の場合にのみ存在します。
Kotlin
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
Java
Parcelable[] shippingOptions = extras.getParcelableArray("shippingOptions");
for (Parcelable it : shippingOptions) {
if (it != null && it instanceof Bundle) {
Bundle shippingOption = (Bundle) it;
}
}
各配送オプションは、次のキーを持つ Bundle
です。
id
- 配送オプションの識別子。label
- ユーザーに表示される配送オプションのラベル。amount
- 文字列値のcurrency
キーとvalue
キーを含む送料バンドル。selected
- 支払いアプリに配送オプションが表示されたときに、配送オプションを選択するかどうか。
selected
以外のすべてのキーには文字列値があります。selected
にはブール値があります。
Kotlin
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)
Java
String id = bundle.getString("id");
String label = bundle.getString("label");
Bundle amount = bundle.getBundle("amount");
Boolean selected = bundle.getBoolean("selected", false);
支払いレスポンスで必要な情報を提供する
アプリは、PAY
アクティビティへのレスポンスに必要な追加情報を含める必要があります。
そのためには、次のパラメータをインテントの追加情報として指定する必要があります。
payerName
- 支払人の氏名。paymentOptions.requestPayerName
が true の場合、空でない文字列にする必要があります。payerPhone
- 支払者の電話番号。paymentOptions.requestPayerPhone
が true の場合、空でない文字列にする必要があります。payerEmail
- 支払者のメールアドレス。paymentOptions.requestPayerEmail
が true の場合、空でない文字列にする必要があります。shippingAddress
- ユーザーが指定した配送先住所。paymentOptions.requestShipping
が true の場合、これは空ではないバンドルである必要があります。バンドルには、物理アドレスのさまざまな部分を表す次のキーが必要です。countryCode
postalCode
sortingCode
region
city
dependentLocality
addressLine
organization
recipient
phone
addressLine
以外のすべてのキーには文字列値があります。addressLine
は文字列の配列です。
shippingOptionId
- ユーザーが選択した配送オプションの識別子。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".'
次のコードサンプルは、有効なレスポンスの例です。
Kotlin
fun Intent.populateRequestedPaymentOptions() {
if (requestPayerName) {
putExtra("payerName", "John Smith")
}
if (requestPayerPhone) {
putExtra("payerPhone", "5555555555")
}
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", "5555555555")
putExtra("shippingAddress", address)
putExtra("shippingOptionId", "standard")
}
}
Java
private Intent populateRequestedPaymentOptions() {
Intent result = new Intent();
if (requestPayerName) {
result.putExtra("payerName", "John Smith");
}
if (requestPayerPhone) {
presult.utExtra("payerPhone", "5555555555");
}
if (requestPayerEmail) {
result.putExtra("payerEmail", "john.smith@gmail.com");
}
if (requestShipping) {
Bundle address = new Bundle();
address.putExtra("countryCode", "CA");
address.putExtra("postalCode", "M5H2G4");
address.putExtra("region", "Ontario");
address.putExtra("city", "Toronto");
String[] addressLines = new String[] {"111 Richmond st. West"};
address.putExtra("addressLines", addressLines);
address.putExtra("recipient", "John Smith");
address.putExtra("phone", "5555555555");
result.putExtra("shippingAddress", address);
result.putExtra("shippingOptionId", "standard");
}
return result;
}
省略可: 動的フローをサポートする
ユーザーがエクスプレス配送オプションを選択した場合や、ユーザーが国際配送先住所を選択した際に利用可能な配送オプションのリストやその料金が変更された場合など、取引の合計費用が増加することがあります。アプリでユーザーが選択した配送先住所またはオプションを提供する場合、配送先住所またはオプションの変更を販売者に通知し、更新されたお支払い情報(販売者から提供)をユーザーに表示できる必要があります。
新しい変更を販売者に通知するには、IPaymentDetailsUpdateServiceCallback
インターフェースを実装し、UPDATE_PAYMENT_DETAILS
インテント フィルタを使用して AndroidManifest.xml
で宣言します。
PAY
インテントを呼び出した直後、Chrome は PAY
インテントと同じパッケージ内の UPDATE_PAYMENT_DETAILS
サービス(存在する場合)に接続し、setPaymentDetailsUpdateService(service)
を呼び出して支払いアプリに IPaymentDetailsUpdateService
エンドポイントを提供します。これにより、ユーザーのお支払い方法、配送オプション、配送先住所の変更を通知できます。
プロセス間通信(IPC)を受信するときに packageManager.getPackagesForUid(Binder.getCallingUid())
を使用して、PAY
インテントを呼び出したアプリが IPaymentDetailsUpdateServiceCallback
メソッドを呼び出したアプリと同じパッケージ名を持つことを検証します。
AIDL
次の内容の 2 つの AIDL ファイルを作成します。
org/chromium/components/payments/IPaymentDetailsUpdateServiceCallback.aidl
package org.chromium.components.payments;
import android.os.Bundle;
import org.chromium.components.payments.IPaymentDetailsUpdateService;
interface IPaymentDetailsUpdateServiceCallback {
oneway void updateWith(in Bundle updatedPaymentDetails);
oneway void paymentDetailsNotUpdated();
oneway void setPaymentDetailsUpdateService(IPaymentDetailsUpdateService service);
}
org/chromium/components/payments/IPaymentDetailsUpdateService.aidl
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);
}
サービス
IPaymentDetailsUpdateServiceCallback
サービスを実装します。
Kotlin
class SampleUpdatePaymentDetailsCallbackService : Service() {
private val binder = object : IPaymentDetailsUpdateServiceCallback.Stub() {
override fun updateWith(updatedPaymentDetails: Bundle) {}
override fun paymentDetailsNotUpdated() {}
override fun setPaymentDetailsUpdateService(service: IPaymentDetailsUpdateService) {}
}
override fun onBind(intent: Intent?): IBinder? {
return binder
}
}
Java
import org.chromium.components.paymsnts.IPaymentDetailsUpdateServiceCallback;
public class SampleUpdatePaymentDetailsCallbackService extends Service {
private final IPaymentDetailsUpdateServiceCallback.Stub mBinder =
new IPaymentDetailsUpdateServiceCallback.Stub() {
@Override
public void updateWith(Bundle updatedPaymentDetails) {}
@Override
public void paymentDetailsNotUpdated() {}
@Override
public void setPaymentDetailsUpdateService(IPaymentDetailsUpdateService service) {}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
AndroidManifest.xml
AndroidManifest.xml
で IPaymentDetailsUpdateServiceCallback
のサービスを公開します。
<service
android:name=".SampleUpdatePaymentDetailsCallbackService"
android:exported="true">
<intent-filter>
<action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
</intent-filter>
</service>
お客様が選択したお支払い方法、配送先住所、配送オプションの変更について販売者に通知する
Kotlin
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
}
Java
if (service == null) {
return;
}
try {
if (isOptionChange) {
service.changeShippingOption(selectedOptionId, callback);
} else (isAddressChange) {
service.changeShippingAddress(selectedAddress, callback);
} else {
service.changePaymentMethod(methodData, callback);
}
} catch (RemoteException e) {
// Handle the remote exception
}
changePaymentMethod
ユーザーが選択した支払い方法の変更について販売者に通知します。paymentHandlerMethodData
バンドルには、methodName
キーと省略可能な details
キーが含まれます。どちらも文字列値です。Chrome は、空でない methodName
を含む空でないバンドルをチェックし、検証に失敗した場合は、callback.updateWith
を介して次のいずれかのエラー メッセージを含む updatePaymentDetails
を送信します。
'Method data required.'
'Method name required.'
changeShippingOption
ユーザーが選択した配送オプションの変更について販売者に通知します。shippingOptionId
は、販売者が指定した配送オプションのいずれかの識別子にする必要があります。Chrome は空でない shippingOptionId
をチェックし、検証に失敗した場合は、callback.updateWith
を介して次のエラー メッセージを含む updatePaymentDetails
を送信します。
'Shipping option identifier required.'
changeShippingAddress
ユーザーが指定した配送先住所の変更について販売者に通知します。Chrome は、有効な countryCode
を含む空でない shippingAddress
バンドルをチェックし、検証に失敗した場合は、callback.updateWith
を介して次のエラー メッセージを含む updatePaymentDetails
を送信します。
'Payment app returned invalid shipping address in response.'
無効な状態に関するエラー メッセージ
Chrome が変更リクエストを受信したときに無効な状態に遭遇した場合は、削除された updatePaymentDetails
バンドルを渡して callback.updateWith
を呼び出します。バンドルには、"Invalid state"
を含む error
キーのみが含まれます。無効な状態の例を次に示します。
- Chrome が、以前の変更(進行中の変更イベントなど)に対する販売者の対応をまだ待機している場合。
- 支払いアプリから提供された配送オプションの識別子が、販売者が指定した配送オプションのいずれにも属していない。
販売者から更新されたお支払い情報を受け取る
Kotlin
override fun updateWith(updatedPaymentDetails: Bundle) {}
override fun paymentDetailsNotUpdated() {}
Java
@Override
public void updateWith(Bundle updatedPaymentDetails) {}
@Override
public void paymentDetailsNotUpdated() {}
updatedPaymentDetails
は、PaymentRequestDetailsUpdate
WebIDL 辞書と同等のバンドルで、次のオプション キーが含まれています。
total
-currency
キーとvalue
キーを含むバンドル。両方のキーに文字列値が設定されています。shippingOptions
- 配送オプションの Parcelable 配列error
- 一般的なエラー メッセージを含む文字列(changeShippingOption
が有効な配送オプション ID を提供しない場合など)stringifiedPaymentMethodErrors
- お支払い方法の検証エラーを表す JSON 文字列addressErrors
- 配送先住所と文字列値と同じオプションのキーを含むバンドル。各キーは、配送先住所の対応する部分に関連する検証エラーを表します。modifiers
- バンドルの Parcelable 配列。それぞれにtotal
フィールドとmethodData
フィールド(どちらもバンドル)があります。
キーが存在しない場合は、値が変更されていないことを意味します。