إنشاء تجربة دفع سريعة على Android باستخدام Google Pay

1. مقدمة

تتيح واجهة Google Pay API للمستخدمين إمكانية الدفع من أي مكان باستخدام معلومات الدفع المحفوظة في حساباتهم على Google. يستخدم هذا البرنامج مكتبة برامج Google Pay لنظام التشغيل Android لتحسين تجربة الدفع في نموذج مبسّط متوافق مع الأجهزة الجوّالة، وذلك من خلال إنشاء تجربة أسرع وأكثر ملاءمة وأمانًا، ما يؤدي بدوره إلى زيادة الإحالات الناجحة وشعور العملاء بالسعادة أكثر.

متجر Auto T-T Shirt Shop هو متجر مبتكر يستفيد من أحدث التطورات في مجال الذكاء الاصطناعي، ويتيح لك استخدام معلومات مثل الإعدادات المفضّلة للأزياء والطقس والوقت من السنة ومؤشرات الموضة اقتراح أكثر سلعة مناسبة لشرائها.

المقاييس المتعلقة بالتفاعل تتجاوز الحد. للأسف، تعكس الأرقام أيضًا عددًا كبيرًا من حالات التراجع أثناء عملية الدفع. عزمًا على حلّ هذه المشكلة، يتذكّر أحد مالكي المشروع أنّه شاهد فيديو يعرض النتائج الواعدة التي حقّقتها خدمة Google Pay لمواقع إلكترونية أخرى مشابهة، لذلك قرّر المحاولة والوثوق بك للتعامل مع عملية الدمج.

نظرة عامة

يرشدك هذا الدرس التطبيقي حول الترميز خلال عملية دمج Google Pay في تطبيق حالي، بما في ذلك تحديد ما إذا كان بإمكان المستخدم الدفع باستخدام طريقة دفع متوافقة مع Google Pay، وموضع زر الدفع وتصميمه، وكيفية تنفيذ المعاملة.

نموذج تطبيق

ستتعلّم في هذا الدرس التطبيقي كيفية:

  1. دمج Google Pay في تطبيق Android حالي
  2. تحديد ما إذا كان المستخدم مستعدًا للدفع باستخدام Google Pay
  3. إضافة زر Google Pay إلى واجهة المستخدم
  4. إكمال عملية دفع باستخدام Google Pay

المتطلبات الأساسية

  • Git
  • استوديو Android أو بيئة تطوير بديلة لتطبيقات Android
  • جهاز Android أو محاكي تم تثبيت أحدث إصدار من "خدمات Google Play" عليه

الدعم

إذا واجهتك مشكلة، يحتوي مستودع GitHub google-pay/android-quickstart على حلّ كامل يمكن الرجوع إليه.

2. البدء

استنساخ المستودع من GitHub

استخدِم الأمر التالي لانسخ المستودع في مجلد على جهاز الكمبيوتر:

git clone https://github.com/google-pay/android-quickstart

إذا كنت تفضّل إنشاء أرشيف بتنسيق ZIP:

تصفُّح محتوى النموذج

كما ترى، يتميز المستودع ببنية ملفات غير معقدة. يتمثّل الهدف الأساسي من هذا الدرس التطبيقي في منحك إمكانية تعديل هذا الدمج مع تطبيقاتك الحالية والمستقبلية، وذلك بشكل مستقل عن لغة البرمجة أو المكتبات أو الأدوات التي تختار استخدامها.

3- فتح المشروع في "استوديو Android"

يحتوي مستودع GitHub الذي استنسخته على مشروع Android بنشاط أساسي. في هذه الخطوة، ستُجري تعديلاً في هذا النشاط للتحقّق من جاهزية Google Pay وإظهار زر Google Pay.

  1. فتح "استوديو Android"
  2. انقر على ملف، ثم على فتح.
  3. اختيار الدليل kotlin في المستودع
  4. انقر على فتح.

أضِف مكتبة Google Pay كمكتبة تابعة في ملف build.gradle.

  1. فتح ملف إصدار Gradle على مستوى الوحدة (kotlin/app/build.gradle.kts)
  2. إضافة مكتبة Google Pay إلى القسم dependencies
implementation "com.google.android.gms:play-services-wallet:19.3.0"
  1. حفظ الملف
  2. اختَر ملف، ثم مزامنة المشروع مع ملفات Gradle

تفعيل Google Pay API في ملف البيان الخاص بنظام التشغيل Android

أخيرًا، يمكنك إضافة عنصر meta-data داخل العقدة application من ملف البيان:

<meta-data
    android:name="com.google.android.gms.wallet.api.enabled"
    android:value="true" />

4. تحديد مكان وضع زر Google Pay في واجهتك

يُعد التنسيق والموضع العام في طرق العرض من الجوانب المهمة التي تؤثر في مدى احتمالية إكمال المستخدمين لمعاملة دفع. بفضل إمكانية اختيار طريقة استلام الدفعات ببضع نقرات باستخدام Google Pay، تتوفّر خيارات جديدة تتيح للمستخدمين تحديد مكان وموعد توفير طريقة الدفع في تطبيقك. على سبيل المثال، يمكنك إضافة خيارات الدفع السريع في وقت مبكر من العملية، في مناطق مثل عرض تفاصيل العنصر، للسماح للمستخدمين بالدفع بسرعة مقابل عنصر واحد يحبونه.

بعد أن تقرر كيفية ترتيب واجهة المستخدم، تكمن الخطوة التالية في وضع زر Google Pay. يمكنك ضبط بعض الميزات المرئية للزر مثل النوع والمظهر واستدارة الزوايا. وإليك بعض الأمثلة:

مثال على أزرار Google Pay الديناميكية

تتضمّن مكتبة Google Pay عرضًا لتسهيل إضافة الزر إلى واجهة المستخدم. إليك كيفية القيام بذلك إذا كنت تقوم بإنشاء تخطيطاتك باستخدام XML:

<com.google.android.gms.wallet.button.PayButton
    android:id="@+id/googlePayButton"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

يمكنك بعد ذلك تهيئة الزر آليًا (اطّلع على المثال).
إذا كنت تستخدم Jetpack Compose، يمكنك تضمين أحدث إصدار من الاعتمادية التالية في ملف build.gradle أو build.gradle.kts:

implementation "com.google.pay.button:compose-pay-button:1.0.0"

وأضِف زر Google Pay إلى تنسيق Compose على النحو التالي:

PayButton(
    modifier = Modifier
        .testTag("payButton")
        .fillMaxWidth(),
    onClick = onGooglePayButtonClick,
    allowedPaymentMethods = PaymentsUtil.allowedPaymentMethods.toString()
)

يمكنك الاطلاع على النموذج في GitHub لمعرفة المزيد من المعلومات حول كيفية إنشاء قائمة طرق الدفع المقبولة.

5- إعداد Google Pay API وضبطها

إنشاء مثيل لبرنامج واجهة برمجة التطبيقات

لبدء استخدام واجهة برمجة التطبيقات، يجب إنشاء مثيل كائن العميل الذي تستخدمه لإجراء طلبات إلى Google Pay API. ويمكنك إجراء ذلك فور إنشاء نشاطك أو وحدة التحكُّم:

private val paymentsClient: PaymentsClient = createPaymentsClient(context)

fun createPaymentsClient(context: Context): PaymentsClient {
    val walletOptions = Wallet.WalletOptions.Builder()
            .setEnvironment(WalletConstants.ENVIRONMENT_TEST).build()
    return Wallet.getPaymentsClient(context, walletOptions)
}

يتمّ إعداد برنامج الدفع باستخدام عنصر WalletOptions. يؤدي ضبط البيئة على ENVIRONMENT_TEST إلى السماح لك بتجربة معلومات الدفع التجريبية. وبعد أن تصبح مستعدًا لإصدار معاملات دفع فعلية، يمكنك تعديل موقع البيئة إلى ENVIRONMENT_PRODUCTION.

بنية طلب Google Pay

عندما تصدر طلبات إلى Google Pay API، هناك عدد من مَعلمات الإعداد التي يجب تضمينها في طلباتك، مثل إصدار واجهة برمجة التطبيقات الذي تستهدفه. لأغراض هذا الدرس التطبيقي، يحتوي هذا العنصر أيضًا على معلومات عن طرق الدفع المقبولة في طلبك. يبدو الهيكل النهائي على النحو التالي:

{
    apiVersion: number,
    apiVersionMinor: number,
    allowedPaymentMethods: Array
}

يتضمّن الموقع "allowedPaymentMethods" قائمة بطُرق الدفع. في كل طريقة دفع، عليك تضمين السمات التالية:

{
    type: 'CARD',
    parameters: {
        allowedCardNetworks: Array.<string>,
        allowedAuthMethods: Array.<string>
    }
}

إعدادات طريقة الدفع

لأغراض هذا المثال، يمكنك قبول الدفعات بواسطة بطاقات Mastercard وVisa فقط، سواء باستخدام نموذج الرمز المميّز أو رقم الحساب الأساسي (PAN). إليك طريقة الدفع:

private val baseCardPaymentMethod =
    JSONObject()
        .put("type", "CARD")
        .put("parameters", JSONObject()
            .put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
            .put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
        )

خلاصة ما سبق ذكره

دعنا نلخص. لقد حددت طريقة دفع واحدة ليتم قبولها في طلبك، وستعمل على استخدام الإصدار 2.0 من واجهة برمجة التطبيقات. هذا هو ما تبدو عليه التهيئة الناتجة:

private val baseCardPaymentMethod = JSONObject()
    .put("type", "CARD")
    .put("parameters", JSONObject()
        .put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        .put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
    )

private val googlePayBaseConfiguration = JSONObject()
    .put("apiVersion", 2)
    .put("apiVersionMinor", 0)
    .put("allowedPaymentMethods",  JSONArray(listOf(baseCardPaymentMethod)))
}

6- تحديد الاستعداد للدفع باستخدام Google Pay

ويتيح لك استخدام طلب isReadyToPay تحديد ما إذا كان بإمكان المستخدم في تطبيقك الدفع باستخدام Google Pay. استخدِم هذه المعلومات لتعديل تجربة المستخدم في تطبيقك وفقًا لذلك.

يتطلّب منك هذا الطلب تحديد إصدار Google Pay API وقائمة طرق الدفع المسموح بها في تطبيقك. هذا هو بالضبط ما يحتويه كائن الإعداد الأساسي المحدّد في الخطوة السابقة على ما يلي:

private suspend fun fetchCanUseGooglePay(): Boolean {
    val request = IsReadyToPayRequest.fromJson(googlePayBaseConfiguration.toString())
    return paymentsClient.isReadyToPay(request).await()
}

جانبًا، تستخدم Google Pay API واجهات برمجة التطبيقات Task لمعالجة المكالمات التي تتم عن بُعد. تتيح لك واجهة برمجة تطبيقات "مهام Google" حلّ عمليات Task باستخدام الكوروتينات. مزيد من المعلومات

كما ترى، يتم عرض عنصر منطقي عند التحقق من الاستعداد للدفع باستخدام Google Pay. إذا كانت النتيجة إيجابية، يمكنك عرض زر Google Pay في واجهة المستخدم على موقعك الإلكتروني. أو يمكنك عرض واجهة مستخدم إضافية تتوافق مع وسائل دفع أخرى.

عرض زر Google Pay

يمكنك الآن الرجوع إلى واجهة المستخدم وتعديل موضع زر Google Pay بناءً على نتيجة المكالمة السابقة. يستخدم هذا المثال فئة للاحتفاظ بحالة العرض، والتي يتم تعديلها استنادًا إلى إدخال مثل الطلب إلى isReadyToPay.

if (payUiState !is PaymentUiState.NotStarted) {
    PayButton(
        modifier = Modifier
            .testTag("payButton")
            .fillMaxWidth(),
        onClick = onGooglePayButtonClick,
        allowedPaymentMethods = PaymentsUtil.allowedPaymentMethods.toString()
    )
}

7. حان وقت الدفع.

### إعداد طلب الدفع

في هذه المرحلة، تكون قد حمَّلت Google Pay API وتبيّن أنّ المستخدم في تطبيقك يمكنه استخدام Google Pay لإجراء عملية دفع. نتيجةً لذلك، ظهر زر الدفع في Google Pay في واجهة المستخدم وأصبح بإمكان المستخدم بدء المعاملة. حان الوقت الآن لتحميل جدول بيانات الدفع مع طرق الدفع المتاحة للمستخدم.

على غرار استدعاء isReadyToPay، يتطلب هذا الطلب السمات في كائن الضبط الأساسي المحددة سابقًا (apiVersion وapiVersionMinor وallowedPaymentMethods). هذه المرة، ستحتاج أيضًا إلى موقع جديد باسم tokenizationSpecification، ومَعلمات إضافية لوصف المعاملة وطلب معلومات، مثل عنوانَي الفوترة والشحن أو عناوين المستخدِمين. عنوان بريدك الإلكتروني أو رقم هاتفك.

#### السمة tokenizationSpecification

تحدّد مواصفات الترميز كيف يتم التعامل مع طريقة الدفع التي يختارها المستخدمون واستخدامها لإكمال معاملة.

هناك نوعان مختلفان من آليات المناولة المتاحة. إذا كنت تعالج معاملة الدفع من داخل خوادم PCI DSS المتوافقة، استخدِم نوع مواصفات DIRECT. في هذا المثال، يمكنك استخدام بوابة دفع لمعالجة الدفعة، وبالتالي يمكنك ضبط نوع مواصفات PAYMENT_GATEWAY:

private val tokenizationSpecification = JSONObject()
    .put("type", "PAYMENT_GATEWAY")
    .put("parameters", JSONObject(mapOf(
            "gateway" to "example",
            "gatewayMerchantId" to "exampleGatewayMerchantId")))
}

في القسم parameters، يمكنك تحديد مدخل من قائمة مقدّمي الخدمة الذين تتيحهم واجهة Google Pay API، بالإضافة إلى الإعدادات الإضافية التي تتطلّبها كل بوابة. لأغراض هذا النشاط، ستستخدم بوابة example التي تعرض نتائج اختبار للمعاملات التي يتم تنفيذها.

المَعلمات الإضافية

وبالمثل، يمكنك طلب المزيد من التفاصيل من المستخدم لتقديم الطلب بنجاح. اطّلِع في هذا المثال على كيفية إضافة السمتَين billingAddressRequired وbillingAddressParameters للإشارة إلى أنّه في هذه المعاملة، يجب إدخال عنوان إرسال الفواتير للمستخدم بالتنسيق الكامل مع تضمين رقم الهاتف:

private val cardPaymentMethod = JSONObject()
    .put("type", "CARD")
    .put("tokenizationSpecification", tokenizationSpecification)
    .put("parameters", JSONObject()
        .put("allowedCardNetworks", JSONArray(listOf("VISA", "MASTERCARD")))
        .put("allowedAuthMethods", JSONArray(listOf("PAN_ONLY", "CRYPTOGRAM_3DS")))
        .put("billingAddressRequired", true)
        .put("billingAddressParameters", JSONObject(mapOf("format" to "FULL")))
    )

#### تضمين معلومات إضافية عن المعاملة

تحتوي السمة transactionInfo على عنصر يتضمّن تفاصيل مالية عن المعاملة، وهي السعر ورمز العملة (بتنسيق ISO 4217 alpha) بالإضافة إلى حالة السعر التي يمكن أن تكون نهائية أو مقدّرة استنادًا إلى طبيعة المعاملة (على سبيل المثال: قد يختلف السعر استنادًا إلى عنوان الشحن المحدَّد):

private val transactionInfo = JSONObject()
    .put("totalPrice", "123.45")
    .put("totalPriceStatus", "FINAL")
    .put("currencyCode", "USD")
}

#### إضافة معلومات نشاطك التجاري

يتضمّن طلب الدفع معلومات عن التاجر الذي ينفّذ الطلب من خلال الموقع الإلكتروني merchantInfo. في هذا الدرس التطبيقي حول الترميز، ستركّز على خاصيتَين:

  • يحمل merchantId المعرّف المرتبط بحسابك. يمكنك الحصول على معرّف التاجر في صفحة الدفع وحدة التحكم في المحفظة يُرجى العلم أنّه لا يتم تقييم هذا الحقل عند استخدام بيئة TEST.
  • merchantName هو الاسم المرئي للمستخدم لتطبيقك أو مؤسستك. ويمكن أن يظهر هذا الرقم في ورقة الدفع في Google Pay لتزويد المستخدمين بسياق إضافي حول الجهة التي تطلب العملية.

بعد أن تصبح جاهزة، ما عليك سوى إضافة المعلومات حول التاجر إلى عنصر paymentDataRequest:

private val merchantInfo = JSONObject()
    .put("merchantName", "Example Merchant")
    .put("merchantId", "01234567890123456789")

إصدار الطلب ومعالجة النتيجة

والآن، اجمع كائن الإعداد معًا ومرِّره إلى طلب loadPaymentData:

private val paymentDataRequestJson = JSONObject(googlePayBaseConfiguration.toString())
    .put("allowedPaymentMethods", JSONArray().put(cardPaymentMethod))
    .put("transactionInfo", transactionInfo)
    .put("merchantInfo", merchantInfo)

في هذه المرحلة، لديك كل ما تحتاج إليه لطلب طريقة دفع صالحة من Google Pay API. ولإجراء ذلك، استخدِم الطريقة loadPaymentData في الكائن PaymentsClient، مع ضبط الإعدادات التي حدّدتها للتو:

fun getLoadPaymentDataTask(): Task<PaymentData> {
    val request = PaymentDataRequest.fromJson(paymentDataRequestJson.toString())
    return paymentsClient.loadPaymentData(request)
}

private fun requestPayment() {
    val task = getLoadPaymentDataTask()
    task.addOnCompleteListener(paymentDataLauncher::launch)
}

تستخدم Google Pay API Activity Result API لعرض نتيجة. تحتوي واجهة برمجة التطبيقات على عقود لتبسيط عملية المعالجة والاستجابة للنتيجة. يستخدم هذا المثال عقد GetPaymentDataResult، الذي يتضمّن معلومات عن العملية بالإضافة إلى نتيجة الدفع:

private val paymentDataLauncher = registerForActivityResult(GetPaymentDataResult()) { taskResult ->
    when (taskResult.status.statusCode) {
        CommonStatusCodes.SUCCESS -> {
            taskResult.result!!.let {
                Log.i("Google Pay result:", it.toJson())
                // TODO something with the result
            }
        }
        CommonStatusCodes.CANCELED -> // The user canceled
        AutoResolveHelper.RESULT_ERROR -> // The API returned an error (it.status: Status)
        CommonStatusCodes.INTERNAL_ERROR -> // Handle other unexpected errors
    }
}

يؤدي استدعاء هذه الطريقة إلى عرض ورقة بيانات الدفع في Google Pay. وفي حال عدم وجود أخطاء في الإعداد، يمكنك الاطّلاع على قائمة بطرق الدفع الصالحة المرتبطة بالحساب الذي تم تسجيل الدخول إليه حاليًا.

عند التحديد، يتم إغلاق ورقة البيانات ويتم إرسال النتيجة مرة أخرى إلى نشاطك ويتم التقاطها من خلال مشغّل نتائج النشاط المحدّد أعلاه.

إذا كان الاختيار ناجحًا، يتم عرض النتيجة مع عنصر PaymentData يتضمن معلومات ذات صلة حول طريقة الدفع المحددة:

{
  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "examplePaymentMethodToken"
    },
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234",
      "billingAddress": {
        "phoneNumber": ...,
        ...
      }
    }
  }
}

يمكنك الآن استخدام طريقة الدفع التالية لإكمال المعاملة باستخدام بوابة الدفع:

private fun handlePaymentSuccess(paymentData: PaymentData) {
    val paymentMethodToken = paymentData
            .getJSONObject("tokenizationData")
            .getString("token")

    // Sample TODO: Use this token to perform a payment through your payment gateway
}

8. تهانينا

لقد أضفت Google Pay بنجاح إلى أحد تطبيقات Android.

### الخطوات التالية

### مزيد من المعلومات

هل كان هذا المحتوى مفيدًا؟

مفيدة جدًا تمامًا كما توقعت ليس في الواقع