Android ödeme uygulaması geliştiricileri kılavuzu

Android ödeme uygulamanızı Web Ödemeleri ile çalışacak şekilde nasıl uyarlayacağınızı ve müşterilere daha iyi bir kullanıcı deneyimi nasıl sunacağınızı öğrenin.

Payment Request API, web, kullanıcıların gereken ödeme tutarını girmelerine olanak tanıyan yerleşik bir tarayıcı tabanlı arayüzdür. hiç olmadığı kadar kolay hale geldi. API, platforma özel ödeme yöntemini de çağırabilir.

Tarayıcı Desteği

  • Chrome: 60..
  • Kenar: 15..
  • Firefox: Bir bayrağın arkasında.
  • Safari: 11.1.

Kaynak

Web ödemelerini kullanan platforma özel Google Pay uygulamasıyla ödeme akışı.

Web Ödemeleri, yalnızca Android Intent'leri kullanmaya kıyasla daha iyi entegrasyon sağlar tarayıcı, güvenlik ve kullanıcı deneyimi ile:

  • Ödeme uygulaması, satıcının web sitesi bağlamında kalıcı olarak kullanıma sunulur.
  • Bu uygulama, mevcut ödeme uygulamanıza ek olarak gelir elde etmenizi sağlar. yararlanabilmeniz için çok iyi bir fırsattır.
  • Bu sorunu önlemek için ödeme uygulamasının imzası kontrol edilir. başka cihazdan yükleme.
  • Ödeme uygulamaları birden fazla ödeme yöntemini destekleyebilir.
  • Kripto para ve banka havalesi gibi tüm ödeme yöntemleri entegre edilmiştir. Android cihazlardaki ödeme uygulamaları cihazdaki donanım çipine erişmesi gerekir.
ziyaret edin.

Bir Android ödeme uygulamasında Web Ödemeleri'ni uygulamak için dört adım gerekir:

  1. Satıcıların ödeme uygulamanızı keşfetmesine izin verin.
  2. Müşterinin kayıtlı bir aracını (ör. kredi) satıcıya bildirin kartı) ödeme yapabilirsiniz.
  3. Müşterinin ödeme yapmasına izin verin.
  4. Arayanın imza sertifikasını doğrulayın.

Web Ödemelerinin işleyiş şeklini görmek için şu sayfaya göz atın: android-web-payment demomuz var.

1. Adım: Satıcıların ödeme uygulamanızı keşfetmesine izin verin

Bir satıcının ödeme uygulamanızı kullanabilmesi için Ödeme Request API ve ödeme yöntemini kullanarak desteklediğiniz ödeme yöntemini belirtin tanımlayıcı'yı kullanabilirsiniz.

Ödeme uygulamanıza özgü bir ödeme yöntemi tanımlayıcınız varsa kendi ödeme yönteminizi ayarlayabilirsiniz manifesto'yu indirin. uygulamanızı keşfedin.

2. Adım: Müşterinin ödeme yapmaya hazır bir kayıtlı aracının olup olmadığını satıcıya bildirin

Satıcı, müşterinin müşterininhasEnrolledInstrument() ödeme yapabiliyor olması gerekir. Şunları yapabilirsiniz: Bu sorguyu yanıtlamak için IS_READY_TO_PAY uygulamasını Android hizmeti olarak uygulayın.

AndroidManifest.xml

Hizmetinizi intent filtresiyle bildirin org.chromium.intent.action.IS_READY_TO_PAY

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

IS_READY_TO_PAY hizmeti isteğe bağlıdır. Android'de böyle bir intent işleyici yoksa ödeme uygulaması söz konusu olduğunda, web tarayıcısı uygulamanın her zaman ödeme.

AIDL

IS_READY_TO_PAY hizmetinin API'si AIDL'de tanımlanmıştır. İki AIDL oluşturun şu içeriğe sahip dosyaları:

app/src/main/aidl/org/chromium/IsReadyToPayServiceCallback.aidl

package org.chromium;
interface IsReadyToPayServiceCallback {
    oneway void handleIsReadyToPay(boolean isReadyToPay);
}

app/src/main/aidl/org/chromium/IsReadyToPayService.aidl

package org.chromium;
import org.chromium.IsReadyToPayServiceCallback;

interface IsReadyToPayService {
    oneway void isReadyToPay(IsReadyToPayServiceCallback callback);
}

IsReadyToPayService kullanımı

IsReadyToPayService etiketinin en basit uygulaması aşağıda gösterilmiştir örnek:

class SampleIsReadyToPayService : Service() {
  private val binder = object : IsReadyToPayService.Stub() {
    override fun isReadyToPay(callback: IsReadyToPayServiceCallback?) {
      callback?.handleIsReadyToPay(true)
    }
  }

  override fun onBind(intent: Intent?): IBinder? {
    return binder
  }
}

Yanıt

Hizmet, yanıtını handleIsReadyToPay(Boolean) yöntemiyle gönderebilir.

callback?.handleIsReadyToPay(true)

İzin

Arayanın kim olduğunu kontrol etmek için Binder.getCallingUid() hizmetini kullanabilirsiniz. Lütfen bunu onBind yönteminde değil, isReadyToPay yönteminde yapmanız gerekir.

override fun isReadyToPay(callback: IsReadyToPayServiceCallback?) {
  try {
    val callingPackage = packageManager.getNameForUid(Binder.getCallingUid())
    // …

Nasıl yapıldığını öğrenmek için Arayanın imzalama sertifikasını doğrulama başlıklı makaleye göz atın. .

3. Adım: Müşterinin ödeme yapmasına izin verin

Satıcı, ödemeyi başlatmak için show() adlı satıcıyı arar uygulama Böylece müşterinin ödeme yapmasını sağlayabilirsiniz. Ödeme uygulaması Android üzerinden çağrılır intent parametrelerinde işlem bilgileriyle PAY.

Ödeme uygulaması, ödeme uygulaması olan methodName ve details ile yanıt veriyor. ve tarayıcı için opak olmalıdır. Tarayıcı, details öğesini dönüştürür dizeyi, JSON seri dışı hale getirme aracılığıyla satıcı için bir JavaScript nesnesine yazar, ancak bunun dışında herhangi bir geçerliliği yoktur. Tarayıcı, details; bu parametrenin değeri doğrudan satıcıya aktarılır.

AndroidManifest.xml

PAY intent filtresine sahip etkinlikte, <meta-data> birincil ödeme yöntemi tanımlayıcısını uygulamasını indirin.

Birden fazla ödeme yöntemini desteklemek için<meta-data> <string-array> kaynak.

<activity
  android:name=".PaymentActivity"
  android:theme="@style/Theme.SamplePay.Dialog">
  <intent-filter>
    <action android:name="org.chromium.intent.action.PAY" />
  </intent-filter>

  <meta-data
    android:name="org.chromium.default_payment_method_name"
    android:value="https://bobbucks.dev/pay" />
  <meta-data
    android:name="org.chromium.payment_method_names"
    android:resource="@array/method_names" />
</activity>

resource, her biri geçerli bir dize olmak üzere dizelerin listesi olmalıdır. Burada gösterildiği gibi bir HTTPS şemasına sahip mutlak URL'niz olmalıdır.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="method_names">
        <item>https://alicepay.com/put/optional/path/here</item>
        <item>https://charliepay.com/put/optional/path/here</item>
    </string-array>
</resources>

Parametreler

Aşağıdaki parametreler etkinliğe Intent ekstraları olarak aktarılır:

  • methodNames
  • methodData
  • topLevelOrigin
  • topLevelCertificateChain
  • paymentRequestOrigin
  • total
  • modifiers
  • paymentRequestId
val extras: Bundle? = intent?.extras

methodNames

Kullanılan yöntemlerin adları. Öğeler, methodData sözlüğü. Bunlar, ödeme uygulamasının desteklediği yöntemlerdir.

val methodNames: List<String>? = extras.getStringArrayList("methodNames")

methodData

Her bir methodNames öğesinden, methodData

val methodData: Bundle? = extras.getBundle("methodData")

merchantName

Satıcının ödeme sayfasındaki <title> HTML etiketinin içeriği tarayıcının üst düzey göz atma bağlamı).

val merchantName: String? = extras.getString("merchantName")

topLevelOrigin

Satıcının şema içermeyen kökeni ( göz atma bağlamı). Örneğin, https://mystore.com/checkout mystore.com olarak geçti.

val topLevelOrigin: String? = extras.getString("topLevelOrigin")

topLevelCertificateChain

Satıcının sertifika zinciri (Üst düzey sertifika zincirinin sertifika zinciri) göz atma bağlamı). Güvenli olan localhost ve diskteki dosya için null bağlamları SSL sertifikasız. Her Parcelable bir Pakettir: certificate anahtarı ve bir bayt dizisi değeri.

val topLevelCertificateChain: Array<Parcelable>? =
    extras.getParcelableArray("topLevelCertificateChain")
val list: List<ByteArray>? = topLevelCertificateChain?.mapNotNull { p ->
  (p as Bundle).getByteArray("certificate")
}

paymentRequestOrigin

JavaScript'te new PaymentRequest(methodData, details, options) oluşturucuyu çağıran iframe göz atma bağlamının şemasız kaynağı. Öğe oluşturucu üst düzey bağlamdan çağrılmıştır; ardından bu çağrının değeri parametresi, topLevelOrigin parametresinin değerine eşit.

val paymentRequestOrigin: String? = extras.getString("paymentRequestOrigin")

total

İşlemin toplam tutarını temsil eden JSON dizesi.

val total: String? = extras.getString("total")

Aşağıda, dizenin örnek bir içeriği belirtilmiştir:

{"currency":"USD","value":"25.00"}

modifiers

details.modifiers olan JSON.stringify(details.modifiers) çıkışı yalnızca supportedMethods ve total içerir.

paymentRequestId

"push-payment" işlemi yapılan PaymentRequest.id alanı şununla ilişkilendirilmesi gerekir: işlem durumu. Satıcı web siteleri, &quot;push-payment&quot; uygulamaların bant dışı durumunu kontrol edin.

val paymentRequestId: String? = extras.getString("paymentRequestId")

Yanıt

Etkinlik, RESULT_OK üzerinden setResult üzerinden yanıtını geri gönderebilir.

setResult(Activity.RESULT_OK, Intent().apply {
  putExtra("methodName", "https://bobbucks.dev/pay")
  putExtra("details", "{\"token\": \"put-some-data-here\"}")
})
finish()

Intent ekstraları olarak iki parametre belirtmeniz gerekir:

  • methodName: Kullanılan yöntemin adı.
  • details: Satıcının şunları yapması için gerekli bilgileri içeren JSON dizesi: tamamlanması gerekir. Başarı true ise details olmalıdır öylesine yapılandırılmıştır ki JSON.parse(details) başarılı olacaktır.

İşlemRESULT_CANCELED ödeme uygulaması (örneğin, kullanıcı e-posta adresi için doğru PIN kodunu ödeme uygulamasında kullanabilir. Tarayıcı, kullanıcının başka bir ödeme uygulaması.

setResult(RESULT_CANCELED)
finish()

Çağrılan ödemeden alınan bir ödeme yanıtının etkinlik sonucu uygulama RESULT_OK olarak ayarlanırsa Chrome, boş olmayan methodName ve Ekstra özellikleri details. Doğrulama başarısız olursa Chrome reddedilen bir uyarı döndürür. aşağıdaki geliştiriciden kaynaklanan hatadan biriyle ilgili söz (request.show()) mesajlar:

'Payment app returned invalid response. Missing field "details".'
'Payment app returned invalid response. Missing field "methodName".'

İzin

Etkinlik, arayanı getCallingPackage() yöntemiyle kontrol edebilir.

val caller: String? = callingPackage

Son adım, arayanın imza sertifikasını doğrulamak için arayanın imza sertifikasının doğru imzaya sahip olduğundan emin olun.

4. Adım: Arayanın imza sertifikasını doğrulayın

Arayanın paket adını Binder.getCallingUid() ile kontrol edebilirsiniz: IS_READY_TO_PAY ve Activity.getCallingPackage() ile PAY içinde. Bu amaçla arayanın aklınızdaki tarayıcı olduğunu doğruladığınızda, imzalama sertifikasını kontrol edin ve sertifikanın doğru sertifikayla eşleştiğinden emin olun değer.

API düzeyi 28 ve üstünü hedefliyorsanız ve bir tarayıcıyla entegrasyon yapıyorsanız varsa tek bir imzalama sertifikası varsa PackageManager.hasSigningCertificate()

val packageName: String =  // The caller's package name
val certificate: ByteArray =  // The correct signing certificate.
val verified = packageManager.hasSigningCertificate(
  callingPackage,
  certificate,
  PackageManager.CERT_INPUT_SHA256
)

Tek sertifika için PackageManager.hasSigningCertificate() tercih edilir çünkü sertifika rotasyonunu doğru şekilde işler. (Chrome'un bir tek imzalı sertifika.) Birden fazla imzalama sertifikası olan uygulamalar döndürebilirsiniz.

27 ve önceki eski API düzeylerini desteklemeniz gerekiyorsa veya birden fazla imzalama sertifikası bulunan tarayıcılarda PackageManager.GET_SIGNATURES

val packageName: String =  // The caller's package name
val certificates: Set<ByteArray> =  // The correct set of signing certificates

val packageInfo = getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
val sha256 = MessageDigest.getInstance("SHA-256")
val signatures = packageInfo.signatures.map { sha256.digest(it.toByteArray()) }
val verified = signatures.size == certificates.size &&
    signatures.all { s -> certificates.any { it.contentEquals(s) } }