คำแนะนำในการผสานรวมในแอปสำหรับตัวเลือกการเรียกเก็บเงิน

คู่มือนี้อธิบายวิธีผสานรวมแอปกับ Play Billing Library API เพื่อให้คุณเสนอตัวเลือกการเรียกเก็บเงินให้แก่ผู้ใช้ได้

การผสานรวมกับ PBL

คุณสามารถผสานรวมตัวเลือกการเรียกเก็บเงินกับ PBL ได้ใน 4 สถานการณ์ โดยสถานการณ์จะแตกต่างกันไปตามผู้แสดงผลหน้าจอตัวเลือกและสถานที่ที่จะมีการชำระเงิน ตารางต่อไปนี้สรุปสถานการณ์การผสานรวม

การชำระเงินเกิดขึ้นที่ใด
ในแอป เว็บลิงก์ภายนอก
คุณต้องการแสดงผลหน้าจอตัวเลือกการเรียกเก็บเงินใด ของ Google Play สถานการณ์ 1A

Google แสดงผลหน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายในแอปของคุณ

สถานการณ์ 1B

นักพัฒนาแอปแสดงผลหน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายในแอปของคุณ

ของคุณเอง (ตามหลักเกณฑ์ UX) สถานการณ์ 2A

Google แสดงผลหน้าจอตัวเลือกและระบบจะลิงก์ผู้ใช้ออกไปนอกแอปไปยังเว็บไซต์ของคุณเอง เพื่อทำการซื้อ

สถานการณ์ 2B

นักพัฒนาแอปแสดงผลหน้าจอตัวเลือกและระบบจะลิงก์ผู้ใช้ออกไปนอกแอปไปยังเว็บไซต์ของคุณเอง เพื่อทำการซื้อ

ภาพประกอบต่อไปนี้แสดงรายละเอียดขั้นตอนการเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจสำหรับแต่ละสถานการณ์

ขั้นตอนการเลือกการเรียกเก็บเงินที่แสดงลําดับการเรียก API และการโต้ตอบของผู้ใช้สําหรับสถานการณ์การผสานรวม 4 แบบ
รูปที่ 1 สถานการณ์การผสานรวมการเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจ

สถานการณ์การผสานรวม PBL

ทำตามขั้นตอนในส่วนนี้เพื่อใช้การเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจในแอปของคุณ ทั้งนี้ขึ้นอยู่กับสถานการณ์การผสานรวม

จัดการสถานการณ์ 1A

Google แสดงผลหน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายใน แอปของคุณ ทำตามขั้นตอนต่อไปนี้เพื่อเปิดใช้การเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจในสถานการณ์นี้

  1. เรียกใช้ enableBillingProgram ด้วย EnableBillingProgramParams เมื่อ สร้างอินสแตนซ์ BillingClient แล้วเริ่มการเชื่อมต่อ เช่น

    Kotlin

    
    // Build the parameters to enable the Billing Choice program and assign the listener
    // to handle user selection of the developer-provided billing option.
    val params = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
        .build()
    
    // Build the parameters to enable support for pending purchases.
    val pendingPurchasesParams = PendingPurchasesParams.newBuilder()
        .enableOneTimeProducts()
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(pendingPurchasesParams)
        .enableBillingProgram(params)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                continuation.resume(billingResult)
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.BillingResponseCode.SERVICE_DISCONNECTED)
                        .setDebugMessage("Billing service disconnected during connection setup")
                        .build()
                )
            }
        })
    }
    
    

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases(
                    PendingPurchasesParams.newBuilder()
                            .enableOneTimeProducts()
                            .build()
            )
            .enableBillingProgram(params)
            .build();
    
    
  2. ตรวจสอบว่าตัวเลือกการเรียกเก็บเงินที่ Google แสดงผลพร้อมให้บริการแก่ผู้ใช้

    เรียกใช้ isBillingProgramAvailableAsync เพื่อตรวจสอบความพร้อมให้บริการของโปรแกรม แล้วเรียกใช้ queryProductDetailsAsync เพื่อแสดงผลิตภัณฑ์ที่พร้อมให้บริการ เช่น

    Kotlin

    
    val (billingResult, billingProgramAvailabilityDetails) = billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    if (billingResult.responseCode == BillingResponseCode.OK) {
        val billingChoiceAvailabilityDetails = billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == ChoiceScreenType.GOOGLE_RENDERED
        ) {
            // Billing choice is available. Query products and proceed.
    
        } else {
            // Fallback to other available programs.
        }
    } else {
        // Fallback to other available programs.
    }
    
    
    

    Java

    
    // ...
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
    
                if (billingChoiceAvailabilityDetails != null &&
                    billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.GOOGLE_RENDERED) {
                    // Billing choice is available. Query products and proceed.
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    

    หมายเหตุ: billingProgramAvailabilityDetails จะบอกคุณว่าหน้าจอตัวเลือกการเรียกเก็บเงินที่ Google แสดงผลหรือนักพัฒนาแอปแสดงผลพร้อมให้บริการหรือไม่

  3. เรียกใช้ launchBillingFlow เพื่อทริกเกอร์ขั้นตอนการซื้อเมื่อผู้ใช้ คลิก "ซื้อ" หากตัวเลือกการเรียกเก็บเงินพร้อมให้บริการ ให้ส่ง DeveloperBillingOptionParams ไปยัง BillingFlowParams เช่น

    Kotlin

    
    val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build()
    
    val billingFlowParams = BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .enableDeveloperBillingOption(developerBillingOptionParams)
        .build()
    
    val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
    
    

    Java

    
    DeveloperBillingOptionParams developerBillingOptionParams =
        DeveloperBillingOptionParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .enableDeveloperBillingOption(developerBillingOptionParams)
            .build();
    
    BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
    
    

    หมายเหตุ: การควบคุมโดยผู้ปกครองจะแสดงสำหรับผู้ใช้ภายใต้การควบคุมดูแล

  4. จัดการตัวเลือกประเภทการเรียกเก็บเงินของผู้ใช้ดังนี้

    • หากผู้ใช้เลือก Play Billing ระบบจะส่งผลการเรียกเก็บเงินกลับไปยัง PurchasesUpdatedListener ที่ลงทะเบียนไว้ในขั้นตอนที่ 1
    • หากผู้ใช้เลือกการเรียกเก็บเงินระบบอื่นของคุณ ระบบจะส่งผลการเรียกเก็บเงินกลับไปยัง DeveloperProvidedBillingListener ที่ลงทะเบียนไว้ใน ขั้นตอนที่ 1 DeveloperProvidedBillingDetails ที่ส่งกลับมาจะมี externalTransactionToken ในกรณีนี้ ระบบจะใช้โทเค็นนี้สำหรับการรายงานธุรกรรม

จัดการสถานการณ์ 1B

นักพัฒนาแอปแสดงผลหน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายใน แอปของคุณ ทำตามขั้นตอนต่อไปนี้เพื่อเปิดใช้การเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจในสถานการณ์นี้

  1. เรียกใช้ enableBillingProgram โดยไม่มี DeveloperProvidedBillingListener ใน EnableBillingProgramParams เมื่อสร้างอินสแตนซ์ BillingClient แล้วเริ่มการเชื่อมต่อ เช่น

    Kotlin

    
    // Build the parameters to enable the Billing Choice program.
    val params = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases()
        .enableBillingProgram(params)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine<BillingResult> { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                continuation.resume(billingResult)
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.BillingResponseCode.SERVICE_DISCONNECTED)
                        .setDebugMessage("Billing service disconnected during connection setup")
                        .build()
                )
            }
        })
    }
    
    

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .enableBillingProgram(params)
            .build();
    
    
  2. ตรวจสอบว่าตัวเลือกการเรียกเก็บเงินที่นักพัฒนาแอปแสดงผลพร้อมให้บริการแก่ผู้ใช้

    เรียกใช้ isBillingProgramAvailableAsync เพื่อตรวจสอบความพร้อมให้บริการของโปรแกรม แล้วเรียกใช้ queryProductDetailsAsync เพื่อแสดงผลิตภัณฑ์ที่พร้อมให้บริการ เช่น

    Kotlin

    
    val (billingResult, billingProgramAvailabilityDetails) =
        billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    if (billingResult.responseCode == BillingResponseCode.OK) {
        val billingChoiceAvailabilityDetails =
            billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
    
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == ChoiceScreenType.DEVELOPER_RENDERED
        ) {
            // Billing choice is available. Query products and proceed.
            // You can inspect details such as:
            // - billingChoiceAvailabilityDetails.choiceScreenType
            // - billingChoiceAvailabilityDetails.isExternalLinkAvailable
        } else {
            // Fallback to other available programs.
        }
    } else {
        // Fallback to other available programs.
    }
    
    

    Java

    
    // ...
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
    
                if (billingChoiceAvailabilityDetails != null
                        && billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.DEVELOPER_RENDERED) {
                    // Billing choice is available. Query products and proceed.
                    // You can inspect details such as:
                    // - billingChoiceAvailabilityDetails.getChoiceScreenType()
                    // - billingChoiceAvailabilityDetails.isExternalLinkAvailable()
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    

    หมายเหตุ: billingProgramAvailabilityDetails จะบอกคุณว่าหน้าจอตัวเลือกการเรียกเก็บเงินที่ Google แสดงผล หรือนักพัฒนาแอปแสดงผลพร้อมให้บริการหรือไม่

  3. เรียกใช้เมธอด getBillingChoiceInfoAsync เพื่อรับแบนเนอร์ Play Billing และข้อมูลโปรแกรมสะสมแต้ม เช่น

    Kotlin

    
    // 1. Create the params required for the request
    val params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build()
    
    // 2. Call the suspend method on your billingClient instance
    val (billingResult, playBillingChoiceInfo) = billingClient.getBillingChoiceInfo(params)
    
    if (billingResult.responseCode == BillingResponseCode.OK && playBillingChoiceInfo != null) {
        // Access the URL of the image associated with the Play Billing Choice
        val imageUrl = playBillingChoiceInfo.playBillingChoiceImageUrl
    
        // Access the Play Loyalty string information, if available
        val loyaltyInfo = playBillingChoiceInfo.playBillingLoyaltyInfo
    
        // Populate your developer-rendered UI elements
        playBillingLoyaltyTextView.text = loyaltyInfo
        loadImage(imageUrl, playBillingImageView)
    } else {
        // Handle error scenarios
    }
    
    

    Java

    
    // 1. Create the params required for the request
    GetBillingChoiceInfoParams params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build();
    // 2. Call the method asynchronously on your billingClient instance
    billingClient.getBillingChoiceInfoAsync(params, (billingResult, playBillingChoiceInfo) -> {
        if (billingResult.getResponseCode() == BillingResponseCode.OK && playBillingChoiceInfo != null) {
          // Access the URL of the image associated with the Play Billing Choice
            String imageUrl = playBillingChoiceInfo.getPlayBillingChoiceImageUrl();
            // Access the Play Loyalty string information, if available
            String loyaltyInfo = playBillingChoiceInfo.getPlayBillingLoyaltyInfo();
    
            // Populate your developer-rendered UI elements
            playBillingLoyaltyTextView.setText(loyaltyInfo);
              loadImage(imageUrl, playBillingImageView);
          } else {
              // Handle error scenarios
          }
    });
    
    
  4. สร้างโทเค็นธุรกรรมภายนอกโดยตั้งค่า `DeveloperBillingType` เป็น IN_APP เช่น

    Kotlin

    
    // Build the parameters specifying the billing program and that the billing type is IN_APP.
    val params = BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperBillingType(DeveloperBillingType.IN_APP)
        .build()
    
    // Call the suspending extension function to request the reporting details
    val (billingResult, billingProgramReportingDetails) =
        billingClient.createBillingProgramReportingDetails(params)
        
    if (billingResult.responseCode != BillingResponseCode.OK) {
        // Handle failures such as retrying due to network errors.
        return
    }
    
    // Extract the transaction token from the returned reporting details
    val transactionToken = billingProgramReportingDetails?.externalTransactionToken
    
    // Persist the external transaction token locally. Pass it to
    // DeveloperBillingOptionParams when launchBillingFlow is called.
    // It can also be used as part of your external website
    
    

    Java

    
    BillingProgramReportingDetailsParams params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.IN_APP)
            .build();
    
    billingClient.createBillingProgramReportingDetailsAsync(
        params,
        new BillingProgramReportingDetailsListener() {
            @Override
            public void onCreateBillingProgramReportingDetailsResponse(
                BillingResult billingResult,
                @Nullable BillingProgramReportingDetails billingProgramReportingDetails
            ) {
                if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                    // Handle failures such as retrying due to network errors.
                    return;
                }
    
                String transactionToken =
                    billingProgramReportingDetails.getExternalTransactionToken();
    
                // Persist the external transaction token locally. Pass it to
                // DeveloperBillingOptionParams when launchBillingFlow is called.
                // It can also be used as part of your external website
            }
        }
    );
    
    
    
  5. เมื่อผู้ใช้คลิก "ซื้อ" ให้เรียกใช้ showBillingProgramInformationDialog เพื่อแสดงกล่องโต้ตอบข้อมูล ดูตัวอย่างได้ที่ กล่องโต้ตอบข้อมูลสำหรับผู้ใช้ คุณต้องตั้งค่า BillingProgram และ transactionToken จากขั้นตอนที่ 4 ในคำขอ

    หมายเหตุ: การควบคุมโดยผู้ปกครองจะแสดงสำหรับผู้ใช้ภายใต้การควบคุมดูแล

  6. เปิดหน้าจอตัวเลือกการเรียกเก็บเงินระบบอื่นหากผลลัพธ์จากขั้นตอนก่อนหน้าคือ OK

  7. จัดการตัวเลือกประเภทการเรียกเก็บเงินของผู้ใช้ดังนี้

    • หากผู้ใช้เลือก Play Billing ให้เรียกใช้ launchBillingFlow ตามคำแนะนำมาตรฐานของ Play Billing ระบบจะส่งผลการเรียกเก็บเงิน กลับไปยัง PurchasesUpdatedListener ที่ลงทะเบียนไว้ในขั้นตอนที่ 1
    • หากผู้ใช้เลือกการเรียกเก็บเงินระบบอื่นของคุณ คุณต้องจัดการธุรกรรมด้วยตนเองและรายงานไปยัง Play โดยใช้โทเค็นที่สร้างขึ้นในขั้นตอนที่ 4

จัดการสถานการณ์ 2A

Google แสดงผลหน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายนอก แอปของคุณ ทำตามขั้นตอนต่อไปนี้เพื่อเปิดใช้การเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจในสถานการณ์นี้

  1. เรียกใช้ enableBillingProgram ด้วย EnableBillingProgramParams เมื่อ สร้างอินสแตนซ์ BillingClient แล้วเริ่มการเชื่อมต่อ เช่น

    Kotlin

    
    // Build the parameters to enable the Billing Choice program and assign the listener
    // to handle user selection of the developer-provided billing option.
    val params = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
        .build()
    
    // Build the parameters to enable support for pending purchases.
    val pendingPurchasesParams = PendingPurchasesParams.newBuilder()
        .enableOneTimeProducts()
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(pendingPurchasesParams)
        .enableBillingProgram(params)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                continuation.resume(billingResult)
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.BillingResponseCode.SERVICE_DISCONNECTED)
                        .setDebugMessage("Billing service disconnected during connection setup")
                        .build()
                )
            }
        })
    }
    
    

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases(
                    PendingPurchasesParams.newBuilder()
                            .enableOneTimeProducts()
                            .build()
            )
            .enableBillingProgram(params)
            .build();
    
    
  2. ตรวจสอบความพร้อมให้บริการของรายการต่อไปนี้

    • ตัวเลือกการเรียกเก็บเงินที่ Google แสดงผล
    • เว็บลิงก์ภายนอก

    เรียกใช้ isBillingProgramAvailableAsync เพื่อตรวจสอบความพร้อมให้บริการของโปรแกรม แล้วเรียกใช้ queryProductDetailsAsync เพื่อแสดงผลิตภัณฑ์ที่พร้อมให้บริการ เช่น

    Kotlin

    
    // Check the availability of the billing choice program asynchronously using coroutines
    val (billingResult, billingProgramAvailabilityDetails) =
        billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    // Ensure the billing program query succeeded
    if (billingResult.responseCode == BillingResponseCode.OK) {
        // Retrieve the availability details specific to the billing choice program
        val billingChoiceAvailabilityDetails =
            billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
    
        // Check if billing choice is available, renders via Google Play, and external link is supported
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == ChoiceScreenType.GOOGLE_RENDERED &&
            billingChoiceAvailabilityDetails.isExternalLinkAvailable
        ) {
            // Billing choice is available and external transaction links are supported. Query products and proceed.
        } else {
            // Fallback to other available programs.
        }
    } else {
        // Fallback to other available programs.
    }
    
    
    

    Java

    
    // ...
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
    
                if (billingChoiceAvailabilityDetails != null
                        && billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.GOOGLE_RENDERED
                        && billingChoiceAvailabilityDetails.isExternalLinkAvailable()) {
                    // Billing choice is available and external transaction links are supported.
                    // Query products and proceed.
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    
    
  3. เรียกใช้ createBillingProgramReportingDetailsAsync เพื่อสร้างโทเค็นธุรกรรมภายนอก เมื่อผู้ใช้แสดงความตั้งใจที่จะซื้อ เช่น

    Kotlin

    
    // Build the parameters for creating reporting details
    val params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build()
    
    // Call the suspend function to create billing program reporting details
    val (billingResult, billingProgramReportingDetails) =
        billingClient.createBillingProgramReportingDetails(params)
    
    // Handle response failure cases
    if (billingResult.responseCode != BillingResponseCode.OK) {
        // Handle failures such as retrying due to network errors.
        return
    }
    
    // Retrieve the external transaction token
    val transactionToken =
        billingProgramReportingDetails?.externalTransactionToken
    
    // Persist the external transaction token locally. Pass it to
    // DeveloperBillingOptionParams when launchBillingFlow is called.
    // It can also be used as part of your external website
    
    

    Java

    
    BillingProgramReportingDetailsParams params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build();
    
    billingClient.createBillingProgramReportingDetailsAsync(
        params,
        new BillingProgramReportingDetailsListener() {
            @Override
            public void onCreateBillingProgramReportingDetailsResponse(
                BillingResult billingResult,
                @Nullable BillingProgramReportingDetails billingProgramReportingDetails
            ) {
                if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                    // Handle failures such as retrying due to network errors.
                    return;
                }
    
                String transactionToken =
                    billingProgramReportingDetails.getExternalTransactionToken();
    
                // Persist the external transaction token locally. Pass it to
                // DeveloperBillingOptionParams when launchBillingFlow is called.
                // It can also be used as part of your external website.
            }
        }
    );
    
    
  4. เรียกใช้ launchBillingFlow เพื่อทริกเกอร์ขั้นตอนการซื้อเมื่อผู้ใช้ คลิก "ซื้อ" หากตัวเลือกการเรียกเก็บเงินพร้อมให้บริการแก่ผู้ใช้ ให้ทำดังนี้

    1. ส่ง DeveloperBillingOptionParams ไปยัง BillingFlowParams
    2. ส่งโทเค็นธุรกรรมภายนอกจากขั้นตอนที่ 3 ไปยัง DeveloperBillingOptionParams

    เช่น

    Kotlin

    
    // Build the developer billing option parameters with the external link URI,
    // the transaction token, and browser/app launch mode.
    val developerBillingOptionParams =
        DeveloperBillingOptionParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setLinkUri(Uri.parse("https://www.example.com/external/purchase"))
            .setExternalTransactionToken(transactionToken)
            .setLaunchMode(
                DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP
            )
            .build()
    
    

    Java

    
    DeveloperBillingOptionParams developerBillingOptionParams =
        DeveloperBillingOptionParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setLinkUri(Uri.parse("https://www.example.com/external/purchase"))
            .setExternalTransactionToken(transactionToken)
            .setLaunchMode(
              DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
            .build();
    
    

    หมายเหตุ: การควบคุมโดยผู้ปกครองจะแสดงสำหรับ ผู้ใช้ภายใต้การควบคุมดูแล

  5. จัดการตัวเลือกประเภทการเรียกเก็บเงินของผู้ใช้ดังนี้

    • หากผู้ใช้เลือก Play Billing ให้เรียกใช้ launchBillingFlow ตามคำแนะนำมาตรฐานของ Play Billing ระบบจะส่งผลการเรียกเก็บเงิน กลับไปยัง PurchasesUpdatedListener ที่ลงทะเบียนไว้ในขั้นตอนที่ 1
    • หากผู้ใช้เลือกการเรียกเก็บเงินระบบอื่นของคุณ ระบบจะส่งผลการเรียกเก็บเงินกลับไปยัง DeveloperProvidedBillingListener ที่ลงทะเบียนไว้ในขั้นตอนที่
      1. DeveloperProvidedBillingDetails ที่ส่งกลับมาจะมี externalTransactionToken ที่ส่งไปยัง DeveloperBillingOptionParams ในขั้นตอนที่ 4 หากเป็นโทเค็นที่ถูกต้อง

จัดการสถานการณ์ 2B

นักพัฒนาแอปแสดงผลหน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายนอก แอป ทำตามขั้นตอนต่อไปนี้เพื่อเปิดใช้การเรียกเก็บเงินแบบให้ผู้ใช้ตัดสินใจในสถานการณ์นี้

  1. เรียกใช้ enableBillingProgram โดยไม่มี DeveloperProvidedBillingListener ใน EnableBillingProgramParams เมื่อสร้างอินสแตนซ์ BillingClient แล้วเริ่มการเชื่อมต่อ เช่น

    Kotlin

    
    // Build the parameters to enable the Billing Choice program.
    val params = EnableBillingProgramParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build()
    
    // Construct the BillingClient instance with the purchases updated listener,
    // pending purchases support, and the billing choice params.
    val billingClient = BillingClient.newBuilder(context)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases()
        .enableBillingProgram(params)
        .build()
    
    // Establish a connection to Google Play
    val billingResult = suspendCancellableCoroutine<BillingResult> { continuation ->
        billingClient.startConnection(object : BillingClientStateListener {
            // Called when the connection setup process completes.
            override fun onBillingSetupFinished(billingResult: BillingResult) {
                // Resume the coroutine and pass back the BillingResult to the caller.
                continuation.resume(billingResult)
            }
    
            // Called if the connection to the Play Store service is dropped.
            // This prevents the await or suspension point from hanging indefinitely.
            override fun onBillingServiceDisconnected() {
                continuation.resume(
                    BillingResult.newBuilder()
                        .setResponseCode(BillingClient.BillingResponseCode.SERVICE_DISCONNECTED)
                        .setDebugMessage("Billing service disconnected during connection setup")
                        .build()
                )
            }
        })
    }
    
    

    Java

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .enableBillingProgram(params)
            .build();
    
    
  2. ตรวจสอบความพร้อมให้บริการของรายการต่อไปนี้

    • ตัวเลือกการเรียกเก็บเงินที่ Google แสดงผล
    • เว็บลิงก์ภายนอก

    เรียกใช้ isBillingProgramAvailableAsync เพื่อตรวจสอบความพร้อมให้บริการของโปรแกรม แล้วเรียกใช้ queryProductDetailsAsync เพื่อแสดงผลิตภัณฑ์ที่พร้อมให้บริการ เช่น

    Kotlin

    
    // Check the availability of the billing choice program asynchronously using a coroutine
    val (billingResult, billingProgramAvailabilityDetails) =
        billingClient.isBillingProgramAvailable(BillingProgram.BILLING_CHOICE)
    
    // Ensure the response code is OK
    if (billingResult.responseCode == BillingResponseCode.OK) {
        // Retrieve the billing choice availability details
        val billingChoiceAvailabilityDetails =
            billingProgramAvailabilityDetails.billingChoiceAvailabilityDetails
    
        // Check if billing choice details are available, choice screen is developer-rendered,
        // and external transaction links are supported.
        if (billingChoiceAvailabilityDetails != null &&
            billingChoiceAvailabilityDetails.choiceScreenType == ChoiceScreenType.DEVELOPER_RENDERED &&
            billingChoiceAvailabilityDetails.isExternalLinkAvailable
        ) {
            // Billing choice is available and external transaction links are supported.
            // Query products and proceed.
        } else {
            // Fallback to other available programs.
        }
    } else {
        // Fallback to other available programs.
    }
    
    

    Java

    
    // ...
    
    billingClient.isBillingProgramAvailableAsync(
        BillingProgram.BILLING_CHOICE,
        (billingResult, billingProgramAvailabilityDetails) -> {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                BillingChoiceAvailabilityDetails billingChoiceAvailabilityDetails =
                    billingProgramAvailabilityDetails.getBillingChoiceAvailabilityDetails();
                if (billingChoiceAvailabilityDetails != null &&
                    billingChoiceAvailabilityDetails.getChoiceScreenType() == ChoiceScreenType.DEVELOPER_RENDERED &&
                    billingChoiceAvailabilityDetails.isExternalLinkAvailable()) {
                    // Billing choice is available and external transaction links are supported. Query products and proceed.
                } else {
                    // Fallback to other available programs.
                }
            } else {
                // Fallback to other available programs.
            }
        }
    );
    
    
  3. เรียกใช้เมธอด getBillingChoiceInfoAsync เพื่อรับแบนเนอร์ Play Billing และข้อมูลโปรแกรมสะสมแต้ม

    Kotlin

    
    // 1. Create the params required for the request
    val params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build()
    
    // 2. Call the suspend method on your billingClient instance
    val (billingResult, playBillingChoiceInfo) = billingClient.getBillingChoiceInfo(params)
    
    if (billingResult.responseCode == BillingResponseCode.OK && playBillingChoiceInfo != null) {
        // Access the URL of the image associated with the Play Billing Choice
        val imageUrl = playBillingChoiceInfo.playBillingChoiceImageUrl
    
        // Access the Play Loyalty string information, if available
        val loyaltyInfo = playBillingChoiceInfo.playBillingLoyaltyInfo
    
        // Populate your developer-rendered UI elements
        playBillingLoyaltyTextView.text = loyaltyInfo
        loadImage(imageUrl, playBillingImageView)
    } else {
        // Handle error scenarios
    }
    
    

    Java

    
    // 1. Create the params required for the request
    GetBillingChoiceInfoParams params = GetBillingChoiceInfoParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .setPlayBillingChoiceImageLayout(GetBillingChoiceInfoParams.ImageLayout.RECTANGULAR_FOUR_BY_ONE)
        .build();
    // 2. Call the method asynchronously on your billingClient instance
    billingClient.getBillingChoiceInfoAsync(params, (billingResult, playBillingChoiceInfo) -> {
        if (billingResult.getResponseCode() == BillingResponseCode.OK && playBillingChoiceInfo != null) {
          // Access the URL of the image associated with the Play Billing Choice
            String imageUrl = playBillingChoiceInfo.getPlayBillingChoiceImageUrl();
            // Access the Play Loyalty string information, if available
            String loyaltyInfo = playBillingChoiceInfo.getPlayBillingLoyaltyInfo();
    
            // Populate your developer-rendered UI elements
            playBillingLoyaltyTextView.setText(loyaltyInfo);
              loadImage(imageUrl, playBillingImageView);
          } else {
              // Handle error scenarios
          }
    });
    
    
  4. เรียกใช้ createBillingProgramReportingDetailsAsync เพื่อสร้างโทเค็นธุรกรรมภายนอก เมื่อผู้ใช้แสดงความตั้งใจที่จะซื้อ เช่น

    Kotlin

    
    // Build the parameters for creating reporting details
    val params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build()
    
    // Call the suspend function to create billing program reporting details
    val (billingResult, billingProgramReportingDetails) =
        billingClient.createBillingProgramReportingDetails(params)
    
    // Handle response failure cases
    if (billingResult.responseCode != BillingResponseCode.OK) {
        // Handle failures such as retrying due to network errors.
        return
    }
    
    // Retrieve the external transaction token
    val transactionToken =
        billingProgramReportingDetails?.externalTransactionToken
    
    // Persist the external transaction token locally. Pass it to
    // DeveloperBillingOptionParams when launchBillingFlow is called.
    // It can also be used as part of your external website
    
    

    Java

    
    BillingProgramReportingDetailsParams params =
        BillingProgramReportingDetailsParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
            .build();
    
    billingClient.createBillingProgramReportingDetailsAsync(
        params,
        new BillingProgramReportingDetailsListener() {
            @Override
            public void onCreateBillingProgramReportingDetailsResponse(
                BillingResult billingResult,
                @Nullable BillingProgramReportingDetails billingProgramReportingDetails
            ) {
                if (billingResult.getResponseCode() != BillingResponseCode.OK) {
                    // Handle failures such as retrying due to network errors.
                    return;
                }
    
                String transactionToken =
                    billingProgramReportingDetails.getExternalTransactionToken();
    
                // Persist the external transaction token locally. Pass it to
                // DeveloperBillingOptionParams when launchBillingFlow is called.
                // It can also be used as part of your external website.
            }
        }
    );
    
    
  5. เปิดหน้าจอตัวเลือกการเรียกเก็บเงินระบบอื่นเมื่อผู้ใช้คลิก "ซื้อ"

  6. จัดการตัวเลือกประเภทการเรียกเก็บเงินของผู้ใช้ดังนี้

    • หากผู้ใช้เลือก Play Billing ให้เรียกใช้ launchBillingFlow ตามคำแนะนำมาตรฐานของ Play Billing ระบบจะส่งผลการเรียกเก็บเงิน กลับไปยัง PurchasesUpdatedListener ที่ลงทะเบียนไว้ในขั้นตอนที่ 1

      การควบคุมโดยผู้ปกครองจะแสดงสำหรับ ผู้ใช้ภายใต้การควบคุมดูแล

    • หากผู้ใช้เลือกการเรียกเก็บเงินระบบอื่นของคุณ ให้เรียกใช้ `launchExternalLink` เช่น

      Kotlin

      
      // An activity reference from which the purchase flow will be launched.
      val activity: Activity = ...
      
      val params = LaunchExternalLinkParams.newBuilder()
          .setBillingProgram(BillingProgram.BILLING_CHOICE)
          // You can pass along the external transaction token from
          // BillingProgramReportingDetails as a URL parameter in the URI
          .setLinkUri(yourLinkUri)
          .setLinkType(LaunchExternalLinkParams.LinkType.LINK_TO_DIGITAL_CONTENT_OFFER)
          .setLaunchMode(
              LaunchExternalLinkParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP
          )
          .build()
      
      // Call launchExternalLink with a callback
      billingClient.launchExternalLink(activity, params) { billingResult ->
          if (billingResult.responseCode == BillingResponseCode.OK) {
              // Proceed with the rest of the purchase flow. If the user
              // purchases an item, be sure to report the transaction to Google
              // Play.
          } else {
              // Handle failures such as retrying due to network errors.
          }
      }
      
      

      Java

      
      // An activity reference from which the purchase flow will be launched.
      Activity activity = ...;
      
      LaunchExternalLinkParams params = LaunchExternalLinkParams.newBuilder()
          .setBillingProgram(BillingProgram.BILLING_CHOICE)
          // You can pass along the external transaction token from
          // BillingProgramReportingDetails as a URL parameter in the URI
          .setLinkUri(yourLinkUri)
          .setLinkType(LaunchExternalLinkParams.LinkType.LINK_TO_DIGITAL_CONTENT_OFFER)
          .setLaunchMode(
              LaunchExternalLinkParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
          .setExternalTransactionToken(transactionToken)
          .build();
      
      LaunchExternalLinkResponseListener listener =
          new LaunchExternalLinkResponseListener() {
            @Override
            public void onLaunchExternalLinkResponse(BillingResult billingResult) {
              if (billingResult.getResponseCode() == BillingResponseCode.OK) {
                // Proceed with the rest of the purchase flow. If the user
                // purchases an item, be sure to report the transaction to Google
                // Play.
              } else {
                // Handle failures such as retrying due to network errors.
              }
            }
          };
      
      billingClient.launchExternalLink(activity, params, listener);
      
      
    • ส่งโทเค็นธุรกรรมภายนอกจากขั้นตอนที่ 4 ไปยัง LaunchExternalLinkParams หากระบบส่งกลับมาเป็น "ตกลง" ให้ดำเนินการธุรกรรมต่อและรายงานธุรกรรมไปยัง Google Play

      การควบคุมโดยผู้ปกครองจะแสดงสำหรับ ผู้ใช้ภายใต้การควบคุมดูแล.

ตัวเลือกการเรียกเก็บเงินระหว่างการเปลี่ยนการสมัครใช้บริการ

สำหรับการเปลี่ยนการสมัครใช้บริการ ระบบไม่ควรแสดงหน้าจอตัวเลือกของผู้ใช้ เนื่องจากระบบจะเก็บรักษาตัวเลือกของผู้ใช้สำหรับการซื้อเดิมไว้สำหรับการอัปเกรดและการดาวน์เกรด

หากการซื้อเดิมดำเนินการผ่าน Google Play Billing คุณ ควรเรียกใช้ launchBillingFlow พร้อมข้อมูลการเปลี่ยนการสมัครใช้บริการมาตรฐานของ Google Play Billing

อย่างไรก็ตาม หากการซื้อเดิมดำเนินการผ่านการเรียกเก็บเงินระบบอื่น การจัดการการเปลี่ยนการสมัครใช้บริการจะแตกต่างกันเล็กน้อยตาม สถานการณ์

การเปลี่ยนการสมัครใช้บริการในสถานการณ์ 1A

ผู้ใช้ที่ขออัปเกรดหรือดาวน์เกรดควรดำเนินการผ่านระบบการเรียกเก็บเงินระบบอื่นของนักพัฒนาแอปโดยไม่ต้องผ่านประสบการณ์การใช้งานตัวเลือกของผู้ใช้อีกครั้ง

หากต้องการดำเนินการนี้ ให้เรียกใช้ launchBillingFlow เมื่อผู้ใช้ขออัปเกรดหรือ ดาวน์เกรด ใช้ setOriginalExternalTransactionId ภายในออบเจ็กต์ SubscriptionUpdateParams ในพารามิเตอร์เพื่อระบุรหัสธุรกรรมภายนอกสำหรับการซื้อเดิม การดำเนินการนี้จะไม่แสดงหน้าจอตัวเลือกของผู้ใช้ เนื่องจากระบบจะเก็บรักษาตัวเลือกของผู้ใช้สำหรับการซื้อเดิมไว้สำหรับการอัปเกรดและการดาวน์เกรด การเรียกใช้ launchBillingFlow ในกรณีนี้ จะสร้าง โทเค็นธุรกรรมภายนอกใหม่ สำหรับธุรกรรมที่คุณสามารถ ดึงข้อมูลได้จาก Callback

Kotlin


// The external transaction ID from the current
// alternative billing subscription.
val externalTransactionId = //... ;

val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
    .setBillingProgram(BillingProgram.BILLING_CHOICE)
    .build()

val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched using queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in
                // ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        BillingFlowParams.SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()
    )
    .enableDeveloperBillingOption(developerBillingOptionParams)
    .build()

val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)

// When the user selects the alternative billing flow,
// the DeveloperProvidedBillingListener is triggered.

Java


// The external transaction ID from the current
// alternative billing subscription.
String externalTransactionId = //... ;

DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .build();

List<ProductDetailsParams> productDetailsParamsList = new ArrayList<>();
productDetailsParamsList.add(
    ProductDetailsParams.newBuilder()
        // Fetched using queryProductDetailsAsync.
        .setProductDetails(productDetailsNewPlan)
        // offerIdToken can be found in
        // ProductDetails=>SubscriptionOfferDetails
        .setOfferToken(offerTokenNewPlan)
        .build());

BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .setSubscriptionUpdateParams(
            SubscriptionUpdateParams.newBuilder()
                .setOriginalExternalTransactionId(externalTransactionId)
                .build())
        .enableDeveloperBillingOption(developerBillingOptionParams)
        .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

// When the user selects the alternative billing flow,
// the DeveloperProvidedBillingListener is triggered.


เมื่อการอัปเกรดหรือดาวน์เกรดเสร็จสมบูรณ์ คุณต้องรายงานธุรกรรมใหม่ โดยใช้โทเค็นธุรกรรมภายนอกที่ได้รับจากการ เรียกใช้ครั้งก่อนสำหรับการซื้อการสมัครใช้บริการใหม่

การเปลี่ยนการสมัครใช้บริการในสถานการณ์ 1B

ในสถานการณ์นี้ คุณต้องสร้างโทเค็นธุรกรรมภายนอกใหม่ ความแตกต่างจากการซื้อปกติเพียงอย่างเดียวคือในสถานการณ์นี้ ระบบจะเก็บรักษาตัวเลือกของผู้ใช้ไว้ และคุณไม่ต้องแสดงหน้าจอตัวเลือกสำหรับการอัปเกรดหรือดาวน์เกรด อย่างไรก็ตาม คุณต้องแสดงกล่องโต้ตอบข้อมูลแบบครั้งเดียวและการรับทราบของผู้ปกครอง

ดูโค้ดการผสานรวมตัวอย่างได้ที่ ขั้นตอนที่ 4 ในสถานการณ์ 1B: นักพัฒนาแอปแสดงผล หน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายในแอปของคุณ

เมื่อการอัปเกรดหรือดาวน์เกรดเสร็จสมบูรณ์ คุณต้องรายงานธุรกรรมใหม่ โดยใช้โทเค็นธุรกรรมภายนอกที่ได้รับจากการ เรียกใช้ครั้งก่อนสำหรับการซื้อการสมัครใช้บริการใหม่

การเปลี่ยนการสมัครใช้บริการในสถานการณ์ 2A

สำหรับการสมัครใช้บริการที่ซื้อผ่านเว็บไซต์ของนักพัฒนาแอปหรือแอปการชำระเงินหลังจากที่ผู้ใช้เลือกตัวเลือกแล้ว ผู้ใช้ที่ขออัปเกรดหรือดาวน์เกรดควรดำเนินการผ่านเว็บไซต์ของนักพัฒนาแอปหรือแอปการชำระเงินโดยไม่ต้องผ่านประสบการณ์การใช้งานตัวเลือกของผู้ใช้อีกครั้ง

หากต้องการดำเนินการนี้ ให้เรียกใช้ launchBillingFlow เมื่อผู้ใช้ขออัปเกรดหรือ ดาวน์เกรด ให้ใช้ setOriginalExternalTransactionId โดยระบุรหัสธุรกรรมภายนอกสำหรับการซื้อเดิมแทนการระบุพารามิเตอร์อื่นๆ ภายใต้ออบเจ็กต์ SubscriptionUpdateParams นอกจากนี้ คุณต้องระบุ DeveloperBillingOptionParams ในการเรียกใช้นี้ด้วย การดำเนินการนี้จะไม่แสดงหน้าจอตัวเลือกของผู้ใช้ เนื่องจากระบบจะเก็บรักษาตัวเลือกของผู้ใช้สำหรับการซื้อเดิมไว้สำหรับการอัปเกรดและการดาวน์เกรด เช่น

Kotlin


val externalTransactionId = //... ;

// 1. Construct DeveloperBillingOptionParams indicating the billing program
val developerBillingOptionParams = DeveloperBillingOptionParams.newBuilder()
    .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
    .build()

// 2. Build BillingFlowParams combining DeveloperBillingOptionParams and SubscriptionUpdateParams
val billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        listOf(
            BillingFlowParams.ProductDetailsParams.newBuilder()
                // Fetched using queryProductDetailsAsync.
                .setProductDetails(productDetailsNewPlan)
                // offerIdToken can be found in ProductDetails=>SubscriptionOfferDetails.
                .setOfferToken(offerTokenNewPlan)
                .build()
        )
    )
    .setSubscriptionUpdateParams(
        SubscriptionUpdateParams.newBuilder()
            .setOriginalExternalTransactionId(externalTransactionId)
            .build()
    )
    .enableDeveloperBillingOption(developerBillingOptionParams)
    .build()

Java


String externalTransactionId = //... ;

// 1. Construct DeveloperBillingOptionParams indicating the billing program
DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingClient.BillingProgram.BILLING_CHOICE)
        .build();

// 2. Add ProductDetailsParams
List productDetailsParamsList = new ArrayList<>();
productDetailsParamsList.add(
    ProductDetailsParams.newBuilder()
        // Fetched using queryProductDetailsAsync.
        .setProductDetails(productDetailsNewPlan)
        // offerIdToken can be found in ProductDetails=>SubscriptionOfferDetails
        .setOfferToken(offerTokenNewPlan)
        .build());

// 3. Build BillingFlowParams combining DeveloperBillingOptionParams and SubscriptionUpdateParams
BillingFlowParams billingFlowParams =
    BillingFlowParams.newBuilder()
        .setProductDetailsParamsList(productDetailsParamsList)
        .setSubscriptionUpdateParams(
            SubscriptionUpdateParams.newBuilder()
                .setOriginalExternalTransactionId(externalTransactionId)
                .build())
        .enableDeveloperBillingOption(developerBillingOptionParams)
        .build();


นอกจากนี้ คุณต้องสร้างโทเค็นธุรกรรมภายนอกใหม่ด้วย เช่น

Kotlin


val params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
        .build()

billingClient.createBillingProgramReportingDetailsAsync(
    params,
    object : BillingProgramReportingDetailsListener {
        override fun onCreateBillingProgramReportingDetailsResponse(
            billingResult: BillingResult,
            billingProgramReportingDetails: BillingProgramReportingDetails?
        ) {
            if (billingResult.responseCode != BillingResponseCode.OK) {
                // Handle failures such as retrying due to network errors.
                return
            }
            val externalTransactionToken =
                billingProgramReportingDetails?.externalTransactionToken
            // Persist the external transaction token locally. Pass it to
            // the external website using DeveloperBillingOptionParams when
            // launchBillingFlow is called.
        }
    }
)

Java


BillingProgramReportingDetailsParams params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.BILLING_CHOICE)
        .setDeveloperBillingType(DeveloperBillingType.EXTERNAL_LINK)
        .build();

billingClient.createBillingProgramReportingDetailsAsync(
    params,
    new BillingProgramReportingDetailsListener() {
      @Override
      public void onCreateBillingProgramReportingDetailsResponse(
          BillingResult billingResult,
          @Nullable BillingProgramReportingDetails billingProgramReportingDetails) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
          // Handle failures such as retrying due to network errors.
          return;
        }
        String transactionToken =
            billingProgramReportingDetails.getExternalTransactionToken();
        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
      }
    });

หลังจากสร้างโทเค็นใหม่แล้ว คุณต้องเรียกใช้เมธอด launchBillingFlow เพื่อเปิดใช้ขั้นตอนการซื้อ

เมื่อการอัปเกรดหรือดาวน์เกรดเสร็จสมบูรณ์ คุณต้องรายงานธุรกรรมใหม่ โดยใช้โทเค็นธุรกรรมภายนอกที่ได้รับจากการ เรียกใช้ครั้งก่อนสำหรับการซื้อการสมัครใช้บริการใหม่

การเปลี่ยนการสมัครใช้บริการในสถานการณ์ 2B

ขั้นตอนการจัดการการเปลี่ยนการสมัครใช้บริการในสถานการณ์นี้คล้ายกับขั้นตอนที่อธิบายไว้ในการเปลี่ยนการสมัครใช้บริการในสถานการณ์ 2A ความแตกต่างเพียงอย่างเดียวคือหลังจากสร้างโทเค็นธุรกรรมแล้ว คุณต้องเรียกใช้ launchExternalLink เพื่อแสดงกล่องโต้ตอบคำเตือนการลิงก์ออกแทนการเรียกใช้เมธอด launchBillingFlow ในสถานการณ์นี้ ระบบจะเก็บรักษาตัวเลือกของผู้ใช้ไว้ และคุณไม่ต้องแสดงหน้าจอตัวเลือกสำหรับการอัปเกรดหรือดาวน์เกรด

ดูโค้ดการผสานรวมตัวอย่างได้ที่ ขั้นตอนที่ 6 ในสถานการณ์ 2B: นักพัฒนาแอปแสดงผล หน้าจอตัวเลือกและจัดการการเรียกเก็บเงินระบบอื่นภายในแอปของคุณ

เมื่อการอัปเกรดหรือดาวน์เกรดเสร็จสมบูรณ์ คุณต้องรายงานธุรกรรมใหม่ โดยใช้โทเค็นธุรกรรมภายนอกที่ได้รับจากการ เรียกใช้ครั้งก่อนสำหรับการซื้อการสมัครใช้บริการใหม่