Android 결제 앱의 배송 및 연락처 정보 제공

Web Payments API로 배송지 주소와 결제자의 연락처 정보를 제공하도록 Android 결제 앱을 업데이트하는 방법

Sahel Sharify
Sahel Sharify

웹 양식을 통해 배송지 주소와 연락처 정보를 입력하는 것은 번거로운 경험을 갖게 될 것입니다. 오류가 발생하고 전환율이 낮아질 수 있습니다. 있습니다.

이러한 이유로 Payment Request API는 배송 요청 기능을 지원합니다. 주소 및 연락처 정보가 필요합니다. 이렇게 하면 다음과 같은 여러 이점이 있습니다.

  • 사용자는 탭 몇 번으로 올바른 주소를 선택할 수 있습니다.
  • 주소는 항상 표준화된 형식을 참고하세요.
  • 잘못된 주소를 제출할 경우

브라우저는 배송지 주소 및 연락처 정보 수집을 통합 결제 환경을 제공하는 결제 앱입니다. 이 기능은 위임이라고 합니다.

가능한 경우 Chrome은 항상 고객의 배송 상품 수금을 위임합니다. 호출된 Android 결제 앱으로 전송합니다. 이 위임은 결제 과정의 불편함을 줄여줍니다.

판매자 웹사이트에서 배송 옵션과 총가격을 동적으로 업데이트할 수 있습니다. 고객이 선택한 배송지 주소와 배송지에 따라 옵션을 선택합니다.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
배송 옵션 및 배송지 주소 변경 실제 사례 배송비 옵션 및 총가격에 동적으로 미치는 영향을 확인합니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.
를 통해 개인정보처리방침을 정의할 수 있습니다.

기존 Android 결제 앱에 위임 지원을 추가하려면 다음 단계를 따르세요. 다음 단계를 구현합니다.

  1. 지원되는 위임을 선언합니다.
  2. 필수 결제에 대한 PAY 인텐트 추가 항목 파싱 옵션을 선택합니다.
  3. 결제 시 필수 정보 입력 응답을 참조하세요.
  4. [선택사항] 동적 흐름 지원: <ph type="x-smartling-placeholder">
      </ph>
    1. 사용자가 선택한 결제 수단의 변경사항에 관해 판매자에게 알립니다. 배송지 주소 또는 배송지 주소 옵션을 사용합니다.
    2. 판매자로부터 업데이트된 결제 세부정보 (예: 선택한 배송 옵션의 비용)을 입력합니다.

지원되는 위임 선언

브라우저에서는 결제에 사용되는 추가 정보 목록을 해당 정보를 사용자의 앱 이용자에게 있습니다. 지원되는 위임을 앱의<meta-data> AndroidManifest.xml

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

<resource>는 다음 유효한 값에서 선택된 문자열 목록이어야 합니다.

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

다음 예시에서는 배송지 주소와 결제자의 이메일만 제공할 수 있습니다. 있습니다.

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

필수 결제 옵션의 PAY 인텐트 추가 항목 파싱

판매자는 paymentOptions 드림 있습니다. Chrome은 앱이 사용 가능한 필수 옵션 목록을 제공합니다. 다음 매개변수를 PAY 활동에 인텐트로 전달하여 제공합니다. extras를 제공합니다.

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

여기에는 다음 매개변수가 포함될 수 있습니다.

  • requestPayerName - 결제자의 이름이 있는지 여부를 나타내는 불리언입니다. 은(는) 필수입니다.
  • requestPayerPhone - 결제자의 전화 여부를 나타내는 불리언입니다. 은(는) 필수입니다.
  • requestPayerEmail - 결제자의 이메일 여부를 나타내는 불리언입니다. 은(는) 필수입니다.
  • requestShipping - 배송 정보 여부를 나타내는 불리언입니다. 은(는) 필수입니다.
  • shippingType - 배송 유형을 나타내는 문자열입니다. 배송 유형은 다음과 같습니다. "shipping", "delivery" 또는 "pickup"입니다. 앱에서 이 힌트를 사용할 수 있는 사용자의 주소 또는 배송 옵션 선택을 요청하는 UI

shippingOptions

shippingOptions는 판매자 지정 배송의 parcelable 배열입니다. 있습니다. 이 매개변수는 paymentOptions.requestShipping == true인 경우에만 존재합니다.

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

각 배송 옵션은 다음 키가 포함된 Bundle입니다.

  • id - 배송 옵션 식별자입니다.
  • label - 사용자에게 표시되는 배송물 옵션 라벨입니다.
  • amount - currencyvalue 키가 포함된 배송비 번들: 문자열 값입니다.
  • 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)

결제 응답에 필수 정보 제공

앱은 다음과 같은 질문에 대한 응답에 필수 추가 정보를 포함해야 합니다. PAY 활동

이를 위해서는 다음 매개변수를 인텐트 추가 항목으로 지정해야 합니다.

  • payerName - 지급인의 전체 이름 다음과 같은 경우 비어 있지 않은 문자열이어야 합니다. paymentOptions.requestPayerName이(가) true입니다.
  • payerPhone - 결제자의 전화번호입니다. 다음과 같은 경우 비어 있지 않은 문자열이어야 합니다. paymentOptions.requestPayerPhone이(가) true입니다.
  • payerEmail - 결제자의 이메일 주소입니다. 비어 있지 않은 문자열이어야 합니다. paymentOptions.requestPayerEmail가 true일 때
  • shippingAddress - 사용자가 제공한 배송지 주소입니다. 이름은 paymentOptions.requestShipping가 true인 경우 비어 있지 않은 번들입니다. 번들 물리적 서비스의 여러 부분을 나타내는 다음 키가 있어야 합니다. 주소를 입력합니다.
    • city
    • countryCode
    • dependentLocality
    • organization
    • phone
    • postalCode
    • recipient
    • region
    • sortingCode
    • addressLine addressLine 이외의 모든 키는 문자열 값을 갖습니다. addressLine 는 문자열의 배열입니다.
  • shippingOptionId - 사용자가 선택한 배송 옵션의 식별자입니다. 이 paymentOptions.requestShipping가 true인 경우 비어 있지 않은 문자열이어야 합니다.

결제 응답 확인

호출된 결제로부터 결제 응답의 활동 결과가 수신된 경우 앱이 RESULT_OK로 설정된 경우 Chrome에서 정보를 볼 수 있습니다. 확인에 실패하면 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", "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")
    }
}

선택사항: 동적 흐름 지원

사용자가 거래를 성사시키는 경우처럼 사용자가 거래하는 빠른 배송 옵션을 선택하거나 사용 가능한 배송 목록이 사용자가 해외 배송을 선택할 때 옵션 또는 가격이 변경됩니다. 있습니다. 앱이 사용자가 선택한 배송지 주소 또는 옵션을 제공하는 경우 판매자에게 배송지 주소나 옵션에 대해 알릴 수 있어야 합니다. 변경사항을 적용한 후 업데이트된 결제 세부정보를 판매자).

AIDL

판매자에게 새로운 변경사항을 알리려면 PaymentDetailsUpdateService를 사용하세요. 서비스를 선언할 수 있습니다. 이 서비스를 사용하려면 두 개의 다음 콘텐츠가 포함된 AIDL 파일입니다.

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

사용자가 선택한 결제 수단, 배송지 주소 또는 배송 옵션의 변경사항에 대해 판매자에게 알립니다.

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

서비스의 시작 인텐트에 사용되는 callingPackageName에는 다음 중 하나가 있을 수 있습니다. 지불을 시작한 브라우저에 따라 다음 값이 달라질 수 있습니다. 합니다.

Chrome 채널 패키지 이름
정식 "com.android.chrome"
베타 "com.chrome.beta"
개발 "com.chrome.dev"
카나리아 "com.chrome.canary"
Chromium "org.chromium.chrome"
Google 빠른 검색창 (WebLayer 삽입기) "com.google.android.googlequicksearchbox"

changePaymentMethod

사용자가 선택한 결제 수단의 변경사항을 판매자에게 알립니다. 이 paymentHandlerMethodData 번들에 methodNamedetails(선택사항)이 포함되어 있습니다. 모두 문자열 값이 있는 키입니다. Chrome은 비어 있지 않은 methodName를 만들고 다음 중 하나와 함께 updatePaymentDetails를 전송합니다. 유효성 검사에 실패하면 callback.updateWith를 통해 다음 오류 메시지가 표시됩니다.

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

changeShippingOption

사용자가 선택한 배송 옵션의 변경사항을 판매자에게 알립니다. shippingOptionId는 판매자가 지정한 중 하나의 식별자여야 합니다. 배송 옵션 Chrome은 비어 있지 않은 shippingOptionId를 확인하고 다음을 통해 updatePaymentDetails와 함께 다음 오류 메시지가 표시됨 유효성 검사에 실패하면 callback.updateWith입니다.

'Shipping option identifier required.'

changeShippingAddress

사용자가 제공한 배송지 주소의 변경사항을 판매자에게 알립니다. 크롬 유효한 countryCode가 포함된 비어 있지 않은 shippingAddress 번들을 확인합니다. 다음을 통해 다음 오류 메시지와 함께 updatePaymentDetails를 전송합니다. 검증이 실패하면 callback.updateWith입니다.

'Payment app returned invalid shipping address in response.'

잘못된 상태 오류 메시지

변경 요청 수신 시 Chrome에 잘못된 상태가 표시되는 경우 수정된 updatePaymentDetailscallback.updateWith를 호출합니다. 번들을 선택합니다. 번들에는 "Invalid state"error 키만 포함됩니다. 잘못된 상태의 예는 다음과 같습니다.

  • Chrome에서 이전 변경사항에 대한 판매자의 응답을 기다리고 있는 경우 진행 중인 변경 이벤트 등).
  • 결제 앱에서 제공하는 배송 옵션 식별자가 다음 중 어디에도 속하지 않습니다. 판매자가 지정한 배송 옵션입니다.

판매자로부터 업데이트된 결제 세부정보 받기

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

updatePaymentDetailsPaymentRequestDetailsUpdate WebIDL 사전( modifiers 필드)를 포함하고 다음과 같은 선택적 키를 포함합니다.

  • total - currencyvalue 키가 포함된 번들입니다. 두 키 모두 문자열 값
  • shippingOptions - shipping의 parcelable 배열 옵션
  • error - 일반 오류 메시지가 포함된 문자열입니다 (예: changeShippingOption에서 올바른 배송 옵션 식별자를 제공하지 않음)
  • stringifiedPaymentMethodErrors - 검증을 나타내는 JSON 문자열 결제 수단 오류
  • addressErrors - 배송과 동일한 선택적 키가 포함된 번들 address 및 string 값으로 사용됩니다. 각 키는 해당 키와 관련된 유효성 검사 오류를 나타냅니다. 배송되지 않습니다.

키가 없다는 것은 값이 변경되지 않았음을 의미합니다.