קבלת תשלומים דרך חיוב ב-Google Play באמצעות Digital Goods API ו-Payment Request API

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

באפליקציות שנוצרו באמצעות פעילויות אינטרנט מהימנות ונשלחו דרך חנות Google Play, אפשר עכשיו להשתמש ב-Payment Request API וב-Digital Goods API כדי לשלב אותן עם החיוב ב-Google Play. היא זמינה ב-Chrome מגרסה 101 ואילך ל-Android ול-ChromeOS.

במדריך הזה תלמדו איך להוסיף תמיכה בחיוב ב-Google Play לאפליקציית ה-PWA שלכם ואיך לארוז אותה להפצה בחנות Google Play, גם ל-ChromeOS וגם ל-Play Store.

כדי להוסיף תמיכה בחיוב ב-Play לאפליקציית ה-PWA, תשתמשו בשני ממשקי API של פלטפורמת אינטרנט. Digital Goods API משמש לאיסוף פרטי מק"ט ולבדיקת רכישות והרשאות מחנות Play. Payment Request API משמש להגדרת חנות Google Play כאמצעי התשלום ולהשלמת תהליך הרכישה.

איך לייצר הכנסות מאפליקציות בחנות Play

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

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

דרישות

כדי להגדיר חיוב ב-Google Play, צריך:

עדכון הפרויקט Bubblewrap

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

גם ב-Bubblewrap התכונה הזו מוסתרת מאחורי דגל. כדי להפעיל אותו, צריך לשנות את הגדרות הפרויקט בקובץ twa-manifest.json שנמצא ברמה הבסיסית של הפרויקט, ולהפעיל גם את alphaDependencies וגם את התכונה playBilling:

  ...,
  "enableNotifications": true,
  "features": {
    "playBilling": {
      "enabled": true
    }
  },
  "alphaDependencies": {
    "enabled": true
  },
  ...

אחרי שמעדכנים את קובץ התצורה, מריצים את הפקודה bubblewrap update כדי להחיל את התצורה על הפרויקט, ואז את הפקודה bubblewrap build כדי ליצור חבילה חדשה ל-Android ולהעלות את החבילה הזו לחנות Play.

תכונת זיהוי של Digital Goods API וזמינות של חיוב ב-Google Play

נכון לעכשיו, Chrome תומך ב-Digital Goods API רק כש-PWA מופעל בתוך פעילות אינטרנט מהימנה. אפשר לבדוק אם הוא זמין על ידי בדיקה של getDigitalGoodsService באובייקט window:

if ('getDigitalGoodsService' in window) {
 // Digital Goods API is supported!
}

יכול להיות ש-Digital Goods API יהיה זמין בכל דפדפן וישמש בחנויות שונות. כדי לבדוק אם יש תמיכה בקצה העורפי של חנות מסוימת, צריך להפעיל את getDigitalGoodsService() ולהעביר את מזהה החנות כפרמטר. חנות Google Play מזוהה באמצעות המחרוזת https://play.google.com/billing:

if ('getDigitalGoodsService' in window) {
  // Digital Goods API is supported!
  try {
    const service =
        await window.getDigitalGoodsService('https://play.google.com/billing');
    // Google Play Billing is supported!

  } catch (error) {
    // Google Play Billing is not available. Use another payment flow.
    return;
  }
}

אחזור פרטים של מק"ט

‏Digital Goods API מספק את getDetails(), שמאפשר לאחזר את המידע כמו שם המוצר, התיאור והכי חשוב, המחיר, מצד העורפי של התשלומים.

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

const skuDetails = await service.getDetails(['shiny_sword', 'gem']);
for (item of skuDetails) {
  // Format the price according to the user locale.
  const localizedPrice = new Intl.NumberFormat(
      navigator.language,
      {style: 'currency', currency: item.price.currency}
    ).format(item.price.value);

  // Render the price to the UI.
  renderProductDetails(
        item.itemId, item.title, localizedPrice, item.description);
}

בניית תהליך הרכישה

למבנה ה-PaymentRequest יש שני פרמטרים: רשימה של אמצעי תשלום ורשימה של פרטי תשלום.

כשמשתמשים ב-Trusted Web Activity, צריך להשתמש באמצעי התשלום לחיוב ב-Google Play. לשם כך, מגדירים את https://play.google.com/billing כמזהה ומוסיפים את המק"ט של המוצר כחבר נתונים:

async function makePurchase(service, sku) {
   // Define the preferred payment method and item ID
   const paymentMethods = [{
       supportedMethods: "https://play.google.com/billing",
       data: {
           sku: sku,
       }
   }];

   ...
}

למרות שחובה לציין את פרטי התשלום, החיוב ב-Play תתעלם מהערכים האלה ותשתמש בערכים שהוגדרו כשיוצרים את המק"ט ב-Play Console, כדי שאפשר יהיה למלא אותם בערכים מזויפים:

const paymentDetails = {
    total: {
        label: `Total`,
        amount: {currency: `USD`, value: `0`}
    }
};

const request = new PaymentRequest(paymentMethods, paymentDetails);

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

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

...
const request = new PaymentRequest(paymentMethods, paymentDetails);
try {
    const paymentResponse = await request.show();
    const {purchaseToken} = paymentResponse.details;

    // Call backend to validate and acknowledge the purchase.
    if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
        // Optional: tell the PaymentRequest API the validation was
        // successful. The user-agent may show a "payment successful"
        // message to the user.
        const paymentComplete = await paymentResponse.complete('success');
    } else {
        // Optional: tell the PaymentRequest API the validation failed. The
        // user agent may show a message to the user.
        const paymentComplete = await paymentResponse.complete('fail');
    }
} catch(e) {
    // The purchase failed, and we can handle the failure here. AbortError
    // usually means a user cancellation
}
...

לחלופין, אפשר לקרוא ל-consume() באסימון purchase כדי לסמן את הרכישה כמשומשת ולאפשר את הרכישה מחדש.

כשמרכזים את כל הנתונים, שיטת קנייה נראית כך:

async function makePurchase(service, sku) {
    // Define the preferred payment method and item ID
    const paymentMethods = [{
        supportedMethods: "https://play.google.com/billing",
        data: {
            sku: sku,
        }
    }];

    // The "total" member of the paymentDetails is required by the Payment
    // Request API, but is not used when using Google Play Billing. We can
    // set it up with bogus details.
    const paymentDetails = {
        total: {
            label: `Total`,
            amount: {currency: `USD`, value: `0`}
        }
    };

    const request = new PaymentRequest(paymentMethods, paymentDetails);
    try {
        const paymentResponse = await request.show();
        const {purchaseToken} = paymentResponse.details;

        // Call backend to validate and acknowledge the purchase.
        if (await acknowledgePurchaseOnBackend(purchaseToken, sku)) {
            // Optional: consume the purchase, allowing the user to purchase
            // the same item again.
            service.consume(purchaseToken);

            // Optional: tell the PaymentRequest API the validation was
            // successful. The user-agent may show a "payment successful"
            // message to the user.
            const paymentComplete =
                    await paymentResponse.complete('success');
        } else {
            // Optional: tell the PaymentRequest API the validation failed.
            // The user agent may show a message to the user.
            const paymentComplete = await paymentResponse.complete('fail');
        }
    } catch(e) {
        // The purchase failed, and we can handle the failure here.
        // AbortError usually means a user cancellation
    }
}

בדיקת הסטטוס של רכישות קיימות

באמצעות Digital Goods API אפשר לבדוק אם למשתמש יש הרשאות קיימות (רכישות מתוך האפליקציה שעדיין לא נוצלו או מינויים פעילים) מרכישות קודמות שכבר בוצעו, בין אם במכשיר אחר, מהתקנה קודמת, למימוש של קוד פרסום או בפעם האחרונה שבה המשתמש פתח את האפליקציה.


const service =
     await window.getDigitalGoodsService('https://play.google.com/billing');
...
const existingPurchases = await service.listPurchases();
for (const p of existingPurchases) {
    // Update the UI with items the user is already entitled to.
    console.log(`Users has entitlement for ${p.itemId}`);
}

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

const service =
     await window.getDigitalGoodsService("https://play.google.com/billing");
...
const existingPurchases = await service.listPurchases();
for (const p of existingPurchases) {
    await verifyOrAcknowledgePurchaseOnBackend(p.purchaseToken, p.itemId);

    // Update the UI with items the user is already entitled to.
    console.log(`Users has entitlement for ${p.itemId}`);
}

בדיקת השילוב

במכשיר Android לצורכי פיתוח

אפשר להפעיל את Digital Goods API במכשיר Android לפיתוח לצורך בדיקה:

  • מוודאים שמשתמשים ב-Android מגרסה 9 ואילך עם מצב הפיתוח מופעל.
  • מתקינים את Chrome בגרסה 101 ואילך.
  • כדי להפעיל את הדגלים הבאים ב-Chrome, עוברים אל chrome://flags ומחפשים את הדגל לפי שם:
    • #enable-debug-for-store-billing
  • צריך לוודא שהאתר מתארח בפרוטוקול https. שימוש ב-http יגרום ל-API להיות undefined

במכשיר ChromeOS

Digital Goods API יהיה זמין בגרסה היציבה של ChromeOS החל מגרסה 89. בינתיים, אפשר לבדוק את Digital Goods API:

  • מתקינים את האפליקציה במכשיר מחנות Play.
  • צריך לוודא שהאתר מתארח בפרוטוקול https. שימוש ב-http יגרום לממשק ה-API להיות undefined

עם משתמשי בדיקה וצוותים של בקרת איכות

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

לאן ממשיכים?

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