Jak zaktualizować aplikację do płatności na Androida, aby udostępnić adres dostawy i informacje kontaktowe płatnika za pomocą interfejsów Web Payments API.
Podawanie adresu dostawy i danych kontaktowych w formularzu internetowym może być uciążliwe dla klientów. Może to powodować błędy i obniżać współczynnik konwersji.
Dlatego interfejs Payment Request API ma funkcję żądania adresu dostawy i danych kontaktowych. Zapewnia to wiele korzyści:
- Użytkownicy mogą wybrać odpowiedni adres za pomocą kilku kliknięć.
- Adres jest zawsze zwracany w standardowym formacie.
- Przesłanie nieprawidłowego adresu jest mniej prawdopodobne.
Przeglądarki mogą odroczyć zbieranie adresu dostawy i danych kontaktowych do aplikacji płatniczej, aby zapewnić jednolitą obsługę płatności. Ta funkcja nazywa się delegacja.
W miarę możliwości Chrome przekazuje adres dostawy i informacje kontaktowe klienta do wywoływanej aplikacji płatniczej na Androida. Przekazywanie dostępu ułatwia proces płatności.
Strona sprzedawcy może dynamicznie aktualizować opcje dostawy i łączną cenę w zależności od wybranego przez klienta adresu dostawy i opcji dostawy.
Aby dodać obsługę przekazywania dostępu do istniejącej aplikacji płatniczej na Androida, wykonaj te czynności:
- Deklaruj obsługiwane delegacje.
- Przeanalizuj
PAY
dodatkowe informacje o intencji, aby sprawdzić wymagane opcje płatności. - Podaj wymagane informacje w odpowiedzi na prośbę o płatność.
- [Opcjonalnie] Obsługa dynamicznego przepływu:
Zadeklaruj obsługiwane delegacje
Przeglądarka musi znać listę dodatkowych informacji, które może udostępnić Twoja aplikacja do płatności, aby mogła zlecić jej zbieranie. Zadeklaruj obsługiwane delegowanie jako <meta-data>
w pliku AndroidManifest.xml aplikacji.
<activity
android:name=".PaymentActivity"
…
<meta-data
android:name="org.chromium.payment_supported_delegations"
android:resource="@array/supported_delegations" />
</activity>
<resource>
musi być listą ciągów znaków wybranych spośród tych prawidłowych wartości:
[ "payerName", "payerEmail", "payerPhone", "shippingAddress" ]
W tym przykładzie można podać tylko adres dostawy i adres e-mail płatnika.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
Parsowanie PAY
dodatkowych informacji o zamierzeniu w przypadku wymaganych opcji płatności
Sprzedawca może podać dodatkowe wymagane informacje za pomocą słownika paymentOptions
. Chrome przekaże listę wymaganych opcji, które może zapewnić Twoja aplikacja, przekazując poniższe parametry do aktywności PAY
jako extras.
paymentOptions
paymentOptions
to podzbiór opcji płatności określonych przez sprzedawcę, w przypadku których Twoja aplikacja zadeklarowała obsługę przekazywania dostępu.
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")
Może on zawierać te parametry:
requestPayerName
– wartość logiczna wskazująca, czy imię i nazwisko płatnika jest wymagane.requestPayerPhone
– wartość logiczna określająca, czy telefon płatnika jest wymagany.requestPayerEmail
– wartość logiczna wskazująca, czy adres e-mail płatnika jest wymagany.requestShipping
– wartość logiczna wskazująca, czy informacje o dostawie są wymagane.shippingType
– ciąg tekstowy określający typ dostawy. Typ dostawy może być określony jako"shipping"
,"delivery"
lub"pickup"
. Aplikacja może używać tego podpowiedzi w interfejsie użytkownika, gdy prosi o adres użytkownika lub wybór opcji dostawy.
shippingOptions
shippingOptions
to tablica z opcjami dostawy określonymi przez sprzedawcę. Ten parametr będzie istnieć tylko wtedy, gdy paymentOptions.requestShipping ==
true
.
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
Każda opcja dostawy to Bundle
z tymi kluczami.
id
– identyfikator opcji dostawy.label
– etykieta opcji dostawy wyświetlana użytkownikowi.amount
– pakiet kosztów dostawy zawierający kluczecurrency
ivalue
z wartościami typu ciąg znaków.currency
pokazuje walutę kosztu dostawy jako prawidłowo sformułowany 3-literowy kod alfabetyczny ISO 4217.value
pokazuje wartość kosztu dostawy jako prawidłową wartość dziesiętną
selected
– określa, czy opcja dostawy ma być wybrana, gdy aplikacja do płatności wyświetla opcje dostawy.
Wszystkie klucze inne niż selected
mają wartości ciągu znaków. selected
ma wartość logiczną.
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)
Podawanie wymaganych informacji w odpowiedzi na prośbę o płatność
Aplikacja powinna zawierać wymagane dodatkowe informacje w odpowiedzi na aktywność PAY
.
W tym celu jako dodatki intencji należy określić te parametry:
payerName
– imię i nazwisko płatnika. GdypaymentOptions.requestPayerName
ma wartość prawda, ten ciąg nie może być pusty.payerPhone
– numer telefonu płatnika. Jeśli parametrpaymentOptions.requestPayerPhone
ma wartość prawda, ciąg znaków powinien być niepusty.payerEmail
– adres e-mail płatnika. Ten ciąg znaków nie może być pusty, gdypaymentOptions.requestPayerEmail
ma wartość true.shippingAddress
– podany przez użytkownika adres dostawy. Jeśli parametrpaymentOptions.requestShipping
ma wartość prawda, pakiet powinien być niepusty. Pakiet powinien zawierać te klucze, które reprezentują różne części adresu fizycznego.city
countryCode
dependentLocality
organization
phone
postalCode
recipient
region
sortingCode
addressLine
Wszystkie klucze inne niżaddressLine
mają wartości ciągu znaków. ArgumentaddressLine
jest tablicą ciągów znaków.
shippingOptionId
– identyfikator opcji dostawy wybranej przez użytkownika. Jeśli parametrpaymentOptions.requestShipping
ma wartość prawda, ten ciąg znaków nie może być pusty.
Sprawdź odpowiedź dotyczącą płatności
Jeśli wynik aktywności odpowiedzi na płatność otrzymanej z wywołanej aplikacji do płatności ma wartość RESULT_OK
, Chrome sprawdzi, czy w sekcji dodatków znajdują się wymagane dodatkowe informacje. Jeśli weryfikacja się nie powiedzie, Chrome zwróci odrzucone obiecanie z request.show()
z jednym z tych komunikatów o błędzie dla deweloperów:
'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".'
Poniższa próbka kodu to przykład prawidłowej odpowiedzi:
fun Intent.populateRequestedPaymentOptions() {
if (requestPayerName) {
putExtra("payerName", "John Smith")
}
if (requestPayerPhone) {
putExtra("payerPhone", "4169158200")
}
if (requestPayerEmail) {
putExtra("payerEmail", "[email protected]")
}
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")
}
}
Opcjonalnie: obsługa przepływu dynamicznego
Czasami całkowity koszt transakcji wzrasta, np. gdy użytkownik wybierze opcję dostawy ekspresowej lub gdy lista dostępnych opcji dostawy lub ich ceny zmieni się po wybraniu przez użytkownika międzynarodowego adresu dostawy. Gdy Twoja aplikacja udostępnia adres dostawy lub opcję wybrane przez użytkownika, powinna być w stanie powiadomić sprzedawcę o zmianach adresu dostawy lub opcji oraz wyświetlić użytkownikowi zaktualizowane szczegóły płatności (udostępnione przez sprzedawcę).
AIDL
Aby powiadomić sprzedawcę o nowych zmianach, użyj usługi PaymentDetailsUpdateService
zadeklarowanej w pliku AndroidManifest.xml w Chrome. Aby korzystać z tej usługi, utwórz 2 pliki AIDL z takimi treściami:
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);
}
powiadamianie sprzedawcy o zmianach w wybranej przez użytkownika formie płatności, adresie dostawy lub opcji dostawy;
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
}
}
}
Wartość callingPackageName
używana do określania intencji uruchomienia usługi może być jedną z tych wartości w zależności od przeglądarki, która zainicjowała żądanie płatności.
Kanały Chrome | Nazwa pakietu |
---|---|
Stabilny |
"com.android.chrome"
|
Beta |
"com.chrome.beta"
|
Dla programistów |
"com.chrome.dev"
|
Canary |
"com.chrome.canary"
|
Chromium |
"org.chromium.chrome"
|
Okno szybkiego wyszukiwania Google (osadzający komponent WebLayer) |
"com.google.android.googlequicksearchbox"
|
changePaymentMethod
Informuje sprzedawcę o zmianach w wybranej przez użytkownika formie płatności. Pakiet paymentHandlerMethodData
zawiera klucze methodName
i opcjonalnie details
, oba z wartościami tekstowymi. Jeśli weryfikacja się nie powiedzie, Chrome sprawdzi, czy nie ma pustego pakietu z niepustym methodName
i wyśle updatePaymentDetails
z jednym z tych komunikatów o błędzie przez callback.updateWith
.
'Method data required.'
'Method name required.'
changeShippingOption
powiadamia sprzedawcę o zmianach w wybranej przez użytkownika opcji dostawy.
shippingOptionId
powinien być identyfikatorem jednej z opcji dostawy określonych przez sprzedawcę. Jeśli weryfikacja się nie powiedzie, Chrome sprawdzi, czy shippingOptionId
nie jest pusty, i wyśle updatePaymentDetails
z tym komunikatem o błędzie przez callback.updateWith
.
'Shipping option identifier required.'
changeShippingAddress
powiadamia sprzedawcę o zmianach adresu dostawy podanego przez użytkownika; Chrome sprawdzi, czy istnieje niepusty pakiet shippingAddress
z prawidłowym countryCode
, i wyśle updatePaymentDetails
z tym komunikatem o błędzie przez callback.updateWith
, jeśli weryfikacja się nie powiedzie.
'Payment app returned invalid shipping address in response.'
Komunikat o błędzie „Nieprawidłowy stan”
Jeśli po otrzymaniu żądania zmiany Chrome napotka nieprawidłowy stan, wywoła funkcję callback.updateWith
z zawartym w niej zbiorem updatePaymentDetails
. Pakiet będzie zawierać tylko klucz error
z wartością "Invalid state"
.
Przykłady nieprawidłowego stanu:
- Gdy Chrome nadal oczekuje na odpowiedź sprzedawcy na poprzednią zmianę (np. trwające zdarzenie zmiany).
- Identyfikator opcji dostawy podany w aplikacji nie należy do żadnej z opcji dostawy określonych przez sprzedawcę.
Odbieranie zaktualizowanych danych do płatności od sprzedawcy
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
to pakiet odpowiednika słownika PaymentRequestDetailsUpdate
WebIDL (po usunięciu pola modifiers
) i zawiera te klucze opcjonalne:
total
– pakiet zawierający kluczecurrency
ivalue
, oba klucze mają wartości ciągu znakówshippingOptions
– tablica opcji dostawy do pakowania.error
– ciąg tekstowy zawierający ogólny komunikat o błędzie (np.gdychangeShippingOption
nie podaje prawidłowego identyfikatora opcji dostawy).stringifiedPaymentMethodErrors
– ciąg JSON reprezentujący błędy walidacji formy płatności.addressErrors
– pakiet z opcjonalnymi kluczami identycznymi z adresem dostawy i wartościami w postaci ciągów znaków. Każdy klucz reprezentuje błąd walidacji związany z odpowiadającym mu elementem adresu dostawy.
Brak klucza oznacza, że jego wartość się nie zmieniła.