বিলিং পছন্দের জন্য ইন-অ্যাপ ইন্টিগ্রেশন নির্দেশিকা

এই নির্দেশিকায় বর্ণনা করা হয়েছে কীভাবে আপনার অ্যাপকে প্লে বিলিং লাইব্রেরি এপিআই-এর সাথে সংযুক্ত করবেন, যাতে আপনি আপনার ব্যবহারকারীদের বিলিং বেছে নেওয়ার সুযোগ দিতে পারেন।

পিবিএল-এর সাথে একীকরণ

আপনি চারটি সিনারিওতে পিবিএল (PBL)-এর সাথে বিলিং চয়েস ইন্টিগ্রেট করতে পারেন। সিনারিওগুলো ভিন্ন হয়, যা নির্ভর করে কে চয়েস স্ক্রিনটি রেন্ডার করছে এবং পেমেন্ট কোথায় করা হবে তার উপর। নিচের টেবিলে ইন্টিগ্রেশন সিনারিওগুলো তুলে ধরা হলো:

পেমেন্ট কোথায় করা হয়?
অ্যাপের মধ্যে বাহ্যিক ওয়েব লিঙ্ক
আপনি কোন বিলিং পছন্দের স্ক্রিনটি রেন্ডার করতে চান? গুগল প্লে-এর দৃশ্যকল্প ১ক

গুগল পছন্দের স্ক্রিনটি প্রদর্শন করে এবং বিকল্প বিলিংয়ের বিষয়টি আপনার অ্যাপের মধ্যেই পরিচালিত হয়

দৃশ্যকল্প 1B

অ্যাপ ডেভেলপার পছন্দের স্ক্রিনটি রেন্ডার করে এবং বিকল্প বিলিং আপনার অ্যাপের মধ্যেই পরিচালিত হয়

আপনার নিজস্ব (UX নির্দেশিকা অনুসারে) দৃশ্যকল্প 2A

গুগল পছন্দের স্ক্রিনটি প্রদর্শন করে এবং কেনাকাটার জন্য ব্যবহারকারীকে আপনার অ্যাপের বাইরে আপনার নিজস্ব ওয়েবসাইটে লিঙ্ক করা হয়।

দৃশ্যকল্প 2B

অ্যাপ ডেভেলপার পছন্দের স্ক্রিনটি রেন্ডার করে এবং ব্যবহারকারীকে কেনাকাটার জন্য আপনার অ্যাপের বাইরে আপনার নিজস্ব ওয়েবসাইটে লিঙ্ক করা হয়।

নিম্নলিখিত চিত্রটিতে এই প্রতিটি পরিস্থিতির জন্য বিলিং পছন্দের প্রবাহটি বিশদভাবে ব্যাখ্যা করা হয়েছে:

চারটি ইন্টিগ্রেশন সিনারিওর জন্য এপিআই কল এবং ব্যবহারকারীর ইন্টারঅ্যাকশনের ক্রম প্রদর্শনকারী বিলিং পছন্দ প্রবাহ।
চিত্র ১. বিলিং পছন্দের সমন্বয়ের পরিস্থিতি

পিবিএল ইন্টিগ্রেশন সিনারিও

আপনার ইন্টিগ্রেশন পরিস্থিতির উপর নির্ভর করে, আপনার অ্যাপে বিলিংয়ের বিকল্প ব্যবস্থা চালু করতে এই বিভাগের ধাপগুলো অনুসরণ করুন।

দৃশ্যকল্প 1A পরিচালনা করুন

গুগল পছন্দের স্ক্রিনটি প্রদর্শন করে এবং বিকল্প বিলিং আপনার অ্যাপের মধ্যেই পরিচালিত হয় । এই পরিস্থিতিতে বিলিং বিকল্পটি চালু করতে নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

  1. আপনার BillingClient ইনস্ট্যান্স তৈরি করার সময় EnableBillingProgramParams সহ enableBillingProgram কল করুন, এবং তারপরে সংযোগটি শুরু করুন। উদাহরণস্বরূপ:

    কোটলিন

    
    // 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. ব্যবহারকারী 'Buy' বোতামে ক্লিক করলে ক্রয় প্রক্রিয়াটি চালু করতে 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. ব্যবহারকারীর বিলিং ধরণ নির্বাচন নিম্নলিখিতভাবে সম্পন্ন করুন:

    • যদি ব্যবহারকারী প্লে বিলিং নির্বাচন করেন, তাহলে বিলিং ফলাফলটি ধাপ ১-এ নিবন্ধিত PurchasesUpdatedListener এ ফেরত পাঠানো হয়।
    • যদি ব্যবহারকারী আপনার বিকল্প বিলিং নির্বাচন করেন, তাহলে বিলিং ফলাফলটি ধাপ ১-এ নিবন্ধিত DeveloperProvidedBillingListener এ ফেরত পাঠানো হয়। এক্ষেত্রে, ফেরত আসা DeveloperProvidedBillingDetails এ একটি externalTransactionToken থাকে। এই টোকেনটি লেনদেন প্রতিবেদন তৈরির জন্য ব্যবহার করা হবে।

দৃশ্যকল্প 1B পরিচালনা করুন

ডেভেলপার পছন্দের স্ক্রিনটি রেন্ডার করে এবং বিকল্প বিলিং আপনার অ্যাপের মধ্যেই পরিচালিত হয় । এই পরিস্থিতিতে বিলিং পছন্দটি সক্রিয় করতে নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

  1. একটি BillingClient ইনস্ট্যান্স তৈরি করার সময় EnableBillingProgramParamsDeveloperProvidedBillingListener ছাড়া enableBillingProgram কল করুন, এবং তারপর সংযোগটি শুরু করুন। উদাহরণস্বরূপ:

    কোটলিন

    
    // 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. প্লে বিলিং ব্যানার এবং লয়ালটি তথ্য পেতে 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. যখন ব্যবহারকারী 'Buy' বোতামে ক্লিক করেন, তখন একটি তথ্য ডায়ালগ দেখানোর জন্য showBillingProgramInformationDialog কল করুন। উদাহরণস্বরূপ, ব্যবহারকারীদের জন্য তথ্য ডায়ালগ দেখুন। ধাপ ৪ থেকে প্রাপ্ত BillingProgram এবং transactionToken অবশ্যই রিকোয়েস্টে সেট করা থাকতে হবে।

    দ্রষ্টব্য : তত্ত্বাবধানাধীন ব্যবহারকারীদের জন্য অভিভাবকীয় নিয়ন্ত্রণ প্রদর্শিত হয়।

  6. পূর্ববর্তী ধাপের ফলাফল OK হলে, আপনার বিকল্প বিলিং পছন্দের স্ক্রিনটি চালু করুন।

  7. ব্যবহারকারীর বিলিং ধরণ নির্বাচন নিম্নলিখিতভাবে সম্পন্ন করুন:

    • যদি ব্যবহারকারী প্লে বিলিং নির্বাচন করেন, তাহলে সাধারণ প্লে বিলিং নির্দেশিকা অনুসরণ করে launchBillingFlow কল করুন। বিলিং ফলাফলটি ধাপ ১-এ নিবন্ধিত PurchasesUpdatedListener এ ফেরত পাঠানো হয়।
    • যদি ব্যবহারকারী আপনার বিকল্প বিলিং পদ্ধতি নির্বাচন করেন, তবে আপনাকে অবশ্যই লেনদেনটি নিজে সম্পন্ন করতে হবে এবং ধাপ ৪-এ তৈরি করা টোকেন ব্যবহার করে Play-কে তা জানাতে হবে।

দৃশ্যকল্প 2A পরিচালনা করুন

গুগল পছন্দের স্ক্রিনটি প্রদর্শন করে এবং বিকল্প বিলিং আপনার অ্যাপের বাইরে পরিচালিত হয় । এই পরিস্থিতিতে বিলিং বিকল্পটি চালু করতে নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

  1. আপনার BillingClient ইনস্ট্যান্স তৈরি করার সময় EnableBillingProgramParams সহ enableBillingProgram কল করুন, এবং তারপরে সংযোগটি শুরু করুন। উদাহরণস্বরূপ:

    কোটলিন

    
    // 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. ব্যবহারকারী 'Buy' বোতামে ক্লিক করলে ক্রয় প্রক্রিয়াটি চালু করতে 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. ব্যবহারকারীর বিলিং ধরণ নির্বাচন নিম্নলিখিতভাবে সম্পন্ন করুন:

    • যদি ব্যবহারকারী প্লে বিলিং নির্বাচন করেন, তাহলে সাধারণ প্লে বিলিং নির্দেশিকা অনুসরণ করে launchBillingFlow কল করুন। বিলিং ফলাফলটি ধাপ ১-এ নিবন্ধিত PurchasesUpdatedListener এ ফেরত পাঠানো হয়।
    • যদি ব্যবহারকারী আপনার বিকল্প বিলিং নির্বাচন করেন, তাহলে বিলিং ফলাফলটি ধাপে নিবন্ধিত DeveloperProvidedBillingListener এর কাছে ফেরত পাঠানো হয়।
      1. ফেরত আসা DeveloperProvidedBillingDetailsexternalTransactionToken থাকে, যা ধাপ ৪-এ DeveloperBillingOptionParams এ পাঠানো হয়েছিল, যদি সেটি একটি বৈধ টোকেন হয়।

দৃশ্যকল্প 2B পরিচালনা করুন

ডেভেলপার পছন্দের স্ক্রিনটি রেন্ডার করেন এবং বিকল্প বিলিং অ্যাপের বাইরে পরিচালনা করা হয় । এই পরিস্থিতিতে বিলিং পছন্দটি সক্রিয় করতে নিম্নলিখিত ধাপগুলি অনুসরণ করুন:

  1. একটি BillingClient ইনস্ট্যান্স তৈরি করার সময় EnableBillingProgramParamsDeveloperProvidedBillingListener ছাড়া enableBillingProgram কল করুন, এবং তারপর সংযোগটি শুরু করুন। উদাহরণস্বরূপ:

    কোটলিন

    
    // 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. প্লে বিলিং ব্যানার এবং লয়ালটি তথ্য পেতে 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. ব্যবহারকারীর বিলিং ধরণ নির্বাচন নিম্নলিখিতভাবে সম্পন্ন করুন:

    • যদি ব্যবহারকারী প্লে বিলিং নির্বাচন করেন, তাহলে সাধারণ প্লে বিলিং নির্দেশিকা অনুসরণ করে launchBillingFlow কল করুন। বিলিং ফলাফলটি ধাপ ১-এ নিবন্ধিত 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-কে ট্রানজ্যাকশনটি সম্পর্কে রিপোর্ট করুন।

      তত্ত্বাবধানাধীন ব্যবহারকারীদের জন্য অভিভাবকীয় নিয়ন্ত্রণ প্রদর্শিত হয়।

সাবস্ক্রিপশন প্রতিস্থাপনের সময় বিলিং পছন্দ

সাবস্ক্রিপশন প্রতিস্থাপনের ক্ষেত্রে ব্যবহারকারীর পছন্দের স্ক্রিনটি দেখানো উচিত নয়, কারণ মূল ক্রয়ের জন্য করা ব্যবহারকারীর পছন্দ আপগ্রেড এবং ডাউনগ্রেডের জন্য সংরক্ষিত থাকে।

যদি মূল কেনাকাটাটি গুগল প্লে বিলিং-এর মাধ্যমে সম্পন্ন হয়ে থাকে , তাহলে আপনাকে গুগল প্লে বিলিং সাবস্ক্রিপশন প্রতিস্থাপনের সাধারণ তথ্য দিয়ে launchBillingFlow কল করতে হবে।

তবে, যদি মূল ক্রয়টি কোনো বিকল্প বিলিং পদ্ধতির মাধ্যমে সম্পন্ন হয়ে থাকে, তাহলে পরিস্থিতিভেদে সাবস্ক্রিপশন প্রতিস্থাপনের প্রক্রিয়া কিছুটা ভিন্ন হয়।

সিনারিও 1A-তে সাবস্ক্রিপশন প্রতিস্থাপন

যেসব ব্যবহারকারী আপগ্রেড বা ডাউনগ্রেডের অনুরোধ করতে চান, তাদের পুনরায় ইউজার চয়েস প্রক্রিয়ার মধ্য দিয়ে না গিয়ে ডেভেলপারের বিকল্প বিলিং সিস্টেম ব্যবহার করে কাজটি সম্পন্ন করা উচিত।

এটি করার জন্য, যখন ব্যবহারকারী আপগ্রেড বা ডাউনগ্রেডের অনুরোধ করেন, তখন launchBillingFlow কল করুন। মূল ক্রয়ের জন্য এক্সটার্নাল ট্রানজ্যাকশন আইডি প্রদান করতে, প্যারামিটারের মধ্যে থাকা SubscriptionUpdateParams অবজেক্টে setOriginalExternalTransactionId ব্যবহার করুন। এতে ব্যবহারকারীর পছন্দের স্ক্রিনটি প্রদর্শিত হয় না, কারণ মূল ক্রয়ের জন্য ব্যবহারকারীর পছন্দটি আপগ্রেড এবং ডাউনগ্রেডের ক্ষেত্রেও সংরক্ষিত থাকে। এক্ষেত্রে launchBillingFlow এর কলটি ট্রানজ্যাকশনটির জন্য একটি নতুন এক্সটার্নাল ট্রানজ্যাকশন টোকেন তৈরি করে, যা আপনি কলব্যাক থেকে পুনরুদ্ধার করতে পারবেন।

কোটলিন


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


আপগ্রেড বা ডাউনগ্রেড সম্পন্ন হলে, নতুন সাবস্ক্রিপশন কেনার জন্য পূর্ববর্তী কলের মাধ্যমে প্রাপ্ত এক্সটার্নাল ট্রানজ্যাকশন টোকেন ব্যবহার করে আপনাকে একটি নতুন ট্রানজ্যাকশন রিপোর্ট করতে হবে।

সিনারিও 1B-তে সাবস্ক্রিপশন প্রতিস্থাপন

এই পরিস্থিতিতে, একটি নতুন এক্সটার্নাল ট্রানজ্যাকশন টোকেন তৈরি করতে হবে। সাধারণ কেনাকাটার সাথে এর একমাত্র পার্থক্য হলো, এই পরিস্থিতিতে ব্যবহারকারীর পছন্দের স্বাধীনতা সংরক্ষিত থাকে এবং আপগ্রেড বা ডাউনগ্রেডের জন্য পছন্দের স্ক্রিনটি দেখানোর প্রয়োজন হয় না। তবে আপনাকে অবশ্যই এককালীন তথ্য ডায়ালগ এবং অভিভাবকের স্বীকৃতি প্রদর্শন করতে হবে।

নমুনা ইন্টিগ্রেশন কোডের জন্য, সিনারিও 1B-এর ধাপ 4 দেখুন: যেখানে ডেভেলপার পছন্দের স্ক্রিনটি রেন্ডার করে এবং বিকল্প বিলিং আপনার অ্যাপের মধ্যেই পরিচালিত হয়

আপগ্রেড বা ডাউনগ্রেড সম্পন্ন হলে, নতুন সাবস্ক্রিপশন কেনার জন্য পূর্ববর্তী কলের মাধ্যমে প্রাপ্ত এক্সটার্নাল ট্রানজ্যাকশন টোকেন ব্যবহার করে আপনাকে একটি নতুন ট্রানজ্যাকশন রিপোর্ট করতে হবে।

সিনারিও 2A-তে সাবস্ক্রিপশন প্রতিস্থাপন

যেসব সাবস্ক্রিপশন ব্যবহারকারীর পছন্দের পর ডেভেলপারের ওয়েবসাইট বা পেমেন্ট অ্যাপের মাধ্যমে কেনা হয়েছিল, সেগুলোর ক্ষেত্রে আপগ্রেড বা ডাউনগ্রেডের অনুরোধ করতে হলে ব্যবহারকারীদের পুনরায় পছন্দের প্রক্রিয়ার মধ্য দিয়ে না গিয়ে ডেভেলপারের ওয়েবসাইট বা পেমেন্ট অ্যাপের মাধ্যমেই অগ্রসর হতে হবে।

এটি করার জন্য, যখন ব্যবহারকারী আপগ্রেড বা ডাউনগ্রেডের অনুরোধ করেন, তখন 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 মেথডটি কল করতে হবে।

আপগ্রেড বা ডাউনগ্রেড সম্পন্ন হলে, নতুন সাবস্ক্রিপশন কেনার জন্য পূর্ববর্তী কলের মাধ্যমে প্রাপ্ত এক্সটার্নাল ট্রানজ্যাকশন টোকেন ব্যবহার করে আপনাকে একটি নতুন ট্রানজ্যাকশন রিপোর্ট করতে হবে।

সিনারিও 2B-তে সাবস্ক্রিপশন প্রতিস্থাপন

এই সিনারিওতে সাবস্ক্রিপশন প্রতিস্থাপন পরিচালনা করার ধাপগুলো সিনারিও 2A-তে বর্ণিত সাবস্ক্রিপশন প্রতিস্থাপনের ধাপগুলোর মতোই। একমাত্র পার্থক্য হলো, ট্রানজ্যাকশন টোকেন তৈরি করার পর, launchBillingFlow মেথডটি কল করার পরিবর্তে, লিঙ্কআউট ডিসক্লেইমার ডায়ালগটি দেখানোর জন্য আপনাকে অবশ্যই launchExternalLink কল করতে হবে। এই সিনারিওতে, ব্যবহারকারীর পছন্দ সংরক্ষিত থাকে এবং আপনাকে আপগ্রেড বা ডাউনগ্রেডের জন্য পছন্দের স্ক্রিনটি দেখাতে হয় না।

নমুনা ইন্টিগ্রেশন কোডের জন্য, সিনারিও 2B-এর ধাপ 6 দেখুন: ডেভেলপার পছন্দের স্ক্রিনটি রেন্ডার করে এবং বিকল্প বিলিং আপনার অ্যাপের মধ্যেই পরিচালিত হয়

আপগ্রেড বা ডাউনগ্রেড সম্পন্ন হলে, নতুন সাবস্ক্রিপশন কেনার জন্য পূর্ববর্তী কলের মাধ্যমে প্রাপ্ত এক্সটার্নাল ট্রানজ্যাকশন টোকেন ব্যবহার করে আপনাকে একটি নতুন ট্রানজ্যাকশন রিপোর্ট করতে হবে।