अपने Android पेमेंट ऐप्लिकेशन को वेब पेमेंट के साथ काम करने के लिए अडैप्ट करने का तरीका जानें. इससे, ग्राहकों को बेहतर यूज़र एक्सपीरियंस मिलता है.
पब्लिश किया गया: 5 मई, 2020, पिछली बार अपडेट किया गया: 27 मई, 2025
Payment Request API, वेब पर ब्राउज़र पर आधारित एक इंटरफ़ेस उपलब्ध कराता है. इसकी मदद से, उपयोगकर्ता पेमेंट की ज़रूरी जानकारी को पहले से ज़्यादा आसानी से डाल सकते हैं. एपीआई, प्लैटफ़ॉर्म के हिसाब से पेमेंट ऐप्लिकेशन भी चालू कर सकता है.
सिर्फ़ Android इंटेंट का इस्तेमाल करने की तुलना में, वेब पेमेंट की सुविधा से ब्राउज़र, सुरक्षा, और उपयोगकर्ता अनुभव के साथ बेहतर इंटिग्रेशन मिलता है:
- पेमेंट ऐप्लिकेशन को व्यापारी/कंपनी की वेबसाइट के संदर्भ में, मॉडल के तौर पर लॉन्च किया जाता है.
- इसे लागू करने से, आपके मौजूदा पेमेंट ऐप्लिकेशन को बेहतर बनाने में मदद मिलेगी. साथ ही, आपको अपने उपयोगकर्ताओं का फ़ायदा पाने में भी मदद मिलेगी.
- साइडलोडिंग को रोकने के लिए, पेमेंट ऐप्लिकेशन के हस्ताक्षर की जांच की जाती है.
- पेमेंट ऐप्लिकेशन में, पेमेंट के कई तरीके इस्तेमाल किए जा सकते हैं.
- क्रिप्टो करंसी, बैंक ट्रांसफ़र वगैरह जैसे पेमेंट के किसी भी तरीके को इंटिग्रेट किया जा सकता है. Android डिवाइसों पर मौजूद पेमेंट ऐप्लिकेशन, ऐसे तरीकों को भी इंटिग्रेट कर सकते हैं जिनके लिए डिवाइस पर मौजूद हार्डवेयर चिप का ऐक्सेस ज़रूरी होता है.
Android के पेमेंट ऐप्लिकेशन में वेब पेमेंट की सुविधा लागू करने के लिए, चार चरण पूरे करने होंगे:
- कारोबारियों या कंपनियों को अपना पेमेंट ऐप्लिकेशन दिखाएं.
- व्यापारी/कंपनी को बताएं कि ग्राहक के पास रजिस्टर किया गया कोई ऐसा पेमेंट कार्ड है या नहीं जिससे पेमेंट किया जा सकता है.
- ग्राहक को पेमेंट करने की अनुमति दें.
- कॉलर के हस्ताक्षर वाले सर्टिफ़िकेट की पुष्टि करें.
वेब पेमेंट की सुविधा को इस्तेमाल करते हुए देखने के लिए, android-web-payment के डेमो को देखें.
पहला चरण: व्यापारियों/कंपनियों को अपने पेमेंट ऐप्लिकेशन के बारे में बताना
पेमेंट का तरीका सेट अप करना में दिए गए निर्देशों के मुताबिक, वेब ऐप्लिकेशन मेनिफ़ेस्ट में related_applications
प्रॉपर्टी सेट करें.
कारोबारी या कंपनी को आपके पेमेंट ऐप्लिकेशन का इस्तेमाल करने के लिए, Payment Request API का इस्तेमाल करना होगा. साथ ही, पेमेंट के तरीके के आइडेंटिफ़ायर का इस्तेमाल करके, पेमेंट के उस तरीके के बारे में बताना होगा जिसका इस्तेमाल आपके ऐप्लिकेशन में किया जा सकता है.
अगर आपके पास पेमेंट के तरीके का ऐसा आइडेंटिफ़ायर है जो आपके पेमेंट ऐप्लिकेशन के लिए यूनीक है, तो आपके पास अपना पेमेंट के तरीके का मेनिफ़ेस्ट सेट अप करने का विकल्प है. इससे ब्राउज़र आपके ऐप्लिकेशन को खोज पाएंगे.
दूसरा चरण: व्यापारी/कंपनी को यह बताना कि ग्राहक के पास रजिस्टर किया गया कोई ऐसा पेमेंट कार्ड है जिससे पेमेंट किया जा सकता है
व्यापारी/कंपनी hasEnrolledInstrument()
को कॉल करके, यह पता कर सकती है कि ग्राहक पेमेंट कर सकता है या नहीं. इस क्वेरी का जवाब देने के लिए, IS_READY_TO_PAY
को Android सेवा के तौर पर लागू किया जा सकता है.
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
सेवा के लिए एपीआई, एआईडीएल में तय किया गया है. यहां दिए गए कॉन्टेंट के साथ दो AIDL
फ़ाइलें बनाएं:
org/chromium/IsReadyToPayServiceCallback.aidl
package org.chromium;
interface IsReadyToPayServiceCallback {
oneway void handleIsReadyToPay(boolean isReadyToPay);
}
org/chromium/IsReadyToPayService.aidl
package org.chromium;
import org.chromium.IsReadyToPayServiceCallback;
interface IsReadyToPayService {
oneway void isReadyToPay(IsReadyToPayServiceCallback callback, in Bundle parameters);
}
IsReadyToPayService
लागू करना
IsReadyToPayService
को लागू करने का सबसे आसान तरीका, यहां दिए गए उदाहरण में दिखाया गया है:
class SampleIsReadyToPayService : Service() {
private val binder = object : IsReadyToPayService.Stub() {
override fun isReadyToPay(callback: IsReadyToPayServiceCallback?, parameters: Bundle?) {
callback?.handleIsReadyToPay(true)
}
}
override fun onBind(intent: Intent?): IBinder? {
return binder
}
}
import org.chromium.IsReadyToPayService;
public class SampleIsReadyToPayService extends Service {
private final IsReadyToPayService.Stub mBinder =
new IsReadyToPayService.Stub() {
@Override
public void isReadyToPay(IsReadyToPayServiceCallback callback, Bundle parameters) {
if (callback != null) {
callback.handleIsReadyToPay(true);
}
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
जवाब
सेवा, handleIsReadyToPay(Boolean)
तरीके का इस्तेमाल करके अपना जवाब भेज सकती है.
callback?.handleIsReadyToPay(true)
if (callback != null) {
callback.handleIsReadyToPay(true);
}
अनुमति
Binder.getCallingUid()
का इस्तेमाल करके, यह देखा जा सकता है कि कॉल करने वाला कौन है. ध्यान दें कि आपको onBind
तरीके के बजाय, isReadyToPay
तरीके का इस्तेमाल करना होगा. ऐसा इसलिए, क्योंकि Android OS, सेवा कनेक्शन को कैश मेमोरी में सेव करके उसका फिर से इस्तेमाल कर सकता है. इससे onBind()
तरीका ट्रिगर नहीं होता.
override fun isReadyToPay(callback: IsReadyToPayServiceCallback?, parameters: Bundle?) {
try {
val untrustedPackageName = parameters?.getString("packageName")
val actualPackageNames = packageManager.getPackagesForUid(Binder.getCallingUid())
// ...
@Override
public void isReadyToPay(IsReadyToPayServiceCallback callback, Bundle parameters) {
try {
String untrustedPackageName = parameters != null
? parameters.getString("packageName")
: null;
String[] actualPackageNames = packageManager.getPackagesForUid(Binder.getCallingUid());
// ...
इंटर-प्रोसेस कम्यूनिकेशन (आईपीसी) कॉल मिलने पर, null
के इनपुट पैरामीटर हमेशा देखें. यह जानकारी खास तौर पर इसलिए ज़रूरी है, क्योंकि Android OS के अलग-अलग वर्शन या फ़ॉर्क, अनचाहे तरीके से काम कर सकते हैं. साथ ही, अगर इनका ध्यान नहीं रखा जाता है, तो गड़बड़ियां हो सकती हैं.
आम तौर पर, packageManager.getPackagesForUid()
एक एलिमेंट दिखाता है. हालांकि, आपके कोड को उस असामान्य स्थिति को भी मैनेज करना चाहिए जहां कॉलर कई पैकेज के नाम का इस्तेमाल करता है. इससे यह पक्का होता है कि आपका ऐप्लिकेशन बेहतर तरीके से काम करता रहे.
कॉल करने वाले के पैकेज पर सही हस्ताक्षर है या नहीं, इसकी पुष्टि करने के तरीके के बारे में जानने के लिए, कॉल करने वाले के हस्ताक्षर वाले सर्टिफ़िकेट की पुष्टि करना लेख पढ़ें.
पैरामीटर
parameters
बंडल को Chrome 139 में जोड़ा गया था. इसकी जांच हमेशा null
के साथ की जानी चाहिए.
parameters
बंडल में, सेवा को ये पैरामीटर भेजे जाते हैं:
packageName
methodNames
methodData
topLevelOrigin
paymentRequestOrigin
topLevelCertificateChain
packageName
को Chrome 138 में जोड़ा गया था. इस पैरामीटर की वैल्यू का इस्तेमाल करने से पहले, आपको Binder.getCallingUid()
के साथ इसकी पुष्टि करनी होगी. यह पुष्टि करना ज़रूरी है, क्योंकि parameters
बंडल पर कॉल करने वाले का पूरा कंट्रोल होता है, जबकि Binder.getCallingUid()
पर Android OS का कंट्रोल होता है.
topLevelCertificateChain
, वेबव्यू और ऐसी वेबसाइटों पर null
होता है जो आम तौर पर लोकल टेस्टिंग के लिए इस्तेमाल की जाती हैं. जैसे, http://localhost
.
तीसरा चरण: ग्राहक को पेमेंट करने की सुविधा देना
व्यापारी/कंपनी, पेमेंट ऐप्लिकेशन को लॉन्च करने के लिए show()
को कॉल करती है, ताकि ग्राहक पेमेंट कर सके. पेमेंट ऐप्लिकेशन को Android Intent PAY
का इस्तेमाल करके चालू किया जाता है. इसमें, इंटेंट पैरामीटर में लेन-देन की जानकारी होती है.
पेमेंट ऐप्लिकेशन, methodName
और details
के साथ जवाब देता है. ये पेमेंट ऐप्लिकेशन के हिसाब से होते हैं और ब्राउज़र के लिए साफ़ तौर पर नहीं दिखते. ब्राउज़र, JSON स्ट्रिंग को डिसइंटिग्रेट करके, व्यापारी/कंपनी/कारोबारी के लिए details
स्ट्रिंग को JavaScript डिक्शनरी में बदल देता है. हालांकि, वह इसकी पुष्टि नहीं करता. ब्राउज़र, details
में बदलाव नहीं करता. इस पैरामीटर की वैल्यू, सीधे व्यापारी/कंपनी/कारोबारी को भेजी जाती है.
AndroidManifest.xml
PAY
इंटेंट फ़िल्टर वाली गतिविधि में <meta-data>
टैग होना चाहिए. यह टैग, ऐप्लिकेशन के लिए पैसे चुकाने के डिफ़ॉल्ट तरीके के आइडेंटिफ़ायर की पहचान करता है.
पेमेंट के एक से ज़्यादा तरीकों का इस्तेमाल करने के लिए, <meta-data>
टैग के साथ <string-array>
संसाधन जोड़ें.
<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/chromium_payment_method_names" />
</activity>
android:resource
, स्ट्रिंग की सूची होनी चाहिए. इसमें मौजूद हर स्ट्रिंग, एचटीटीपीएस स्कीम वाला मान्य और एब्सोल्यूट यूआरएल होना चाहिए, जैसा कि यहां दिखाया गया है.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="chromium_payment_method_names">
<item>https://alicepay.com/put/optional/path/here</item>
<item>https://charliepay.com/put/optional/path/here</item>
</string-array>
</resources>
पैरामीटर
यहां दिए गए पैरामीटर, Intent
एक्सट्रा के तौर पर गतिविधि को पास किए जाते हैं:
methodNames
methodData
merchantName
topLevelOrigin
topLevelCertificateChain
paymentRequestOrigin
total
modifiers
paymentRequestId
paymentOptions
shippingOptions
val extras: Bundle? = getIntent()?.extras
Bundle extras = getIntent() != null ? getIntent().getExtras() : null;
methodNames
इस्तेमाल किए जा रहे तरीकों के नाम. एलिमेंट, methodData
डिक्शनरी में मौजूद कुंजियां होती हैं. पेमेंट ऐप्लिकेशन में ये तरीके काम करते हैं.
val methodNames: List<String>? = extras.getStringArrayList("methodNames")
List<String> methodNames = extras.getStringArrayList("methodNames");
methodData
हर methodNames
से methodData
तक की मैपिंग.
val methodData: Bundle? = extras.getBundle("methodData")
Bundle methodData = extras.getBundle("methodData");
merchantName
व्यापारी/कंपनी/कारोबारी के चेकआउट पेज (ब्राउज़र के टॉप-लेवल ब्राउज़िंग कॉन्टेक्स्ट) के <title>
एचटीएमएल टैग का कॉन्टेंट.
val merchantName: String? = extras.getString("merchantName")
String merchantName = extras.getString("merchantName");
topLevelOrigin
स्कीम के बिना व्यापारी/कंपनी/कारोबारी का ऑरिजिन (टॉप-लेवल ब्राउज़िंग कॉन्टेक्स्ट का स्कीम-लेस ऑरिजिन). उदाहरण के लिए, https://mystore.com/checkout
को mystore.com
के तौर पर पास किया जाता है.
val topLevelOrigin: String? = extras.getString("topLevelOrigin")
String topLevelOrigin = extras.getString("topLevelOrigin");
topLevelCertificateChain
व्यापारी/कंपनी/कारोबारी का सर्टिफ़िकेट चेन (टॉप-लेवल ब्राउज़िंग कॉन्टेक्स्ट का सर्टिफ़िकेट चेन). वेबव्यू, localhost या डिस्क पर मौजूद फ़ाइल के लिए वैल्यू null
होती है.
हर Parcelable
, certificate
बटन और बाइट कलेक्शन वैल्यू वाला एक बंडल होता है.
val topLevelCertificateChain: Array<Parcelable>? =
extras.getParcelableArray("topLevelCertificateChain")
val list: List<ByteArray>? = topLevelCertificateChain?.mapNotNull { p ->
(p as Bundle).getByteArray("certificate")
}
Parcelable[] topLevelCertificateChain =
extras.getParcelableArray("topLevelCertificateChain");
if (topLevelCertificateChain != null) {
for (Parcelable p : topLevelCertificateChain) {
if (p != null && p instanceof Bundle) {
((Bundle) p).getByteArray("certificate");
}
}
}
paymentRequestOrigin
iframe ब्राउज़िंग कॉन्टेक्स्ट का स्कीम-लेस ऑरिजिन, जिसने JavaScript में new
PaymentRequest(methodData, details, options)
कन्स्ट्रक्टर को ट्रिगर किया. अगर कॉन्स्ट्रक्टर को टॉप-लेवल कॉन्टेक्स्ट से शुरू किया गया था, तो इस पैरामीटर की वैल्यू, topLevelOrigin
पैरामीटर की वैल्यू के बराबर होती है.
val paymentRequestOrigin: String? = extras.getString("paymentRequestOrigin")
String paymentRequestOrigin = extras.getString("paymentRequestOrigin");
total
लेन-देन की कुल रकम दिखाने वाली JSON स्ट्रिंग.
val total: String? = extras.getString("total")
String total = extras.getString("total");
यहां स्ट्रिंग का एक उदाहरण दिया गया है:
{"currency":"USD","value":"25.00"}
modifiers
JSON.stringify(details.modifiers)
का आउटपुट, जहां details.modifiers
में सिर्फ़ supportedMethods
, data
, और total
शामिल हैं.
paymentRequestId
PaymentRequest.id
फ़ील्ड, जिसे "पुश-पेमेंट" ऐप्लिकेशन को लेन-देन की स्थिति से जोड़ना चाहिए. व्यापारी/कंपनी/कारोबारी की वेबसाइटें, इस फ़ील्ड का इस्तेमाल करके, "पुश-पेमेंट" ऐप्लिकेशन से लेन-देन की स्थिति के बारे में जानकारी हासिल करेंगी.
val paymentRequestId: String? = extras.getString("paymentRequestId")
String paymentRequestId = 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()
Intent result = new Intent();
Bundle extras = new Bundle();
extras.putString("methodName", "https://bobbucks.dev/pay");
extras.putString("details", "{\"token\": \"put-some-data-here\"}");
result.putExtras(extras);
setResult(Activity.RESULT_OK, result);
finish();
आपको दो पैरामीटर, इंटेंट एक्स्ट्रा के तौर पर बताने होंगे:
methodName
: इस्तेमाल किए जा रहे तरीके का नाम.details
: JSON स्ट्रिंग, जिसमें लेन-देन पूरा करने के लिए व्यापारी/कंपनी के लिए ज़रूरी जानकारी होती है. अगर सफलताtrue
है, तोdetails
को इस तरह से बनाया जाना चाहिए किJSON.parse(details)
सफल हो. अगर कोई ऐसा डेटा नहीं है जिसे दिखाना है, तो यह स्ट्रिंग"{}"
हो सकती है. इसे व्यापारी/कंपनी/कारोबारी की वेबसाइट को खाली JavaScript डिक्शनरी के तौर पर मिलेगा.
अगर पेमेंट ऐप्लिकेशन में लेन-देन पूरा नहीं हुआ है, तो RESULT_CANCELED
को पास किया जा सकता है. उदाहरण के लिए, अगर उपयोगकर्ता ने पेमेंट ऐप्लिकेशन में अपने खाते के लिए सही पिन कोड नहीं डाला है. ब्राउज़र, उपयोगकर्ता को कोई दूसरा पेमेंट ऐप्लिकेशन चुनने की अनुमति दे सकता है.
setResult(Activity.RESULT_CANCELED)
finish()
setResult(Activity.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
String caller = getCallingPackage();
आखिरी चरण में, कॉल करने वाले के हस्ताक्षर वाले सर्टिफ़िकेट की पुष्टि की जाती है. इससे यह पक्का किया जाता है कि कॉलिंग पैकेज में सही हस्ताक्षर है.
चौथा चरण: कॉल करने वाले व्यक्ति के हस्ताक्षर करने वाले सर्टिफ़िकेट की पुष्टि करना
कॉलर के पैकेज का नाम देखने के लिए, IS_READY_TO_PAY
में Binder.getCallingUid()
और PAY
में Activity.getCallingPackage()
पर क्लिक करें. यह पुष्टि करने के लिए कि कॉल करने वाला ब्राउज़र वही है जिसे आपको कॉल करना है, आपको उसके हस्ताक्षर वाले सर्टिफ़िकेट की जांच करनी चाहिए. साथ ही, यह पक्का करना चाहिए कि वह सही वैल्यू से मेल खाता हो.
अगर एपीआई लेवल 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
)
String packageName = … // The caller's package name
byte[] certificate = … // The correct signing certificate
boolean verified = packageManager.hasSigningCertificate(
callingPackage,
certificate,
PackageManager.CERT_INPUT_SHA256);
एक सर्टिफ़िकेट ब्राउज़र के लिए, PackageManager.hasSigningCertificate()
को प्राथमिकता दी जाती है, क्योंकि यह सर्टिफ़िकेट रोटेशन को सही तरीके से मैनेज करता है. (Chrome के पास एक सिंगल साइनिंग सर्टिफ़िकेट होता है.) जिन ऐप्लिकेशन के पास साइन करने के लिए एक से ज़्यादा सर्टिफ़िकेट हैं उनके लिए, सर्टिफ़िकेट बदलने की सुविधा का इस्तेमाल नहीं किया जा सकता.
अगर आपको एपीआई लेवल 27 और उससे पहले के वर्शन के साथ काम करना है या आपको कई साइनिंग सर्टिफ़िकेट वाले ब्राउज़र को मैनेज करना है, तो PackageManager.GET_SIGNATURES
का इस्तेमाल करें.
val packageName: String = … // The caller's package name
val expected: Set<String> = … // The correct set of signing certificates
val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
val sha256 = MessageDigest.getInstance("SHA-256")
val actual = packageInfo.signatures.map {
SerializeByteArrayToString(sha256.digest(it.toByteArray()))
}
val verified = actual.equals(expected)
String packageName = … // The caller's package name
Set<String> expected = … // The correct set of signing certificates
PackageInfo packageInfo =
packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
Set<String> actual = new HashSet<>();
for (Signature it : packageInfo.signatures) {
actual.add(SerializeByteArrayToString(sha256.digest(it.toByteArray())));
}
boolean verified = actual.equals(expected);
डीबग
गड़बड़ियों या जानकारी देने वाले मैसेज देखने के लिए, यह कमांड इस्तेमाल करें:
adb logcat | grep -i pay