1. نظرة عامة
يمكنك تحسين مصادر أرباحك وإطلاق تطبيقك بثقة من خلال تجربة الترميز هذه لدمج "مكتبة الفوترة في Google Play" من Google Play. يرشدك هذا الدرس التطبيقي المنظَّم حول الترميز إلى خطوات إعداد عملية موثوقة لمعالجة عمليات الشراء واختبارها وتنفيذها، ما يتيح لك تحقيق أهداف تحقيق الربح وتقديم تجربة أكثر سلاسة للمستخدمين.
سنساعدك في إعداد إشعارات في الوقت الفعلي خاصة بالمطوّرين وPlay Billing Lab للاشتراكات والمنتجات التي يتم تحصيل سعرها مرة واحدة في تطبيقاتك وألعابك. ستتعرّف على كيفية الحدّ من حالات إلغاء الاشتراك، والحماية من الاحتيال وإساءة الاستخدام، واختبار الحالات الحدّية، ومحاكاة المشاكل المحتملة وإعادة إنتاجها وحلّها، وتجربة العروض وتغييرات الأسعار بدون التأثير في المستخدمين.
وبحلول نهاية هذه السلسلة، ستكون مستعدًا لتنفيذ استراتيجيات استعادة المستخدمين، وحلّ تحديات الدمج بسرعة، وتحسين عائد الاستثمار، وتقديم تجربة مميزة، وطرح تطبيقك وتحديثاته بثقة.
المتطلبات الأساسية
- الإلمام بالدمج الأساسي لمكتبة الفوترة في Play
- معرفة أساسية بتطوير تطبيقات Android (Java)
أهداف الدورة التعليمية
- كيفية إدارة دورات الشراء بشكلٍ سليم للمساعدة في تحسين النمو باستخدام أساليب لتحسين الإحالات الناجحة المتمثّلة بعمليات شراء والاحتفاظ بالعملاء
- كيفية إعداد ميزة "الإشعارات في الوقت الفعلي الخاصة بالمطوّرين" (RTDN) باستخدام Google Cloud Pub/Sub، والتي يمكن الاستفادة منها بعد ذلك لتنفيذ حملات استعادة المستخدمين واستراتيجيات أخرى لإدارة مراحل النشاط
- كيفية إعداد جهاز استقبال على خادم الخلفية للتعامل مع الإشعارات بشكل آمن مع تتبُّع دقيق وإثبات ملكية للحدّ من عمليات رد الأموال غير المقصودة أو مخاطر الاحتيال وإساءة الاستخدام
- كيفية اختبار عملية الدمج ومحاكاة الأخطاء باستخدام Play Billing Lab لتحسين تجربة المستخدم مع تقليل تكاليف التطوير
المتطلبات
- إمكانية الوصول إلى حساب المطوِّر على Play لتطبيقك في Google Play Console
- إذن الوصول إلى مشروعك على Google Cloud Platform مع تفعيل Google Play Developer API
- خادم خلفي للتعامل مع الحسابات والأذونات لتطبيق Android
- مختبِرو الترخيص المسجَّلون لتطبيقك في Play Console
- تطبيق Play Billing Lab مثبَّت على جهاز الاختبار
2. استراتيجيات تحقيق الربح من الاشتراكات وعمليات الشراء لمرة واحدة
عند بيع منتجات رقمية من خلال تطبيقك، يجب أن تراعي استراتيجية تحقيق الربح الناجحة تجربة المستخدم بأكملها، سواء عمليات الشراء لمرة واحدة أو الاشتراكات. يمكن أن تؤدي التجربة السلسة إلى زيادة الاستعداد للشراء وتقليل معدّل التوقّف عن استخدام الخدمة.
يتضمّن مسار الشراء الشائع لعملية شراء لمرة واحدة أو اشتراك عدة مراحل:
- يتصفّح المستخدم السلع لشرائها.
- ابدأ مسار الشراء ليتمكّن المستخدم من إكمال عملية الشراء والدفع.
- إرسال إشعار إلى الخادم بشأن عملية الشراء المكتملة
- تأكيد عملية الشراء على الخادم
- تقديم المحتوى للمستخدم
- أكِّد استلام المحتوى. بالنسبة إلى المنتجات الاستهلاكية، استهلك عملية الشراء في الوقت المناسب ليتمكّن المستخدم من شراء المنتج مرة أخرى.
يتيح لك الدمج داخل التطبيق بدء عمليات شراء وإدارة تجربة المستخدم هذه، ولكن من الضروري إبقاء الخلفية محدّثة بشأن الأذونات التي يشتريها المستخدمون. وهذا مهم لتتبُّع عمليات الشراء وإدارة الجوانب الأخرى من تجربة المستخدم، مثل الأذونات من عدّة منصات.
تُعدّ الإشعارات في الوقت الفعلي الخاصة بالمطوّرين (RTDN) طريقة رائعة للتعرّف على هذه المراحل المختلفة في دورة حياة عملية الشراء، ويمكن استخدامها بفعالية كأداة لتتبُّع الأداء في الوقت الفعلي، وكأداة لتفعيل استراتيجيات استعادة المشتركين.
على سبيل المثال: لنفترض أنّ المستخدم اشترى للتو منتجًا جديدًا أو فاته موعد الدفع، لذا دخل الاشتراك في فترة السماح. باستخدام إشعارات RTDN المناسبة، يمكنك التعرّف في الوقت الفعلي تقريبًا على أنّ حالة المستخدم قد تغيّرت، والتصرّف وفقًا لذلك من خلال زيادة تفاعل المستخدم مع المنتج الذي اشتراه للتو، أو إرسال رسائل تذكيرية إليه لتعديل تفاصيل الدفع من أجل مواصلة الاشتراك.
تُعدّ إشعارات المعاملات في الوقت الفعلي أيضًا طريقة رائعة لإضافة عناصر تحكّم إضافية من جهة الخادم لمساعدتك في إدارة عمليات الشراء حتى في حال حدوث مشاكل في جهاز المستخدم. لنفترض أنّ أحد المستخدمين أجرى عملية شراء ناجحة وتلقّى تأكيدًا من Google، ولكن انقطع الاتصال بالشبكة في جهازه قبل أن يتلقّى الجهاز وتطبيقك إشعارًا بعملية الشراء من خلال متتبِّع عمليات الشراء. باستخدام الإشعارات في الوقت الفعلي عند إتمام المعاملة، ستتلقّى إشعارًا مستقلاً من خلال الخادم، ما يتيح لك التعرّف على عملية الشراء ومنح المستخدم الإذن بشكل مستقل عن مشكلة العميل، ما يضمن عملية شراء موثوقة.
يمكنك الاطّلاع على مزيد من المعلومات حول جميع أنواع الإشعارات في الوقت الفعلي التي تتوافق معها حاليًا هنا. يشير كل نوع من إشارات RTDN إلى حالة شراء مختلفة. من الضروري تنفيذ آليات معالجة مناسبة لضمان المعالجة السليمة حسب الحاجة في حالات الاستخدام. سيرشدك هذا الدرس التطبيقي حول الترميز إلى مثال يعالج رسالة الإشعارات في الوقت الفعلي عند استلامها في خادم الخلفية الآمن، ويتحقّق من عملية الشراء ويمنح الإذن للمستخدم المناسب عند إكمال عملية الشراء بنجاح في تطبيقك. وسنوضّح لك بعد ذلك كيفية إعداد الإشعارات في الوقت الفعلي لتطبيقك.
3- ضبط الإشعارات في الوقت الفعلي الخاصة بالمطوّرين
تستفيد الإشعارات في الوقت الفعلي الخاصة بالمطوّرين من خدمة 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، اتّبِع الخطوات التالية:
- اطّلِع على دليل المشترك في Cloud Pub/Sub للتعرّف على كيفية ضبط الاشتراك كـ اشتراك فوري أو اشتراك عادي. في هذا الدرس التطبيقي حول الترميز، سنستخدم اشتراك سحب يتطلّب من خادم الخلفية الآمن بدء الطلبات إلى خادم Cloud Pub/Sub لاسترداد الرسائل.
- اتّبِع التعليمات الواردة في مقالة إضافة اشتراك لإنشاء اشتراك.
منح حقوق النشر بشأن موضوعك
تتطلّب خدمة Cloud Pub/Sub منح Google Play أذونات مميّزة لنشر الإشعارات في موضوعك.
- افتح Google Cloud Console.
- اختَر مشروعك، ثم ابحث عن Pub/Sub في شريط البحث وانتقِل إلى صفحة إعداد Pub/Sub.

- ابحث عن موضوعك وافتح إعدادات الأذونات.

- انقر على إضافة مستخدم رئيسي لإضافة حساب الخدمة
google-play-developer-notifications@system.gserviceaccount.comومنحه دور ناشر Pub/Sub.
- انقر على حفظ لإكمال عملية إعداد المواضيع.

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

- انقر على حفظ التغييرات.
لقد أكملت الآن إعداد إشعارات في الوقت الفعلي خاصة بالمطوّرين لتطبيقك، ما يوفّر لك الأدوات اللازمة لمواجهة التحديات الشائعة، مثل فقدان المستخدمين من خلال رسائل استعادة المستخدمين، أو الاحتيال وإساءة الاستخدام. في القسم التالي، سننشئ مشتركًا في خادم الخلفية الآمن لاستهلاك الرسائل المُرسَلة إلى موضوع Cloud Pub/Sub.
4. تلقّي إشعارات
من الضروري إبقاء خادم الخلفية على اطّلاع دائم بحالة عمليات الشراء لتقديم أفضل تجربة للمستخدمين في تطبيقك. على سبيل المثال، عندما يُكمل المستخدم عملية شراء بنجاح من خلال الدفع في التطبيق، يجب أن يتلقّى المحتوى في حسابه في أقرب وقت ممكن.
ويتطلّب ذلك رصد عملية الشراء وإكمالها ومعالجتها في الوقت المناسب. توفّر واجهة برمجة التطبيقات Play Billing Library طرقًا متعدّدة لاكتشاف عمليات الشراء في تطبيقك. وعند رصد عملية شراء مكتملة، يجب أن يرسل تطبيقك إشعارًا إلى خادم الخلفية للتحقّق من عملية الشراء، ومنح المحتوى للمستخدم المناسب، ثم إرسال إشعار إلى Google بأنّه تمّت معالجة عملية الشراء. ومع ذلك، قد يحدث ألا يرصد تطبيقك عملية الشراء في الوقت المناسب لأسباب مختلفة. على سبيل المثال، يمكن للمستخدم إجراء عملية شراء ناجحة وتلقّي تأكيد من Google، ولكن يفقد الجهاز إمكانية الاتصال بالشبكة قبل أن يتلقّى الجهاز وتطبيقك إشعارًا من خلال واجهة Play Billing Library. توفّر الإشعارات في الوقت الفعلي عناصر تحكّم إضافية من جهة الخادم لمساعدتك في إدارة عمليات الشراء حتى إذا واجه تطبيق المستخدم مشاكل. تضمن إشعارات 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. للمصادقة على Security Command Center، عليك إعداد "بيانات الاعتماد التلقائية للتطبيق". راجِع مقالة إعداد المصادقة لبيئة تطوير محلية.
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- إرفاق معرّفات المستخدمين في مسار الشراء داخل تطبيقك
عندما يتلقّى الخادم رسالة الإشعارات في الوقت الفعلي بشأن تعديل حالة الشراء، يجب أن يعرف الخادم المستخدم الذي أجرى عملية الشراء لمعالجتها، مثل تسليم المحتوى إلى المستخدم الصحيح. يمكنك تحقيق ذلك من خلال إرفاق أي معرّفات مستخدم لديك للمستخدم الذي يجري عملية الشراء باستخدام 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. يجب إجراء ما يلي في خادم الخلفية:
- حلِّل
purchaseTokenمن رسالة Pub/Sub. عليك الاحتفاظ بسجلّ لجميع قيمpurchaseTokenلكل عمليات الشراء. - تأكَّد من أنّ قيمة
purchaseTokenلعملية الشراء الحالية لا تتطابق مع أي قيمpurchaseTokenسابقة.purchaseTokenفريد على مستوى العالم، لذا يمكنك استخدام هذه القيمة بأمان كمفتاح أساسي في قاعدة البيانات. - استخدِم نقطة النهاية purchases.products:get في Google Play Developer API للتحقّق من خلال Google أنّ عملية الشراء قانونية.
- إذا كانت عملية الشراء قانونية ولم يتم استخدامها في الماضي، يمكنك بعد ذلك منح إذن الوصول إلى المنتج داخل التطبيق أو الاشتراك بأمان.
- يجب منح إذن الوصول فقط عندما تكون حالة الشراء
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".
8. الاختبار باستخدام برنامج Play Billing Lab
ولإطلاق التطبيق بثقة، عليك اختبار عملية الدمج طوال فترة التطوير. Play Billing Lab هو تطبيق Android مجاني يساعد المطوّرين في اختبار تكامل تطبيقاتهم مع نظام الفوترة في Google Play، ما يوفّر لهم طريقة سهلة ومريحة لاختبار ميزات "الفوترة في Play" وتحقيق التكامل مع التطبيقات بسرعة أكبر وإطلاقها بثقة أعلى.
توفّر أداة Play Billing Lab ميزات اختبار متنوعة للمساعدة في اختبار سيناريوهات مختلفة، بما في ذلك:
- غيِّر بلد Play من داخل تطبيق Play Billing Lab وطبِّق الإعدادات على اختبارك. يتيح ذلك اختبار تجارب المستخدم المخصّصة في بلدان أو مناطق مختلفة بغض النظر عن الموقع الجغرافي الذي يجري فيه المختبِر الاختبار.
- اختبار الفترات التجريبية أو العروض التمهيدية بشكل متكرّر باستخدام الحساب نفسه
- اختبار تغييرات أسعار الاشتراكات بدون التأثير في المشتركين النشطين الآخرين
- محاكاة رمز الاستجابة في Play Billing Library لاختبار سيناريوهات الأخطاء المختلفة
- تسريع عمليات تجديد الاشتراك لتسريع الاختبار
- الاختبار باستخدام طرق دفع حقيقية لتجاوز بعض إشارات المخاطر في مسار الشراء
نضيف باستمرار إمكانات اختبار جديدة إلى تطبيق 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 Billing Lab للحصول على رمز الاستجابة الذي ضبطته في "محاكي الاستجابة" في Play Billing Lab.
تفعيل اختبار تجاوزات الفوترة في Play Billing Library
لتفعيل التواصل بين "محاكي الردود" وتطبيقك، عليك أولاً تفعيل اختبار عمليات إلغاء الفوترة في 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 Billing Lab".
عند نشر تطبيقك في بيئة الإنتاج بعد الاختبار، عليك إما استخدام ملف AndroidManifest.xml منفصل لا يتضمّن علامات البيانات الوصفية هذه أو التأكّد من إزالة هذه العلامات من ملف AndroidManifest.xml.
محاكاة أخطاء Play Billing Library
لاختبار الأخطاء المحاكية في Play Billing Library، عليك أولاً ضبط رمز الاستجابة في تطبيق Play Billing Lab، ثم إجراء الاختبار في تطبيقك.
ضبط رمز استجابة
- سجِّل الدخول إلى تطبيق Play Billing Lab باستخدام حساب مختبِر مرخَّص لتطبيقك. تعرض الصورة التالية لوحة بيانات Play Billing Lab، بما في ذلك بطاقة محاكي الردود.

- انقر على إدارة في بطاقة "محاكي الاستجابة" للانتقال إلى شاشة "محاكي الاستجابة".
- عندما يُطلب منك ذلك، اسمح بتلقّي إشعارات من تطبيق Play Billing Lab للاطّلاع على حالة ربط تطبيقك.
- فعِّل خيار "محاكاة استجابة Play Billing Library" إذا لم يكن مفعَّلاً.

- اختَر رمز استجابة لواجهات برمجة التطبيقات Play Billing Library التي تريد اختبارها. لمحاكاة الخطأ في عملية الشراء الاستهلاكية، اختَر رمز خطأ لواجهة برمجة التطبيقات
consumeAsync. يتم حفظ اختياراتك تلقائيًا. أصبح "محاكي الاستجابة" الآن جاهزًا لإرسال رموز الاستجابة المحدّدة إلى تطبيقك.
اختبار تطبيقك
يمكنك الآن اختبار تطبيقك للتأكّد من أنّ كل شيء يعمل على النحو المتوقّع في سيناريو الخطأ الذي تم ضبطه. افتح تطبيقك وشغِّل طريقة واجهة برمجة التطبيقات Play Billing Library. إذا كان تطبيقك يطلب إجراء مكالمة consumeAsync لاستهلاك عملية الشراء، سيتلقّى تطبيقك رمز الخطأ الذي تم ضبطه للتو. يمكنك التأكّد من أنّ تطبيقك يعمل بشكل صحيح عند ظهور رمز الخطأ وأنّ خادم الخلفية يعالج عملية الشراء بشكل صحيح.
بعد الانتهاء من الاختبار، ما عليك سوى إيقاف خيار "محاكاة استجابة Play Billing Library" لإيقاف محاكاة الاستجابة.
يمكنك الاطّلاع على مزيد من المعلومات حول الاختبار باستخدام Play Billing Lab أو الانتقال إلى "مركز المساعدة" للحصول على مزيد من المعلومات حول اختبار الفوترة داخل التطبيق باستخدام "مختبِرو الترخيص".
9- تهانينا!
لقد انتهيت من هذا الدرس التطبيقي حول الترميز وأصبحت الآن مؤهلاً لتحسين عملية تحقيق الربح من تطبيقك بشكل استراتيجي من أجل تحسين تجربة المستخدم، ما يؤدي إلى تحسين مستوى رضا المستخدمين والإحالات الناجحة المتمثّلة بعملية شراء ومعدّل توقّف المشتركين عن استخدام التطبيق.
من خلال الاستفادة من الإشعارات في الوقت الفعلي الخاصة بالمطوّرين وتطبيق Play Billing Lab المصاحب، يمكنك معالجة أحداث مراحل نشاط عمليات الشراء بشكل استباقي لكل من عمليات الشراء لمرة واحدة والاشتراكات.
باستخدام هذه الأدوات، يمكنك تنفيذ استراتيجيات فعّالة لجذب المستخدمين مجددًا، وحلّ مشاكل الدمج بسرعة، وتحسين تجربة المستخدم ومصادر الإيرادات في النهاية لإطلاق تطبيقك أو لعبتك بثقة.
من خلال إكمال هذا الدرس التطبيقي حول الترميز، ستكتسب المهارات اللازمة لإدارة رحلة الشراء بأكملها واختبار عملية التنفيذ بدقة باستخدام "مختبر الفوترة في Play"، ما يضمن تقديم تجربة مستخدم سلسة وتحقيق أقصى إمكانات تحقيق الربح على Google Play.