1. บทนำ
ในโค้ดแล็บนี้ คุณจะมุ่งเน้นที่การสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว การผสานรวมแอปกับ Play Billing Library (PBL) และวิเคราะห์สาเหตุที่ทำให้การซื้อลดลง
ผู้ชม
Codelab นี้มีไว้สำหรับนักพัฒนาแอป Android ที่ใช้ Play Billing Library (PBL) หรือต้องการใช้ PBL เพื่อสร้างรายได้จากผลิตภัณฑ์แบบครั้งเดียว
สิ่งที่คุณจะได้เรียนรู้...
- วิธีสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวใน Google Play Console
- วิธีผสานรวมแอปกับ PBL
- วิธีประมวลผลการซื้อไอเทมแบบเรียกเก็บเงินครั้งเดียวที่ใช้แล้วหมดไปและไอเทมแบบเรียกเก็บเงินครั้งเดียวที่อยู่ตลอดไปใน PBL
- วิธีวิเคราะห์การเลิกทำกลางคันระหว่างการซื้อ
สิ่งที่คุณต้องมี...
- สิทธิ์เข้าถึง Google Play Console ด้วยบัญชีนักพัฒนาแอป หากยังไม่มีบัญชีนักพัฒนาแอป คุณจะต้องสร้างบัญชี
- แอปตัวอย่างสำหรับโค้ดแล็บนี้ ซึ่งคุณดาวน์โหลดจาก GitHub ได้
- Android Studio
2. สร้างแอปตัวอย่าง
แอปตัวอย่างออกแบบมาให้เป็นแอป Android ที่ทำงานได้อย่างเต็มรูปแบบซึ่งมีซอร์สโค้ดที่สมบูรณ์ซึ่งแสดงให้เห็นถึงแง่มุมต่อไปนี้
- การผสานรวมแอปกับ PBL
- ดึงข้อมูลไอเทมแบบเรียกเก็บเงินครั้งเดียว
- เปิดตัวขั้นตอนการซื้อสำหรับไอเทมแบบเรียกเก็บเงินครั้งเดียว
- สถานการณ์การซื้อที่ทำให้เกิดการตอบกลับการเรียกเก็บเงินต่อไปนี้
BILLING_UNAVAILABLE
USER_CANCELLED
OK
ITEM_ALREADY_OWNED
วิดีโอเดโมต่อไปนี้แสดงลักษณะและการทำงานของแอปตัวอย่างหลังจากที่ติดตั้งใช้งานและเรียกใช้
สิ่งที่ต้องดำเนินการก่อน
ก่อนที่จะสร้างและติดตั้งใช้งานแอปตัวอย่าง ให้ทำดังนี้
- สร้างบัญชีนักพัฒนาแอป Google Play Console หากมีบัญชีนักพัฒนาแอปอยู่แล้ว ให้ข้ามขั้นตอนนี้
- สร้างแอปใหม่ใน Play Console เมื่อสร้างแอป คุณจะระบุชื่อแอปใดก็ได้สำหรับแอปตัวอย่าง
- ติดตั้ง Android Studio
สร้าง
วัตถุประสงค์ของขั้นตอนการสร้างนี้คือการสร้างไฟล์ Android App Bundle ที่ลงนามแล้วของแอปตัวอย่าง
หากต้องการสร้าง Android App Bundle ให้ทำตามขั้นตอนต่อไปนี้
- ดาวน์โหลดแอปตัวอย่างจาก GitHub
- สร้างแอปตัวอย่าง ก่อนสร้าง ให้เปลี่ยนชื่อแพ็กเกจของแอปตัวอย่าง แล้วจึงสร้าง หากคุณมีแพ็กเกจของแอปอื่นๆ ใน Play Console โปรดตรวจสอบว่าชื่อแพ็กเกจที่คุณระบุสำหรับแอปตัวอย่างนั้นไม่ซ้ำกัน
หมายเหตุ: การสร้างแอปตัวอย่างจะสร้างเฉพาะไฟล์ APK ที่คุณใช้สำหรับการทดสอบในเครื่องได้ อย่างไรก็ตาม การเรียกใช้แอปจะไม่ดึงผลิตภัณฑ์และราคาเนื่องจากยังไม่ได้กำหนดค่าผลิตภัณฑ์ใน Play Console ซึ่งคุณจะได้ทำใน Codelab นี้ - สร้าง Android App Bundle ที่ลงนามแล้ว
ขั้นตอนถัดไปคือการอัปโหลด Android App Bundle ไปยัง 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 ได้
- คลิกทดสอบและเผยแพร่ > การทดสอบ > รุ่นภายใน > สร้างรุ่นใหม่
- ป้อนชื่อรุ่นแล้วอัปโหลดไฟล์ App Bundle ที่ลงชื่อแล้ว
- คลิกถัดไป แล้วคลิกบันทึกและเผยแพร่
ตอนนี้คุณสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวได้แล้ว
สร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว
วิธีสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว
- ใน Google Play Console ให้ไปที่สร้างรายได้ด้วย Play > ผลิตภัณฑ์ > ผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว จากเมนูการนำทางด้านซ้าย
- คลิกสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว
- ป้อนรายละเอียดผลิตภัณฑ์ต่อไปนี้
- รหัสผลิตภัณฑ์: ป้อนรหัสผลิตภัณฑ์ที่ไม่ซ้ำกัน ป้อน
one_time_product_01
- (ไม่บังคับ) แท็ก: เพิ่มแท็กที่เกี่ยวข้อง
- ชื่อ: ป้อนชื่อผลิตภัณฑ์ เช่น
Product name
- คำอธิบาย: ป้อนคำอธิบายผลิตภัณฑ์ เช่น
Product description
- (ไม่บังคับ) เพิ่มรูปภาพไอคอน: อัปโหลดไอคอนที่แสดงถึงผลิตภัณฑ์
- รหัสผลิตภัณฑ์: ป้อนรหัสผลิตภัณฑ์ที่ไม่ซ้ำกัน ป้อน
- คลิกถัดไป
- เพิ่มตัวเลือกการซื้อและกำหนดค่าความพร้อมจำหน่ายสินค้าระดับภูมิภาค ผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวต้องมีตัวเลือกการซื้ออย่างน้อย 1 รายการ ซึ่งจะกำหนดวิธีการให้สิทธิ์ ราคา และความพร้อมจำหน่ายสินค้าระดับภูมิภาค สำหรับโค้ดแล็บนี้ เราจะเพิ่มตัวเลือกซื้อมาตรฐานสำหรับผลิตภัณฑ์ ในส่วนตัวเลือกการซื้อ ให้ป้อนรายละเอียดต่อไปนี้
- รหัสตัวเลือกการซื้อ: ป้อนรหัสตัวเลือกการซื้อ เช่น
buy
- ประเภทการซื้อ: เลือกซื้อ
- (ไม่บังคับ) แท็ก: เพิ่มแท็กที่เฉพาะเจาะจงสำหรับตัวเลือกการซื้อนี้
- (ไม่บังคับ) คลิกตัวเลือกขั้นสูงเพื่อกำหนดค่าตัวเลือกขั้นสูง คุณข้ามการกำหนดค่าตัวเลือกขั้นสูงได้เพื่อวัตถุประสงค์ของโค้ดแล็บนี้
- รหัสตัวเลือกการซื้อ: ป้อนรหัสตัวเลือกการซื้อ เช่น
- ในส่วนความพร้อมให้บริการและการกำหนดราคา ให้คลิกกำหนดราคา > แก้ไขราคาแบบเป็นกลุ่ม
- เลือกตัวเลือกประเทศ / ภูมิภาค ซึ่งจะเป็นการเลือกทุกภูมิภาค
- คลิกต่อไป ซึ่งจะเปิดกล่องโต้ตอบสำหรับป้อนราคา ป้อน 100 บาท แล้วคลิกใช้
- คลิกบันทึก แล้วคลิกเปิดใช้งาน ซึ่งจะสร้างและเปิดใช้งานตัวเลือกการซื้อ
สำหรับ Codelab นี้ ให้สร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวเพิ่มเติม 3 รายการโดยใช้รหัสผลิตภัณฑ์ต่อไปนี้
- consumable_product_01
- consumable_product_02
- consumable_product_03
แอปตัวอย่างได้รับการกำหนดค่าให้ใช้รหัสผลิตภัณฑ์เหล่านี้ คุณระบุรหัสผลิตภัณฑ์ที่แตกต่างกันได้ ในกรณีนี้ คุณจะต้องแก้ไขแอปตัวอย่างเพื่อใช้รหัสผลิตภัณฑ์ที่คุณระบุ
เปิดแอปตัวอย่างใน Google Play Console แล้วไปที่สร้างรายได้ด้วย Play > ผลิตภัณฑ์ > ผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว จากนั้นคลิกสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว แล้วทำซ้ำขั้นตอนที่ 3-9
วิดีโอการสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว
วิดีโอตัวอย่างต่อไปนี้แสดงขั้นตอนการสร้างไอเทมแบบเรียกเก็บเงินครั้งเดียวที่อธิบายไว้ก่อนหน้านี้
4. ผสานรวมกับ PBL
ตอนนี้เราจะมาดูวิธีผสานรวมแอปกับ Play Billing Library (PBL) ส่วนนี้อธิบายขั้นตอนระดับสูงสำหรับการผสานรวมและแสดงข้อมูลโค้ดสำหรับแต่ละขั้นตอน คุณสามารถใช้ข้อมูลโค้ดเหล่านี้เป็นแนวทางในการติดตั้งใช้งานจริงได้
หากต้องการผสานรวมแอปกับ PBL ให้ทำตามขั้นตอนต่อไปนี้
- เพิ่มทรัพยากร Dependency ของ Play Billing Library ลงในแอปตัวอย่าง
dependencies { val billing_version = "8.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
- เริ่มต้น BillingClient BillingClient คือ SDK ของไคลเอ็นต์ที่อยู่ในแอปและสื่อสารกับ Play Billing Library ข้อมูลโค้ดต่อไปนี้แสดงวิธีเริ่มต้นไคลเอ็นต์การเรียกเก็บเงิน
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 มุ่งเน้นไปที่สถานการณ์ที่จำกัด เช่น การตอบกลับ USER_CANCELLED, BILLING_UNAVAILABLE, OK และ ITEM_ALREADY_OWNED อย่างไรก็ตาม การเรียกเก็บเงินของ Play สามารถแสดงรหัสการตอบกลับที่แตกต่างกัน 13 รายการ ซึ่งอาจเกิดจากปัจจัยต่างๆ ในโลกแห่งความเป็นจริง
ส่วนนี้จะอธิบายสาเหตุของการตอบกลับข้อผิดพลาด USER_CANCELLED
และ BILLING_UNAVAILABLE
รวมถึงแนะนำการดำเนินการแก้ไขที่เป็นไปได้ซึ่งคุณสามารถนำไปใช้ได้
รหัสข้อผิดพลาดในการตอบกลับ USER_CANCELED
รหัสการตอบกลับนี้บ่งชี้ว่าผู้ใช้ละทิ้ง UI ของขั้นตอนการซื้อก่อนที่จะทำการซื้อให้เสร็จสมบูรณ์
สาเหตุที่เป็นไปได้ | คุณทำอะไรได้บ้าง |
|
|
รหัสข้อผิดพลาดในการตอบกลับ BILLING_UNAVAILABLE
รหัสการตอบกลับนี้หมายความว่าระบบไม่สามารถดำเนินการซื้อให้เสร็จสมบูรณ์ได้เนื่องจากมีปัญหาเกี่ยวกับผู้ให้บริการชำระเงินของผู้ใช้หรือรูปแบบการชำระเงินที่ผู้ใช้เลือก เช่น บัตรเครดิตของผู้ใช้หมดอายุแล้ว หรือผู้ใช้อยู่ในประเทศที่ไม่รองรับ รหัสนี้ไม่ได้บ่งบอกถึงข้อผิดพลาดเกี่ยวกับระบบการเรียกเก็บเงินของ Play เอง
สาเหตุที่เป็นไปได้ | คุณทำอะไรได้บ้าง |
|
|
กลยุทธ์การลองอีกครั้งสำหรับรหัสข้อผิดพลาดในการตอบกลับ
กลยุทธ์การลองใหม่ที่มีประสิทธิภาพสำหรับข้อผิดพลาดที่กู้คืนได้จาก Play Billing Library (PBL) จะแตกต่างกันไปตามบริบท เช่น การโต้ตอบของผู้ใช้ในเซสชัน (เช่น ระหว่างการซื้อ) กับการดำเนินการในเบื้องหลัง (เช่น การค้นหาการซื้อเมื่อแอปกลับมาทำงานต่อ) การใช้กลยุทธ์เหล่านี้มีความสำคัญเนื่องจากBillingResponseCode
ค่าบางค่าบ่งบอกถึงปัญหาชั่วคราวที่แก้ไขได้โดยการลองอีกครั้ง ในขณะที่ค่าอื่นๆ เป็นค่าถาวรและไม่จำเป็นต้องลองอีกครั้ง
สำหรับข้อผิดพลาดที่พบเมื่อผู้ใช้อยู่ในเซสชัน เราขอแนะนำให้ใช้กลยุทธ์การลองใหม่แบบง่ายๆ โดยกำหนดจำนวนครั้งสูงสุดที่พยายามเพื่อลดการรบกวนประสบการณ์ของผู้ใช้ ในทางกลับกัน สำหรับการดำเนินการในเบื้องหลัง เช่น การรับทราบการซื้อใหม่ ซึ่งไม่จำเป็นต้องดำเนินการทันที Exponential Backoff เป็นแนวทางที่แนะนำ
ดูข้อมูลโดยละเอียดเกี่ยวกับรหัสการตอบกลับที่เฉพาะเจาะจงและกลยุทธ์การลองใหม่ที่แนะนำที่เกี่ยวข้องได้ที่จัดการรหัสการตอบกลับ BillingResult
6. ขั้นตอนถัดไป
- ดูวิธีเพิ่มประสิทธิภาพการผสานรวมการเรียกเก็บเงินใน Play
- อย่าลืมทำตามแนวทางปฏิบัติแนะนำสำหรับการยืนยันและประมวลผลการซื้อในแบ็กเอนด์ที่ปลอดภัยเมื่อผู้ใช้เริ่มซื้อผลิตภัณฑ์เหล่านี้
เอกสารอ้างอิง
7. ยินดีด้วย
ยินดีด้วย คุณได้ไปยัง Google Play Console เพื่อสร้างผลิตภัณฑ์แบบครั้งเดียวใหม่ ทดสอบรหัสการตอบกลับการเรียกเก็บเงิน และวิเคราะห์การเลิกซื้อเรียบร้อยแล้ว
แบบสำรวจ
ความคิดเห็นของคุณเกี่ยวกับ Codelab นี้มีค่าอย่างยิ่ง โปรดสละเวลาสักครู่เพื่อตอบแบบสำรวจของเรา