วิธีอัปเดตแอปการชำระเงิน Android เพื่อระบุที่อยู่สำหรับจัดส่งและข้อมูลติดต่อของผู้ชำระเงินด้วย Web Payments API
การป้อนที่อยู่สำหรับจัดส่งและข้อมูลติดต่อผ่านเว็บฟอร์มอาจเป็นเรื่องยุ่งยากสำหรับลูกค้า อาจทำให้เกิดข้อผิดพลาด และอัตรา Conversion
ซึ่งเป็นเหตุผลที่ Payment Request API รองรับฟีเจอร์สำหรับขอที่อยู่สำหรับจัดส่งและข้อมูลติดต่อ ซึ่งมีประโยชน์หลายประการดังนี้
- ผู้ใช้จะเลือกที่อยู่ที่ถูกต้องได้ด้วยการแตะเพียงไม่กี่ครั้ง
- ระบบจะแสดงผลอีเมลในรูปแบบมาตรฐานเสมอ
- การส่งที่อยู่ที่ไม่ถูกต้องมีโอกาสน้อยลง
เบราว์เซอร์สามารถเลื่อนการเก็บข้อมูลที่อยู่สำหรับจัดส่งและข้อมูลติดต่อไปยังแอปการชำระเงินเพื่อมอบประสบการณ์การชำระเงินที่เป็นหนึ่งเดียวได้ ฟังก์ชันการทำงานนี้เรียกว่าการมอบสิทธิ์
หากเป็นไปได้ Chrome จะมอบสิทธิ์ในการรวบรวมที่อยู่สำหรับจัดส่งและข้อมูลติดต่อของลูกค้าให้แก่แอปการชำระเงินของ Android ที่เรียกใช้ ซึ่งการมอบสิทธิ์นี้จะช่วยลดความยุ่งยากในระหว่างการชำระเงิน
เว็บไซต์ผู้ขายสามารถอัปเดตตัวเลือกการจัดส่งและราคารวมแบบไดนามิก โดยขึ้นอยู่กับทางเลือกในการจัดส่งของลูกค้าและตัวเลือกการจัดส่ง
หากต้องการเพิ่มการสนับสนุนการมอบสิทธิ์ในแอปการชำระเงิน Android ที่มีอยู่แล้ว ให้ทำตามขั้นตอนต่อไปนี้
- ประกาศการมอบสิทธิ์ที่รองรับ
- แยกวิเคราะห์ Intent เพิ่มเติม
PAY
สำหรับตัวเลือกการชำระเงินที่จำเป็น - ระบุข้อมูลที่จำเป็นในการตอบกลับการชำระเงิน
- [ไม่บังคับ] รองรับขั้นตอนแบบไดนามิก
ประกาศการมอบสิทธิ์ที่รองรับ
เบราว์เซอร์จำเป็นต้องทราบรายการข้อมูลเพิ่มเติมที่แอปสำหรับชำระเงินสามารถให้เพื่อมอบสิทธิ์การรวบรวมข้อมูลดังกล่าวให้กับแอปของคุณได้ ประกาศการมอบสิทธิ์ที่รองรับเป็น <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" ]
ตัวอย่างต่อไปนี้ระบุได้เฉพาะที่อยู่สำหรับจัดส่งและอีเมลของผู้ชำระเงินเท่านั้น
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
แยกวิเคราะห์ส่วนเสริม Intent PAY
สำหรับตัวเลือกการชำระเงินที่จำเป็น
ผู้ขายจะระบุข้อมูลที่จำเป็นเพิ่มเติมได้โดยใช้พจนานุกรม paymentOptions
Chrome จะแสดงรายการตัวเลือกที่จําเป็นซึ่งแอปสามารถให้ได้โดยส่งพารามิเตอร์ต่อไปนี้ไปยังกิจกรรม PAY
เป็น Intent extras
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"
แอปของคุณสามารถใช้คำแนะนำนี้ใน UI เมื่อขอที่อยู่ของผู้ใช้หรือตัวเลือกการจัดส่ง
shippingOptions
shippingOptions
คือตัวเลือกการจัดส่งที่ผู้ขายระบุได้ซึ่งจัดเรียงเป็นที่ดิน พารามิเตอร์นี้จะมีอยู่ก็ต่อเมื่อ paymentOptions.requestShipping ==
true
เท่านั้น
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
ตัวเลือกการจัดส่งแต่ละรายการคือ Bundle
ที่มีคีย์ต่อไปนี้
id
- ตัวระบุตัวเลือกการจัดส่งlabel
- ป้ายกำกับตัวเลือกการจัดส่งที่แสดงต่อผู้ใช้amount
- แพ็กเกจค่าจัดส่งที่มีcurrency
และvalue
คีย์ที่มีค่าสตริงcurrency
แสดงสกุลเงินของค่าจัดส่ง เป็นรหัสตัวอักษร 3 ตัวที่มีการจัดรูปแบบเป็น ISO4217value
แสดงมูลค่าของค่าจัดส่งเป็นมูลค่าเงินทศนิยมที่ถูกต้อง
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
โดยต้องระบุพารามิเตอร์ต่อไปนี้เป็น Intent เพิ่มเติม
payerName
- ชื่อและนามสกุลของผู้ชำระเงิน สตริงนี้ควรเป็นสตริงที่ไม่ว่างเปล่าเมื่อpaymentOptions.requestPayerName
เป็นจริงpayerPhone
- หมายเลขโทรศัพท์ของผู้ชำระเงิน สตริงนี้ควรเป็นสตริงที่ไม่ว่างเปล่าเมื่อpaymentOptions.requestPayerPhone
เป็นจริงpayerEmail
- อีเมลของผู้ชำระเงิน สตริงนี้ควรเป็นสตริงที่ไม่ว่างเปล่า เมื่อpaymentOptions.requestPayerEmail
เป็นจริงshippingAddress
- ที่อยู่สำหรับจัดส่งที่ได้จากผู้ใช้ ซึ่งควรเป็นแพ็กเกจที่ไม่ว่างเปล่าเมื่อpaymentOptions.requestShipping
เป็นจริง แพ็กเกจดังกล่าวควรมีคีย์ต่อไปนี้ซึ่งแสดงส่วนต่างๆ ในที่อยู่จริงcity
countryCode
dependentLocality
organization
phone
postalCode
recipient
region
sortingCode
addressLine
คีย์ทั้งหมดที่ไม่ใช่addressLine
มีค่าสตริงaddressLine
คืออาร์เรย์ของสตริง
shippingOptionId
- ตัวระบุของตัวเลือกการจัดส่งที่ผู้ใช้เลือก ค่านี้ควรเป็นสตริงที่ไม่ว่างเปล่าเมื่อpaymentOptions.requestShipping
เป็นจริง
ตรวจสอบการตอบกลับการชำระเงิน
หากผลกิจกรรมของการตอบกลับการชำระเงินที่ได้รับจากแอปการชำระเงินที่เรียกใช้มีการตั้งค่าเป็น 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")
}
}
ไม่บังคับ: รองรับขั้นตอนแบบไดนามิก
บางครั้งค่าใช้จ่ายรวมในการทำธุรกรรมจะเพิ่มขึ้น เช่น เมื่อผู้ใช้เลือกตัวเลือกการจัดส่งด่วน หรือเมื่อรายการตัวเลือกการจัดส่งที่ใช้ได้หรือราคามีการเปลี่ยนแปลงเมื่อผู้ใช้เลือกที่อยู่สำหรับจัดส่งระหว่างประเทศ เมื่อแอปของคุณแจ้งที่อยู่สำหรับจัดส่งหรือตัวเลือกที่ผู้ใช้เลือกแล้ว แอปควรจะสามารถแจ้งผู้ขายเกี่ยวกับที่อยู่สำหรับจัดส่งหรือการเปลี่ยนแปลงตัวเลือกใดๆ และแสดงรายละเอียดการชำระเงินที่อัปเดตให้ผู้ใช้ทราบ (ซึ่งผู้ขายให้ไว้)
AIDL
หากต้องการแจ้งให้ผู้ขายทราบเกี่ยวกับการเปลี่ยนแปลงใหม่ ให้ใช้บริการ PaymentDetailsUpdateService
ที่ประกาศใน AndroidManifest.xml ของ Chrome หากต้องการใช้บริการนี้ ให้สร้างไฟล์ AIDL 2 ไฟล์ที่มีเนื้อหาต่อไปนี้
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
ที่ใช้สำหรับ Intent เริ่มต้นของบริการอาจมีค่าใดค่าหนึ่งต่อไปนี้ ทั้งนี้ขึ้นอยู่กับเบราว์เซอร์ที่ส่งคำขอการชำระเงิน
ช่องทาง Chrome | ชื่อแพ็กเกจ |
---|---|
คงที่ |
"com.android.chrome"
|
เบต้า |
"com.chrome.beta"
|
กำลังพัฒนา |
"com.chrome.dev"
|
คะแนรี |
"com.chrome.canary"
|
Chromium |
"org.chromium.chrome"
|
ช่อง Google Quick Search (เครื่องมือฝัง WebLayer) |
"com.google.android.googlequicksearchbox"
|
changePaymentMethod
แจ้งผู้ขายเกี่ยวกับการเปลี่ยนแปลงวิธีการชำระเงินที่ผู้ใช้เลือก แพ็กเกจ paymentHandlerMethodData
มี methodName
และคีย์ details
ที่ไม่บังคับทั้ง 2 รายการที่มีค่าสตริง Chrome จะตรวจหากลุ่มที่ไม่ว่างเปล่าซึ่งมี methodName
ที่ไม่ว่างเปล่าและส่ง updatePaymentDetails
พร้อมด้วยข้อความแสดงข้อผิดพลาดอย่างใดอย่างหนึ่งต่อไปนี้ผ่านทาง callback.updateWith
หากการตรวจสอบไม่สำเร็จ
'Method data required.'
'Method name required.'
changeShippingOption
แจ้งผู้ขายเกี่ยวกับการเปลี่ยนแปลงในตัวเลือกการจัดส่งที่ผู้ใช้เลือก
shippingOptionId
ควรเป็นตัวระบุของตัวเลือกการจัดส่งที่ผู้ขายระบุ Chrome จะตรวจหา shippingOptionId
ที่ไม่ว่างเปล่าและส่ง updatePaymentDetails
พร้อมข้อความแสดงข้อผิดพลาดต่อไปนี้ผ่าน callback.updateWith
หากตรวจสอบไม่สำเร็จ
'Shipping option identifier required.'
changeShippingAddress
แจ้งให้ผู้ขายทราบเกี่ยวกับการเปลี่ยนแปลงในที่อยู่สำหรับจัดส่งที่ผู้ใช้ให้ไว้ Chrome จะตรวจหาแพ็กเกจ shippingAddress
ที่ไม่ว่างเปล่าซึ่งมี countryCode
ที่ถูกต้องและส่ง updatePaymentDetails
พร้อมข้อความแสดงข้อผิดพลาดต่อไปนี้ผ่านทาง callback.updateWith
หากตรวจสอบไม่สำเร็จ
'Payment app returned invalid shipping address in response.'
ข้อความแสดงข้อผิดพลาดเกี่ยวกับสถานะไม่ถูกต้อง
หาก Chrome พบสถานะที่ไม่ถูกต้องเมื่อได้รับคำขอเปลี่ยนแปลง ระบบจะเรียกใช้ callback.updateWith
โดยมีแพ็กเกจ updatePaymentDetails
ที่มีการปกปิด แพ็กเกจดังกล่าวจะมีเฉพาะคีย์ error
ที่มี "Invalid state"
ตัวอย่างของสถานะที่ไม่ถูกต้อง ได้แก่
- เมื่อ Chrome ยังคงรอให้ผู้ขายตอบรับการเปลี่ยนแปลงก่อนหน้า (เช่น เหตุการณ์การเปลี่ยนแปลงที่ดำเนินอยู่)
- ตัวระบุตัวเลือกการจัดส่งที่แอปสำหรับชำระเงินไม่ได้อยู่ในตัวเลือกการจัดส่งที่ผู้ขายระบุ
รับรายละเอียดการชำระเงินที่อัปเดตจากผู้ขาย
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
เป็นแพ็กเกจที่เทียบเท่ากับพจนานุกรม
PaymentRequestDetailsUpdate
WebIDL (หลังจากปกปิดช่อง modifiers
) และมีคีย์ที่ไม่บังคับต่อไปนี้
total
- แพ็กเกจที่มีคีย์currency
และvalue
โดยทั้ง 2 คีย์มีค่าสตริงshippingOptions
- อาร์เรย์ที่แยกวิเคราะห์ได้ของตัวเลือกการจัดส่งerror
- สตริงที่มีข้อความแสดงข้อผิดพลาดทั่วไป (เช่น เมื่อchangeShippingOption
ไม่มีตัวระบุตัวเลือกการจัดส่งที่ถูกต้อง)stringifiedPaymentMethodErrors
- สตริง JSON ที่แสดงข้อผิดพลาดในการตรวจสอบความถูกต้องของวิธีการชำระเงินaddressErrors
- แพ็กเกจที่มีคีย์ที่ไม่บังคับซึ่งเหมือนกับที่อยู่จัดส่งและค่าสตริง แต่ละคีย์จะแสดงข้อผิดพลาดในการตรวจสอบความถูกต้องที่เกี่ยวข้องกับส่วนที่เกี่ยวข้องของที่อยู่สำหรับจัดส่ง
คีย์ที่ไม่มีหมายความว่าค่าคีย์ไม่มีการเปลี่ยนแปลง