Android ödeme uygulamasından gönderim ve iletişim bilgileri sağlama

Android ödeme uygulamanızı, gönderim adresini ve ödeme yapan kullanıcının iletişim bilgilerini Web Payments API'lerine sağlayacak şekilde güncelleme.

Sahel Sharify
Sahel Sharify

Yayınlanma tarihi: 17 Temmuz 2020, Son güncelleme tarihi: 27 Mayıs 2025

Gönderim adresini ve iletişim bilgilerini bir web formu aracılığıyla girmek müşteriler için zahmetli bir deneyim olabilir. Bu durum hatalara ve dönüşüm oranının düşmesine neden olabilir.

Bu nedenle, Payment Request API'de gönderim adresi ve iletişim bilgileri isteme özelliği desteklenir. Bu durum birden fazla avantaj sağlar:

  • Kullanıcılar birkaç dokunuşla doğru adresi seçebilir.
  • Adres her zaman standartlaştırılmış biçimde döndürülür.
  • Yanlış adres gönderme olasılığı daha düşüktür.

Tarayıcılar, birleşik bir ödeme deneyimi sunmak için gönderim adresi ve iletişim bilgilerinin toplanmasını bir ödeme uygulamasına erteleyebilir. Bu işleve yetki verme adı verilir.

Mümkün olduğunda Chrome, müşterinin gönderim adresi ve iletişim bilgilerinin toplanmasını çağrılan Android ödeme uygulamasına devreder. Bu yetkilendirme, ödeme sırasındaki zorlukları azaltır.

Satıcının web sitesi, müşterinin gönderim adresi ve gönderim seçeneği tercihine bağlı olarak gönderim seçeneklerini ve toplam fiyatı dinamik olarak güncelleyebilir.

Kargo seçeneği ve kargo adresi değişikliği. Bu değişikliğin kargo seçeneklerini ve toplam fiyatı dinamik olarak nasıl etkilediğini görebilirsiniz.

Mevcut bir Android ödeme uygulamasına yetkilendirme desteği eklemek için aşağıdaki adımları uygulayın:

  1. Desteklenen yetkilendirmeleri beyan edin.
  2. Zorunlu ödeme seçenekleri için PAY intent ekstralarını ayrıştırın.
  3. Ödeme yanıtında gerekli bilgileri sağlayın.
  4. [İsteğe bağlı] Dinamik akışı destekleyin:
    1. Kullanıcı tarafından seçilen ödeme yöntemi, gönderim adresi veya kargo seçeneğindeki değişiklikleri satıcıya bildirin.
    2. Satıcıdan güncellenmiş ödeme ayrıntılarını alın (ör. seçilen kargo seçeneğinin maliyetine göre düzenlenmiş toplam tutar).

Desteklenen yetkilendirmeleri bildirme

Tarayıcının, bu bilgilerin toplanmasını uygulamanıza devredebilmek için ödeme uygulamanızın sağlayabileceği ek bilgilerin listesini bilmesi gerekir. Desteklenen yetkilendirmeleri uygulamanızın AndroidManifest.xml dosyasında <meta-data> olarak tanımlayın.

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

android:resource, aşağıdaki değerlerin tümünü veya bir alt kümesini içeren bir <string-array>'a işaret etmelidir:

  • payerName
  • payerEmail
  • payerPhone
  • shippingAddress

Aşağıdaki örnekte yalnızca gönderim adresi ve ödeme yapan kullanıcının e-posta adresi sağlanabilir.

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

Zorunlu ödeme seçenekleri için PAY intent ekstralarını ayrıştırma

Satıcı, paymentOptions sözlüğünü kullanarak gerekli ek bilgileri belirtebilir. Chrome, paymentOptions Intent ekstralarını PAY etkinliğine ileterek uygulamanızın sağlayabileceği gerekli seçeneklerin listesini sağlar.

paymentOptions

paymentOptions, uygulamanızın yetkilendirme desteğini beyan ettiği, satıcı tarafından belirtilen ödeme seçeneklerinin alt kümesidir.

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

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

Aşağıdaki parametreleri içerebilir:

  • requestPayerName: Ödemeyi yapanın adının gerekli olup olmadığını belirten boole değeri.
  • requestPayerPhone: Ödeyenin telefonunun gerekli olup olmadığını belirten boole değeri.
  • requestPayerEmail: Ödeyen kişinin e-posta adresinin gerekli olup olmadığını belirten boole değeri.
  • requestShipping: Gönderim bilgilerinin gerekli olup olmadığını belirten boole değeri.
  • shippingType: Gönderim türünü gösteren dize. Gönderim türü "shipping", "delivery" veya "pickup" olabilir. Uygulamanız, kullanıcının adresini veya kargo seçeneklerini sorarken kullanıcı arayüzünde bu ipucunu kullanabilir.

shippingOptions

shippingOptions, satıcı tarafından belirtilen kargo seçeneklerinin paketlenebilir dizisidir. Bu parametre yalnızca paymentOptions.requestShipping == true olduğunda mevcut olur.

Kotlin

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

Java

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

Her kargo seçeneği, aşağıdaki anahtarlara sahip bir Bundle öğesidir.

  • id: Gönderim seçeneği tanımlayıcısı.
  • label: Kullanıcıya gösterilen kargo seçeneği etiketi.
  • amount: Dize değerlerine sahip currency ve value anahtarlarını içeren kargo maliyeti paketi.
  • selected: Ödeme uygulaması kargo seçeneklerini gösterdiğinde kargo seçeneğinin seçilip seçilmeyeceği.

selected dışındaki tüm anahtarların dize değerleri vardır. selected bir boole değerine sahip.

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)

Java

String id = bundle.getString("id");
String label = bundle.getString("label");
Bundle amount = bundle.getBundle("amount");
Boolean selected = bundle.getBoolean("selected", false);

Ödeme yanıtında gerekli bilgileri sağlama

Uygulamanız, PAY etkinliğine verdiği yanıtta gerekli ek bilgileri içermelidir.

Bunun için aşağıdaki parametreler intent ekstraları olarak belirtilmelidir:

  • payerName: Ödemeyi yapanın tam adı. paymentOptions.requestPayerName doğru olduğunda bu, boş olmayan bir dize olmalıdır.
  • payerPhone: Ödeyenin telefon numarası. paymentOptions.requestPayerPhone doğru olduğunda bu, boş olmayan bir dize olmalıdır.
  • payerEmail: Ödeyenin e-posta adresi. paymentOptions.requestPayerEmail doğru olduğunda bu, boş olmayan bir dize olmalıdır.
  • shippingAddress: Kullanıcı tarafından sağlanan gönderim adresi. paymentOptions.requestShipping doğru olduğunda bu, boş olmayan bir paket olmalıdır. Pakette, fiziksel adresteki farklı bölümleri temsil eden aşağıdaki anahtarlar bulunmalıdır.
    • countryCode
    • postalCode
    • sortingCode
    • region
    • city
    • dependentLocality
    • addressLine
    • organization
    • recipient
    • phone addressLine dışındaki tüm anahtarların dize değerleri vardır. addressLine, bir dizi dizedir.
  • shippingOptionId: Kullanıcı tarafından seçilen gönderim seçeneğinin tanımlayıcısıdır. paymentOptions.requestShipping doğru olduğunda bu dize boş olmamalıdır.

Ödeme yanıtını doğrulama

Çağrılan ödeme uygulamasından alınan bir ödeme yanıtının etkinlik sonucu RESULT_OK olarak ayarlanırsa Chrome, ekstralarında gerekli ek bilgileri kontrol eder. Doğrulama başarısız olursa Chrome, request.show()'ten reddedilmiş bir söz döndürür ve geliştiricilere yönelik aşağıdaki hata mesajlarından birini gösterir:

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

Aşağıdaki kod örneği, geçerli bir yanıt örneğidir:

Kotlin

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

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

İsteğe bağlı: Dinamik akışı destekleme

Bazen bir işlemin toplam maliyeti artar. Örneğin, kullanıcı hızlı kargo seçeneğini tercih ettiğinde veya uluslararası bir kargo adresi seçtiğinde mevcut kargo seçeneklerinin listesi ya da fiyatları değiştiğinde bu durum yaşanabilir. Uygulamanız, kullanıcı tarafından seçilen gönderim adresini veya seçeneğini sağladığında satıcıyı gönderim adresi ya da seçenek değişiklikleri hakkında bilgilendirebilmeli ve kullanıcıya güncellenmiş ödeme ayrıntılarını (satıcı tarafından sağlanır) gösterebilmelidir.

Satıcıyı yeni değişiklikler hakkında bilgilendirmek için IPaymentDetailsUpdateServiceCallback arayüzünü uygulayın ve UPDATE_PAYMENT_DETAILS intent filtresiyle AndroidManifest.xml içinde tanımlayın.

Chrome, PAY intent'i çağırdıktan hemen sonra PAY intent ile aynı paketteki UPDATE_PAYMENT_DETAILS hizmetine (varsa) bağlanır ve ödeme uygulamanıza kullanıcının ödeme yöntemi, gönderim seçeneği veya gönderim adresindeki değişiklikler hakkında bildirimde bulunmak için IPaymentDetailsUpdateService uç noktasını sağlamak üzere setPaymentDetailsUpdateService(service)'yi çağırır.

PAY intent'ini çağıran uygulamanın, IPaymentDetailsUpdateServiceCallback yöntemlerini çağıran uygulamayla aynı paket adına sahip olduğunu doğrulamak için packageManager.getPackagesForUid(Binder.getCallingUid())'ü kullanın.

AIDL

Aşağıdaki içeriğe sahip iki AIDL dosyası oluşturun:

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

Hizmet

IPaymentDetailsUpdateServiceCallback hizmetini uygulayın.

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

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 için hizmeti AndroidManifest.xml'inizde açığa çıkarın.IPaymentDetailsUpdateServiceCallback

<service
    android:name=".SampleUpdatePaymentDetailsCallbackService"
    android:exported="true">
    <intent-filter>
        <action android:name="org.chromium.intent.action.UPDATE_PAYMENT_DETAILS" />
    </intent-filter>
</service>

Kullanıcının seçtiği ödeme yöntemi, gönderim adresi veya kargo seçeneğindeki değişiklikler hakkında satıcıyı bilgilendirme

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
}

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

Satıcıyı, kullanıcı tarafından seçilen ödeme yöntemindeki değişiklikler hakkında bilgilendirir. paymentHandlerMethodData paketi, hem dize değerlerine sahip methodName hem de isteğe bağlı details anahtarları içerir. Chrome, boş olmayan bir methodName içeren boş olmayan bir paket olup olmadığını kontrol eder ve doğrulama başarısız olursa callback.updateWith üzerinden aşağıdaki hata mesajlarından birini içeren bir updatePaymentDetails gönderir.

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

changeShippingOption

Satıcıyı, kullanıcı tarafından seçilen gönderim seçeneğinde yapılan değişiklikler hakkında bilgilendirir. shippingOptionId, satıcı tarafından belirtilen gönderim seçeneklerinden birinin tanımlayıcısıdır. Chrome, boş olmayan bir shippingOptionId olup olmadığını kontrol eder ve doğrulama başarısız olursa callback.updateWith üzerinden aşağıdaki hata mesajını içeren bir updatePaymentDetails gönderir.

'Shipping option identifier required.'

changeShippingAddress

Satıcıyı, kullanıcı tarafından sağlanan gönderim adresindeki değişiklikler hakkında bilgilendirir. Chrome, geçerli bir countryCode içeren boş olmayan bir shippingAddress paketi olup olmadığını kontrol eder ve doğrulama başarısız olursa callback.updateWith üzerinden aşağıdaki hata mesajını içeren bir updatePaymentDetails gönderir.

'Payment app returned invalid shipping address in response.'

Geçersiz durum hatası mesajı

Chrome, değişiklik isteklerinden herhangi birini aldıktan sonra geçersiz bir durumla karşılaşırsa çıkartılmış bir updatePaymentDetails paketiyle callback.updateWith'ü çağırır. Pakette yalnızca "Invalid state" ile error anahtarı bulunur. Geçersiz durum örnekleri:

  • Chrome, satıcının önceki bir değişikliğe verdiği yanıtı (ör. devam eden bir değişiklik etkinliği) hâlâ bekliyorsa.
  • Ödeme uygulaması tarafından sağlanan gönderim seçeneği tanımlayıcısı, satıcı tarafından belirtilen gönderim seçeneklerinden hiçbirine ait değil.

Satıcıdan güncellenmiş ödeme ayrıntılarını alma

Kotlin

override fun updateWith(updatedPaymentDetails: Bundle) {}

override fun paymentDetailsNotUpdated() {}

Java

@Override
public void updateWith(Bundle updatedPaymentDetails) {}

@Override
public void paymentDetailsNotUpdated() {}

updatedPaymentDetails, PaymentRequestDetailsUpdate WebIDL sözlüğüne eşdeğer pakettir ve aşağıdaki isteğe bağlı anahtarları içerir:

  • total: currency ve value anahtarlarını içeren bir paket. Her iki anahtarın da dize değerleri vardır.
  • shippingOptions: Gönderim seçenekleri'nin paketlenebilir dizisi
  • error: Genel bir hata mesajı içeren bir dize (ör. changeShippingOption geçerli bir gönderim seçeneği tanımlayıcısı sağlamadığında)
  • stringifiedPaymentMethodErrors: Ödeme yöntemiyle ilgili doğrulama hatalarını temsil eden bir JSON dizesi
  • addressErrors: Gönderim adresi ve dize değerleriyle aynı olan isteğe bağlı anahtarları içeren bir paket. Her anahtar, gönderim adresinin ilgili kısmıyla ilgili bir doğrulama hatasını temsil eder.
  • modifiers: Her biri bir total ve methodData alanına (ayrıca paket) sahip olan, paketlerden oluşan ve paket olarak bölünebilir bir dizi.

Anahtar yoksa değeri değişmemiştir.