Cara mengupdate aplikasi pembayaran Android agar memberikan alamat pengiriman dan informasi kontak pembayar dengan Web Payments API.
Memasukkan alamat pengiriman dan informasi kontak melalui formulir web dapat menjadi dan pengalaman yang rumit bagi pelanggan. Dapat menyebabkan error dan menurunkan konversi besar.
Itulah mengapa Payment Request API mendukung fitur untuk meminta pengiriman alamat dan informasi kontak Anda. Hal ini memberikan beberapa manfaat:
- Pengguna dapat memilih alamat yang tepat hanya dengan beberapa ketukan.
- Alamat akan selalu ditampilkan dalam nilai format.
- Sebaiknya Anda mengirimkan alamat yang salah.
Browser dapat menunda pengumpulan alamat pengiriman dan informasi kontak ke aplikasi pembayaran untuk memberikan pengalaman pembayaran terpadu. Fungsi ini adalah yang disebut delegasi.
Jika memungkinkan, Chrome akan mendelegasikan pengumpulan data pengiriman pelanggan dan informasi kontak ke aplikasi pembayaran Android yang dipanggil. Tujuan delegasi mengurangi friksi selama {i>checkout<i}.
Situs penjual dapat memperbarui opsi pengiriman dan harga total secara dinamis bergantung pada pilihan pelanggan untuk alamat pengiriman dan metode pengiriman sebelumnya.
Untuk menambahkan dukungan delegasi ke aplikasi pembayaran Android yang sudah ada, terapkan langkah-langkah berikut:
- Deklarasikan delegasi yang didukung.
- Mengurai tambahan intent
PAY
untuk pembayaran yang diperlukan opsi. - Berikan informasi yang diperlukan terkait pembayaran respons.
- [Opsional] Mendukung alur dinamis:
Mendeklarasikan delegasi yang didukung
Browser perlu mengetahui daftar informasi tambahan yang digunakan
yang disediakan oleh aplikasi Anda sehingga dapat mendelegasikan pengumpulan informasi tersebut kepada
. Deklarasikan delegasi yang didukung sebagai <meta-data>
di metode
AndroidManifest.xml aplikasi Anda.
<activity
android:name=".PaymentActivity"
…
<meta-data
android:name="org.chromium.payment_supported_delegations"
android:resource="@array/supported_delegations" />
</activity>
<resource>
harus berupa daftar string yang dipilih dari nilai valid berikut:
[ "payerName", "payerEmail", "payerPhone", "shippingAddress" ]
Contoh berikut hanya dapat mencantumkan alamat pengiriman dan email pembayar alamat IPv6
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
Mengurai tambahan intent PAY
untuk opsi pembayaran yang diperlukan
Penjual dapat menentukan informasi tambahan yang diperlukan menggunakan
paymentOptions
kata kunci. Chrome akan memberikan daftar opsi yang diperlukan yang dapat digunakan aplikasi Anda
sediakan dengan meneruskan parameter berikut ke aktivitas PAY
sebagai Intent
tambahan.
paymentOptions
paymentOptions
adalah subkumpulan opsi pembayaran yang ditentukan penjual yang
aplikasi Anda telah mendeklarasikan dukungan delegasi.
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")
Hal ini dapat mencakup parameter berikut:
requestPayerName
- Boolean yang menunjukkan apakah nama pembayar atau bukan tidak diperlukan.requestPayerPhone
- Boolean yang menunjukkan apakah ponsel pembayar atau tidak tidak diperlukan.requestPayerEmail
- Boolean yang menunjukkan apakah email pembayar atau tidak tidak diperlukan.requestShipping
- Boolean yang menunjukkan apakah informasi pengiriman atau tidak tidak diperlukan.shippingType
- String yang menunjukkan jenis pengiriman. Jenis pengiriman dapat berupa"shipping"
,"delivery"
, atau"pickup"
. Aplikasi Anda dapat menggunakan petunjuk ini di UI saat meminta alamat pengguna atau pilihan opsi pengiriman.
shippingOptions
shippingOptions
adalah array yang dapat dibagi-bagi dari pengiriman yang ditentukan penjual
lainnya. Parameter ini hanya akan ada saat paymentOptions.requestShipping ==
true
.
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
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-nilai {i>string<i}.currency
menunjukkan mata uang biaya pengiriman, sebagai ISO4217 tersusun dengan baik Kode alfabet 3 hurufvalue
menampilkan nilai biaya pengiriman, dalam bentuk uang desimal yang valid nilai
selected
- Apakah opsi pengiriman harus dipilih atau tidak saat aplikasi pembayaran akan menampilkan opsi pengiriman.
Semua kunci selain selected
memiliki nilai string. selected
memiliki boolean
dengan sejumlah nilai.
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)
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 ditetapkan sebagai tambahan Intent:
payerName
- Nama lengkap pembayar. Seharusnya string ini tidak kosong saatpaymentOptions.requestPayerName
benar.payerPhone
- Nomor telepon pembayar. Seharusnya string ini tidak kosong saatpaymentOptions.requestPayerPhone
benar.payerEmail
- Alamat email pembayar. Kolom ini harus berupa string yang tidak kosong jikapaymentOptions.requestPayerEmail
benar.shippingAddress
- Alamat pengiriman yang diberikan pengguna. Ini harus berupa paket yang tidak kosong jikapaymentOptions.requestShipping
benar. Paket harus memiliki kunci berikut yang mewakili bagian berbeda dalam data alamat email.city
countryCode
dependentLocality
organization
phone
postalCode
recipient
region
sortingCode
addressLine
Semua kunci selainaddressLine
memiliki nilai string.addressLine
adalah array string.
shippingOptionId
- ID opsi pengiriman yang dipilih pengguna. Ini harus berupa string yang tidak kosong jikapaymentOptions.requestShipping
benar.
Memvalidasi respons pembayaran
Jika hasil aktivitas dari respons pembayaran diterima dari pembayaran yang dipanggil
aplikasi disetel ke RESULT_OK
, lalu Chrome akan memeriksa
informasi dalam bagian tambahannya. Jika validasi gagal, Chrome akan menampilkan penolakan
promise dari request.show()
dengan salah satu error yang dihadapi developer berikut
pesan:
'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:
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")
}
}
Opsional: Mendukung alur dinamis
Terkadang total biaya transaksi meningkat, seperti ketika pengguna memilih opsi pengiriman ekspres, atau jika daftar pengiriman yang tersedia opsi pengiriman atau harganya berubah jika pengguna memilih pengiriman internasional alamat IPv6 Jika aplikasi Anda memberikan alamat atau opsi pengiriman yang dipilih pengguna, aplikasi harus dapat memberi tahu penjual tentang alamat atau opsi pengiriman apa pun perubahan, dan menunjukkan kepada pengguna detail pembayaran yang diperbarui (disediakan oleh penjual).
AIDL
Untuk memberi tahu penjual tentang perubahan baru, gunakan PaymentDetailsUpdateService
yang dideklarasikan di AndroidManifest.xml di Chrome. Untuk menggunakan layanan ini, buat dua
File AIDL dengan konten berikut:
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);
}
Beri tahu penjual tentang perubahan pada metode pembayaran, alamat pengiriman, atau opsi pengiriman yang dipilih pengguna
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
yang digunakan untuk intent awal layanan dapat memiliki salah satu
nilai berikut, bergantung pada browser yang telah melakukan pembayaran
permintaan.
Saluran Chrome | Nama Paket |
---|---|
Stabil |
"com.android.chrome"
|
Beta |
"com.chrome.beta"
|
Pengembang |
"com.chrome.dev"
|
Canary |
"com.chrome.canary"
|
Kromium |
"org.chromium.chrome"
|
Kotak Penelusuran Cepat Google (penyemat Lapisan Web) |
"com.google.android.googlequicksearchbox"
|
changePaymentMethod
Memberi tahu penjual tentang perubahan pada metode pembayaran yang dipilih pengguna. Tujuan
Paket paymentHandlerMethodData
berisi methodName
dan details
opsional
kunci dengan nilai string. Chrome akan memeriksa paket yang tidak kosong dengan
methodName
yang tidak kosong dan mengirim updatePaymentDetails
dengan salah satu
pesan error berikut melalui 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 dari yang ditentukan penjual
opsi pengiriman. Chrome akan memeriksa shippingOptionId
yang tidak kosong dan mengirim
updatePaymentDetails
dengan pesan error berikut melalui
callback.updateWith
jika validasi gagal.
'Shipping option identifier required.'
changeShippingAddress
Memberi tahu penjual tentang perubahan alamat pengiriman yang diberikan pengguna. Krom
akan memeriksa paket shippingAddress
yang tidak kosong dengan countryCode
yang valid
dan kirim updatePaymentDetails
dengan pesan error berikut melalui
callback.updateWith
jika validasi gagal.
'Payment app returned invalid shipping address in response.'
Pesan error status tidak valid
Jika Chrome mendapatkan status yang tidak valid setelah menerima salah satu permintaan perubahan
fungsi ini akan memanggil callback.updateWith
dengan updatePaymentDetails
yang disamarkan
paket. Paket hanya akan berisi kunci error
dengan "Invalid state"
.
Contoh status yang 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 bukan milik siapa pun opsi pengiriman yang ditentukan penjual.
Menerima detail pembayaran terbaru dari penjual
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
setara dengan paket
PaymentRequestDetailsUpdate
Kamus WebIDL (setelah menyamarkan
modifiers
) dan berisi kunci opsional berikut:
total
- Paket yang berisi kuncicurrency
danvalue
, kedua kunci memiliki nilai stringshippingOptions
- Array yang dapat dibagi dari pengiriman opsierror
- String yang berisi pesan error generik (misalnya, saatchangeShippingOption
tidak memberikan ID opsi pengiriman yang valid)stringifiedPaymentMethodErrors
- String JSON yang mewakili validasi error untuk metode pembayaranaddressErrors
- Paket dengan kunci opsional yang sama dengan pengiriman alamat dan string masing-masing. Setiap kunci mewakili error validasi yang terkait dengan kunci bagian dari alamat pengiriman.
Kunci yang tidak ada berarti nilainya tidak berubah.