এই ডকুমেন্টটিতে সাবস্ক্রিপশনের জীবনচক্রের বিভিন্ন ঘটনা, যেমন নবায়ন এবং মেয়াদোত্তীর্ণ হওয়া, কীভাবে পরিচালনা করতে হয় তা বর্ণনা করা হয়েছে। এতে সাবস্ক্রিপশনের অতিরিক্ত কিছু বৈশিষ্ট্য, যেমন প্রচারমূলক অফার দেওয়া এবং ব্যবহারকারীদের নিজেদের সাবস্ক্রিপশন পরিচালনা করার সুযোগ দেওয়ার বিষয়েও বর্ণনা করা হয়েছে।
আপনি যদি আপনার অ্যাপের জন্য সাবস্ক্রিপশন প্রোডাক্ট কনফিগার না করে থাকেন, তাহলে আপনার প্রোডাক্ট তৈরি ও কনফিগার করুন (Create and configure your products) দেখুন।
সাবস্ক্রিপশনের সংক্ষিপ্ত বিবরণ
সাবস্ক্রিপশন হলো একটি পুনরাবৃত্তিমূলক লেনদেন যা ব্যবহারকারীদের নির্দিষ্ট অধিকার প্রদান করে। এই অধিকারগুলো হলো এমন কিছু সুবিধার সমষ্টি যা ব্যবহারকারীরা একটি নির্দিষ্ট সময়কালে ব্যবহার করতে পারেন। উদাহরণস্বরূপ, একটি সাবস্ক্রিপশন একজন ব্যবহারকারীকে প্রিমিয়াম অ্যাক্সেসের অধিকার দিতে পারে।
বেস প্ল্যান এবং অফারের মাধ্যমে, আপনি একই সাবস্ক্রিপশন প্রোডাক্টের জন্য একাধিক কনফিগারেশন তৈরি করতে পারেন। উদাহরণস্বরূপ, আপনি সেইসব ব্যবহারকারীদের জন্য একটি পরিচিতিমূলক অফার তৈরি করতে পারেন যারা আপনার অ্যাপে আগে কখনও সাবস্ক্রাইব করেননি। একইভাবে, আপনি সেইসব ব্যবহারকারীদের জন্য একটি আপগ্রেড অফার তৈরি করতে পারেন যারা ইতিমধ্যেই সাবস্ক্রাইব করেছেন।
সাবস্ক্রিপশন প্রোডাক্ট, বেস প্ল্যান এবং অফারগুলির বিস্তারিত বিবরণের জন্য, প্লে কনসোল হেল্প সেন্টারের ডকুমেন্টেশন দেখুন।
প্লে বিলিং লাইব্রেরি নিম্নলিখিত সাবস্ক্রিপশন প্রকারগুলি সমর্থন করে:
সাবস্ক্রিপশন - এই প্রকারে, একটি অধিকারের জন্য একটি আইটেম থাকে। উদাহরণস্বরূপ, একটি মিউজিক স্ট্রিমিং সার্ভিসের সাবস্ক্রিপশন।
অ্যাড-অন সহ সাবস্ক্রিপশন - এই ধরনের ক্ষেত্রে, একটিমাত্র ক্রয়ের মধ্যেই বেশ কয়েকটি স্বতন্ত্র সুবিধা একসাথে পাওয়া যেতে পারে। উদাহরণস্বরূপ, মিউজিক স্ট্রিমিং পরিষেবা এবং একটি ভিডিও সাবস্ক্রিপশন উভয়েরই সাবস্ক্রিপশন। অ্যাড-অন সহ সাবস্ক্রিপশন সম্পর্কে নির্দিষ্ট তথ্যের জন্য, ‘অ্যাড-অন সহ সাবস্ক্রিপশন’ দেখুন।
প্রিপেইড প্ল্যান ইন্টিগ্রেশন
প্রিপেইড প্ল্যানগুলোর মেয়াদ শেষ হয়ে গেলে সেগুলো স্বয়ংক্রিয়ভাবে নবায়ন হয় না । সাবস্ক্রিপশনের মেয়াদ নিরবচ্ছিন্নভাবে বাড়ানোর জন্য, ব্যবহারকারীকে অবশ্যই একই সাবস্ক্রিপশনের জন্য একটি প্রিপেইড প্ল্যান টপ-আপ করতে হবে।
টপ-আপের জন্য, মূল ক্রয়ের মতোই বিলিং প্রক্রিয়াটি চালু করুন। কোনো ক্রয় যে একটি টপ-আপ, তা উল্লেখ করার প্রয়োজন নেই।
প্রিপেইড প্ল্যান টপ-আপ করার সময় সর্বদা CHARGE_FULL_PRICE রিপ্লেসমেন্ট মোড ব্যবহার করা হয় এবং আপনাকে এই মোডটি আলাদাভাবে সেট করতে হয় না। ব্যবহারকারীর কাছ থেকে তাৎক্ষণিকভাবে সম্পূর্ণ বিলিং পিরিয়ডের জন্য চার্জ করা হয় এবং টপ-আপে উল্লেখিত সময়কাল পর্যন্ত তার প্রাপ্যতার মেয়াদ বৃদ্ধি পায়।
টপ-আপ করার পরে, সর্বশেষ টপ-আপ ক্রয়টি প্রতিফলিত করার জন্য Purchase রেজাল্ট অবজেক্টের নিম্নলিখিত ফিল্ডগুলি আপডেট করা হয়:
- অর্ডার আইডি
- ক্রয়ের সময়
- স্বাক্ষর
- টোকেন কিনুন
- স্বীকৃত
নিম্নলিখিত Purchase ক্ষেত্রগুলিতে সর্বদা মূল ক্রয়ে থাকা একই ডেটা থাকে:
- প্যাকেজের নাম
- ক্রয় অবস্থা
- পণ্য
- স্বয়ংক্রিয়ভাবে নবায়ন
প্রিপেইড ক্রয়ের স্বীকৃতি
স্বয়ংক্রিয়ভাবে নবায়নযোগ্য সাবস্ক্রিপশনের মতোই, প্রিপেইড প্ল্যান কেনার পর আপনাকে তা নিশ্চিত করতে হবে। প্রাথমিক ক্রয় এবং যেকোনো টপ-আপ, উভয়ই নিশ্চিত করতে হবে। আরও তথ্যের জন্য, ‘ক্রয় প্রক্রিয়াকরণ’ দেখুন।
প্রিপেইড প্ল্যানের মেয়াদ কম হওয়ার সম্ভাবনার কারণে, যত দ্রুত সম্ভব ক্রয়টি নিশ্চিত করা জরুরি।
এক সপ্তাহ বা তার বেশি মেয়াদের প্রিপেইড প্ল্যানগুলো তিন দিনের মধ্যে নিশ্চিত করতে হবে।
এক সপ্তাহের কম মেয়াদের প্রিপেইড প্ল্যানগুলো অবশ্যই প্ল্যানের মেয়াদের অর্ধেক সময়ের মধ্যে নিশ্চিত করতে হবে। উদাহরণস্বরূপ, ডেভেলপারদের একটি তিন দিনের প্রিপেইড প্ল্যান নিশ্চিত করার জন্য দেড় দিন সময় দেওয়া হয়।
কিস্তি সাবস্ক্রিপশন ইন্টিগ্রেশন
কিস্তিভিত্তিক সাবস্ক্রিপশন হলো এমন এক ধরনের সাবস্ক্রিপশন, যেখানে ব্যবহারকারীরা পুরো সাবস্ক্রিপশন ফি একবারে পরিশোধ না করে, একটি নির্দিষ্ট সময় ধরে একাধিক কিস্তিতে এর মূল্য পরিশোধ করেন।
কিস্তিতে সাবস্ক্রিপশনের ক্ষেত্রে অতিরিক্ত বিবেচ্য বিষয়সমূহ:
- দেশভিত্তিক প্রাপ্যতা : কিস্তিতে সাবস্ক্রিপশনের সুবিধাটি শুধুমাত্র ব্রাজিল, ফ্রান্স, ইতালি এবং স্পেনে উপলব্ধ (সর্বশেষ প্রাপ্যতা জানতে কনসোল দেখুন)।
- মূল্য নির্ধারণ : কনসোলে কোনো কিস্তিভিত্তিক সাবস্ক্রিপশনের মূল্য নির্ধারণ করার সময়, এই মূল্যটি মাসিক পরিশোধের পরিমাণকে বোঝায়। এটি, নির্ধারিত প্রতিশ্রুতির মেয়াদের সাথে মিলিত হয়ে, ক্রয় স্ক্রিনে সাবস্ক্রিপশনটির মোট পরিমাণ তৈরি করে।
- প্রতিশ্রুতিকাল : প্রাথমিক সাবস্ক্রিপশনের মোট সময়কাল, যে সময়ে মাসিক পেমেন্ট করতে হয়। উদাহরণস্বরূপ, যদি কোনো বেস প্ল্যানের প্রতিশ্রুতিকাল ১৫ মাস হয়, তবে ব্যবহারকারীকে এই সময়ের মধ্যে ১৫টি মাসিক পেমেন্ট করতে হবে।
- নবায়ন : কিস্তিভিত্তিক সাবস্ক্রিপশনের ক্ষেত্রে, "নবায়ন" বলতে একটি প্রতিশ্রুতি মেয়াদের সমাপ্তি বোঝায়, যা প্রাথমিক বা পরবর্তী প্রতিশ্রুতি মেয়াদ হতে পারে। প্রাথমিক সাইন আপের পর, সম্পূর্ণ প্রাথমিক প্রতিশ্রুতি মেয়াদ শেষ হলে প্রথম নবায়নটি হয়। পরবর্তী প্রতিটি প্রতিশ্রুতি মেয়াদ পূর্ণ হওয়ার পর পরবর্তী নবায়নগুলো হয়। কিস্তিভিত্তিক সাবস্ক্রিপশনের জন্য নবায়নের ধরণগুলো হতে পারে "মাসিক স্বয়ংক্রিয় নবায়ন" অথবা "একই মেয়াদের জন্য স্বয়ংক্রিয় নবায়ন"। "মাসিক স্বয়ংক্রিয় নবায়ন"-এর ক্ষেত্রে, কোনো পরবর্তী প্রতিশ্রুতি থাকে না এবং প্ল্যানটি একটি মাসিক সাবস্ক্রিপশনের মতো কাজ করে, যেখানে প্রতিটি মাসিক সাবস্ক্রিপশন চার্জ একটি নবায়ন হিসেবে গণ্য হয়।
- বিলিং পিরিয়ড : কিস্তি সাবস্ক্রিপশনের ক্ষেত্রে, এটি বেস প্ল্যানে উল্লেখিত পৃথক পেমেন্ট করার পুনরাবৃত্ত বিরতিকে বোঝায়।
- প্ল্যান পরিবর্তন বনাম মূল্য পরিবর্তনের আচরণ : মূল্য পরিবর্তন এবং বাতিলের ক্ষেত্রে, প্রতিশ্রুতিটি অটল থাকে। এর মানে হলো, যদি কোনো ব্যবহারকারী বাতিল করতে চান বা কোনো ডেভেলপার মূল্য পরিবর্তন করতে চান, তবে সেই পরিবর্তনটি একটি প্রতিশ্রুতি মেয়াদের শেষে কার্যকর হয়। প্ল্যান পরিবর্তনের ক্ষেত্রে, প্রতিশ্রুতিটি অটল থাকে না। এর মানে হলো, প্ল্যান পরিবর্তনের জন্য প্রতিশ্রুতি মেয়াদের শেষ পর্যন্ত অপেক্ষা করতে হয় না; এটি নির্ধারিত প্রতিস্থাপন পদ্ধতির উপর ভিত্তি করে হয় অবিলম্বে অথবা পরবর্তী পেমেন্টের তারিখে কার্যকর হয়।
- একই সাবস্ক্রিপশনের প্ল্যান পরিবর্তন : একই সাবস্ক্রিপশন প্রোডাক্টের কিস্তিভিত্তিক প্ল্যান থেকে কিস্তিবিহীন প্ল্যানে পরিবর্তন করার অনুমতি নেই।
রিয়েল-টাইম ডেভেলপার নোটিফিকেশন (RTDN) : প্রতিশ্রুতি মেয়াদের জন্য পেমেন্ট বাকি থাকলে, ব্যবহারকারীর উদ্যোগে বাতিল করার সাথে সাথেই একটি
SUBSCRIPTION_CANCELLATION_SCHEDULEDRTDN পাঠানো হয়। বাতিলকরণটি প্রক্রিয়াধীন থাকে এবং এটি শুধুমাত্র প্রতিশ্রুতি মেয়াদের শেষে কার্যকর হবে। এরপর, যদি ব্যবহারকারী এটি পুনরুদ্ধার না করেন, তাহলে প্রতিশ্রুতি মেয়াদের শেষেSUBSCRIPTION_CANCELEDএবংSUBSCRIPTION_EXPIREDRTDN পাঠানো হয়।অর্থ প্রদান / রাজস্ব আদায় : ব্যবহারকারীরা তাদের মাসিক পেমেন্ট করার সাথে সাথে ডেভেলপারদের অর্থ প্রদান করা হবে, যা অন্যান্য সমস্ত সাবস্ক্রিপশনের মতোই একই শর্তাবলী সাপেক্ষে। ব্যবহারকারী যখন কিস্তিভিত্তিক সাবস্ক্রিপশনের জন্য সাইন আপ করেন, তখন ডেভেলপারদের অগ্রিম কোনো অর্থ প্রদান করা হয় না।
বকেয়া পেমেন্ট সংগ্রহ : যদি কোনো ব্যবহারকারী সাবস্ক্রিপশনের কোনো কিস্তির পেমেন্ট করতে ব্যর্থ হন, তবে Google বা ডেভেলপার কেউই ব্যবহারকারীর কাছ থেকে সেই বকেয়া বা অপরিশোধিত পেমেন্ট আদায়ের চেষ্টা করবে না। তবে, Google তার স্বাভাবিক পেমেন্ট পুনরায় চেষ্টার পদ্ধতি অনুসারে, প্রযোজ্য গ্রেস পিরিয়ড বা অ্যাকাউন্ট হোল্ড পিরিয়ডের সময় পর্যায়ক্রমে পেমেন্টটি পুনরায় চেষ্টা করতে পারে। কোনো অবশিষ্ট অপরিশোধিত কিস্তির পেমেন্টের জন্য Google, ডেভেলপারের কাছে দায়ী থাকবে না।
প্লে বিলিং লাইব্রেরির প্রাপ্যতা :
installmentDetailsফিল্ডটি শুধুমাত্র PBL 7 বা তার পরবর্তী সংস্করণের জন্য উপলব্ধ। PBL 5 এবং তার পরবর্তী সংস্করণের জন্য,queryProductDetails()ব্যবহার করে ইনস্টলমেন্ট সাবস্ক্রিপশনটি ফেরত দেওয়া হয়, কিন্তু সেই সাবস্ক্রিপশনে প্ল্যানটির প্রতিশ্রুতিবদ্ধ পেমেন্টের সংখ্যার মতো বিস্তারিত ইনস্টলমেন্ট তথ্য অন্তর্ভুক্ত থাকে না।
ব্যবহারকারীদের সাবস্ক্রিপশন পরিচালনা করার সুযোগ দিতে ডিপ লিঙ্ক ব্যবহার করুন।
আপনার অ্যাপের সেটিংস বা প্রেফারেন্স স্ক্রিনে একটি লিঙ্ক থাকা উচিত, যার মাধ্যমে ব্যবহারকারীরা তাদের সাবস্ক্রিপশনগুলো পরিচালনা করতে পারবেন এবং আপনি এটিকে আপনার অ্যাপের স্বাভাবিক রূপ ও অনুভূতির সাথে একীভূত করতে পারেন।
আপনি আপনার অ্যাপ থেকে গুগল প্লে সাবস্ক্রিপশন সেন্টারে সেইসব সাবস্ক্রিপশনের জন্য একটি ডিপ লিঙ্ক অন্তর্ভুক্ত করতে পারেন, যেগুলোর মেয়াদ এখনো শেষ হয়নি। এই সাবস্ক্রিপশনগুলো আপনি সাবস্ক্রিপশন রিসোর্সের subscriptionState ফিল্ড ব্যবহার করে নির্ধারণ করতে পারেন। এর উপর ভিত্তি করে, প্লে স্টোর সাবস্ক্রিপশন সেন্টারে ডিপ লিঙ্ক করার বিভিন্ন উপায় রয়েছে।
সাবস্ক্রিপশন সেন্টারের লিঙ্ক
ব্যবহারকারীদের তাদের সমস্ত সাবস্ক্রিপশন দেখার পৃষ্ঠায় নিয়ে যেতে নিম্নলিখিত URL-টি ব্যবহার করুন, যেমনটি চিত্র ১ এবং ২-এ দেখানো হয়েছে:
https://play.google.com/store/account/subscriptions


এই ডিপ লিঙ্কটি কোনো ব্যবহারকারীকে প্লে স্টোর সাবস্ক্রিপশন সেন্টার থেকে বাতিল করা সাবস্ক্রিপশন পুনরুদ্ধার করতে সাহায্য করতে পারে।
একটি নির্দিষ্ট সাবস্ক্রিপশন ব্যবস্থাপনা পৃষ্ঠার লিঙ্ক (প্রস্তাবিত)
মেয়াদোত্তীর্ণ নয় এমন কোনো সাবস্ক্রিপশনের ম্যানেজমেন্ট পেজে সরাসরি লিঙ্ক করতে, ক্রয়কৃত সাবস্ক্রিপশনটির সাথে যুক্ত প্যাকেজের নাম এবং productId উল্লেখ করুন। কোনো বিদ্যমান সাবস্ক্রিপশনের productId প্রোগ্রাম্যাটিকভাবে নির্ধারণ করতে, আপনার অ্যাপের ব্যাকএন্ডে কোয়েরি করুন অথবা কোনো নির্দিষ্ট ব্যবহারকারীর সাথে যুক্ত সাবস্ক্রিপশনগুলোর তালিকা পেতে BillingClient.queryPurchasesAsync() কল করুন। প্রতিটি সাবস্ক্রিপশনে তার স্ট্যাটাস তথ্যের অংশ হিসেবে সংশ্লিষ্ট productId থাকে। একটি সাবস্ক্রিপশন ক্রয়ের সাথে যুক্ত প্রতিটি SubscriptionPurchaseLineItem অবজেক্টে সেই লাইন আইটেমে ব্যবহারকারীর কেনা সাবস্ক্রিপশনটির সাথে সম্পর্কিত productId ভ্যালুটি থাকে।
ব্যবহারকারীদের একটি নির্দিষ্ট সাবস্ক্রিপশন ম্যানেজমেন্ট স্ক্রিনে নিয়ে যেতে নিম্নলিখিত URL-টি ব্যবহার করুন, যেখানে 'your-sub-product-id' এবং 'your-app-package'-এর জায়গায় যথাক্রমে productId এবং app package name বসান:
https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package
এরপর ব্যবহারকারী তার পেমেন্ট পদ্ধতিগুলো পরিচালনা করতে এবং বাতিলকরণ, পুনঃসাবস্ক্রিপশন ও বিরতিসহ বিভিন্ন ফিচার ব্যবহার করতে পারেন।
ব্যবহারকারীদের তাদের সাবস্ক্রিপশন আপগ্রেড, ডাউনগ্রেড বা পরিবর্তন করার অনুমতি দিন।
আপনি বিদ্যমান গ্রাহকদের চাহিদা আরও ভালোভাবে মেটানোর জন্য তাদের সাবস্ক্রিপশন প্ল্যান পরিবর্তন করার বিভিন্ন বিকল্প প্রদান করতে পারেন:
- আপনি যদি 'বেসিক' এবং 'প্রিমিয়াম' সাবস্ক্রিপশনের মতো একাধিক সাবস্ক্রিপশন স্তর বিক্রি করেন, তাহলে আপনি ব্যবহারকারীদের অন্য কোনো সাবস্ক্রিপশনের বেস প্ল্যান বা অফার কেনার মাধ্যমে স্তর পরিবর্তন করার সুযোগ দিতে পারেন।
- আপনি ব্যবহারকারীদের তাদের বর্তমান বিলিং সময়কাল পরিবর্তন করার অনুমতি দিতে পারেন, যেমন মাসিক প্ল্যান থেকে বার্ষিক প্ল্যানে পরিবর্তন করা।
- আপনি ব্যবহারকারীদের স্বয়ংক্রিয়ভাবে নবায়নযোগ্য এবং প্রিপেইড প্ল্যানের মধ্যে পরিবর্তন করার সুযোগও দিতে পারেন।
যোগ্য ব্যবহারকারীদের ছাড় দেওয়ার জন্য সাবস্ক্রিপশন অফার প্রদানের মাধ্যমে আপনি এই পরিবর্তনগুলোকে উৎসাহিত করতে পারেন। উদাহরণস্বরূপ, আপনি মাসিক প্ল্যান থেকে বার্ষিক প্ল্যানে পরিবর্তন করার ক্ষেত্রে প্রথম বছরে ৫০% ছাড়ের একটি অফার তৈরি করতে পারেন এবং এই অফারটি শুধুমাত্র সেইসব মাসিক প্ল্যানের গ্রাহকদের জন্য সীমাবদ্ধ রাখতে পারেন যারা এই অফারটি কেনেননি। অফারের যোগ্যতার মানদণ্ড সম্পর্কে আরও তথ্য হেল্প সেন্টারে পাওয়া যাবে।
চিত্র ৩-এ তিনটি ভিন্ন প্ল্যানসহ একটি নমুনা অ্যাপ দেখানো হয়েছে:

আপনার অ্যাপটি চিত্র ৩-এর মতো একটি স্ক্রিন দেখাতে পারে, যেখানে ব্যবহারকারীরা তাদের সাবস্ক্রিপশন পরিবর্তন করার বিকল্প পাবেন। সব ক্ষেত্রেই, ব্যবহারকারীদের কাছে এটা স্পষ্ট থাকা উচিত যে তাদের বর্তমান সাবস্ক্রিপশন প্ল্যানটি কী এবং এটি পরিবর্তন করার জন্য তাদের কাছে কী কী বিকল্প রয়েছে।
যখন ব্যবহারকারীরা তাদের সাবস্ক্রিপশন আপগ্রেড, ডাউনগ্রেড বা পরিবর্তন করার সিদ্ধান্ত নেন, তখন আপনি একটি প্রতিস্থাপন মোড নির্দিষ্ট করে দেন, যা নির্ধারণ করে যে বর্তমান পরিশোধিত বিলিং মেয়াদের আনুপাতিক মূল্য কীভাবে প্রয়োগ করা হবে এবং কখন প্রাপ্যতার কোনো পরিবর্তন ঘটবে।
প্রতিস্থাপন মোড
নিম্নলিখিত সারণিতে উপলব্ধ প্রতিস্থাপন মোড ও তার উদাহরণমূলক ব্যবহার এবং পরিশোধিত বলে বিবেচিত অর্থপ্রদানের সংখ্যা তালিকাভুক্ত করা হয়েছে।
প্রতিস্থাপন মোড | বর্ণনা | উদাহরণ ব্যবহার | প্রতিশ্রুতিবদ্ধ অর্থপ্রদান পরিশোধিত হিসাবে নথিভুক্ত করা হয়েছে (কিস্তি সাবস্ক্রিপশন প্রতিস্থাপনের জন্য) |
| সাবস্ক্রিপশন আইটেমটি তাৎক্ষণিকভাবে আপগ্রেড বা ডাউনগ্রেড করা হয়। মূল্যের পার্থক্যের উপর ভিত্তি করে অবশিষ্ট সময় সমন্বয় করা হয় এবং পরবর্তী বিলিং তারিখ এগিয়ে দিয়ে তা নতুন সাবস্ক্রিপশনের সাথে সমন্বয় করা হয়। এটিই ডিফল্ট আচরণ। | কোনো তাৎক্ষণিক অতিরিক্ত অর্থ প্রদান ছাড়াই আরও ব্যয়বহুল স্তরে আপগ্রেড করুন। | ০ |
| সাবস্ক্রিপশনটি তাৎক্ষণিকভাবে আপগ্রেড করা হয় এবং বিলিং চক্র অপরিবর্তিত থাকে। এরপর অবশিষ্ট মেয়াদের জন্য মূল্যের পার্থক্যটুকু ব্যবহারকারীর কাছ থেকে চার্জ করা হয়। দ্রষ্টব্য: এই বিকল্পটি শুধুমাত্র সাবস্ক্রিপশন আইটেম আপগ্রেডের ক্ষেত্রে উপলব্ধ, যেখানে প্রতি ইউনিট সময়ের মূল্য বৃদ্ধি পায়। | বিলিং তারিখ পরিবর্তন না করে আরও ব্যয়বহুল স্তরে আপগ্রেড করুন। | ১ |
| সাবস্ক্রিপশনটি তাৎক্ষণিকভাবে আপগ্রেড বা ডাউনগ্রেড করা হয় এবং নতুন সুবিধার জন্য ব্যবহারকারীর কাছ থেকে সাথে সাথেই সম্পূর্ণ মূল্য চার্জ করা হয়। পূর্ববর্তী সাবস্ক্রিপশনের অবশিষ্ট মূল্য একই সুবিধার জন্য স্থানান্তরিত হয়, অথবা ভিন্ন সুবিধায় পরিবর্তন করার সময় সময়ের অনুপাতে সমন্বয় করা হয়। দ্রষ্টব্য: নতুন সাবস্ক্রিপশনে যদি কোনো ফ্রি ট্রায়াল বা পরিচিতিমূলক অফার থাকে, তাহলে আপগ্রেড বা ডাউনগ্রেড করার সময় ব্যবহারকারীকে $0 অথবা পরিচিতিমূলক অফারের মূল্য, এই দুটির মধ্যে যেটি প্রযোজ্য, সেটি চার্জ করা হবে। | স্বল্প মেয়াদী বিলিং থেকে দীর্ঘ মেয়াদী বিলিং-এ আপগ্রেড করুন। | ১ (দ্রষ্টব্য: নতুন সাবস্ক্রিপশনে ফ্রি ট্রায়াল থাকলে ০।) |
| সাবস্ক্রিপশনটি তাৎক্ষণিকভাবে আপগ্রেড বা ডাউনগ্রেড করা হয় এবং সাবস্ক্রিপশন নবায়নের সময় নতুন মূল্য ধার্য করা হয়। বিলিং চক্র একই থাকে। | অবশিষ্ট বিনামূল্যের সময়কাল বজায় রেখে উচ্চতর সাবস্ক্রিপশন স্তরে আপগ্রেড করুন। | ০ |
| সাবস্ক্রিপশন আইটেমটি শুধুমাত্র সাবস্ক্রিপশন নবায়নের সময়ই আপগ্রেড বা ডাউনগ্রেড করা হয়, কিন্তু নতুন ক্রয়ের সাথে নিম্নলিখিত দুটি আইটেম অবিলম্বে প্রদান করা হয়:
দ্রষ্টব্য: কিস্তিভিত্তিক সাবস্ক্রিপশনের ক্ষেত্রে, পরবর্তী পেমেন্টের তারিখের শুরু থেকে প্ল্যান পরিবর্তনটি কার্যকর হবে। | কম ব্যয়বহুল স্তরে অবনমিত করুন। | ১ |
| প্রতিস্থাপিত সংস্করণেও সাবস্ক্রিপশন আইটেমটির অর্থ পরিশোধের সময়সূচী অপরিবর্তিত থাকবে। | যখন কোনো নির্দিষ্ট আইটেম অপরিবর্তিত রাখা প্রয়োজন, তখন অ্যাড-অন সহ একটি সাবস্ক্রিপশন থেকে সেই আইটেমটি যোগ বা অপসারণ করুন। | প্রযোজ্য নয় |
আপগ্রেড বা ডাউনগ্রেড অফারের বিভিন্ন আপসেল এবং উইনব্যাক অ্যাপ্লিকেশন সম্পর্কে আরও জানতে, অফার ও প্রমোশন গাইডটি পড়ুন।
ক্রয়ের জন্য প্রতিস্থাপন মোড সেট করুন
আপনার পছন্দ এবং ব্যবসায়িক যুক্তির উপর ভিত্তি করে, আপনি বিভিন্ন ধরণের সাবস্ক্রিপশন পরিবর্তনের জন্য ভিন্ন ভিন্ন রিপ্লেসমেন্ট মোড ব্যবহার করতে পারেন। এই বিভাগে একটি সাবস্ক্রিপশন পরিবর্তনের জন্য কীভাবে রিপ্লেসমেন্ট মোড সেট করতে হয় এবং এর সাথে প্রযোজ্য সীমাবদ্ধতাগুলো ব্যাখ্যা করা হয়েছে।
একই সাবস্ক্রিপশনের মধ্যে পুনরায় সাবস্ক্রাইব করুন বা প্ল্যান পরিবর্তন করুন।
আপনি গুগল প্লে কনসোলে একটি ডিফল্ট রিপ্লেসমেন্ট মোড নির্দিষ্ট করতে পারেন। এই সেটিংটি আপনাকে বেছে নিতে দেয় যে, বর্তমান গ্রাহকরা যদি একই সাবস্ক্রিপশনের জন্য একটি ভিন্ন বেস প্ল্যান বা অফার কেনেন অথবা বাতিল করার পর পুনরায় সাবস্ক্রাইব করেন, তাহলে কখন তাদের থেকে চার্জ করা হবে। উপলব্ধ অপশনগুলো হলো: অবিলম্বে চার্জ করুন (Charge immediately ), যা CHARGE_FULL_PRICE এর সমতুল্য, এবং পরবর্তী বিলিং তারিখে চার্জ করুন (Charge at the next billing date) , যা WITHOUT_PRORATION এর সমতুল্য। একই সাবস্ক্রিপশনের মধ্যে বেস প্ল্যান পরিবর্তন করার ক্ষেত্রে এই দুটিই একমাত্র প্রাসঙ্গিক রিপ্লেসমেন্ট মোড।
উদাহরণস্বরূপ, যদি ব্যবহারকারী সাবস্ক্রিপশন বাতিল করার পর কিন্তু তার মেয়াদ শেষ হওয়ার আগে আপনি একই প্ল্যানের জন্য একটি উইনব্যাক অফার চালু করেন, তাহলে আপনি SubscriptionUpdateParams এ কোনো মান উল্লেখ না করেই নতুন ক্রয়টিকে একটি সাধারণ ক্রয় হিসাবে প্রক্রিয়া করতে পারেন। সিস্টেমটি সাবস্ক্রিপশনে আপনার কনফিগার করা ডিফল্ট রিপ্লেসমেন্ট মোড ব্যবহার করে এবং স্বয়ংক্রিয়ভাবে পুরানো ক্রয় থেকে নতুন ক্রয়ে প্ল্যান পরিবর্তনটি পরিচালনা করে।
সাবস্ক্রিপশন জুড়ে প্ল্যান পরিবর্তন করুন, অথবা ডিফল্ট প্রতিস্থাপন মোড ওভাররাইড করুন।
যদি ব্যবহারকারী সাবস্ক্রিপশন প্রোডাক্ট পরিবর্তন করেন—যেমন ভিন্ন কোনো সাবস্ক্রিপশন কেনেন —অথবা যদি আপনি কোনো কারণে ডিফল্ট রিপ্লেসমেন্ট মোডকে ওভাররাইড করতে চান, তাহলে আপনাকে পারচেজ ফ্লো প্যারামিটারের অংশ হিসেবে রানটাইমে প্রোরেশন রেট নির্দিষ্ট করে দিতে হবে।
আপনার রানটাইম পারচেজ ফ্লো কনফিগারেশনের অংশ হিসেবে SubscriptionProductReplacementParams বা SubscriptionUpdateParams এ ReplacementMode সঠিকভাবে প্রদান করতে, নিম্নলিখিত সীমাবদ্ধতাগুলো লক্ষ্য করুন:
- প্রিপেইড প্ল্যান, অটো-রিনিউয়িং প্ল্যান বা ইনস্টলমেন্ট প্ল্যান থেকে কোনো প্রিপেইড প্ল্যানে আপগ্রেড, ডাউনগ্রেড বা একই সাবস্ক্রিপশনে সুইচ করার সময়, একমাত্র অনুমোদিত রিপ্লেসমেন্ট মোড হলো
CHARGE_FULL_PRICE। আপনি অন্য কোনো রিপ্লেসমেন্ট মোড নির্দিষ্ট করলে, ক্রয়টি ব্যর্থ হবে এবং ব্যবহারকারীকে একটি ত্রুটি দেখানো হবে। - একই সাবস্ক্রিপশনের মধ্যে প্রিপেইড প্ল্যান থেকে অটো-রিনিউয়িং প্ল্যানে পরিবর্তন করার সময়, বৈধ প্রোরেশন মোডগুলো হলো
CHARGE_FULL_PRICEএবংWITHOUT_PRORATION। আপনি যদি অন্য কোনো প্রোরেশন মোড নির্দিষ্ট করেন, তাহলে ক্রয়টি ব্যর্থ হয় এবং ব্যবহারকারীকে একটি ত্রুটি দেখানো হয়। - একই সাবস্ক্রিপশন প্রোডাক্টের মধ্যে কিস্তিভিত্তিক প্ল্যান থেকে কিস্তিবিহীন প্ল্যানে পরিবর্তন করার অনুমতি নেই।
- প্রতিস্থাপনের সময় কোনো আইটেমের পেমেন্ট অপরিবর্তিত রাখতে
SubscriptionProductReplacementParamsএKEEP_EXISTINGরিপ্লেসমেন্ট মোড ব্যবহার করার ক্ষেত্রে, পুরোনো প্রোডাক্ট আইডি এবং নতুন প্রোডাক্টের প্রোডাক্ট আইডি একই হতে হবে।SubscriptionUpdateParamsএKEEP_EXISTINGমোড সমর্থিত নয়।
প্রতিস্থাপনের উদাহরণ এবং আচরণ
প্রতিটি প্রোরেশন মোড কীভাবে কাজ করে তা বোঝার জন্য, নিম্নলিখিত পরিস্থিতিটি বিবেচনা করুন:
স্যামওয়াইজের কান্ট্রি গার্ডেনার অ্যাপের অনলাইন কন্টেন্টের একটি সাবস্ক্রিপশন রয়েছে। তিনি কন্টেন্টের টিয়ার ১ সংস্করণের জন্য একটি মাসিক সাবস্ক্রিপশন নিয়েছেন, যা শুধুমাত্র টেক্সট-ভিত্তিক। এই সাবস্ক্রিপশনের জন্য তাকে প্রতি মাসে ২ ডলার খরচ করতে হয় এবং এটি মাসের প্রথম তারিখে নবায়ন হয়।
১৫ই এপ্রিল, স্যামওয়াইজ টিয়ার ২ সাবস্ক্রিপশনের বার্ষিক সংস্করণে আপগ্রেড করার সিদ্ধান্ত নেন, যেটিতে ভিডিও আপডেট অন্তর্ভুক্ত এবং যার খরচ বছরে ৩৬ ডলার ।
সাবস্ক্রিপশন আপগ্রেড করার সময়, ডেভেলপার একটি প্রোরেশন মোড নির্বাচন করেন। নিম্নলিখিত তালিকাটি বর্ণনা করে যে প্রতিটি প্রোরেশন মোড কীভাবে Samwise-এর সাবস্ক্রিপশনকে প্রভাবিত করে:
WITH_TIME_PRORATION
স্যামওয়াইজের টিয়ার ১ সাবস্ক্রিপশনটি অবিলম্বে শেষ হয়ে যাচ্ছে। যেহেতু সে পুরো এক মাসের (এপ্রিল ১-৩০) জন্য অর্থ প্রদান করেছিল কিন্তু সাবস্ক্রিপশনের মেয়াদের মাঝপথে আপগ্রেড করেছিল, তাই এক মাসের সাবস্ক্রিপশনের অর্ধেক ($১) তার নতুন সাবস্ক্রিপশনে যোগ করা হয়েছে। তবে, যেহেতু সেই নতুন সাবস্ক্রিপশনটির খরচ বছরে $৩৬, তাই $১ ক্রেডিট ব্যালেন্স দিয়ে মাত্র ১০ দিনের (এপ্রিল ১৬-২৫) বিল পরিশোধ করা যায়; ফলে ২৬শে এপ্রিল তার কাছ থেকে নতুন সাবস্ক্রিপশনের জন্য $৩৬ এবং পরবর্তী প্রতি বছরের ২৬শে এপ্রিল আরও $৩৬ চার্জ করা হবে।
ক্রয় সফল হওয়ার সাথে সাথেই আপনার অ্যাপের PurchasesUpdatedListener কল করা উচিত এবং আপনি একটি queryPurchasesAsync() কলের অংশ হিসেবে নতুন ক্রয়টি গ্রহণ করতে পারবেন। আপনার ব্যাকএন্ড সাথে সাথেই একটি SUBSCRIPTION_PURCHASED রিয়েল টাইম ডেভেলপার নোটিফিকেশন পাবে।
CHARGE_PRORATED_PRICE
এই মোডটি ব্যবহার করা যেতে পারে কারণ টিয়ার ২ সাবস্ক্রিপশনের প্রতি একক সময়ের মূল্য ($৩৬/বছর = $৩/মাস) টিয়ার ১ সাবস্ক্রিপশনের প্রতি একক সময়ের মূল্যের ($২/মাস) চেয়ে বেশি। স্যামওয়াইজের টিয়ার ১ সাবস্ক্রিপশনটি অবিলম্বে শেষ হয়ে যায়। যেহেতু সে পুরো এক মাসের জন্য অর্থ প্রদান করেছে কিন্তু তার অর্ধেক ব্যবহার করেছে, তাই এক মাসের সাবস্ক্রিপশনের অর্ধেক ($১) তার নতুন সাবস্ক্রিপশনে যোগ করা হয়। তবে, যেহেতু সেই নতুন সাবস্ক্রিপশনের খরচ $৩৬/বছর, তাই বাকি ১৫ দিনের খরচ $১.৫০; ফলে তার নতুন সাবস্ক্রিপশনের জন্য $০.৫০-এর পার্থক্যটুকু চার্জ করা হয়। ১লা মে, স্যামওয়াইজের নতুন সাবস্ক্রিপশন টিয়ারের জন্য $৩৬ চার্জ করা হয় এবং এর পরের প্রতি বছরের ১লা মে আরও $৩৬ চার্জ করা হয়।
ক্রয় সফল হওয়ার সাথে সাথেই আপনার অ্যাপের PurchasesUpdatedListener কল করা উচিত এবং আপনি একটি queryPurchasesAsync() কলের অংশ হিসেবে নতুন ক্রয়টি গ্রহণ করতে পারবেন। আপনার ব্যাকএন্ড সাথে সাথেই একটি SUBSCRIPTION_PURCHASED রিয়েল টাইম ডেভেলপার নোটিফিকেশন পাবে।
WITHOUT_PRORATION
স্যামওয়াইজের টিয়ার ১ সাবস্ক্রিপশনটি কোনো অতিরিক্ত চার্জ ছাড়াই তাৎক্ষণিকভাবে টিয়ার ২- তে আপগ্রেড করা হয় এবং প্রতি বছরের ১লা মে তার নতুন সাবস্ক্রিপশন টিয়ারের জন্য ৩৬ ডলার ও পরবর্তী প্রতি বছর ১লা মে আরও ৩৬ ডলার চার্জ করা হয়।
ক্রয় সফল হওয়ার সাথে সাথেই আপনার অ্যাপের PurchasesUpdatedListener কল করা উচিত এবং আপনি একটি queryPurchasesAsync() কলের অংশ হিসেবে নতুন ক্রয়টি গ্রহণ করতে পারবেন। আপনার ব্যাকএন্ড সাথে সাথেই একটি SUBSCRIPTION_PURCHASED রিয়েল টাইম ডেভেলপার নোটিফিকেশন পাবে।
DEFERRED
স্যামওয়াইজের টিয়ার ১ সাবস্ক্রিপশনটি ৩০শে এপ্রিল মেয়াদ শেষ হওয়া পর্যন্ত চালু থাকবে। ১লা মে থেকে টিয়ার ২ সাবস্ক্রিপশনটি কার্যকর হবে এবং স্যামওয়াইজের নতুন সাবস্ক্রিপশন টিয়ারের জন্য তার কাছ থেকে ৩৬ ডলার চার্জ করা হবে।
ক্রয় সফল হওয়ার সাথে সাথেই আপনার অ্যাপের PurchasesUpdatedListener কল করা উচিত, এবং আপনি একটি queryPurchasesAsync() কলের অংশ হিসাবে নতুন ক্রয়টি পুনরুদ্ধার করতে পারবেন। আপনার ব্যাকএন্ড অবিলম্বে একটি SUBSCRIPTION_PURCHASED রিয়েল টাইম ডেভেলপার নোটিফিকেশন (RTDN) পাবে। সেই মুহূর্তে, আপনি অন্য যেকোনো নতুন ক্রয়ের মতোই এটি প্রক্রিয়া করবেন। বিশেষ করে, নতুন ক্রয়টি স্বীকার (acknowledge) করা নিশ্চিত করুন। মনে রাখবেন যে নতুন সাবস্ক্রিপশনের startTime তখনই পূরণ করা হয় যখন প্রতিস্থাপনটি কার্যকর হয়, যা পুরানো সাবস্ক্রিপশনের মেয়াদ শেষ হওয়ার সাথে সাথে ঘটে। সেই মুহূর্তে, আপনি নতুন সাবস্ক্রিপশন প্ল্যানের জন্য একটি SUBSCRIPTION_RENEWED RTDN পাবেন। Handle deferred replacement অংশে ReplacementMode.DEFERRED আচরণ সম্পর্কে আরও পড়ুন।
CHARGE_FULL_PRICE
স্যামওয়াইজের টিয়ার ১ সাবস্ক্রিপশন অবিলম্বে শেষ হয়ে যাচ্ছে। তার টিয়ার ২ সাবস্ক্রিপশন আজ থেকে শুরু হচ্ছে এবং তার থেকে ৩৬ ডলার চার্জ করা হয়েছে। যেহেতু সে পুরো এক মাসের জন্য অর্থ প্রদান করেছে কিন্তু এর অর্ধেক ব্যবহার করেছে, তাই এক মাসের সাবস্ক্রিপশনের অর্ধেক (১ ডলার) তার নতুন সাবস্ক্রিপশনে যোগ করা হয়েছে। যেহেতু সেই নতুন সাবস্ক্রিপশনের খরচ বছরে ৩৬ ডলার, তাই তার সাবস্ক্রিপশনের মেয়াদের সাথে বছরের ১/৩৬ অংশ (প্রায় ১০ দিন) যোগ হবে। সুতরাং, স্যামওয়াইজের পরবর্তী চার্জ হবে আজ থেকে ১ বছর এবং ১০ দিন পর ৩৬ ডলার। এরপর থেকে প্রতি বছর তার থেকে ৩৬ ডলার চার্জ করা হবে।
প্রোরেশন মোড বেছে নেওয়ার সময়, আমাদের প্রতিস্থাপন সংক্রান্ত সুপারিশগুলো পর্যালোচনা করতে ভুলবেন না।
KEEP_EXISTING
স্যামওয়াইজের কান্ট্রি গার্ডেনার অ্যাপের অনলাইন কন্টেন্টের একটি সাবস্ক্রিপশন রয়েছে। বেসিক কন্টেন্টের জন্য তার প্ল্যান ১-এর একটি মাসিক সাবস্ক্রিপশন আছে। এই সাবস্ক্রিপশনের প্রারম্ভিক মূল্য ৩ মাসের জন্য প্রতি মাসে ২ ডলার এবং তারপর প্রতি মাসে ৪ ডলার। স্যামওয়াইজ এটি ১লা এপ্রিল কিনেছিলেন। কান্ট্রি গার্ডেনার অ্যাপ প্রতি মাসে ৩ ডলারের বিনিময়ে অ্যাড-অন স্পেশালিটি কন্টেন্ট হিসেবে প্ল্যান ২ অফার করে। ১৫ই এপ্রিল, স্যামওয়াইজ তার বিদ্যমান প্ল্যান ১ চালু রেখেই কান্ট্রি গার্ডেনার অ্যাপের সাবস্ক্রিপশনে প্ল্যান ২ যোগ করেন। স্যামওয়াইজের পেমেন্টের সময়সূচী নিম্নরূপ:
- প্ল্যান ২-এর জন্য আনুপাতিক মূল্য ১.৫০ ডলার, যা ১৫ই এপ্রিলের মধ্যে পরিশোধ করতে হবে।
- পরবর্তী ২ মাসের জন্য প্রতি মাসে $৫.০০ মূল্যে প্ল্যান ১-এর প্রারম্ভিক মূল্য এবং প্ল্যান ২-এর নিয়মিত মূল্য উভয়ই অন্তর্ভুক্ত।
- এরপর, প্রতি মাসে নিয়মিতভাবে ৭.০০ ডলার পরিশোধ করতে হবে।
অ্যাপের মধ্যে সাবস্ক্রিপশন পরিবর্তন শুরু করুন
আপনার অ্যাপ একটি ক্রয় প্রক্রিয়া চালু করার মতোই একই ধাপগুলো অনুসরণ করে ব্যবহারকারীদের আপগ্রেড বা ডাউনগ্রেড করার সুযোগ দিতে পারে। তবে, আপগ্রেড বা ডাউনগ্রেড করার সময়, আপনাকে বর্তমান সাবস্ক্রিপশন, ভবিষ্যৎ (আপগ্রেড বা ডাউনগ্রেড করা) সাবস্ক্রিপশন এবং ব্যবহারের জন্য প্রতিস্থাপন মোডের বিবরণ প্রদান করতে হবে।
প্রতিস্থাপনের জন্য SubscriptionProductReplacementParams ব্যবহার করুন (পছন্দনীয়)।
নিম্নলিখিত উদাহরণে দেখানো হয়েছে কিভাবে SubscriptionProductReplacementParams ব্যবহার করে একটি সাবস্ক্রিপশন আপডেট করতে হয়।
BillingFlowParams.ProductDetailsParamsঅবজেক্টটিতে এখনsetSubscriptionProductReplacementParams()নামে একটি মেথড রয়েছে, যার মাধ্যমে প্রোডাক্ট লেভেলের রিপ্লেসমেন্ট তথ্য নির্দিষ্ট করা যায়।SubscriptionProductReplacementParamsদুটি সেটার মেথড আছে:-
setOldProductId:এটি হলো পুরোনো পণ্য, যা বর্তমানProductDetails. -
setReplacementMode:এটি হলো আইটেম লেভেল রিপ্লেসমেন্ট মোড। মোডগুলো মূলতSubscriptionUpdateParamsমতোই, তবে ভ্যালু ম্যাপিং আপডেট করা হয়েছে।
-
বিদ্যমান পারচেজ লেভেল আপডেট প্যারামিটার
BillingFlowParams.setSubscriptionUpdateParams()অবশ্যইsetOldPurchaseToken()দিয়ে তৈরি করতে হবে।ProductDetailsParamsযেকোনোটির জন্য একবারsetSubscriptionProductReplacementParams()কল করা হলে,SubscriptionUpdateParams.setSubscriptionReplacementMode()আর কোনো প্রভাব ফেলবে না।
নিম্নলিখিত কোড নমুনাটি দেখায় কিভাবে একটি সাবস্ক্রিপশন প্ল্যান ( old_product_1 , old_product_2 ) থেকে ( product_1 , product_2 , product_3 )-এ পরিবর্তন করতে হয়। এই ক্ষেত্রে, product_1 , old_product_1 প্রতিস্থাপন করে, product_2 , old_product_2 প্রতিস্থাপন করে, এবং product_3 অবিলম্বে সাবস্ক্রিপশনে যুক্ত হয়।
কোটলিন
val billingClient: BillingClient = ... val replacementModeForBasePlan: Int = ... val replacementModeForAddon: Int = ... val purchaseTokenOfExistingSubscription: String = "your_old_purchase_token" // ProductDetails instances obtained from queryProductDetailsAsync(); val productDetailsParams1 = ProductDetailsParams.newBuilder() .setProductDetails(productDetails1_obj) // Required: Set the ProductDetails object .setSubscriptionProductReplacementParams( SubscriptionProductReplacementParams.newBuilder() .setOldProductId("old_product_id_1") .setReplacementMode(replacementModeForBasePlan) .build() ) .build() val productDetailsParams2 = ProductDetailsParams.newBuilder() .setProductDetails(productDetails2_obj) // Required: Set the ProductDetails object .setSubscriptionProductReplacementParams( SubscriptionProductReplacementParams.newBuilder() .setOldProductId("old_product_id_2") .setReplacementMode(replacementModeForAddon) .build() ) .build() // Example for a third item without replacement params val productDetailsParams3 = ProductDetailsParams.newBuilder() .setProductDetails(productDetails3_obj) // Required: Set the ProductDetails object .build() val newProductDetailsList = listOf( productDetailsParams1, productDetailsParams2, productDetailsParams3 ) val billingFlowParams = BillingFlowParams.newBuilder() .setSubscriptionUpdateParams( SubscriptionUpdateParams.newBuilder() .setOldPurchaseToken(purchaseTokenOfExistingSubscription) .build() ) .setProductDetailsParamsList(newProductDetailsList) .build() // To launch the billing flow: // billingClient.launchBillingFlow(activity, billingFlowParams)
জাভা
BillingClient billingClient = …; int replacementModeForBasePlan =…; int replacementModeForAddon =…; // ProductDetails obtained from queryProductDetailsAsync(). ProductDetailsParams productDetails1 = ProductDetailsParams.newBuilder() .setSubscriptionProductReplacementParams( SubscriptionProductReplacementParams.newBuilder() .setOldProductId("old_product_id_1") .setReplacementMode(replacementModeForBasePlan)) .build(); ProductDetailsParams productDetails2 = ProductDetailsParams.newBuilder() .setSubscriptionProductReplacementParams( SubscriptionProductReplacementParams.newBuilder() .setOldProductId("old_product_id_2") .setReplacementMode(replacementModeForAddon)) .build(); ProductDetailsParams productDetails3 = ...; ArrayListnewProductDetailsList = new ArrayList<>(); newProductDetailsList.add(productDetails1); newProductDetailsList.add(productDetails2); newProductDetailsList.add(productDetails3); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setSubscriptionUpdateParams( SubscriptionUpdateParams.newBuilder() .setOldPurchaseToken(purchaseTokenOfExistingSubscription) .build()) .setProductDetailsParamsList(productDetailsList) .build(); billingClient.launchBillingFlow(billingFlowParams);
প্রতিস্থাপনের জন্য সাবস্ক্রিপশনআপডেটপ্যারামস সেট করুন (অপ্রচলিত)
নিম্নলিখিত উদাহরণে দেখানো হয়েছে কিভাবে SubscriptionUpdateParams ব্যবহার করে একটি সাবস্ক্রিপশন আপডেট করতে হয়।
কোটলিন
val offerToken = productDetails .getSubscriptionOfferDetails(selectedOfferIndex) .getOfferToken() val billingParams = BillingFlowParams.newBuilder().setProductDetailsParamsList( listOf( BillingFlowParams.ProductDetailsParams.newBuilder() .setProductDetails(productDetails) .setOfferToken(offerToken) .build() ) ).setSubscriptionUpdateParams( BillingFlowParams.SubscriptionUpdateParams.newBuilder() .setOldPurchaseToken("old_purchase_token") .setSubscriptionReplacementMode( BillingFlowParams.ReplacementMode.CHARGE_FULL_PRICE ) .build() ).build() billingClient.launchBillingFlow( activity, billingParams ) // ...
জাভা
String offerToken = productDetails .getSubscriptionOfferDetails(selectedOfferIndex) .getOfferToken(); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList( ImmuableList.of( ProductDetailsParams.newBuilder() // fetched via queryProductDetailsAsync .setProductDetails(productDetails) // offerToken can be found in // ProductDetails=>SubscriptionOfferDetails .setOfferToken(offerToken) .build())) .setSubscriptionUpdateParams( SubscriptionUpdateParams.newBuilder() // purchaseToken can be found in Purchase#getPurchaseToken .setOldPurchaseToken("old_purchase_token") .setSubscriptionReplacementMode(ReplacementMode.CHARGE_FULL_PRICE) .build()) .build(); BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams); // ...
প্রতিস্থাপন সুপারিশ
নিম্নলিখিত সারণিতে বিভিন্ন আনুপাতিক বন্টন পরিস্থিতি এবং প্রতিটি পরিস্থিতির জন্য আমাদের সুপারিশ দেখানো হয়েছে:
| দৃশ্যকল্প | প্রস্তাবিত প্রতিস্থাপন মোড | ফলাফল |
|---|---|---|
| আরও ব্যয়বহুল স্তরে আপগ্রেড করা | CHARGE_PRORATED_PRICE | ব্যবহারকারী একই বিলিং সময়কাল বজায় রেখে অবিলম্বে অ্যাক্সেস পেয়ে যান। |
| কম ব্যয়বহুল স্তরে অবনমন | DEFERRED | ব্যবহারকারী যেহেতু আরও ব্যয়বহুল টায়ারটির জন্য ইতিমধ্যেই অর্থ পরিশোধ করেছেন, তাই পরবর্তী বিলিং তারিখ পর্যন্ত তাঁর অ্যাক্সেস বজায় থাকবে। |
| ফ্রি ট্রায়াল চলাকালীন আপগ্রেড করা, ট্রায়ালটি চালু রাখা | WITHOUT_PRORATION | ব্যবহারকারী ট্রায়াল পিরিয়ডের বাকি সময়ের জন্য কোনো অতিরিক্ত চার্জ ছাড়াই উচ্চতর টায়ারে আপগ্রেড করতে পারবেন। |
| ফ্রি ট্রায়াল চলাকালীন আপগ্রেড করলে ফ্রি ট্রায়ালের অ্যাক্সেস বন্ধ হয়ে যাবে। | CHARGE_PRORATED_PRICE | ব্যবহারকারী অবিলম্বে নতুন টায়ারে অ্যাক্সেস পান এবং ফ্রি ট্রায়ালের অবশিষ্ট মেয়াদ স্থানান্তরিত হয়। এই স্থানান্তরিত মেয়াদ বেস প্ল্যানের মূল্যের উপর ভিত্তি করে গণনা করা হয়। |
| 'সাবস্ক্রিপশন উইথ অ্যাড-অনস' থেকে অন্যান্য সাবস্ক্রিপশন আইটেম যোগ বা অপসারণ করার সময় কিছু সাবস্ক্রিপশন আইটেমের পেমেন্টের সময়সূচী অপরিবর্তিত রাখা। | KEEP_EXISTING | ব্যবহারকারী অপরিবর্তিত আইটেমটির জন্য পুরোনো দামই দিতে থাকেন। নতুন আইটেমগুলো সঙ্গে সঙ্গে যুক্ত হয়ে যায়। একটি প্রতিস্থাপন মোড নির্দিষ্ট করে অন্যান্য পুরোনো আইটেম প্রতিস্থাপন করা যায় অথবা সরিয়ে ফেলা যায়। |
সাবস্ক্রিপশন পরিবর্তনের কেনাকাটা পরিচালনা করুন
প্ল্যান পরিবর্তন সর্বতোভাবে নতুন ক্রয় হিসেবে গণ্য হয় এবং বিলিং প্রক্রিয়া সফলভাবে সম্পন্ন হওয়ার পর সেভাবেই তা প্রক্রিয়া ও স্বীকৃতি প্রদান করতে হবে। নতুন ক্রয়টি যথাযথভাবে প্রক্রিয়া করার পাশাপাশি, যে ক্রয়টি প্রতিস্থাপন করা হচ্ছে, সেটিও বাতিল করতে হবে।
অ্যাপের ভেতরের আচরণ যেকোনো নতুন কেনাকাটার মতোই। আপনার অ্যাপ PurchasesUpdatedListener এ নতুন কেনাকাটার ফলাফল গ্রহণ করে এবং queryPurchasesAsync এ নতুন কেনাকাটাটি উপলব্ধ হয়।
যখন কোনো নতুন ক্রয় একটি বিদ্যমান ক্রয়কে প্রতিস্থাপন করে, তখন Google Play Developer API সাবস্ক্রিপশন রিসোর্সে একটি linkedPurchaseToken ফেরত দেয়। আইটেম স্তরের প্রতিস্থাপনের বিবরণ বোঝার জন্য আপনি নতুন ক্রয়ের SubscriptionPurchaseLineItem অধীনে itemReplacement পরীক্ষা করতে পারেন। এছাড়াও, কাস্টমাইজড ব্যবহারকারী অভিজ্ঞতা প্রদানের জন্য, আপনি নতুন সাবস্ক্রিপশনের বর্তমান অফার পর্যায় (যেমন প্রোরেশন পিরিয়ড বা ফ্রি ট্রায়াল) শনাক্ত করতে offerPhase ফিল্ডটি ব্যবহার করতে পারেন। linkedPurchaseToken এ প্রদত্ত টোকেনটি অবশ্যই বাতিল করুন, যাতে পুরানো টোকেনটি আপনার পরিষেবাগুলিতে অ্যাক্সেস পেতে ব্যবহার করা না হয়। আপগ্রেড এবং ডাউনগ্রেড ক্রয় পরিচালনার তথ্যের জন্য Upgrades, downgrades, and resignups দেখুন।
যখন আপনি নতুন পারচেজ টোকেনটি পাবেন, তখন একটি নতুন পারচেজ টোকেন ভেরিফাই করার মতোই একই ভেরিফিকেশন প্রক্রিয়া অনুসরণ করুন। Google Play বিলিং লাইব্রেরি থেকে BillingClient.acknowledgePurchase() অথবা Google Play ডেভেলপার API থেকে Purchases.subscriptions:acknowledge ব্যবহার করে এই পারচেজগুলো অ্যাকনলেজ করতে ভুলবেন না।
বিলম্বিত প্রতিস্থাপন পরিচালনা করুন
বিলম্বিত প্রতিস্থাপন মোড একজন ব্যবহারকারীকে নতুন প্ল্যান শুরু করার আগে তার পুরানো প্ল্যানের অবশিষ্ট সুবিধাটুকু ব্যবহার করার সুযোগ দেয়।
যখন আপনি নতুন কোনো ক্রয়ের জন্য ReplacementMode.DEFERRED ব্যবহার করেন, তখন ক্রয় প্রক্রিয়া শেষে queryPurchasesAsync() একটি নতুন ক্রয় টোকেন ফেরত দেয়। এই টোকেনটি পরবর্তী নবায়নের তারিখে বিলম্বিত প্রতিস্থাপন সম্পন্ন না হওয়া পর্যন্ত পুরোনো পণ্যটির সাথে যুক্ত থাকে, যার পরে নতুন পণ্যটি ফেরত পাঠানো হয়।
অতীতে আপনি অপ্রচলিত ProrationMode.DEFERRED ব্যবহার করে এই ইউজার এক্সপেরিয়েন্সটি পেতে পারতেন, কিন্তু Play Billing Library 6-এর সাথে ProrationMode.DEFERRED অপ্রচলিত হয়ে গেছে। আচরণটি কোথায় ভিন্ন তা বোঝার জন্য নিচের সারণিটি দেখুন:
সময় | ProrationMode.DEFERRED (অপ্রচলিত) | প্রতিস্থাপন মোড স্থগিত |
ক্রয় প্রক্রিয়া সফল হওয়ার ঠিক পরেই (অ্যাপ) | ক্রয়ের পরে আপগ্রেড বা ডাউনগ্রেড সফল হয়েছে কিনা, সেই স্ট্যাটাস সহ পরবর্তী নবায়নের তারিখ পর্যন্ত পুরোনো প্ল্যানের অধিকার অব্যাহত থাকে। অ্যাপটি যাতে সঠিক অধিকার প্রদান করে, তা নিশ্চিত করার জন্য, প্রতিস্থাপন না হওয়া পর্যন্ত নতুন ক্রয় টোকেনটি এখনও প্রকাশিত হয়নি, তাই এই মুহূর্তে এটি প্রক্রিয়া করা সম্ভব নয়। | ক্রয়ের পরে আপগ্রেড বা ডাউনগ্রেড সফল হয়েছে কিনা, সেই স্ট্যাটাস সহ নতুন ক্রয় টোকেনটি প্রকাশিত হয়েছে, তাই প্রতিস্থাপনটি কখন সম্পন্ন হবে তা বিবেচনায় রেখে এই পর্যায়ে এটি প্রক্রিয়া করা উচিত। |
ক্রয় প্রক্রিয়া সফল হওয়ার ঠিক পরেই (ব্যাকএন্ডে) | ক্রয় প্রক্রিয়া সম্পন্ন হওয়ার পর SUBSCRIPTION_PURCHASED RTDN পাঠানো হয় না । ব্যাকএন্ডকে এখনও নতুন ক্রয়টি সম্পর্কে জানানো হয়নি। | নতুন পারচেজ টোকেনের জন্য পারচেজ ফ্লো শেষ হওয়ার সাথে সাথেই পুরনো product_id সহ SUBSCRIPTION_PURCHASED RTDN পাঠানো হয়। নতুন পারচেজ টোকেন দিয়ে purchases.subscriptionsv2.get মেথডটি কল করলে একটি পারচেজ রিটার্ন হয়, যার 'startTime' পারচেজের সময় নির্দেশ করে এবং এতে দুটি লাইন আইটেম থাকে:
পুরানো ক্রয় টোকেনের জন্য SUBSCRIPTION_EXPIRED পাঠানো হয়েছে। পুরানো ক্রয় টোকেন দিয়ে purchases.subscriptionsv2.get পদ্ধতিটি কল করলে, এটি মেয়াদোত্তীর্ণ হিসাবে প্রদর্শিত হয় (পুরানো প্ল্যানের এনটাইটেলমেন্ট অবশিষ্ট সময়ের জন্য নতুন ক্রয়ে স্থানান্তরিত হয়)। |
প্রতিস্থাপনের ক্ষেত্রে - ক্রয় প্রক্রিয়া (অ্যাপ) সম্পন্ন হওয়ার পর প্রথম নবায়ন | নতুন ক্রয় টোকেনটি এখন প্রকাশিত হয়েছে, তাই এটি প্রক্রিয়া করা উচিত। | ক্রয় প্রক্রিয়াটি সফল হলেই নতুন ক্রয়টি ইতিমধ্যে সম্পন্ন হয়ে যাওয়ার কথা, তাই সঠিক অধিকার নিশ্চিত করা ছাড়া অ্যাপটির অন্য কোনো বিশেষ পদক্ষেপ নেওয়ার কথা নয়। |
প্রতিস্থাপনের সময় - ক্রয় প্রক্রিয়ার (ব্যাকএন্ড) পরে প্রথম নবায়ন | প্রথম SUBSCRIPTION_RENEWED RTDN পাঠানোর পরেই নতুন ক্রয়টি প্রক্রিয়া করা এবং তার স্বীকৃতি দেওয়া যাবে। সাবস্ক্রিপশন রিসোর্সে থাকা | যখন নতুন ক্রয় টোকেনের জন্য SUBSCRIPTION_PURCHASED RTDN পাঠানো হয় এবং 'startTime' হিসাবে রেকর্ড করা হয়, তখন নতুন ক্রয়টি প্রক্রিয়া করা হয়েছে এবং তার স্বীকৃতি দেওয়া হয়েছে। ReplacementMode.DEFERRED চালু থাকলে, প্রথম নবায়নগুলো অন্য যেকোনো নবায়নের মতোই সাধারণ আচরণ অনুসরণ করে এবং এই ইভেন্টটি ঘটলে প্রতিস্থাপনের জন্য আপনাকে কোনো বিশেষ লজিক পরিচালনা করতে হয় না। নতুন পারচেজ টোকেন দিয়ে purchases.subscriptionsv2.get মেথডটি কল করলে দুটি লাইন আইটেম সহ একটি পারচেজ রিটার্ন হয়:
|
ReplacementMode.DEFERRED should be used from now on instead of the deprecated ProrationMode.DEFERRED, as it presents the same behavior regarding entitlement changes, but offers a way to manage the purchase that is more consistent with behaviors for other new purchases.
Customer management
Using Real-time developer notifications, you can detect in real time when a user decides to cancel. When a user cancels, but before their subscription has expired, you can send them push notifications or in-app messages to ask them to resubscribe.
After a user has cancelled their subscription, you can try to win them back either in your app, or through the Play store. The following table describes various subscription scenarios along with associated winback actions and app requirements.
| Before subscription expiration | After subscription expiration | |||
| In-app | In Play Store | In-app | In Play Store | |
| Winback feature | In-app subscription | পুনরুদ্ধার করুন | In-app subscription | Resubscribe |
| User goes through checkout flow | হ্যাঁ | না | হ্যাঁ | হ্যাঁ |
| User subscription remains associated with the same SKU | User can sign up for same or different SKU | হ্যাঁ | User can sign up for same or different SKU | হ্যাঁ |
| Creates new purchase token | হ্যাঁ | না | হ্যাঁ | হ্যাঁ |
| Enabled by default | না | Yes, support required for all devs | না | Apps without Billing Library 2.0+: No Apps with Billing Library 2.0+: Yes. Devs can opt-out in Console. |
| When user is charged | If using same SKU: end of current billing period. If using different SKU: depends on proration mode. | End of current billing period | অবিলম্বে | অবিলম্বে |
| Implementation required | Provide a re-signup UI in your app | Detect change in subscription state Deep-link to Play Store | Provide a re-signup UI in your app | Handle out-of-app purchases |
Before subscription expiration - in-app
For subscriptions that have been canceled but have not yet expired, you can allow subscribers to restore their subscription within your app by applying the same in-app product purchase flow as for new subscribers. Ensure your UI reflects that the user has an existing subscription. For example, you might want to display the user's current expiration date and recurring price with a Reactivate button.
Most of the time, you will want to offer the user the same price and SKU they were already subscribed to, as follows:
- Initiate a new subscription purchase with the same SKU.
- The new subscription replaces the old one and renews on the same expiration date. The old subscription is immediately marked as expired.
- As an example, Achilles has a subscription to Example Music App, and the subscription is due to expire on August 1. On July 10, he resubscribes to the one-month subscription at the same price per month. The new subscription is prorated with the remaining credit, is immediately active, and still renews on August 1.
If you would like to offer a different price—for example a new free trial or a winback discount—you can instead offer a different SKU to the user:
- Initiate an upgrade or downgrade with the different SKU using the replacement mode
WITHOUT_PRORATION. - The new subscription replaces the old one and renews on the same expiration date. The user is charged the price of the new SKU, including any introductory prices, on the original expiration date. If the old subscription was created using an obfuscated account ID, that same ID should be passed to the
BillingFlowParamsfor upgrades and downgrades. - As an example, Achilles has a subscription to Example Music App, and the subscription is due to expire on August 1. On July 10, he resubscribes to an annual subscription with an introductory price. The new subscription is immediately active, and the user is charged the introductory price on August 1.
- If you decide to include a free trial or intro price in your winback SKU, ensure that the user is eligible by unchecking the Allow one free trial per app box in the Google Play Console, which restricts the user to getting one free trial per app.
When you receive the purchase token, process the purchase just as you would with a new subscription. Additionally, the Google Play Developer API returns a linkedPurchaseToken in the subscription resource. Be sure to invalidate the token provided in the linkedPurchaseToken to ensure that the old token is not used to gain access to your services.
Before subscription expiration - in Play Store
While the subscription is canceled but still active, users can restore the subscription in the Google Play subscriptions center by clicking Resubscribe (previously Restore ). This keeps the same subscription and purchase token.

For more information on restoring subscriptions, see Restorations .
After subscription expiration - in-app
You can allow expired subscribers to resubscribe within your app by applying the same in-app product purchase flow as for new subscribers. Note the following:
- To offer users a discount, you might want to offer a product ID with special pricing for your subscription, also called a winback SKU . You can provide the offer in your app, or you can notify the user of the offer outside of the app, such as in email.
- To start a winback subscription, launch the purchase flow in your Android app using the Google Play Billing Library. This is the same process as with a new subscription, but you can determine the SKU that is available to the user.
- If you decide to include a free trial or intro price in your winback SKU, ensure that the user is eligible by unchecking the Allow one free trial per app box in the Google Play Console, which restricts the user to getting one free trial per app.
- If the user resubscribes to the same SKU, they are no longer eligible for free trials or introductory price. Ensure that your UI reflects this.
When you receive the purchase token, process the purchase just as you would with a new subscription. You won't receive a linkedPurchaseToken in the subscription resource.
After subscription expiration - in Play Store
If enabled, users can resubscribe to the same SKU for up to one year after expiration by clicking Resubscribe in the Google Play subscriptions center. This generates a new subscription and purchase token.

Re-subscribing is considered an out-of-app purchase, so be sure to follow best practices for properly acknowledging them from your backend .
Promote your subscription
You can create promotion codes to give selected users an extended free trial to an existing subscription. To learn more, see Promo codes .
For free trials, Google Play verifies that the user has a valid payment method before starting the free trial. Some users may see this verification as a hold or charge on their payment method. This hold or charge is temporary and is later reversed or refunded.
After the trial period ends, the user's payment method is charged for the full subscription amount.
If a user cancels a subscription at any time during the free trial, the subscription remains active until the end of the trial, and they aren't charged when the free trial period ends.
Cancel or revoke
You can use the Google Play Developer API to cancel or revoke a subscription. This functionality is also available in the Google Play Console .
Cancel : Users can cancel a subscription on Google Play. You can also provide an option for users to cancel in your app or on your website. Your app should handle these cancellations as described in Cancellations .
Revoke : When you revoke, the user immediately loses access to the subscription. This can be used if, for example, there was a technical error that prevented the user from accessing your product, and the user does not want to continue using the product. Your app should handle these cancellations as described in Revocations .
The following table illustrates the differences between cancel and revoke.
| Stops renewal | Revoke access | |
| বাতিল করুন | হ্যাঁ | না |
| বাতিল করুন | হ্যাঁ | হ্যাঁ |
Defer billing for a subscriber
You can extend the entitlement period for a subscription by using the subscriptionsv2.defer method. When you defer a subscription with add-ons, all items in the subscription are deferred by the same duration. During the deferral period, the user is subscribed to your content with full access but is not charged. The subscription renewal date is updated to reflect the new date.
For prepaid plans, you can use the defer billing API to defer the expiration time.
Deferred billing lets you do the following:
- Give users free access as a special offer, such as giving one week free for purchasing a movie.
- Give free access to customers as a gesture of goodwill.
Billing can be deferred by as little as one day and by as long as one year per API call. To defer the billing even further, you can call the API again before the new billing date arrives.
As an example, Darcy has a monthly subscription to online content for the Fishing Quarterly app. She is normally billed £1.25 on the first of each month. In March, she participated in an online survey for the app publisher. The publisher rewards her with six free weeks by deferring the next payment until May 15, which is six weeks after her previously scheduled billing date of April
- Darcy is not charged for April or the beginning of May and still has access to the content. On May 15, she is charged the normal £1.25 subscription fee for the month. Her next renewal date is now June 15.
When deferring, you might want to notify the user by email or within the app to notify them that their billing date has changed.
Handling payment declines
If there are payment issues with a subscription renewal, Google will periodically attempt to renew the subscription for some time before canceling. This recovery period can consists of a grace period, followed by an account hold period. During this time, Google sends the user emails and notifications prompting them to update their payment method.
Upon payment decline, the subscription enters a grace period if one is configured. During the grace period, you should ensure the user still has access to the subscription entitlements.
After any grace period has ended, the subscription enters an account hold period. During account hold, you should ensure the user does not have access to the subscription entitlements.
You can specify the length of each auto-renewing base plan's grace period and account hold in the Google Play Console. Specifying lengths less than the default values may reduce the number of subscriptions recovered from payment declines.
To maximize the likelihood of subscription recovery during a payment decline, you can inform your user of a payment issue and ask them to fix it.
You can either do this yourself, as described in the grace period and account hold sections, or you can implement the in-app messaging API, where Google shows a message to users in your app.
In-app messaging
If you've enabled in-app messaging with InAppMessageCategoryId.TRANSACTIONAL , Google Play will show users messaging during grace period and account hold once per day and provide them an opportunity to fix their payment without leaving the app.

We recommend that you call this API whenever the user opens the app to determine whether the message should be shown.
If the user successfully recovered their subscription, you will receive a response code of SUBSCRIPTION_STATUS_UPDATED along with a purchase token. You should then use this purchase token to call the Google Play Developer API and refresh the subscription status in your app.
Integrate in-app messaging
To show in-app messaging to user, use BillingClient.showInAppMessages() .
Here is an example of triggering the in-app messaging flow:
কোটলিন
val inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build() billingClient.showInAppMessages(activity, inAppMessageParams, object : InAppMessageResponseListener() { override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } })
জাভা
InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder() .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL) .build(); billingClient.showInAppMessages(activity, inAppMessageParams, new InAppMessageResponseListener() { @Override public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) { if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) { // The flow has finished and there is no action needed from developers. } else if (inAppMessageResult.responseCode == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) { // The subscription status changed. For example, a subscription // has been recovered from a suspend state. Developers should // expect the purchase token to be returned with this response // code and use the purchase token with the Google Play // Developer API. } } });
Handle subscription pending transactions
Pending transactions can happen in initial purchase, top-up, upgrade or downgrade. The subscription purchase starts with the SUBSCRIPTION_STATE_PENDING state before transitioning to SUBSCRIPTION_STATE_ACTIVE . If the transaction is expired or canceled by the user, it goes to SUBSCRIPTION_STATE_PENDING_PURCHASE_EXPIRED . You must and should only update the user's entitlement after the transaction is completed.
Subscription state change for initial purchase with pending transactions is straightforward. Your app receives a Purchase with PENDING state when the user initiates a pending transaction. When the transaction is completed, your app receives the Purchase again with state updated to PURCHASED . A SubscriptionNotification message with type SUBSCRIPTION_PURCHASED is sent to your RTDN client. Follow the normal process to verify the purchase, give the user access to the content and acknowledge the purchase. If the transaction expires or is canceled, a SubscriptionNotification message with type SUBSCRIPTION_PENDING_PURCHASE_CANCELED is sent to your RTDN client. In such cases, the user should never have gained access to the content.
Top-up, upgrade or downgrade with pending transactions involves state changes for both the old and new subscriptions. When the user initiates a pending top-up, upgrade or downgrade transaction, your app receives a Purchase for the old subscription with a PendingPurchaseUpdate object. At this time, the user is still owning the old subscription and has not gained the new subscription yet. Calling getProducts() and getPurchaseToken() on the PendingPurchaseUpdate object returns the product ids and purchase token of the new subscription. When the transaction is completed, your app receives a Purchase with the top-level purchase token set for the new subscription and the state set to PURCHASED . A SubscriptionNotification message with type SUBSCRIPTION_PURCHASED is sent to your RTDN client. Only at this time, you should replace the old purchase token with the new purchase token and update the user's access to the content. If the transaction expires or is canceled, a SubscriptionNotification message with type SUBSCRIPTION_PENDING_PURCHASE_CANCELED is sent to your RTDN client. In such cases, the user should still have access to the content of the old subscription.