Proporciona información de contacto y de envío desde una app de pagos de Android

Cómo actualizar tu app de pagos de Android para proporcionar la dirección de envío y la información de contacto del pagador con las API de pagos web

Sahel Sharify
Sahel Sharify

Ingresar la dirección de envío y la información de contacto en un formulario web puede ser una experiencia complicada para los clientes. Puede causar errores y reducir las conversiones tasa.

Por eso la API Payment Request admite una función para solicitar envíos dirección personal y de contacto. Esto proporciona varios beneficios:

  • Los usuarios pueden elegir la dirección correcta con solo presionar la pantalla un par de veces.
  • La dirección siempre se devuelve en la formato.
  • Es menos probable que envíes una dirección incorrecta.

Los navegadores pueden diferir la recopilación de la dirección de envío y la información de contacto a una app de pagos para brindar una experiencia de pago unificada. Esta función es llamada delegación.

Siempre que sea posible, Chrome delega la recopilación de los envíos que realice un cliente. la dirección y la información de contacto de la app de pagos de Android invocada. El la delegación reduce la fricción durante la confirmación de la compra.

El sitio web del comercio puede actualizar de forma dinámica las opciones de envío y el precio total según la dirección de envío que elija el cliente y el de 12 a 1 con la nueva opción de compresión.

La opción de envío y el cambio de dirección de envío en acción. Descubre cómo afecta las opciones de envío y el precio total de forma dinámica.

Para agregar compatibilidad con la delegación a una app de pagos para Android existente, haz lo siguiente: implementa los siguientes pasos:

  1. Declara las delegaciones admitidas.
  2. Analiza los extras del intent de PAY para obtener el pago requerido .
  3. Proporciona la información requerida en el pago respuesta.
  4. [Opcional] Admite el flujo dinámico:
    1. Notificar al comercio sobre los cambios en la forma de pago seleccionada por el usuario dirección de envío o envío de la aplicación.
    2. Recibir detalles del pago actualizados del comercio (por ejemplo, importe total ajustado en función de la opción de envío seleccionada costo).

Declara las delegaciones admitidas

El navegador debe conocer la lista de información adicional que su pago aplicación puede proporcionar para delegar la recopilación de esa información a tu . Declara las delegaciones admitidas como <meta-data> en el archivo AndroidManifest.xml

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

<resource> debe ser una lista de cadenas elegidas de los siguientes valores válidos:

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

En el siguiente ejemplo, solo se puede proporcionar una dirección de envío y el correo electrónico del pagador web.

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

Analiza los extras del intent PAY para las opciones de pago requeridas

El comercio puede especificar la información adicional requerida con los paymentOptions diccionario. Chrome proporcionará la lista de opciones requeridas que tu app puede Proporciona pasando los siguientes parámetros a la actividad PAY como Intent adicionales.

paymentOptions

paymentOptions es el subconjunto de opciones de pago especificadas por el comercio para las que tu app declaró la compatibilidad con la delegación.

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

Puede incluir los siguientes parámetros:

  • requestPayerName: Es el valor booleano que indica si el nombre del pagador. es obligatorio.
  • requestPayerPhone: Es el valor booleano que indica si el teléfono del pagador o no. es obligatorio.
  • requestPayerEmail: Es el valor booleano que indica si el correo electrónico del pagador o no. es obligatorio.
  • requestShipping: valor booleano que indica si la información de envío es o no. es obligatorio.
  • shippingType: Es la cadena que muestra el tipo de envío. El tipo de envío puede ser "shipping", "delivery" o "pickup". Tu app puede usar esta sugerencia en su IU cuando se solicita la dirección del usuario o la elección de opciones de envío

shippingOptions

shippingOptions es el array parcelable del envío especificado por el comercio. opciones de estado. Este parámetro solo existirá cuando sea paymentOptions.requestShipping == true.

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

Cada opción de envío es un Bundle con las siguientes claves.

  • id: Es el identificador de la opción de envío.
  • label: Es la etiqueta de opción de envío que se muestra al usuario.
  • amount: El paquete de costo de envío que contiene currency y value claves con de cadena.
    • currency muestra la moneda del costo de envío como un Con formato ISO4217 correcto Código del alfabeto de 3 letras
    • value muestra el valor del costo de envío como un decimal decimal válido valor
  • selected: Indica si se debe seleccionar la opción de envío cuando la La app de pagos muestra las opciones de envío.

Todas las claves que no sean selected tienen valores de cadena. selected tiene un valor booleano valor.

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)

Proporciona información obligatoria en una respuesta de pago

Tu aplicación debe incluir la información adicional requerida en su respuesta a la actividad PAY

Para ello, se deben especificar los siguientes parámetros como extras de intent:

  • payerName: Es el nombre completo del pagador. Debe ser una cadena que no esté vacía cuando paymentOptions.requestPayerName es verdadero.
  • payerPhone: Es el número de teléfono del pagador. Debe ser una cadena que no esté vacía cuando paymentOptions.requestPayerPhone es verdadero.
  • payerEmail: Es la dirección de correo electrónico del pagador. Debe ser una cadena que no esté vacía cuando paymentOptions.requestPayerEmail es verdadero.
  • shippingAddress: Es la dirección de envío proporcionada por el usuario. Debe ser una Paquete no vacío cuando paymentOptions.requestShipping es verdadero. El paquete debe tener las siguientes claves, que representan diferentes partes de un entorno físico, dirección.
    • city
    • countryCode
    • dependentLocality
    • organization
    • phone
    • postalCode
    • recipient
    • region
    • sortingCode
    • addressLine Todas las claves que no sean addressLine tienen valores de cadena. El addressLine es un array de cadenas.
  • shippingOptionId: Es el identificador de la opción de envío que selecciona el usuario. Esta debe ser una cadena que no esté vacía cuando paymentOptions.requestShipping sea verdadero.

Validar respuesta de pago

Si el resultado de la actividad de una respuesta de pago recibida del pago invocado aplicación está configurada como RESULT_OK, Chrome comprobará si se necesitan información en sus extras. Si la validación falla, Chrome devolverá promesa de request.show() con uno de los siguientes errores dirigidos al desarrollador mensajes:

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

La siguiente muestra de código es un ejemplo de una respuesta válida:

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

Opcional: Admite el flujo dinámico

A veces aumenta el costo total de una transacción; por ejemplo, cuando el usuario elija la opción de envío exprés o cuando la lista de productos disponibles opciones o sus precios cambian cuando el usuario elige un envío internacional. web. Cuando tu app proporciona la opción o dirección de envío seleccionada por el usuario, deben poder notificar al comercio sobre cualquier opción o dirección de envío cambia y mostrará al usuario los detalles del pago actualizados (proporcionados por el comercio).

AIDL

Para notificar al comercio sobre los nuevos cambios, usa el PaymentDetailsUpdateService declarado en el archivo AndroidManifest.xml de Chrome. Para usar este servicio, crea dos Archivos AIDL con el siguiente contenido:

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

Notificar al comercio sobre los cambios en la forma de pago, la dirección de envío o la opción de envío que seleccionó el usuario

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

El callingPackageName que se usa para el intent de inicio del servicio puede tener uno de los siguientes: los siguientes valores según el navegador que haya iniciado el pago para cada solicitud.

Canal de Chrome Nombre del paquete
Estable "com.android.chrome"
Beta "com.chrome.beta"
Desarrollo "com.chrome.dev"
Canary "com.chrome.canary"
Chromium "org.chromium.chrome"
Cuadro de búsqueda rápida de Google (un incorporador de WebLayer) "com.google.android.googlequicksearchbox"

changePaymentMethod

Notifica al comercio sobre los cambios en la forma de pago seleccionada por el usuario. El El paquete paymentHandlerMethodData contiene methodName y los campos opcionales details claves ambas con valores de cadena. Chrome buscará un paquete que no esté vacío con un methodName no vacío y envía un updatePaymentDetails con uno de los a través de callback.updateWith si la validación falla.

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

changeShippingOption

Notifica al comercio sobre los cambios en la opción de envío seleccionada por el usuario. shippingOptionId debe ser el identificador de uno de los comercios especificados. de envío al día siguiente. Chrome buscará un shippingOptionId que no esté vacío y enviará una updatePaymentDetails con el siguiente mensaje de error mediante callback.updateWith si falla la validación

'Shipping option identifier required.'

changeShippingAddress

Notifica al comercio sobre los cambios en la dirección de envío proporcionada por el usuario. Chrome buscará un paquete de shippingAddress que no esté vacío con un countryCode válido Envía un updatePaymentDetails con el siguiente mensaje de error mediante callback.updateWith si falla la validación.

'Payment app returned invalid shipping address in response.'

Mensaje de error de estado no válido

Si Chrome encuentra un estado no válido al recibir alguna de las solicitudes de cambio llamará a callback.updateWith con un updatePaymentDetails oculto en un paquete. El paquete solo contendrá la clave error con "Invalid state". Estos son algunos ejemplos de un estado no válido:

  • Cuando Chrome sigue esperando la respuesta del comercio a un cambio anterior (como un evento de cambio en curso).
  • El identificador de opción de envío proporcionado por la aplicación de pago no pertenece a ninguno de las opciones de envío especificadas por el comercio.

Recibir los detalles del pago actualizados del comercio

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 es el paquete equivalente a PaymentRequestDetailsUpdate diccionario WebIDL (después de ocultar el modifiers) y contiene las siguientes claves opcionales:

  • total: Es un paquete que contiene claves currency y value; ambas claves tienen. valores de cadenas
  • shippingOptions: Es el array parcelable de shipping. Opciones
  • error: Es una cadena que contiene un mensaje de error genérico (p.ej., cuando changeShippingOption no proporciona un identificador de opción de envío válido)
  • stringifiedPaymentMethodErrors: Es una cadena JSON que representa la validación. errores en la forma de pago
  • addressErrors: paquete con claves opcionales idénticas al elemento shipping dirección y cadena de salida. Cada clave representa un error de validación relacionado con su de la dirección de envío.

Una clave ausente significa que su valor no cambió.