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

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

Sahel Sharify
Sahel Sharify

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

Ecco perché l'API Payment Request supporta una funzionalità per richiedere la spedizione indirizzo e dati di contatto. Ciò offre diversi vantaggi:

  • Gli utenti possono scegliere l'indirizzo giusto con pochi tocchi.
  • L'indirizzo viene sempre restituito nella standard.
  • È meno probabile che invii un indirizzo errato.

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

Quando è possibile, Chrome delega la raccolta dei dati di spedizione di un cliente indirizzo e dati di contatto all'app per i pagamenti Android richiamata. La delega semplifica la procedura di pagamento.

Il sito web del commerciante può aggiornare in modo dinamico le opzioni di spedizione e il prezzo totale a seconda dell'indirizzo di spedizione e della spedizione scelti dal cliente .

L'opzione di spedizione e l'indirizzo di spedizione cambiano in azione. Scopri come influisce dinamicamente sulle opzioni di spedizione e sul prezzo totale.
di Gemini Advanced.
.

Per aggiungere il supporto della delega a un'app per pagamenti Android già esistente: implementa i seguenti passaggi:

  1. Dichiara le deleghe supportate.
  2. Analizza gli extra di PAY per l'intent per il pagamento richiesto opzioni.
  3. Fornire i dati richiesti per il pagamento risposta.
  4. [Facoltativo] Supporto del flusso dinamico:
      .
    1. Comunicare al commerciante le modifiche al metodo di pagamento selezionato dall'utente; l'indirizzo di spedizione o l'indirizzo di spedizione .
    2. Ricevere dal commerciante i dati di pagamento aggiornati (ad es. importo totale modificato in base all'opzione di spedizione selezionata di base).

Dichiara le deleghe supportate

Il browser deve conoscere l'elenco di informazioni aggiuntive che il tuo metodo di pagamento che l'app può fornire per delegare la raccolta di queste informazioni al tuo dell'app. Dichiara le deleghe supportate come <meta-data> nel AndroidManifest.xml.

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

<resource> deve essere un elenco di stringhe scelto dai seguenti valori validi:

[ "payerName", "payerEmail", "payerPhone", "shippingAddress" ]

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

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

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

Il commerciante può specificare le informazioni aggiuntive richieste utilizzando il paymentOptions dizionario. Chrome fornirà l'elenco delle opzioni richieste che la tua app può fornire passando i seguenti parametri all'attività PAY come Intent contenuti extra.

paymentOptions

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

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

Può includere i seguenti parametri:

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

shippingOptions

shippingOptions è la serie di informazioni parcellabili della spedizione specificata dal commerciante le opzioni di CPU e memoria disponibili. Questo parametro esisterà solo quando paymentOptions.requestShipping == true.

val shippingOptions: List<ShippingOption>? =
    extras.getParcelableArray("shippingOptions")?.mapNotNull {
        p -> from(p as Bundle)
    }

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 pacchetto per il costo di spedizione contenente currency e value chiavi con valori di stringa.
  • selected - Indica se selezionare o meno l'opzione di spedizione quando l'app di pagamento mostra le opzioni di spedizione.

Tutte le chiavi tranne selected hanno valori stringa. selected contiene un valore booleano valore.

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)

Fornire le informazioni richieste nella risposta al pagamento

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

A tale scopo, è necessario specificare i seguenti parametri come extra per intent:

  • payerName: nome completo del pagatore. Deve essere una stringa non vuota quando paymentOptions.requestPayerName è vero.
  • payerPhone: il numero di telefono di chi effettua il pagamento. Deve essere una stringa non vuota quando paymentOptions.requestPayerPhone è vero.
  • payerEmail: l'indirizzo email del pagatore. Deve essere una stringa non vuota quando paymentOptions.requestPayerEmail è vero.
  • shippingAddress: l'indirizzo di spedizione fornito dall'utente. Deve essere una bundle non vuoto quando paymentOptions.requestShipping è true. Il bundle dovrebbe avere le seguenti chiavi che rappresentano parti diverse in un .
    • city
    • countryCode
    • dependentLocality
    • organization
    • phone
    • postalCode
    • recipient
    • region
    • sortingCode
    • addressLine Tutte le chiavi tranne addressLine hanno valori 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 la risposta al pagamento

Se l'attività è il risultato di una risposta al pagamento ricevuta dal pagamento richiamato è impostata su RESULT_OK, Chrome verificherà la presenza di eventuali le informazioni nei suoi extra. Se la convalida non va a buon fine, Chrome restituisce un messaggio promessa da request.show() con uno dei seguenti errori rivolti agli sviluppatori messaggi:

'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:

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

(Facoltativo) Supporto del flusso dinamico

A volte il costo totale di una transazione aumenta, ad esempio quando l'utente sceglie l'opzione di spedizione espressa o quando l'elenco delle spedizioni disponibili o i loro prezzi cambiano quando l'utente sceglie una spedizione internazionale. . Quando la tua app fornisce l'indirizzo o l'opzione di spedizione selezionati dall'utente, deve poter informare il commerciante in merito a qualsiasi indirizzo o opzione di spedizione cambia e mostra all'utente i dati di pagamento aggiornati (forniti dal commerciante).

AIDL

Per informare il commerciante delle nuove modifiche, utilizza PaymentDetailsUpdateService dichiarato nel file AndroidManifest.xml di Chrome. Per utilizzare questo servizio, crea due File AIDL con i seguenti contenuti:

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

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

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

Il valore callingPackageName utilizzato per l'intent di avvio del servizio può avere uno dei seguenti valori: seguenti valori in base al browser che ha avviato il pagamento richiesta.

Canale di Chrome Nome pacchetto
Stabile "com.android.chrome"
Beta "com.chrome.beta"
Sviluppatore "com.chrome.dev"
Canary "com.chrome.canary"
Cromo "org.chromium.chrome"
Casella di ricerca rapida Google (un incorporatore Weblayer) "com.google.android.googlequicksearchbox"

changePaymentMethod

Informa il commerciante in merito alle modifiche apportate al metodo di pagamento selezionato dall'utente. La Il bundle paymentHandlerMethodData contiene methodName e details facoltativo e chiavi entrambe con valori stringa. Chrome cercherà un bundle non vuoto con un non vuoto methodName e invia un updatePaymentDetails con uno dei i seguenti messaggi di errore tramite callback.updateWith se la convalida non va a buon fine.

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

changeShippingOption

Informa il commerciante in merito alle modifiche apportate all'opzione di spedizione selezionata dall'utente. shippingOptionId deve essere l'identificatore di uno dei valori specificati dal commerciante le opzioni di spedizione. Chrome cercherà un shippingOptionId non vuoto e invierà un updatePaymentDetails con il seguente messaggio di errore tramite callback.updateWith se la convalida non va a buon fine.

'Shipping option identifier required.'

changeShippingAddress

Informa il commerciante in merito alle modifiche all'indirizzo di spedizione fornito dall'utente. Google Chrome verifica la presenza di un bundle shippingAddress non vuoto con un valore countryCode valido e invia un updatePaymentDetails con il seguente messaggio di errore tramite callback.updateWith se la convalida non va a buon fine.

'Payment app returned invalid shipping address in response.'

Messaggio di errore relativo allo stato non valido

Se Chrome riscontra uno stato non valido alla ricezione delle richieste di modifica chiamerà callback.updateWith con un updatePaymentDetails oscurato gruppo. Il bundle conterrà solo la chiave error con "Invalid state". Esempi di stato non valido:

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

Ricevere i dati di pagamento aggiornati dal commerciante

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 è l'equivalente del bundle PaymentRequestDetailsUpdate Dizionario WebIDL (dopo aver oscurato il modifiers) e contiene le seguenti chiavi facoltative:

  • total: un bundle contenente chiavi currency e value; entrambe le chiavi hanno valori stringa
  • shippingOptions: l'array assegnabile di spedizione opzioni
  • error: una stringa contenente un messaggio di errore generico (ad es. quando changeShippingOption non fornisce un identificatore dell'opzione di spedizione valido)
  • stringifiedPaymentMethodErrors: una stringa JSON che rappresenta la convalida errori relativi al metodo di pagamento
  • addressErrors: un set con chiavi facoltative identiche a shipping indirizzo e stringa e i relativi valori. Ogni chiave rappresenta un errore di convalida relativo al dell'indirizzo di spedizione.

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