เอกสารนี้อธิบายวิธีผสานรวม 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 ด้วย ผู้ฟังรายนี้จะได้รับการอัปเดตสำหรับการซื้อทั้งหมดในแอปของคุณ
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() { // 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
วิธีนี้จะแสดงข้อเสนอหลายรายการตามการกำหนดค่าผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว
ของคุณ ดูข้อมูลเพิ่มเติมได้ที่ตัวเลือกการซื้อและข้อเสนอหลายรายการ
สำหรับไอเทมแบบเรียกเก็บเงินครั้งเดียว
หากต้องการจัดการผลลัพธ์ของการดำเนินการแบบไม่พร้อมกัน คุณต้องระบุ
เครื่องมือฟังที่ใช้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, 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() เพื่อส่งผลลัพธ์ของการดำเนินการ
ซื้อไปยัง Listener ที่ใช้ 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 หลังจากตรวจสอบ isAcknowledged() แล้วก็ได้ การซื้อการสมัครใช้บริการครั้งแรกทั้งหมดต้องได้รับการรับทราบ การต่ออายุการสมัครใช้บริการ
ไม่จำเป็นต้องได้รับการรับทราบ ดูข้อมูลเพิ่มเติมเกี่ยวกับเวลาที่ต้องรับทราบการสมัครใช้บริการได้ที่หัวข้อขายการสมัครใช้บริการ
สรุป
ข้อมูลโค้ดต่อไปนี้แสดงสรุปขั้นตอนเหล่านี้
Kotlin
fun handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your // onPurchasesUpdated. 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 (delaying // notification if needed as discussed above). // Step 4: Notify Google the purchase was processed using the steps // discussed in the processing purchases section. }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your // onPurchasesUpdated. 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 (delaying // notification if needed as discussed above). // Step 4: Notify Google the purchase was processed using the steps // discussed in the processing purchases section. }
หากต้องการยืนยันว่าแอปได้ติดตั้งใช้งานขั้นตอนเหล่านี้อย่างถูกต้องแล้ว ให้ทำตามคู่มือการทดสอบ
จัดการธุรกรรมที่รอดำเนินการ
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 Developer 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 } } });
การช่วยเตือนการทิ้งรถเข็นในหน้าแรกของ Google Play Games (เปิดใช้โดยค่าเริ่มต้น)
สำหรับนักพัฒนาแอปเกมที่สร้างรายได้ผ่านผลิตภัณฑ์แบบครั้งเดียว วิธีหนึ่งในการขายหน่วยเก็บสินค้า (SKU) ที่ใช้งานอยู่ใน Google Play Console นอกแอปของคุณคือฟีเจอร์การช่วยเตือนการละทิ้งรถเข็นกลางคัน ซึ่งจะกระตุ้นให้ผู้ใช้ดำเนินการซื้อที่หยุดกลางคันก่อนหน้านี้ให้เสร็จสมบูรณ์ขณะเรียกดู Google Play Store การซื้อเหล่านี้เกิดขึ้นนอกแอปของคุณจากหน้าแรกของ Google Play Games ใน Google Play Store
ระบบจะเปิดใช้ฟีเจอร์นี้โดยค่าเริ่มต้นเพื่อช่วยให้ผู้ใช้ใช้งานต่อจากจุดที่หยุดไว้ และช่วยให้นักพัฒนาแอปเพิ่มยอดขายได้สูงสุด อย่างไรก็ตาม คุณสามารถเลือกไม่ใช้ฟีเจอร์นี้สำหรับแอปได้โดยส่งแบบฟอร์มการเลือกไม่ใช้ฟีเจอร์การช่วยเตือนการละทิ้งรถเข็นกลางคัน ดูแนวทางปฏิบัติแนะนำในการจัดการ SKU ภายใน Google Play Console ได้ที่ สร้างไอเทมที่ซื้อในแอป
รูปภาพต่อไปนี้แสดงการช่วยเตือนให้กลับไปชำระสินค้าในรถเข็นที่ปรากฏใน Google Play Store