Cara memperbarui aplikasi pembayaran Android Anda untuk memberikan alamat pengiriman dan informasi kontak pembayar dengan Web Payments API.
Dipublikasikan: 17 Juli 2020, Terakhir diperbarui: 27 Mei 2025
Memasukkan alamat pengiriman dan informasi kontak melalui formulir web dapat menjadi pengalaman yang merepotkan bagi pelanggan. Hal ini dapat menyebabkan error dan menurunkan rasio konversi.
Itulah sebabnya Payment Request API mendukung fitur untuk meminta alamat pengiriman dan informasi kontak. Hal ini memberikan beberapa manfaat:
- Pengguna dapat memilih alamat yang tepat hanya dengan beberapa ketukan.
- Alamat selalu ditampilkan dalam format standar.
- Alamat yang salah lebih jarang dikirimkan.
Browser dapat menunda pengumpulan alamat pengiriman dan informasi kontak ke aplikasi pembayaran untuk memberikan pengalaman pembayaran yang terpadu. Fungsi ini disebut delegasi.
Jika memungkinkan, Chrome mendelegasikan pengumpulan alamat pengiriman dan informasi kontak pelanggan ke aplikasi pembayaran Android yang dipanggil. Delegasi ini mengurangi hambatan selama checkout.
Situs penjual dapat memperbarui opsi pengiriman dan total harga secara dinamis, bergantung pada pilihan alamat pengiriman dan opsi pengiriman pelanggan.
Untuk menambahkan dukungan delegasi ke aplikasi pembayaran Android yang sudah ada, terapkan langkah-langkah berikut:
- Mendeklarasikan delegasi yang didukung.
- Mengurai ekstra intent
PAY
untuk opsi pembayaran yang diperlukan. - Memberikan informasi yang diperlukan dalam respons pembayaran.
- Opsional: Mendukung alur dinamis:
Mendeklarasikan delegasi yang didukung
Browser perlu mengetahui daftar informasi tambahan yang dapat diberikan oleh aplikasi pembayaran Anda sehingga browser dapat mendelegasikan pengumpulan informasi tersebut ke aplikasi Anda. Nyatakan delegasi yang didukung sebagai <meta-data>
di
AndroidManifest.xml aplikasi Anda.
<activity
android:name=".PaymentActivity"
…
<meta-data
android:name="org.chromium.payment_supported_delegations"
android:resource="@array/chromium_payment_supported_delegations" />
</activity>
android:resource
harus mengarah ke <string-array>
yang berisi semua atau sebagian nilai berikut:
payerName
payerEmail
payerPhone
shippingAddress
Contoh berikut hanya dapat memberikan alamat pengiriman dan alamat email pembayar.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="chromium_payment_supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
Mengurai ekstra intent PAY
untuk opsi pembayaran yang diperlukan
Penjual dapat menentukan informasi tambahan yang diperlukan menggunakan
kamus paymentOptions
. Chrome akan memberikan daftar opsi yang diperlukan yang dapat disediakan aplikasi Anda dengan meneruskan paymentOptions
Intent ekstra
ke aktivitas PAY
.
paymentOptions
paymentOptions
adalah subset opsi pembayaran yang ditentukan penjual yang
dukungan delegasinya telah dideklarasikan oleh aplikasi Anda.
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");
}
Parameter ini dapat mencakup parameter berikut:
requestPayerName
- Boolean yang menunjukkan apakah nama pembayar diperlukan atau tidak.requestPayerPhone
- Boolean yang menunjukkan apakah ponsel pembayar diperlukan atau tidak.requestPayerEmail
- Boolean yang menunjukkan apakah email pembayar diperlukan atau tidak.requestShipping
- Boolean yang menunjukkan apakah informasi pengiriman diperlukan atau tidak.shippingType
- String yang menunjukkan jenis pengiriman. Jenis pengiriman dapat berupa"shipping"
,"delivery"
, atau"pickup"
. Aplikasi Anda dapat menggunakan petunjuk ini di UI-nya saat meminta alamat pengguna atau pilihan opsi pengiriman.
shippingOptions
shippingOptions
adalah array pengiriman yang ditentukan penjual yang dapat di-parcel. Parameter ini hanya akan ada jika 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;
}
}
Setiap opsi pengiriman adalah Bundle
dengan kunci berikut.
id
- ID opsi pengiriman.label
- Label opsi pengiriman yang ditampilkan kepada pengguna.amount
- Paket biaya pengiriman yang berisi kuncicurrency
danvalue
dengan nilai string.currency
menunjukkan mata uang biaya pengiriman, sebagai kode alfabet 3 huruf yang disusun dengan baik ISO4217value
menunjukkan nilai biaya pengiriman, sebagai nilai uang desimal yang valid
selected
- Apakah opsi pengiriman harus dipilih atau tidak saat aplikasi pembayaran menampilkan opsi pengiriman.
Semua kunci selain selected
memiliki nilai string. selected
memiliki nilai
boolean.
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);
Memberikan informasi yang diperlukan dalam respons pembayaran
Aplikasi Anda harus menyertakan informasi tambahan yang diperlukan dalam responsnya terhadap
aktivitas PAY
.
Untuk melakukannya, parameter berikut harus ditentukan sebagai ekstra Intent:
payerName
- Nama lengkap pembayar. Kolom ini harus berupa string tidak kosong jikapaymentOptions.requestPayerName
benar.payerPhone
- Nomor telepon pembayar. Kolom ini harus berupa string tidak kosong jikapaymentOptions.requestPayerPhone
benar.payerEmail
- Alamat email pembayar. Ini harus berupa string tidak kosong jikapaymentOptions.requestPayerEmail
bernilai benar (true).shippingAddress
- Alamat pengiriman yang diberikan pengguna. Ini harus berupa paket tidak kosong jikapaymentOptions.requestShipping
benar. Paket harus memiliki kunci berikut yang merepresentasikan berbagai bagian dalam alamat fisik.countryCode
postalCode
sortingCode
region
city
dependentLocality
addressLine
organization
recipient
phone
Semua kunci selainaddressLine
memiliki nilai string.addressLine
adalah array string.
shippingOptionId
- ID opsi pengiriman yang dipilih pengguna. Kolom ini harus berupa string tidak kosong jikapaymentOptions.requestShipping
benar.
Memvalidasi respons pembayaran
Jika hasil aktivitas respons pembayaran yang diterima dari aplikasi pembayaran yang dipanggil ditetapkan ke RESULT_OK
, Chrome akan memeriksa informasi tambahan yang diperlukan di bagian tambahan. Jika validasi gagal, Chrome akan menampilkan promise yang ditolak
dari request.show()
dengan salah satu pesan error yang ditujukan untuk developer
berikut:
'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".'
Contoh kode berikut adalah contoh respons yang valid:
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;
}
Opsional: Mendukung alur dinamis
Terkadang total biaya transaksi meningkat, seperti saat pengguna memilih opsi pengiriman ekspres, atau saat daftar opsi pengiriman yang tersedia atau harganya berubah saat pengguna memilih alamat pengiriman internasional. Saat aplikasi Anda menyediakan alamat atau opsi pengiriman yang dipilih pengguna, aplikasi tersebut harus dapat memberi tahu penjual tentang perubahan alamat atau opsi pengiriman dan menampilkan detail pembayaran yang diperbarui kepada pengguna (disediakan oleh penjual).
Untuk memberi tahu penjual tentang perubahan baru, terapkan antarmuka
IPaymentDetailsUpdateServiceCallback
dan deklarasikan di
AndroidManifest.xml
dengan filter intent UPDATE_PAYMENT_DETAILS
.
Segera setelah memanggil intent PAY
, Chrome akan terhubung ke layanan UPDATE_PAYMENT_DETAILS
(jika ada) dalam paket yang sama dengan intent PAY
dan akan memanggil setPaymentDetailsUpdateService(service)
untuk memberikan endpoint IPaymentDetailsUpdateService
ke aplikasi pembayaran Anda untuk memberi tahu tentang perubahan metode pembayaran, opsi pengiriman, atau alamat pengiriman pengguna.
Gunakan packageManager.getPackagesForUid(Binder.getCallingUid())
saat menerima
Komunikasi Antar-Proses (IPC) untuk memvalidasi bahwa aplikasi yang memanggil intent
PAY
memiliki nama paket yang sama dengan aplikasi yang memanggil metode
IPaymentDetailsUpdateServiceCallback
.
AIDL
Buat dua file AIDL dengan konten berikut:
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);
}
Layanan
Implementasikan layanan 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
Ekspos layanan untuk IPaymentDetailsUpdateServiceCallback
di
AndroidManifest.xml
Anda.
<service
android:name=".SampleUpdatePaymentDetailsCallbackService"
android:exported="true">
<intent-filter>
<action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
</intent-filter>
</service>
Memberi tahu penjual tentang perubahan pada metode pembayaran, alamat pengiriman, atau opsi pengiriman yang dipilih pengguna
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
Memberi tahu penjual tentang perubahan pada metode pembayaran yang dipilih pengguna. Paket
paymentHandlerMethodData
berisi kunci methodName
dan details
opsional, keduanya dengan nilai string. Chrome akan memeriksa apakah ada paket yang tidak kosong dengan
methodName
yang tidak kosong dan mengirim updatePaymentDetails
dengan salah satu
pesan error berikut menggunakan callback.updateWith
jika validasi gagal.
'Method data required.'
'Method name required.'
changeShippingOption
Memberi tahu penjual tentang perubahan pada opsi pengiriman yang dipilih pengguna.
shippingOptionId
harus berupa ID salah satu opsi pengiriman yang ditentukan penjual. Chrome akan memeriksa shippingOptionId
yang tidak kosong dan mengirim
updatePaymentDetails
dengan pesan error berikut menggunakan
callback.updateWith
jika validasi gagal.
'Shipping option identifier required.'
changeShippingAddress
Memberi tahu penjual tentang perubahan alamat pengiriman yang diberikan pengguna. Chrome akan memeriksa paket shippingAddress
yang tidak kosong dengan countryCode
yang valid dan mengirim updatePaymentDetails
dengan pesan error berikut menggunakan callback.updateWith
jika validasi gagal.
'Payment app returned invalid shipping address in response.'
Pesan error status tidak valid
Jika Chrome mengalami status tidak valid saat menerima permintaan perubahan apa pun, Chrome akan memanggil callback.updateWith
dengan paket updatePaymentDetails
yang disamarkan. Paket hanya akan berisi kunci error
dengan "Invalid state"
.
Contoh status tidak valid adalah:
- Saat Chrome masih menunggu respons penjual terhadap perubahan sebelumnya (seperti peristiwa perubahan yang sedang berlangsung).
- ID opsi pengiriman yang disediakan aplikasi pembayaran tidak termasuk dalam opsi pengiriman yang ditentukan penjual.
Menerima detail pembayaran yang diperbarui dari penjual
Kotlin
override fun updateWith(updatedPaymentDetails: Bundle) {}
override fun paymentDetailsNotUpdated() {}
Java
@Override
public void updateWith(Bundle updatedPaymentDetails) {}
@Override
public void paymentDetailsNotUpdated() {}
updatedPaymentDetails
adalah paket yang setara dengan
kamus PaymentRequestDetailsUpdate
WebIDL dan berisi kunci opsional berikut:
total
- Bundle yang berisi kuncicurrency
danvalue
, kedua kunci memiliki nilai stringshippingOptions
- Array objek yang dapat di-parcel dari shipping optionserror
- String yang berisi pesan error umum (misalnya, saatchangeShippingOption
tidak memberikan ID opsi pengiriman yang valid)stringifiedPaymentMethodErrors
- String JSON yang merepresentasikan error validasi untuk metode pembayaranaddressErrors
- Paket dengan kunci opsional yang identik dengan shipping address dan nilai string. Setiap kunci mewakili error validasi yang terkait dengan bagian alamat pengiriman yang sesuai.modifiers
- Array Bundel yang dapat di-parcel, masing-masing dengan kolomtotal
danmethodData
, yang juga merupakan Bundel.
Kunci yang tidak ada berarti nilainya tidak berubah.