בנושא הזה נסביר איך לשלב את ספריית החיובים ב-Google Play עם את האפליקציה כדי להתחיל למכור מוצרים.
חיי הרכישה
זה תהליך הרכישה הרגיל של רכישה חד-פעמית או מינוי.
- צריך להראות למשתמשים מה הם יכולים לקנות.
- מפעילים את תהליך הרכישה כדי שהמשתמשים יאשרו את הרכישה.
- מאמתים את הרכישה בשרת.
- מספקים תוכן למשתמש.
- לאשר את מסירת התוכן. למוצרים מתכלים, כדי שהמשתמש יוכל לקנות אותו שוב.
מינויים מתחדשים באופן אוטומטי עד שהם מבוטלים. יש לך מינוי באמצעות המדינות הבאות:
- פעיל: המשתמש במצב ניהול תקין ויש לו גישה למינוי.
- בוטל: המשתמש ביטל את המינוי אבל עדיין יש לו גישה עד שהתוקף שלו פג.
- בתקופת חסד: משתמש נתקל בבעיית תשלום אבל עדיין יש לו גישה בזמן ש-Google מנסה שוב את אמצעי התשלום.
- בהמתנה: למשתמש הייתה בעיה בתשלום ואין לו יותר גישה בזמן Google מנסה שוב את אמצעי התשלום.
- מושהית: המשתמש השהה את הגישה שלו ואין לו גישה עד שהוא בקורות החיים שלו.
- התוקף פג: המשתמש ביטל את המינוי ואיבד את הגישה אליו. משתמש נחשב כנוטש כשהתוקף שלו פג.
אתחול החיבור ל-Google Play
השלב הראשון בשילוב עם מערכת החיוב של Google Play הוא להוסיף את ספריית החיובים ב-Google Play לאפליקציה שלך והפעלה של החיבור.
הוספת התלות של ספריית החיובים ב-Google Play
הוספת התלות של ספריית החיובים ב-Google Play אל build.gradle
של האפליקציה
קובץ כפי שמוצג:
מגניב
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing:$billing_version") }
אם משתמשים ב-Kotlin, מודול KTX של ספריית החיובים ב-Google Play כולל
תוספי Kotlin ותמיכה בקורוטינים שמאפשרים לכתוב אידיומטי
Kotlin כשמשתמשים בספריית החיובים של Google Play. כדי לכלול את הרכיבים האלה:
בפרויקט שלך, עליך להוסיף את התלות הבאה
קובץ build.gradle
כפי שמוצג:
מגניב
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
אתחול לקוח חיוב
לאחר שמוסיפים תלות בספריית החיובים ב-Google Play, צריך
כדי לאתחל מכונה BillingClient
. BillingClient
הוא המשבצת הראשית
ממשק התקשורת בין ספריית החיובים ב-Google Play
שאר האפליקציה. BillingClient
מספק שיטות נוחות, גם סינכרוניות
ואסינכרונית, לביצוע פעולות חיוב נפוצות רבות. מומלץ מאוד
שיש לכם חיבור BillingClient
פעיל אחד שפתוח בכל פעם כדי
להימנע מריבוי PurchasesUpdatedListener
קריאות חוזרות (callback) במהלך אירוע יחיד.
כדי ליצור BillingClient
, צריך להשתמש ב-newBuilder()
. אפשר להעביר כל הקשר
ל-newBuilder()
, ו-BillingClient
משתמש בו כדי לקבל הקשר של אפליקציה.
המשמעות היא שאין צורך לחשוש מדליפות זיכרון. כדי לקבל עדכונים בנושא
של רכישות, עליך לקרוא גם ל-setListener()
, להעביר הפניה אל
PurchasesUpdatedListener
המאזינים האלה מקבלים עדכונים לכל
רכישות באפליקציה שלך.
Kotlin
private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases -> // To be implemented in a later section. } private var billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() { @Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { // To be implemented in a later section. } }; private BillingClient billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build();
חיבור ל-Google Play
אחרי שיוצרים BillingClient
, צריך ליצור חיבור אל
Google Play.
כדי להתחבר אל Google Play, צריך להתקשר למספר startConnection()
. החיבור
הוא אסינכרוני, ועליך להטמיע
BillingClientStateListener
כדי לקבל התקשרות חזרה לאחר השלמת ההגדרה של
הלקוח הושלם ומוכן להגיש בקשות נוספות.
בנוסף, צריך להטמיע לוגיקה של ניסיונות חוזרים כדי לטפל בחיבורים שאבדו ל-Google Play.
כדי להטמיע לוגיקה של ניסיונות חוזרים, צריך לעקוף את onBillingServiceDisconnected()
של קריאה חוזרת, ולוודא שה-BillingClient
קורא
startConnection()
כדי להתחבר מחדש ל-Google Play לפני שמבצעים
בקשות נוספות.
הדוגמה הבאה ממחישה איך להתחיל חיבור ולבדוק שהוא מוכן לשימוש:
Kotlin
billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } override fun onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } })
Java
billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } });
הצגת מוצרים שזמינים לקנייה
לאחר יצירת החיבור ל-Google Play, אפשר לשלוח שאילתה של המוצרים הזמינים שלכם ולהציג אותם למשתמשים.
שליחת פרטי המוצר היא שלב חשוב לפני הצגת של המשתמשים, כי הוא מחזיר פרטי מוצרים מותאמים לשוק המקומי. עבור מינויים, צריך לוודא שתצוגת המוצר עומדת בכל סעיפי המדיניות של Play.
כדי לשלוח שאילתה על פרטי מוצר מתוך האפליקציה, צריך להתקשר למספר queryProductDetailsAsync()
.
כדי לטפל בתוצאה של הפעולה האסינכרונית, עליך לציין גם
שמטמיע את הממשק של ProductDetailsResponseListener
.
לאחר מכן אפשר לשנות את הערך של onProductDetailsResponse()
, כדי שתישלח התראה ל:
כשהשאילתה מסתיימת, כפי שמוצג בדוגמה הבאה:
Kotlin
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build() billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult, productDetailsList -> // check billingResult // process returned productDetailsList }
Java
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) { // check billingResult // process returned productDetailsList } } )
כשאתם שולחים שאילתה על פרטי מוצר, עליכם להעביר מופע של
QueryProductDetailsParams
שמציינת רשימת מחרוזות של מזהי מוצרים.
שנוצר ב-Google Play Console יחד עם ProductType
.
ProductType
יכול להיות ProductType.INAPP
למוצרים בחיוב חד-פעמי או
ProductType.SUBS
למינויים.
שליחת שאילתות עם תוספים של Kotlin
אם משתמשים בתוספים של Kotlin, אפשר לשלוח שאילתה על מוצר מתוך האפליקציה
באמצעות קריאה לפונקציית התוסף queryProductDetails()
.
queryProductDetails()
משתמשת בקורוטינים של Kotlin
להגדיר מאזין נפרד. במקום זאת, הפונקציה מושהית עד לביצוע השאילתה
מסתיים, ולאחר מכן אפשר לעבד את התוצאה:
suspend fun processPurchases() {
val productList = listOf(
QueryProductDetailsParams.Product.newBuilder()
.setProductId("product_id_example")
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
val params = QueryProductDetailsParams.newBuilder()
params.setProductList(productList)
// leverage queryProductDetails Kotlin extension function
val productDetailsResult = withContext(Dispatchers.IO) {
billingClient.queryProductDetails(params.build())
}
// Process the result.
}
לעיתים רחוקות, מכשירים מסוימים לא תומכים ב-ProductDetails
וב
queryProductDetailsAsync()
, בדרך כלל בגלל גרסאות מיושנות של Google Play
שירותים. כדי להבטיח תמיכה הולמת לתרחיש הזה, נלמד איך להשתמש
תכונות תאימות לאחור בהעברה של ספריית החיובים ב-Play 5
guide.
עיבוד התוצאה
תוצאות השאילתה נשמרות בספריית החיובים של Google Play ב-List
ProductDetails
אובייקטים. לאחר מכן אפשר להפעיל מגוון שיטות בכל
אובייקט אחד (ProductDetails
) ברשימה כדי להציג מידע רלוונטי על אפליקציה בתוך האפליקציה
של המוצר, כגון המחיר או התיאור שלו. כדי לצפות בפרטי המוצר הזמינים
מידע נוסף, אפשר לראות את רשימת השיטות במחלקה ProductDetails
.
לפני שמציעים פריט למכירה, צריך לבדוק שלמשתמש אין כבר בעלות על שימושי. אם למשתמש יש פריט מתכלה שעדיין נמצא בספריית הפריטים שלו, חייבים לצרוך את הפריט לפני שהם יוכלו לקנות אותו שוב.
לפני שמציעים מינוי, חשוב לוודא שהמשתמש עדיין לא רשום כמנוי. כמו כן, חשוב לשים לב לדברים הבאים:
- פרטי המוצר במסגרת המינוי להחזרת מוצרים של
queryProductDetailsAsync()
עד 50 מבצעים לכל מינוי. queryProductDetailsAsync()
מחזיר רק מוצרים שעבורם המשתמש כשיר/ה. אם המשתמש מנסה לרכוש הצעה שבשבילה הוא לא כשיר (לדוגמה, אם האפליקציה מציגה רשימה מיושנת של מוצרים שעומדים בדרישות), מערכת Play מודיעה למשתמשים שהם לא עומדים בדרישות), המשתמש יכול לבחור לרכוש את המינוי הבסיסי במקום זאת.
הפעלת תהליך הרכישה
כדי להתחיל תהליך רכישה מהאפליקציה, צריך להתקשר למוקד של launchBillingFlow()
מה-thread הראשי של האפליקציה. השיטה הזו מתייחסת אל
אובייקט BillingFlowParams
שמכיל את האובייקט הרלוונטי
התקבל אובייקט ProductDetails
מקריאה
queryProductDetailsAsync()
. כדי ליצור אובייקט BillingFlowParams
, צריך להשתמש
הכיתה BillingFlowParams.Builder
.
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ...; val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For One-time product, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user .setOfferToken(selectedOfferToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() // Launch the billing flow val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For one-time products, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call // ProductDetails.subscriptionOfferDetails() for a list of offers // that are available to the user. .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
השיטה launchBillingFlow()
מחזירה אחד מקודי התגובה המפורטים ב-
BillingClient.BillingResponseCode
. חשוב לבדוק את התוצאה הזו כדי
לוודא שאין שגיאות בהפעלת תהליך הרכישה. BillingResponseCode
של OK
מצביע על השקה מוצלחת.
בשיחה אל launchBillingFlow()
, המערכת תציג את חשבון Google
מסך רכישה ב-Play. איור 1 מציג מסך רכישה של מינוי:
![במסך הרכישה ב-Google Play מוצג מינוי
זמינים לרכישה](https://developer.android.google.cn/static/images/google/play/billing/purchase-screen.png?authuser=9&hl=he)
Google Play מתקשרת למספר onPurchasesUpdated()
כדי לספק את תוצאת הרכישה
ל-listener שמטמיע את PurchasesUpdatedListener
גרפי. ה-listener מצוין באמצעות ה-method setListener()
כאשר
אתחול הלקוח.
כדי לטפל בקודי תגובה אפשריים, עליכם להטמיע את onPurchasesUpdated()
.
הדוגמה הבאה מראה איך לבטל את onPurchasesUpdated()
:
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
Java
@Override void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
רכישה מוצלחת יוצרת מסך השלמת רכישה ב-Google Play, שדומה לזה איור 2.
![מסך השלמת הרכישה ב-Google Play](https://developer.android.google.cn/static/images/google/play/billing/purchase-success.png?authuser=9&hl=he)
רכישה מוצלחת גם יוצרת אסימון רכישה, שהוא מזהה שמייצג את המשתמש ואת מזהה המוצר של המוצר מתוך האפליקציה שהם רכשו. האפליקציות שלך יכולות לאחסן את אסימון הרכישה באופן מקומי, למרות שאנחנו מומלץ להעביר את האסימון לשרת העורפי המאובטח, שבו תוכלו לאמת את הרכישה ולהגן מפני הונאה. התהליך הזה מפורט יותר בקטע הבא.
המשתמש יקבל גם קבלה באימייל על העסקה שמכילה את מזהה ההזמנה, או מזהה ייחודי של העסקה. המשתמשים מקבלים אימייל עם מזהה הזמנה ייחודי בכל רכישה חד-פעמית של מוצר, וגם עבור המינוי הראשוני של רכישות וחידושים אוטומטיים קבועים עתידיים. אפשר להשתמש במזהה ההזמנה כדי לנהל החזרים כספיים ב-Google Play Console.
ציון מחיר מותאם אישית
אם אפשר להפיץ את האפליקציה למשתמשים באיחוד האירופי, יש להשתמש ב
שיטה setIsOfferPersonalized()
להצגת גילוי נאות למשתמשים כשמחיר הפריט
מותאמת אישית באמצעות קבלת החלטות אוטומטית.
![מסך הרכישה ב-Google Play, שמציין שהמחיר הותאם אישית עבור המשתמש.](https://developer.android.google.cn/static/images/google/play/billing/personalized-pricing.png?authuser=9&hl=he)
עליך להתייעץ עם סעיף 6 (1) (ea) CRD של Consumer Rights Directive 2011/83/EU כדי לקבוע אם המחיר שאתם מציעים למשתמשים הוא בהתאמה אישית.
setIsOfferPersonalized()
מקבל קלט בוליאני. כאשר true
, ממשק המשתמש של Play
שכולל את הגילוי הנאות. כאשר false
, ממשק המשתמש לא יחשוף את הגילוי הנאות. ברירת המחדל
הערך הוא false
.
מידע נוסף זמין במרכז העזרה לצרכנים.
מתבצע עיבוד של הרכישות
אחרי שמשתמש משלים רכישה, האפליקציה צריכה לעבד את הרכישה.
ברוב המקרים, האפליקציה מקבלת התראות על רכישות דרך
PurchasesUpdatedListener
אבל יש מקרים שבהם האפליקציה
יידע אותך לגבי רכישות על ידי חיוג אל BillingClient.queryPurchasesAsync()
כמו שמתואר במאמר אחזור רכישות.
בנוסף, אם יש לכם לקוח התראות בזמן אמת למפתחים ב-
בקצה העורפי המאובטח, תוכלו לרשום רכישות חדשות על ידי קבלת
subscriptionNotification
או oneTimeProductNotification
עם התראות על
רכישה חדשה. לאחר קבלת ההתראות האלה, אפשר להתקשר ל-Google Play
API למפתחים כדי לקבל את הסטטוס המלא ולעדכן את מצב הקצה העורפי שלך.
האפליקציה שלך צריכה לעבד רכישה באופן הבא:
- מאמתים את הרכישה.
- לתת תוכן למשתמש ולאשר את מסירת התוכן. אפשר לסמן את הפריט כפריט שנצרך כדי שהמשתמש יוכל לקנות אותו שוב.
כדי לאמת רכישה, קודם צריך לוודא שמצב הרכישה הוא
PURCHASED
. אם הרכישה היא PENDING
, עליך לעבד את
purchase כפי שמתואר במאמר טיפול בעסקאות בהמתנה. לרכישות
שהתקבלו מ-onPurchasesUpdated()
או queryPurchasesAsync()
,
צריך לאמת עוד את הרכישה כדי להבטיח לגיטימיות לפני שהאפליקציה מעניקה אישור
אם יש לכם הרשאה. כדי לקבל מידע נוסף על אימות רכישה, אפשר לעיין במאמר אימות רכישות
לפני שמעניקים הרשאות.
לאחר אימות הרכישה, האפליקציה מוכנה להעניק הרשאה ל
משתמש. אפשר לזהות את חשבון המשתמש שמשויך לרכישה באמצעות
ProductPurchase.obfuscatedExternalAccountId
הוחזר על ידי
Purchases.products:get
לרכישות של מוצרים מתוך האפליקציה
SubscriptionPurchase.obfuscatedExternalAccountId
הוחזר על ידי
Purchases.subscriptions:get
למינויים בצד השרת, או
obfuscatedAccountId
החל מ-Purchase.getAccountIdentifiers()
בצד הלקוח, אם הוגדר עם setObfuscatedAccountId
כאשר
בוצעה.
לאחר הענקת ההרשאה, האפליקציה צריכה לאשר את הרכישה. הזה אישור מדווח ל-Google Play על כך שהענקתם הרשאה עבור הרכישה.
התהליך להענקת הרשאה ולאישור הרכישה תלוי בגורמים הבאים: הרכישה היא מינוי מתכלה, מינוי שאינו מתכלה או מינוי.
מוצרים מתכלים
למוצרים מתכלים, אם לאפליקציה שלך יש קצה עורפי מאובטח, מומלץ להשתמש
Purchases.products:consume
כדי לצרוך רכישות בצורה אמינה. צריך לוודא שהמאפיינים
הרכישה לא נצפתה כבר על ידי בדיקת consumptionState
של
התוצאה של הקריאה ל-Purchases.products:get
. אם האפליקציה מיועדת ללקוחות בלבד
ללא קצה עורפי, צריך להשתמש ב-consumeAsync()
ספריית החיובים ב-Google Play. שתי השיטות עונות על האישור
ולציין שהאפליקציה שלך העניקה למשתמש הרשאה.
השיטות האלה גם מאפשרות לאפליקציה ליצור את המוצר החד-פעמי שתואם ל-
את אסימון הרכישה שהוזן שזמין לרכישה חוזרת. עם consumeAsync()
איתך
חייב גם להעביר אובייקט שמטמיע את ConsumeResponseListener
גרפי. האובייקט הזה מטפל בתוצאה של פעולת הצריכה. אפשר
לשנות את השיטה onConsumeResponse()
,
לאחר השלמת הפעולה, תופעל ספריית החיובים ב-Google Play.
הדוגמה הבאה ממחישה איך צריך להשתמש במוצר עם ספריית החיובים ב-Google Play עם אסימון הרכישה המשויך:
Kotlin
suspend fun handlePurchase(purchase: Purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. val purchase : Purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) } }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. Purchase purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); ConsumeResponseListener listener = new ConsumeResponseListener() { @Override public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } } }; billingClient.consumeAsync(consumeParams, listener); }
מוצרים שאינם מתכלים
כדי לאשר רכישות שלא ניתנות לצריכה, אם לאפליקציה שלך יש קצה עורפי מאובטח,
מומלץ להשתמש ב-Purchases.products:acknowledge
כדי לאשר בצורה אמינה
רכישות. צריך לוודא שהרכישה לא אושרה לפני כן על ידי
בדיקת acknowledgementState
מתוצאת הקריאה
Purchases.products:get
אם האפליקציה מיועדת ללקוח בלבד, צריך להשתמש ב-BillingClient.acknowledgePurchase()
מתוך
ספריית החיובים של Google Play באפליקציה שלכם. לפני שאתם מאשרים
הרכישה, האפליקציה שלך צריכה לבדוק אם היא כבר קיבלה אישור באמצעות
isAcknowledged()
בספריית החיובים ב-Google Play.
בדוגמה הבאה אפשר לראות איך לאשר רכישה באמצעות ספריית החיובים ב-Google Play:
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... suspend fun handlePurchase() { if (purchase.purchaseState === PurchaseState.PURCHASED) { if (!purchase.isAcknowledged) { val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) } } } }
Java
BillingClient client = ... AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ... void handlePurchase(Purchase purchase) { if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
מינויים
הטיפול במינויים דומה לזה של מוצרים שאינם מתכלים. אם אפשר, השתמשו
Purchases.subscriptions.acknowledge
מתוך
ממשק API של Google Play למפתחים כדי לאשר באופן מהימן את הרכישה מ-
הקצה העורפי מאובטח. מוודאים שהרכישה לא אושרה לפני כן על ידי
לבדוק את acknowledgementState
במשאב הרכישה מ-
Purchases.subscriptions:get
אחרת, תוכלו לאשר
מנוי באמצעות BillingClient.acknowledgePurchase()
מ
ספריית החיובים ב-Google Play אחרי הבדיקה isAcknowledged()
. הכול
רכישות ראשוניות של מינויים צריכות לכלול אישור. חידושי מינויים
לא צריך לקבל הכרה. לקבלת מידע נוסף על מתי המינויים
נדרש אישור. יש לעיין בנושא מכירת מינויים.
מתבצע אחזור של רכישות
האזנה לעדכוני רכישות באמצעות PurchasesUpdatedListener
לא
מספיקים כדי להבטיח שהאפליקציה תעבד את כל הרכישות. ייתכן
ייתכן שהאפליקציה לא מודעת לכל הרכישות שהמשתמש ביצע. הנה כמה דוגמאות
תרחישים שבהם אתם עלולים לאבד את המעקב אחר הרכישות באפליקציה שלכם או שהיא לא תהיה מודעת לרכישות:
- בעיות ברשת במהלך הרכישה: משתמש מבצע רכישה מוצלחת
ומקבל אישור מ-Google, אבל המכשיר שלו מתנתק מהרשת
לפני שהמכשיר מקבל הודעה על הרכישה
באמצעות
PurchasesUpdatedListener
. - מכשירים מרובים: משתמש קונה פריט במכשיר אחד ולאחר מכן מצפה לראות את הפריט כשהם מחליפים מכשיר.
- טיפול ברכישות שבוצעו מחוץ לאפליקציה: חלק מהרכישות, כמו למימוש מבצעים מחוץ לאפליקציה.
כדי לטפל במצבים כאלה, צריך לוודא שהאפליקציה
BillingClient.queryPurchasesAsync()
בשיטה onResume()
כדי
לוודא שכל הרכישות מעובדות בהצלחה, כפי שמתואר בעיבוד
רכישות.
הדוגמה הבאה מראה איך לאחזר נתונים של רכישות מינוי של משתמש.
הערה: queryPurchasesAsync()
מחזיר רק מינויים פעילים ו
רכישות חד-פעמיות שלא נוצלו.
Kotlin
val params = QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) // uses queryPurchasesAsync Kotlin extension function val purchasesResult = billingClient.queryPurchasesAsync(params.build()) // check purchasesResult.billingResult // process returned purchasesResult.purchasesList, e.g. display the plans user owns
Java
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) .build(), new PurchasesResponseListener() { public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) { // check billingResult // process returned purchase list, e.g. display the plans user owns } } );
טיפול ברכישות שבוצעו מחוץ לאפליקציה
רכישות מסוימות, כמו מימוש מבצעים, יכולות להתבצע מחוץ לאפליקציה. כשמשתמשים מבצעים רכישה מחוץ לאפליקציה, הם מצפים שהאפליקציה תופיע הודעה בתוך האפליקציה, או להשתמש במנגנון התראות כלשהו כדי לאפשר למשתמש לדעת שהאפליקציה קיבלה את הרכישה ועיבדה בצורה נכונה. מקובל עליי מנגנונים הם:
- הצגת חלון קופץ בתוך האפליקציה.
- להעביר את ההודעה לתיבת ההודעות בתוך האפליקציה, ולציין בבירור שהיא היא הודעה חדשה בתיבת ההודעות בתוך האפליקציה.
- להשתמש בהודעה של מערכת ההפעלה.
חשוב לזכור: האפליקציה יכולה להיות בכל מצב שבו היא מזהה את הרכישה. ייתכן אפילו שהאפליקציה שלך לא לאחר ביצוע הרכישה. המשתמשים מצפים לקבל את הרכישה כשהם ממשיכים להפעיל את האפליקציה, בלי קשר למצב שבו האפליקציה נמצאת.
עליך לזהות רכישות בלי קשר למצב שבו האפליקציה נמצאת בוצעה. עם זאת, יש כמה חריגים שבהם אנחנו עשויים לקבל את האישור. כדי לא להודיע למשתמש באופן מיידי שהפריט התקבל. לדוגמה:
- בשלב האקשן במשחק, שבו הצגת הודעה עלולה להסיח את הדעת משתמש. במקרה כזה, צריך להודיע למשתמש אחרי שהחלק של הפעולה מסתיים.
- במהלך קטעי מעבר, שבהם הצגת הודעה עלולה להסיח את דעת המשתמש. כאן עליכם להודיע למשתמש אחרי שקטע החיתוך מסתיים.
- במהלך המדריך הראשוני ותהליך ההגדרה של המשתמש, בחלקים של המשחק. ההמלצות שלנו מודיעים למשתמשים חדשים על הפרס מיד לאחר שהם פותחים את המשחק, או במהלך ההגדרה הראשונית של המשתמש. עם זאת, ניתן להמתין עד רצף המשחקים זמין כדי ליידע את המשתמש.
תמיד חשוב לזכור את המשתמש כשהוא מחליטים מתי ואיך להודיע למשתמשים על
רכישות שבוצעו מחוץ לאפליקציה. בכל פעם שמשתמש לא מקבל תשלום באופן מיידי
התראה, הם עלולים לבלבל אותם, והם עלולים להפסיק להשתמש באפליקציה, ליצור קשר עם המשתמש
או להתלונן על זה ברשתות החברתיות. הערה:
PurchasesUpdatedListener
רשום באפליקציה שלך
הקשר לטיפול בעדכונים בנושא רכישות, כולל רכישות שבוצעו מחוץ לארגון
של האפליקציה. המשמעות היא שאם תהליך הבקשה שלכם לא קיים,
PurchasesUpdatedListener
לא יקבל הודעה. לכן צריך לשפר את האפליקציה
קוראים לפונקציה BillingClient.queryPurchasesAsync()
בשיטה onResume()
בתור
שמוזכר בקטע אחזור רכישות.
טיפול בעסקאות בהמתנה
Google Play תומכת בעסקאות בהמתנה, או בעסקאות שמצריכות המרה אחת או שלבים נוספים בין הרגע שבו המשתמש מבצע רכישה לבין המועד שבו אמצעי התשלום לביצוע הרכישה נמצא בתהליך עיבוד. האפליקציה לא צריכה להעניק הרשאה לרכישות מהסוגים האלה עד ש-Google תודיע לכם אמצעי התשלום של המשתמש חויב בהצלחה.
לדוגמה, משתמש יכול ליזום עסקה על ידי בחירה בחנות פיזית שבו ישלמו מאוחר יותר במזומן. המשתמש מקבל קוד דרך בהודעה ובאימייל. כשהמשתמש מגיע לחנות הפיזית, יכול לממש את הקוד אצל הקופאי ולשלם במזומן. לאחר מכן Google שולחת התראה גם לך וגם למשתמש שהתשלום התקבל. לאחר מכן האפליקציה יכולה להעניק הרשאה למשתמש.
קוראים לפונקציה enablePendingPurchases()
כחלק מאתחול הפקודה
BillingClient
כדי להפעיל עסקאות בהמתנה באפליקציה. האפליקציה שלך חייבת
להפעיל ולתמוך בעסקאות בהמתנה עבור מוצרים בחיוב חד-פעמי. לפני
הוספת תמיכה, ודאו שאתם מבינים את מחזור החיים של רכישות בהמתנה
עסקאות.
כשהאפליקציה שלך מקבלת רכישה חדשה, דרך
PurchasesUpdatedListener
או כתוצאה משיחה
queryPurchasesAsync()
, צריך להשתמש בשיטה getPurchaseState()
כדי
לקבוע אם מצב הרכישה הוא PURCHASED
או PENDING
. אתם צריכים
להעניק הרשאה רק כשהמדינה (State) היא PURCHASED
.
אם האפליקציה שלך פועלת כשהמשתמש משלים את הרכישה,
מתבצעת שיחה חוזרת אל PurchasesUpdatedListener
, והPurchaseState
נקרא
PURCHASED
בשלב הזה, האפליקציה תוכל לעבד את הרכישה באמצעות
לעיבוד רכישות. האפליקציה צריכה להתקשר גם
queryPurchasesAsync()
בשיטה onResume()
של האפליקציה שלך כדי לטפל ברכישות
שעברו למצב PURCHASED
בזמן שהאפליקציה לא פעלה.
כשהרכישה עוברת מ-PENDING
אל
PURCHASED
, לקוח ההתראות בזמן אמת למפתחים מקבל
ONE_TIME_PRODUCT_PURCHASED
או
התראת SUBSCRIPTION_PURCHASED
. אם הרכישה תבוטל,
מקבל ONE_TIME_PRODUCT_CANCELED
או
התראת SUBSCRIPTION_PENDING_PURCHASE_CANCELED
. הדבר יכול להתרחש אם
הלקוח לא משלים את התשלום במסגרת הזמן הנדרשת. שימו לב:
יכולים להשתמש תמיד בממשק API של Google Play למפתחים כדי לבדוק את המצב הנוכחי
רכישה.
טיפול ברכישות בכמות גדולה
נתמך בגרסאות 4.0 ואילך של ספריית החיובים ב-Google Play. ב-Google Play, לקוחות יכולים לקנות יותר מפריט אחד של אותה אפליקציה מוצר בעסקה אחת על ידי ציון כמות מעגלת הרכישה. שלך האפליקציה צפויה לטפל ברכישות בכמות גדולה ולהעניק הרשאה בהתאם בכמות הרכישה שצוינה.
כדי לאשר רכישות בכמות גדולה, צריך לבדוק את לוגיקת הקצאת ההרשאות של האפליקציה
לכמות של פריט. אפשר לגשת לשדה quantity
דרך
ממשקי ה-API הבאים:
getQuantity()
מספריית החיובים ב-Google Play.Purchases.products.quantity
מ-Google Play Developer API.
אחרי שמוסיפים לוגיקה לטיפול ברכישות בכמות גדולה, צריך להפעיל את התכונה 'כמות מרובה' למוצר המתאים באפליקציה דף ניהול המוצר ב-Google Play Console.
שליחת שאילתה לגבי הגדרות החיוב של המשתמש
getBillingConfigAsync()
מציין את המדינה שעבורה המשתמש משתמש
Google Play.
אפשר להריץ שאילתה על הגדרת החיוב של המשתמש אחרי
ויוצרים BillingClient
. קטע הקוד הבא מתאר
איך להתקשר אל getBillingConfigAsync()
. צריך לטפל בתשובה באמצעות
מוטמעת BillingConfigResponseListener
. המאזינים האלה מקבלים
עדכונים לכל השאילתות של הגדרות החיוב שנשלחות מהאפליקציה שלך.
אם הערך של BillingResult
שהוחזר לא מכיל שגיאות, אפשר לבדוק את
השדה countryCode
באובייקט BillingConfig
כדי לקבל את ה-Play של המשתמש
מדינה.
Kotlin
// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
object : BillingConfigResponseListener {
override fun onBillingConfigResponse(
billingResult: BillingResult,
billingConfig: BillingConfig?
) {
if (billingResult.responseCode == BillingResponseCode.OK
&& billingConfig != null) {
val countryCode = billingConfig.countryCode
...
} else {
// TODO: Handle errors
}
}
})
Java
// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
new BillingConfigResponseListener() {
public void onBillingConfigResponse(
BillingResult billingResult, BillingConfig billingConfig) {
if (billingResult.getResponseCode() == BillingResponseCode.OK
&& billingConfig != null) {
String countryCode = billingConfig.getCountryCode();
...
} else {
// TODO: Handle errors
}
}
});