1. מבוא
ב-codelab הזה תתמקדו ביצירת מוצר חד-פעמי, בשילוב האפליקציה עם ספריית החיובים ב-Play (PBL) ובניתוח הסיבות לנטישת רכישות.
קהל
ה-codelab הזה מיועד למפתחי אפליקציות ל-Android שמשתמשים בספריית החיובים ב-Google Play (PBL) או שרוצים להשתמש בה כדי לייצר הכנסות ממוצרים חד-פעמיים.
מה תלמדו...
- איך ליצור מוצרים בחיוב חד-פעמי ב-Google Play Console.
- איך משלבים את האפליקציה עם PBL.
- איך מעבדים רכישות חד-פעמיות של מוצרים מתכלים ומוצרים לא מתכלים ב-PBL.
- איך מנתחים נטישות של רכישות.
מה צריך...
- גישה אל Google Play Console עם חשבון פיתוח. אם אין לכם חשבון פיתוח, אתם צריכים ליצור חשבון.
- אפליקציה לדוגמה ל-Codelab הזה שאפשר להוריד מ-GitHub.
- Android Studio.
2. פיתוח אפליקציה לדוגמה
אפליקציית הדוגמה מיועדת להיות אפליקציית Android פונקציונלית לחלוטין, עם קוד מקור מלא שמציג את ההיבטים הבאים:
- שילוב האפליקציה עם PBL
- אחזור מוצרים בחיוב חד-פעמי
- הפעלת תהליכי רכישה של מוצרים בחיוב חד-פעמי
- תרחישי רכישה שמובילים לתגובות החיוב הבאות:
BILLING_UNAVAILABLE
USER_CANCELLED
OK
ITEM_ALREADY_OWNED
בסרטון ההדגמה הבא אפשר לראות איך אפליקציית הדוגמה תיראה ותתנהג אחרי הפריסה וההפעלה שלה.
דרישות מוקדמות
לפני שיוצרים ומפעילים את האפליקציה לדוגמה, צריך לבצע את הפעולות הבאות:
- יוצרים חשבון פיתוח ב-Google Play Console. אם כבר יש לכם חשבון פיתוח, אתם יכולים לדלג על השלב הזה.
- יוצרים אפליקציה חדשה ב-Play Console. כשיוצרים אפליקציה, אפשר לציין כל שם אפליקציה לאפליקציה לדוגמה.
- מתקינים את Android Studio.
פיתוח פתרונות
המטרה של שלב ה-build הזה היא ליצור קובץ חתום של Android App Bundle של אפליקציית הדוגמה.
כדי ליצור את חבילת האפליקציה ל-Android:
- מורידים את האפליקציה לדוגמה מ-GitHub.
- יוצרים את האפליקציה לדוגמה. לפני שיוצרים את האפליקציה, משנים את שם החבילה שלה ואז יוצרים אותה. אם יש לכם חבילות של אפליקציות אחרות ב-Play Console, ודאו ששם החבילה שציינתם לאפליקציית הדוגמה הוא ייחודי.
הערה: בניית אפליקציית הדוגמה יוצרת רק קובץ APK שאפשר להשתמש בו לבדיקה מקומית. עם זאת, הפעלת האפליקציה לא מאחזרת מוצרים ומחירים כי המוצרים לא הוגדרו ב-Play Console, וזה מה שתעשו בהמשך ה-codelab הזה. - יוצרים קובץ Android App Bundle חתום.
השלב הבא הוא להעלות את חבילת האפליקציה ל-Android אל Google Play Console.
3. יצירת מוצר בחיוב חד-פעמי ב-Play Console
כדי ליצור מוצרים חד-פעמיים ב-Google Play Console, צריך שתהיה לכם אפליקציה ב-Play Console. יוצרים אפליקציה ב-Play Console, ואז מעלים את ה-App Bundle החתום שנוצר קודם.
יצירת אפליקציה
כדי ליצור אפליקציה:
- מתחברים אל Google Play Console באמצעות חשבון המפתח.
- לוחצים על יצירת אפליקציה. ייפתח הדף יצירת אפליקציה.
- מזינים את שם האפליקציה, בוחרים את שפת ברירת המחדל ופרטים נוספים שקשורים לאפליקציה.
- לוחצים על יצירת אפליקציה. כך נוצרת אפליקציה ב-Google Play Console.
עכשיו אפשר להעלות את קובץ ה-App Bundle החתום של האפליקציה לדוגמה.
העלאת קובץ App Bundle חתום
- מעלים את ה-App Bundle החתום למסלול הפצה לבדיקה פנימית ב-Google Play Console. רק אחרי ההעלאה אפשר להגדיר את התכונות שקשורות למונטיזציה ב-Play Console.
- לוחצים על בדיקה ופרסום > בדיקה > גרסה לבדיקה פנימית > יצירת גרסה חדשה.
- מזינים שם לגרסת האפליקציה ומעלים את קובץ חבילת האפליקציה החתום.
- לוחצים על הבא ואז על שמירה ופרסום.
עכשיו אפשר ליצור מוצרים בחיוב חד-פעמי.
יצירת מוצר בחיוב חד-פעמי
כדי ליצור מוצר בחיוב חד-פעמי:
- בGoogle Play Console, בתפריט הניווט הימני, עוברים אל מונטיזציה ב-Play > מוצרים > מוצרים חד-פעמיים.
- לוחצים על יצירת מוצר בחיוב חד-פעמי.
- מזינים את פרטי המוצר הבאים:
- מזהה מוצר: מזינים מזהה מוצר ייחודי. מזינים
one_time_product_01
. - (אופציונלי) תגים: מוסיפים תגים רלוונטיים.
- שם: מזינים שם למוצר. לדוגמה,
Product name
. - תיאור: מזינים תיאור של המוצר. לדוגמה,
Product description
. - (אופציונלי) מוסיפים תמונה של סמל: מעלים סמל שמייצג את המוצר.
- מזהה מוצר: מזינים מזהה מוצר ייחודי. מזינים
- לוחצים על הבא.
- מוסיפים אפשרות רכישה ומגדירים את הזמינות שלה לפי אזור. למוצר חד-פעמי צריך להיות לפחות אפשרות רכישה אחת, שבה מוגדר אופן הענקת ההרשאה, המחיר והזמינות האזורית. ב-codelab הזה, נוסיף את האפשרות הסטנדרטית קנייה למוצר.בקטע אפשרות רכישה, מזינים את הפרטים הבאים:
- המזהה של אפשרות הרכישה: מזינים את המזהה של אפשרות הרכישה. לדוגמה,
buy
. - סוג הרכישה: בוחרים באפשרות קנייה.
- (אופציונלי) תגים: מוסיפים תגים ספציפיים לאפשרות הרכישה הזו.
- (אופציונלי) לוחצים על אפשרויות מתקדמות כדי להגדיר את האפשרויות המתקדמות. לצורך ה-codelab הזה, אפשר לדלג על הגדרת האפשרויות המתקדמות.
- המזהה של אפשרות הרכישה: מזינים את המזהה של אפשרות הרכישה. לדוגמה,
- בקטע זמינות ומחירים, לוחצים על הגדרת מחירים > עריכת מחירים בכמות גדולה.
- בוחרים באפשרות מדינה או אזור. הפעולה הזו בוחרת את כל האזורים.
- לוחצים על המשך. תיפתח תיבת דו-שיח שבה אפשר להזין מחיר. מזינים 10 USD ולוחצים על אישור.
- לוחצים על שמירה ואז על הפעלה. אחרי שמסיימים, אפשרות הרכישה נוצרת ומופעלת.
לצורך ה-codelab הזה, יוצרים עוד 3 מוצרים חד-פעמיים עם מזהי המוצרים הבאים:
- consumable_product_01
- consumable_product_02
- consumable_product_03
אפליקציית הדוגמה מוגדרת לשימוש במזהי המוצרים האלה. אתם יכולים לספק מזהי מוצרים שונים, ובמקרה כזה תצטרכו לשנות את אפליקציית הדוגמה כדי להשתמש במזהה המוצר שסיפקתם.
פותחים את האפליקציה לדוגמה ב-Google Play Console ועוברים אל Monetize with Play (מונטיזציה באמצעות Play) > Products (מוצרים) > One-time products (מוצרים חד-פעמיים). לאחר מכן לוחצים על יצירת מוצר חד-פעמי וחוזרים על שלבים 3 עד 9.
סרטון על יצירת מוצר בחיוב חד-פעמי
בסרטון לדוגמה הבא מוצגים השלבים ליצירת מוצר בחיוב חד-פעמי שמתוארים למעלה.
4. שילוב עם PBL
במאמר הזה נסביר איך לשלב את האפליקציה עם ספריית החיובים ב-Play (PBL). בקטע הזה מפורטים השלבים העיקריים לשילוב, ומוצג קטע קוד לכל אחד מהשלבים. אפשר להשתמש בקטעי הקוד האלה כהנחיות להטמעה של השילוב בפועל.
כדי לשלב את האפליקציה עם PBL, מבצעים את השלבים הבאים:
- מוסיפים את התלות בספריית החיוב ב-Play לאפליקציית הדוגמה.
dependencies { val billing_version = "8.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
- מפעילים את BillingClient. BillingClient הוא ה-SDK של הלקוח שקיים באפליקציה שלכם ומתקשר עם ספריית החיובים ב-Play. בקטע הקוד הבא מוצג אופן האתחול של לקוח החיוב.
protected BillingClient createBillingClient() { return BillingClient.newBuilder(activity) .setListener(purchasesUpdatedListener) .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build()) .enableAutoServiceReconnection() .build(); }
- מתחברים ל-Google Play.קטע הקוד הבא מראה איך מתחברים ל-Google Play.
public void startBillingConnection(ImmutableList<Product> productList) { Log.i(TAG, "Product list sent: " + productList); Log.i(TAG, "Starting connection"); billingClient.startConnection( new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Query product details to get the product details list. queryProductDetails(productList); } else { // BillingClient.enableAutoServiceReconnection() will retry the connection on // transient errors automatically. // We don't need to retry on terminal errors (e.g., BILLING_UNAVAILABLE, // DEVELOPER_ERROR). Log.e(TAG, "Billing connection failed: " + billingResult.getDebugMessage()); Log.e(TAG, "Billing response code: " + billingResult.getResponseCode()); } } @Override public void onBillingServiceDisconnected() { Log.e(TAG, "Billing Service connection lost."); } }); }
- מאחזרים את פרטי המוצר החד-פעמיים.אחרי שמשלבים את האפליקציה עם PBL, צריך לאחזר את פרטי המוצר החד-פעמיים אל האפליקציה. בקטע הקוד הבא מוצג איך לאחזר את פרטי המוצר החד-פעמיים באפליקציה.
התגובה לבקשה להבאתprivate void queryProductDetails(ImmutableList<Product> productList) { Log.i(TAG, "Querying products for: " + productList); QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder().setProductList(productList).build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { @Override public void onProductDetailsResponse( BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) { // check billingResult Log.i(TAG, "Billing result after querying: " + billingResult.getResponseCode()); // process returned productDetailsList Log.i( TAG, "Print unfetched products: " + productDetailsResponse.getUnfetchedProductList()); setupProductDetailsMap(productDetailsResponse.getProductDetailsList()); billingServiceClientListener.onProductDetailsFetched(productDetailsMap); } }); }
ProductDetails
תהיה דומה לדוגמה הבאה:{ "productId": "consumable_product_01", "type": "inapp", "title": "Shadow Coat (Yolo's Realm | Play Samples)", "name": "Shadow Coat", "description": "A sleek, obsidian coat for stealth and ambushes", "skuDetailsToken": "<---skuDetailsToken--->", "oneTimePurchaseOfferDetails": {}, "oneTimePurchaseOfferDetailsList": [ { "priceAmountMicros": 1990000, "priceCurrencyCode": "USD", "formattedPrice": "$1.99", "offerIdToken": "<--offerIdToken-->", "purchaseOptionId": "buy", "offerTags": [] } ] }, { "productId": "consumable_product_02", "type": "inapp", "title": "Emperor Den (Yolo's Realm | Play Samples)", "name": "Emperor Den", "description": "A fair lair glowing with molten rock and embers", "skuDetailsToken": "<---skuDetailsToken--->", "oneTimePurchaseOfferDetails": {}, "oneTimePurchaseOfferDetailsList": [ { "priceAmountMicros": 2990000, "priceCurrencyCode": "USD", "formattedPrice": "$2.99", "offerIdToken": "<--offerIdToken-->", "purchaseOptionId": "buy", "offerTags": [] } ] }
- מפעילים את תהליך החיוב.
public void launchBillingFlow(String productId) { ProductDetails productDetails = productDetailsMap.get(productId); if (productDetails == null) { Log.e( TAG, "Cannot launch billing flow: ProductDetails not found for productId: " + productId); billingServiceClientListener.onBillingResponse( BillingResponseCode.ITEM_UNAVAILABLE, BillingResult.newBuilder().setResponseCode(BillingResponseCode.ITEM_UNAVAILABLE).build()); return; } ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder().setProductDetails(productDetails).build()); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); billingClient.launchBillingFlow(activity, billingFlowParams); }
- זיהוי ועיבוד של רכישות. בשלב הזה צריך:
- אימות הרכישה
- הענקת זכאות למשתמש
- הודעה למשתמש
- הודעה ל-Google על תהליך הרכישה
private void handlePurchase(Purchase purchase) { // Step 1: Send the purchase to your secure backend to verify the purchase following // https://developer.android.com/google/play/billing/security#verify // Step 2: Update your entitlement storage with the purchase. If purchase is // in PENDING state then ensure the entitlement is marked as pending and the // user does not receive benefits yet. It is recommended that this step is // done on your secure backend and can combine in the API call to your // backend in step 1. // Step 3: Notify the user using appropriate messaging. if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { for (String product : purchase.getProducts()) { Log.d(TAG, product + " purchased successfully! "); } } // Step 4: Notify Google the purchase was processed. // For one-time products, acknowledge the purchase. // This sample app (client-only) uses billingClient.acknowledgePurchase(). // For consumable one-time products, consume the purchase // This sample app (client-only) uses billingClient.consumeAsync() // If you have a secure backend, you must acknowledge purchases on your server using the // server-side API. // See https://developer.android.com/google/play/billing/security#acknowledge if (purchase.getPurchaseState() == PurchaseState.PURCHASED && !purchase.isAcknowledged()) { if (shouldConsume(purchase)) { ConsumeParams consumeParams = ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build(); billingClient.consumeAsync(consumeParams, consumeResponseListener); } else { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); billingClient.acknowledgePurchase( acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
5. ניתוח של נטישת רכישות
עד עכשיו, התגובות של החיובים ב-Play שהוצגו ב-codelab התמקדו בתרחישים מוגבלים כמו התגובות USER_CANCELLED, BILLING_UNAVAILABLE, OK ו-ITEM_ALREADY_OWNED. עם זאת, מערכת החיוב של Play יכולה להחזיר 13 קודי תגובה שונים שיכולים להיות מופעלים על ידי גורמים שונים בעולם האמיתי.
בקטע הזה מוסברות הסיבות לתשובות השגיאה USER_CANCELLED
ו-BILLING_UNAVAILABLE
, ומוצעות פעולות תיקון אפשריות שאפשר לבצע.
קוד שגיאה בתגובה USER_CANCELED
קוד התגובה הזה מציין שהמשתמש נטש את ממשק המשתמש של תהליך הרכישה לפני שהשלים את הרכישה.
סיבות אפשריות | אילו פעולות אפשר לבצע? |
|
|
קוד שגיאה של תגובה מסוג BILLING_UNAVAILABLE
קוד התגובה הזה מציין שלא הייתה אפשרות להשלים את הרכישה בגלל בעיה בספק התשלומים של המשתמש או באמצעי התשלום שהוא בחר. לדוגמה, תוקף כרטיס האשראי של המשתמש פג או שהמשתמש נמצא במדינה שלא נתמכת. הקוד הזה לא מצביע על שגיאה במערכת החיוב של Play עצמה.
סיבות אפשריות | אילו פעולות אפשר לבצע? |
|
|
אסטרטגיות לניסיון חוזר של קודי שגיאה בתגובה
אסטרטגיות יעילות לניסיון חוזר לתיקון שגיאות שניתנות לתיקון בספריית החיוב של Play (PBL) משתנות בהתאם להקשר, כמו אינטראקציות של משתמשים במהלך סשן (למשל במהלך רכישה) לעומת פעולות ברקע (למשל שאילתות לגבי רכישות בהמשך השימוש באפליקציה). חשוב להטמיע את האסטרטגיות האלה כי ערכים מסוימים של BillingResponseCode
מציינים בעיות זמניות שאפשר לפתור באמצעות ניסיון חוזר, בעוד שערכים אחרים הם קבועים ולא דורשים ניסיונות חוזרים.
במקרה של שגיאות שמתרחשות כשהמשתמש נמצא בסשן, מומלץ להשתמש באסטרטגיית ניסיון חוזר פשוטה עם מספר מקסימלי מוגדר של ניסיונות, כדי למזער את ההפרעות לחוויית המשתמש. לעומת זאת, עבור פעולות ברקע כמו אישור רכישות חדשות, שלא דורשות ביצוע מיידי, מומלץ להשתמש בגישה של השהיה לפני ניסיון חוזר (backoff) עם גידול אקספוננציאלי.
מידע מפורט על קודי תגובה ספציפיים ועל אסטרטגיות מומלצות לניסיון חוזר שמתאימות להם מופיע במאמר טיפול בקודי תגובה של BillingResult.
6. השלבים הבאים
- איך למקסם את השילוב של מערכת החיוב של Play
- חשוב לזכור לפעול לפי השיטות המומלצות לאימות ולעיבוד של רכישות בשרת העורפי המאובטח שלכם, ברגע שהמשתמשים מתחילים לקנות את המוצרים האלה.
מסמכי עזר
7. מעולה!
מעולה! הצלחת להשתמש ב-Google Play Console כדי ליצור מוצר חד-פעמי חדש, לבדוק קודי תגובה לחיוב ולנתח את הנטישות בתהליך הרכישה.
סקר
נשמח לקבל ממך משוב על ה-Codelab הזה. כדאי להקדיש כמה דקות למילוי הסקר שלנו.