Android 결제 앱을 업데이트하여 웹 결제 API에 배송지 주소와 결제자의 연락처 정보를 제공하는 방법
게시: 2020년 7월 17일, 최종 업데이트: 2025년 5월 27일
웹 양식을 통해 배송지 주소와 연락처 정보를 입력하는 것은 고객에게 번거로운 경험일 수 있습니다. 이로 인해 오류가 발생하고 전환율이 낮아질 수 있습니다.
그렇기 때문에 Payment Request API는 배송지 주소 및 연락처 정보를 요청하는 기능을 지원합니다. 이렇게 하면 다음과 같은 여러 이점이 있습니다.
- 사용자는 몇 번만 탭하면 올바른 주소를 선택할 수 있습니다.
- 주소는 항상 표준화된 형식으로 반환됩니다.
- 잘못된 주소를 제출할 가능성은 적습니다.
브라우저는 통합 결제 환경을 제공하기 위해 배송지 주소 및 연락처 정보 수집을 결제 앱으로 지연할 수 있습니다. 이 기능을 위임이라고 합니다.
Chrome은 가능하면 고객의 배송지 주소 및 연락처 정보 수집을 호출된 Android 결제 앱에 위임합니다. 위임을 통해 결제 중 발생하는 불편을 줄일 수 있습니다.
판매자 웹사이트는 고객이 선택한 배송지 주소와 배송 옵션에 따라 배송 옵션과 총 가격을 동적으로 업데이트할 수 있습니다.
기존 Android 결제 앱에 위임 지원을 추가하려면 다음 단계를 구현하세요.
지원되는 위임 선언
브라우저는 결제 앱에서 제공할 수 있는 추가 정보 목록을 알아야 해당 정보 수집을 앱에 위임할 수 있습니다. 지원되는 위임을 앱의 AndroidManifest.xml에서 <meta-data>
로 선언합니다.
<activity
android:name=".PaymentActivity"
…
<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" encoding="utf-8"?>
<resources>
<string-array name="chromium_payment_supported_delegations">
<item>payerEmail</item>
<item>shippingAddress</item>
</string-array>
</resources>
필수 결제 옵션의 PAY
인텐트 추가 항목 파싱
판매자는 paymentOptions
사전을 사용하여 추가 필수 정보를 지정할 수 있습니다. Chrome은 paymentOptions
인텐트 추가 항목을 PAY
활동에 전달하여 앱이 제공할 수 있는 필수 옵션 목록을 제공합니다.
paymentOptions
paymentOptions
는 앱에서 위임 지원을 선언한 판매자 지정 결제 옵션의 하위 집합입니다.
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")
자바
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"
일 수 있습니다. 앱은 사용자의 주소 또는 배송 옵션 선택을 요청할 때 UI에서 이 힌트를 사용할 수 있습니다.
shippingOptions
shippingOptions
는 판매자가 지정한 배송 옵션의 parcelable 배열입니다. 이 매개변수는 paymentOptions.requestShipping ==
true
인 경우에만 존재합니다.
Kotlin
val shippingOptions: List<ShippingOption>? =
extras.getParcelableArray("shippingOptions")?.mapNotNull {
p -> from(p as Bundle)
}
자바
Parcelable[] shippingOptions = extras.getParcelableArray("shippingOptions");
for (Parcelable it : shippingOptions) {
if (it != null && it instanceof Bundle) {
Bundle shippingOption = (Bundle) it;
}
}
각 배송 옵션은 다음 키가 있는 Bundle
입니다.
id
- 배송 옵션 식별자입니다.label
- 사용자에게 표시되는 배송 옵션 라벨입니다.amount
- 문자열 값이 있는currency
및value
키가 포함된 배송비 번들입니다.currency
는 배송비의 통화를 ISO4217의 올바른 형식의 3자리 알파벳 코드로 표시합니다.value
는 배송비 값을 유효한 십진수 금액 값으로 표시합니다.
selected
- 결제 앱에 배송 옵션이 표시될 때 배송 옵션을 선택해야 하는지 여부입니다.
selected
를 제외한 모든 키에는 문자열 값이 있습니다. selected
에는 불리언 값이 있습니다.
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)
자바
String id = bundle.getString("id");
String label = bundle.getString("label");
Bundle amount = bundle.getBundle("amount");
Boolean selected = bundle.getBoolean("selected", false);
결제 응답에 필수 정보 제공
앱은 PAY
활동에 대한 응답에 필요한 추가 정보를 포함해야 합니다.
이렇게 하려면 다음 매개변수를 인텐트 추가 항목으로 지정해야 합니다.
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은 부가 항목에서 필요한 추가 정보를 확인합니다. 유효성 검사에 실패하면 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".'
다음 코드 샘플은 유효한 응답의 예입니다.
Kotlin
fun Intent.populateRequestedPaymentOptions() {
if (requestPayerName) {
putExtra("payerName", "John Smith")
}
if (requestPayerPhone) {
putExtra("payerPhone", "5555555555")
}
if (requestPayerEmail) {
putExtra("payerEmail", "[email protected]")
}
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")
}
}
자바
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", "[email protected]");
}
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
인터페이스를 구현하고 UPDATE_PAYMENT_DETAILS
인텐트 필터로 AndroidManifest.xml
에 선언합니다.
PAY
인텐트를 호출한 직후 Chrome은 PAY
인텐트와 동일한 패키지에 있는 UPDATE_PAYMENT_DETAILS
서비스 (있는 경우)에 연결하고 setPaymentDetailsUpdateService(service)
를 호출하여 결제 앱에 IPaymentDetailsUpdateService
엔드포인트를 제공하여 사용자의 결제 수단, 배송 옵션 또는 배송지 주소 변경사항을 알립니다.
프로세스 간 통신 (IPC)을 수신할 때 packageManager.getPackagesForUid(Binder.getCallingUid())
를 사용하여 PAY
인텐트를 호출한 앱이 IPaymentDetailsUpdateServiceCallback
메서드를 호출한 앱과 패키지 이름이 동일한지 확인합니다.
AIDL
다음 콘텐츠로 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
서비스를 구현합니다.
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
}
}
자바
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:exported="true">
<intent-filter>
<action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
</intent-filter>
</service>
사용자가 선택한 결제 수단, 배송지 주소 또는 배송 옵션의 변경사항을 판매자에게 알립니다.
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
}
자바
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
를 사용하여 비어 있지 않은 번들을 확인하고 유효성 검사에 실패하면 callback.updateWith
를 통해 다음 오류 메시지 중 하나가 포함된 updatePaymentDetails
를 전송합니다.
'Method data required.'
'Method name required.'
changeShippingOption
사용자가 선택한 배송 옵션의 변경사항을 판매자에게 알립니다.
shippingOptionId
는 판매자가 지정한 배송 옵션 중 하나의 식별자여야 합니다. Chrome은 비어 있지 않은 shippingOptionId
를 확인하고 유효성 검사에 실패하면 callback.updateWith
를 통해 다음 오류 메시지가 포함된 updatePaymentDetails
를 전송합니다.
'Shipping option identifier required.'
changeShippingAddress
사용자가 제공한 배송지 주소 변경사항을 판매자에게 알립니다. Chrome은 유효한 countryCode
가 있는 비어 있지 않은 shippingAddress
번들을 확인하고 유효성 검사에 실패하면 callback.updateWith
를 통해 다음 오류 메시지가 포함된 updatePaymentDetails
를 전송합니다.
'Payment app returned invalid shipping address in response.'
잘못된 상태 오류 메시지
Chrome에서 변경 요청을 수신할 때 잘못된 상태가 발생하면 수정된 updatePaymentDetails
번들로 callback.updateWith
를 호출합니다. 번들에는 "Invalid state"
가 있는 error
키만 포함됩니다.
잘못된 상태의 예는 다음과 같습니다.
- Chrome이 이전 변경사항(예: 진행 중인 변경 이벤트)에 대한 판매자의 응답을 아직 기다리는 경우
- 결제 앱에서 제공한 배송 옵션 식별자가 판매자가 지정한 배송 옵션에 속하지 않습니다.
판매자로부터 업데이트된 결제 세부정보 수신
Kotlin
override fun updateWith(updatedPaymentDetails: Bundle) {}
override fun paymentDetailsNotUpdated() {}
자바
@Override
public void updateWith(Bundle updatedPaymentDetails) {}
@Override
public void paymentDetailsNotUpdated() {}
updatedPaymentDetails
는 PaymentRequestDetailsUpdate
WebIDL 사전과 동일한 번들이며 다음과 같은 선택적 키를 포함합니다.
total
-currency
및value
키가 포함된 번들로, 두 키 모두 문자열 값을 갖습니다.shippingOptions
- 배송 옵션의 parcelable 배열error
- 일반 오류 메시지가 포함된 문자열입니다 (예:changeShippingOption
가 유효한 배송 옵션 식별자를 제공하지 않는 경우).stringifiedPaymentMethodErrors
- 결제 수단의 유효성 검사 오류를 나타내는 JSON 문자열입니다.addressErrors
- 배송지 주소와 동일한 선택적 키와 문자열 값이 포함된 번들입니다. 각 키는 배송지 주소의 해당 부분과 관련된 유효성 검사 오류를 나타냅니다.modifiers
: 각각 번들인total
및methodData
필드가 있는 번들의 parcelable 배열입니다.
키가 없으면 값이 변경되지 않은 것입니다.