Fornire i dati di spedizione e di contatto da un'app di pagamento per Android

Come aggiornare l'app di pagamento per Android per fornire l'indirizzo di spedizione e i dati di contatto del pagatore con le API Web Payments.

Sahel Sharify
Sahel Sharify

Pubblicato: 17 luglio 2020, ultimo aggiornamento: 27 maggio 2025

L'inserimento dell'indirizzo di spedizione e dei dati di contatto tramite un modulo web può essere un'esperienza complicata per i clienti. Può causare errori e ridurre il tasso di conversione.

Per questo motivo, l'API Payment Request supporta una funzionalità per richiedere l'indirizzo di spedizione e i dati di contatto. Questo offre diversi vantaggi:

  • Gli utenti possono scegliere l'indirizzo giusto con pochi tocchi.
  • L'indirizzo viene sempre restituito nel formato standardizzato.
  • È meno probabile che venga inviato un indirizzo errato.

I browser possono posticipare la raccolta dell'indirizzo di spedizione e dei dati di contatto a un'app di pagamento per fornire un'esperienza di pagamento unificata. Questa funzionalità è chiamata delega.

Quando possibile, Chrome delega la raccolta dell'indirizzo di spedizione e dei dati di contatto di un cliente all'app di pagamento Android richiamata. La delega riduce l'attrito durante il pagamento.

Il sito web del commerciante può aggiornare dinamicamente le opzioni di spedizione e il prezzo totale a seconda della scelta del cliente dell'indirizzo di spedizione e dell'opzione di spedizione.

Opzione di spedizione e modifica dell'indirizzo di spedizione in corso. Scopri come influisce in modo dinamico sulle opzioni di spedizione e sul prezzo totale.

Per aggiungere il supporto della delega a un'app di pagamento per Android già esistente, segui questi passaggi:

  1. Dichiara le deleghe supportate.
  2. Analizza gli extra dell'intent PAY per le opzioni di pagamento richieste.
  3. Fornisci le informazioni richieste nella risposta al pagamento.
  4. (Facoltativo) Supporta il flusso dinamico:
    1. Notificare al commerciante le modifiche al metodo di pagamento selezionato dall'utente, all'indirizzo di spedizione o all'opzione di spedizione.
    2. Ricevere i dettagli di pagamento aggiornati dal commerciante (ad esempio, l'importo totale aggiustato in base al costo dell'opzione di spedizione selezionata).

Dichiarare le deleghe supportate

Il browser deve conoscere l'elenco delle informazioni aggiuntive che la tua app di pagamento può fornire, in modo da poter delegare la raccolta di queste informazioni alla tua app. Dichiara le deleghe supportate come <meta-data> nel file AndroidManifest.xml della tua app.

<activity
  android:name=".PaymentActivity"
    <meta-data
    android:name="org.chromium.payment_supported_delegations"
    android:resource="@array/chromium_payment_supported_delegations" />
</activity>

android:resource deve puntare a un <string-array> contenente tutti o un sottoinsieme dei seguenti valori:

  • payerName
  • payerEmail
  • payerPhone
  • shippingAddress

Il seguente esempio può fornire solo un indirizzo di spedizione e l'indirizzo email del pagatore.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string-array name="chromium_payment_supported_delegations">
    <item>payerEmail</item>
    <item>shippingAddress</item>
  </string-array>
</resources>

Analizza gli extra dell'intent PAY per le opzioni di pagamento richieste

Il commerciante può specificare ulteriori informazioni richieste utilizzando il dizionario paymentOptions. Chrome fornirà l'elenco delle opzioni richieste che la tua app può fornire passando gli paymentOptions extra dell'intent all'attività PAY.

paymentOptions

paymentOptions è il sottoinsieme di opzioni di pagamento specificate dal commerciante per le quali la tua app ha dichiarato il supporto della delega.

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");
}

Può includere i seguenti parametri:

  • requestPayerName: valore booleano che indica se il nome del pagatore è obbligatorio.
  • requestPayerPhone: il valore booleano che indica se è richiesto o meno il telefono del pagatore.
  • requestPayerEmail: il valore booleano che indica se l'email del pagatore è obbligatoria.
  • requestShipping: il valore booleano che indica se le informazioni di spedizione sono obbligatorie.
  • shippingType: la stringa che mostra il tipo di spedizione. Il tipo di spedizione può essere "shipping", "delivery" o "pickup". La tua app può utilizzare questo suggerimento nella sua UI quando chiede l'indirizzo dell'utente o la scelta delle opzioni di spedizione.

shippingOptions

shippingOptions è l'array di opzioni di spedizione specificate dal commerciante. Questo parametro esisterà solo quando 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;
  }
}

Ogni opzione di spedizione è un Bundle con le seguenti chiavi.

  • id: l'identificatore dell'opzione di spedizione.
  • label: l'etichetta dell'opzione di spedizione mostrata all'utente.
  • amount - Il bundle dei costi di spedizione contenente le chiavi currency e value con valori stringa.
    • currency mostra la valuta del costo di spedizione, come codice alfabetico di tre lettere ISO4217 ben formato
    • value mostra il valore del costo di spedizione come valore monetario decimale valido
  • selected - Indica se l'opzione di spedizione deve essere selezionata quando l'app di pagamento mostra le opzioni di spedizione.

Tutte le chiavi, ad eccezione di selected, hanno valori di stringa. selected ha un valore booleano.

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);

Fornire le informazioni richieste in una risposta al pagamento

La tua app deve includere le informazioni aggiuntive richieste nella risposta all'attività PAY.

A questo scopo, i seguenti parametri devono essere specificati come extra dell'intent:

  • payerName: il nome completo del pagatore. Deve essere una stringa non vuota quando paymentOptions.requestPayerName è true.
  • payerPhone: il numero di telefono del pagatore. Deve essere una stringa non vuota quando paymentOptions.requestPayerPhone è true.
  • payerEmail: l'indirizzo email del pagatore. Deve essere una stringa non vuota quando paymentOptions.requestPayerEmail è true.
  • shippingAddress: l'indirizzo di spedizione fornito dall'utente. Questo deve essere un bundle non vuoto quando paymentOptions.requestShipping è true. Il bundle deve avere le seguenti chiavi che rappresentano le diverse parti di un indirizzo fisico.
    • countryCode
    • postalCode
    • sortingCode
    • region
    • city
    • dependentLocality
    • addressLine
    • organization
    • recipient
    • phone Tutte le chiavi, ad eccezione di addressLine, hanno valori di stringa. addressLine è un array di stringhe.
  • shippingOptionId: l'identificatore dell'opzione di spedizione selezionata dall'utente. Questo deve essere una stringa non vuota quando paymentOptions.requestShipping è true.

Convalida della risposta di pagamento

Se il risultato dell'attività di una risposta di pagamento ricevuta dall'app di pagamento richiamata è impostato su RESULT_OK, Chrome verificherà la presenza di informazioni aggiuntive richieste nei suoi extra. Se la convalida non va a buon fine, Chrome restituirà una promessa rifiutata da request.show() con uno dei seguenti messaggi di errore rivolti agli sviluppatori:

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

Il seguente esempio di codice è un esempio di risposta valida:

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;
}

(Facoltativo) Supportare il flusso dinamico

A volte il costo totale di una transazione aumenta, ad esempio quando l'utente sceglie l'opzione di spedizione rapida o quando l'elenco delle opzioni di spedizione disponibili o i relativi prezzi cambiano quando l'utente sceglie un indirizzo di spedizione internazionale. Quando la tua app fornisce l'indirizzo o l'opzione di spedizione selezionati dall'utente, deve essere in grado di comunicare al commerciante eventuali modifiche all'indirizzo o all'opzione di spedizione e mostrare all'utente i dettagli di pagamento aggiornati (forniti dal commerciante).

Per comunicare al commerciante le nuove modifiche, implementa l'interfaccia IPaymentDetailsUpdateServiceCallback e dichiarala nel tuo AndroidManifest.xml con il filtro per intent UPDATE_PAYMENT_DETAILS.

Subito dopo aver richiamato l'intent PAY, Chrome si connette al servizio UPDATE_PAYMENT_DETAILS (se esistente) nello stesso pacchetto dell'intent PAY e chiama setPaymentDetailsUpdateService(service) per fornire alla tua app di pagamento l'endpoint IPaymentDetailsUpdateService per ricevere notifiche sulle modifiche al metodo di pagamento, all'opzione di spedizione o all'indirizzo di spedizione dell'utente.

Utilizza packageManager.getPackagesForUid(Binder.getCallingUid()) quando ricevi la comunicazione interprocesso (IPC) per verificare che l'app che ha richiamato l'intent PAY abbia lo stesso nome di pacchetto dell'app che ha richiamato i metodi IPaymentDetailsUpdateServiceCallback.

AIDL

Crea due file AIDL con i seguenti contenuti:

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);
}

Servizio

Implementa il servizio 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

Esporre il servizio per IPaymentDetailsUpdateServiceCallback nel tuo AndroidManifest.xml.

<service
    android:name=".SampleUpdatePaymentDetailsCallbackService"
    android:exported="true">
    <intent-filter>
        <action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
    </intent-filter>
</service>

Comunicare al commerciante le modifiche al metodo di pagamento, all'indirizzo di spedizione o all'opzione di spedizione selezionati dall'utente

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

Comunica al commerciante le modifiche al metodo di pagamento selezionato dall'utente. Il bundle paymentHandlerMethodData contiene le chiavi methodName e details facoltative, entrambe con valori stringa. Chrome verificherà la presenza di un bundle non vuoto con un methodName non vuoto e invierà un updatePaymentDetails con uno dei seguenti messaggi di errore utilizzando callback.updateWith se la convalida non va a buon fine.

'Method data required.'
'Method name required.'

changeShippingOption

Notifica al commerciante le modifiche all'opzione di spedizione selezionata dall'utente. shippingOptionId deve essere l'identificatore di una delle opzioni di spedizione specificate dal commerciante. Chrome controllerà la presenza di un shippingOptionId non vuoto e invierà un updatePaymentDetails con il seguente messaggio di errore utilizzando callback.updateWith se la convalida non riesce.

'Shipping option identifier required.'

changeShippingAddress

Notifica al commerciante le modifiche all'indirizzo di spedizione fornito dall'utente. Chrome controlla la presenza di un bundle shippingAddress non vuoto con un countryCode valido e invia un updatePaymentDetails con il seguente messaggio di errore utilizzando callback.updateWith se la convalida non riesce.

'Payment app returned invalid shipping address in response.'

Messaggio di errore relativo allo stato non valido

Se Chrome rileva uno stato non valido al ricevimento di una delle richieste di modifica, chiama callback.updateWith con un bundle updatePaymentDetails modificato. Il bundle conterrà solo la chiave error con "Invalid state". Esempi di stato non valido:

  • Quando Chrome è ancora in attesa della risposta del commerciante a una modifica precedente (ad esempio un evento di modifica in corso).
  • L'identificatore dell'opzione di spedizione fornito dall'app di pagamento non appartiene a nessuna delle opzioni di spedizione specificate dal commerciante.

Ricevere i dettagli di pagamento aggiornati dal commerciante

Kotlin

override fun updateWith(updatedPaymentDetails: Bundle) {}

override fun paymentDetailsNotUpdated() {}

Java

@Override
public void updateWith(Bundle updatedPaymentDetails) {}

@Override
public void paymentDetailsNotUpdated() {}

updatedPaymentDetails è il bundle equivalente al dizionario PaymentRequestDetailsUpdate WebIDL e contiene le seguenti chiavi facoltative:

  • total: un bundle contenente le chiavi currency e value, entrambe con valori stringa
  • shippingOptions - The parcelable array of shipping options
  • error: una stringa contenente un messaggio di errore generico (ad es. quando changeShippingOption non fornisce un identificatore di opzione di spedizione valido)
  • stringifiedPaymentMethodErrors: una stringa JSON che rappresenta gli errori di convalida per il metodo di pagamento
  • addressErrors: un bundle con chiavi facoltative identiche a shipping address e valori stringa. Ogni chiave rappresenta un errore di convalida relativo alla parte corrispondente dell'indirizzo di spedizione.
  • modifiers: un array di pacchi di bundle, ognuno con un campo total e un campo methodData, che sono anche bundle.

Una chiave assente indica che il suo valore non è cambiato.