הטמעה של מערכת החיוב של Play באפליקציית PWA

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

Digital Goods API

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

ב-30 בנובמבר 2021, יצאה גרסה ChromeOS 96 עם הטמעה של Digital Goods API 2.0.

גרסת המקור לניסיון של הגרסה הראשונה של Digital Goods API הסתיימה ב-30 בינואר 2022. לכן, הוצאנו אותה משימוש ועכשיו זמינה רק גרסה 2 של ה-API.

ב-23 ביוני 2022, גרסה ChromeOS 103 הושקה עם הטמעה של Digital Goods API 2.1. בגרסה הזו אין שינויים שעלולים לשבור את התאימות לאחור, והיא כוללת רק שיטות חדשות ושדות נוספים: listPurchaseHistory() ו-itemType.

הרשמה לגרסת מקור לניסיון

הערה: נכון לעכשיו, Digital Goods API זמין דרך Origin Trial – מנגנון שמאפשר למפתחים לקבל גישה מוקדמת לממשקי Web API חדשים. תצטרכו להירשם לגרסת הניסיון של Digital Goods API v2 ולבקש אסימון, שיהיה עליכם לספק בכל הדפים במקור.

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

Payment Request API

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

זיהוי תכונות של Digital Goods API

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

if ('getDigitalGoodsService' in window) {
  // Digital Goods API is supported!
} else {
  console.log('DigitalGoodsService is not available.');
  // Use another payment method
}

חיבור לשירות החיוב של Google Play

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

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

if ('getDigitalGoodsService' in window) {
  // Digital Goods API is supported!
  try {
    const service = await window.getDigitalGoodsService('https://play.google.com/billing');
    // Google Play Billing service is available
  } catch (error) {
    // Google Play Billing service is not available. Use another payment flow.
  }
}

קבלת פרטי פריט

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

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

בשיטה getDetails() צריך להשתמש ברשימה של מזהי פריטים שתואמים למזהי המוצרים של המוצרים והמינויים בתוך האפליקציה שיצרתם ב-Play Console.

const itemDetails = await service.getDetails(['product_1', 'product_2', 'product_3']);
for (const item of itemDetails) {
  // Display item information to user
  displayItem(item.title, item.description, item.price);
}

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

const localePrice = new Intl.NumberFormat(navigator.language, {
  style: 'currency',
  currency: item.price.currency,
}).format(item.price.value);

הערה: Digital Goods API לא מספק שיטה לקבלת רשימה של מזהי פריטים. במקום זאת, תצטרכו להוסיף אותם לקוד של הלקוח או לאחזר אותם משרת הקצה העורפי. ‫Google Play Developer API מאפשר לבצע שאילתה ברשימת מזהי הפריטים מהקצה העורפי. (מידע נוסף על הטמעה של רכיבי חיוב מרכזיים ב-Play בשרת הקצה העורפי לא משנה באיזה פתרון תבחרו, חשוב לוודא שמזהי הפריטים זהים לאלה שמופיעים ב-Play Console.

בגרסה 2.1 של ה-API, אחד מהשדות שמוחזרים על ידי getDetails() הוא itemType. זהו enum שבו הערך הוא ”product” או ”subscription”, כדי לציין אם הפריט התואם הוא מוצר או מינוי בתוך האפליקציה, בהתאמה. היכולת להבחין בין שני סוגי המוצרים יכולה להיות שימושית אם אתם צריכים להחיל טיפולים שונים על כל סוג מוצר. לדוגמה, יכול להיות שיש לכם דף ספציפי שבו המשתמשים יכולים להירשם למינוי, ודף אחר למוצרים אחרים שאינם מינויים. הוא גם עוזר לדעת באיזה מקור REST של Google Play Developer API צריך להשתמש בקצה העורפי (purchases.products או purchases.subscriptions).

רכישת פריט

אחרי שהמוצרים והפרטים מוצגים למשתמש, אפשר ליצור את תהליך הרכישה באמצעות Payment Request API. כשמשתמשים ב-API של מוצרים דיגיטליים, נדרש רק פרמטר קלט אחד: methodData.

מערכת החיוב של Play מאפשרת רכישה של פריט אחד בלבד בכל פעם. המחיר והפרטים של הפריט כבר ידועים לשרת של Play, ולכן הפרמטר details לא נחוץ. הסבר מפורט יותר זמין כאן.

משתמשים בפרמטר supportedMethods member of the methodData בפרמטר PaymentRequest כדי לציין ששיטת התשלום היא חיוב ב-Google Play, באמצעות המחרוזת "https://play.google.com/billing". לאחר מכן, במאפיין data, מעבירים את מזהה הפריט כערך של sku.

const paymentMethodData = [
  {
    supportedMethods: 'https://play.google.com/billing',
    data: {
      sku: item.itemId,
    },
  },
];

לאחר מכן יוצרים את בקשת התשלום ומפעילים את הפונקציה show() כדי להתחיל את תהליך התשלום:

const request = new PaymentRequest(paymentMethodData);
const paymentResponse = await request.show();

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

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

אחרי אימות הרכישה, קוראים ל-complete() בתגובת התשלום כדי לסיים את תהליך התשלום ולסגור את ממשק המשתמש של החיוב. אפשר גם להעביר מחרוזת אופציונלית result כדי לציין את מצב תהליך התשלום. הדפדפן מחליט אם לספק למשתמש אינדיקציה כלשהי לגבי התוצאה הזו. ‫Chrome לא יוצר רמזים שגלויים למשתמשים, ולכן מומלץ להציג הודעות שגיאה או הצלחה משלכם ב-PWA.

/* Changes were recently made so that the PaymentResponse `details` property returns the purchase token as `purchaseToken` instead of `token`. Note that `token` will be deprecated at some point in the future. To ensure that your app won't be affected by this, make the change to `purchaseToken` in your client code and use the latest version of Bubblewrap (v1.13.5 and later) to update and generate a new app package to upload to the Play Console. */
const { purchaseToken } = paymentResponse.details;

let paymentComplete;
if (validatePurchaseOnBackend(purchaseToken)) {
  paymentComplete = await paymentResponse.complete('success');
  // Let user know their purchase transaction has successfully completed and been verified
} else {
  paymentComplete = await paymentResponse.complete('fail');
  // Let user know their purchase transaction failed to verify
}

שדרוגים ושדרוגים לאחור של מינויים

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

  • sku: מזהה הפריט של המינוי החדש שאליו רוצים לשדרג או לשנמך.
  • oldSku: מזהה הפריט של המינוי הנוכחי של המשתמש.
  • purchaseToken: זהו אסימון הרכישה של המינוי הנוכחי של המשתמש. כמו שצוין קודם, מומלץ לעקוב אחרי אסימוני הרכישה בקצה העורפי. במקרה הזה ובמקרים אחרים, כדאי לשייך משתמש לרכישות הנוכחיות שלו ולטוקנים של הרכישות.
  • prorationMode: כך יחויב המינוי החדש כשהוא יחליף את המינוי הנוכחי של המשתמש.
מצב חיוב יחסי תיאור

immediateAndChargeProratedPrice

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

immediateAndChargeFullPrice

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

immediateWithoutProration

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

immediateWithTimeProration

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

בעיכוב

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

unknownSubscriptionUpgradeDowngradePolicy

לא הוגדרה מדיניות. מומלץ לא לעשות זאת.

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

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

const paymentMethod = [
  {
    supportedMethods: 'https://play.google.com/billing',
    data: {
      sku: item.itemId,
      oldSku: oldPurchase.itemId,
      purchaseToken: oldPurchase.purchaseToken,
      prorationMode: 'immediateAndChargeProratedPrice',
    },
  },
];

במקרה הזה, item הוא ItemDetails של המינוי החדש שהמשתמש מנסה לשדרג או לשדרג לאחור אליו, ו-oldPurchase הוא PurchaseDetails של המינוי הנוכחי של המשתמש.

אישור רכישה

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

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

כדאי לאשר רכישות משרת הקצה העורפי באמצעות Google Play Developer API. מומלץ להעניק הרשאות ואז לאשר את הרכישה יחד בשרת העורפי.

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

מימוש רכישה

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

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

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

// After the user purchases the item, send the purchase token and item ID to your backend to grant the entitlement and acknowledge it right away

. . .
// When the user uses the item or if it is a repeatable item, consume it so it’s available for purchase again.
service.consume(purchaseToken);
}

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

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

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

השיטה listPurchases() של Digital Goods API תחזיר רשימה של PurchaseDetails שמכילה את itemId ואת purchaseToken לכל אחת מהרכישות. תצטרכו להשתמש ב-Google Play Developer API בשרת העורפי כדי לבדוק את סטטוס הרכישות ולאשר אותן בהתאם. אתם צריכים:

  1. קוראים לשיטה listPurchases() של Digital Goods API בצד הלקוח כדי לאחזר את רשימת הרכישות של המשתמש.
  2. לכל רכישה, מעבירים את הערכים purchaseToken ו-itemId לקצה העורפי.
  3. במקרה הצורך, צריך להעניק זכאות במסד הנתונים של השרת העורפי.
  4. אחר כך מתקשרים ובודקים את acknowledgementState.
  5. אם הערך הוא 0 (עדיין לא אושר), צריך להתקשר אל:

מידע נוסף על אימות רכישות בשרת העורפי לפני הענקת הרשאות

היסטוריית רכישות

השיטה listPurchases תחזיר מידע על הרכישות הקיימות של המשתמש, אבל השיטה listPurchaseHistory() (בגרסה 2.1 של ה-API) תחזיר את הרכישה האחרונה שבוצעה על ידי המשתמש עבור כל פריט, בלי קשר לתוקף הרכישה, לביטול שלה או למימוש שלה. השיטה listPurchaseHistory() מחזירה רשימה של PurchaseDetails שמכילה את itemId ואת purchaseToken של כל רכישה. תצטרכו להשתמש בה עם Google Play Developer API בשרת העורפי כדי לאחזר מידע נוסף.

רכישות מחוץ לאפליקציה

רכישות מחוץ לאפליקציה הן רכישות שלא מתבצעות בתהליך הרגיל של רכישות מתוך האפליקציה. הרכישות האלה מתבצעות בדרך כלל בחנות Play ולא באפליקציה. יש שתי דרכים עיקריות שבהן משתמשים יכולים לבצע רכישה מחוץ לאפליקציה:

  • מימוש קוד שובר: בתפריט המשתמש של Play Store, בקטע מבצעים והתראות > מימוש קוד שובר או בקטע תשלומים ומינויים > מימוש קוד מתנה.
  • חידוש המינוי: בתפריט המשתמש בחנות Play, בקטע תשלומים ומינויים > מינויים. כאן המשתמשים יכולים לנהל את כל המינויים שלהם באפליקציות שונות. במינויים שתוקפם פג או שבוטלו, המשתמשים יכולים ללחוץ על 'הרשמה מחדש'.

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

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

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

מתן אפשרות למשתמשים לנהל מינויים

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

https://play.google.com/store/account/subscriptions?sku=sub-product-id&package=app-package-name

השלבים הבאים

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

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