Mettre à jour votre application de paiement Android pour fournir l'adresse de livraison et les coordonnées du payeur avec les API Web Payments
Publié le 17 juillet 2020, dernière mise à jour le 27 mai 2025
La saisie de l'adresse de livraison et des coordonnées via un formulaire Web peut être une expérience fastidieuse pour les clients. Cela peut entraîner des erreurs et réduire le taux de conversion.
C'est pourquoi l'API Payment Request propose une fonctionnalité permettant de demander l'adresse de livraison et les coordonnées. Cela présente plusieurs avantages:
- Les utilisateurs peuvent sélectionner la bonne adresse en quelques gestes.
- L'adresse est toujours renvoyée au format standardisé.
- Il est moins probable que vous saisisiez 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é est appelée 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. La délégation réduit les frictions lors du règlement.
Le site Web du marchand peut mettre à jour dynamiquement les options de livraison et le prix total en fonction de l'adresse de livraison et de l'option de livraison choisies par le client.
Pour ajouter la prise en charge de la délégation à une application de paiement Android existante, procédez comme suit:
- Déclarez les délégations acceptées.
- Analysez les extras d'intent
PAY
pour les options de paiement requises. - Fournissez les informations requises dans la réponse au paiement.
- [Facultatif] Prise en charge du flux dynamique :
- 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
- Recevoir 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 compatibles 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 l'ensemble ou un sous-ensemble 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 requises supplémentaires à l'aide du dictionnaire paymentOptions
. Chrome fournit la liste des options requises que votre application peut fournir en transmettant les éléments supplémentaires d'intent paymentOptions
à 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é la prise en charge de 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");
}
Elle 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 téléphone du payeur est requis 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 cette indication dans son interface utilisateur lorsqu'elle demande l'adresse de l'utilisateur ou le choix des options de livraison.
shippingOptions
shippingOptions
est le tableau parcellable 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 présenté à l'utilisateur.amount
: bundle des frais de port contenant les cléscurrency
etvalue
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 valide.value
affiche la valeur des frais de port sous la forme d'une 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 autres que 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 lorsquepaymentOptions.requestPayerName
est défini sur "true".payerPhone
: numéro de téléphone du payeur. Il doit s'agir d'une chaîne non vide lorsquepaymentOptions.requestPayerPhone
est défini sur "true".payerEmail
: adresse e-mail du payeur. Il doit s'agir d'une chaîne non vide lorsquepaymentOptions.requestPayerEmail
est vrai.shippingAddress
: adresse de livraison fournie par l'utilisateur. Il doit s'agir d'un bundle non vide lorsquepaymentOptions.requestShipping
est vrai. Le bundle doit contenir 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 autres queaddressLine
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 lorsquepaymentOptions.requestShipping
est défini sur "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 recherche les informations supplémentaires requises dans ses extras. Si la validation échoue, Chrome renvoie une promesse refusée de request.show()
avec l'un des messages d'erreur destinés aux développeurs suivants:
'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 est un exemple de 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: Prendre en charge le flux dynamique
Parfois, 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 leurs prix changent lorsque l'utilisateur choisit une adresse de livraison internationale. 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 connectera au service UPDATE_PAYMENT_DETAILS
(s'il existe) dans le même package que l'intent PAY
et appellera setPaymentDetailsUpdateService(service)
pour fournir à votre application de paiement le point de terminaison IPaymentDetailsUpdateService
afin de l'informer des modifications apportées au mode de paiement, à l'option de livraison ou à l'adresse de livraison de l'utilisateur.
Utilisez packageManager.getPackagesForUid(Binder.getCallingUid())
lorsque vous recevez une communication inter-processus (IPC) pour vérifier que l'application qui a appelé l'intent PAY
porte 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
Informe le marchand des modifications apportées au mode de paiement sélectionné par l'utilisateur. Le bundle paymentHandlerMethodData
contient des clés methodName
et details
facultatives, toutes deux avec des valeurs de chaîne. Chrome recherche un bundle non vide avec un methodName
non vide et envoie un updatePaymentDetails
avec l'un des messages d'erreur suivants via callback.updateWith
en cas d'échec de la validation.
'Method data required.'
'Method name required.'
changeShippingOption
Informe 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 recherche un shippingOptionId
non vide et envoie un updatePaymentDetails
avec le message d'erreur suivant via callback.updateWith
si la validation échoue.
'Shipping option identifier required.'
changeShippingAddress
Informe le marchand des modifications apportées à l'adresse de livraison fournie par l'utilisateur. Chrome recherche un bundle shippingAddress
non vide avec un countryCode
valide et envoie un updatePaymentDetails
avec le message d'erreur suivant via callback.updateWith
si la validation échoue.
'Payment app returned invalid shipping address in response.'
Message d'erreur d'état non valide
Si Chrome rencontre un état non valide lors de la réception de l'une des requêtes 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 les informations de paiement mises à jour 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 WebIDL PaymentRequestDetailsUpdate
et contient les clés facultatives suivantes:
total
: bundle contenant les cléscurrency
etvalue
, les deux clés ayant des valeurs de chaîneshippingOptions
: tableau parcelable des options de livraisonerror
: chaîne contenant un message d'erreur générique (par exemple, lorsquechangeShippingOption
ne fournit pas d'identifiant d'option de livraison valide)stringifiedPaymentMethodErrors
: chaîne JSON représentant les erreurs de validation pour le mode de paiementaddressErrors
: bundle avec des clés facultatives identiques à l'adresse de livraison et aux valeurs de chaîne. Chaque clé représente une erreur de validation liée à la partie correspondante de l'adresse de livraison.modifiers
: tableau parcellable d'offres groupées, chacune avec un champtotal
et un champmethodData
, qui sont également des offres groupées.
Une clé absente signifie que sa valeur n'a pas changé.