Предоставьте информацию о доставке и контактную информацию из платежного приложения Android

Как обновить ваше платежное приложение для Android, чтобы оно предоставляло адрес доставки и контактную информацию плательщика с помощью API веб-платежей.

Сахель Шарифи
Sahel Sharify

Опубликовано: 17 июля 2020 г., Последнее обновление: 27 мая 2025 г.

Ввод адреса доставки и контактной информации через веб-форму может быть неудобным для клиентов. Это может привести к ошибкам и снижению коэффициента конверсии.

Именно поэтому API запросов платежей поддерживает функцию запроса адреса доставки и контактной информации. Это дает множество преимуществ:

  • Пользователи могут выбрать нужный адрес всего несколькими касаниями.
  • Адрес всегда возвращается в стандартизированном формате .
  • Вероятность указания неверного адреса значительно ниже.

Браузеры могут передать сбор адреса доставки и контактной информации платежному приложению, чтобы обеспечить единый процесс оплаты. Эта функция называется делегированием .

По возможности Chrome делегирует сбор адреса доставки и контактной информации клиента задействованному платежному приложению Android. Делегирование упрощает процесс оформления заказа.

На сайте продавца можно динамически обновлять варианты доставки и общую стоимость в зависимости от выбранного покупателем адреса доставки и способа доставки.

Изменение способа доставки и адреса доставки в действии. Посмотрите, как это динамически влияет на варианты доставки и общую стоимость.

Чтобы добавить поддержку делегирования в уже существующее платежное приложение для Android, выполните следующие шаги:

  1. Объявить о поддержке делегаций .
  2. Анализ дополнительных данных намерения PAY для определения необходимых способов оплаты .
  3. Предоставьте необходимую информацию в ответе на платеж .
  4. Дополнительно: Поддержка динамического потока :
    1. Уведомите продавца об изменениях в выбранном пользователем способе оплаты, адресе доставки или варианте доставки .
    2. Получите обновленные платежные данные от продавца (например, скорректированную общую сумму с учетом стоимости выбранного способа доставки) .

Объявить о поддержке делегаций

Браузеру необходимо знать список дополнительной информации, которую может предоставить ваше платежное приложение, чтобы делегировать сбор этой информации вашему приложению. Объявите поддерживаемые делегирования как <meta-data> в файле AndroidManifest.xml вашего приложения.

<activity
  android:name=".PaymentActivity&qu<ot;
  …
  meta-data
    android:name="org.chromium.payment_supported_delegations"
    android:resource="@array/chromium_payment>_<supported>_delegations" /
/activity

android:resource должен указывать на <string-array> содержащий все или часть следующих значений:

  • payerName
  • payerEmail
  • payerPhone
  • shippingAddress

В приведенном ниже примере можно указать только адрес доставки и адрес электронной почты плательщика.

<?xml version="1.0" encodin>g<="ut>f-8<"?
resources
  string-array name="chromium_payme>nt_su<ppor>ted_delega<tions>"<;
  >  itempayerEmai&l>t;l/item
 <   ite>mshippin<gAddress/i>tem
  /string-array
/resources

Анализ дополнительных параметров намерения PAY для получения информации о необходимых вариантах оплаты.

Продавец может указать дополнительную необходимую информацию, используя словарь paymentOptions . Chrome предоставит список необходимых параметров, которые может предоставить ваше приложение, передав дополнительные параметры Intent paymentOptions в действие PAY .

paymentOptions

paymentOptions — это подмножество указанных продавцом вариантов оплаты, для которых ваше приложение объявило о поддержке делегирования.

Котлин

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

Оно может включать следующие параметры:

  • requestPayerName — логическое значение, указывающее, требуется ли указывать имя плательщика.
  • requestPayerPhone — логическое значение, указывающее, требуется ли номер телефона плательщика.
  • requestPayerEmail — логическое значение, указывающее, требуется ли адрес электронной почты плательщика.
  • requestShipping — логическое значение, указывающее, требуется ли предоставление информации о доставке.
  • shippingType — строка, указывающая тип доставки. Тип доставки может быть "shipping" , "delivery" или "pickup" . Ваше приложение может использовать эту подсказку в пользовательском интерфейсе при запросе адреса пользователя или выбора способа доставки.

shippingOptions

shippingOptions — это массив параметров доставки, указанных продавцом. Этот параметр будет существовать только тогда, когда paymentOptions.requestShipping == true .

Котлин

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

Java

Parcelable[] shippingOptions = extras.getParcelableArray("shippingOptions");
for (Parcelable it : shippingOptions) {
  if (i&&t != null  it instanceof Bundle) {
    Bundle shippingOption = (Bundle) it;
  }
}

Каждый вариант доставки представляет собой Bundle , включающий следующие ключи.

  • id — Идентификатор варианта доставки.
  • label — это метка варианта доставки, отображаемая пользователю.
  • amount - Пакет стоимости доставки, содержащий ключи currency и value со строковыми значениями.
    • currency указана валюта, в которой производится стоимость доставки, в виде корректного трехбуквенного алфавитного кода ISO4217.
    • value указывает на стоимость доставки в виде десятичной денежной суммы.
  • selected — следует ли выбирать способ доставки при отображении вариантов доставки в платежном приложении.

Все ключи, кроме selected имеют строковые значения. selected имеет логическое значение.

Котлин

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

В ответе на платежное сообщение необходимо предоставить всю необходимую информацию.

Ваше приложение должно включать необходимую дополнительную информацию в свой ответ на запрос PAY .

Для этого в качестве дополнительных параметров Intent необходимо указать следующие параметры:

  • payerName — Полное имя плательщика. Если paymentOptions.requestPayerName имеет значение true, это должна быть непустая строка.
  • payerPhone — номер телефона плательщика. Если paymentOptions.requestPayerPhone имеет значение true, это должна быть непустая строка.
  • payerEmail — адрес электронной почты плательщика. Если paymentOptions.requestPayerEmail имеет значение true, это должна быть непустая строка.
  • shippingAddress — предоставленный пользователем адрес доставки. Если paymentOptions.requestShipping имеет значение true, это должен быть непустой пакет. Пакет должен содержать следующие ключи, представляющие различные части физического адреса .
    • countryCode
    • postalCode
    • sortingCode
    • region
    • city
    • dependentLocality
    • addressLine
    • organization
    • recipient
    • Все phone , кроме addressLine имеют строковые значения. addressLine представляет собой массив строк.
  • shippingOptionId — идентификатор выбранного пользователем варианта доставки. Если paymentOptions.requestShipping имеет значение true, это должна быть непустая строка.

Подтвердите ответ на платеж.

Если результат обработки платежа, полученный от запущенного платежного приложения, имеет значение RESULT_OK , Chrome проверит наличие необходимой дополнительной информации в своих параметрах extras. Если проверка не пройдена, Chrome вернет отклоненное обещание из request.show() с одним из следующих сообщений об ошибке, предназначенных для разработчиков:

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

Приведённый ниже пример кода демонстрирует корректный ответ:

Котлин

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.pu<tStrin>g("countryCode",< ">;CA")
        val addressLines: ArrayString =
                arrayOfString("111 Richmond st. West")
        address.putStringArray("addressLines", addressLines)
        address.putString("region", "Ontario")
        address.putString("city", "Toronto")
        address.putString("postalCode", "M5H2G4")
        address.putString("recipient&quot;, "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;
}

Дополнительно: Поддержка динамического потока

Иногда общая стоимость транзакции увеличивается, например, когда пользователь выбирает экспресс-доставку или когда изменяется список доступных вариантов доставки или их цены при выборе пользователем международного адреса доставки. Когда ваше приложение предоставляет пользователю выбранный адрес доставки или вариант доставки, оно должно уведомлять продавца о любых изменениях адреса доставки или варианта и показывать пользователю обновленные платежные данные (предоставленные продавцом).

Чтобы уведомить продавца о новых изменениях, реализуйте интерфейс IPaymentDetailsUpdateServiceCallback и объявите его в файле AndroidManifest.xml с помощью фильтра намерений UPDATE_PAYMENT_DETAILS .

Сразу после вызова интента PAY , Chrome подключится к службе UPDATE_PAYMENT_DETAILS (если она существует) в том же пакете, что и интент PAY , и вызовет setPaymentDetailsUpdateService(service) , чтобы предоставить вашему платежному приложению конечную точку IPaymentDetailsUpdateService для уведомления об изменениях в способе оплаты пользователя, варианте доставки или адресе доставки.

Используйте packageManager.getPackagesForUid(Binder.getCallingUid()) при получении данных от межпроцессного взаимодействия (IPC), чтобы проверить, что приложение, вызвавшее намерение PAY , имеет то же имя пакета, что и приложение, вызвавшее методы IPaymentDetailsUpdateServiceCallback .

АИДЛ

Создайте два файла AIDL со следующим содержимым:

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

Услуга

Реализуйте службу IPaymentDetailsUpdateServiceCallback .

Котлин

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

Добавьте в файл AndroidManifest.xml ссылку на сервис IPaymentDetailsUpdateServiceCallback .

<service
    android:name=".SampleUpdatePaymentDetailsCallbackService"
    android:expor>ted=&<quot;true&quo>t;
    in<tent-filter
        action android:name="org.chromium.intent.action.>UPDAT<E_PAYMENT_DETA>I<LS"> /
    /intent-filter
/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
}

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

Уведомляет продавца об изменениях в выбранном пользователем способе оплаты. Пакет paymentHandlerMethodData содержит ключи methodName и необязательные details оба со строковыми значениями. Chrome проверит наличие непустого пакета с непустым значением methodName и отправит updatePaymentDetails с одним из следующих сообщений об ошибке, используя callback.updateWith если проверка не пройдена.

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

changeShippingOption

Уведомляет продавца об изменениях в выбранном пользователем варианте доставки. shippingOptionId должен быть идентификатором одного из указанных продавцом вариантов доставки. Chrome проверит наличие непустого значения shippingOptionId и отправит запрос updatePaymentDetails со следующим сообщением об ошибке, используя callback.updateWith если проверка не пройдена.

'Shipping option identifier required.'

changeShippingAddress

Уведомляет продавца об изменениях в предоставленном пользователем адресе доставки. Chrome проверит наличие непустого пакета shippingAddress с действительным countryCode и отправит updatePaymentDetails со следующим сообщением об ошибке, используя callback.updateWith , если проверка не пройдена.

'Payment app returned invalid shipping address in response.'

Сообщение об ошибке "Недопустимое состояние"

Если Chrome обнаружит недопустимое состояние при получении любого из запросов на изменение, он вызовет метод callback.updateWith с отредактированным пакетом updatePaymentDetails . Пакет будет содержать только ключ error с пометкой "Invalid state" . Примеры недопустимого состояния:

  • Когда Chrome все еще ожидает ответа от продавца на предыдущее изменение (например, на текущее событие изменения).
  • Идентификатор варианта доставки, предоставляемый платежным приложением, не относится ни к одному из вариантов доставки, указанных продавцом.

Получите обновленные платежные данные от продавца.

Котлин

override fun updateWith(updatedPaymentDetails: Bundle) {}

override fun paymentDetailsNotUpdated() {}

Java

@Override
public void updateWith(Bundle updatedPaymentDetails) {}

@Override
public void paymentDetailsNotUpdated() {}

updatedPaymentDetails — это пакет, эквивалентный словарю WebIDL PaymentRequestDetailsUpdate , и содержит следующие необязательные ключи:

  • total — набор, содержащий ключи currency и value , оба ключа имеют строковые значения.
  • shippingOptions — широкий выбор вариантов доставки посылок.
  • error — строка, содержащая общее сообщение об ошибке (например, когда changeShippingOption не предоставляет допустимый идентификатор варианта доставки).
  • stringifiedPaymentMethodErrors — строка JSON, представляющая ошибки проверки для способа оплаты.
  • addressErrors — пакет с необязательными ключами, идентичными адресу доставки и строковым значениям. Каждый ключ представляет собой ошибку проверки, связанную с соответствующей частью адреса доставки.
  • modifiers - массив объектов Bundle, каждый из которых содержит поля total и methodData , и все они также являются объектами Bundle.

Отсутствие ключа означает, что его значение не изменилось.