این راهنما نحوه ادغام برنامه شما با APIهای کتابخانه پرداخت Play را شرح میدهد تا بتوانید به کاربران خود حق انتخاب در مورد پرداخت را ارائه دهید.
ادغام با PBL
شما میتوانید انتخاب صورتحساب را با PBL در چهار سناریو ادغام کنید. سناریوها بر اساس اینکه چه کسی صفحه انتخاب را نمایش میدهد و پرداخت کجا انجام میشود، متفاوت هستند. جدول زیر سناریوهای ادغام را شرح میدهد:
| پرداخت کجا اتفاق میافتد؟ | |||
| درون برنامهای | پیوند وب خارجی | ||
| کدام صفحه انتخاب صورتحساب را میخواهید رندر کنید؟ | گوگل پلی | سناریوی ۱الف گوگل صفحه انتخاب را رندر میکند و صورتحساب جایگزین در برنامه شما مدیریت میشود . | سناریوی ۱ب توسعهدهندهی برنامه، صفحهی انتخاب را رندر میکند و صورتحساب جایگزین در برنامهی شما مدیریت میشود . |
| خودتان (مطابق با دستورالعملهای UX) | سناریوی ۲الف گوگل صفحه انتخاب را نمایش میدهد و کاربر برای خرید به خارج از برنامه شما به وبسایتهای خودتان لینک میشود. | سناریوی ۲ب توسعهدهندهی اپلیکیشن، صفحهی انتخاب را رندر میکند و کاربر برای خرید ، به وبسایتهای شما در خارج از اپلیکیشن متصل میشود. | |
تصویر زیر جریان انتخاب صورتحساب را برای هر یک از این سناریوها شرح میدهد:


سناریوهای ادغام PBL
بسته به سناریوی ادغام خود، مراحل این بخش را برای پیادهسازی انتخاب صورتحساب در برنامه خود دنبال کنید.
سناریوی ۱A را مدیریت کنید
گوگل صفحه انتخاب را رندر میکند و صورتحساب جایگزین در برنامه شما مدیریت میشود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:
هنگام ساخت نمونهی 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();تأیید کنید که گزینه پرداخت ارائه شده توسط گوگل برای کاربر در دسترس است.
برای بررسی در دسترس بودن برنامه، تابع
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به شما میگوید که آیا صفحه انتخاب صورتحساب رندر شده توسط گوگل یا رندر شده توسط توسعهدهنده در دسترس است یا خیر.برای فعال کردن جریان خرید هنگام کلیک کاربر روی خرید، تابع
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);توجه : کنترل والدین برای کاربران تحت نظارت نمایش داده میشود.
انتخاب نوع صورتحساب توسط کاربر را به صورت زیر مدیریت کنید:
- اگر کاربر گزینهی Play Billing را انتخاب کند، نتیجهی صورتحساب به
PurchasesUpdatedListenerثبتشده در مرحلهی ۱ بازگردانده میشود. - اگر کاربر روش پرداخت جایگزین شما را انتخاب کند، نتیجه پرداخت به
DeveloperProvidedBillingListenerثبت شده در مرحله 1 بازگردانده میشود.DeveloperProvidedBillingDetailsبازگردانده شده در این مورد حاوی یکexternalTransactionTokenاست. این توکن برای گزارش تراکنش استفاده خواهد شد.
- اگر کاربر گزینهی Play Billing را انتخاب کند، نتیجهی صورتحساب به
سناریوی ۱ب را مدیریت کنید
توسعهدهنده صفحه انتخاب را رندر میکند و صورتحساب جایگزین در برنامه شما مدیریت میشود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:
هنگام ساخت یک نمونه
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();تأیید کنید که گزینهی پرداخت ارائه شده توسط توسعهدهنده برای کاربر در دسترس است.
برای بررسی در دسترس بودن برنامه، تابع
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به شما میگوید که آیا صفحه انتخاب صورتحساب رندر شده توسط گوگل یا رندر شده توسط توسعهدهنده در دسترس است یا خیر.برای دریافت بنر 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 } });یک توکن تراکنش خارجی با مقداردهی 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 } } );وقتی کاربر روی خرید کلیک میکند، تابع
showBillingProgramInformationDialogرا فراخوانی کنید تا یک پنجره اطلاعات نمایش داده شود. برای مثال، به پنجره اطلاعات برای کاربران مراجعه کنید. BillingProgram و transactionToken از مرحله ۴ باید در درخواست تنظیم شوند.توجه : کنترل والدین برای کاربران تحت نظارت نمایش داده میشود.
اگر نتیجه مرحله قبل
OKبود، صفحه انتخاب صورتحساب جایگزین خود را اجرا کنید.انتخاب نوع صورتحساب توسط کاربر را به صورت زیر مدیریت کنید:
- اگر کاربر Play Billing را انتخاب کند،
launchBillingFlowطبق راهنمای استاندارد Play Billing فراخوانی کنید. نتیجهی صورتحساب بهPurchasesUpdatedListenerثبتشده در مرحلهی ۱ بازگردانده میشود. - اگر کاربر روش پرداخت جایگزین شما را انتخاب کند، باید خودتان تراکنش را انجام دهید و با استفاده از توکن تولید شده در مرحله ۴، آن را به Play گزارش دهید.
- اگر کاربر Play Billing را انتخاب کند،
سناریوی ۲A را مدیریت کنید
گوگل صفحه انتخاب را رندر میکند و صورتحساب جایگزین خارج از برنامه شما مدیریت میشود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:
هنگام ساخت نمونهی 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();در دسترس بودن موارد زیر را تأیید کنید:
- گوگل گزینه پرداخت را ارائه داد
- پیوند وب خارجی
برای بررسی در دسترس بودن برنامه، تابع
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. } } );برای ایجاد یک توکن تراکنش خارجی، زمانی که کاربر قصد خرید را نشان میدهد، تابع
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. } } );برای فعال کردن جریان خرید هنگام کلیک کاربر روی خرید،
launchBillingFlowفراخوانی کنید. اگر انتخاب صورتحساب برای کاربر در دسترس است، موارد زیر را انجام دهید:- DeveloperBillingOptionParams را به
BillingFlowParamsارسال کنید. - توکن تراکنش خارجی را از مرحله ۳ به
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();توجه : کنترل والدین برای کاربران تحت نظارت نمایش داده میشود.
- DeveloperBillingOptionParams را به
انتخاب نوع صورتحساب توسط کاربر را به صورت زیر مدیریت کنید:
- اگر کاربر Play Billing را انتخاب کند،
launchBillingFlowطبق راهنمای استاندارد Play Billing فراخوانی کنید. نتیجهی صورتحساب بهPurchasesUpdatedListenerثبتشده در مرحلهی ۱ بازگردانده میشود. - اگر کاربر روش پرداخت جایگزین شما را انتخاب کند، نتیجه پرداخت به
DeveloperProvidedBillingListenerثبت شده در مرحله ... برگردانده میشود.-
DeveloperProvidedBillingDetailsبرگردانده شده، شاملexternalTransactionTokenاست که در مرحله ۴ بهDeveloperBillingOptionParamsارسال شده است، البته اگر توکن معتبری باشد.
-
- اگر کاربر Play Billing را انتخاب کند،
سناریوی ۲ب را مدیریت کنید
توسعهدهنده صفحه انتخاب را رندر میکند و صورتحساب جایگزین خارج از برنامه مدیریت میشود . برای فعال کردن انتخاب صورتحساب در این سناریو، مراحل زیر را انجام دهید:
هنگام ساخت یک نمونه 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();در دسترس بودن موارد زیر را تأیید کنید:
- گوگل گزینه پرداخت را ارائه داد
- پیوند وب خارجی
برای بررسی در دسترس بودن برنامه، تابع
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. } } );برای دریافت بنر 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 } });برای ایجاد یک توکن تراکنش خارجی، زمانی که کاربر قصد خرید را نشان میدهد، تابع
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. } } );وقتی کاربر روی خرید کلیک کرد، صفحه انتخاب جایگزین شما نمایش داده میشود.
انتخاب نوع صورتحساب توسط کاربر را به صورت زیر مدیریت کنید:
اگر کاربر 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 فراخوانی کنید. در این سناریو، انتخاب کاربر حفظ میشود و لازم نیست صفحه انتخاب را برای ارتقا یا تنزل رتبه نمایش دهید.
برای نمونه کد یکپارچهسازی، به مرحله ۶ در سناریو ۲ب مراجعه کنید: توسعهدهنده صفحه انتخاب را رندر میکند و صورتحساب جایگزین در برنامه شما مدیریت میشود .
وقتی ارتقا یا تنزل رتبه کامل شد، باید با استفاده از توکن تراکنش خارجی که از طریق فراخوانی قبلی برای خرید اشتراک جدید به دست آمده است ، یک تراکنش جدید را گزارش دهید .