অ্যান্ড্রয়েড পেমেন্ট অ্যাপ ডেভেলপার গাইড

ওয়েব পেমেন্টের সাথে কাজ করার জন্য আপনার Android পেমেন্ট অ্যাপটিকে কীভাবে মানিয়ে নিতে হয় এবং গ্রাহকদের জন্য আরও ভাল ব্যবহারকারীর অভিজ্ঞতা প্রদান করতে হয় তা জানুন।

পেমেন্ট রিকোয়েস্ট API ওয়েবে একটি অন্তর্নির্মিত ব্রাউজার-ভিত্তিক ইন্টারফেস নিয়ে আসে যা ব্যবহারকারীদের প্রয়োজনীয় অর্থপ্রদানের তথ্য আগের চেয়ে সহজে প্রবেশ করতে দেয়। এপিআই প্ল্যাটফর্ম-নির্দিষ্ট অর্থপ্রদানের অ্যাপ্লিকেশনগুলিকেও আহ্বান করতে পারে।

ব্রাউজার সমর্থন

  • ক্রোম: ৬০।
  • প্রান্ত: 15।
  • ফায়ারফক্স: একটি পতাকার পিছনে।
  • সাফারি: 11.1।

উৎস

প্ল্যাটফর্ম-নির্দিষ্ট Google Pay অ্যাপের সাথে চেকআউট প্রবাহ যা ওয়েব পেমেন্ট ব্যবহার করে।

শুধুমাত্র অ্যান্ড্রয়েড ইন্টেন্ট ব্যবহার করার তুলনায়, ওয়েব পেমেন্ট ব্রাউজার, নিরাপত্তা এবং ব্যবহারকারীর অভিজ্ঞতার সাথে আরও ভাল একীকরণের অনুমতি দেয়:

  • পেমেন্ট অ্যাপটি বণিক ওয়েবসাইটের পরিপ্রেক্ষিতে একটি মডেল হিসেবে চালু করা হয়েছে।
  • বাস্তবায়ন আপনার বিদ্যমান পেমেন্ট অ্যাপের পরিপূরক, যা আপনাকে আপনার ব্যবহারকারী বেসের সুবিধা নিতে সক্ষম করে।
  • সাইডলোডিং এড়াতে পেমেন্ট অ্যাপের স্বাক্ষর চেক করা হয়।
  • পেমেন্ট অ্যাপ একাধিক পেমেন্ট পদ্ধতি সমর্থন করতে পারে।
  • যেকোনো অর্থপ্রদানের পদ্ধতি, যেমন ক্রিপ্টোকারেন্সি, ব্যাঙ্ক ট্রান্সফার এবং আরও অনেক কিছু একত্রিত করা যেতে পারে। অ্যান্ড্রয়েড ডিভাইসে অর্থপ্রদানের অ্যাপ্লিকেশনগুলি এমনকি এমন পদ্ধতিগুলিকে একীভূত করতে পারে যেগুলির জন্য ডিভাইসে হার্ডওয়্যার চিপে অ্যাক্সেস প্রয়োজন৷

একটি অ্যান্ড্রয়েড পেমেন্ট অ্যাপে ওয়েব পেমেন্ট বাস্তবায়ন করতে চারটি ধাপ লাগে:

  1. ব্যবসায়ীদের আপনার পেমেন্ট অ্যাপ আবিষ্কার করতে দিন।
  2. একজন বণিককে জানান যে একজন গ্রাহকের কাছে একটি নথিভুক্ত যন্ত্র (যেমন ক্রেডিট কার্ড) আছে যা অর্থপ্রদানের জন্য প্রস্তুত।
  3. একজন গ্রাহককে অর্থপ্রদান করতে দিন।
  4. কলারের স্বাক্ষরকারী শংসাপত্র যাচাই করুন।

ওয়েব পেমেন্টগুলি কার্যকর দেখতে, অ্যান্ড্রয়েড-ওয়েব-পেমেন্ট ডেমো দেখুন।

ধাপ 1: ব্যবসায়ীদের আপনার পেমেন্ট অ্যাপ আবিষ্কার করতে দিন

একজন বণিক আপনার অর্থপ্রদানের অ্যাপ ব্যবহার করার জন্য, তাদের অর্থপ্রদানের অনুরোধ API ব্যবহার করতে হবে এবং অর্থপ্রদানের পদ্ধতি শনাক্তকারী ব্যবহার করে আপনি যে অর্থপ্রদানের পদ্ধতি সমর্থন করেন তা নির্দিষ্ট করতে হবে।

আপনার যদি একটি পেমেন্ট পদ্ধতি শনাক্তকারী থাকে যা আপনার পেমেন্ট অ্যাপের জন্য অনন্য, আপনি আপনার নিজস্ব অর্থপ্রদানের পদ্ধতি মেনিফেস্ট সেট আপ করতে পারেন যাতে ব্রাউজারগুলি আপনার অ্যাপটি আবিষ্কার করতে পারে।

ধাপ 2: একজন বণিককে জানান যে একজন গ্রাহকের একটি নথিভুক্ত যন্ত্র আছে যা অর্থ প্রদানের জন্য প্রস্তুত

গ্রাহক পেমেন্ট করতে সক্ষম কিনা তা জানতে ব্যবসায়ী hasEnrolledInstrument() কল করতে পারেন। আপনি এই প্রশ্নের উত্তর দিতে একটি Android পরিষেবা হিসাবে IS_READY_TO_PAY প্রয়োগ করতে পারেন৷

AndroidManifest.xml

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 পরিষেবা ঐচ্ছিক। পেমেন্ট অ্যাপে যদি এমন কোনও উদ্দেশ্য হ্যান্ডলার না থাকে, তাহলে ওয়েব ব্রাউজার অনুমান করে যে অ্যাপটি সর্বদা অর্থপ্রদান করতে পারে।

এআইডিএল

IS_READY_TO_PAY পরিষেবার API AIDL-এ সংজ্ঞায়িত করা হয়েছে। নিম্নলিখিত বিষয়বস্তু সহ দুটি AIDL ফাইল তৈরি করুন:

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 বাস্তবায়ন করা হচ্ছে

IsReadyToPayService এর সহজতম বাস্তবায়ন নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

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

প্রতিক্রিয়া

পরিষেবাটি handleIsReadyToPay(Boolean) পদ্ধতির মাধ্যমে তার প্রতিক্রিয়া পাঠাতে পারে।

callback?.handleIsReadyToPay(true)

অনুমতি

কলকারী কে তা পরীক্ষা করতে আপনি Binder.getCallingUid() ব্যবহার করতে পারেন। মনে রাখবেন যে আপনাকে এটি isReadyToPay পদ্ধতিতে করতে হবে, onBind পদ্ধতিতে নয়।

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

কলিং প্যাকেজে সঠিক স্বাক্ষর আছে কিনা তা যাচাই করার বিষয়ে কলারের স্বাক্ষর করার শংসাপত্র যাচাই করুন দেখুন।

ধাপ 3: একজন গ্রাহককে অর্থপ্রদান করতে দিন

পেমেন্ট অ্যাপ চালু করতে মার্চেন্ট কল show() যাতে গ্রাহক পেমেন্ট করতে পারেন। অর্থপ্রদানের অ্যাপটি অভিপ্রায়ের প্যারামিটারে লেনদেনের তথ্য সহ একটি অ্যান্ড্রয়েড ইন্টেন্ট PAY মাধ্যমে আহ্বান করা হয়েছে।

অর্থপ্রদান অ্যাপটি methodName এবং details সহ প্রতিক্রিয়া জানায়, যা পেমেন্ট অ্যাপ নির্দিষ্ট এবং ব্রাউজারে অস্বচ্ছ। ব্রাউজারটি JSON ডিসিরিয়ালাইজেশনের মাধ্যমে বণিকের জন্য একটি জাভাস্ক্রিপ্ট অবজেক্টে details স্ট্রিংকে রূপান্তর করে, কিন্তু এর বাইরে কোনো বৈধতা প্রয়োগ করে না। ব্রাউজার details পরিবর্তন করে না; সেই প্যারামিটারের মান সরাসরি বণিকের কাছে পাঠানো হয়।

AndroidManifest.xml

PAY অভিপ্রায় ফিল্টারের সাথে কার্যকলাপে একটি <meta-data> ট্যাগ থাকা উচিত যা অ্যাপটির জন্য ডিফল্ট অর্থপ্রদানের পদ্ধতি শনাক্তকারীকে চিহ্নিত করে

একাধিক অর্থপ্রদানের পদ্ধতি সমর্থন করতে, একটি <string-array> সংস্থান সহ একটি <meta-data> ট্যাগ যোগ করুন।

<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 অবশ্যই স্ট্রিংগুলির একটি তালিকা হতে হবে, যার প্রতিটি একটি বৈধ, পরম URL হতে হবে একটি HTTPS স্কিম সহ এখানে দেখানো হয়েছে৷

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

পরামিতি

নিম্নলিখিত পরামিতিগুলিকে উদ্দেশ্য অতিরিক্ত হিসাবে কার্যকলাপে প্রেরণ করা হয়:

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

পদ্ধতির নাম

ব্যবহৃত পদ্ধতির নাম। উপাদানগুলি methodData অভিধানের কী। পেমেন্ট অ্যাপ সমর্থন করে এই পদ্ধতিগুলি।

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

methodData

প্রতিটি methodNames থেকে methodData ডেটাতে একটি ম্যাপিং।

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

ব্যবসায়ীর নাম

বণিকের চেকআউট পৃষ্ঠার <title> HTML ট্যাগের বিষয়বস্তু (ব্রাউজারের শীর্ষ-স্তরের ব্রাউজিং প্রসঙ্গ)।

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

topLevelOrigin

স্কিম ছাড়াই বণিকের উৎপত্তি (টপ-লেভেল ব্রাউজিং প্রসঙ্গের স্কিম-লেস অরিজিন)। উদাহরণস্বরূপ, https://mystore.com/checkout mystore.com হিসাবে পাস করা হয়েছে।

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

topLevelCertificateChain

ব্যবসায়ীর শংসাপত্রের চেইন (শীর্ষ-স্তরের ব্রাউজিং প্রসঙ্গের শংসাপত্রের চেইন)। লোকালহোস্ট এবং ডিস্কে ফাইলের জন্য নাল, যেটি SSL সার্টিফিকেট ছাড়াই সুরক্ষিত প্রসঙ্গ। প্রতিটি Parcelable হল একটি certificate কী এবং একটি বাইট অ্যারে মান সহ একটি বান্ডিল।

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

paymentRequestOrigin

আইফ্রেম ব্রাউজিং প্রসঙ্গের স্কিম-লেস মূল যা JavaScript-এ new PaymentRequest(methodData, details, options) কনস্ট্রাক্টরকে আমন্ত্রণ জানিয়েছে। যদি কনস্ট্রাক্টরকে শীর্ষ-স্তরের প্রসঙ্গ থেকে আহ্বান করা হয়, তাহলে এই প্যারামিটারের মান topLevelOrigin প্যারামিটারের মানের সমান।

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

total

JSON স্ট্রিং লেনদেনের মোট পরিমাণ প্রতিনিধিত্ব করে।

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

এখানে স্ট্রিং এর একটি উদাহরণ বিষয়বস্তু আছে:

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

modifiers

JSON.stringify(details.modifiers) এর আউটপুট, যেখানে details.modifiers শুধুমাত্র supportedMethods এবং total ধারণ করে।

paymentRequestId

PaymentRequest.id ক্ষেত্র যা "পুশ-পেমেন্ট" অ্যাপগুলিকে লেনদেনের অবস্থার সাথে যুক্ত করা উচিত। বণিক ওয়েবসাইটগুলি ব্যান্ডের বাইরে লেনদেনের অবস্থার জন্য "পুশ-পেমেন্ট" অ্যাপগুলি জিজ্ঞাসা করতে এই ক্ষেত্রটি ব্যবহার করবে৷

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

প্রতিক্রিয়া

কার্যকলাপটি RESULT_OK এর সাথে setResult মাধ্যমে তার প্রতিক্রিয়া ফেরত পাঠাতে পারে।

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

আপনাকে অভিপ্রায় অতিরিক্ত হিসাবে দুটি পরামিতি নির্দিষ্ট করতে হবে:

  • methodName : যে পদ্ধতিটি ব্যবহার করা হচ্ছে তার নাম।
  • details : লেনদেন সম্পূর্ণ করার জন্য বণিকের জন্য প্রয়োজনীয় তথ্য ধারণকারী JSON স্ট্রিং। যদি সফলতা true হয়, তাহলে details এমনভাবে তৈরি করতে হবে যাতে JSON.parse(details) সফল হয়৷

আপনি RESULT_CANCELED পাস করতে পারেন যদি পেমেন্ট অ্যাপে লেনদেন সম্পূর্ণ না হয়, উদাহরণস্বরূপ, ব্যবহারকারী যদি পেমেন্ট অ্যাপে তাদের অ্যাকাউন্টের জন্য সঠিক পিন কোড টাইপ করতে ব্যর্থ হন। ব্রাউজার ব্যবহারকারীকে একটি ভিন্ন অর্থপ্রদানের অ্যাপ বেছে নিতে দিতে পারে।

setResult(RESULT_CANCELED)
finish()

যদি আমন্ত্রিত অর্থপ্রদান অ্যাপ থেকে প্রাপ্ত একটি অর্থপ্রদানের প্রতিক্রিয়ার কার্যকলাপের ফলাফল RESULT_OK তে সেট করা হয়, তাহলে Chrome তার অতিরিক্তগুলিতে অ-খালি methodName এবং details পরীক্ষা করবে৷ বৈধতা ব্যর্থ হলে Chrome request.show() থেকে একটি প্রত্যাখ্যান করা প্রতিশ্রুতি ফিরিয়ে দেবে এবং নিম্নলিখিত বিকাশকারীগুলির মধ্যে একটি ত্রুটি বার্তার সম্মুখীন হবে:

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

অনুমতি

কার্যকলাপটি তার getCallingPackage() পদ্ধতির মাধ্যমে কলকারীকে পরীক্ষা করতে পারে।

val caller: String? = callingPackage

কলিং প্যাকেজে সঠিক স্বাক্ষর আছে কিনা তা নিশ্চিত করতে কলারের স্বাক্ষর করার শংসাপত্র যাচাই করা চূড়ান্ত পদক্ষেপ।

ধাপ 4: কলার স্বাক্ষরকারী শংসাপত্র যাচাই করুন

আপনি IS_READY_TO_PAYBinder.getCallingUid() দিয়ে এবং PAY তে Activity.getCallingPackage() দিয়ে কলারের প্যাকেজের নাম পরীক্ষা করতে পারেন। কলারটি যে ব্রাউজারটি আপনার মনে আছে তা সত্যই যাচাই করার জন্য, আপনাকে এটির স্বাক্ষর শংসাপত্রটি পরীক্ষা করা উচিত এবং নিশ্চিত করা উচিত যে এটি সঠিক মানের সাথে মেলে।

আপনি যদি API লেভেল 28 এবং তার উপরে টার্গেট করে থাকেন এবং এমন একটি ব্রাউজারের সাথে একীভূত হন যার একটি একক স্বাক্ষর শংসাপত্র আছে, আপনি 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
)

PackageManager.hasSigningCertificate() একক শংসাপত্র ব্রাউজারগুলির জন্য পছন্দ করা হয়, কারণ এটি সঠিকভাবে শংসাপত্র ঘূর্ণন পরিচালনা করে। (Chrome-এর একটি একক স্বাক্ষর শংসাপত্র রয়েছে।) যে অ্যাপগুলির একাধিক স্বাক্ষর শংসাপত্র রয়েছে সেগুলিকে ঘোরাতে পারে না৷

আপনি যদি 27 এবং তার নীচের পুরানো API স্তরগুলিকে সমর্থন করতে চান, বা একাধিক সাইনিং শংসাপত্র সহ ব্রাউজারগুলি পরিচালনা করতে চান তবে আপনি 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) } }