Fournir des informations de livraison et de contact à partir d'une application de paiement Android

Découvrez comment mettre à jour votre application de paiement Android pour fournir l'adresse de livraison et les coordonnées du payeur avec les API Web Payments.

Sahel Sharify
Sahel Sharify

Publié le 17 juillet 2020, dernière mise à jour le 27 mai 2025

Saisir une adresse de livraison et des coordonnées dans un formulaire Web peut être une expérience fastidieuse pour les clients. Cela peut entraîner des erreurs et un taux de conversion plus faible.

C'est pourquoi l'API Payment Request prend en charge une fonctionnalité permettant de demander l'adresse de livraison et les coordonnées. Cela présente plusieurs avantages :

  • Les utilisateurs peuvent choisir la bonne adresse en quelques gestes.
  • L'adresse est toujours renvoyée au format standardisé.
  • Il est moins probable que vous saisissiez une adresse incorrecte.

Les navigateurs peuvent différer la collecte de l'adresse de livraison et des coordonnées à une application de paiement pour offrir une expérience de paiement unifiée. Cette fonctionnalité s'appelle la délégation.

Dans la mesure du possible, Chrome délègue la collecte de l'adresse de livraison et des coordonnées d'un client à l'application de paiement Android appelée. Cette délégation réduit les frictions lors du règlement.

Le site Web du marchand peut mettre à jour de manière dynamique les options de livraison et le prix total en fonction du choix du client concernant l'adresse et le mode de livraison.

Modification de l'option et de l'adresse de livraison en cours. Découvrez comment cela affecte les options de livraison et le prix total de manière dynamique.

Pour ajouter la prise en charge de la délégation à une application de paiement Android existante, procédez comme suit :

  1. Déclarez les délégations acceptées.
  2. Analysez les extras d'intent PAY pour les options de paiement requises.
  3. Fournissez les informations requises dans la réponse au paiement.
  4. Facultatif : Compatibilité avec le flux dynamique :
    1. Informer le marchand des modifications apportées au mode de paiement, à l'adresse de livraison ou à l'option de livraison sélectionnée par l'utilisateur.
    2. Recevez les informations de paiement mises à jour du marchand (par exemple, le montant total ajusté en fonction du coût de l'option de livraison sélectionnée).

Déclarer les délégations acceptées

Le navigateur doit connaître la liste des informations supplémentaires que votre application de paiement peut fournir afin de pouvoir déléguer la collecte de ces informations à votre application. Déclarez les délégations acceptées en tant que <meta-data> dans le fichier AndroidManifest.xml de votre application.

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

android:resource doit pointer vers un <string-array> contenant tout ou partie des valeurs suivantes :

  • payerName
  • payerEmail
  • payerPhone
  • shippingAddress

L'exemple suivant ne peut fournir qu'une adresse de livraison et l'adresse e-mail du payeur.

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

Analyser les extras d'intent PAY pour les options de paiement requises

Le marchand peut spécifier des informations supplémentaires requises à l'aide du dictionnaire paymentOptions. Chrome fournit la liste des options requises que votre application peut fournir en transmettant les paymentOptions extras d'intent à l'activité PAY.

paymentOptions

paymentOptions est le sous-ensemble des options de paiement spécifiées par le marchand pour lesquelles votre application a déclaré une compatibilité avec la délégation.

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

Il peut inclure les paramètres suivants :

  • requestPayerName : valeur booléenne indiquant si le nom du payeur est obligatoire ou non.
  • requestPayerPhone : valeur booléenne indiquant si le numéro de téléphone du payeur est obligatoire ou non.
  • requestPayerEmail : valeur booléenne indiquant si l'adresse e-mail du payeur est requise ou non.
  • requestShipping : valeur booléenne indiquant si les informations de livraison sont requises ou non.
  • shippingType : chaîne indiquant le type de livraison. Le type de livraison peut être "shipping", "delivery" ou "pickup". Votre application peut utiliser cet indice dans son interface utilisateur lorsqu'elle demande l'adresse de l'utilisateur ou son choix d'options de livraison.

shippingOptions

shippingOptions est le tableau de colis des options de livraison spécifiées par le marchand. Ce paramètre n'existe que lorsque 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;
  }
}

Chaque option de livraison est un Bundle avec les clés suivantes.

  • id : identifiant de l'option de livraison.
  • label : libellé de l'option de livraison affiché à l'utilisateur.
  • amount : bundle de frais de port contenant les clés currency et value avec des valeurs de chaîne.
    • currency indique la devise des frais de port sous la forme d'un code alphabétique à trois lettres ISO4217 bien formé.
    • value indique la valeur des frais de port sous forme de valeur monétaire décimale valide.
  • selected : indique si l'option de livraison doit être sélectionnée lorsque l'application de paiement affiche les options de livraison.

Toutes les clés, à l'exception de selected, ont des valeurs de chaîne. selected a une valeur booléenne.

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

Fournir les informations requises dans une réponse de paiement

Votre application doit inclure les informations supplémentaires requises dans sa réponse à l'activité PAY.

Pour ce faire, les paramètres suivants doivent être spécifiés en tant qu'extras d'intent :

  • payerName : nom complet du payeur. Il doit s'agir d'une chaîne non vide lorsque la valeur de paymentOptions.requestPayerName est "true".
  • payerPhone : numéro de téléphone du payeur. Il doit s'agir d'une chaîne non vide lorsque la valeur de paymentOptions.requestPayerPhone est "true".
  • payerEmail : adresse e-mail du payeur. Il doit s'agir d'une chaîne non vide lorsque paymentOptions.requestPayerEmail est défini sur "true".
  • shippingAddress : adresse de livraison fournie par l'utilisateur. Il doit s'agir d'un bundle non vide lorsque paymentOptions.requestShipping est défini sur "true". Le bundle doit comporter les clés suivantes, qui représentent différentes parties d'une adresse physique.
    • countryCode
    • postalCode
    • sortingCode
    • region
    • city
    • dependentLocality
    • addressLine
    • organization
    • recipient
    • phone Toutes les clés, à l'exception de addressLine, ont des valeurs de chaîne. addressLine est un tableau de chaînes.
  • shippingOptionId : identifiant de l'option de livraison sélectionnée par l'utilisateur. Il doit s'agir d'une chaîne non vide lorsque la valeur de paymentOptions.requestShipping est "true".

Valider la réponse de paiement

Si le résultat de l'activité d'une réponse de paiement reçue de l'application de paiement appelée est défini sur RESULT_OK, Chrome recherchera les informations supplémentaires requises dans ses extras. Si la validation échoue, Chrome renvoie une promesse refusée à partir de request.show() avec l'un des messages d'erreur suivants destinés aux développeurs :

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

L'exemple de code suivant illustre une réponse valide :

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

Facultatif : Assurez la compatibilité avec le flux dynamique

Il arrive que le coût total d'une transaction augmente, par exemple lorsque l'utilisateur choisit l'option de livraison express ou lorsque la liste des options de livraison disponibles ou de leurs prix change lorsque l'utilisateur choisit une adresse de livraison à l'étranger. Lorsque votre application fournit l'adresse ou l'option de livraison sélectionnée par l'utilisateur, elle doit pouvoir informer le marchand de toute modification de l'adresse ou de l'option de livraison et afficher à l'utilisateur les informations de paiement mises à jour (fournies par le marchand).

Pour informer le marchand des nouvelles modifications, implémentez l'interface IPaymentDetailsUpdateServiceCallback et déclarez-la dans votre AndroidManifest.xml avec le filtre d'intent UPDATE_PAYMENT_DETAILS.

Immédiatement après l'appel de l'intent PAY, Chrome se connecte au service UPDATE_PAYMENT_DETAILS (s'il existe) dans le même package que l'intent PAY et appelle setPaymentDetailsUpdateService(service) pour fournir à votre application de paiement le point de terminaison IPaymentDetailsUpdateService permettant de notifier les modifications apportées au mode de paiement, à l'option de livraison ou à l'adresse de livraison de l'utilisateur.

Utilisez packageManager.getPackagesForUid(Binder.getCallingUid()) lors de la réception de la communication interprocessus (IPC) pour valider que l'application qui a appelé l'intent PAY possède le même nom de package que l'application qui a appelé les méthodes IPaymentDetailsUpdateServiceCallback.

AIDL

Créez deux fichiers AIDL avec le contenu suivant :

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

Service

Implémentez le service 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

Exposez le service pour IPaymentDetailsUpdateServiceCallback dans votre AndroidManifest.xml.

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

Informer le marchand des modifications apportées au mode de paiement, à l'adresse de livraison ou à l'option de livraison sélectionnés par l'utilisateur

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

Avertit le marchand des modifications apportées au mode de paiement sélectionné par l'utilisateur. Le bundle paymentHandlerMethodData contient les clés methodName et details (facultative), qui ont toutes deux des valeurs de chaîne. Chrome recherchera un bundle non vide avec un methodName non vide et enverra un updatePaymentDetails avec l'un des messages d'erreur suivants à l'aide de callback.updateWith si la validation échoue.

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

changeShippingOption

Avertit le marchand des modifications apportées à l'option de livraison sélectionnée par l'utilisateur. shippingOptionId doit être l'identifiant de l'une des options de livraison spécifiées par le marchand. Chrome recherchera un shippingOptionId non vide et enverra un updatePaymentDetails avec le message d'erreur suivant à l'aide de callback.updateWith si la validation échoue.

'Shipping option identifier required.'

changeShippingAddress

Avertit le marchand des modifications apportées à l'adresse de livraison fournie par l'utilisateur. Chrome recherchera un bundle shippingAddress non vide avec un countryCode valide et enverra un updatePaymentDetails avec le message d'erreur suivant à l'aide de callback.updateWith si la validation échoue.

'Payment app returned invalid shipping address in response.'

Message d'erreur "État non valide"

Si Chrome rencontre un état non valide lors de la réception de l'une des demandes de modification, il appelle callback.updateWith avec un bundle updatePaymentDetails masqué. Le bundle ne contiendra que la clé error avec "Invalid state". Voici des exemples d'états non valides :

  • Lorsque Chrome attend toujours la réponse du marchand à une modification précédente (par exemple, un événement de modification en cours).
  • L'identifiant de l'option de livraison fournie par l'application de paiement n'appartient à aucune des options de livraison spécifiées par le marchand.

Recevoir des informations de paiement mises à jour de la part du marchand

Kotlin

override fun updateWith(updatedPaymentDetails: Bundle) {}

override fun paymentDetailsNotUpdated() {}

Java

@Override
public void updateWith(Bundle updatedPaymentDetails) {}

@Override
public void paymentDetailsNotUpdated() {}

updatedPaymentDetails est le bundle équivalent au dictionnaire PaymentRequestDetailsUpdate WebIDL et contient les clés facultatives suivantes :

  • total : bundle contenant les clés currency et value, qui ont toutes deux des valeurs de chaîne
  • shippingOptions : tableau d'options d'expédition pouvant être mises en colis
  • error : chaîne contenant un message d'erreur générique (par exemple, lorsque changeShippingOption ne fournit pas d'identifiant d'option de livraison valide)
  • stringifiedPaymentMethodErrors : chaîne JSON représentant les erreurs de validation du mode de paiement.
  • addressErrors : bundle avec des clés facultatives identiques à shipping address et des valeurs de chaîne. Chaque clé représente une erreur de validation liée à la partie correspondante de l'adresse de livraison.
  • modifiers : tableau de Bundles pouvant être mis en paquet, chacun avec un champ total et un champ methodData, qui sont également des Bundles.

Une clé absente signifie que sa valeur n'a pas changé.