Jak zaktualizować aplikację do płatności na Androida, aby podać adres dostawy i dane kontaktowe płatnika za pomocą interfejsów API płatności internetowych.
Podawanie adresu dostawy i danych kontaktowych w formularzu internetowym może być uciążliwe dla klientów. Może powodować błędy i obniżać współczynnik konwersji.
Dlatego interfejs Payment Request API obsługuje funkcję żądania adresu dostawy i informacji kontaktowych. Dzięki temu:
- Użytkownicy mogą wybrać właściwy adres zaledwie kilkoma kliknięciami.
- Adres jest zawsze zwracany w formacie standardowym.
- Podanie nieprawidłowego adresu jest mniej prawdopodobne.
Przeglądarki mogą opóźnić zbieranie adresu dostawy i danych kontaktowych przez aplikację płatniczą, aby zapewnić ujednolicone proces płatności. Jest to tzw. przekazywanie dostępu.
O ile jest to możliwe, Chrome przekazuje dane kontaktowe i adres dostawy klienta do wywołanej aplikacji płatniczej na Androida. Przekazywanie dostępu upraszcza proces płatności.
Witryna 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 aplikacji do płatności na Androida, która już istnieje, wykonaj te czynności:
- Deklaruj obsługiwane przekazywanie dostępu.
- Przeanalizuj dodatkowe intencje (
PAY
) dla wymaganych opcji płatności. - Podaj wymagane informacje w odpowiedzi na płatność.
- [Opcjonalnie] Obsługa dynamicznego przepływu:
Deklarowanie obsługiwanych przedstawicieli
Przeglądarka musi znać listę dodatkowych informacji, które może udostępnić aplikacja płatnicza, aby mogła przekazać zbieranie tych informacji do aplikacji. Obsługiwane uprawnienia dostępu muszą być zadeklarowane 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 wybranych spośród tych prawidłowych wartości:
[ "payerName", "payerEmail", "payerPhone", "shippingAddress" ]
Poniższy przykład może zawierać 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>
Przeanalizuj dodatki intencji PAY
pod kątem wymaganych opcji płatności
Dodatkowe wymagane informacje sprzedawca może podać w słowniku paymentOptions
. Chrome przedstawi listę wymaganych opcji, które może udostępnić Twoja aplikacja, przekazując te parametry do aktywności PAY
jako rozszerzenia intencji.
paymentOptions
paymentOptions
to podzbiór opcji płatności określonych przez sprzedawcę, w przypadku których Twoja aplikacja zadeklarowała pomoc w przekazywaniu 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 zawierać te parametry:
requestPayerName
– wartość logiczna wskazująca, czy nazwa płatnika jest wymagana.requestPayerPhone
– wartość logiczna wskazująca, czy wymagany jest numer telefonu płatnika.requestPayerEmail
– wartość logiczna wskazująca, czy wymagany jest adres e-mail płatnika.requestShipping
– wartość logiczna wskazująca, czy informacje o dostawie są wymagane.shippingType
– ciąg tekstowy przedstawiający typ dostawy. Typ dostawy to"shipping"
,"delivery"
lub"pickup"
. Aplikacja może użyć tej wskazówki w swoim interfejsie, gdy prosi o podanie adresu użytkownika lub wyboru opcji dostawy.
shippingOptions
shippingOptions
to tablica opcji dostawy określonych przez sprzedawcę z możliwością paczki. Ten parametr będzie występować 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 poniższymi kluczami.
id
– identyfikator opcji dostawy.label
– etykieta opcji wysyłki wyświetlana użytkownikowi.amount
– pakiet kosztów dostawy zawierający kluczecurrency
ivalue
z wartościami ciągów.currency
pokazuje walutę, w której podano koszt dostawy, w postaci prawidłowego, 3-literowego kodu alfabetu ISO4217.value
pokazuje koszt dostawy jako prawidłową wartość pieniężną dziesiętną.
selected
– określa, czy opcję dostawy należy wybrać, gdy aplikacja płatnicza wyświetla opcje dostawy.
Wszystkie klucze oprócz selected
zawierają wartości w postaci ciągów 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 płatność
Aplikacja powinna zawierać wymagane informacje dodatkowe w odpowiedzi na aktywność PAY
.
Aby było to możliwe, następujące parametry muszą być określone jako dodatki do intencji:
payerName
– pełna nazwa płatnika. JeślipaymentOptions.requestPayerName
ma wartość prawda, to pole nie może być puste.payerPhone
– numer telefonu płatnika. JeślipaymentOptions.requestPayerPhone
ma wartość prawda, to pole nie może być puste.payerEmail
– adres e-mail płatnika. JeślipaymentOptions.requestPayerEmail
ma wartość prawda, ciąg znaków nie może być pusty.shippingAddress
– adres dostawy podany przez użytkownika. GdypaymentOptions.requestShipping
ma wartość prawda, pakiet nie powinien być pusty. Pakiet powinien mieć następujące klucze reprezentujące różne części adresu fizycznego.city
countryCode
dependentLocality
organization
phone
postalCode
recipient
region
sortingCode
addressLine
Wszystkie klucze opróczaddressLine
zawierają wartości w postaci ciągów znaków.addressLine
to tablica ciągów tekstowych.
shippingOptionId
– identyfikator opcji dostawy wybranej przez użytkownika. JeślipaymentOptions.requestShipping
ma wartość prawda, to pole nie może być puste.
Zweryfikuj odpowiedź dotyczącą płatności
Jeśli wynik aktywności odpowiedzi na płatność otrzymaną z wywołanej aplikacji płatniczej jest ustawiony na RESULT_OK
, Chrome sprawdzi w dodatkach wymagane dodatkowe informacje. Jeśli weryfikacja się nie powiedzie, Chrome zwróci od request.show()
komunikat o odrzuceniu z jednym z tych komunikatów o błędzie:
'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".'
Oto przykładowy kod prawidłowej odpowiedzi:
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")
}
}
Opcjonalnie: obsługa przepływu dynamicznego
Czasami całkowity koszt transakcji rośnie, np. gdy użytkownik wybiera opcję ekspresowej dostawy lub gdy lista dostępnych opcji dostawy bądź ich ceny zmieniają się, gdy użytkownik wybiera międzynarodowy adres dostawy. Gdy aplikacja udostępnia wybrany przez użytkownika adres dostawy lub opcję, powinna być w stanie powiadamiać sprzedawcę o wszelkich zmianach adresu dostawy lub opcji i wyświetlać użytkownikowi zaktualizowane dane do płatności (podane 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 dwa pliki AI o tej zawartości:
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);
}
Powiadom sprzedawcę 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
}
}
}
Pole callingPackageName
używane w intencji uruchomienia usługi może mieć jedną z tych wartości w zależności od przeglądarki, która zainicjowała żądanie płatności.
Kanał Chrome | Nazwa pakietu |
---|---|
Stabilny |
"com.android.chrome"
|
Beta |
"com.chrome.beta"
|
Dla programistów |
"com.chrome.dev"
|
Wyspy Kanaryjskie |
"com.chrome.canary"
|
Chromium |
"org.chromium.chrome"
|
Okno szybkiego wyszukiwania Google (umieszczony element WebLayer) |
"com.google.android.googlequicksearchbox"
|
changePaymentMethod
Powiadamia sprzedawcę o zmianach w wybranej przez użytkownika formie płatności. Pakiet paymentHandlerMethodData
zawiera methodName
i opcjonalne klucze details
z wartościami będącymi ciągiem znaków. Chrome sprawdzi, czy pakiet nie jest pusty z niepustym elementem methodName
, i jeśli weryfikacja się nie powiedzie, Chrome wyśle polecenie updatePaymentDetails
z jednym z tych komunikatów o błędach.callback.updateWith
'Method data required.'
'Method name required.'
changeShippingOption
Powiadamia sprzedawcę o zmianach w wybranej przez użytkownika opcji dostawy.
Wartość shippingOptionId
powinna być identyfikatorem jednej z opcji dostawy określonych przez sprzedawcę. Chrome sprawdzi, czy brakuje niepustego elementu shippingOptionId
, i jeśli weryfikacja się nie powiedzie, wyśle updatePaymentDetails
ten komunikat o błędzie za pomocą callback.updateWith
.
'Shipping option identifier required.'
changeShippingAddress
Powiadamia sprzedawcę o zmianach w adresie dostawy podanym przez użytkownika. Chrome sprawdzi niepusty pakiet shippingAddress
z prawidłową wartością countryCode
i w razie niepowodzenia weryfikacji wyśle za pomocą callback.updateWith
komunikat updatePaymentDetails
z poniższym komunikatem o błędzie.
'Payment app returned invalid shipping address in response.'
Komunikat o błędzie dotyczącym nieprawidłowego stanu
Jeśli po otrzymaniu któregokolwiek z żądań zmiany Chrome napotka nieprawidłowy stan, wywoła metodę callback.updateWith
z usuniętym pakietem updatePaymentDetails
. Pakiet będzie zawierać tylko klucz error
z "Invalid state"
.
Przykłady nieprawidłowego stanu:
- Gdy Chrome nadal czeka na odpowiedź sprzedawcy na poprzednią zmianę (np. trwającą zmianę).
- Identyfikator opcji dostawy dostarczony przez aplikację płatności nie należy do żadnej z opcji dostawy określonych przez sprzedawcę.
Otrzymuj od sprzedawcy zaktualizowane dane do płatności
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
jest odpowiednikiem pakietu ze słownika PaymentRequestDetailsUpdate
WebIDL (po usunięciu pola modifiers
) i zawiera te opcjonalne klucze:
total
– pakiet zawierający kluczecurrency
ivalue
; oba klucze mają wartości w postaci ciągówshippingOptions
– tablica opcji dostawy z możliwością dostawy.error
– ciąg znaków zawierający ogólny komunikat o błędzie (np.changeShippingOption
nie podaje prawidłowego identyfikatora opcji dostawy).stringifiedPaymentMethodErrors
– ciąg znaków JSON zawierający błędy weryfikacji formy płatności.addressErrors
– pakiet z opcjonalnymi kluczami identycznymi z adresem dostawy i wartościami ciągów znaków. Każdy klucz reprezentuje błąd weryfikacji związany z odpowiadającą mu częścią adresu dostawy.
Brak klucza oznacza, że jego wartość się nie zmieniła.