במאמר הזה מוסבר איך לשלב את ממשקי ה-API של Play Billing Library כדי להציע תשלומים חיצוניים באפליקציות שעומדות בדרישות. מידע נוסף על התוכנית זמין כאן.
הגדרה של ספריית החיובים ב-Play
מוסיפים את התלות בספריית החיובים ב-Play לאפליקציית Android. כדי להשתמש בממשקי ה-API של אמצעי תשלום חיצוניים, צריך להשתמש בגרסה 8.3 ואילך. אם אתם צריכים לבצע העברה מגרסה קודמת, עליכם לפעול לפי ההוראות במדריך ההעברה כדי לשדרג לפני שתתחילו בשילוב.
אתחול של לקוח החיוב
השלבים הראשונים בתהליך השילוב זהים לאלה שמתוארים במדריך לשילוב של מערכת החיוב של Google Play, עם כמה שינויים כשמפעילים את BillingClient:
- כדי לציין שאתם רוצים להציע תשלומים חיצוניים, אתם צריכים לקרוא לרכיב ה-method החדש
enableBillingProgram(EnableBillingProgramParams). - צריך לרשום
DeveloperProvidedBillingListenerלטיפול במקרים שבהם המשתמש בוחר לשלם באתר או באפליקציית תשלומים.
בדוגמה הבאה מוצגת אתחול של BillingClient עם השינויים האלה:
Kotlin
val purchasesUpdatedListener =
PurchasesUpdatedListener { billingResult, purchases ->
// Handle new Google Play purchase.
}
val developerProvidedBillingListener =
DeveloperProvidedBillingListener { details ->
// Handle user selection for developer provided billing option.
}
val billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.enableBillingProgram(
EnableBillingProgramParams.newBuilder()
.setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
.setDeveloperProvidedBillingListener(developerProvidedBillingListener)
.build())
.build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
// Handle new Google Play purchase.
}
};
private DeveloperProvidedBillingListener developerProvidedBillingListener =
new DeveloperProvidedBillingListener() {
@Override
public void onUserSelectedDeveloperBilling(
DeveloperProvidedBillingDetails details) {
// Handle user selection for developer provided billing option.
}
};
private BillingClient billingClient = BillingClient.newBuilder(context)
.setListener(purchasesUpdatedListener)
.enablePendingPurchases()
.enableBillingProgram(
EnableBillingProgramParams.newBuilder()
.setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
.setDeveloperProvidedBillingListener(developerProvidedBillingListener)
.build())
.build();
חיבור ל-Google Play
אחרי שמפעילים את BillingClient, מתחברים ל-Google Play כמו שמתואר במאמר חיבור ל-Google Play.
בדיקת הזכאות של המשתמשים
אחרי שמתחברים ל-Google Play, אפשר לבדוק אם המשתמש עומד בדרישות של תוכנית התשלומים החיצוניים באמצעות הקריאה לשיטה isBillingProgramAvailableAsync(). השיטה הזו מחזירה BillingResponseCode.OK אם המשתמש עומד בדרישות.
בדוגמה הבאה אפשר לראות איך בודקים את הזכאות:
Kotlin
billingClient.isBillingProgramAvailableAsync(
BillingProgram.EXTERNAL_PAYMENTS,
object : BillingProgramAvailabilityListener {
override fun onBillingProgramAvailabilityResponse(
billingProgram: Int, billingResult: BillingResult) {
if (billingResult.responseCode != BillingResponseCode.OK) {
// Handle failures such as retrying due to network errors,
// handling external payments unavailable, etc.
return
}
// External payments are available. Can proceed with generating an
// external transaction token.
})
Java
billingClient.isBillingProgramAvailableAsync(
BillingProgram.EXTERNAL_PAYMENTS,
new BillingProgramAvailabilityListener() {
@Override
public void onBillingProgramAvailabilityResponse(
int billingProgram, BillingResult billingResult) {
if (billingResult.getResponseCode() != BillingResponseCode.OK) {
// Handle failures such as retrying due to network errors,
// handling external payments unavailable, etc.
return;
}
// External payments are available. Can proceed with generating an external transaction token.
}
});
בקטע טיפול בתגובות מוסבר איך האפליקציה צריכה להגיב לקודי תגובה אחרים. אם משתמשים בתוספים של Kotlin, אפשר להשתמש ב-coroutines של Kotlin כדי שלא תצטרכו להגדיר מאזין נפרד.
הצגת מוצרים זמינים
אתם יכולים להציג למשתמש את המוצרים הזמינים באותו אופן כמו בשילוב של מערכת החיוב של Google Play. אחרי שהמשתמש רואה את המוצרים שזמינים לרכישה ובוחר מוצר לקנייה, צריך להפעיל את תהליך התשלום החיצוני כמו שמתואר בקטע על הפעלת תהליך התשלום החיצוני.
הכנה של טוקן עסקה חיצוני
כדי לדווח על עסקה חיצונית ל-Google Play, צריך ליצור אסימון עסקה חיצונית באמצעות ספריית החיוב של Play. צריך ליצור אסימון חדש של עסקה חיצונית בכל פעם שהמשתמש מבקר באתר או באפליקציה חיצוניים דרך External Payments API. אפשר לעשות זאת באמצעות קריאה ל-API createBillingProgramReportingDetailsAsync. צריך ליצור את האסימון מיד לפני הקריאה ל-launchBillingFlow.
Kotlin
val params =
BillingProgramReportingDetailsParams.newBuilder()
.setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
.build()
billingClient.createBillingProgramReportingDetailsAsync(
params,
object : BillingProgramReportingDetailsListener {
override fun onCreateBillingProgramReportingDetailsResponse(
billingResult: BillingResult,
billingProgramReportingDetails: BillingProgramReportingDetails?) {
if (billingResult.responseCode != BillingResponseCode.OK) {
// Handle failures such as retrying due to network errors.
return
}
val externalTransactionToken =
billingProgramReportingDetails?.externalTransactionToken
// Persist the external transaction token locally. Pass it to
// the external website using DeveloperBillingOptionParams when
// launchBillingFlow is called.
}
})
Java
BillingProgramReportingDetailsParams params =
BillingProgramReportingDetailsParams.newBuilder()
.setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
.build();
billingClient.createBillingProgramReportingDetailsAsync(
params,
new BillingProgramReportingDetailsListener() {
@Override
public void onCreateBillingProgramReportingDetailsResponse(
BillingResult billingResult,
@Nullable BillingProgramReportingDetails
billingProgramReportingDetails) {
if (billingResult.getResponseCode() != BillingResponseCode.OK) {
// Handle failures such as retrying due to network errors.
return;
}
String transactionToken =
billingProgramReportingDetails.getExternalTransactionToken();
// Persist the external transaction token locally. Pass it to
// the external website using DeveloperBillingOptionParams when
// launchBillingFlow is called.
}
});
אם משתמשים בתוספים של Kotlin, אפשר להשתמש ב-coroutines של Kotlin כדי שלא תצטרכו להגדיר מאזין נפרד.
הפעלת תהליך התשלומים החיצוניים
מפעילים את תהליך התשלום החיצוני על ידי קריאה ל-launchBillingFlow(), בדומה להפעלת תהליך רכישה עם שילוב של מערכת החיוב של Google Play, אבל עם פרמטר נוסף DeveloperBillingOptionParams שמציין שהאפליקציה רוצה להפעיל את תהליך התשלום החיצוני לרכישה הזו.
המודעה DeveloperBillingOptionParams חייבת לכלול את הפרטים הבאים:
billingProgramמוגדרת לתוכנית החיובEXTERNAL_PAYMENTS-
linkURIמוגדר ליעד הקישור -
launchModeLAUNCH_IN_EXTERNAL_BROWSER_OR_APPאם Google Play צריך לפתוח את הקישור אוCALLER_WILL_LAUNCH_LINKאם האפליקציה שלכם תפתח את הקישור.
כשהאפליקציה שלכם קוראת ל-launchBillingFlow() עם הערך DeveloperBillingOptionParams, מערכת החיוב של Google Play מבצעת את הבדיקה הבאה:
- המערכת בודקת אם המדינה שמוגדרת ב-Google Play של המשתמש היא מדינה שבה יש תמיכה בתשלומים חיצוניים (כלומר, מדינה נתמכת). אם המדינה של המשתמש ב-Google Play נתמכת, מערכת Google Play בודקת אם התשלומים החיצוניים מופעלים על סמך ההגדרה של BillingClient והאם
DeveloperBillingOptionParamsסופק.- אם הפעלתם תשלומים חיצוניים, בתהליך הרכישה יוצג למשתמש ממשק משתמש לבחירה.
- אם התשלומים החיצוניים לא מופעלים, תהליך הרכישה יציג את ממשק המשתמש הרגיל של מערכת החיוב של Google Play, בלי אפשרות בחירה למשתמש.
- אם המדינה שמוגדרת ב-Google Play של המשתמש לא נתמכת, בתהליך הרכישה מוצג ממשק המשתמש הרגיל של מערכת החיוב של Google Play, ללא אפשרות בחירה למשתמש.
המדינה ב-Play של המשתמש היא מדינה נתמכת |
המדינה של המשתמש ב-Play לא נתמכת |
|
הופעלו תשלומים חיצוניים (הגדרה של BillingClient ושל launchBillingFlow) |
המשתמש רואה את חוויית המשתמש של בחירת המשתמש |
חוויית המשתמש של מערכת החיוב הרגילה של Google Play |
תשלומים חיצוניים לא מופעלים (לא הופעלו במהלך ההגדרה של BillingClient או שלא סופקו DeveloperBillingOptionParams להפעלת launchBillingFlow) |
חוויית המשתמש של מערכת החיוב הרגילה של Google Play |
חוויית המשתמש של מערכת החיוב הרגילה של Google Play |
בקטע הקוד הבא אפשר לראות איך יוצרים DeveloperBillingOptionParams:
Kotlin
val developerBillingOptionParams =
DeveloperBillingOptionParams.newBuilder()
.setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
.setLinkUri("https://www.example.com/external/purchase")
.setLaunchMode(
DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
.build()
Java
DeveloperBillingOptionParams developerBillingOptionParams =
DeveloperBillingOptionParams.newBuilder()
.setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
.setLinkUri("https://www.example.com/external/purchase")
.setLaunchMode(
DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
.build();
טיפול בבחירת המשתמש
האופן שבו אתם מטפלים בשאר תהליך הרכישה משתנה בהתאם לבחירה של המשתמש: מערכת החיוב של Google Play או תשלום באתר שלכם.
כשהמשתמש בוחר לשלם באתר או באפליקציית תשלום
אם המשתמש בוחר לשלם באתר שלכם, Google Play קוראת ל-DeveloperProvidedBillingListener כדי להודיע לאפליקציה שהמשתמש בחר לשלם באתר שלכם או באפליקציית תשלום. בפרט, מתבצעת קריאה לשיטה onUserSelectedDeveloperBilling().
אם האפליקציה מגדירה את launchMode ל-LAUNCH_IN_EXTERNAL_BROWSER_OR_APP, מערכת Google Play תפעיל את הקישור. אם הערך של launchMode הוגדר ל-CALLER_WILL_LAUNCH_LINK, האפליקציה אחראית להפעלת הקישור.
כשמקשרים משתמשים לאפליקציית תשלומים, אתם אחראים לבדוק שהמשתמש כבר התקין את אפליקציית התשלומים במכשיר שלו.
אפשר להשתמש בטוקן הזה כדי לדווח על כל עסקה שנובעת מהבחירה הזו, כמו שמוסבר במדריך לשילוב עם ה-Backend.
כשהמשתמש בוחר במערכת החיוב של Google Play
אם המשתמש בוחר במערכת החיוב של Google Play, הוא ממשיך ברכישה דרך Google Play.
- מידע נוסף על טיפול ברכישות חדשות מתוך אפליקציות דרך מערכת החיוב של Google Play זמין במאמר עיבוד רכישות במדריך לשילוב הספרייה.
- במדריך לניהול מינויים יש מידע נוסף על רכישת מינויים, בקטע מינויים חדשים.
טיפול בשינויים במינוי
מפתחים שמשתמשים באמצעי תשלום חיצוניים צריכים לעבד את הרכישות דרך מערכת החיוב של Google Play או לדווח עליהן באמצעות externalTransactionId, בהתאם לבחירת המשתמש. שינויים במינויים קיימים שעברו עיבוד דרך האתר של המפתח יכולים להתבצע דרך אותה מערכת חיוב עד למועד התפוגה.
בקטע הזה מוסבר איך לטפל בכמה תרחישים נפוצים של שינויים במינוי.
תהליכי שדרוג ושדרוג לאחור
התהליכים של שינוי תוכנית מינוי, כולל שדרוג ושנמוך, צריכים להתבצע בצורה שונה בהתאם לאופן שבו המינוי נרכש במקור – דרך מערכת החיוב של Google Play או דרך האתר של המפתח.
חבילות שמוסיפים למינוי קיים, שמשתמשות באותו אמצעי תשלום ושמחויבות בתשלומים קבועים, נחשבות לשדרוגים. בתוספים אחרים, המשתמשים יכולים לבחור באיזו מערכת חיוב הם רוצים להשתמש. כדי להתחיל חוויית רכישה חדשה, משתמשים ב-launchBillingFlow(), כמו שמתואר במאמר בנושא הפעלת תהליך תשלום חיצוני.
מינויים שנרכשו דרך האתר של המפתח או דרך אפליקציית תשלומים
אם המשתמשים רכשו מינויים במקור דרך האתר של המפתח או דרך אפליקציית תשלומים אחרי שהם בחרו את האפשרות הרצויה, הם צריכים לשדרג או לשנמך את המינוי דרך האתר של המפתח או דרך אפליקציית התשלומים, בלי לעבור שוב את תהליך בחירת האפשרות הרצויה.
כדי לעשות את זה, צריך להפעיל את launchBillingFlow() כשמשתמש מבקש שדרוג או שדרוג לאחור. במקום לציין פרמטרים אחרים באובייקט SubscriptionUpdateParams, צריך להשתמש ב-setOriginalExternalTransactionId() ולציין את מזהה העסקה החיצוני של הרכישה המקורית.
צריך לספק גם את DeveloperBillingOptionParams בשיחה הזו. המסך לבחירת המשתמש לא מוצג, כי הבחירה של המשתמש לגבי הרכישה המקורית נשמרת לשדרוגים ולדאונגריידים. צריך ליצור טוקן חדש של עסקה חיצונית לעסקה הזו, כמו שמתואר כאן.
כשהשדרוג או השנמוך מסתיימים באמצעות האתר של המפתח או אפליקציית תשלום, צריך לדווח על עסקה חדשה באמצעות אסימון העסקה החיצוני שהתקבל דרך הקריאה הקודמת לרכישת המינוי החדש.
מינויים שנרכשו דרך מערכת החיוב של Google Play
באופן דומה, משתמשים שרכשו את המינוי הנוכחי שלהם דרך מערכת החיוב של Google Play אחרי שהם בחרו את מערכת החיוב, צריכים לעבור את תהליך החיוב הרגיל של Google Play. אסור להגדיר את DeveloperBillingOptionParams בשיחה אל launchBillingFlow.
ביטולים ושחזורים של מינויים
המשתמשים צריכים להיות מסוגלים לבטל את המינוי שלהם בכל שלב. כשמשתמש מבטל מינוי, יכול להיות שהסיום של זכות השימוש יידחה עד לסיום התקופה בתשלום. לדוגמה, אם משתמש מבטל מינוי חודשי באמצע החודש, יכול להיות שהוא יוכל להמשיך לגשת לשירות למשך שבועיים נוספים עד שהגישה שלו תוסר. במהלך התקופה הזו, המינוי עדיין פעיל מבחינה טכנית, כך שהמשתמש יכול להשתמש בשירות.
לא נדיר שהמשתמשים מחליטים לבטל את הביטול במהלך התקופה הפעילה הזו. במדריך הזה, הפעולה הזו נקראת שחזור. בקטעים הבאים מוסבר איך לטפל בתרחישי שחזור בשילוב של API חיצוני לתשלומים.
מינויים שנרכשו דרך האתר של המפתח
אם יש לכם מזהה עסקה חיצוני למינוי שבוטל, אין צורך להתקשר אל launchBillingFlow() כדי לשחזר את המינוי, ולכן לא מומלץ להשתמש בו להפעלה מסוג זה. אם משתמש משחזר את המינוי שלו בזמן שהוא עדיין בתקופה הפעילה של מינוי שבוטל, לא מתבצעת עסקה באותו זמן. אפשר פשוט להמשיך לדווח על חידושים כשתקופת המינוי הנוכחית מסתיימת והחידוש הבא מתבצע. כולל מקרים שבהם המשתמש מקבל קרדיט או מחיר מיוחד לחידוש המינוי כחלק מהשחזור (לדוגמה, מבצע כדי לעודד את המשתמש להמשיך את המינוי).
מינויים שנרכשו דרך מערכת החיוב של Google Play
בדרך כלל, המשתמשים יכולים לשחזר מינויים במערכת החיוב של Google Play. במקרה של מינויים שבוטלו ונרכשו במקור דרך מערכת החיוב של Google Play, המשתמש יכול לבטל את הביטול בזמן שהמינוי פעיל באמצעות התכונה הרשמה מחדש של Google Play. במקרה כזה, תקבלו התראה למפתחים בזמן אמת (RTDN) מסוג SUBSCRIPTION_RESTARTED בקצה העורפי, ולא יונפק אסימון רכישה חדש – האסימון המקורי ישמש להמשך המינוי. במדריך לניהול מינויים מוסבר איך לנהל שחזור במערכת החיוב של Google Play.
אפשר גם להפעיל שחזור במערכת החיוב של Google Play מתוך האפליקציה על ידי קריאה ל-launchBillingFlow(). במאמר לפני תפוגת המינוי – בתוך האפליקציה מוסבר איך עושים את זה. במקרה של משתמשים שעברו את תהליך בחירת המשתמש לרכישה המקורית (שבוטלה אבל עדיין פעילה), המערכת מזהה באופן אוטומטי את הבחירה שלהם ומציגה את ממשק המשתמש לשחזור הרכישות האלה. המשתמשים מתבקשים לאשר את הרכישה מחדש של המינוי דרך Google Play, אבל הם לא צריכים לעבור שוב את תהליך בחירת המשתמש. במקרה כזה, מונפק למשתמש טוקן רכישה חדש.
הקצה העורפי מקבל הודעה למפתחים בזמן אמת מסוג SUBSCRIPTION_PURCHASED, והערך של linkedPurchaseToken עבור סטטוס הרכישה החדש מוגדר כמו במקרה של שדרוג או שדרוג לאחור, עם טוקן הרכישה הישן של המינוי שבוטל.
הרשמה מחדש
אם תוקף המינוי פג לגמרי, בגלל ביטול או בגלל שהתשלום נדחה ולא שוחזר (השהיית חשבון שתוקפה פג), המשתמש צריך להירשם מחדש אם הוא רוצה להפעיל מחדש את ההרשאה.
אפשר גם להפעיל הרשמה מחדש דרך האפליקציה, בתהליך דומה להרשמה רגילה. המשתמשים צריכים להיות מסוגלים לבחור באיזו מערכת חיוב הם רוצים להשתמש. יכול להיות שתיקרא הפונקציה launchBillingFlow() במקרה הזה, כמו שמתואר במאמר בנושא הפעלת תהליך התשלומים החיצוניים.
טיפול בתגובות
אם מתרחשת שגיאה, יכול להיות שה-methods isBillingProgramAvailableAsync(), createBillingProgramReportingDetailsAsync() ו-launchBillingFlow() יספקו BillingResponseCode שאינו BillingResponseCode.OK. כדאי לטפל בקודי התגובה האלה באופן הבא:
-
BillingResponseCode.ERROR: זו שגיאה פנימית. אל תמשיכו בעסקה או בפתיחת האתר החיצוני. מנסים שוב על ידי קריאה חוזרת ל-API. -
BillingResponseCode.FEATURE_NOT_SUPPORTED: חנות Play במכשיר הנוכחי לא תומכת בממשקי ה-API של מערכות תשלום חיצוניות. אל תמשיכו בעסקה או בפתיחת האתר החיצוני. -
BillingResponseCode.DEVELOPER_ERROR: יש שגיאה בבקשה. כדאי להשתמש בהודעת ניפוי הבאגים כדי לזהות ולתקן את השגיאה לפני שממשיכים. -
BillingResponseCode.USER_CANCELED: לא ממשיכים בפתיחה של האתר או האפליקציה החיצוניים. קוראים שוב ל-launchBillingFlow()כדי להציג למשתמש את תיבת הדו-שיח עם המידע בפעם הבאה שמנסים להפנות את המשתמש אל מחוץ לאפליקציה. -
BillingResponseCode.BILLING_UNAVAILABLE: העסקה לא עומדת בדרישות לשימוש בתשלומים חיצוניים, ולכן חיוב המפתח לא יהיה זמין במסגרת התוכנית הזו. יכול להיות שהמשתמש לא נמצא במדינה שעומדת בדרישות של התוכנית הזו, או שהחשבון שלכם לא נרשם לתוכנית בהצלחה. אם זה המקרה השני, צריך לבדוק את סטטוס ההרשמה ב-Play Console. -
BillingResponseCode.NETWORK_ERROR,BillingResponseCode.SERVICE_DISCONNECTED,BillingResponseCode.SERVICE_UNAVAILABLE: אלה שגיאות זמניות שצריך לטפל בהן באמצעות מדיניות מתאימה של ניסיון חוזר. במקרה שלSERVICE_DISCONNECTED, צריך ליצור מחדש חיבור ל-Google Play לפני שמנסים שוב.
בדיקת קישורים לתשלומים חיצוניים
כדי לבדוק את השילוב של מערכת התשלומים החיצונית, צריך להשתמש בבודקי רישיונות. לא ננפיק חשבונית על עסקאות שבוצעו על ידי חשבונות לבדיקת רישיונות. מידע נוסף על הגדרת בודקי רישיונות זמין במאמר בנושא בדיקת חיובים על רכישות באפליקציות באמצעות רישוי אפליקציות.
השלבים הבאים
אחרי שתסיימו את השילוב באפליקציה, תוכלו לשלב את ה-backend.