איך להפיק את המקסימום מהשילוב של החיוב ב-Play

1. סקירה כללית

כדאי להיעזר ב-Codelab הזה של Google Play בנושא שילוב של ספריית החיובים ב-Play כדי לייעל את מקורות ההכנסה ולפרסם את האפליקציה בביטחון. ב-Codelab המובנה הזה מוסבר איך להגדיר, לבדוק ולהטמיע עיבוד אמין של רכישות, כדי שתוכלו לתמוך ביעדי המונטיזציה שלכם ולספק חוויית משתמש חלקה יותר.

נעזור לכם להגדיר התראות בזמן אמת למפתחים (RTDN) וPlay Billing Lab למינויים ולמוצרים בחיוב חד-פעמי באפליקציות ובמשחקים שלכם. תלמדו איך להפחית את נטישת המינויים, איך להגן על עצמכם מפני הונאות ושימוש לרעה, איך לבדוק מקרים קיצוניים, איך לדמות, לשחזר ולטפל בבעיות פוטנציאליות, ואיך להתנסות בשינויים במחירים ובמבצעים בלי להשפיע על המשתמשים.

בסיום הקורס, תהיו מוכנים ליישם אסטרטגיות להחזרת משתמשים, לפתור במהירות בעיות שילוב, לשפר את החזר ה-ROI, לספק חוויית פרימיום ולהשיק את האפליקציה ואת העדכונים שלה בביטחון.

דרישות מוקדמות

מה תלמדו

  • איך לנהל בצורה נכונה את מחזורי החיים של הרכישות כדי לשפר את הצמיחה באמצעות טכניקות לשיפור ההמרות של הרכישות ושימור הלקוחות
  • איך להגדיר התראות בזמן אמת למפתחים (RTDN) באמצעות Google Cloud Pub/Sub, שאפשר להשתמש בהן כדי להטמיע קמפיינים להחזרת לקוחות ואסטרטגיות אחרות לניהול מחזור החיים
  • איך מגדירים שרת קצה עורפי לקבלת התראות ולטיפול בהן בצורה מאובטחת, עם מעקב מדויק והרשאות, כדי לצמצם את הסיכון להחזרים לא מכוונים או להונאה ולשימוש לרעה
  • איך בודקים את השילוב ומדמים שגיאות באמצעות Play Billing Lab כדי לשפר את חוויית המשתמש ולצמצם את עלויות הפיתוח

הדרישות

2. אסטרטגיות מונטיזציה למינויים ולרכישות חד-פעמיות

כשמוכרים מוצרים דיגיטליים דרך האפליקציה, אסטרטגיית מונטיזציה מוצלחת צריכה להתייחס לחוויית המשתמש הכוללת, גם ברכישות חד-פעמיות וגם במינויים. חוויה חלקה יכולה להגדיל את הנכונות של הלקוחות לבצע רכישה ולצמצם את נטישת הלקוחות.

תהליך רכישה נפוץ של רכישה חד-פעמית או מינוי כולל כמה שלבים:

  1. המשתמש מעיין בפריטים כדי לקנות.
  2. מפעילים את תהליך הרכישה כדי שהמשתמש יוכל להשלים את הרכישה והתשלום.
  3. הודעה לשרת על השלמת הרכישה
  4. מאמתים את הרכישה בשרת.
  5. להעביר תוכן למשתמש.
  6. אישור המסירה של התוכן. במקרה של מוצרי צריכה, צריך להשתמש ברכישה בזמן המתאים כדי שהמשתמש יוכל לקנות את הפריט שוב.

שילוב באפליקציה מאפשר לכם להפעיל תהליכי רכישה ולנהל את חוויית המשתמש הזו, אבל חשוב לוודא שהקצה העורפי שלכם מעודכן לגבי ההרשאות שהמשתמשים רוכשים. המידע הזה חשוב למעקב אחרי רכישות ולניהול היבטים אחרים של חוויית המשתמש, כמו הרשאות בפלטפורמות שונות.

התראות בזמן אמת למפתחים (RTDN) הן דרך מצוינת לזהות את השלבים השונים במחזור החיים של הרכישה. אפשר להשתמש בהן ביעילות ככלי למעקב אחר הביצועים בזמן אמת, וגם ככלי להפעלת אסטרטגיות להחזרת מנויים.

לדוגמה: נניח שהמשתמש שלך רכש פריט חדש או שהתשלום שלו לא עבר והמינוי שלו נכנס לתקופת החסד. בעזרת RTDN מתאים, אפשר לזהות כמעט בזמן אמת שהסטטוס של המשתמש השתנה, ולפעול בהתאם. למשל, אפשר לעודד את המשתמש להשתמש בפריט שהוא קנה, או לשלוח לו תזכורות באימייל לעדכן את פרטי התשלום כדי להמשיך את המינוי.

התראות בזמן אמת על עסקאות הן גם דרך מצוינת להוסיף אמצעי בקרה נוספים בצד השרת, שיעזרו לכם לנהל רכישות גם אם יש בעיות בצד הלקוח של המשתמש. נניח שמשתמש ביצע רכישה בהצלחה וקיבל אישור מ-Google, אבל המכשיר שלו איבד את הקישוריות לרשת לפני שהמכשיר והאפליקציה קיבלו הודעה על הרכישה דרך מאזין הרכישות. עם RTDNs תקבלו התראה עצמאית דרך השרת, שתאפשר לכם לזהות את הרכישה ולהעניק את הזכאות למשתמש באופן עצמאי, ללא קשר לבעיה בלקוח, וכך תבטיחו תהליך רכישה אמין.

כאן אפשר לקרוא מידע נוסף על כל סוגי ההודעות על הפרת זכויות יוצרים שנתמכות כרגע. כל סוג של אות RTDN מציין סטטוס רכישה שונה. חשוב להטמיע מנגנוני טיפול מתאימים כדי להבטיח עיבוד נכון לפי הצורך בתרחישים לדוגמה שלכם. ב-codelab הזה נסביר איך לטפל בהודעת RTDN בשרת הקצה העורפי המאובטח שלכם, כולל קבלת ההודעה, אימות הרכישה והענקת הזכאות למשתמש הנכון, כשמשתמש משלים רכישה באפליקציה. בהמשך נסביר איך להגדיר הודעות RTDN באפליקציה.

3. הגדרת התראות בזמן אמת למפתחים (RTDN)

התראות בזמן אמת למפתחים (RTDN) מבוססות על Google Cloud Pub/Sub ומאפשרות לכם להגיב באופן מיידי לשינויים במצב הרכישה. ‫Cloud Pub/Sub הוא שירות מנוהל מלא להעברת הודעות בזמן אמת, שבעזרתו אפשר לשלוח ולקבל הודעות בין אפליקציות עצמאיות. ‫Google Play משתמש ב-Cloud Pub/Sub כדי לפרסם הודעות שנשלחות מאפליקציה בנושאים שאליהם נרשמתם.

כדי להפעיל RTDN, קודם צריך להגדיר את Cloud Pub/Sub באמצעות פרויקט Google Cloud Platform ‏ (GCP) משלכם, ואז להפעיל את ההתראות באפליקציה. אם אתם לא מכירים את GCP ואת Cloud Pub/Sub, תוכלו לעיין במדריך לתחילת העבודה.

יצירת נושא

כדי להתחיל לקבל התראות, צריך ליצור נושא ש-Google Play תפרסם בו את ההתראות. כדי ליצור נושא, פועלים לפי ההוראות שבמאמר יצירת נושא.

יצירת מינוי ל-Pub/Sub

כדי לקבל הודעות שפורסמו בנושא מסוים, צריך ליצור מינוי Pub/Sub לנושא הזה. כדי ליצור מינוי ל-Pub/Sub:

  1. כדאי לעיין במדריך למנויים ב-Cloud Pub/Sub כדי להבין איך להגדיר את המינוי כמינוי דחיפה או כמינוי שליפה. ב-codelab הזה נשתמש במינוי מסוג pull שבו שרת הקצה העורפי המאובטח שלכם צריך ליזום בקשות לשרת Cloud Pub/Sub כדי לאחזר הודעות.
  1. פועלים לפי ההוראות במאמר הוספת מינוי כדי ליצור מינוי.

הענקת הרשאות פרסום בנושא

ב-Cloud Pub/Sub נדרש להעניק ל-Google Play הרשאות לפרסום התראות בנושא.

  1. פותחים את מסוף Google Cloud.
  2. בוחרים את הפרויקט, מחפשים את Pub/Sub בסרגל החיפוש ועוברים לדף ההגדרות של Pub/Sub. חיפוש והגעה לדף ההגדרות של Pub/Sub
  3. מחפשים את הנושא ופותחים את הגדרת ההרשאות. פתיחת הגדרת ההרשאה
  4. לוחצים על ADD PRINCIPAL כדי להוסיף את חשבון השירות google-play-developer-notifications@system.gserviceaccount.com ולהעניק לו את התפקיד Pub/Sub Publisher. מוסיפים את חשבון השירות google-play-developer-notifications@system.gserviceaccount.com ומקצים לו את התפקיד 'פרסום הודעות ב-Pub/Sub'.
  5. כדי לסיים את הגדרת הנושא, לוחצים על שמירה. לוחצים על 'שמירה' כדי להשלים את הגדרת הנושא.

הפעלת RTDN באפליקציה

כדאי ללמוד איך להגדיר התראות בזמן אמת למפתחים (RTDN) כדי לשפר באופן משמעותי את השילוב של החיוב ב-Play. כדי לשפר את החזר ה-ROI הכולל, תוכלו לשפר את מהימנות הרכישות באמצעות הודעות מותאמות אישית, וגם למנוע הונאות וניצול לרעה.

התראות RTDN מספקות עדכונים מיידיים משרת לשרת ישירות מ-Google Play לגבי אירועים חשובים, כמו חידוש מינויים, רכישות חדשות ובעיות בתשלום. הם עוזרים למערכות העורפיות שלכם להסתנכרן אוטומטית עם הסטטוס האמיתי של הרשאות המשתמשים, מעבר למגבלות בצד הלקוח, ומאפשרים לכם להגיב באופן מיידי ומתאים.

כדי להפעיל התראות בזמן אמת למפתחים באפליקציה:

  1. פותחים את Google Play Console.
  2. בוחרים את האפליקציה הרצויה.
  3. עוברים אל מונטיזציה באמצעות Play > הגדרת מונטיזציה.
  4. גוללים לקטע התראות בזמן אמת למפתחים.
  5. מסמנים את התיבה הפעלת התראות בזמן אמת.
  6. בשדה Topic name, מזינים את השם המלא של נושא Cloud Pub/Sub שהגדרתם קודם. שם הנושא צריך להיות בפורמט projects/{project_id}/topics/{topic_name}, כאשר project_id הוא המזהה הייחודי של הפרויקט, ו-topic_name הוא שם הנושא שנוצר קודם.
  7. לוחצים על שליחת הודעת בדיקה כדי לשלוח הודעת בדיקה. ביצוע פרסום לבדיקה עוזר לוודא שהכול מוגדר בצורה נכונה. אם הפרסום לבדיקה מצליח, מוצגת הודעה שהפרסום לבדיקה הצליח. אם צירפתם מינוי לנושא הזה, אתם אמורים לקבל את הודעת הבדיקה. לגבי מינוי מסוג pull, עוברים למינוי ב-Cloud Console, לוחצים על View Messages וממשיכים לשליפת ההודעות. כדי למנוע מסירה חוזרת על ידי 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 מספקת כמה דרכים לזיהוי הרכישות באפליקציה. אחרי זיהוי של רכישה שהושלמה, האפליקציה צריכה לשלוח הודעה לשרת העורפי כדי לאמת את הרכישה, להעניק את התוכן למשתמש הנכון ואז לשלוח ל-Google הודעה שהרכישה עובדה. עם זאת, יכול להיות שהאפליקציה לא זיהתה את הרכישה בזמן בגלל סיבות שונות. לדוגמה, משתמש יכול לבצע רכישה בהצלחה ולקבל אישור מ-Google, אבל הקישוריות לרשת במכשיר שלו תאבד לפני שהמכשיר והאפליקציה יקבלו התראה דרך הממשק של ספריית החיובים ב-Play. התכונה RTDN מספקת אמצעי בקרה נוספים בצד השרת, שיעזרו לכם לנהל רכישות גם אם יש בעיות בצד הלקוח של המשתמש. התכונה RTDN מבטיחה שליחת התראות עצמאיות לשרת שלכם כשסטטוס הרכישה משתנה, כך שתוכלו לזהות את השינויים בסטטוס הרכישה כמעט באופן מיידי דרך נתיב שני, בנפרד מבעיות פוטנציאליות אצל הלקוח, וכך להבטיח תהליך רכישה אמין יותר.

בקטע הזה תבנו מנוי שיקבל את ההודעות שנשלחות לנושא ב-Cloud Pub/Sub באמצעות ספריות הלקוח של Cloud Pub/Sub. הספריות האלה זמינות במגוון שפות. בקטעים הבאים נסביר איך להוסיף את המנוי כדי לאמת את הרכישה, להעניק זכאות למשתמש הנכון ולאשר את הרכישה בשרת. ב-codelab הזה נשתמש ב-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, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר בנושא הגדרת אימות לסביבת פיתוח מקומית.

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. בשרת ה-Backend, צריך לבצע את הפעולות הבאות:

  1. מנתחים את purchaseToken מההודעה ב-Pub/Sub. חשוב לשמור תיעוד של כל הערכים של purchaseToken לכל הרכישות.
  2. מוודאים שהערך של purchaseToken עבור הרכישה הנוכחית לא זהה לערכים קודמים של purchaseToken. הערך של purchaseToken הוא ייחודי באופן גלובלי, כך שאפשר להשתמש בו בבטחה כמפתח ראשי במסד הנתונים.
  3. כדי לוודא שרכישה היא לגיטימית, אפשר להשתמש בנקודת הקצה purchases.products:get ב-ממשק API של Google Play למפתחים כדי לבצע אימות מול Google.
  1. אם הרכישה לגיטימית ולא נעשה בה שימוש בעבר, אפשר להעניק בבטחה זכאות לפריט באפליקציה או למינוי.
  2. צריך להעניק זכאות רק כשמצב הרכישה הוא PURCHASED, ולהקפיד לטפל ברכישות PENDING בצורה נכונה. מידע נוסף זמין במאמר בנושא טיפול בעסקאות בהמתנה.

בדוגמת הקוד הבאה נוצר לקוח API עבור ממשק API של Google Play למפתחים. נשתמש בו כדי לבצע קריאות ל-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);
   }
 }
}

לאחר מכן, מוסיפים את הלוגיקה לביצוע הקריאה ל-API ומשנים את הרכיב לקבלת נתונים שנבנה קודם כדי לאמת את הרכישה ולהעניק את הזכאות למשתמש הנכון.

ב-AndroidPublisherHelper, מוסיפים את השיטה הבאה כדי לאחזר את ProductPurchase מנקודת הקצה Purchases.products:get בממשק API של Google Play למפתחים.

 /* 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 בממשק API של Google Play למפתחים.

 /* 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 שהמשתמש קיבל הרשאה לרכישה. אחרי שהמשתמשים יאשרו את הרכישה, באפליקציה שלך חייב להופיע אישור על הרכישה.

מעולה! הצלחת לשלב את התכונה 'התראות בזמן אמת למפתחים' באפליקציה שלך, וכך אפשר לעבד רכישות בצורה מהימנה, כפי שמוסבר ב-Codelab הזה. כדי לוודא שהכול פועל בצורה מושלמת, כדאי להשתמש ב-Play Billing Lab, כלי ידידותי למשתמש שנועד לעזור לכם לבדוק את השילוב של מערכת החיוב ב-Play.

8. בדיקה באמצעות Play Billing Lab

כדי להשיק את האפליקציה בביטחון, מומלץ לבדוק את השילוב לאורך כל תהליך הפיתוח. ‫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, כי אין לכם שליטה רבה על התקשורת בין חנות Play לבין ה-Backend של Play. התכונה Response Simulator באפליקציית Play Billing Lab מאפשרת להגדיר תגובות של קודי שגיאה לספריית החיובים ב-Play, כדי לבדוק תרחישי שגיאה מורכבים שונים.

לדוגמה, הטמעתם את הלוגיקה באפליקציה כדי לצרוך את הרכישה אחרי שהאפליקציה מזהה שהרכישה הושלמה בהצלחה. אתם רוצים לבדוק את התרחיש שבו האפליקציה לא הצליחה להשתמש ברכישה בגלל כשל ברשת, ומקבל ה-RTDN בשרת הקצה העורפי שלכם קולט את ההודעה ומטפל ברכישה בצורה נכונה. אתם יכולים להשתמש בסימולטור התגובות כדי לדמות את התרחיש לצורך הבדיקה. בשלבים הבאים מוסבר איך לבצע בדיקה באמצעות סימולטור התגובות של Play Billing Lab.

בדיקה באמצעות סימולטור התגובות

כשבודקים באמצעות סימולטור התגובות, האפליקציה מתקשרת עם Play Billing Lab כדי לקבל את קוד התגובה שהגדרתם בסימולטור התגובות של Play Billing Lab.

הפעלת בדיקות של שינויים בחיוב בספריית החיובים ב-Play

כדי לאפשר תקשורת בין סימולטור התגובות לבין האפליקציה, צריך קודם להפעיל באפליקציה את בדיקת ההגדרות של שינוי ברירת המחדל של החיובים בספריית החיובים ב-Play. כדי לעשות זאת, מוסיפים את תגי המטא-נתונים הבאים לקובץ 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

כדי לבדוק באמצעות שגיאות מדומה של ספריית החיובים ב-Play, קודם צריך להגדיר את קוד התגובה באפליקציית Play Billing Lab, ואז לבצע את הבדיקה באפליקציה.

הגדרת קוד תגובה

  1. נכנסים לאפליקציית Play Billing Lab באמצעות חשבון של בודק רישיונות לאפליקציה. בתמונה הבאה מוצגת לוח הבקרה של Play Billing Lab,כולל הכרטיס Response Simulator (סימולטור התגובות).

לוח הבקרה של Play Billing Lab עם סימולטור התגובות

  1. לוחצים על ניהול בכרטיס של סימולטור התגובות כדי לעבור למסך של סימולטור התגובות.
  2. כשמתבקשים, מאשרים את ההתראות מ-Play Billing Lab כדי לראות את סטטוס החיבור של האפליקציה.
  3. מפעילים את המתג Simulate Play Billing Library response (סימולציה של תגובות לספריית החיובים ב-Play), אם הוא עדיין לא מופעל.

c841baa4c96bf306.png

  1. בוחרים קוד תגובה לממשקי ספריית החיובים ב-Play API שרוצים לבדוק. כדי לדמות את השגיאה ברכישה שצורכת את ה-API, בוחרים קוד שגיאה עבור consumeAsync. הבחירות שלכם נשמרות באופן אוטומטי. עכשיו סימולטור התגובות מוכן לשלוח את קודי התגובה שנבחרו לאפליקציה.

בדיקת האפליקציה

עכשיו אפשר לבדוק את האפליקציה כדי לוודא שהכול פועל כמו שצריך בתרחיש השגיאה שהוגדר. פותחים את האפליקציה ומפעילים את השיטה של ספריית החיובים ב-Play API. אם האפליקציה שלכם מבצעת את הקריאה consumeAsync כדי לצרוך את הרכישה, האפליקציה תקבל את קוד השגיאה שהגדרתם. אפשר לבדוק אם האפליקציה פועלת בצורה תקינה לפי קוד השגיאה, ולוודא ששרת הקצה העורפי מעבד את הרכישה בצורה תקינה.

אחרי שמסיימים את הבדיקה, פשוט משביתים את המתג Simulate Play Billing Library response (סימולציה של תגובות לספריית החיובים ב-Play) כדי להפסיק את הסימולציה של התגובה.

מידע נוסף על בדיקות באמצעות Play Billing Lab זמין במרכז העזרה בנושא בדיקת חיובים על רכישות באפליקציות באמצעות בודקי רישיונות.

9. מעולה!

סיימתם את ה-codelab הזה, ועכשיו יש לכם את כל הכלים לבצע אופטימיזציה אסטרטגית של המונטיזציה באפליקציה כדי לשפר את חוויית המשתמש, להגדיל את שביעות הרצון של המשתמשים, להגדיל את מספר ההמרות לרכישה ולצמצם את נטישת המנויים.

בעזרת התראות בזמן אמת למפתחים ואפליקציית הליווי Play Billing Lab, אתם יכולים לטפל באופן יזום באירועים במחזור החיים של הרכישה, גם של רכישות חד-פעמיות וגם של מינויים.

הכלים האלה מאפשרים לכם ליישם ביעילות אסטרטגיות מעורבות להחזרת משתמשים, לפתור במהירות בעיות שקשורות לשילוב, ובסופו של דבר לשפר את חוויית המשתמש ואת מקורות ההכנסה כדי להשיק את האפליקציה או המשחק בביטחון.

אחרי שתשלימו את ה-codelab הזה, יהיו לכם את הכישורים לנהל את כל תהליך הרכישה ולבדוק באופן יסודי את ההטמעה באמצעות Play Billing Lab. כך תוכלו להבטיח חוויית משתמש חלקה ולמקסם את פוטנציאל המונטיזציה שלכם ב-Google Play.