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

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.

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 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.

Zmiana opcji dostawy i adresu dostawy w trakcie działania. Zobacz, jak dynamicznie wpływa to na opcje dostawy i cenę całkowitą.

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

  1. Deklarowanie obsługiwanych delegacji
  2. Analizowanie dodatkowych informacji o intencji PAY w celu uzyskania wymaganych opcji płatności.
  3. Podaj wymagane informacje w odpowiedzi na płatność.
  4. Opcjonalnie: obsługa dynamicznego procesu:
    1. Powiadamianie sprzedawcy 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 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 klucze currencyvalue z wartościami tekstowymi.
  • 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ść parametru paymentOptions.requestPayerName to „true”, ten ciąg znaków nie może być pusty.
  • payerPhone – numer telefonu płatnika. Jeśli wartość parametru paymentOptions.requestPayerPhone to „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 wartość parametru paymentOptions.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 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 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 IPaymentDetailsUpdateServiceCallbackAndroidManifest.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 klucze currencyvalue, 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. 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 totalmethodData, które również są pakietami.

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