Como fornecer dados de contato e de envio de um app de pagamento para Android

Como atualizar seu app de pagamento Android para fornecer o endereço de entrega e os dados de contato do pagador com as APIs Web Payments.

Sahel Sharify
Sahel Sharify

Digitar endereço de entrega e informações de contato por meio de um formulário da Web pode ser uma uma experiência complicada para os clientes. Isso pode causar erros e reduzir conversões e a taxa de conversão.

É por isso que a API Payment Request é compatível com um recurso para solicitar frete endereço e dados de contato. Isso oferece vários benefícios:

  • Os usuários podem escolher o endereço certo com apenas alguns toques.
  • O endereço é sempre retornado na configuração padrão formato.
  • É menos provável que envie um endereço incorreto.

Os navegadores podem adiar a coleta do endereço de entrega e dos dados de contato para um aplicativo de pagamento para proporcionar uma experiência de pagamento unificada. Essa funcionalidade chamado delegação.

Sempre que possível, o Chrome delega a coleta dos dados de envio de um cliente e os dados de contato para o app de pagamento para Android invocado. A a delegação reduz o atrito na finalização da compra.

O site do comerciante pode atualizar dinamicamente as opções de frete e o preço total. dependendo do endereço de entrega e do frete que o cliente é a melhor opção.

Mudança na opção de frete e no endereço de entrega em ação. Veja como isso afeta as opções de frete e o preço total de forma dinâmica.
.

Para adicionar suporte à delegação a um app de pagamento já existente no Android, faça o seguinte: implemente as seguintes etapas:

  1. Declare as delegações compatíveis.
  2. Analisar os extras da intent PAY para o pagamento necessário de controle de acesso.
  3. Forneça as informações necessárias no pagamento resposta.
  4. [Opcional] Suporte ao fluxo dinâmico:
    1. Notificar o comerciante sobre mudanças na forma de pagamento selecionada pelo usuário endereço de entrega ou endereço de entrega .
    2. Receba detalhes de pagamento atualizados do comerciante (por exemplo, o o valor total ajustado com base na opção de envio selecionada ).

Declarar delegações compatíveis

O navegador precisa saber a lista de informações adicionais que seu pagamento que o app pode fornecer para delegar a coleta dessas informações à sua app. Declare as delegações com suporte como um <meta-data> no arquivo AndroidManifest.xml (link em inglês).

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

<resource> precisa ser uma lista de strings escolhidas entre os seguintes valores válidos:

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

O exemplo a seguir fornece apenas um endereço de entrega e o e-mail do pagador endereço IP.

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

Analisar os extras da intent PAY para as opções de pagamento necessárias

O comerciante pode especificar informações adicionais necessárias usando o paymentOptions dicionário. O Chrome vai fornecer a lista de opções necessárias que o app pode fornecem passando os seguintes parâmetros para a atividade PAY como Intent extras.

paymentOptions

paymentOptions é o subconjunto de opções de pagamento especificadas pelo comerciante em que o app declarou suporte à delegação.

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

Ele pode incluir os seguintes parâmetros:

  • requestPayerName: o booleano que indica se o nome do pagador é obrigatório.
  • requestPayerPhone: o booleano que indica se o smartphone do pagador é obrigatório.
  • requestPayerEmail: o booleano que indica se o e-mail do pagador é obrigatório.
  • requestShipping: o booleano que indica se as informações de frete são ou não é obrigatório.
  • shippingType: a string que mostra o tipo de frete. O tipo de frete pode ser "shipping", "delivery" ou "pickup". Seu app pode usar essa dica IU ao solicitar o endereço do usuário ou a escolha das opções de envio.

shippingOptions

shippingOptions é a matriz fracionável do frete especificado pelo comerciante. . Esse parâmetro só existe quando paymentOptions.requestShipping == true.

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

Cada opção de envio é um Bundle com as chaves a seguir.

  • id: identificador da opção de envio.
  • label: o rótulo da opção de envio mostrado ao usuário.
  • amount: o pacote de custo de frete que contém as chaves currency e value com valores de string.
  • selected: se a opção de envio deve ser selecionada ou não quando o o app de pagamento mostra as opções de envio.

Todas as chaves, exceto selected, têm valores de string. selected tem um booleano .

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)

Fornecer as informações necessárias na resposta ao pagamento

Seu aplicativo deve incluir as informações adicionais necessárias em resposta a a atividade PAY.

Para fazer isso, os seguintes parâmetros precisam ser especificados como extras de intent:

  • payerName: o nome completo do pagador. Precisa ser uma string que não esteja vazia quando paymentOptions.requestPayerName é verdadeiro.
  • payerPhone: número de telefone do pagador. Precisa ser uma string que não esteja vazia quando paymentOptions.requestPayerPhone é verdadeiro.
  • payerEmail: endereço de e-mail do pagador. Precisa ser uma string que não esteja vazia quando paymentOptions.requestPayerEmail for verdadeiro.
  • shippingAddress: o endereço de entrega fornecido pelo usuário. Ele deve ser pacote não vazio quando paymentOptions.requestShipping for verdadeiro. O pacote deve ter as seguintes chaves que representam diferentes partes de uma física endereço IP.
    • city
    • countryCode
    • dependentLocality
    • organization
    • phone
    • postalCode
    • recipient
    • region
    • sortingCode
    • addressLine Todas as chaves, exceto addressLine, têm valores de string. O addressLine é uma matriz de strings.
  • shippingOptionId: o identificador da opção de envio selecionada pelo usuário. Isso precisa ser uma string não vazia quando paymentOptions.requestShipping for verdadeiro.

Validar resposta de pagamento

Se o resultado da atividade de uma resposta de pagamento recebida do pagamento invocado app está definido como RESULT_OK, o Chrome verificará se existem nos extras. Se a validação falhar, o Chrome retornará uma mensagem promessa de request.show() com um dos seguintes erros voltados ao desenvolvedor mensagens:

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

O exemplo de código a seguir mostra uma resposta 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: suporte ao fluxo dinâmico

Às vezes, o custo total de uma transação aumenta, como quando o usuário escolha a opção de frete expresso ou quando a lista de opções ou os preços mudam quando o usuário escolhe uma opção de envio endereço IP. Quando o app fornece o endereço ou a opção de entrega selecionada pelo usuário, precisa notificar o comerciante sobre qualquer endereço ou opção de entrega alterações e mostrar ao usuário os detalhes de pagamento atualizados (fornecidos pelo comerciante).

AIDL

Para notificar o comerciante sobre novas mudanças, use o PaymentDetailsUpdateService declarado no AndroidManifest.xml do Chrome. Para usar esse serviço, crie dois Arquivos AIDL com o seguinte conteúdo:

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 o comerciante sobre mudanças na forma de pagamento, endereço de entrega ou opção de envio selecionada pelo usuário

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

O callingPackageName usado para a intent de inicialização do serviço pode ter uma das valores a seguir, dependendo do navegador que iniciou o pagamento solicitação.

Canal do Chrome Nome do pacote
Estável "com.android.chrome"
Beta "com.chrome.beta"
Dev "com.chrome.dev"
Canary "com.chrome.canary"
Chromium "org.chromium.chrome"
Caixa de pesquisa rápida do Google (um incorporador da WebLayer) "com.google.android.googlequicksearchbox"

changePaymentMethod

Notifica o comerciante sobre mudanças na forma de pagamento selecionada pelo usuário. A O pacote paymentHandlerMethodData contém methodName e details opcional chaves com valores de string. O Chrome verificará se há um pacote que não esteja vazio com uma methodName não vazio e enviar um updatePaymentDetails com um dos mensagens de erro a seguir via callback.updateWith se a validação falhar.

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

changeShippingOption

Notifica o comerciante sobre mudanças na opção de envio selecionada pelo usuário. shippingOptionId deve ser o identificador de um dos endereços especificados pelo comerciante opções de envio. O Chrome vai verificar se há um shippingOptionId não vazio e enviar um updatePaymentDetails com a seguinte mensagem de erro via callback.updateWith se a validação falhar.

'Shipping option identifier required.'

changeShippingAddress

Notifica o comerciante sobre mudanças no endereço de entrega fornecido pelo usuário. Google Chrome vai procurar um pacote de shippingAddress não vazio com um parâmetro countryCode válido e envie uma updatePaymentDetails com a seguinte mensagem de erro via callback.updateWith se a validação falhar.

'Payment app returned invalid shipping address in response.'

Mensagem de erro de estado inválido

Se o Chrome encontrar um estado inválido ao receber qualquer uma das solicitações de mudança ele vai chamar callback.updateWith com uma updatePaymentDetails encoberta; feixe. O pacote conterá apenas a chave error com "Invalid state". Exemplos de um estado inválido:

  • Quando o Chrome ainda está aguardando a resposta do comerciante a uma alteração anterior (como um evento de alteração contínua).
  • O identificador da opção de envio fornecido pelo aplicativo de pagamento não pertence a nenhum as opções de envio especificadas pelo comerciante.

Receber detalhes de pagamento atualizados do comerciante

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 é o pacote equivalente ao PaymentRequestDetailsUpdate dicionário WebIDL (depois de encobrir o modifiers) e contém as seguintes chaves opcionais:

  • total: um pacote contendo as chaves currency e value, ambas as chaves têm valores de string
  • shippingOptions: a matriz fracionável de frete opções
  • error: uma string que contém uma mensagem de erro genérica (por exemplo, quando changeShippingOption não fornece um identificador de opção de envio válido)
  • stringifiedPaymentMethodErrors: uma string JSON que representa a validação erros na forma de pagamento
  • addressErrors: um pacote com chaves opcionais idênticas a shipping [frete] address e string e a distribuição dos valores dos dados. Cada chave representa um erro de validação relacionado ao parte do endereço de entrega.

Uma chave ausente significa que o valor não foi alterado.