Podawanie informacji o dostawie i danych kontaktowych z aplikacji do płatności na Androida

Jak zaktualizować aplikację płatniczą na Androida, aby udostępniać adres dostawy i dane kontaktowe płatnika za pomocą interfejsów Web Payments API.

Sahel Sharify
Sahel Sharify

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 interfejs Payment Request API obsługuje funkcję, która umożliwia wysyłanie próśb o adres dostawy i dane kontaktowe. 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ć ujednolicone środowisko płatności, przeglądarki mogą odroczyć zbieranie adresu dostawy i danych kontaktowych do aplikacji płatniczej. Ta funkcja jest nazywana delegowaniem.

W miarę możliwości Chrome przekazuje zbieranie adresu dostawy i informacji 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.

Zmiana opcji dostawy i adresu dostawy w trakcie realizacji. Zobacz, jak dynamicznie wpływa to na opcje dostawy i łączną cenę.

Aby dodać obsługę delegowania do istniejącej aplikacji płatniczej na Androida, wykonaj te czynności:

  1. Deklarowanie obsługiwanych delegacji
  2. Przetwarzanie dodatkowych informacji o intencji PAY w celu uzyskania wymaganych opcji płatności
  3. Podaj wymagane informacje w odpowiedzi na prośbę o płatność.
  4. Opcjonalnie: obsługa dynamicznego przepływu:
    1. Powiadom sprzedawcę o zmianach w wybranej przez użytkownika formie płatności, adresie dostawy lub opcji dostawy.
    2. Otrzymywanie od sprzedawcy zaktualizowanych szczegółów płatności (np. skorygowanej łącznej kwoty na podstawie kosztu wybranej opcji dostawy).

Deklarowanie obsługiwanych delegacji

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 lub część tych wartości:

  • 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 intencji PAY pod kątem wymaganych opcji płatności

Sprzedawca może podać dodatkowe wymagane informacje za pomocą słownika paymentOptions. Chrome udostępni listę wymaganych opcji, które aplikacja może przekazać, przesyłają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 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 znaków pokazują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 istniał 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 klucze currency i value z wartościami tekstowymi.
  • selected – określa, 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 dotyczącej płatności

Aplikacja powinna zawierać wymagane dodatkowe informacje w odpowiedzi na aktywność PAY.

W tym celu musisz określić te parametry jako dodatki do intencji:

  • payerName – imię i nazwisko płatnika. Jeśli parametr paymentOptions.requestPayerName ma wartość „true”, ten ciąg znaków nie może być pusty.
  • payerPhone – numer telefonu płatnika. Jeśli parametr paymentOptions.requestPayerPhone ma wartość „true”, ten ciąg znaków nie może być pusty.
  • payerEmail – adres e-mail płatnika. Jeśli wartość parametru paymentOptions.requestPayerEmail to „true”, ten ciąg znaków nie może być pusty.
  • shippingAddress – adres dostawy podany przez użytkownika. Jeśli parametr paymentOptions.requestShipping ma wartość „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
    • phoneWszystkie 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 parametr paymentOptions.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 dodatkowe informacje. Jeśli weryfikacja się nie powiedzie, Chrome zwróci odrzuconą obietnicę z funkcji 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 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ę, gdy użytkownik wybierze adres dostawy międzynarodowej. Gdy aplikacja udostępnia wybrany przez użytkownika adres dostawy lub opcję, powinna być w stanie powiadomić sprzedawcę o wszelkich zmianach adresu dostawy lub opcji oraz wyświetlić użytkownikowi zaktualizowane dane płatności (dostarczone przez sprzedawcę).

Aby powiadomić sprzedawcę o nowych zmianach, zaimplementuj interfejs IPaymentDetailsUpdateServiceCallback i zadeklaruj go w pliku 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 nie jest pusty obiekt methodName. Jeśli weryfikacja się nie powiedzie, wyśle obiekt updatePaymentDetails z jednym z tych komunikatów o błędzie, używając obiektu 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 adresu dostawy podanego 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 żądanie updatePaymentDetails z tym komunikatem o błędzie za pomocą żądania callback.updateWith.

'Payment app returned invalid shipping address in response.'

Komunikat o błędzie „Nieprawidłowy stan”

Jeśli Chrome napotka nieprawidłowy stan po otrzymaniu dowolnego żądania zmiany, wywoła funkcję callback.updateWith z ocenzurowanym pakietem updatePaymentDetails. Pakiet będzie zawierać tylko klucz error z wartością "Invalid state". Przykłady nieprawidłowego stanu:

  • Gdy Chrome wciąż czeka 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 pakiet odpowiadający słownikowi PaymentRequestDetailsUpdate WebIDL. Zawiera te opcjonalne klucze:

  • total – pakiet zawierający klucze currency i value, oba klucze mają wartości tekstowe.
  • shippingOptions – tablica obiektów Parcelable z opcjami dostawy.
  • error – ciąg zawierający ogólny komunikat o błędzie (np.gdy changeShippingOption 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 pola total i methodData, które również są pakietami.

Brak klucza oznacza, że jego wartość nie uległa zmianie.