หัวข้อนี้จะอธิบายวิธีผสานรวม Google Play Billing Library ไว้ใน แอปของคุณเพื่อเริ่มขายผลิตภัณฑ์
ตลอดอายุการซื้อ
ขั้นตอนการซื้อโดยทั่วไปสำหรับการซื้อครั้งเดียวหรือการสมัครใช้บริการมีดังนี้
- แสดงให้ผู้ใช้เห็นสิ่งที่ซื้อได้
- เปิดขั้นตอนการซื้อเพื่อให้ผู้ใช้ยอมรับการซื้อ
- ยืนยันการซื้อบนเซิร์ฟเวอร์ของคุณ
- ให้เนื้อหาแก่ผู้ใช้
- รับทราบการนำส่งเนื้อหา สำหรับผลิตภัณฑ์เพื่อการบริโภค ให้ใช้ เพื่อให้ผู้ใช้ซื้อได้อีกครั้ง
การสมัครใช้บริการจะต่ออายุโดยอัตโนมัติจนกว่าจะมีการยกเลิก การสมัครใช้บริการสามารถทำได้ ผ่านสถานะต่อไปนี้
- ใช้งานอยู่: ผู้ใช้อยู่ในสถานะดีและมีสิทธิ์เข้าถึงการสมัครใช้บริการ
- ยกเลิกแล้ว: ผู้ใช้ยกเลิกแล้ว แต่ยังมีสิทธิ์เข้าถึงจนกว่าจะหมดอายุ
- ในระยะเวลาผ่อนผัน: ผู้ใช้ประสบปัญหาการชําระเงินแต่ยังคงเข้าถึงได้ ขณะที่ Google กำลังลองใช้วิธีการชำระเงินอีกครั้ง
- ถูกระงับ: ผู้ใช้ประสบปัญหาการชำระเงิน และไม่มีสิทธิ์เข้าถึงอีกต่อไป Google กำลังลองใช้วิธีการชำระเงินอีกครั้ง
- หยุดชั่วคราว: ผู้ใช้หยุดสิทธิ์เข้าถึงชั่วคราวและจะไม่มีสิทธิ์เข้าถึงจนกว่าผู้ใช้ ให้กลับมาเริ่มอีกครั้ง
- หมดอายุแล้ว: ผู้ใช้ยกเลิกและสูญเสียสิทธิ์เข้าถึงการสมัครใช้บริการ ถือว่าผู้ใช้เลิกใช้งานเมื่อหมดอายุ
เริ่มต้นการเชื่อมต่อกับ Google Play
ขั้นตอนแรกในการผสานรวมกับระบบการเรียกเก็บเงินของ Google Play คือการเพิ่ม Google Play Billing Library ไปยังแอปของคุณและเริ่มการเชื่อมต่อ
เพิ่มทรัพยากร Dependency ของ Google Play Billing Library
เพิ่มทรัพยากร Dependency ของ Google Play Billing Library ลงในbuild.gradle
ของแอป
ตามที่แสดงไว้:
ดึงดูด
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing:$billing_version") }
หากคุณใช้ Kotlin โมดูล KTX ของ Google Play Billing Library ประกอบด้วย
รองรับส่วนขยายและโครูทีน Kotlin ที่ให้คุณเขียนสำนวนได้
Kotlin เมื่อใช้ Google Play Billing Library หากต้องการรวมรายการเหล่านี้
ส่วนขยายในโปรเจ็กต์ของคุณ ให้เพิ่มทรัพยากร Dependency ต่อไปนี้ในส่วน
build.gradle
ไฟล์ตามภาพที่แสดง
ดึงดูด
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
เริ่มต้น BillingClient
เมื่อคุณเพิ่มทรัพยากร Dependency ใน Google Play Billing Library แล้ว
เพื่อเริ่มต้นอินสแตนซ์ BillingClient
BillingClient
เป็นหมายเลขหลัก
เพื่อการสื่อสารระหว่าง Google Play Billing Library กับ
ที่เหลือในแอปด้วย BillingClient
มีวิธีอำนวยความสะดวกทั้งแบบซิงโครนัส
และไม่พร้อมกัน สำหรับการดำเนินการเรียกเก็บเงินทั่วไป เราขอแนะนำเป็นอย่างยิ่ง
คุณเปิดการเชื่อมต่อ BillingClient
ที่ใช้งานอยู่ 1 รายการพร้อมกันเพื่อ
หลีกเลี่ยงการเรียกกลับของ PurchasesUpdatedListener
หลายครั้งในเหตุการณ์เดียว
หากต้องการสร้าง 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
หากต้องการใช้ตรรกะการลองอีกครั้ง ให้ลบล้าง onBillingServiceDisconnected()
Callback และตรวจสอบว่า BillingClient
เรียกใช้เมธอด
วิธี startConnection()
เพื่อเชื่อมต่อกับ Google Play อีกครั้งก่อนดำเนินการ
คำขอเพิ่มเติม
ตัวอย่างต่อไปนี้แสดงวิธีเริ่มต้นการเชื่อมต่อ และทดสอบว่าการเชื่อมต่อ พร้อมใช้:
Kotlin
billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } override fun onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } })
Java
billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } });
แสดงผลิตภัณฑ์ที่พร้อมจำหน่าย
หลังจากที่คุณสร้างการเชื่อมต่อกับ Google Play คุณก็พร้อมที่จะค้นหา สำหรับผลิตภัณฑ์ที่พร้อมจำหน่าย และแสดงให้ผู้ใช้เห็น
การค้นหารายละเอียดผลิตภัณฑ์เป็นขั้นตอนสำคัญก่อนที่จะแสดง ผลิตภัณฑ์ให้แก่ผู้ใช้ของคุณ เพราะจะแสดงข้อมูลผลิตภัณฑ์ที่แปลเป็นภาษาท้องถิ่น สำหรับ สำหรับการสมัครใช้บริการ โปรดตรวจสอบว่าการแสดงผลิตภัณฑ์เป็นไปตามนโยบายทั้งหมดของ Play
โทร queryProductDetailsAsync()
เพื่อขอรายละเอียดไอเทมที่ซื้อในแอป
ในการจัดการผลของการดำเนินการแบบอะซิงโครนัส คุณจะต้องระบุ
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, productDetailsList -> // check billingResult // process returned productDetailsList }
Java
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) { // check billingResult // process returned productDetailsList } } )
เมื่อค้นหารายละเอียดผลิตภัณฑ์ ให้ส่งตัวอย่าง
QueryProductDetailsParams
ที่ระบุรายการสตริงรหัสผลิตภัณฑ์
ที่สร้างใน Google Play Console พร้อมกับ ProductType
ProductType
สามารถเป็น ProductType.INAPP
สำหรับผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว หรือ
ProductType.SUBS
สำหรับการสมัครใช้บริการ
การค้นหาด้วยส่วนขยาย Kotlin
หากใช้ส่วนขยาย Kotlin คุณค้นหาไอเทมที่ซื้อในแอปได้
โดยเรียกใช้ฟังก์ชันส่วนขยาย queryProductDetails()
queryProductDetails()
ใช้ประโยชน์จากโครูทีน Kotlin เพื่อให้คุณไม่ต้อง
กำหนด 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 5
ประมวลผลผลลัพธ์
Google Play Billing Library จะจัดเก็บผลการค้นหาไว้ใน List
ของ
ออบเจ็กต์ ProductDetails
รายการ จากนั้น คุณสามารถเรียกหลายวิธีใน
ProductDetails
ออบเจ็กต์ในรายการเพื่อดูข้อมูลที่เกี่ยวข้องกับในแอป
เช่น ราคา หรือรายละเอียด วิธีดูรายละเอียดผลิตภัณฑ์ที่พร้อมจำหน่าย
โปรดดูรายการเมธอดในคลาส ProductDetails
ก่อนที่จะเสนอขายสินค้า โปรดตรวจสอบว่าผู้ใช้ไม่ได้เป็นเจ้าของ รายการ หากผู้ใช้มีอุปกรณ์สิ้นเปลืองที่ยังอยู่ในคลังรายการของผู้ใช้ ต้องบริโภครายการก่อนที่จะซื้อได้อีกครั้ง
ก่อนเสนอการสมัครใช้บริการ โปรดยืนยันว่าผู้ใช้นั้นยังไม่ได้สมัครใช้บริการ และโปรดทราบข้อมูลต่อไปนี้
queryProductDetailsAsync()
ส่งคืนรายละเอียดผลิตภัณฑ์ที่ต้องสมัครใช้บริการและ สูงสุด 50 ข้อเสนอต่อการสมัครใช้บริการ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) // For One-time product, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user .setOfferToken(selectedOfferToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() // Launch the billing flow val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For one-time products, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call // ProductDetails.subscriptionOfferDetails() for a list of offers // that are available to the user. .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
เมธอด launchBillingFlow()
จะแสดงโค้ดตอบกลับรายการใดรายการหนึ่งที่ระบุไว้ใน
BillingClient.BillingResponseCode
อย่าลืมตรวจสอบผลการค้นหานี้เพื่อ
ตรวจสอบว่าไม่มีข้อผิดพลาดในการเปิดขั้นตอนการซื้อ BillingResponseCode
ของ OK
หมายถึงการเปิดที่สำเร็จ
เมื่อโทรหา launchBillingFlow()
สำเร็จ ระบบจะแสดงหมายเลข Google
หน้าจอซื้อของ Play รูปที่ 1 แสดงหน้าจอการซื้อการสมัครใช้บริการ
![หน้าจอซื้อของ Google Play แสดงการสมัครใช้บริการ
พร้อมจำหน่าย](https://developer.android.google.cn/static/images/google/play/billing/purchase-screen.png?authuser=0000&hl=th)
Google Play โทรหา onPurchasesUpdated()
เพื่อแจ้งผลการซื้อ
ไปยัง Listener ที่ใช้ PurchasesUpdatedListener
ของ Google ระบบจะระบุ Listener โดยใช้เมธอด setListener()
เมื่อคุณ
เริ่มต้นไคลเอ็นต์ของคุณ
คุณต้องใช้ onPurchasesUpdated()
เพื่อจัดการโค้ดตอบกลับที่เป็นไปได้
ตัวอย่างต่อไปนี้แสดงวิธีลบล้าง onPurchasesUpdated()
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
Java
@Override void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
การซื้อที่สำเร็จจะสร้างหน้าจอแสดงขั้นตอนสำเร็จในการซื้อใน Google Play ซึ่งคล้ายกับ รูปที่ 2
![หน้าจอการซื้อของ Google Play ที่สำเร็จ](https://developer.android.google.cn/static/images/google/play/billing/purchase-success.png?authuser=0000&hl=th)
การซื้อที่สำเร็จจะสร้างโทเค็นการซื้อด้วย ซึ่งเป็นโทเค็นที่ไม่ซ้ำ ตัวระบุที่แสดงถึงผู้ใช้และรหัสผลิตภัณฑ์สําหรับไอเทมที่ซื้อในแอป ที่พวกเขาซื้อ แอปของคุณสามารถจัดเก็บโทเค็นการซื้อไว้ในเครื่องได้ แต่เรา ขอแนะนำให้ส่งโทเค็นไปยังเซิร์ฟเวอร์แบ็กเอนด์ที่ปลอดภัย ซึ่งคุณจะ ยืนยันการซื้อและป้องกันการประพฤติมิชอบ กระบวนการนี้มีการอธิบายเพิ่มเติม ในส่วนต่อไปนี้
และผู้ใช้จะได้รับอีเมลใบเสร็จของธุรกรรมที่มีรหัสคำสั่งซื้อ หรือ รหัสธุรกรรมที่ไม่ซ้ำกัน ผู้ใช้จะได้รับอีเมลพร้อมรหัสคำสั่งซื้อที่ไม่ซ้ำกัน สำหรับการซื้อผลิตภัณฑ์แบบครั้งเดียวแต่ละครั้ง และสำหรับการสมัครใช้บริการครั้งแรก การซื้อและการต่ออายุอัตโนมัติตามรอบที่ตามมา คุณสามารถใช้รหัสคำสั่งซื้อ เพื่อจัดการการคืนเงินใน Google Play Console
ระบุราคาสำหรับคุณโดยเฉพาะ
หากสามารถจัดจำหน่ายแอปให้แก่ผู้ใช้ในสหภาพยุโรปได้ ให้ใช้
setIsOfferPersonalized()
วิธีในการเปิดเผยให้ผู้ใช้ทราบว่าราคาของสินค้าหนึ่งๆ
ที่ปรับให้เหมาะกับแต่ละบุคคลโดยใช้
การตัดสินใจอัตโนมัติ
![หน้าจอการซื้อใน Google Play ที่ระบุว่ามีการปรับราคาให้เหมาะกับผู้ใช้](https://developer.android.google.cn/static/images/google/play/billing/personalized-pricing.png?authuser=0000&hl=th)
คุณต้องปรึกษา Art 6 (1) (ea) CRD ของคำสั่งว่าด้วยสิทธิของผู้บริโภค 2011/83/EU เพื่อพิจารณาว่าราคาที่คุณเสนอแก่ผู้ใช้คือ ที่ปรับเปลี่ยนในแบบของคุณ
setIsOfferPersonalized()
รับอินพุตบูลีน เมื่อ true
UI ของ Play
มีการเปิดเผยข้อมูลด้วย โดย UI จะละเว้นการเปิดเผยข้อมูลเมื่อ false
ค่าเริ่มต้น
ค่าคือ false
ดูข้อมูลเพิ่มเติมที่ศูนย์ช่วยเหลือผู้บริโภค
กำลังดำเนินการซื้อ
เมื่อผู้ใช้ทำการซื้อเสร็จสมบูรณ์ แอปของคุณจะต้องประมวลผลการซื้อนั้น
ในกรณีส่วนใหญ่ แอปของคุณจะได้รับการแจ้งเตือนเกี่ยวกับการซื้อผ่านทาง
PurchasesUpdatedListener
แต่ก็มีบางกรณีที่แอป
ทราบเกี่ยวกับการซื้อด้วยการโทรไปที่ BillingClient.queryPurchasesAsync()
ตามที่อธิบายไว้ในการดึงข้อมูลการซื้อ
นอกจากนี้ หากคุณมีไคลเอ็นต์การแจ้งเตือนแบบเรียลไทม์สำหรับนักพัฒนาซอฟต์แวร์ใน
แบ็กเอนด์ที่ปลอดภัยแล้ว คุณสามารถลงทะเบียนการซื้อใหม่ได้โดยรับ
subscriptionNotification
หรือoneTimeProductNotification
ซึ่งแจ้งเตือนเกี่ยวกับ
การซื้อใหม่ เมื่อได้รับการแจ้งเตือนเหล่านี้แล้ว ให้โทรติดต่อ Google Play
API สำหรับนักพัฒนาซอฟต์แวร์ เพื่อรับสถานะที่สมบูรณ์และอัปเดตสถานะแบ็กเอนด์ของคุณเอง
แอปของคุณควรประมวลผลการซื้อในลักษณะต่อไปนี้
- ยืนยันการซื้อ
- มอบเนื้อหาให้แก่ผู้ใช้และรับทราบการส่งมอบเนื้อหา (ไม่บังคับ) ทำเครื่องหมายรายการว่าใช้แล้วเพื่อให้ผู้ใช้ซื้อไอเทมได้ อีกครั้ง
หากต้องการยืนยันการซื้อ ก่อนอื่นให้ตรวจสอบว่าสถานะการซื้อคือ
PURCHASED
หากการซื้อPENDING
คุณควรประมวลผล
การซื้อตามที่อธิบายไว้ในการจัดการธุรกรรมที่รอดำเนินการ สำหรับการซื้อ
ที่ได้รับจาก onPurchasesUpdated()
หรือ queryPurchasesAsync()
คุณ
ควรตรวจสอบการซื้อเพิ่มเติมเพื่อให้แน่ใจว่าถูกต้องตามกฎหมายก่อนที่แอปจะให้สิทธิ์
หากต้องการดูวิธียืนยันการซื้ออย่างถูกต้อง โปรดดูหัวข้อยืนยันการซื้อ
ก่อนให้สิทธิ์
เมื่อยืนยันการซื้อแล้ว แอปของคุณก็พร้อมที่จะให้สิทธิ์
ผู้ใช้ บัญชีผู้ใช้ที่เชื่อมโยงกับการซื้อสามารถระบุด้วย
ProductPurchase.obfuscatedExternalAccountId
ส่งคืนโดย
Purchases.products:get
สำหรับการซื้อผลิตภัณฑ์ในแอปและ
SubscriptionPurchase.obfuscatedExternalAccountId
ส่งคืนโดย
Purchases.subscriptions:get
สำหรับการสมัครใช้บริการฝั่งเซิร์ฟเวอร์ หรือ
obfuscatedAccountId
จาก Purchase.getAccountIdentifiers()
ในพื้นที่
ฝั่งไคลเอ็นต์ หากตั้งค่ารายการหนึ่งด้วย setObfuscatedAccountId
เมื่อ
ได้ทำการซื้อแล้ว
หลังจากให้สิทธิ์แล้ว แอปจะต้องรับทราบการซื้อ ช่วงเวลานี้ การรับทราบจะแจ้ง Google Play ว่าคุณได้ให้อนุญาต สำหรับการซื้อ
กระบวนการในการให้สิทธิ์และรับทราบการซื้อขึ้นอยู่กับว่า การซื้อเป็นแบบใช้แล้วหมดไป การซื้อไม่ได้ หรือการสมัครใช้บริการ
ผลิตภัณฑ์อุปโภคบริโภค
สำหรับโฆษณาที่ใช้แล้วหมดไป หากแอปมีแบ็กเอนด์ที่ปลอดภัย เราขอแนะนำให้ใช้
Purchases.products:consume
เพื่อให้ใช้การซื้อได้อย่างน่าเชื่อถือ ตรวจสอบว่า
ยังไม่มีการใช้งานรายการที่ซื้อ โดยการตรวจสอบ consumptionState
จาก
ผลจากการเรียก Purchases.products:get
หากแอปของคุณเป็นแบบไคลเอ็นต์เท่านั้น
ที่ไม่มีแบ็กเอนด์ ให้ใช้ consumeAsync()
จาก
Google Play Billing Library ทั้ง 2 วิธีจะช่วยส่งเสริมการตอบรับ
และระบุว่าแอปของคุณให้สิทธิแก่ผู้ใช้
วิธีการเหล่านี้ยังช่วยให้แอปสร้างผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียวที่สอดคล้องกับ
โทเค็นการซื้อที่ป้อนซึ่งสามารถซื้ออีกครั้งได้ กับ consumeAsync()
คุณ
ต้องส่งออบเจ็กต์ที่ใช้งาน ConsumeResponseListener
ด้วย
ของ Google ออบเจ็กต์นี้จัดการผลลัพธ์ของการดำเนินการบริโภค คุณสามารถ
ลบล้างเมธอด onConsumeResponse()
ซึ่งฟังก์ชัน
Google Play Billing Library จะเรียกใช้เมื่อการดำเนินการเสร็จสมบูรณ์
ตัวอย่างต่อไปนี้แสดงการใช้ผลิตภัณฑ์ที่มี Google Play Billing Library ที่ใช้โทเค็นการซื้อที่เชื่อมโยง
Kotlin
suspend fun handlePurchase(purchase: Purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. val purchase : Purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) } }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. Purchase purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); ConsumeResponseListener listener = new ConsumeResponseListener() { @Override public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } } }; billingClient.consumeAsync(consumeParams, listener); }
ผลิตภัณฑ์ที่ใช้แล้วหมดไป
ในการรับทราบการซื้อที่บริโภคไม่ได้ หากแอปมีแบ็กเอนด์ที่ปลอดภัย เราจะ
ขอแนะนำให้ใช้ Purchases.products:acknowledge
เพื่อรับทราบ
การซื้อ ตรวจสอบว่ายังไม่มีการรับทราบการซื้อนี้ก่อนหน้านี้
กำลังตรวจสอบ acknowledgementState
จากผลการโทร
Purchases.products:get
หากแอปของคุณเป็นแบบไคลเอ็นต์เท่านั้น ให้ใช้ BillingClient.acknowledgePurchase()
จาก
Google Play Billing Library ไว้ในแอปของคุณ ก่อนรับทราบ
แอปควรตรวจสอบว่ามีการรับทราบแล้วหรือไม่โดยใช้
isAcknowledged()
ใน Google Play Billing Library
ตัวอย่างต่อไปนี้แสดงวิธีตอบรับการซื้อโดยใช้ Google Play Billing Library
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... suspend fun handlePurchase() { if (purchase.purchaseState === PurchaseState.PURCHASED) { if (!purchase.isAcknowledged) { val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) } } } }
Java
BillingClient client = ... AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ... void handlePurchase(Purchase purchase) { if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
การสมัครใช้บริการ
การสมัครใช้บริการจะได้รับการจัดการในลักษณะเดียวกับรายการที่รับชมไม่ได้ หากเป็นไปได้ ให้ใช้
Purchases.subscriptions.acknowledge
จาก
API สำหรับนักพัฒนาแอปของ Google Play เพื่อตอบรับการซื้อจาก
แบ็กเอนด์ที่ปลอดภัย ตรวจสอบว่าการซื้อดังกล่าวยังไม่เคยมีการยอมรับโดย
กำลังตรวจสอบ acknowledgementState
ในแหล่งข้อมูลการซื้อจาก
Purchases.subscriptions:get
มิฉะนั้น คุณสามารถรับทราบ
การสมัครใช้บริการที่ใช้ BillingClient.acknowledgePurchase()
จาก
Google Play Billing Library หลังจากที่ตรวจสอบ isAcknowledged()
ทั้งหมด
คุณต้องรับทราบการซื้อการสมัครใช้บริการครั้งแรก การต่ออายุการสมัครใช้บริการ
คุณไม่จำเป็นต้องรับทราบ ดูข้อมูลเพิ่มเติมเกี่ยวกับเวลาที่สมัครใช้บริการ
คุณต้องรับทราบ โปรดดูหัวข้อขายการสมัครใช้บริการ
กำลังดึงข้อมูลการซื้อ
การฟังอัปเดตการซื้อโดยใช้ PurchasesUpdatedListener
ไม่
เพียงพอที่จะทำให้แอปประมวลผลการซื้อทั้งหมดได้ เป็นไปได้ว่า
อาจไม่ทราบถึงการซื้อทั้งหมดที่ผู้ใช้ทำ นี่คือบางส่วน
สถานการณ์ที่แอปอาจพลาดการติดตามหรือไม่ทราบการซื้อโดยไม่รู้ตัว
- ปัญหาเกี่ยวกับเครือข่ายระหว่างการซื้อ: ผู้ใช้ทำการซื้อเสร็จสมบูรณ์
และได้รับการยืนยันจาก Google แต่อุปกรณ์ขาดเครือข่าย
การเชื่อมต่อก่อนที่อุปกรณ์จะได้รับการแจ้งเตือนเกี่ยวกับการซื้อ
ผ่าน
PurchasesUpdatedListener
- อุปกรณ์หลายเครื่อง: ผู้ใช้ซื้อสินค้าในอุปกรณ์เครื่องหนึ่งและคาดหวังว่าจะดำเนินการ จะเห็นรายการเมื่อเปลี่ยนอุปกรณ์
- การจัดการการซื้อภายนอกแอป: การซื้อบางอย่าง เช่น คุณสามารถแลกรับโปรโมชันภายนอกแอปได้
หากต้องการจัดการกับสถานการณ์เหล่านี้ อย่าลืมเรียกแอป
BillingClient.queryPurchasesAsync()
ในเมธอด onResume()
เพื่อ
ตรวจสอบว่าการซื้อทั้งหมดได้รับการประมวลผลเสร็จสมบูรณ์ตามที่อธิบายไว้ในการประมวลผล
ตัวอย่างต่อไปนี้แสดงวิธีดึงข้อมูลการซื้อการสมัครใช้บริการของผู้ใช้
โปรดทราบว่า queryPurchasesAsync()
จะแสดงเฉพาะการสมัครใช้บริการที่ใช้งานอยู่และ
เป็นการซื้อครั้งเดียวที่ไม่มีการใช้งาน
Kotlin
val params = QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) // uses queryPurchasesAsync Kotlin extension function val purchasesResult = billingClient.queryPurchasesAsync(params.build()) // check purchasesResult.billingResult // process returned purchasesResult.purchasesList, e.g. display the plans user owns
Java
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) .build(), new PurchasesResponseListener() { public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) { // check billingResult // process returned purchase list, e.g. display the plans user owns } } );
การจัดการกับการซื้อที่ดำเนินการนอกแอปของคุณ
การซื้อบางอย่าง เช่น การแลกรับโปรโมชัน อาจเกิดขึ้นได้นอกแอป เมื่อผู้ใช้ทำการซื้อนอกแอป พวกเขาคาดหวังว่าแอปจะแสดง ข้อความในแอป หรือใช้กลไกการแจ้งเตือนบางอย่างเพื่อให้ผู้ใช้ ทำให้ทราบว่าแอปได้รับและประมวลผลการซื้ออย่างถูกต้อง ยอมรับได้บางส่วน ได้แก่
- แสดงป๊อปอัปในแอป
- ส่งข้อความไปยังกล่องข้อความในแอป และระบุอย่างชัดเจนว่า เป็นข้อความใหม่ในกล่องข้อความในแอป
- ใช้ข้อความแจ้งเตือนของระบบปฏิบัติการ
โปรดทราบว่าแอปของคุณอาจอยู่ในสถานะใดก็ได้เมื่อแอป จดจำการซื้อนั้นได้ แม้กระทั่งแอปของคุณอาจ ติดตั้งเมื่อทำการซื้อ ผู้ใช้คาดหวังว่าจะได้รับสิ่งที่ซื้อ เมื่อผู้ใช้กลับมาใช้แอปอีกครั้ง ไม่ว่าแอปจะอยู่ในสถานะใดก็ตาม
คุณต้องตรวจหาการซื้อโดยไม่คํานึงถึงสถานะของแอปเมื่อ ได้ทำการซื้อแล้ว แต่มีข้อยกเว้นบางประการที่สามารถยอมรับได้ ไม่แจ้งให้ผู้ใช้ทราบทันทีว่าได้รับสินค้าแล้ว เช่น
- ระหว่างการดำเนินการในเกม ซึ่งการแสดงข้อความอาจทำให้ ผู้ใช้ ในกรณีนี้ คุณต้องแจ้งให้ผู้ใช้ทราบหลังสิ้นสุดส่วนการดำเนินการ
- ระหว่างที่ใช้คัตซีน ซึ่งการแสดงข้อความอาจเบี่ยงเบนความสนใจของผู้ใช้ ด้วยวิธีนี้ คุณต้องแจ้งให้ผู้ใช้ทราบหลังจากที่คัตซีนสิ้นสุดลง
- ระหว่างบทแนะนำเริ่มต้นและส่วนต่างๆ ที่ผู้ใช้ตั้งค่าในเกม คำแนะนำจากเรา คุณแจ้งให้ผู้ใช้ใหม่ทราบเกี่ยวกับรางวัลทันทีหลังจากที่เปิดเกม หรือ ระหว่างการตั้งค่าผู้ใช้ครั้งแรก อย่างไรก็ตาม คุณสามารถรอจนกว่า ลำดับเกมพร้อมให้แจ้งเตือนผู้ใช้
คำนึงถึงผู้ใช้เสมอเมื่อตัดสินใจว่าจะแจ้งให้ผู้ใช้ทราบเมื่อใดและอย่างไร
การซื้อที่ดำเนินการนอกแอปของคุณ เมื่อใดก็ตามที่ผู้ใช้ไม่ได้รับ
การแจ้งเตือน ผู้ใช้อาจสับสน และอาจหยุดใช้แอปของคุณ ติดต่อผู้ใช้
หรือบ่นเกี่ยวกับเรื่องนี้บนโซเชียลมีเดีย หมายเหตุ:
PurchasesUpdatedListener
ลงทะเบียนกับใบสมัครของคุณแล้ว
บริบทในการจัดการการอัปเดตการซื้อ รวมถึงการซื้อที่เริ่มต้นภายนอก
ของแอปของคุณ ซึ่งหมายความว่าหากไม่มีขั้นตอนการสมัคร
PurchasesUpdatedListener
จะไม่ได้รับการแจ้งเตือน แอปของคุณจึงควร
เรียก BillingClient.queryPurchasesAsync()
ในเมธอด onResume()
เป็น
ที่ระบุไว้ในดึงข้อมูลการซื้อ
การจัดการธุรกรรมที่รอดำเนินการ
Google Play รองรับธุรกรรมที่รอดำเนินการหรือธุรกรรมที่ต้องมีธุรกรรมที่ต้องมีหรือ ขั้นตอนเพิ่มเติมระหว่างเวลาที่ผู้ใช้เริ่มซื้อและเมื่อ วิธีการชำระเงินสำหรับการซื้อได้รับการประมวลผลแล้ว แอปของคุณไม่ควรให้สิทธิ์ ได้รับสิทธิ์ในการซื้อประเภทเหล่านี้จนกว่า Google จะแจ้งให้คุณทราบว่า เรียกเก็บเงินจากวิธีการชำระเงินของผู้ใช้เรียบร้อยแล้ว
ตัวอย่างเช่น ผู้ใช้สามารถเริ่มธุรกรรมโดยการเลือกกิจการที่มีหน้าร้านจริง ซึ่งพวกเขาจะใช้เงินสดทีหลัง ผู้ใช้จะได้รับรหัสผ่านทั้ง การแจ้งเตือนและอีเมล เมื่อผู้ใช้มาถึงกิจการที่มีหน้าร้านจริง ผู้ใช้จะ สามารถแลกรหัสกับแคชเชียร์ และชำระด้วยเงินสด จากนั้น Google จะแจ้งเตือน ทั้งคุณและผู้ใช้ที่ได้รับการชำระเงินแล้ว จากนั้นแอปของคุณสามารถให้สิทธิ์ การให้สิทธิ์แก่ผู้ใช้
เรียกใช้ enablePendingPurchases()
เพื่อเริ่มกระบวนการ
BillingClient
เพื่อเปิดใช้ธุรกรรมที่รอดำเนินการสำหรับแอปของคุณ แอปของคุณต้อง
เปิดใช้งานและสนับสนุนธุรกรรมที่รอดำเนินการสำหรับผลิตภัณฑ์แบบเรียกเก็บเงินครั้งเดียว ก่อน
การเพิ่มการสนับสนุน โปรดตรวจสอบว่าคุณเข้าใจวงจรการซื้อสำหรับรอดำเนินการ
ธุรกรรม
เมื่อแอปได้รับการซื้อใหม่ ไม่ว่าจะผ่านทาง
PurchasesUpdatedListener
หรือเป็นผลจากการโทร
queryPurchasesAsync()
ให้ใช้เมธอด getPurchaseState()
เพื่อ
กำหนดสถานะการซื้อเป็น PURCHASED
หรือ PENDING
คุณควร
ให้สิทธิเฉพาะเมื่อรัฐคือ PURCHASED
หากแอปของคุณทำงานอยู่เมื่อผู้ใช้ทำการซื้อเสร็จสมบูรณ์
มีการเรียก PurchasesUpdatedListener
อีกครั้ง และ PurchaseState
เปลี่ยนเป็น
PURCHASED
ณ จุดนี้ แอปของคุณสามารถประมวลผลการซื้อโดยใช้มาตรฐาน
วิธีประมวลผลการซื้อ แอปของคุณควรเรียกใช้
queryPurchasesAsync()
ในเมธอด onResume()
ของแอปเพื่อจัดการการซื้อ
ที่เปลี่ยนเป็นสถานะ PURCHASED
ขณะที่แอปของคุณไม่ได้ทำงานอยู่
เมื่อการซื้อเปลี่ยนจาก PENDING
เป็น
PURCHASED
ไคลเอ็นต์การแจ้งเตือนแบบเรียลไทม์สำหรับนักพัฒนาซอฟต์แวร์จะได้รับ
ONE_TIME_PRODUCT_PURCHASED
หรือ
การแจ้งเตือน SUBSCRIPTION_PURCHASED
รายการ หากการซื้อถูกยกเลิก คุณจะ
ได้รับ ONE_TIME_PRODUCT_CANCELED
หรือ
การแจ้งเตือน SUBSCRIPTION_PENDING_PURCHASE_CANCELED
รายการ เหตุการณ์นี้อาจเกิดขึ้นได้หาก
ลูกค้าไม่ชำระเงินให้เสร็จสมบูรณ์ภายในระยะเวลาที่กำหนด โปรดทราบว่า
สามารถใช้ API สำหรับนักพัฒนาซอฟต์แวร์ Google Play เพื่อตรวจสอบสถานะปัจจุบันของ
การซื้อ
การจัดการกับการซื้อแบบหลายจำนวน
รองรับใน Google Play Billing Library เวอร์ชัน 4.0 ขึ้นไป Google Play ช่วยให้ลูกค้าสามารถซื้อของในแอปเดียวกันได้มากกว่า 1 รายการ ผลิตภัณฑ์ในธุรกรรมเดียวโดยระบุจำนวนจากรถเข็นที่ซื้อ บัญชี จะต้องรองรับการซื้อแบบหลายจำนวนและให้สิทธิ์ สำหรับจำนวนการซื้อที่ระบุ
หากต้องการใช้การซื้อแบบหลายจำนวน ตรรกะการจัดสรรของแอปจะต้องตรวจสอบ
สำหรับจำนวนสินค้า คุณสามารถเข้าถึงช่อง quantity
ได้จาก
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
}
}
});