Jak zaktualizować aplikację do płatności na Androida, aby udostępniać adres dostawy i dane kontaktowe płatnika za pomocą interfejsów Web Payments API.
Data publikacji: 17 lipca 2020 r., ostatnia aktualizacja: 27 maja 2025 r.
Wpisywanie adresu dostawy i danych kontaktowych w formularzu internetowym może być dla klientów uciążliwe. Może to powodować błędy i obniżać współczynnik konwersji.
Dlatego Payment Request API obsługuje funkcję żądania adresu dostawy i informacji kontaktowych. Daje to wiele korzyści:
- Użytkownicy mogą wybrać odpowiedni adres za pomocą kilku kliknięć.
- Adres jest zawsze zwracany w standardowym formacie.
- Podanie nieprawidłowego adresu jest mniej prawdopodobne.
Aby zapewnić spójny proces płatności, przeglądarki mogą odroczyć zbieranie adresu dostawy i danych kontaktowych do momentu, gdy użytkownik skorzysta z aplikacji do płatności. Ta funkcja jest nazywana delegowaniem.
W miarę możliwości Chrome przekazuje zbieranie adresu dostawy i danych kontaktowych klienta do wywołanej aplikacji płatniczej na Androida. Przekazanie zmniejsza trudności podczas płatności.
Strona sprzedawcy może dynamicznie aktualizować opcje dostawy i cenę całkowitą w zależności od wybranego przez klienta adresu dostawy i opcji dostawy.
Aby dodać obsługę delegowania do istniejącej aplikacji płatniczej na Androida, wykonaj te czynności:
- Deklarowanie obsługiwanych delegacji
- Analizowanie dodatkowych informacji o intencji
PAY
w celu uzyskania wymaganych opcji płatności. - Podaj wymagane informacje w odpowiedzi na płatność.
- Opcjonalnie: obsługa dynamicznego procesu:
Deklarowanie obsługiwanych przekazań dostępu
Przeglądarka musi znać listę dodatkowych informacji, które może podać Twoja aplikacja do płatności, aby mogła przekazać jej zbieranie tych informacji. Zadeklaruj obsługiwane przekazywanie jako <meta-data>
w pliku AndroidManifest.xml aplikacji.
<activity
android:name=".PaymentActivity"
…
<meta-data
android:name="org.chromium.payment_supported_delegations"
android:resource="@array/chromium_payment_supported_delegations" />
</activity>
android:resource
musi wskazywać na <string-array>
zawierający wszystkie te wartości lub ich podzbiór:
payerName
payerEmail
payerPhone
shippingAddress
Poniższy przykład może podać tylko adres dostawy i adres e-mail płatnika.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="chromium_payment_supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
Analizowanie dodatkowych informacji o intencjach PAY
w przypadku wymaganych opcji płatności
Sprzedawca może określić dodatkowe wymagane informacje za pomocą słownika paymentOptions
. Chrome wyświetli listę wymaganych opcji, które aplikacja może udostępnić, przekazując paymentOptions
dodatki do intencji do aktywności PAY
.
paymentOptions
paymentOptions
to podzbiór opcji płatności określonych przez sprzedawcę, w przypadku których Twoja aplikacja zadeklarowała obsługę delegowania.
Kotlin
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")
Java
Bundle paymentOptions = extras.getBundle("paymentOptions");
if (paymentOptions != null) {
Boolean requestPayerName = paymentOptions.getBoolean("requestPayerName");
Boolean requestPayerPhone = paymentOptions.getBoolean("requestPayerPhone");
Boolean requestPayerEmail = paymentOptions.getBoolean("requestPayerEmail");
Boolean requestShipping = paymentOptions.getBoolean("requestShipping");
String shippingType = 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 telefon płatnika jest wymagany.requestPayerEmail
– wartość logiczna wskazująca, czy adres e-mail płatnika jest wymagany.requestShipping
– wartość logiczna wskazująca, czy wymagane są informacje o dostawie.shippingType
– ciąg tekstowy określający typ dostawy. Typ dostawy może mieć wartość"shipping"
,"delivery"
lub"pickup"
. Aplikacja może użyć tej wskazówki w interfejsie, gdy będzie prosić użytkownika o podanie adresu lub wybór opcji dostawy.
shippingOptions
shippingOptions
to tablica z możliwością przekazywania w pakietach, która zawiera opcje dostawy określone przez sprzedawcę. Ten parametr będzie występować tylko wtedy, gdy paymentOptions.requestShipping ==
true
.
Kotlin
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
Java
Parcelable[] shippingOptions = extras.getParcelableArray("shippingOptions");
for (Parcelable it : shippingOptions) {
if (it != null && it instanceof Bundle) {
Bundle shippingOption = (Bundle) it;
}
}
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 tekstowymi.currency
pokazuje walutę kosztu dostawy jako prawidłowy 3-literowy kod alfabetyczny ISO4217.value
pokazuje wartość kosztu dostawy jako prawidłową wartość pieniężną w formacie dziesiętnym.
selected
– czy opcja dostawy powinna być wybrana, gdy aplikacja płatnicza wyświetla opcje dostawy.
Wszystkie klucze inne niż selected
mają wartości w formie ciągu znaków. selected
ma wartość logiczną.
Kotlin
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)
Java
String id = bundle.getString("id");
String label = bundle.getString("label");
Bundle amount = bundle.getBundle("amount");
Boolean selected = bundle.getBoolean("selected", false);
Podawanie wymaganych informacji w odpowiedzi na płatność
Aplikacja powinna zawierać wymagane dodatkowe informacje w odpowiedzi na działanie PAY
.
Aby to zrobić, musisz podać te parametry jako dodatkowe informacje o intencji:
payerName
– imię i nazwisko płatnika. Jeśli wartość parametrupaymentOptions.requestPayerName
to „true”, ten ciąg znaków nie może być pusty.payerPhone
– numer telefonu płatnika. Jeśli wartość parametrupaymentOptions.requestPayerPhone
to „true”, ten ciąg znaków nie może być pusty.payerEmail
– adres e-mail płatnika. Jeśli wartość parametrupaymentOptions.requestPayerEmail
to „true”, ten ciąg znaków nie może być pusty.shippingAddress
– adres dostawy podany przez użytkownika. Jeśli wartość parametrupaymentOptions.requestShipping
to „true”, ten pakiet nie może być pusty. Pakiet powinien zawierać te klucze, które reprezentują różne części fizycznego adresu.countryCode
postalCode
sortingCode
region
city
dependentLocality
addressLine
organization
recipient
phone
Wszystkie klucze inne niżaddressLine
mają wartości w formie ciągu znaków.addressLine
to tablica ciągów znaków.
shippingOptionId
– identyfikator wybranej przez użytkownika opcji dostawy. Jeśli parametrpaymentOptions.requestShipping
ma wartość „true”, ten ciąg znaków nie może być pusty.
Sprawdzanie odpowiedzi dotyczącej płatności
Jeśli wynik działania odpowiedzi na płatność otrzymanej z wywołanej aplikacji do płatności jest ustawiony na RESULT_OK
, Chrome sprawdzi, czy w dodatkowych informacjach znajdują się wymagane dane. Jeśli weryfikacja się nie powiedzie, Chrome zwróci odrzuconą obietnicę z request.show()
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".'
Poniższy przykładowy kod to przykład prawidłowej odpowiedzi:
Kotlin
fun Intent.populateRequestedPaymentOptions() {
if (requestPayerName) {
putExtra("payerName", "John Smith")
}
if (requestPayerPhone) {
putExtra("payerPhone", "5555555555")
}
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", "5555555555")
putExtra("shippingAddress", address)
putExtra("shippingOptionId", "standard")
}
}
Java
private Intent populateRequestedPaymentOptions() {
Intent result = new Intent();
if (requestPayerName) {
result.putExtra("payerName", "John Smith");
}
if (requestPayerPhone) {
presult.utExtra("payerPhone", "5555555555");
}
if (requestPayerEmail) {
result.putExtra("payerEmail", "john.smith@gmail.com");
}
if (requestShipping) {
Bundle address = new Bundle();
address.putExtra("countryCode", "CA");
address.putExtra("postalCode", "M5H2G4");
address.putExtra("region", "Ontario");
address.putExtra("city", "Toronto");
String[] addressLines = new String[] {"111 Richmond st. West"};
address.putExtra("addressLines", addressLines);
address.putExtra("recipient", "John Smith");
address.putExtra("phone", "5555555555");
result.putExtra("shippingAddress", address);
result.putExtra("shippingOptionId", "standard");
}
return result;
}
Opcjonalnie: obsługa dynamicznego przepływu
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ę, gdy użytkownik wybierze międzynarodowy adres dostawy. Gdy aplikacja podaje wybrany przez użytkownika adres lub opcję dostawy, powinna powiadamiać sprzedawcę o wszelkich zmianach adresu lub opcji dostawy oraz wyświetlać użytkownikowi zaktualizowane dane do płatności (przesłane przez sprzedawcę).
Aby powiadomić sprzedawcę o nowych zmianach, zaimplementuj interfejs IPaymentDetailsUpdateServiceCallback
i zadeklaruj go w AndroidManifest.xml
za pomocą filtra intencji UPDATE_PAYMENT_DETAILS
.
Natychmiast po wywołaniu intencji PAY
Chrome połączy się z usługą UPDATE_PAYMENT_DETAILS
(jeśli istnieje) w tym samym pakiecie co intencja PAY
i wywoła funkcję setPaymentDetailsUpdateService(service)
, aby przekazać aplikacji płatniczej punkt końcowy IPaymentDetailsUpdateService
, który będzie powiadamiać o zmianach w formie płatności, opcji dostawy lub adresie dostawy użytkownika.
Używaj packageManager.getPackagesForUid(Binder.getCallingUid())
podczas odbierania komunikacji międzyprocesowej (IPC), aby sprawdzić, czy aplikacja, która wywołała intencję PAY
, ma taką samą nazwę pakietu jak aplikacja, która wywołała metody IPaymentDetailsUpdateServiceCallback
.
AIDL
Utwórz 2 pliki AIDL o tej treści:
org/chromium/components/payments/IPaymentDetailsUpdateServiceCallback.aidl
package org.chromium.components.payments;
import android.os.Bundle;
import org.chromium.components.payments.IPaymentDetailsUpdateService;
interface IPaymentDetailsUpdateServiceCallback {
oneway void updateWith(in Bundle updatedPaymentDetails);
oneway void paymentDetailsNotUpdated();
oneway void setPaymentDetailsUpdateService(IPaymentDetailsUpdateService service);
}
org/chromium/components/payments/IPaymentDetailsUpdateService.aidl
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);
}
Usługa
Zaimplementuj usługę IPaymentDetailsUpdateServiceCallback
.
Kotlin
class SampleUpdatePaymentDetailsCallbackService : Service() {
private val binder = object : IPaymentDetailsUpdateServiceCallback.Stub() {
override fun updateWith(updatedPaymentDetails: Bundle) {}
override fun paymentDetailsNotUpdated() {}
override fun setPaymentDetailsUpdateService(service: IPaymentDetailsUpdateService) {}
}
override fun onBind(intent: Intent?): IBinder? {
return binder
}
}
Java
import org.chromium.components.paymsnts.IPaymentDetailsUpdateServiceCallback;
public class SampleUpdatePaymentDetailsCallbackService extends Service {
private final IPaymentDetailsUpdateServiceCallback.Stub mBinder =
new IPaymentDetailsUpdateServiceCallback.Stub() {
@Override
public void updateWith(Bundle updatedPaymentDetails) {}
@Override
public void paymentDetailsNotUpdated() {}
@Override
public void setPaymentDetailsUpdateService(IPaymentDetailsUpdateService service) {}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
AndroidManifest.xml
Udostępnij usługę dla IPaymentDetailsUpdateServiceCallback
w AndroidManifest.xml
.
<service
android:name=".SampleUpdatePaymentDetailsCallbackService"
android:exported="true">
<intent-filter>
<action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
</intent-filter>
</service>
powiadamiać sprzedawcę o zmianach w wybranej przez użytkownika formie płatności, adresie dostawy lub opcji dostawy;
Kotlin
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
}
Java
if (service == null) {
return;
}
try {
if (isOptionChange) {
service.changeShippingOption(selectedOptionId, callback);
} else (isAddressChange) {
service.changeShippingAddress(selectedAddress, callback);
} else {
service.changePaymentMethod(methodData, callback);
}
} catch (RemoteException e) {
// Handle the remote exception
}
changePaymentMethod
Powiadamia sprzedawcę o zmianach w formie płatności wybranej przez użytkownika. Pakiet paymentHandlerMethodData
zawiera klucze methodName
i opcjonalne klucze details
, które mają wartości będące ciągami tekstowymi. Chrome sprawdzi, czy pakiet nie jest pusty i czy zawiera niepusty obiekt methodName
. Jeśli weryfikacja się nie powiedzie, wyśle obiekt updatePaymentDetails
z jednym z tych komunikatów o błędzie, używając 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ę. Chrome sprawdzi, czy element shippingOptionId
nie jest pusty, a jeśli weryfikacja się nie powiedzie, wyśle element updatePaymentDetails
z tym komunikatem o błędzie za pomocą elementu callback.updateWith
.
'Shipping option identifier required.'
changeShippingAddress
Powiadamia sprzedawcę o zmianach w adresie dostawy podanym przez użytkownika. Chrome sprawdzi, czy pakiet shippingAddress
nie jest pusty i czy zawiera prawidłowy plik countryCode
. Jeśli weryfikacja się nie powiedzie, wyśle plik updatePaymentDetails
z tym komunikatem o błędzie za pomocą pliku callback.updateWith
.
'Payment app returned invalid shipping address in response.'
Komunikat o błędzie nieprawidłowego stanu
Jeśli Chrome napotka nieprawidłowy stan podczas odbierania dowolnego z żądań zmiany, wywoła funkcję callback.updateWith
z pakietem updatePaymentDetails
po redakcji. Pakiet będzie zawierać tylko klucz error
z wartością "Invalid state"
.
Przykłady nieprawidłowego stanu:
- Gdy Chrome wciąż oczekuje na odpowiedź sprzedawcy na poprzednią zmianę (np. trwające zdarzenie zmiany).
- Identyfikator opcji dostawy podany przez aplikację do płatności nie należy do żadnej z opcji dostawy określonych przez sprzedawcę.
Otrzymywanie od sprzedawcy zaktualizowanych danych do płatności
Kotlin
override fun updateWith(updatedPaymentDetails: Bundle) {}
override fun paymentDetailsNotUpdated() {}
Java
@Override
public void updateWith(Bundle updatedPaymentDetails) {}
@Override
public void paymentDetailsNotUpdated() {}
updatedPaymentDetails
to odpowiednik słownika PaymentRequestDetailsUpdate
WebIDL. Zawiera te opcjonalne klucze:
total
– pakiet zawierający kluczecurrency
ivalue
, które mają wartości tekstowe.shippingOptions
– tablica obiektów do przekazywania w pakietach zawierająca opcje dostawy.error
– ciąg znaków 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 weryfikacji formy płatności.addressErrors
– pakiet z opcjonalnymi kluczami identycznymi z kluczami shipping address i wartościami typu string. Każdy klucz reprezentuje błąd weryfikacji związany z odpowiednią częścią adresu dostawy.modifiers
– tablica pakietów, z których każdy zawiera polatotal
imethodData
, które również są pakietami.
Brak klucza oznacza, że jego wartość nie uległa zmianie.