راهنمای ادغام درون برنامه‌ای برای انتخاب صورتحساب

این راهنما نحوه ادغام برنامه شما با APIهای کتابخانه پرداخت Play را شرح می‌دهد تا بتوانید به کاربران خود حق انتخاب در مورد پرداخت را ارائه دهید.

ادغام با PBL

شما می‌توانید انتخاب صورتحساب را با PBL در چهار سناریو ادغام کنید. سناریوها بر اساس اینکه چه کسی صفحه انتخاب را نمایش می‌دهد و پرداخت کجا انجام می‌شود، متفاوت هستند. جدول زیر سناریوهای ادغام را شرح می‌دهد:

پرداخت کجا اتفاق می‌افتد؟
درون برنامه‌ای پیوند وب خارجی
کدام صفحه انتخاب صورتحساب را می‌خواهید رندر کنید؟ گوگل پلی سناریوی ۱الف

گوگل صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین در برنامه شما مدیریت می‌شود .

سناریوی ۱ب

توسعه‌دهنده‌ی برنامه، صفحه‌ی انتخاب را رندر می‌کند و صورتحساب جایگزین در برنامه‌ی شما مدیریت می‌شود .

خودتان (مطابق با دستورالعمل‌های UX) سناریوی ۲الف

گوگل صفحه انتخاب را نمایش می‌دهد و کاربر برای خرید به خارج از برنامه شما به وب‌سایت‌های خودتان لینک می‌شود.

سناریوی ۲ب

توسعه‌دهنده‌ی اپلیکیشن، صفحه‌ی انتخاب را رندر می‌کند و کاربر برای خرید ، به وب‌سایت‌های شما در خارج از اپلیکیشن متصل می‌شود.

تصویر زیر جریان انتخاب صورتحساب را برای هر یک از این سناریوها شرح می‌دهد:

جریان انتخاب صورتحساب که توالی فراخوانی‌های API و تعاملات کاربر را برای چهار سناریوی ادغام نشان می‌دهد.
شکل 1. سناریوهای ادغام انتخاب صورتحساب

سناریوهای ادغام PBL

بسته به سناریوی ادغام خود، مراحل این بخش را برای پیاده‌سازی انتخاب صورتحساب در برنامه خود دنبال کنید.

سناریوی ۱A را مدیریت کنید

گوگل صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین در برنامه شما مدیریت می‌شود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:

  1. هنگام ساخت نمونه‌ی BillingClient خود، enableBillingProgram با EnableBillingProgramParams فراخوانی کنید و سپس اتصال را آغاز کنید. برای مثال:

    کاتلین

    
    // 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()
                )
            }
        })
    }
    
    

    جاوا

    
    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. تأیید کنید که گزینه پرداخت ارائه شده توسط گوگل برای کاربر در دسترس است.

    برای بررسی در دسترس بودن برنامه، تابع isBillingProgramAvailableAsync را فراخوانی کنید و سپس برای نمایش محصولات موجود، تابع queryProductDetailsAsync را فراخوانی کنید. برای مثال:

    کاتلین

    
    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.
    }
    
    
    

    جاوا

    
    // ...
    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 به شما می‌گوید که آیا صفحه انتخاب صورتحساب رندر شده توسط گوگل یا رندر شده توسط توسعه‌دهنده در دسترس است یا خیر.

  3. برای فعال کردن جریان خرید هنگام کلیک کاربر روی خرید، تابع launchBillingFlow فراخوانی کنید. اگر گزینه‌ی پرداخت در دسترس است، DeveloperBillingOptionParams را به BillingFlowParams ارسال کنید. برای مثال:

    کاتلین

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

    جاوا

    
    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 ثبت‌شده در مرحله‌ی ۱ بازگردانده می‌شود.
    • اگر کاربر روش پرداخت جایگزین شما را انتخاب کند، نتیجه پرداخت به DeveloperProvidedBillingListener ثبت شده در مرحله 1 بازگردانده می‌شود. DeveloperProvidedBillingDetails بازگردانده شده در این مورد حاوی یک externalTransactionToken است. این توکن برای گزارش تراکنش استفاده خواهد شد.

سناریوی ۱ب را مدیریت کنید

توسعه‌دهنده صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین در برنامه شما مدیریت می‌شود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:

  1. هنگام ساخت یک نمونه BillingClient تابع enableBillingProgram بدون DeveloperProvidedBillingListener در EnableBillingProgramParams فراخوانی کنید و سپس اتصال را آغاز کنید. برای مثال:

    کاتلین

    
    // 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()
                )
            }
        })
    }
    
    

    جاوا

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .enableBillingProgram(params)
            .build();
    
    
  2. تأیید کنید که گزینه‌ی پرداخت ارائه شده توسط توسعه‌دهنده برای کاربر در دسترس است.

    برای بررسی در دسترس بودن برنامه، تابع isBillingProgramAvailableAsync را فراخوانی کنید و سپس برای نمایش محصولات موجود، تابع queryProductDetailsAsync را فراخوانی کنید. برای مثال:

    کاتلین

    
    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.
    }
    
    

    جاوا

    
    // ...
    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 به شما می‌گوید که آیا صفحه انتخاب صورتحساب رندر شده توسط گوگل یا رندر شده توسط توسعه‌دهنده در دسترس است یا خیر.

  3. برای دریافت بنر Play Billing و اطلاعات وفاداری، متد getBillingChoiceInfoAsync را فراخوانی کنید. برای مثال:

    کاتلین

    
    // 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
    }
    
    

    جاوا

    
    // 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 ایجاد کنید. برای مثال:

    کاتلین

    
    // 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
    
    

    جاوا

    
    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 از مرحله ۴ باید در درخواست تنظیم شوند.

    توجه : کنترل والدین برای کاربران تحت نظارت نمایش داده می‌شود.

  6. اگر نتیجه مرحله قبل OK بود، صفحه انتخاب صورتحساب جایگزین خود را اجرا کنید.

  7. انتخاب نوع صورتحساب توسط کاربر را به صورت زیر مدیریت کنید:

    • اگر کاربر Play Billing را انتخاب کند، launchBillingFlow طبق راهنمای استاندارد Play Billing فراخوانی کنید. نتیجه‌ی صورتحساب به PurchasesUpdatedListener ثبت‌شده در مرحله‌ی ۱ بازگردانده می‌شود.
    • اگر کاربر روش پرداخت جایگزین شما را انتخاب کند، باید خودتان تراکنش را انجام دهید و با استفاده از توکن تولید شده در مرحله ۴، آن را به Play گزارش دهید.

سناریوی ۲A را مدیریت کنید

گوگل صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین خارج از برنامه شما مدیریت می‌شود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:

  1. هنگام ساخت نمونه‌ی BillingClient خود، enableBillingProgram با EnableBillingProgramParams فراخوانی کنید و سپس اتصال را آغاز کنید. برای مثال:

    کاتلین

    
    // 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()
                )
            }
        })
    }
    
    

    جاوا

    
    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. در دسترس بودن موارد زیر را تأیید کنید:

    • گوگل گزینه پرداخت را ارائه داد
    • پیوند وب خارجی

    برای بررسی در دسترس بودن برنامه، تابع isBillingProgramAvailableAsync را فراخوانی کنید و سپس برای نمایش محصولات موجود، تابع queryProductDetailsAsync را فراخوانی کنید. برای مثال:

    کاتلین

    
    // 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.
    }
    
    
    

    جاوا

    
    // ...
    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 را فراخوانی کنید. برای مثال:

    کاتلین

    
    // 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
    
    

    جاوا

    
    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. توکن تراکنش خارجی را از مرحله ۳ به DeveloperBillingOptionParams ارسال کنید.

    برای مثال:

    کاتلین

    
    // 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()
    
    

    جاوا

    
    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. انتخاب نوع صورتحساب توسط کاربر را به صورت زیر مدیریت کنید:

سناریوی ۲ب را مدیریت کنید

توسعه‌دهنده صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین خارج از برنامه مدیریت می‌شود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:

  1. هنگام ساخت یک نمونه BillingClient، تابع enableBillingProgram بدون DeveloperProvidedBillingListener در EnableBillingProgramParams فراخوانی کنید و سپس اتصال را آغاز کنید. برای مثال:

    کاتلین

    
    // 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()
                )
            }
        })
    }
    
    

    جاوا

    
    EnableBillingProgramParams params = EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.BILLING_CHOICE)
            .build();
    
    BillingClient billingClient = BillingClient.newBuilder(context)
            .setListener(purchasesUpdatedListener)
            .enablePendingPurchases()
            .enableBillingProgram(params)
            .build();
    
    
  2. در دسترس بودن موارد زیر را تأیید کنید:

    • گوگل گزینه پرداخت را ارائه داد
    • پیوند وب خارجی

    برای بررسی در دسترس بودن برنامه، تابع isBillingProgramAvailableAsync را فراخوانی کنید و سپس برای نمایش محصولات موجود، تابع queryProductDetailsAsync را فراخوانی کنید. برای مثال:

    کاتلین

    
    // 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.
    }
    
    

    جاوا

    
    // ...
    
    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. برای دریافت بنر Play Billing و اطلاعات وفاداری، متد getBillingChoiceInfoAsync را فراخوانی کنید.

    کاتلین

    
    // 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
    }
    
    

    جاوا

    
    // 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 را فراخوانی کنید. برای مثال:

    کاتلین

    
    // 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
    
    

    جاوا

    
    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 ثبت‌شده در مرحله‌ی ۱ بازگردانده می‌شود.

      کنترل والدین برای کاربران تحت نظارت نمایش داده می‌شود.

    • اگر کاربر روش پرداخت جایگزین شما را انتخاب کرد، launchExternalLink را فراخوانی کنید. برای مثال:

      کاتلین

      
      // 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.
          }
      }
      
      

      جاوا

      
      // 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);
      
      
    • توکن تراکنش خارجی مرحله ۴ را به LaunchExternalLinkParams ارسال کنید. اگر مقدار OK را برگرداند، تراکنش را ادامه دهید و تراکنش را به گوگل پلی گزارش دهید.

      کنترل والدین برای کاربران تحت نظارت نمایش داده می‌شود.

انتخاب صورتحساب در طول جایگزینی اشتراک

برای جایگزینی اشتراک، صفحه انتخاب کاربر نباید نمایش داده شود، زیرا انتخاب کاربر برای خرید اصلی برای ارتقا و تنزل رتبه حفظ می‌شود.

اگر خرید اصلی از طریق Google Play Billing پردازش شده باشد ، باید launchBillingFlow با اطلاعات جایگزین اشتراک استاندارد Google Play Billing فراخوانی کنید.

با این حال، اگر خرید اصلی از طریق یک صورتحساب جایگزین پردازش شده باشد، نحوه رسیدگی به جایگزین‌های اشتراک بسته به سناریوها کمی متفاوت خواهد بود.

جایگزینی اشتراک در سناریوی ۱الف

کاربرانی که درخواست ارتقا یا تنزل رتبه دارند، باید از طریق سیستم پرداخت جایگزین توسعه‌دهنده اقدام کنند و نیازی به طی کردن مجدد مرحله انتخاب کاربر نیست.

برای انجام این کار، وقتی کاربر درخواست ارتقا یا تنزل رتبه می‌دهد، launchBillingFlow فراخوانی کنید. از setOriginalExternalTransactionId درون شیء SubscriptionUpdateParams در پارامترها استفاده کنید تا شناسه تراکنش خارجی برای خرید اصلی ارائه شود. با توجه به اینکه انتخاب کاربر برای خرید اصلی برای ارتقاها و تنزل رتبه‌ها حفظ می‌شود، این صفحه انتخاب کاربر را نمایش نمی‌دهد. فراخوانی launchBillingFlow در این مورد، یک توکن تراکنش خارجی جدید برای تراکنش ایجاد می‌کند که می‌توانید از callback بازیابی کنید.

کاتلین


// 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.

جاوا


// 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.


وقتی ارتقا یا تنزل رتبه کامل شد، باید با استفاده از توکن تراکنش خارجی که از طریق فراخوانی قبلی برای خرید اشتراک جدید به دست آمده است ، یک تراکنش جدید را گزارش دهید .

جایگزینی اشتراک در سناریوی ۱ب

در این سناریو، باید یک توکن تراکنش خارجی جدید ایجاد شود. تنها تفاوت با خرید معمولی این است که در این سناریو، حق انتخاب کاربر حفظ می‌شود و لازم نیست صفحه انتخاب را برای ارتقا یا تنزل رتبه نمایش دهید. با این حال، باید کادر گفتگوی اطلاعات یکبار مصرف و تأیید والدین را نمایش دهید.

برای نمونه کد یکپارچه‌سازی، به مرحله ۴ در سناریو ۱ب مراجعه کنید: توسعه‌دهنده صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین در برنامه شما مدیریت می‌شود .

وقتی ارتقا یا تنزل رتبه کامل شد، باید با استفاده از توکن تراکنش خارجی که از طریق فراخوانی قبلی برای خرید اشتراک جدید به دست آمده است ، یک تراکنش جدید را گزارش دهید .

جایگزینی اشتراک در سناریوی ۲الف

برای اشتراک‌هایی که در ابتدا از طریق وب‌سایت توسعه‌دهنده یا یک برنامه پرداخت پس از انتخاب کاربر خریداری شده‌اند، کاربرانی که درخواست ارتقا یا تنزل دارند باید از طریق وب‌سایت توسعه‌دهنده یا یک برنامه پرداخت و بدون نیاز به گذراندن مجدد مرحله انتخاب کاربر، اقدام کنند.

برای انجام این کار، وقتی کاربر درخواست ارتقا یا تنزل رتبه می‌دهد، launchBillingFlow فراخوانی کنید. به جای مشخص کردن پارامترهای دیگر در زیر شیء SubscriptionUpdateParams ، از setOriginalExternalTransactionId استفاده کنید که شناسه تراکنش خارجی را برای خرید اصلی ارائه می‌دهد. DeveloperBillingOptionParams نیز باید در این فراخوانی ارائه شود. با توجه به اینکه انتخاب کاربر برای خرید اصلی برای ارتقا و تنزل رتبه حفظ می‌شود، این صفحه انتخاب کاربر را نمایش نمی‌دهد. به عنوان مثال:

کاتلین


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()

جاوا


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();


شما همچنین باید یک توکن تراکنش خارجی جدید ایجاد کنید. برای مثال:

کاتلین


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.
        }
    }
)

جاوا


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 را برای راه‌اندازی جریان خرید فراخوانی کنید.

وقتی ارتقا یا تنزل رتبه کامل شد، باید با استفاده از توکن تراکنش خارجی که از طریق فراخوانی قبلی برای خرید اشتراک جدید به دست آمده است ، یک تراکنش جدید را گزارش دهید .

جایگزینی اشتراک در سناریوی ۲ب

مراحل مدیریت جایگزینی اشتراک در این سناریو مشابه مراحل شرح داده شده در جایگزینی اشتراک در سناریو 2A است. تنها تفاوت این است که پس از تولید توکن تراکنش، به جای فراخوانی متد launchBillingFlow ، باید launchExternalLink را برای نمایش کادر محاوره‌ای سلب مسئولیت linkout فراخوانی کنید. در این سناریو، انتخاب کاربر حفظ می‌شود و لازم نیست صفحه انتخاب را برای ارتقا یا تنزل رتبه نمایش دهید.

برای نمونه کد یکپارچه‌سازی، به مرحله ۶ در سناریو ۲ب مراجعه کنید: توسعه‌دهنده صفحه انتخاب را رندر می‌کند و صورتحساب جایگزین در برنامه شما مدیریت می‌شود .

وقتی ارتقا یا تنزل رتبه کامل شد، باید با استفاده از توکن تراکنش خارجی که از طریق فراخوانی قبلی برای خرید اشتراک جدید به دست آمده است ، یک تراکنش جدید را گزارش دهید .