الاستفادة إلى أقصى حد من دمج "الفوترة على Play"

الاستفادة إلى أقصى حد من دمج "الفوترة على Play"

لمحة عن هذا الدرس التطبيقي حول الترميز

subjectتاريخ التعديل الأخير: مايو 19, 2025
account_circleتأليف: Fangyi Luo, Steven Natiello

1. نظرة عامة

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

سنساعدك في إعداد الإشعارات في الوقت الفعلي للمطوّرين وبرنامج Play Billing Lab للاشتراكات والمنتجات التي يتم تحصيل سعرها مرة واحدة في تطبيقاتك وألعابك. ستتعرّف على كيفية الحدّ من إيقاف المستخدمين للاشتراكات، والحماية من الاحتيال وإساءة الاستخدام، واختبار الحالات القصوى، ومحاكاة المشاكل المحتمَلة وإعادة إنتاجها ومعالجتها، وتجربة العروض الترويجية وتغييرات الأسعار بدون التأثير في المستخدمين.

وفي النهاية، ستكون مستعدًا لتنفيذ استراتيجيات استعادة المستخدمين، وحلّ تحديات الدمج بسرعة، وتحسين عائد الاستثمار، وتقديم تجربة مميزة، وطرح تطبيقك وتحديثاته بثقة.

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

المُعطيات

  • كيفية إدارة مراحل الشراء بشكلٍ سليم للمساعدة في تحسين النمو باستخدام أساليب لتحسين الإحالات الناجحة للشراء والاحتفاظ بالعملاء
  • كيفية إعداد ميزة "إشعارات المطوّرين في الوقت الفعلي" (RTDN) باستخدام Google Cloud Pub/Sub، والتي يمكن الاستفادة منها بعد ذلك لتنفيذ حملات استعادة المستخدمين واستراتيجيات إدارة دورة الحياة الأخرى
  • كيفية إعداد جهاز استقبال على خادم الخلفية لمعالجة الإشعارات بأمان من خلال تتبُّع دقيق وتحديد أذونات الاستخدام للحدّ من عمليات ردّ الأموال غير المقصودة أو مخاطر الاحتيال وإساءة الاستخدام
  • كيفية اختبار عملية الدمج ومحاكاة الأخطاء باستخدام Play Billing Lab لتحسين تجربة المستخدم مع تقليل تكاليف التطوير

المتطلبات

2. استراتيجيات تحقيق الربح من الاشتراكات وعمليات الشراء لمرة واحدة

عند بيع منتجات رقمية من خلال تطبيقك، يجب أن تراعي استراتيجية تحقيق الربح الناجحة تجربة المستخدم بالكامل، سواءً في عمليات الشراء لمرة واحدة أو الاشتراكات. يمكن أن تزيد التجربة السلسة من استعداد العملاء للشراء وتقلل من إيقاف الاستخدام.

يتضمن مسار الشراء الشائع لعملية شراء أو اشتراك لمرة واحدة مراحل متعدّدة:

  1. يتصفّح المستخدم السلع التي يريد شراؤها.
  2. ابدأ مسار الشراء ليتمكّن المستخدم من إكمال عملية الشراء والدفع.
  3. إرسال إشعار إلى خادمك بشأن عملية الشراء المكتملة
  4. تحقَّق من عملية الشراء على خادمك.
  5. تقديم محتوى للمستخدم
  6. تأكيد استلام المحتوى بالنسبة إلى المنتجات الاستهلاكية، يجب استخدام المحتوى الذي تم شراؤه في الوقت المناسب كي يتمكّن المستخدم من شرائه مرة أخرى.

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

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

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

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

يمكنك الاطّلاع على مزيد من المعلومات حول جميع أنواع "النطاقات المسجّلة في نطاقات أساسية" المتاحة حاليًا هنا. يشير كل نوع من أنواع RTDN إلى حالة شراء مختلفة. من الضروري تنفيذ آليات التعامل المناسبة لضمان المعالجة الصحيحة حسب الحاجة في حالات الاستخدام. سيرشدك هذا الدرس التطبيقي حول الترميز إلى مثال يعالج رسالة RTDN في خادم الخلفية الآمن، بما في ذلك تلقّي الرسالة والتحقّق من عملية الشراء ومنح الإذن للمستخدم الصحيح عندما يُكمِل مستخدم عملية شراء في تطبيقك بنجاح. وبعد ذلك، سنوضّح لك كيفية ضبط عناوين RTDN لتطبيقك.

3. ضبط "الإشعارات في الوقت الفعلي الخاصة بالمطوّرين" (RTDN)

تستفيد "الإشعارات في الوقت الفعلي الخاصة بالمطوّرين" من Google Cloud Pub/Sub للسماح لك بالردّ فورًا على تغييرات حالة الشراء. ‫Cloud Pub/Sub هي خدمة مراسلة مُدارة بالكامل في الوقت الفعلي يمكنك استخدامها لإرسال الرسائل وتلقّيها بين التطبيقات المستقلة. يستخدم Google Play خدمة Cloud Pub/Sub لنشر الإشعارات الفورية حول المواضيع التي تشترك فيها.

لتفعيل ميزة "الإشعارات في الوقت الفعلي"، عليك أولاً إعداد Cloud Pub/Sub باستخدام مشروعك على Google Cloud Platform (GCP)، ثم تفعيل الإشعارات لتطبيقك. إذا لم تكن على دراية بخدمة GCP وCloud Pub/Sub، اطّلِع على دليل البدء السريع.

إنشاء موضوع

لبدء تلقّي الإشعارات، عليك إنشاء موضوع لينشر Google Play الإشعارات عليه. لإنشاء موضوع، اتّبِع التعليمات الواردة في إنشاء الموضوع.

إنشاء اشتراك في Pub/Sub

لتلقّي الرسائل المنشورة في موضوع معيّن، عليك إنشاء اشتراك في Pub/Sub لهذا الموضوع. لإنشاء اشتراك في Pub/Sub، اتّبِع الخطوات التالية:

  1. اطّلِع على دليل مشتركي Cloud Pub/Sub للتعرّف على كيفية ضبط الاشتراك على أنّه اشتراك فوري أو اشتراك سحب. في هذا الدليل التعليمي، سنستخدم اشتراكًا للسحْب يتطلّب من خادم الخلفية الآمن بدء طلبات إلى خادم Cloud Pub/Sub لاسترداد الرسائل.
  1. اتّبِع التعليمات الواردة في مقالة إضافة اشتراك لإنشاء اشتراك.

منح حقوق نشر شاملة حول موضوعك

تتطلّب خدمة Cloud Pub/Sub منك منح Google Play امتيازات لنشر الإشعارات على موضوعك.

  1. افتح Google Cloud Console.
  2. اختَر مشروعك، ثم ابحث عن Pub/Sub في شريط البحث وانتقِل إلى صفحة إعدادات Pub/Sub. البحث عن صفحة إعدادات Pub/Sub والانتقال إليها
  3. ابحث عن موضوعك وافتح إعدادات الأذونات. فتح إعدادات الأذونات
  4. انقر على إضافة مشرف لإضافة حساب الخدمة google-play-developer-notifications@system.gserviceaccount.com ومنحه دور ناشر Pub/Sub. أضِف حساب الخدمة google-play-developer-notifications@system.gserviceaccount.com، وامنحه دور "ناشر Pub/Sub".
  5. انقر على حفظ لإكمال إعداد الموضوع. انقر على "حفظ" لإكمال عملية إعداد الموضوع.

تفعيل ميزة "الإعلانات الديناميكية على شبكة البحث" لتطبيقك

تعرَّف على كيفية إعداد ميزة "الإشعارات في الوقت الفعلي الخاصة بالمطوّرين" لتحسين عملية دمج "الفوترة في Play" بشكل كبير. يمكنك تحسين موثوقية عمليات الشراء من خلال الرسائل المخصّصة، ومنع الاحتيال وإساءة الاستخدام لتحسين عائد الاستثمار العام.

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

في ما يلي خطوات تفعيل ميزة "إشعارات في الوقت الفعلي للمطوّرين" لتطبيقك:

  1. افتح Google Play Console.
  2. اختيار تطبيقك
  3. انتقِل إلى تحقيق الربح من خلال Play > إعداد تحقيق الربح.
  4. انتقِل إلى قسم الإشعارات في الوقت الفعلي الخاصة بالمطوّرين.
  5. ضَع علامة في المربّع بجانب تفعيل الإشعارات الفورية.
  6. في حقل اسم الموضوع، أدخِل اسم موضوع Cloud Pub/Sub الكامل الذي أعددته سابقًا. يجب أن يكون اسم الموضوع بالتنسيق projects/{project_id}/topics/{topic_name} حيث يكون project_id هو المعرّف الفريد لمشروعك، وtopic_name هو اسم الموضوع الذي تم إنشاؤه سابقًا.
  7. انقر على إرسال رسالة اختبار لإرسال رسالة اختبار. يساعد إجراء عملية نشر تجريبية في التأكّد من إعداد كل شيء وضبطه بشكل صحيح. في حال نجاح النشر التجريبي، تظهر رسالة تفيد بنجاح النشر التجريبي. إذا أرفقت اشتراكًا لهذا الموضوع، من المفترض أن تصلك الرسالة الاختبارية. بالنسبة إلى اشتراك سحب، انتقِل إلى الاشتراك في Cloud Console، وانقر على عرض الرسائل، ثم انتقِل إلى سحب الرسائل. يجب تأكيد أي رسالة سحبتها لتجنُّب تسليمها بشكل متكرّر من خلال Cloud Pub/Sub. بالنسبة إلى اشتراك الدفع الفوري، تحقَّق مما إذا تم تسليم الرسالة التجريبية إلى نقطة نهاية الدفع الفوري. سيُعدّ رمز الردّ الناجح بمثابة رسالة تأكيد. إذا تعذّر النشر، ستظهر رسالة خطأ. تأكَّد من صحة اسم الموضوع ومن أنّ حساب الخدمة google-play-developer-notifications@system.gserviceaccount.com لديه إذن وصول ناشر Pub/Sub إلى الموضوع.
  8. اختَر أنواع الإشعارات التي تريد تلقّيها.
  • تلقّي إشعارات بشأن الاشتراكات وجميع عمليات الشراء المُلغاة: يمكنك تلقّي إشعارات في الوقت الفعلي خاصة بالمطوّرين بشأن الاشتراكات وعمليات الشراء المُلغاة. لن تتلقّى إشعارات بشأن عمليات شراء المنتجات التي يتم تحصيل سعرها مرة واحدة.
  • تلقّي جميع الإشعارات بشأن الاشتراكات والمنتجات التي يتم تحصيل سعرها مرة واحدة: يمكنك تلقّي إشعارات بشأن جميع أحداث الاشتراكات وعمليات الشراء المُلغاة. وستتلقّى أيضًا أحداث شراء منتجات لمرّة واحدة، مثل ONE_TIME_PRODUCT_PURCHASED وONE_TIME_PRODUCT_CANCELED. اطّلِع على رحلة الشراء لمرة واحدة للحصول على مزيد من المعلومات عن أحداث الشراء هذه.

a266e5dec5c93cd8.png

  1. انقر على حفظ التغييرات.

لقد أكملت الآن إشعارات المطوّرين في الوقت الفعلي لتطبيقك، ما يمنحك الأدوات اللازمة لمواجهة التحديات الشائعة، مثل إيقاف استخدام المستخدمين لتطبيقك من خلال إرسال رسائل لاستعادتهم أو عمليات الاحتيال وإساءة الاستخدام. في القسم التالي، سننشئ مشتركًا في خادم الخلفية الآمن لاستخدام الرسائل المُرسَلة إلى موضوع Cloud Pub/Sub.

4. تلقّي إشعارات

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

يتطلّب ذلك رصد اكتمال عملية الشراء ومعالجتها في الوقت المناسب. توفّر مكتبة Play Billing Library طرقًا متعدّدة لرصد عمليات الشراء في تطبيقك. وعند رصد عملية شراء مكتملة، يجب أن يُرسِل تطبيقك إشعارًا إلى خادم الخلفية للتحقّق من عملية الشراء، ومنح المستخدم الصحيح الإذن بالوصول إلى المحتوى، ثم إرسال إشعار إلى Google بأنّه تمت معالجة عملية الشراء. ومع ذلك، قد لا يرصد تطبيقك عملية الشراء في الوقت المناسب لأسباب مختلفة. على سبيل المثال، يمكن للمستخدم إجراء عملية شراء ناجحة وتلقّي تأكيد من Google، ولكن يفقد جهازه الاتصال بالشبكة قبل أن يتلقّى جهازه وتطبيقك إشعارًا من خلال واجهة "مكتبة الفوترة في Play". توفّر ميزة RTDN عناصر تحكّم إضافية من جهة الخادم لمساعدتك في إدارة عمليات الشراء حتى في حال حدوث مشاكل في برنامج العميل. تضمن ميزة RTDN إرسال إشعارات مستقلة إلى خادمك عند تغيير حالة الشراء، ما يتيح لك التعرّف على تغييرات حالة الشراء على الفور تقريبًا من خلال مسار ثانٍ بغض النظر عن المشاكل المحتملة في العميل، ما يضمن عملية شراء أكثر موثوقية.

في هذا القسم، ستنشئ مشتركًا لاستهلاك الرسائل المُرسَلة إلى موضوع Cloud Pub/Sub باستخدام مكتبات عملاء Cloud Pub/Sub. تتوفّر هذه المكتبات بعدة لغات. في الأقسام التالية، سنضيف إلى المشترك عملية إثبات صحة عملية الشراء ومنح الإذن للمستخدم الصحيح وتأكيد/استخدام عملية الشراء على الخادم. في هذا الدرس التطبيقي حول الترميز، سنستخدم Java.

يحتوي كلّ نشر يتم إجراؤه على موضوع Cloud Pub/Sub على حقل بيانات واحد بترميز base64.

{
 "message": {
   "attributes": {
     "key": "value"
   },
   "data": "eyAidmVyc2lvbiI6IHN0cmluZywgInBhY2thZ2VOYW1lIjogc3RyaW5nLCAiZXZlbnRUaW1lTWlsbGlzIjogbG9uZywgIm9uZVRpbWVQcm9kdWN0Tm90aWZpY2F0aW9uIjogT25lVGltZVByb2R1Y3ROb3RpZmljYXRpb24sICJzdWJzY3JpcHRpb25Ob3RpZmljYXRpb24iOiBTdWJzY3JpcHRpb25Ob3RpZmljYXRpb24sICJ0ZXN0Tm90aWZpY2F0aW9uIjogVGVzdE5vdGlmaWNhdGlvbiB9",
   "messageId": "136969346945"
 },
 "subscription": "projects/myproject/subscriptions/mysubscription"
}

بعد فك ترميز حقل البيانات المشفَّر بترميز base64، يحتوي DeveloperNotification على الحقول التالية:

{
 "version": string,
 "packageName": string,
 "eventTimeMillis": long,
 "oneTimeProductNotification": OneTimeProductNotification,
 "subscriptionNotification": SubscriptionNotification,
 "voidedPurchaseNotification": VoidedPurchaseNotification,
 "testNotification": TestNotification
}

يُرجى الرجوع إلى مرجع الإشعارات في الوقت الفعلي للمطوّرين للحصول على مزيد من المعلومات.

في ما يلي نموذج الرمز البرمجي لفئة NotificationReceiver لخادم الخلفية الآمن لمعالجة رسائل Pub/Sub. لمصادقة الدخول إلى "مركز طلبات الأمان"، عليك إعداد "بيانات الاعتماد التلقائية للتطبيق"، راجِع مقالة إعداد المصادقة لبيئة تطوير محلية.

import com.google.cloud.pubsub.v1.AckReplyConsumer;
import com.google.cloud.pubsub.v1.MessageReceiver;
import com.google.cloud.pubsub.v1.Subscriber;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.PubsubMessage;
import java.util.Base64;
import org.json.JSONObject;

/** Real-time developer notifications receiver. */
public class NotificationReceiver {

 private NotificationReceiver() {}

 /*
  * Receive notification messages from the subscription.
  *
  * @param projectId The project ID of your Google Cloud Project.
  * @param subscriptionId The subscription ID of the subscriber to the pub/sub topic.
  */
 public static void receiveNotificationMessages(String projectId, String subscriptionId) {
   ProjectSubscriptionName subscriptionName =
       ProjectSubscriptionName.of(projectId, subscriptionId);

   try {
     Subscriber subscriber =
         Subscriber.newBuilder(subscriptionName, new NotificationMessageReceiver()).build();
     // Start the subscriber.
     subscriber.startAsync().awaitRunning();

     subscriber.awaitTerminated();
   } catch (IllegalStateException e) {
     System.out.println("Subscriber stopped: " + e);
   }
 }

 static class NotificationMessageReceiver implements MessageReceiver {

   @Override
   public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
     // Decode the data into a String from the message data field.
     String jsonString = new String(Base64.getDecoder().decode(message.getData().toStringUtf8()));
     // Parse the String into a JSON object.
     JSONObject messageJson = new JSONObject(jsonString);

     // Fetch the value for certain fields.
     String version = messageJson.getString("version");
     String packageName = messageJson.getString("packageName");
     System.out.println("version: " + version);
     System.out.println("packageName: " + packageName);

     // Validate the purchase and grant the entitlement as needed.
     // More details in the following sections.
     // ......

     // Acknowledge the message to avoid repeated delivery.
     consumer.ack();
   }
 }
}

لديك الآن جهاز استقبال إشعارات يستخدِم الرسائل المُرسَلة إلى موضوع Cloud Pub/Sub في خادم الخلفية الآمن. في الأقسام التالية، سنتناول أفضل الممارسات لمعالجة رسائل RTDN في خادم الخلفية.

5. إرفاق معرّفات المستخدمين في مسار الشراء في تطبيقك

عندما يتلقّى خادمك رسالة RTDN بشأن تعديل حالة الشراء، يجب أن يعرف الخادم المستخدم الذي أجرى عملية الشراء لمعالجتها، مثل إرسال المحتوى إلى المستخدم الصحيح. يمكنك إجراء ذلك من خلال إرفاق أي معرّفات مستخدم لديك للمستخدِم الذي يُجري عملية الشراء باستخدام obfuscatedAccountId عند بدء عملية الشراء في تطبيقك. ويمكن أن يكون مثال على المعرّف نسخة مشوّهة من معلومات تسجيل دخول المستخدم في نظامك. يمكن أن يساعد ضبط هذه المَعلمة Google في رصد عمليات الاحتيال. بالإضافة إلى ذلك، يمكن أن يساعدك ذلك في التأكّد من أنّ عمليات الشراء منسوبة إلى المستخدم المناسب كما هو موضّح في مقالة منح الأذونات للمستخدمين.

يعرض ما يلي نماذج الرموز لربط معرّف المستخدم عند بدء مسار الشراء في التطبيق من خلال ضبط obfuscatedAccountId.

// An activity reference from which the billing flow will be launched.
Activity activity = ...;
// A user identifier, e.g. an obfuscated user id in your system.
String obfuscatedAccountId = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
            // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // set the offer token to specify the offer to purchase when applicable, e.g., subscription products
            // .setOfferToken(offerToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .setObfuscatedAccountId(obfuscatedAccountId)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

كما سترى في القسم التالي، سيتم تضمين معرّف المستخدم الذي تم ضبطه في مسار الشراء في عملية الشراء ويمكن استخدامه لمنح الأذونات للمستخدم الصحيح.

6. التحقّق من عمليات الشراء قبل منح الأذونات

في هذا القسم، سنراجع أفضل الممارسات للتحقّق من عمليات الشراء قبل منح الأذونات في خادم الخلفية الآمن.

بعد أن يُجري المستخدم عملية شراء لمنتج يتم تحصيل سعره مرة واحدة، سيتلقّى المشترك في Pub/Sub في خادم الخلفية الآمن رسالة Pub/Sub. عليك إجراء ما يلي في خادم الخلفية:

  1. قسِّم purchaseToken من رسالة Pub/Sub. يجب الاحتفاظ بسجلّ لجميع قيم purchaseToken لكل عمليات الشراء.
  2. تأكَّد من أنّ قيمة purchaseToken لعملية الشراء الحالية لا تتطابق مع أي قيم purchaseToken سابقة. القيمة purchaseToken فريدة على مستوى العالم، لذا يمكنك استخدام هذه القيمة بأمان كمفتاح أساسي في قاعدة بياناتك.
  3. استخدِم نقطة النهاية purchases.products:get في Google Play Developer API للتحقّق من صحة عملية الشراء مع Google.
  1. إذا كانت عملية الشراء مشروعة ولم يتم استخدامها في السابق، يمكنك منح إذن الوصول إلى المنتج أو الاشتراك داخل التطبيق بأمان.
  2. يجب عدم منح الإذن إلا عندما تكون حالة الشراء هي PURCHASED، وتأكَّد من معالجة عمليات الشراء PENDING بشكل صحيح. يمكنك الاطّلاع على مزيد من المعلومات في مقالة معالجة المعاملات المعلّقة.

ينشئ مثال الرمز البرمجي التالي عميل واجهة برمجة تطبيقات لواجهة برمجة التطبيقات Google Play Developer API. سنستخدمه لإجراء طلبات البيانات من واجهة برمجة التطبيقات لاحقًا.

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.androidpublisher.AndroidPublisher;
import com.google.api.services.androidpublisher.AndroidPublisherScopes;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

/** Helper class to initialize the publisher APIs client library. */
public class AndroidPublisherHelper {
 /* Your application name */
 private static final String APPLICATION_NAME = "YourApplicationName";

 /* Load credentials from a JSON key file. Replace with the actual path to your downloaded service
  * account key file.
  */
 private static final String RESOURCES_CLIENT_SECRETS_JSON =
     "/path/to/your/service_account_key.json";

 /** Global instance of the JSON factory. */
 private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();

 /* The API client */
 private static final AndroidPublisher ANDROID_PUBLISHER = init();

 /**
  * Performs all necessary setup steps for running requests against the API.
  *
  * @return the {@link AndroidPublisher} service
  */
 private static AndroidPublisher init(){
   try {
     // Authorization.
     Credential credential =
         GoogleCredential.fromStream(
                 AndroidPublisherHelper.class.getResourceAsStream(RESOURCES_CLIENT_SECRETS_JSON))
             .createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));

     HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

     // Set up and return API client.
     return new AndroidPublisher.Builder(httpTransport, JSON_FACTORY, credential)
         .setApplicationName(ApplicationConfig.APPLICATION_NAME)
         .build();
   } catch (GeneralSecurityException | IOException ex) {
     throw new RuntimeException("fail to initialize the publisher APIs client library", ex);
   }
 }
}

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

في AndroidPublisherHelper، أضِف الطريقة التالية لتحميل ProductPurchase من نقطة النهاية Purchases.products:get في Google Play Developer API.

 /* Fetch the ProductPurchase for the one-time product purchase from
  * Purchases.products.get endpoint in the Google Play Developer API
  */
 public static ProductPurchase executeProductPurchasesGet(
     String packageName, String sku, String purchaseToken) {
   try {
     ProductPurchase productPurchase =
         ANDROID_PUBLISHER.purchases().products().get(packageName, sku, purchaseToken).execute();
     return productPurchase;
   } catch (IOException ex) {
     log.error("Exception was thrown while getting a product purchase", ex);
     // It is recommended to apply some retry mechanism, such as exponential backoff, to fetch the purchase in case of transient failures.
     return null;
   }
 }

في NotificationMessageReceiver، عليك التحقّق من عملية الشراء ومنح الإذن للمستخدم الصحيح في نظامك استنادًا إلى البيانات المضمّنة في الإشعار. يجب مواصلة تتبُّع purchaseToken في خادمك لتجنُّب تكرار المعالجة.

 @Override
 public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
   // Decode the data into a String from the message data field.
   String jsonString = new String(Base64.getDecoder().decode(message.getData().toStringUtf8()));
   // Parse the String into a JSON object.
   JSONObject messageJson = new JSONObject(jsonString);

   // Fetch the value for certain fields.
   String version = messageJson.getString("version");
   String packageName = messageJson.getString("packageName");

   // Process notification data based on your business requirements.
   // Process oneTimeProductNotification in the message.
   JSONObject oneTimeProductNotificationJson =
       messageJson.getJSONObject("oneTimeProductNotification");
   if (oneTimeProductNotificationJson != null) {
     String purchaseToken = oneTimeProductNotificationJson.getString("purchaseToken");
     String sku = oneTimeProductNotificationJson.getString("sku");
     int notificationType = oneTimeProductNotificationJson.getInt("notificationType");

     if (notificationType == 1) {
       // ONE_TIME_PRODUCT_PURCHASED - A one-time product was successfully purchased by a user.
       // Verify that the purchaseToken value does not match any previous purchaseToken values in
       // your backend system to avoid duplicate processing.
       ......
       // Fetch the ProductPurchase from Purchases.products.get endpoint
       ProductPurchase productPurchase =
         AndroidPublisherHelper.executeProductPurchasesGet(packageName, sku, purchaseToken);
       if (productPurchase != null && productPurchase.getPurchaseState() == 0) {
         // The purchase is valid and in PURCHASED state.

         // The account Id set in the App when launching the billing flow.
         String obfuscatedExternalAccountId = productPurchase.getObfuscatedExternalAccountId();
         // Grant the entitlement to the correct account for obfuscatedExternalAccountId in your
         // system.
       ......
       }
     }
     // Process subscriptionNotification in the message.
     JSONObject subscriptionNotificationJson = messageJson.getJSONObject("subscriptionNotification");
     if (subscriptionNotificationJson != null) {
       ......
     }
     // Process other notification data in the message as needed.
     ......
   }

   // Acknowledge the message to avoid repeated delivery.
   consumer.ack();
 }

7. إبلاغ Google بأنّه تمّت معالجة عملية الشراء

بعد منح الإذن، عليك إبلاغ Google بأنّه تمت معالجة عملية الشراء من خلال طلب نقاط نهاية purchases.products:consume أو purchases.products:acknowledge في Play Developer API من خادم الخلفية الآمن لاستهلاك منتج قابل للاستهلاك أو الإقرار بمنتج غير قابل للاستهلاك.

في AndroidPublisherHelper، أضِف الطريقتَين التاليتَين للاتّصال purchases.products:consume أو purchases.products:acknowledge في Google Play Developer API.

 /* Consume the one-time product purchase by calling
  * Purchases.products.consume endpoint in the Google Play Developer API
  */
 public static void executeProductPurchasesConsume(
     String packageName, String sku, String purchaseToken) {
   try {
     ANDROID_PUBLISHER
       .purchases().products().consume(packageName, sku, purchaseToken).execute();
   } catch (IOException ex) {
     log.error("Exception was thrown while consuming a product purchase", ex);
     // It is recommended to apply some retry mechanism, such as exponential backoff, to ensure the purchase is correctly consumed in case of transient failures.
   }
 }

 /* Acknowledge the one-time product purchase by calling
  * Purchases.products.acknowledge endpoint in the Google Play Developer API
  */
 public static void executeProductPurchasesAcknowledge(
     String packageName, String sku, String purchaseToken) {
   try {
     ANDROID_PUBLISHER
       .purchases().products().acknowledge(packageName, sku, purchaseToken, new ProductPurchasesAcknowledgeRequest()).execute();
   } catch (IOException ex) {
     log.error("Exception was thrown while acknowledging a product purchase", ex);
     // It is recommended to apply some retry mechanism, such as exponential backoff, to ensure the purchase is correctly acknowledged in case of transient failures.
   }
 }

في NotificationMessageReceiver، استخدِم عملية شراء المنتج الاستهلاكي أو أكِّد عملية شراء المنتج غير الاستهلاكي بعد منح الإذن في خادم الخلفية.

 @Override
 public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
   ......
       String obfuscatedExternalAccountId = productPurchase.getObfuscatedExternalAccountId();
       // Grant the entitlement to the correct account for obfuscatedExternalAccountId in your
       // system.
       ......
       // If the product is a consumable product, consume the purchase.
       AndroidPublisherHelper.executeProductPurchasesConsume(packageName, sku, purchaseToken);
       // Or if the product is a non-consumable product, acknowledge the purchase.
       // AndroidPublisherHelper.executeProductPurchasesAcknowledge(packageName, sku, purchaseToken);
  ......

 }

يجب تقديم الإقرار، لأنّه يُعلم Google Play بأنّه تم منح المستخدم إذن الوصول إلى ما اشتراه. يجب الإقرار بإتمام الشراء فور منح الإذن.

أحسنت صنعًا. لقد أكملت عملية الدمج مع ميزة "الإشعارات في الوقت الفعلي الخاصة بالمطوّرين"، ما أدى إلى تفعيل معالجة عمليات الشراء بشكل موثوق كما هو موضّح في هذا الدليل التعليمي. الآن، لضمان عمل كل شيء بشكلٍ مثالي، لنطّلِع على Play Billing Lab، وهي أداة سهلة الاستخدام مصمّمة للمساعدة في اختبار عملية دمج Play Billing.

8. الاختبار باستخدام &quot;برنامج الفوترة في Play&quot;

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

يوفّر Play Billing Lab ميزات اختبار مختلفة للمساعدة في اختبار سيناريوهات مختلفة، بما في ذلك:

نحن نضيف باستمرار إمكانات اختبار جديدة إلى تطبيق Play Billing Lab. يمكنك تنزيل تطبيق Play Billing Lab وتثبيته من متجر Play، أو الاطّلاع على اختبار عملية الدمج للحصول على مزيد من المعلومات حول الاختبار باستخدام Play Billing Lab.

استخدام Play Billing Lab لاختبار BillingResponseCode

من الشائع مواجهة تحديات في اختبار جميع مسارات BillingResponseCode عند دمج تطبيقك مع Play Billing Library، لأنّه لا يمكنك التحكّم كثيرًا في عملية التواصل بين "متجر Play" ونظام Play الأساسي. تتيح لك ميزة محاكي الردود في تطبيق Play Billing Lab ضبط الردود على رموز الأخطاء في Play Billing Library لاختبار سيناريوهات الأخطاء المعقدة المختلفة.

على سبيل المثال، نفّذت المنطق في تطبيقك لاستخدام عملية الشراء بعد أن يرصد تطبيقك عملية الشراء الناجحة. تريد اختبار السيناريو الذي يتعذّر فيه على تطبيقك استخدام عملية الشراء بسبب تعذّر الاتصال بالشبكة، ويتلقّى جهاز استقبال RTDN في خادم الخلفية الرسالة ويعالج عملية الشراء بشكل صحيح. يمكنك الاستفادة من "محاكي الاستجابة" لمحاكاة السيناريو الخاص باختبارك. سترشدك الخطوات التالية خلال عملية الاختبار باستخدام "محاكي الردود" في Play Billing Lab.

الاختبار باستخدام "محاكي الاستجابة"

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

تفعيل اختبار عمليات إلغاء الفوترة في "مكتبة الفوترة في Play"

لتفعيل الاتصالات بين "محاكي الردود" وتطبيقك، عليك أولاً تفعيل اختبار عمليات إلغاء الفوترة في Play Billing Library من داخل تطبيقك. لإجراء ذلك، أضِف علامات البيانات الوصفية التالية إلى ملف AndroidManifest.xml في تطبيقك.

<manifest ... >
  <application ... >
    ...
     <meta-data
      android:name="com.google.android.play.largest_release_audience.NONPRODUCTION"
      android:value="" />
    <meta-data
      android:name="com.google.android.play.billingclient.enableBillingOverridesTesting"
      android:value="true" />
  </application>
</manifest>

أنشئ تطبيقك باستخدام ملف AndroidManifest.xml المعدَّل. أصبح تطبيقك جاهزًا لاستخدام "محاكي الاستجابة" في "برنامج الفوترة في Play".

عند نشر تطبيقك في بيئة الإنتاج بعد الاختبار، يجب استخدام ملف AndroidManifest.xml منفصل لا يتضمّن علامات البيانات الوصفية هذه أو التأكّد من إزالة هذه العلامات من ملف AndroidManifest.xml.

محاكاة أخطاء Play Billing Library

لإجراء اختبار باستخدام أخطاء محاكية في Play Billing Library، عليك أولاً ضبط رمز الاستجابة في تطبيق Play Billing Lab، ثم إجراء الاختبار في تطبيقك.

ضبط رمز استجابة

  1. سجِّل الدخول إلى تطبيق "برنامج الفوترة في Play" باستخدام حساب مختبِر الترخيص لتطبيقك. تعرض الصورة التالية لوحة البيانات في "برنامج الفوترة في Play"، بما في ذلك بطاقة محاكي الاستجابة.

لوحة بيانات &quot;برنامج الفوترة في Play&quot; مع &quot;محاكي الاستجابة&quot;

  1. انقر على إدارة في بطاقة "محاكي الاستجابة" للانتقال إلى شاشة "محاكي الاستجابة".
  2. اسمح بالإشعارات الواردة من "برنامج الفوترة في Play" عندما يُطلب منك ذلك للاطّلاع على حالة اتصال تطبيقك.
  3. فعِّل مفتاح التبديل "محاكاة استجابة Play Billing Library"، إذا لم يكن مفعّلاً.

c841baa4c96bf306.png

  1. اختَر رمز استجابة لواجهات برمجة التطبيقات Play Billing Library API التي تريد اختبارها. لمحاكاة الخطأ في عملية الشراء المستهلكة، اختَر رمز خطأ لواجهة برمجة التطبيقات consumeAsync. يتم حفظ اختياراتك تلقائيًا. أصبح "محاكي الاستجابة" جاهزًا الآن لإرسال رموز الاستجابة المحدّدة إلى تطبيقك.

اختبار تطبيقك

يمكنك الآن اختبار تطبيقك للتأكّد مما إذا كان كل شيء يعمل على النحو المتوقّع في سيناريو الخطأ الذي تم ضبطه. افتح تطبيقك وشغِّل طريقة واجهة برمجة التطبيقات Play Billing Library API. إذا أرسل تطبيقك طلب consumeAsync لاستخدام عملية الشراء، سيتلقّى تطبيقك رمز الخطأ الذي ضبطته للتو. يمكنك التحقّق مما إذا كان تطبيقك يعمل بشكل صحيح استنادًا إلى رمز الخطأ وما إذا كان خادم الخلفية يعالج عملية الشراء بشكل صحيح.

بعد الانتهاء من الاختبار، ما عليك سوى إيقاف مفتاح التبديل "محاكاة استجابة Play Billing Library" لإيقاف محاكاة الاستجابة.

اطّلِع على مزيد من المعلومات عن الاختبار باستخدام برنامج الفوترة في Play، أو انتقِل إلى مركز المساعدة للاطّلاع على مزيد من المعلومات عن اختبار الفوترة داخل التطبيقات باستخدام "مختبِري التراخيص".

9. تهانينا!

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

من خلال الاستفادة من ميزة "الإشعارات في الوقت الفعلي للمطوّرين" والتطبيق المصاحب Play Billing Lab، يمكنك معالجة أحداث دورة حياة الشراء بشكل استباقي لكل من عمليات الشراء لمرة واحدة والاشتراكات.

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

بعد إكمال هذا الدرس التطبيقي حول الترميز، ستمتلك الآن المهارات اللازمة لإدارة رحلة الشراء بالكامل واختبار عملية التنفيذ بدقة باستخدام Play Billing Lab، ما يضمن توفير تجربة سلسة للمستخدمين وتحقيق أقصى قدر ممكن من إمكانية تحقيق الربح على Google Play.