เอกสารนี้อธิบายวิธีผสานรวม Google Play Billing Library เข้ากับแอปเพื่อเริ่มขายผลิตภัณฑ์
วงจรของการซื้อ
ต่อไปนี้คือขั้นตอนการซื้อทั่วไปสำหรับการซื้อแบบครั้งเดียวหรือการสมัครใช้บริการ
- แสดงให้ผู้ใช้เห็นว่าซื้ออะไรได้บ้าง
- เปิดขั้นตอนการซื้อเพื่อให้ผู้ใช้ยอมรับการซื้อ
- ยืนยันการซื้อในเซิร์ฟเวอร์
- แสดงเนื้อหาต่อผู้ใช้
- รับทราบการนำส่งเนื้อหา สำหรับไอเทมที่ใช้แล้วหมดไป ให้ใช้ การซื้อเพื่อให้ผู้ใช้ซื้อไอเทมนั้นได้อีกครั้ง
การสมัครใช้บริการจะต่ออายุโดยอัตโนมัติจนกว่าจะมีการยกเลิก การสมัครใช้บริการอาจมีสถานะต่อไปนี้
- ใช้งานอยู่: ผู้ใช้มีสถานะดีและมีสิทธิ์เข้าถึงการสมัครใช้บริการ
- ยกเลิกแล้ว: ผู้ใช้ยกเลิกแล้วแต่ยังคงมีสิทธิ์เข้าถึงจนกว่าจะหมดอายุ
- อยู่ในระยะเวลาผ่อนผัน: ผู้ใช้พบปัญหาการชำระเงินแต่ยังคงมีสิทธิ์เข้าถึง ขณะที่ Google ลองใช้วิธีการชำระเงินอีกครั้ง
- ระงับ: ผู้ใช้พบปัญหาเกี่ยวกับการชำระเงินและไม่มีสิทธิ์เข้าถึงอีกต่อไปในขณะที่ Google กำลังลองเรียกเก็บเงินจากวิธีการชำระเงินอีกครั้ง
- หยุดชั่วคราว: ผู้ใช้หยุดสิทธิ์เข้าถึงชั่วคราวและจะไม่มีสิทธิ์เข้าถึงจนกว่าจะ กลับมาใช้สิทธิ์อีกครั้ง
- หมดอายุ: ผู้ใช้ยกเลิกและเสียสิทธิ์เข้าถึงการสมัครใช้บริการ ระบบจะถือว่าผู้ใช้เลิกใช้งานเมื่อการสมัครใช้บริการหมดอายุ
เริ่มต้นการเชื่อมต่อกับ Google Play
ขั้นตอนแรกในการผสานรวมกับระบบการเรียกเก็บเงินของ Google Play คือการเพิ่ม Google Play Billing Library ลงในแอปและเริ่มต้นการเชื่อมต่อ
เพิ่มการอ้างอิงไลบรารี Google Play Billing
เพิ่มทรัพยากร Dependency ของ Google Play Billing Library ลงในไฟล์ build.gradle
ของแอปตามที่แสดง
Groovy
dependencies { def billing_version = "8.3.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "8.3.0" implementation("com.android.billingclient:billing:$billing_version") }
หากคุณใช้ Kotlin โมดูล KTX ของ Google Play Billing Library จะมีส่วนขยาย Kotlin และการรองรับ Coroutine ที่ช่วยให้คุณเขียน Kotlin ที่เป็นสำนวนเมื่อใช้ Google Play Billing Library ได้ หากต้องการรวมส่วนขยายเหล่านี้ไว้ในโปรเจ็กต์ ให้เพิ่มทรัพยากร Dependency ต่อไปนี้ลงในไฟล์ build.gradle ของแอปตามที่แสดง
Groovy
dependencies { def billing_version = "8.3.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "8.3.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
เริ่มต้น BillingClient
เมื่อเพิ่มการอ้างอิงใน Google Play Billing Library แล้ว คุณจะต้องเริ่มต้นอินสแตนซ์ BillingClient BillingClient เป็นอินเทอร์เฟซหลักสำหรับการสื่อสารระหว่าง Google Play Billing Library กับส่วนอื่นๆ ของแอป BillingClient มีวิธีการที่สะดวกทั้งแบบซิงโครนัสและอะซิงโครนัสสำหรับการดำเนินการเรียกเก็บเงินทั่วไปหลายอย่าง โปรดทราบ
สิ่งต่อไปนี้
- เราขอแนะนำให้คุณมีการเชื่อมต่อ
BillingClientที่ใช้งานอยู่ 1 รายการ เปิดไว้ในครั้งเดียวเพื่อหลีกเลี่ยงการเรียกกลับPurchasesUpdatedListenerหลายรายการ สำหรับเหตุการณ์เดียว - เราขอแนะนำให้เริ่มการเชื่อมต่อสำหรับ BillingClient เมื่อเปิดแอปหรือนำแอปขึ้นมาแสดงในเบื้องหน้า เพื่อให้มั่นใจว่าแอปจะประมวลผลการซื้อได้อย่างทันท่วงที ซึ่งทำได้โดยใช้
ActivityLifecycleCallbacksที่ลงทะเบียนโดยregisterActivityLifecycleCallbacksและรอ onActivityResumed เพื่อเริ่มต้นการเชื่อมต่อเมื่อตรวจพบว่ามีการกลับมาใช้ กิจกรรมอีกครั้งเป็นครั้งแรก ดูรายละเอียดเพิ่มเติมเกี่ยวกับเหตุผลที่ควรปฏิบัติตามแนวทางปฏิบัติแนะนำนี้ได้ที่ส่วนการประมวลผลการซื้อ นอกจากนี้ อย่าลืม สิ้นสุดการเชื่อมต่อเมื่อปิดแอป
หากต้องการสร้าง BillingClient ให้ใช้ newBuilder คุณส่งบริบทใดก็ได้ไปยัง
newBuilder() และ BillingClient จะใช้บริบทนั้นเพื่อรับบริบทของแอปพลิเคชัน ซึ่งหมายความว่าคุณไม่ต้องกังวลเรื่องหน่วยความจำรั่ว หากต้องการรับข้อมูลอัปเดตเกี่ยวกับการซื้อ คุณต้องเรียกใช้ setListener โดยส่งการอ้างอิงไปยัง PurchasesUpdatedListener ด้วย Listener นี้จะได้รับการอัปเดตสำหรับการซื้อทั้งหมดในแอปของคุณ
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 ที่ขาดหายไปด้วย หากต้องการใช้ตรรกะการลองใหม่ ให้ ลบล้างเมธอด Callback onBillingServiceDisconnected() และตรวจสอบว่า BillingClient เรียกใช้เมธอด startConnection() เพื่อ เชื่อมต่อกับ Google Play อีกครั้งก่อนส่งคำขอเพิ่มเติม หากเปิดใช้การเชื่อมต่อบริการอีกครั้งโดยอัตโนมัติ คุณจะใช้เมธอดนี้เป็น no-op ได้
ตัวอย่างต่อไปนี้แสดงวิธีเริ่มการเชื่อมต่อและทดสอบว่าพร้อมใช้งาน แล้ว
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() { // If automatic service reconnection is enabled, this can be left empty (no-op) // because the library handles retries. You can still use this for non-retry // tasks like logging or updating the UI to reflect a disconnected state. // Otherwise, 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() { // If automatic service reconnection is enabled, this can be left empty (no-op) // because the library handles retries. You can still use this for non-retry // tasks like logging or updating the UI to reflect a disconnected state. // Otherwise, try to restart the connection on the next request to // Google Play by calling the startConnection() method. } });
สร้างการเชื่อมต่อใหม่โดยอัตโนมัติ
เมื่อเปิดตัวเมธอด enableAutoServiceReconnection() ใน BillingClient.Builder ในเวอร์ชัน 8.0.0 ตอนนี้ Play Billing Library สามารถสร้างการเชื่อมต่อบริการใหม่โดยอัตโนมัติได้หากมีการเรียก API ขณะที่บริการถูกตัดการเชื่อมต่อ ซึ่งอาจส่งผลให้การตอบกลับของ SERVICE_DISCONNECTED ลดลงเนื่องจากระบบจัดการการเชื่อมต่อใหม่ภายในก่อนที่จะเรียก API
วิธีเปิดใช้การเชื่อมต่อใหม่โดยอัตโนมัติ
เมื่อสร้างอินสแตนซ์ BillingClient ให้ใช้วิธี enableAutoServiceReconnection() ใน BillingClient.Builder เพื่อ
เปิดใช้การเชื่อมต่อใหม่โดยอัตโนมัติ
Kotlin
val billingClient = BillingClient.newBuilder(context)
.setListener(listener)
.enablePendingPurchases()
.enableAutoServiceReconnection() // Add this line to enable reconnection
.build()
Java
BillingClient billingClient = BillingClient.newBuilder(context)
.setListener(listener)
.enablePendingPurchases()
.enableAutoServiceReconnection() // Add this line to enable reconnection
.build();
แสดงผลิตภัณฑ์ที่พร้อมจำหน่าย
หลังจากสร้างการเชื่อมต่อกับ Google Play แล้ว คุณก็พร้อมที่จะค้นหา ผลิตภัณฑ์ที่พร้อมให้บริการและแสดงต่อผู้ใช้
การค้นหารายละเอียดสินค้าเป็นขั้นตอนสำคัญก่อนแสดงสินค้าต่อผู้ใช้ เนื่องจากจะแสดงข้อมูลสินค้าที่แปลเป็นภาษาท้องถิ่น สำหรับข้อมูลการสมัครใช้บริการ ให้ตรวจสอบว่าการแสดงผลิตภัณฑ์เป็นไปตามนโยบายทั้งหมดของ Play
หากต้องการค้นหารายละเอียดผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว ให้เรียกใช้เมธอด queryProductDetailsAsync วิธีนี้จะแสดงข้อเสนอหลายรายการตามการกำหนดค่าผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว
ดูข้อมูลเพิ่มเติมได้ที่ตัวเลือกการซื้อและข้อเสนอหลายรายการ
สำหรับไอเทมแบบเรียกเก็บเงินครั้งเดียว
หากต้องการจัดการผลลัพธ์ของการดำเนินการแบบไม่พร้อมกัน คุณต้องระบุ Listener ที่ใช้ProductDetailsResponseListener อินเทอร์เฟซด้วย
จากนั้นคุณจะลบล้าง onProductDetailsResponse ซึ่งจะแจ้งเตือน Listener เมื่อการค้นหาเสร็จสิ้น ดังที่แสดงในตัวอย่างต่อไปนี้
Kotlin
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build() billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult, queryProductDetailsResult -> if (billingResult.getResponseCode() == BillingResponseCode.OK) { for (ProductDetails productDetails : queryProductDetailsResult.getProductDetailsList()) { // Process successfully retrieved product details here. } for (UnfetchedProduct unfetchedProduct : queryproductDetailsResult.getUnfetchedProductList()) { // Handle any unfetched products as appropriate. } } }
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, QueryProductDetailsResult queryProductDetailsResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { for (ProductDetails productDetails : queryProductDetailsResult().getProductDetailsList()) { // Process success retrieved product details here. } for (UnfetchedProduct unfetchedProduct : queryproductDetailsResult.getUnfetchedProductList()) { // Handle any unfetched products as appropriate. } } } } )
เมื่อค้นหารายละเอียดผลิตภัณฑ์ ให้ส่งอินสแตนซ์ของ
QueryProductDetailsParams ที่ระบุรายการสตริงรหัสผลิตภัณฑ์
ที่สร้างใน Google Play Console พร้อมกับ ProductType ProductType อาจเป็น ProductType.INAPP สำหรับผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวหรือ
ProductType.SUBS สำหรับการสมัครใช้บริการ
ค้นหาด้วยส่วนขยาย Kotlin
หากใช้ส่วนขยาย Kotlin คุณจะค้นหารายละเอียดผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวได้โดยเรียกใช้ฟังก์ชันส่วนขยาย queryProductDetails()
queryProductDetails() ใช้ประโยชน์จากโครูทีน Kotlin เพื่อให้คุณไม่ต้อง
กำหนด Listener แยกต่างหาก แต่ฟังก์ชันจะระงับจนกว่าการค้นหาจะเสร็จสมบูรณ์ จากนั้นคุณจะประมวลผลผลลัพธ์ได้
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 Billing Library 7
ประมวลผลผลลัพธ์
Google Play Billing Library จะจัดเก็บผลการค้นหาในออบเจ็กต์
QueryProductDetailsResult QueryProductDetailsResult
มี List ของออบเจ็กต์ ProductDetails จากนั้นคุณจะเรียกใช้
วิธีการต่างๆ ในออบเจ็กต์ ProductDetails แต่ละรายการในรายการเพื่อดูข้อมูลที่เกี่ยวข้อง
เกี่ยวกับผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวที่ดึงข้อมูลสําเร็จ เช่น
ราคาหรือคําอธิบาย หากต้องการดูข้อมูลรายละเอียดผลิตภัณฑ์ที่มีอยู่ ให้ดูรายการเมธอดในคลาส ProductDetails
QueryProductDetailsResult ยังมี List ของออบเจ็กต์ UnfetchedProduct ด้วย จากนั้นคุณจะค้นหา UnfetchedProduct แต่ละรายการ
เพื่อรับรหัสสถานะที่สอดคล้องกับเหตุผลที่ดึงข้อมูลไม่สำเร็จได้
หากต้องการดูข้อมูลสินค้าที่พร้อมใช้งานซึ่งยังไม่ได้ดึงข้อมูล ให้ดูรายการเมธอดในคลาส UnfetchedProduct
ก่อนเสนอขายไอเทม ให้ตรวจสอบว่าผู้ใช้ยังไม่มีไอเทมนั้น หากผู้ใช้มีไอเทมที่ใช้แล้วหมดซึ่งยังอยู่ในคลังไอเทม ผู้ใช้ ต้องใช้ไอเทมนั้นก่อนจึงจะซื้อได้อีกครั้ง
ก่อนเสนอการสมัครใช้บริการ ให้ตรวจสอบว่าผู้ใช้ยังไม่ได้สมัครใช้บริการ นอกจากนี้ โปรดทราบสิ่งต่อไปนี้
สำหรับการสมัครใช้บริการ
queryProductDetailsAsync()เมธอดจะแสดงรายละเอียดผลิตภัณฑ์ที่ต้องสมัครใช้บริการและข้อเสนอที่มีสิทธิ์สำหรับผู้ใช้สูงสุด 50 รายต่อการสมัครใช้บริการ หากผู้ใช้พยายามซื้อข้อเสนอที่ไม่มีสิทธิ์ (เช่น หากแอปแสดงรายการข้อเสนอที่มีสิทธิ์ที่ล้าสมัย) Play จะแจ้งให้ผู้ใช้ทราบว่าไม่มีสิทธิ์ และผู้ใช้สามารถเลือกซื้อแพ็กเกจเริ่มต้นแทนได้สำหรับไอเทมแบบเรียกเก็บเงินครั้งเดียว เมธอด
queryProductDetailsAsync()จะแสดงเฉพาะข้อเสนอที่ผู้ใช้มีสิทธิ์เท่านั้น หากผู้ใช้พยายามซื้อข้อเสนอที่ไม่มีสิทธิ์ (เช่น หากผู้ใช้ซื้อถึงจำนวนจำกัดแล้ว) Play จะแจ้งให้ผู้ใช้ทราบว่าไม่มีสิทธิ์ และผู้ใช้สามารถเลือกซื้อข้อเสนอตัวเลือกการซื้อแทนได้
เปิดตัวขั้นตอนการซื้อ
หากต้องการเริ่มคำขออนุมัติการซื้อจากแอป ให้เรียกใช้เมธอด launchBillingFlow() จากเทรดหลักของแอป เมธอดนี้ใช้การอ้างอิงไปยังออบเจ็กต์
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) // Get the offer token: // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList() // for a list of offers that are available to the user. // b. For subscriptions, 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) // Get the offer token: // a. For one-time products, call ProductDetails.getOneTimePurchaseOfferDetailsList() // for a list of offers that are available to the user. // b. For subscriptions, 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 จะเรียกใช้ onPurchasesUpdated() เพื่อส่งผลลัพธ์ของการดำเนินการซื้อ
ไปยังผู้ฟังที่ใช้ PurchasesUpdatedListener
อินเทอร์เฟซ โดยระบุ Listener โดยใช้เมธอด setListener() เมื่อคุณ
เริ่มต้นไคลเอ็นต์
คุณต้องใช้ onPurchasesUpdated() เพื่อจัดการโค้ดตอบกลับที่อาจเกิดขึ้น
ตัวอย่างต่อไปนี้แสดงวิธีลบล้าง onPurchasesUpdated()
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { // Process the purchase as described in the next section. } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user canceling 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) { // Process the purchase as described in the next section. } } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user canceling the purchase flow. } else { // Handle any other error codes. } }
การซื้อที่สำเร็จจะสร้างหน้าจอการซื้อใน Google Play ที่สำเร็จซึ่งคล้ายกับ รูปที่ 2
การซื้อที่สำเร็จจะสร้างโทเค็นการซื้อด้วย ซึ่งเป็นตัวระบุที่ไม่ซ้ำกันที่แสดงถึงผู้ใช้และรหัสสินค้าสำหรับผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวที่ผู้ใช้ซื้อ แอปของคุณจัดเก็บโทเค็นการซื้อไว้ในเครื่องได้ แต่เราขอแนะนำอย่างยิ่งให้ส่งโทเค็นไปยังเซิร์ฟเวอร์แบ็กเอนด์ที่ปลอดภัย ซึ่งคุณจะใช้ยืนยันการซื้อและป้องกันการประพฤติมิชอบได้ กระบวนการนี้อธิบายเพิ่มเติมในการตรวจหาและประมวลผลการซื้อ
นอกจากนี้ ผู้ใช้จะได้รับอีเมลใบเสร็จของธุรกรรมที่มีรหัสคำสั่งซื้อหรือรหัสที่ไม่ซ้ำกันของธุรกรรม ผู้ใช้จะได้รับอีเมลที่มีรหัสคำสั่งซื้อที่ไม่ซ้ำกันสำหรับการซื้อผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวแต่ละรายการ รวมถึงสำหรับการซื้อการสมัครใช้บริการครั้งแรกและการต่ออายุอัตโนมัติแบบตามรอบในครั้งต่อๆ ไป คุณใช้รหัสคำสั่งซื้อ เพื่อจัดการการคืนเงินใน Google Play Console ได้
ระบุราคาที่ปรับเปลี่ยนในแบบของคุณ
หากแอปของคุณสามารถเผยแพร่ต่อผู้ใช้ในสหภาพยุโรปได้ ให้ใช้วิธี setIsOfferPersonalized() เมื่อเรียกใช้ launchBillingFlow เพื่อเปิดเผยต่อผู้ใช้ว่ามีการปรับราคาของสินค้าตามโปรไฟล์ของผู้ใช้โดยใช้การตัดสินใจอัตโนมัติ
คุณต้องปรึกษามาตรา 6 (1) (ea) CRD ของคำสั่งว่าด้วยสิทธิของผู้บริโภค 2011/83/EU เพื่อตรวจสอบว่าราคาที่คุณเสนอให้ผู้ใช้นั้นมีการปรับเปลี่ยนตามโปรไฟล์ของผู้ใช้หรือไม่
setIsOfferPersonalized() รับอินพุตบูลีน เมื่อtrue UI ของ Play
จะมีการเปิดเผยข้อมูล เมื่อเป็น false UI จะละเว้นการเปิดเผยข้อมูล ค่าเริ่มต้นคือ false
ดูข้อมูลเพิ่มเติมได้ที่ศูนย์ช่วยเหลือสำหรับผู้บริโภค
แนบตัวระบุผู้ใช้
เมื่อเปิดตัวขั้นตอนการซื้อ แอปจะแนบตัวระบุผู้ใช้ที่คุณมีสำหรับผู้ใช้ที่ทำการซื้อได้โดยใช้ obfuscatedAccountId หรือ obfuscatedProfileId ตัวอย่างตัวระบุอาจเป็นเวอร์ชันที่ผ่านการปกปิด ของการเข้าสู่ระบบของผู้ใช้ในระบบของคุณ การตั้งค่าพารามิเตอร์เหล่านี้จะช่วยให้ Google ตรวจหาการฉ้อโกงได้ นอกจากนี้ ยังช่วยให้มั่นใจได้ว่าระบบจะ ระบุแหล่งที่มาของการซื้อไปยังผู้ใช้ที่เหมาะสมตามที่อธิบายไว้ใน การให้สิทธิ์แก่ผู้ใช้
ตรวจหาและประมวลผลการซื้อ
การตรวจหาและการประมวลผลการซื้อที่อธิบายไว้ในส่วนนี้ ใช้ได้กับการซื้อทุกประเภท รวมถึงการซื้อนอกแอป เช่น การแลกรับโปรโมชัน
แอปของคุณจะตรวจหาการซื้อใหม่และการซื้อที่รอดำเนินการที่เสร็จสมบูรณ์ด้วยวิธีใดวิธีหนึ่งต่อไปนี้
- เมื่อมีการเรียกใช้
onPurchasesUpdatedอันเป็นผลมาจากการที่แอปของคุณเรียกใช้launchBillingFlow(ตามที่อธิบายไว้ในส่วนก่อนหน้า) หรือหากแอปของคุณ ทํางานโดยมีการเชื่อมต่อ Billing Library ที่ใช้งานอยู่เมื่อมีการซื้อ นอกแอปของคุณหรือการซื้อที่รอดำเนินการเสร็จสมบูรณ์ เช่น สมาชิกในครอบครัวอนุมัติการซื้อที่รอดำเนินการในอุปกรณ์อื่น - เมื่อแอปเรียกใช้ queryPurchasesAsync เพื่อค้นหาการซื้อของผู้ใช้
สำหรับ #1 ระบบจะเรียกใช้ onPurchasesUpdated โดยอัตโนมัติสำหรับการซื้อใหม่หรือการซื้อที่เสร็จสมบูรณ์
ตราบใดที่แอปของคุณทำงานอยู่และมีการเชื่อมต่อไลบรารีการเรียกเก็บเงินของ Google Play ที่ใช้งานอยู่
หากแอปพลิเคชันไม่ได้ทำงานหรือแอปไม่มี
การเชื่อมต่อไลบรารีการเรียกเก็บเงินของ Google Play ที่ใช้งานอยู่ ระบบจะไม่เรียกใช้ onPurchasesUpdated โปรดทราบว่าเราขอแนะนำให้แอปของคุณพยายามรักษา
การเชื่อมต่อที่ใช้งานอยู่ตราบใดที่แอปของคุณอยู่เบื้องหน้า เพื่อให้แอปได้รับการอัปเดตการซื้อ
อย่างทันท่วงที
สำหรับข้อ 2 คุณต้องเรียกใช้ BillingClient.queryPurchasesAsync() เพื่อให้แน่ใจว่าแอป ประมวลผลการซื้อทั้งหมด เราขอแนะนำให้คุณทำเช่นนี้เมื่อแอป สร้างการเชื่อมต่อกับ Google Play Billing Library ได้สำเร็จ (ซึ่งแนะนำให้ทำเมื่อแอปเปิดตัวหรือเข้าสู่เบื้องหน้าตามที่อธิบายไว้ในเริ่มต้น BillingClient ซึ่งทำได้โดยการเรียกใช้ queryPurchasesAsync เมื่อได้รับผลลัพธ์ที่สำเร็จไปยัง onServiceConnected การทำตามคำแนะนำนี้เป็นสิ่งสำคัญในการจัดการ เหตุการณ์และสถานการณ์ต่างๆ เช่น
- ปัญหาเกี่ยวกับเครือข่ายระหว่างการซื้อ: ผู้ใช้สามารถซื้อ
ได้สำเร็จและได้รับการยืนยันจาก Google แต่
อุปกรณ์จะสูญเสียการเชื่อมต่อเครือข่ายก่อนที่อุปกรณ์และแอปของคุณจะได้รับการแจ้งเตือน
เกี่ยวกับการซื้อผ่าน
PurchasesUpdatedListener - อุปกรณ์หลายเครื่อง: ผู้ใช้อาจซื้อสินค้าในอุปกรณ์เครื่องหนึ่งและคาดหวัง ว่าจะเห็นสินค้าดังกล่าวเมื่อเปลี่ยนไปใช้อุปกรณ์เครื่องอื่น
- การจัดการการซื้อที่ดำเนินการนอกแอป: การซื้อบางอย่าง เช่น การแลกรับโปรโมชัน สามารถทำได้นอกแอป
- การจัดการการเปลี่ยนสถานะการซื้อ: ผู้ใช้อาจชำระเงินสำหรับการซื้อที่ รอดำเนินการในขณะที่แอปพลิเคชันของคุณไม่ได้ทำงาน และคาดหวังที่จะได้รับ การยืนยันว่าได้ทำการซื้อเสร็จสมบูรณ์แล้วเมื่อเปิดแอป
- การสมัครใช้บริการที่ถูกระงับ: การสมัครใช้บริการอาจถูกระงับระหว่างวงจรการสมัครใช้บริการ BillingClient.queryPurchasesAsync() จะ
แสดงการสมัครใช้บริการที่ถูกระงับก็ต่อเมื่อตั้งค่าพารามิเตอร์
includeSuspendedSubscriptionsในQueryPurchasesParams.Builderการสมัครใช้บริการที่ถูกระงับ จะไม่แสดงในPurchasesUpdatedListener
เมื่อแอปตรวจพบการซื้อใหม่หรือการซื้อที่เสร็จสมบูรณ์แล้ว แอปควรดำเนินการดังนี้
- ยืนยันการซื้อ
- มอบเนื้อหาให้แก่ผู้ใช้สำหรับการซื้อที่เสร็จสมบูรณ์
- แจ้งให้ผู้ใช้ทราบ
- แจ้งให้ Google ทราบว่าแอปของคุณประมวลผลการซื้อที่เสร็จสมบูรณ์แล้ว
เราจะอธิบายขั้นตอนเหล่านี้โดยละเอียดในส่วนต่อไปนี้ และตามด้วยส่วนสรุปขั้นตอนทั้งหมด
ยืนยันการซื้อ
แอปควรตรวจสอบความถูกต้องของการซื้อก่อนให้สิทธิประโยชน์แก่ผู้ใช้เสมอ โดยทำตามหลักเกณฑ์ที่อธิบายไว้ในหัวข้อ ยืนยันการซื้อก่อนให้สิทธิ์ หลังจากยืนยันการซื้อแล้วเท่านั้น แอปของคุณจึงควรดำเนินการกับการซื้อต่อและให้สิทธิ์แก่ผู้ใช้ ซึ่งจะกล่าวถึงในส่วนถัดไป
ให้สิทธิ์แก่ผู้ใช้
เมื่อแอปยืนยันการซื้อแล้ว แอปจะให้สิทธิ์แก่ผู้ใช้ต่อไปและแจ้งให้ผู้ใช้ทราบได้ ก่อนให้สิทธิ์ โปรดตรวจสอบว่าแอปของคุณกำลังตรวจสอบว่าสถานะการซื้อเป็น PURCHASED หากการซื้อมีสถานะเป็น "รอดำเนินการ" แอปของคุณควรแจ้งให้ผู้ใช้ทราบว่ายังคงต้องดำเนินการให้เสร็จสมบูรณ์เพื่อทำการซื้อให้เสร็จสมบูรณ์ก่อนที่จะได้รับสิทธิ์
ให้สิทธิ์เฉพาะเมื่อการซื้อเปลี่ยนจากสถานะ "รอดำเนินการ" เป็น "สำเร็จ"
ดูข้อมูลเพิ่มเติมได้ที่การจัดการธุรกรรมที่รอดำเนินการ
หากคุณแนบตัวระบุผู้ใช้กับการซื้อตามที่อธิบายไว้ในการแนบตัวระบุผู้ใช้ คุณจะเรียกข้อมูลและใช้ตัวระบุเหล่านั้นเพื่อระบุแหล่งที่มาของผู้ใช้ที่ถูกต้องในระบบได้ เทคนิคนี้มีประโยชน์เมื่อต้องกระทบยอดการซื้อ ในกรณีที่แอปอาจสูญเสียบริบทเกี่ยวกับผู้ใช้ที่ทำการซื้อ โปรดทราบว่า การซื้อที่ทำภายนอกแอปจะไม่มีการตั้งค่าตัวระบุเหล่านี้ ในกรณีนี้ แอปของคุณจะให้สิทธิ์แก่ผู้ใช้ที่เข้าสู่ระบบ หรือแจ้งให้ผู้ใช้เลือกบัญชีที่ต้องการก็ได้
สำหรับการสั่งจองล่วงหน้า การซื้อจะอยู่ในสถานะรอดำเนินการก่อนถึงเวลาวางจำหน่าย ระบบจะดำเนินการซื้อที่สั่งจองล่วงหน้าให้เสร็จสมบูรณ์เมื่อถึงเวลาวางจำหน่ายและเปลี่ยนสถานะเป็น "ซื้อแล้ว" โดยที่คุณไม่ต้องดำเนินการใดๆ เพิ่มเติม
แจ้งให้ผู้ใช้ทราบ
หลังจากให้สิทธิ์แก่ผู้ใช้แล้ว แอปของคุณควรแสดงการแจ้งเตือนเพื่อรับทราบการซื้อที่สำเร็จ การแจ้งเตือนนี้จะช่วยให้ผู้ใช้ไม่สับสนว่าการซื้อเสร็จสมบูรณ์หรือไม่ ซึ่งอาจส่งผลให้ผู้ใช้หยุดใช้แอปของคุณ ติดต่อทีมสนับสนุนผู้ใช้ หรือร้องเรียนเกี่ยวกับเรื่องนี้บนโซเชียลมีเดีย โปรดทราบว่าแอปอาจตรวจพบการอัปเดตการซื้อได้ทุกเมื่อในวงจรแอปพลิเคชัน เช่น ผู้ปกครอง อนุมัติการซื้อที่รอดำเนินการในอุปกรณ์อื่น ในกรณีนี้แอปของคุณอาจต้องการ เลื่อนการแจ้งเตือนผู้ใช้ไปยังเวลาที่เหมาะสม ตัวอย่างบางส่วนที่ควรใช้การหน่วงเวลา มีดังนี้
- ในระหว่างช่วงการกระทำของเกมหรือฉากคัตซีน การแสดงข้อความอาจ รบกวนผู้ใช้ ในกรณีนี้ คุณต้องแจ้งให้ผู้ใช้ทราบหลังจากที่ ส่วนการดำเนินการสิ้นสุดลง
- ในระหว่างบทแนะนำเบื้องต้นและส่วนการตั้งค่าผู้ใช้ของเกม เช่น ผู้ใช้อาจทำการซื้อนอกแอปก่อนที่จะติดตั้ง เราขอแนะนำให้คุณแจ้งให้ผู้ใช้ใหม่ทราบเกี่ยวกับรางวัลทันทีหลังจากที่ผู้ใช้เปิดเกมหรือในระหว่างการตั้งค่าผู้ใช้ครั้งแรก หากแอปกำหนดให้ผู้ใช้สร้างบัญชีหรือเข้าสู่ระบบก่อนที่จะให้สิทธิ์แก่ผู้ใช้ เราขอแนะนำให้แจ้งให้ผู้ใช้ทราบถึงขั้นตอนที่ต้องดำเนินการเพื่อรับสิทธิ์จากการซื้อ ซึ่งเป็นสิ่งสำคัญเนื่องจากระบบจะคืนเงินสำหรับการซื้อหลังจากผ่านไป 3 วัน หากแอปของคุณยังไม่ได้ประมวลผลการซื้อ
เมื่อแจ้งเตือนผู้ใช้เกี่ยวกับการซื้อ Google Play ขอแนะนําให้ใช้กลไกต่อไปนี้
- แสดงกล่องโต้ตอบในแอป
- ส่งข้อความไปยังกล่องข้อความในแอป และระบุอย่างชัดเจนว่ามีข้อความใหม่ในกล่องข้อความในแอป
- ใช้ข้อความการแจ้งเตือนของระบบปฏิบัติการ
การแจ้งเตือนควรแจ้งให้ผู้ใช้ทราบถึงสิทธิประโยชน์ที่ได้รับ เช่น "คุณซื้อเหรียญทอง 100 เหรียญแล้ว" นอกจากนี้ หากการซื้อเป็นผลมาจากสิทธิประโยชน์ของโปรแกรม เช่น Play Pass แอปของคุณจะสื่อสารเรื่องนี้กับผู้ใช้ เช่น "ได้รับสินค้าแล้ว คุณเพิ่งได้รับ Gem 100 เม็ดจาก Play Pass ดำเนินการต่อ" แต่ละโปรแกรมอาจมีคำแนะนำเกี่ยวกับข้อความที่แนะนำให้แสดงต่อผู้ใช้เพื่อสื่อสารถึงสิทธิประโยชน์
แจ้งให้ Google ทราบว่ามีการประมวลผลการซื้อแล้ว
หลังจากที่แอปให้สิทธิ์แก่ผู้ใช้และแจ้งให้ผู้ใช้ทราบเกี่ยวกับการทำธุรกรรมที่สำเร็จแล้ว แอปของคุณต้องแจ้งให้ Google ทราบว่าการซื้อได้รับการประมวลผลเรียบร้อยแล้ว โดยการดำเนินการนี้จะทำได้ด้วยการรับทราบการซื้อ และต้องทำภายใน 3 วันเพื่อไม่ให้ระบบคืนเงินโดยอัตโนมัติและเพิกถอนสิทธิ์ กระบวนการรับทราบการซื้อประเภทต่างๆ อธิบายไว้ในส่วนต่อไปนี้
ผลิตภัณฑ์สิ้นเปลือง
สำหรับไอเทมที่ใช้แล้วหมด หากแอปมีแบ็กเอนด์ที่ปลอดภัย เราขอแนะนำให้คุณใช้
Purchases.products:consume เพื่อใช้การซื้อได้อย่างน่าเชื่อถือ ตรวจสอบว่าได้ใช้การซื้อไปแล้วหรือยังโดยดู consumptionState จาก
ผลลัพธ์ของการเรียก Purchases.products:get หากแอปของคุณเป็นไคลเอ็นต์เท่านั้น
โดยไม่มีแบ็กเอนด์ ให้ใช้ consumeAsync() จาก
Google Play Billing Library ทั้ง 2 วิธีเป็นไปตามข้อกำหนดในการรับทราบ และระบุว่าแอปของคุณได้ให้สิทธิ์แก่ผู้ใช้แล้ว
นอกจากนี้ วิธีการเหล่านี้ยังช่วยให้แอปของคุณทำให้ผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวที่สอดคล้องกับโทเค็นการซื้อที่ป้อนพร้อมสำหรับการซื้อซ้ำ เมื่อใช้ consumeAsync() คุณ
ต้องส่งออบเจ็กต์ที่ใช้ConsumeResponseListener
อินเทอร์เฟซด้วย ออบเจ็กต์นี้จัดการผลลัพธ์ของการดำเนินการการใช้งาน คุณสามารถ
แทนที่เมธอด onConsumeResponse() ซึ่ง
Google Play Billing Library จะเรียกใช้เมื่อการดำเนินการเสร็จสมบูรณ์
ตัวอย่างต่อไปนี้แสดงการใช้ผลิตภัณฑ์ด้วย Google Play Billing Library โดยใช้โทเค็นการซื้อที่เชื่อมโยง
Kotlin
val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) }
Java
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 Billing Library ในแอปของคุณ ก่อนที่จะรับทราบการซื้อ
แอปควรตรวจสอบว่ามีการรับทราบแล้วหรือไม่โดยใช้วิธี isAcknowledged() ใน Google Play Billing Library
ตัวอย่างต่อไปนี้แสดงวิธีรับทราบการซื้อโดยใช้ Google Play Billing Library
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) }
Java
BillingClient client = ... AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ... AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
การติดตาม
ระบบจะจัดการการสมัครใช้บริการในลักษณะเดียวกับไอเทมที่ซื้อครั้งเดียว หากเป็นไปได้ ให้ใช้
Purchases.subscriptions.acknowledge จาก
Google Play Developer API เพื่อตอบรับการซื้อจากแบ็กเอนด์ที่ปลอดภัย
ได้อย่างน่าเชื่อถือ ยืนยันว่าก่อนหน้านี้ยังไม่มีการรับทราบการซื้อโดย
ตรวจสอบ acknowledgementState ในแหล่งข้อมูลการซื้อจาก
Purchases.subscriptions:get หรือคุณจะรับทราบการสมัครใช้บริการโดยใช้ BillingClient.acknowledgePurchase() จาก
Google Play Billing Library หลังจากตรวจสอบ isAcknowledged() แล้วก็ได้ การซื้อการสมัครใช้บริการครั้งแรกทั้งหมดต้องได้รับการรับทราบ การต่ออายุการสมัครใช้บริการ
ไม่จำเป็นต้องรับทราบ ดูข้อมูลเพิ่มเติมเกี่ยวกับเวลาที่ต้องรับทราบการสมัครใช้บริการได้ที่หัวข้อขายการสมัครใช้บริการ
สรุป
ต่อไปนี้คือสรุปขั้นตอนเหล่านี้
ส่งการซื้อไปยังแบ็กเอนด์ที่ปลอดภัยเพื่อยืนยันการซื้อก่อน ให้สิทธิ์
อัปเดตที่เก็บข้อมูลการให้สิทธิ์ด้วยการซื้อ หากการซื้ออยู่ในสถานะรอดำเนินการ ให้ตรวจสอบว่าได้ทำเครื่องหมายการให้สิทธิ์เป็นรอดำเนินการแล้วและผู้ใช้ยังไม่ได้รับสิทธิประโยชน์ เราขอแนะนำให้ทำขั้นตอนนี้ในแบ็กเอนด์ที่ปลอดภัยและรวมไว้ในการเรียก API ไปยังแบ็กเอนด์ในขั้นตอนที่ 1
แจ้งให้ผู้ใช้ทราบโดยใช้การรับส่งข้อความที่เหมาะสม (เลื่อนการแจ้งเตือนหากจำเป็นตามที่ได้กล่าวไว้ก่อนหน้านี้)
แจ้งให้ Google ทราบว่ามีการประมวลผลการซื้อแล้วโดยทำตามขั้นตอน ที่อธิบายไว้ในส่วนการประมวลผลการซื้อ
หากต้องการยืนยันว่าแอปได้ติดตั้งใช้งานขั้นตอนเหล่านี้อย่างถูกต้องแล้ว ให้ทำตามคู่มือการทดสอบ
จัดการธุรกรรมที่รอดำเนินการ
Google Play รองรับธุรกรรมที่รอดำเนินการหรือธุรกรรมที่ต้องมีขั้นตอนเพิ่มเติมอย่างน้อย 1 ขั้นตอนระหว่างที่ผู้ใช้เริ่มการซื้อกับตอนที่ระบบประมวลผลวิธีการชำระเงินสำหรับการซื้อ แอปของคุณไม่ควรให้สิทธิ์ ในการซื้อประเภทนี้จนกว่า Google จะแจ้งให้คุณทราบว่าระบบเรียกเก็บเงินจากวิธีการชำระเงินของผู้ใช้ ได้สำเร็จแล้ว
เช่น ผู้ใช้สามารถเริ่มทำธุรกรรมได้โดยเลือกร้านค้าจริง ซึ่งจะชำระเงินด้วยเงินสดในภายหลัง ผู้ใช้จะได้รับรหัสผ่านทั้งการแจ้งเตือนและอีเมล เมื่อผู้ใช้มาถึงหน้าร้านจริง ก็สามารถแลกสิทธิ์รหัสกับแคชเชียร์และชำระเงินด้วยเงินสดได้ จากนั้น Google จะแจ้งให้ทั้งคุณและผู้ใช้ทราบว่าได้รับชำระเงินแล้ว จากนั้นแอปจะให้สิทธิ์แก่ผู้ใช้ได้
เรียกใช้ enablePendingPurchases() เป็นส่วนหนึ่งของการเริ่มต้น BillingClient เพื่อเปิดใช้ธุรกรรมที่รอดำเนินการสำหรับแอปของคุณ แอปต้องเปิดใช้และรองรับธุรกรรมที่รอดำเนินการสำหรับไอเทมแบบเรียกเก็บเงินครั้งเดียว ก่อนเพิ่มการรองรับ โปรดทำความเข้าใจวงจรการซื้อสำหรับธุรกรรมที่รอดำเนินการ
เมื่อแอปได้รับการซื้อใหม่ ไม่ว่าจะผ่านPurchasesUpdatedListener หรือเป็นผลจากการเรียกใช้ queryPurchasesAsync ให้ใช้เมธอด getPurchaseState() เพื่อ
พิจารณาว่าสถานะการซื้อเป็น PURCHASED หรือ PENDING คุณควรให้สิทธิ์เฉพาะเมื่อสถานะเป็น PURCHASED
หากแอปของคุณทำงานอยู่และมีการเชื่อมต่อ Play Billing Library ที่ใช้งานอยู่
เมื่อผู้ใช้ทำการซื้อเสร็จสมบูรณ์ ระบบจะเรียกใช้ PurchasesUpdatedListener อีกครั้ง และตอนนี้ PurchaseState จะเป็น PURCHASED ตอนนี้แอปของคุณสามารถประมวลผลการซื้อโดยใช้วิธีมาตรฐานสำหรับการตรวจหาและการประมวลผลการซื้อ นอกจากนี้ แอปของคุณควรเรียกใช้ queryPurchasesAsync() ใน
เมธอด onResume() ของแอปเพื่อจัดการการซื้อที่เปลี่ยนไปเป็นสถานะ
PURCHASED ขณะที่แอปไม่ได้ทำงาน
เมื่อการซื้อเปลี่ยนจากสถานะ PENDING เป็น PURCHASED ไคลเอ็นต์ real_time_developer_notifications จะได้รับการแจ้งเตือน ONE_TIME_PRODUCT_PURCHASED หรือ SUBSCRIPTION_PURCHASED
หากมีการยกเลิกการซื้อ คุณจะได้รับการแจ้งเตือน ONE_TIME_PRODUCT_CANCELED หรือ SUBSCRIPTION_PENDING_PURCHASE_CANCELED
ปัญหานี้อาจเกิดขึ้นได้หากลูกค้าชำระเงินไม่เสร็จภายในกรอบเวลาที่กำหนด โปรดทราบว่าคุณใช้ Google Play Developer API เพื่อตรวจสอบสถานะปัจจุบันของการซื้อได้เสมอ
จัดการการซื้อหลายรายการ
Google Play อนุญาตให้ลูกค้าซื้อไอเทมแบบเรียกเก็บเงินครั้งเดียวรายการเดียวกันได้มากกว่า 1 รายการในธุรกรรมเดียวโดยการระบุจำนวนจากรถเข็นการซื้อ ซึ่งรองรับใน Google Play Billing Library เวอร์ชัน 4.0 ขึ้นไป แอปของคุณควรจัดการการซื้อแบบหลายจำนวนและให้สิทธิ์ตามจำนวนการซื้อที่ระบุ
ตรรกะการจัดสรรของแอปต้องตรวจสอบจำนวนสินค้าเพื่อรองรับการซื้อหลายรายการ
คุณเข้าถึงquantityฟิลด์ได้จาก API ใด API หนึ่งต่อไปนี้
getQuantity()จาก Google Play Billing LibraryPurchases.products.quantityจาก Google Play Developer API
หลังจากเพิ่มตรรกะเพื่อจัดการการซื้อหลายรายการแล้ว คุณจะต้องเปิดใช้ฟีเจอร์หลายรายการสำหรับผลิตภัณฑ์ที่เกี่ยวข้องในหน้าการจัดการผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวใน Google Play Console
ค้นหาการกำหนดค่าการเรียกเก็บเงินของผู้ใช้
getBillingConfigAsync() ระบุประเทศที่ผู้ใช้ใช้สำหรับ Google
Play
คุณสามารถค้นหาการกำหนดค่าการเรียกเก็บเงินของผู้ใช้ได้หลังจากสร้าง
BillingClient ข้อมูลโค้ดต่อไปนี้อธิบายวิธีโทรหา getBillingConfigAsync()
จัดการการตอบกลับโดยการใช้
BillingConfigResponseListener Listener นี้จะได้รับการอัปเดตสำหรับการค้นหาการกำหนดค่าการเรียกเก็บเงินทั้งหมดที่เริ่มต้นจากแอปของคุณ
หาก 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 } } });
การช่วยเตือนการละทิ้งรถเข็นกลางคันในหน้าแรกของ Google Play Games (เปิดใช้โดยค่าเริ่มต้น)
สำหรับนักพัฒนาแอปเกมที่สร้างรายได้ผ่านผลิตภัณฑ์แบบครั้งเดียว วิธีหนึ่งในการขายหน่วยเก็บสินค้า (SKU) ที่ใช้งานอยู่ใน Google Play Console นอกแอปของคุณคือฟีเจอร์การช่วยเตือนการละทิ้งรถเข็นกลางคัน ซึ่งจะกระตุ้นให้ผู้ใช้ดำเนินการซื้อที่หยุดกลางคันก่อนหน้านี้ให้เสร็จสมบูรณ์ขณะที่เรียกดู Google Play Store การซื้อเหล่านี้เกิดขึ้นนอกแอปของคุณจากหน้าแรกของ Google Play Games ใน Google Play Store
ระบบจะเปิดใช้ฟีเจอร์นี้โดยค่าเริ่มต้นเพื่อช่วยให้ผู้ใช้ใช้งานต่อจากจุดที่หยุดไว้ และช่วยให้นักพัฒนาแอปเพิ่มยอดขายได้สูงสุด อย่างไรก็ตาม คุณสามารถเลือกไม่ใช้ฟีเจอร์นี้สำหรับแอปได้โดยส่งแบบฟอร์มการเลือกไม่ใช้ฟีเจอร์การช่วยเตือนการละทิ้งรถเข็นกลางคัน ดูแนวทางปฏิบัติแนะนำในการจัดการ SKU ภายใน Google Play Console ได้ที่ สร้างไอเทมที่ซื้อในแอป
รูปภาพต่อไปนี้แสดงการช่วยเตือนให้กลับไปชำระสินค้าในรถเข็นที่ปรากฏใน Google Play Store