Android पेमेंट ऐप्लिकेशन डेवलपर गाइड

जानें कि अपने Android पेमेंट ऐप्लिकेशन को वेब पेमेंट के साथ काम करने के लिए कैसे अडॉप्ट किया जाए. साथ ही, ग्राहकों को बेहतर उपयोगकर्ता अनुभव कैसे दिया जाए.

पब्लिश होने की तारीख: 5 मई, 2020, पिछली बार अपडेट किए जाने की तारीख: 27 मई, 2025

Payment Request API, वेब पर ब्राउज़र आधारित एक ऐसा इंटरफ़ेस उपलब्ध कराता है जो पहले से मौजूद होता है. इससे लोग, पेमेंट की ज़रूरी जानकारी को पहले से ज़्यादा आसानी से डाल पाते हैं. एपीआई, प्लैटफ़ॉर्म के हिसाब से पेमेंट करने वाले ऐप्लिकेशन भी चालू कर सकता है.

Browser Support

  • Chrome: 60.
  • Edge: 15.
  • Firefox: behind a flag.
  • Safari: 11.1.

Source

वेब पेमेंट्स का इस्तेमाल करने वाले, प्लैटफ़ॉर्म के हिसाब से Google Pay ऐप्लिकेशन के साथ चेकआउट फ़्लो.

सिर्फ़ Android Intent का इस्तेमाल करने के बजाय, वेब पेमेंट की सुविधा का इस्तेमाल करने से ब्राउज़र, सुरक्षा, और उपयोगकर्ता अनुभव के साथ बेहतर इंटिग्रेशन किया जा सकता है:

  • पेमेंट ऐप्लिकेशन को कारोबारी या कंपनी की वेबसाइट के कॉन्टेक्स्ट में, मोडल के तौर पर लॉन्च किया जाता है.
  • इसे आपके मौजूदा पेमेंट ऐप्लिकेशन के साथ लागू किया जाता है. इससे आपको अपने उपयोगकर्ता आधार का फ़ायदा मिलता है.
  • पेमेंट ऐप्लिकेशन के हस्ताक्षर की जांच की जाती है, ताकि साइडलोडिंग को रोका जा सके.
  • पेमेंट ऐप्लिकेशन में, पेमेंट के कई तरीके इस्तेमाल किए जा सकते हैं.
  • इसमें पेमेंट के किसी भी तरीके को इंटिग्रेट किया जा सकता है. जैसे, क्रिप्टोकरेंसी, बैंक ट्रांसफ़र वगैरह. Android डिवाइसों पर मौजूद पेमेंट ऐप्लिकेशन, ऐसे तरीके भी इंटिग्रेट कर सकते हैं जिनके लिए डिवाइस पर मौजूद हार्डवेयर चिप को ऐक्सेस करने की ज़रूरत होती है.

Android पेमेंट ऐप्लिकेशन में Web Payments को लागू करने के लिए, ये चार चरण पूरे करने होते हैं:

  1. कारोबारियों या कंपनियों को आपके पेमेंट ऐप्लिकेशन के बारे में पता चलने दें.
  2. कारोबारी या कंपनी को यह जानकारी देना कि किसी खरीदार ने पेमेंट के लिए रजिस्टर किया हुआ कोई इंस्ट्रूमेंट (जैसे कि क्रेडिट कार्ड) इस्तेमाल किया है.
  3. किसी ग्राहक को पेमेंट करने की अनुमति दें.
  4. कॉल करने वाले व्यक्ति के हस्ताक्षर वाले सर्टिफ़िकेट की पुष्टि करें.

Web Payments को ऐक्शन में देखने के लिए, android-web-payment डेमो देखें.

पहला चरण: कारोबारियों या कंपनियों को आपके पेमेंट ऐप्लिकेशन के बारे में जानकारी देना

पेमेंट का तरीका सेट अप करना में दिए गए निर्देशों के मुताबिक, वेब ऐप्लिकेशन मेनिफ़ेस्ट में related_applications प्रॉपर्टी सेट करें.

अगर किसी कारोबारी या कंपनी को आपके पेमेंट ऐप्लिकेशन का इस्तेमाल करना है, तो उसे Payment Request API का इस्तेमाल करना होगा. साथ ही, payment method identifier का इस्तेमाल करके, पेमेंट के उस तरीके के बारे में बताना होगा जिसे आपका ऐप्लिकेशन स्वीकार करता है.

अगर आपके पास पेमेंट के तरीके का ऐसा आइडेंटिफ़ायर है जो आपके पेमेंट ऐप्लिकेशन के लिए यूनीक है, तो पेमेंट के तरीके का मेनिफ़ेस्ट सेट अप किया जा सकता है. इससे ब्राउज़र आपके ऐप्लिकेशन को ढूंढ पाएंगे.

दूसरा चरण: कारोबारी या कंपनी को यह बताना कि ग्राहक के पास रजिस्टर किया गया ऐसा इंस्ट्रुमेंट है जिससे पेमेंट किया जा सकता है

कारोबारी या कंपनी, 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 सेवा के लिए एपीआई को एआईडीएल में तय किया गया है. नीचे दिए गए कॉन्टेंट के साथ दो 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 को लागू करने का सबसे आसान तरीका यहां दिए गए उदाहरण में दिखाया गया है:

Kotlin

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

Java

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) तरीके का इस्तेमाल करके अपना जवाब भेज सकती है.

Kotlin

callback?.handleIsReadyToPay(true)

Java

if (callback != null) {
    callback.handleIsReadyToPay(true);
}

अनुमति

Binder.getCallingUid() का इस्तेमाल करके, यह पता लगाया जा सकता है कि कॉलर कौन है. ध्यान दें कि आपको यह काम isReadyToPay तरीके में करना होगा, न कि onBind तरीके में. ऐसा इसलिए, क्योंकि Android OS, सेवा कनेक्शन को कैश मेमोरी में सेव कर सकता है और उसका फिर से इस्तेमाल कर सकता है. इससे onBind() तरीका ट्रिगर नहीं होता है.

Kotlin

override fun isReadyToPay(callback: IsReadyToPayServiceCallback?, parameters: Bundle?) {
    try {
        val untrustedPackageName = parameters?.getString("packageName")
        val actualPackageNames = packageManager.getPackagesForUid(Binder.getCallingUid())
        // ...

Java

@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 इंटेंट PAY का इस्तेमाल करके शुरू किया जाता है. इसमें लेन-देन की जानकारी, इंटेंट पैरामीटर में होती है.

पेमेंट ऐप्लिकेशन, methodName और details के साथ जवाब देता है. ये पेमेंट ऐप्लिकेशन के लिए खास होते हैं और ब्राउज़र के लिए अपारदर्शी होते हैं. ब्राउज़र, कारोबारी या कंपनी के लिए detailsस्ट्रिंग को JSON स्ट्रिंग डीसीरियलाइज़ेशन का इस्तेमाल करके 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

Kotlin

val extras: Bundle? = getIntent()?.extras

Java

Bundle extras = getIntent() != null ? getIntent().getExtras() : null;

methodNames

इस्तेमाल किए जा रहे तरीकों के नाम. ये एलिमेंट, methodData डिक्शनरी में मौजूद कुंजियां हैं. ये पेमेंट के वे तरीके हैं जिनका इस्तेमाल पेमेंट ऐप्लिकेशन में किया जा सकता है.

Kotlin

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

Java

List<String> methodNames = extras.getStringArrayList("methodNames");

methodData

methodNames में से हर एक को methodData में मैप किया गया है.

Kotlin

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

Java

Bundle methodData = extras.getBundle("methodData");

merchantName

कारोबारी या कंपनी के चेकआउट पेज के <title> एचटीएमएल टैग का कॉन्टेंट (ब्राउज़र का टॉप-लेवल ब्राउज़िंग कॉन्टेक्स्ट).

Kotlin

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

Java

String merchantName = extras.getString("merchantName");

topLevelOrigin

कारोबारी या कंपनी का ऑरिजिन, जिसमें स्कीम शामिल नहीं है (टॉप-लेवल ब्राउज़िंग कॉन्टेक्स्ट का स्कीम-लेस ऑरिजिन). उदाहरण के लिए, https://mystore.com/checkout को mystore.com के तौर पर पास किया जाता है.

Kotlin

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

Java

String topLevelOrigin = extras.getString("topLevelOrigin");

topLevelCertificateChain

कारोबारी या कंपनी की सर्टिफ़िकेट चेन (टॉप-लेवल ब्राउज़िंग कॉन्टेक्स्ट की सर्टिफ़िकेट चेन). यह वैल्यू, वेबव्यू, लोकलहोस्ट या डिस्क पर मौजूद किसी फ़ाइल के लिए null होती है. हर Parcelable, certificate कुंजी और बाइट ऐरे वैल्यू वाला बंडल होता है.

Kotlin

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

Java

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 पैरामीटर की वैल्यू के बराबर होती है.

Kotlin

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

Java

String paymentRequestOrigin = extras.getString("paymentRequestOrigin");

total

लेन-देन की कुल रकम दिखाने वाली JSON स्ट्रिंग.

Kotlin

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

Java

String total = extras.getString("total");

यहां स्ट्रिंग के कॉन्टेंट का एक उदाहरण दिया गया है:

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

modifiers

JSON.stringify(details.modifiers) का आउटपुट, जहां details.modifiers में सिर्फ़ supportedMethods, data, और total शामिल हैं.

paymentRequestId

PaymentRequest.id फ़ील्ड, जिसे "पुश-पेमेंट" ऐप्लिकेशन को लेन-देन की स्थिति से जोड़ना चाहिए. कारोबारी या कंपनी की वेबसाइटें, इस फ़ील्ड का इस्तेमाल "पुश-पेमेंट" ऐप्लिकेशन से लेन-देन की स्थिति के बारे में क्वेरी करने के लिए करेंगी.

Kotlin

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

Java

String paymentRequestId = extras.getString("paymentRequestId");

जवाब

गतिविधि, RESULT_OK के साथ setResult के ज़रिए अपना जवाब वापस भेज सकती है.

Kotlin

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

Java

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 स्ट्रिंग है. इसमें कारोबारी या कंपनी को लेन-देन पूरा करने के लिए ज़रूरी जानकारी होती है. अगर success true है, तो details को इस तरह से बनाया जाना चाहिए कि JSON.parse(details) पूरा हो जाए. अगर कोई ऐसा डेटा नहीं है जिसे वापस भेजना है, तो इस स्ट्रिंग को "{}" के तौर पर सेट किया जा सकता है. कारोबारी या कंपनी की वेबसाइट को यह खाली JavaScript डिक्शनरी के तौर पर मिलेगी.

अगर उपयोगकर्ता, पेमेंट ऐप्लिकेशन में लेन-देन रद्द करता है, तो RESULT_CANCELED पास किया जा सकता है. ऐसा करने पर, request.show() अस्वीकार कर दिया जाएगा और कारोबारी या कंपनी की वेबसाइट पर AbortError दिखेगा. इससे पता चलेगा कि उपयोगकर्ता ने लेन-देन रद्द कर दिया है.

Kotlin

setResult(Activity.RESULT_CANCELED)
finish()

Java

setResult(Activity.RESULT_CANCELED);
finish();

Chrome 149 से, नतीजे की इन वैल्यू का इस्तेमाल किया जा सकता है:

Kotlin

Activity.RESULT_CANCELED // 0 (0x00000000)
Activity.RESULT_OK // -1 (0xffffffff)
const val INTERNAL_PAYMENT_APP_ERROR = Activity.RESULT_FIRST_USER // 1 (0x00000001)

Java

Activity.RESULT_CANCELED // 0 (0x00000000)
Activity.RESULT_OK // -1 (0xffffffff)
static final int INTERNAL_PAYMENT_APP_ERROR = Activity.RESULT_FIRST_USER; // 1 (0x00000001)

अगर पेमेंट ऐप्लिकेशन में किसी गड़बड़ी की वजह से पेमेंट नहीं हो पाता है, तो Activity.RESULT_FIRST_USER को नतीजे के तौर पर पास करके इसकी जानकारी दी जा सकती है.

अगर INTERNAL_PAYMENT_APP_ERROR वापस आ जाता है, तो request.show() कारोबारी या कंपनी की वेबसाइट पर OperationError के साथ अस्वीकार कर देगा. इससे पता चलेगा कि पेमेंट ऐप्लिकेशन में कोई गड़बड़ी है.

RESULT_CANCELED (0) का मतलब है कि उपयोगकर्ता ने सदस्यता रद्द की है. इससे AbortError की समस्या होती है. वहीं, INTERNAL_PAYMENT_APP_ERROR (1) का मतलब है कि ऐप्लिकेशन में कोई गड़बड़ी हुई है. इससे OperationError की समस्या होती है. इस अंतर की वजह से कारोबारी या कंपनियां, उपयोगकर्ताओं के लिए बेहतर फ़्लो बना पाती हैं.

Kotlin

setResult(Activity.RESULT_FIRST_USER)
finish()

Java

setResult(Activity.RESULT_FIRST_USER);
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() तरीके का इस्तेमाल करके कॉलर की पुष्टि कर सकती है.

Kotlin

val caller: String? = callingPackage

Java

String caller = getCallingPackage();

आखिरी चरण में, कॉल करने वाले व्यक्ति के हस्ताक्षर वाले सर्टिफ़िकेट की पुष्टि की जाती है. इससे यह पुष्टि की जाती है कि कॉल करने वाले पैकेज पर सही हस्ताक्षर है.

चौथा चरण: कॉल करने वाले व्यक्ति के हस्ताक्षर वाले सर्टिफ़िकेट की पुष्टि करना

Binder.getCallingUid() में IS_READY_TO_PAY और PAY में Activity.getCallingPackage() की मदद से, कॉल करने वाले के पैकेज का नाम देखा जा सकता है. यह पुष्टि करने के लिए कि कॉलर वही ब्राउज़र है जिसके बारे में आपको पता है, आपको उसके हस्ताक्षर वाले सर्टिफ़िकेट की जांच करनी चाहिए. साथ ही, यह पक्का करना चाहिए कि वह सही वैल्यू से मेल खाता हो.

अगर आपको एपीआई लेवल 28 और इसके बाद के वर्शन को टारगेट करना है और आपको ऐसे ब्राउज़र के साथ इंटिग्रेट करना है जिसमें एक ही साइनिंग सर्टिफ़िकेट है, तो PackageManager.hasSigningCertificate() का इस्तेमाल किया जा सकता है.

Kotlin

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
)

Java

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 का इस्तेमाल किया जा सकता है.

Kotlin

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)

Java

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