Cách cập nhật ứng dụng thanh toán Android của bạn để cung cấp địa chỉ giao hàng và thông tin liên hệ của người thanh toán với Web Payments API.
Việc nhập địa chỉ giao hàng và thông tin liên hệ thông qua biểu mẫu trên web có thể gây phiền hà cho khách hàng. Việc này có thể gây ra lỗi và làm giảm tỷ lệ chuyển đổi.
Đó là lý do API yêu cầu thanh toán hỗ trợ tính năng yêu cầu địa chỉ giao hàng và thông tin liên hệ. Điều này mang lại nhiều lợi ích:
- Người dùng có thể chọn đúng địa chỉ chỉ bằng vài lần nhấn.
- Địa chỉ luôn được trả về ở định dạng chuẩn.
- Bạn sẽ ít có khả năng gửi địa chỉ không chính xác hơn.
Trình duyệt có thể trì hoãn việc thu thập địa chỉ giao hàng và thông tin liên hệ cho một ứng dụng thanh toán để mang đến trải nghiệm thanh toán hợp nhất. Chức năng này được gọi là uỷ quyền.
Bất cứ khi nào có thể, Chrome sẽ uỷ quyền việc thu thập địa chỉ giao hàng và thông tin liên hệ của khách hàng cho ứng dụng thanh toán Android được gọi. Tính năng uỷ quyền giúp giảm sự phiền hà trong quá trình thanh toán.
Trang web của người bán có thể tự động cập nhật các lựa chọn vận chuyển và tổng giá tuỳ thuộc vào lựa chọn của khách hàng về địa chỉ giao hàng và lựa chọn vận chuyển.
Để thêm tính năng hỗ trợ uỷ quyền vào một ứng dụng thanh toán hiện có trên Android, hãy triển khai các bước sau:
- Khai báo các hình thức uỷ quyền được hỗ trợ.
- Phân tích cú pháp ý định bổ sung
PAY
cho các lựa chọn thanh toán bắt buộc. - Cung cấp thông tin bắt buộc trong phản hồi về khoản thanh toán.
- [Không bắt buộc] Hỗ trợ luồng động:
Khai báo các hình thức uỷ quyền được hỗ trợ
Trình duyệt cần biết danh sách thông tin bổ sung mà ứng dụng thanh toán của bạn có thể cung cấp để có thể uỷ quyền thu thập thông tin đó cho ứng dụng. Hãy khai báo các uỷ quyền được hỗ trợ dưới dạng <meta-data>
trong AndroidManifest.xml của ứng dụng.
<activity
android:name=".PaymentActivity"
…
<meta-data
android:name="org.chromium.payment_supported_delegations"
android:resource="@array/supported_delegations" />
</activity>
<resource>
phải là một danh sách chuỗi được chọn từ các giá trị hợp lệ sau:
[ "payerName", "payerEmail", "payerPhone", "shippingAddress" ]
Ví dụ sau đây chỉ có thể cung cấp địa chỉ giao hàng và địa chỉ email của người thanh toán.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
Phân tích cú pháp ý định bổ sung PAY
cho các tuỳ chọn thanh toán bắt buộc
Người bán có thể chỉ định thêm thông tin bắt buộc bằng từ điển paymentOptions
. Chrome sẽ cung cấp danh sách các tuỳ chọn bắt buộc mà ứng dụng của bạn có thể cung cấp bằng cách chuyển các tham số sau đến hoạt động PAY
dưới dạng Thông tin bổ sung về ý định.
paymentOptions
paymentOptions
là tập hợp con các tuỳ chọn thanh toán do người bán chỉ định mà ứng dụng của bạn đã khai báo hỗ trợ uỷ quyền.
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")
Hàm này có thể bao gồm các tham số sau:
requestPayerName
– Giá trị boolean cho biết liệu có bắt buộc phải cung cấp tên của người thanh toán hay không.requestPayerPhone
– Giá trị boolean cho biết liệu có bắt buộc phải sử dụng điện thoại của người thanh toán hay không.requestPayerEmail
– Giá trị boolean cho biết liệu email của người thanh toán có bắt buộc hay không.requestShipping
– Giá trị boolean cho biết liệu có bắt buộc phải cung cấp thông tin vận chuyển hay không.shippingType
– Chuỗi thể hiện loại hình vận chuyển. Loại hình vận chuyển có thể là"shipping"
,"delivery"
hoặc"pickup"
. Ứng dụng có thể sử dụng gợi ý này trong giao diện người dùng khi yêu cầu người dùng cung cấp địa chỉ hoặc lựa chọn về cách thức giao hàng.
shippingOptions
shippingOptions
là mảng theo gói của các lựa chọn vận chuyển do người bán chỉ định. Thông số này sẽ chỉ tồn tại khi paymentOptions.requestShipping ==
true
.
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
Mỗi cách tính phí vận chuyển là một Bundle
với các khoá sau.
id
– Giá trị nhận dạng cách tính phí vận chuyển.label
– Nhãn cách tính phí vận chuyển hiển thị cho người dùng.amount
– Gói phí vận chuyển chứa khoácurrency
vàvalue
có giá trị chuỗi.currency
cho biết đơn vị tiền tệ của phí vận chuyển, dưới dạng một mã bảng chữ cái gồm 3 chữ cái có định dạng hợp lệ theo tiêu chuẩn ISO4217value
cho biết giá trị của phí vận chuyển dưới dạng giá trị tiền tệ hợp lệ dạng thập phân
selected
– Liệu có nên chọn cách tính phí vận chuyển khi ứng dụng thanh toán hiển thị các lựa chọn vận chuyển hay không.
Tất cả khoá khác ngoài selected
đều có giá trị chuỗi. selected
có giá trị boolean.
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)
Cung cấp thông tin bắt buộc trong phản hồi thanh toán
Ứng dụng phải bao gồm thông tin bổ sung bắt buộc khi phản hồi hoạt động PAY
.
Để làm vậy, bạn phải chỉ định các tham số sau làm phần bổ sung Ý định:
payerName
– Tên đầy đủ của người thanh toán. Đây phải là một chuỗi không trống khipaymentOptions.requestPayerName
là true.payerPhone
– Số điện thoại của người thanh toán. Đây phải là một chuỗi không trống khipaymentOptions.requestPayerPhone
là true.payerEmail
– Địa chỉ email của người thanh toán. Đây phải là một chuỗi không trống khipaymentOptions.requestPayerEmail
là true.shippingAddress
– Địa chỉ giao hàng do người dùng cung cấp. Đây phải là một gói không trống khipaymentOptions.requestShipping
là true. Gói phải có các khoá sau đại diện cho các phần khác nhau trong một địa chỉ thực tế.city
countryCode
dependentLocality
organization
phone
postalCode
recipient
region
sortingCode
addressLine
Tất cả khoá khác ngoàiaddressLine
đều có giá trị chuỗi.addressLine
là một mảng chuỗi.
shippingOptionId
– Giá trị nhận dạng của hình thức vận chuyển do người dùng chọn. Giá trị này phải là một chuỗi không trống khipaymentOptions.requestShipping
là giá trị true.
Xác thực phản hồi thanh toán
Nếu bạn đặt kết quả hoạt động của một phản hồi thanh toán nhận được từ ứng dụng thanh toán đã gọi thành RESULT_OK
, thì Chrome sẽ kiểm tra thông tin bổ sung bắt buộc trong các ứng dụng bổ sung. Nếu xác thực không thành công, Chrome sẽ trả về lời hứa bị từ chối từ request.show()
kèm theo một trong các thông báo lỗi dành cho nhà phát triển sau đây:
'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".'
Mã mẫu sau đây là ví dụ về phản hồi hợp lệ:
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")
}
}
Không bắt buộc: Hỗ trợ luồng động
Đôi khi, tổng chi phí của một giao dịch sẽ tăng lên, chẳng hạn như khi người dùng chọn phương thức vận chuyển nhanh hoặc khi danh sách các lựa chọn vận chuyển có sẵn hoặc giá thay đổi khi người dùng chọn một địa chỉ giao hàng quốc tế. Khi cung cấp địa chỉ hoặc lựa chọn giao hàng do người dùng chọn, ứng dụng của bạn phải có thể thông báo cho người bán về mọi thay đổi về địa chỉ hoặc lựa chọn giao hàng, đồng thời cho người dùng thấy thông tin thanh toán mới nhất (do người bán cung cấp).
AIDL
Để thông báo cho người bán về các thay đổi mới, hãy sử dụng dịch vụ PaymentDetailsUpdateService
được khai báo trong AndroidManifest.xml của Chrome. Để sử dụng dịch vụ này, hãy tạo 2 tệp AIDL với nội dung sau:
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);
}
Thông báo cho người bán về những thay đổi trong phương thức thanh toán, địa chỉ giao hàng hoặc cách thức giao hàng mà người dùng đã chọn
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
dùng cho ý định bắt đầu của dịch vụ có thể có một trong các giá trị sau, tuỳ thuộc vào trình duyệt đã khởi tạo yêu cầu thanh toán.
Kênh Chrome | Tên gói |
---|---|
Ổn định |
"com.android.chrome"
|
Beta |
"com.chrome.beta"
|
Nhà phát triển |
"com.chrome.dev"
|
Canary |
"com.chrome.canary"
|
Chromium |
"org.chromium.chrome"
|
Hộp Tìm kiếm Nhanh của Google (trình nhúng WebLayer) |
"com.google.android.googlequicksearchbox"
|
changePaymentMethod
Thông báo cho người bán về những thay đổi đối với phương thức thanh toán do người dùng chọn. Gói paymentHandlerMethodData
chứa methodName
và các khoá details
không bắt buộc, cả hai đều có giá trị chuỗi. Chrome sẽ kiểm tra một gói không trống có methodName
không trống và gửi một updatePaymentDetails
kèm theo một trong các thông báo lỗi sau đây qua callback.updateWith
nếu quá trình xác thực không thành công.
'Method data required.'
'Method name required.'
changeShippingOption
Thông báo cho người bán về những thay đổi đối với phương thức vận chuyển do người dùng chọn.
shippingOptionId
phải là giá trị nhận dạng của một trong các hình thức vận chuyển do người bán chỉ định. Chrome sẽ kiểm tra để tìm shippingOptionId
không trống và gửi
updatePaymentDetails
kèm theo thông báo lỗi sau qua
callback.updateWith
nếu quá trình xác thực không thành công.
'Shipping option identifier required.'
changeShippingAddress
Thông báo cho người bán khi địa chỉ giao hàng do người dùng cung cấp thay đổi. Chrome sẽ kiểm tra gói shippingAddress
không trống có countryCode
hợp lệ rồi gửi updatePaymentDetails
kèm theo thông báo lỗi sau qua callback.updateWith
nếu quá trình xác thực không thành công.
'Payment app returned invalid shipping address in response.'
Thông báo lỗi trạng thái không hợp lệ
Nếu gặp phải trạng thái không hợp lệ sau khi nhận được bất kỳ yêu cầu thay đổi nào, thì Chrome sẽ gọi callback.updateWith
với một gói updatePaymentDetails
đã loại bỏ dữ liệu. Gói sẽ chỉ chứa khoá error
với "Invalid state"
.
Ví dụ về trạng thái không hợp lệ:
- Khi Chrome vẫn đang chờ người bán phản hồi về một thay đổi trước đó (chẳng hạn như một sự kiện thay đổi đang diễn ra).
- Giá trị nhận dạng tuỳ chọn vận chuyển do ứng dụng thanh toán cung cấp không thuộc bất kỳ tuỳ chọn vận chuyển nào do người bán chỉ định.
Nhận thông tin thanh toán mới nhất từ người bán
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
là gói tương đương với từ điển PaymentRequestDetailsUpdate
WebIDL (sau khi loại bỏ trường modifiers
) và chứa các khoá không bắt buộc sau:
total
– Gói chứa các khoácurrency
vàvalue
, cả hai khoá đều có giá trị chuỗishippingOptions
– Mảng tuỳ chọn vận chuyển có thể đóng góierror
– Một chuỗi chứa thông báo lỗi chung (ví dụ: khichangeShippingOption
không cung cấp giá trị nhận dạng hợp lệ của lựa chọn vận chuyển)stringifiedPaymentMethodErrors
– Một chuỗi JSON biểu thị các lỗi xác thực của phương thức thanh toánaddressErrors
– Một gói có các khoá không bắt buộc giống hệt với địa chỉ vận chuyển và giá trị chuỗi. Mỗi khoá biểu thị một lỗi xác thực liên quan đến phần tương ứng trong địa chỉ giao hàng.
Khoá vắng mặt có nghĩa là giá trị của khoá không thay đổi.