২৫ জানু, ২০২৫·8 মিনিট পড়তে

কোড ছাড়া Stripe সাবস্ক্রিপশন: আয় লিক করে এমন ভুলগুলো

কোড ছাড়া Stripe সাবস্ক্রিপশন: webhook হ্যান্ডলিং, ট্রায়াল লজিক, প্রোরেশন এজ-কেস এবং ব্যর্থ-পেমেন্ট রিট্রাই ঠিক করে আয় লিক এড়ান।

কোড ছাড়া Stripe সাবস্ক্রিপশন: আয় লিক করে এমন ভুলগুলো

Where subscription revenue leakage usually starts

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

যদিও আপনি কোড ছাড়াই Stripe সাবস্ক্রিপশন বানাচ্ছেন, বিলিং-ও একটি লজিক আছে। Stripe হচ্ছে বিলিং ইঞ্জিন, কিন্তু আপনার অ্যাপটাই নির্ধারণ করে "active" মানে কী, কখন ফিচার আনলক করা হবে, এবং রিনিউয়াল বা ব্যর্থ-পেমেন্টে কী করা উচিত। নো-কোড টুল অনেক কাজ সরিয়ে দেয়, তবুও তারা আপনার নিয়ম অনুমান করতে পারে না।

বেশিরভাগ লিক চারটি জায়গা থেকেই শুরু হয়:

  • Webhooks সঠিকভাবে হ্যান্ডল করা হয় না (মিসড ইভেন্ট, ডুপ্লিকেট, ভুল অর্ডারিং)
  • Trials প্রত্যাশিতভাবে শেষ হয় না (ক্যান্সেল বা অন-পেমেন্ট হলে ট্রায়াল অ্যাক্সেস চালু থাকে)
  • প্ল্যান পরিবর্তনের সময় প্রোরেশন (আপগ্রেড/ডাউনগ্রেড কম চার্জ বা অবাক করা ক্রেডিট তৈরি করে)
  • ব্যর্থ পেমেন্ট এবং রিট্রাই (ডানিং চলাকালে অ্যাক্সেস থাকে, বা খুব আগেই বন্ধ হয়ে যায়)

একটি সাধারণ প্যাটার্ন হলো “হ্যাপি-পাথ টেস্টে কাজ করে।” আপনি সাবস্ক্রাইব করেন, অ্যাক্সেস পান, প্রথম ইনভয়েস পেইড হয়। তারপর বাস্তব জীবন আসে: কার্ড ফেল করে, কেউ মাঝপথে আপগ্রেড করে, কেউ ট্রায়ালে ক্যান্সেল করে, বা Stripe রাতের বেলা পেমেন্ট রিট্রাই করে। যদি আপনার অ্যাপ শুধু এক ফিল্ড চেক করে (অথবা শুধু একটি ইভেন্ট শোনে), তাহলে এটি ফ্রি সময় দিতে পারে বা ভুলক্রমে ডবল ক্রেডিট তৈরি করতে পারে।

যদি আপনি AppMaster-এর মতো প্ল্যাটফর্ম ব্যবহার করে তৈরি করছেন, স্ক্রীন ও ফ্লো দ্রুত বানানো সহজ। ঝুঁকি হচ্ছে ডিফল্ট ফ্লোই সঠিক বিলিং পলিসি বলে ধরে নেওয়া। আপনাকে এখনও আপনার অ্যাক্সেস নিয়ম নির্ধারণ করতে হবে এবং যাচাই করতে হবে যে আপনার ব্যাকএন্ড Stripe ইভেন্টগুলোতে ধারাবাহিকভাবে প্রতিক্রিয়া করছে।

Decide what is the source of truth for access

কোড ছাড়াই Stripe সাবস্ক্রিপশন চালালে একটি সিদ্ধান্ত পরবর্তীতে অনেক লিক প্রতিরোধ করে: কোন সিস্টেম এখনকার জন্য সিদ্ধান্ত নেবে যে ইউজারের অ্যাক্সেস আছে কি না।

সাধারণত দুটি অপশন আছে:

  • Stripe হচ্ছে source of truth: যখনও অ্যাক্সেস সিদ্ধান্ত নেবেন তখন Stripe-এ সাবস্ক্রিপশন স্টেট দেখবেন।
  • আপনার ডাটাবেস হচ্ছে source of truth: আপনি একটি অ্যাক্সেস স্টেট স্টোর করবেন এবং বিলিং ইভেন্ট হলে তা আপডেট করবেন।

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

অনেক প্রোডাক্টের জন্য ব্যবহারযোগ্য বাস্তবপন্থা: Stripe বিলিংয়ের জন্য source of truth, আপনার ডাটাবেস অ্যাক্সেসের জন্য source of truth। আপনার ডাটাবেস ম্যানুয়ালি বা UI বোতামের মাধ্যমে (যেমন “mark paid”) বদলানো উচিত নয়। এটি Stripe ইভেন্ট থেকে ডেরাইভ হওয়া উচিত (এবং মাঝে মাঝে রিকনসাইল করা)।

এর জন্য, স্থিতিশীল পরিচায়ক দরকার। কমপক্ষে, আপনার ইউজার বা অ্যাকাউন্ট রেকর্ডে এই ফিল্ডগুলো রাখুন:

  • Stripe customer ID (কে পে করছে)
  • Stripe subscription ID (তারা কোন প্ল্যানে আছে)
  • Latest invoice ID (কি বিল করা হয়েছে, প্রোরেশন সহ)
  • Latest payment_intent ID (কি পেমেন্ট আসলে চেষ্টা করা হয়েছে)

এরপর, আপনার প্রডাক্টের ভেতরে প্রতিটি সাবস্ক্রিপশন স্টেট কী মানে তা নির্ধারণ করুন। স্ক্রিন, অটোমেশন, বা ওয়েবহুক বানানোর আগে এটাকে সহজ নিয়মে লিখে রাখুন।

একটি ক্লিয়ার ডিফল্ট পলিসি অনেক দল ব্যবহার করে:

  • active: পূর্ণ অ্যাক্সেস
  • trialing: trial_end পর্যন্ত পূর্ণ অ্যাক্সেস, তারপর স্ট্যাটাস আবার চেক করুন
  • past_due: সীমিত অ্যাক্সেস (উদাহরণস্বরূপ, read-only) একটি ছোট গ্রেস পিরিয়ডের জন্য
  • unpaid: পেইড ফিচার ব্লক করুন; বিলিং পেজ ও ডেটা এক্সপোর্টের অনুমতি দিন
  • canceled: আপনি যদি period_end পর্যন্ত অ্যাক্সেস রাখতে দেন, তবেই রাখুন; তারপর ব্লক করুন

“ফ্রি ফোরএভার” গ্যাপ এড়িয়ে চলুন। যদি আপনি past_due-এ পূর্ণ অ্যাক্সেস দেয়, তবে একটি হার্ড কাটঅফ লাগবে (আপনি স্টোর করা তারিখগুলো ব্যবহার করে), ঝাপসা “পরে ঠিক করে নেব” নয়।

AppMaster-এ নির্মাণ করলে, অ্যাক্সেস সিদ্ধান্তকে ব্যবসায়িক লজিক হিসেবে বিবেচনা করুন: অ্যাকাউন্টে বর্তমান অ্যাক্সেস স্টেট স্টোর করুন, Stripe ইভেন্ট থেকে এটি আপডেট করুন, এবং আপনার ওয়েব ও মোবাইল UI ঐ ফিল্ডটাই ধারাবাহিকভাবে চেক করুক। এতে Stripe ইভেন্ট দেরি বা ভুল ক্রমে আসলেও আচরণ predictably থাকবে।

Webhooks: patterns that prevent missed events and double-processing

Webhooks হচ্ছে সেই নীরব জায়গা যেখানে আয় লিক শুরু হয়। Stripe ইভেন্টগুলো একাধিকবার পাঠাতে পারে, ভুল ক্রমে পাঠাতে পারে, বা কয়েক ঘণ্টা পরে ডেলিভারি করতে পারে। প্রতিটি webhook-কে “সম্ভবত দেরিতে” এবং “সম্ভবত ডুপ্লিকেট” হিসেবে ধরুন, এবং এমনভাবে অ্যাক্সেস আপডেট ডিজাইন করুন যে তা সঠিক রইবে।

Events that matter (and the ones you can usually ignore)

যেসব ইভেন্ট বাস্তব সাবস্ক্রিপশন স্টেট পরিবর্তন বোঝায়, সেগুলোর ছোট সেটের ওপর থাকুন। বেশিরভাগ সেটআপের জন্য এগুলো প্রায় সবকিছু কভার করে:

  • checkout.session.completed (আপনি যদি Checkout ব্যবহার করে সাবস্ক্রিপশন শুরু করেন)
  • customer.subscription.created, customer.subscription.updated, customer.subscription.deleted
  • invoice.paid (যখন একটি বিলিং পিরিয়ড আসলে পেইড হয়)
  • invoice.payment_failed (যখন তা হয় না)

অনেক দল charge.updated বা payment_intent.* মতো noisy ইভেন্টে অতিরিক্ত প্রতিক্রিয়া দেয় এবং হতবাককর নিয়ম তৈরি করে ফেলে। যদি আপনি ইতিমধ্যেই ইনভয়েস ও সাবস্ক্রিপশন ভালভাবে হ্যান্ডল করেন, তাহলে নিম্ন-স্তরের ইভেন্টগুলো প্রায়ই বিভ্রান্তি বাড়ায়।

Idempotency: stop double-unlocking when Stripe retries

Stripe webhooks রিট্রাই করে। যদি আপনি invoice.paid দেখলেই প্রতিবারই “অ্যাক্সেস দিন”, কিছু গ্রাহক অতিরিক্ত সময়, অতিরিক্ত ক্রেডিট, বা পুনরাবৃত্ত যোগ্যতা পেয়ে যাবে।

একটি সহজ প্যাটার্ন কাজ করে:

  • কোনো অপরিবর্তনীয় অ্যাকশনের আগে event.id প্রক্রিয়াকৃত হিসেবে স্টোর করুন
  • একই event.id আবার দেখলে, আগেই বেরিয়ে পড়ুন
  • কি পরিবর্তন হয়েছে তা রেকর্ড করুন (user/account, subscription ID, previous access state, new access state)

AppMaster-এ এটি একটি ডেটাবেস টেবিল এবং একটি Business Process ফ্লোতে পরিষ্কারভাবে মানানসই হয়, যা “ইতিমধ্যে প্রক্রিয়াকৃত?” চেক করে তারপর অ্যাক্সেস আপডেট করে।

Event ordering: design for late and out-of-order messages

ধরবেন না customer.subscription.updated আগে আসবে invoice.paid-এর, বা আপনি প্রতিটি ইভেন্ট সিকোয়েন্সে দেখবেন। অ্যাক্সেস নির্ধারণ করুন সর্বশেষ জানা সাবস্ক্রিপশন ও ইনভয়েস স্ট্যাটাসের উপর ভিত্তি করে, না যে আপনি পরেরটাকে কীভাবে আশা করেছিলেন তার উপর।

কিছু অসাম্য দেখলে, Stripe থেকে বর্তমান সাবস্ক্রিপশন ভর করে রিকনসাইল করুন।

কাঁচা webhook payload (অন্তত ৩০—৯০ দিন) সংরক্ষণ করুন। যখন সাপোর্ট বলে “কেন আমার অ্যাক্সেস হারালাম?” বা “কেন আমাকে দ্বিগুণ চার্জ করা হলো?”, সেই audit trail একটি রহস্যকে সমাধানে পরিণত করে।

Webhook mistakes that create free access or billing confusion

Webhooks হচ্ছে Stripe যখন কিছু ঘটেছে তখন পাঠানো মেসেজ। যদি আপনার অ্যাপ এগুলো উপেক্ষা করে বা ভুল মুহূর্তে প্রতিক্রিয়া করে, আপনি ফ্রি অ্যাক্সেস দিতে পারেন বা বিলিং আচরণ অসঙ্গত করতে পারেন।

একটি সাধারণ ভুল হলো Checkout শেষ হলে অ্যাক্সেস দেওয়া, প্রথম টাকা আসার মুহূর্ত না চাওয়া। checkout.session.completed মানে গ্রাহক সাবস্ক্রিপশন শুরু করেছে, কিন্তু প্রথম ইনভয়েস পেইড হয়েছে এমনটি নয়। কার্ড ফেল করতে পারে, 3D Secure বাদ পড়তে পারে, এবং কিছু পেমেন্ট মেথড পরে সেটেল করে। অ্যাক্সেসের জন্য invoice.paid (অথবা ইনভয়েস-সংযুক্ত সফল payment_intent) কে ফিচার অন করার মুহূর্ত হিসেবে বিবেচনা করুন।

আরেকটি লিক উৎস হলো শুধু হ্যাপি-পাথ শোনা। সাবস্ক্রিপশন সময়ের সাথে বদলে যায়: আপগ্রেড, ডাউনগ্রেড, ক্যান্সেল, পজ, এবং past due স্টেট। যদি আপনি সাবস্ক্রিপশন আপডেট কখনই প্রসেস না করেন, একজন ক্যান্সেল করা কাস্টমার সপ্তাহ ধরে অ্যাক্সেস ধরে রাখতে পারে।

চারটি ট্র্যাপ:

  • ক্লায়েন্টকে (ফ্রন্টএন্ড) ভরসা করা যে সাবস্ক্রিপশন active—ইউজ করে ডাটাবেসকে আপডেট করার বদলে
  • webhook সিগনেচার যাচাই না করা, ফলে নকল অনুরোধ সহজে অ্যাক্সেস বদলে দিতে পারে
  • টেস্ট ও লাইভ ইভেন্ট মিশানো (উদাহরণস্বরূপ, টেস্ট-মোড webhook প্রোডাকশনে গ্রহণ করা)
  • কেবল এক টাইপ ইভেন্ট হ্যান্ডল করা এবং সবকিছু "নিজে ঠিক হয়ে যাবে" ধরে নেওয়া

একটি বাস্তব ব্যর্থতা: গ্রাহক checkout কমপ্লিট করে, আপনার অ্যাপ প্রিমিয়াম আনলক করে, এবং প্রথম ইনভয়েস ফেল হয়। যদি সিস্টেম কখনই ব্যর্থ ইভেন্ট প্রসেস না করে, তারা বিনা পয়সায় প্রিমিয়াম পেয়ে থাকবে।

AppMaster-এ কোড ছাড়া Stripe সাবস্ক্রিপশন বানালে লক্ষ্য একই: এক সার্ভার-সাইড রেকর্ড রাখুন অ্যাক্সেসের, এবং কেবল যাচাইকৃত Stripe webhook কলে যখন পেমেন্ট সফল হয়, ব্যর্থ হয়, বা সাবস্ক্রিপশন স্ট্যাটাস বদলে তখনই সেটি পরিবর্তন করুন।

Trials: avoid free time that never ends

Turn trials into clear rules
UI ফ্ল্যাগের বদলে Stripe timestamp ব্যবহার করে ট্রায়াল নিয়ম বাস্তবায়ন করুন—ওয়েব ও মবাইলে সমানভাবে।
এখনই তৈরি করুন

ট্রায়াল শুধুমাত্র “ফ্রি বিলিং” নয়। এটি একটি স্পষ্ট প্রতিশ্রুতি: গ্রাহক কী ব্যবহার করতে পারবে, কত সময়ের জন্য, এবং পরবর্তীতে কী হবে। সবচেয়ে বড় ঝুঁকি ট্রায়ালকে UI-এ একটি লেবেল হিসেবে দেখা, সময়-সীমাবদ্ধ অ্যাক্সেস নিয়ম হিসেবে না দেখা।

নির্ধারণ করুন আপনার প্রডাক্টে “trial access” কী মানে—পূর্ণ অ্যাক্সেস নাকি সীমিত সিট, ফিচার, বা ব্যবহার। ট্রায়াল শেষ হওয়ার আগে কিভাবে রিমাইন্ডার পাঠাবেন (ইমেল, ইন-অ্যাপ ব্যানার) এবং যখন কার্ড নেই তখন বিলিং পেজ কী দেখাবে তা ঠিক করুন।

অ্যাক্সেসকে এমন তারিখের সঙ্গে বেঁধে দিন যা যাচাইযোগ্য, লোকাল বুলিয়ান is_trial = true-এর ওপর নয়। যখন Stripe বলে সাবস্ক্রিপশন ট্রায়াল সহ তৈরি হয়েছে তখন ট্রায়াল অ্যাক্সেস দিন, এবং ট্রায়াল শেষ হলে ট্রায়াল অ্যাক্সেস সরিয়ে দিন—যদি সাবস্ক্রিপশন active ও পেইড না হয়। আপনার অ্যাপ trial_ends_at স্টোর করে থাকলে তা Stripe ইভেন্ট থেকে আপডেট করুন, ফ্রন্টএন্ড ক্লিক থেকে নয়।

কার্ড কালেকশন টাইমিং হচ্ছে যেখানে “ফ্রি ফোরএভার” সাধারণত ঢুকছে। যদি আপনি ট্রায়াল শুরু করেন পেমেন্ট মেথড না নিয়ে, তাহলে কনভার্শন পাথ পরিকল্পনা করুন:

  • ট্রায়াল শেষ হওয়ার আগে স্পষ্ট “পেমেন্ট মেথড যোগ করুন” ধাপ দেখান
  • সিদ্ধান্ত নিন আপনি কার্ড ছাড়া ট্রায়াল শুরু করতে দেবেন কি না
  • কনভার্শনে পেমেন্ট ফেল করলে, সঙ্গে সঙ্গে বা ছোট গ্রেস পিরিয়ড পরে অ্যাক্সেস কমান
  • অ্যাপে সবসময় স্পষ্ট ট্রায়াল শেষের তারিখ দেখান

এজ-কেসগুলো গুরুত্বপূর্ণ কারণ ট্রায়াল এডিট করা হয়ে থাকে—সাপোর্ট ট্রায়াল বাড়াতে পারে, বা ইউজার একদিনেই ক্যান্সেল করতে পারে। ইউজার ট্রায়ালে আপগ্রেডও করতে পারে এবং নতুন প্ল্যানই দ্রুত পেতে আশা করে। সহজ নিয়ম বেছে নিন এবং ধারাবাহিক রাখুন: ট্রায়ালে আপগ্রেড করলে ট্রায়াল শেষ তারিখ রাখবেন নাকি ট্রায়াল শেষ করে এখনই বিলিং শুরু করবেন—যে সিদ্ধান্ত নেন তা predictable এবং দৃশ্যমান করুন।

একটি সাধারণ ব্যর্থতার প্যাটার্ন: ইউজার “Start trial” ক্লিক করলে ট্রায়াল অ্যাক্সেস দেন, কিন্তু আপনি কেবল তখনই তা সরান যখন তারা “Cancel” ক্লিক করে। তারা যদি ট্যাব বন্ধ করে বা আপনার webhook ফেল করে, তারা অ্যাক্সেস ধরে রাখে। নো-কোড অ্যাপ (AppMaster সহ) এ অ্যাক্সেসকে Stripe webhook থেকে প্রাপ্ত সাবস্ক্রিপশন স্ট্যাটাস ও ট্রায়াল এন্ড টাইমস্ট্যাম্পের ওপর ভিত্তি করে রাখুন, ফ্রন্টএন্ড-সেট ম্যানুয়াল ফ্ল্যাগ নয়।

Proration: stop accidental undercharging during plan changes

Make webhooks safe by default
Business Process Editor-এ idempotency চেকসহ Stripe webhook প্রসেস করুন।
ওয়ার্কফ্লো তৈরি করুন

প্রোরেশন ঘটে যখন গ্রাহক মাঝপথে প্ল্যান পরিবর্তন করে এবং Stripe বিলটি সমন্বয় করে যাতে তারা ব্যবহারের জন্যই অর্থ প্রদান করে। আপগ্রেড, ডাউনগ্রেড, পরিমাণ পরিবর্তন (সিট) বা ভিন্ন প্রাইসে সুইচ করলে Stripe প্রোরেটেড ইনভয়েস তৈরি করতে পারে।

সাধারণত আয় লিক ঘটে যখন আপগ্রেডের সময় কম চার্জ হয়। আপনার অ্যাপ নতুন-প্ল্যান ফিচার সাথে সাথেই আনলক করে দেয়, কিন্তু বিলিং পরিবর্তন পরে কার্যকর হয়, বা প্রোরেশন ইনভয়েস কখনো পেইড হয় না। গ্রাহক ভালো প্ল্যান বিনামূল্যে পায় পরবর্তী নবায়ন পর্যন্ত।

Pick a proration policy and stick to it

আপগ্রেড ও ডাউনগ্রেড একইভাবে ট্রিট করা উচিত নয় যদি না আপনি ইচ্ছাকৃতভাবে চান।

একটি সহজ, ধারাবাহিক পলিসি:

  • Upgrades: সঙ্গে সঙ্গে প্রয়োগ করুন, প্রোরেটেড পার্থক্য এখনই চার্জ করুন
  • Downgrades: পরবর্তী নবায়নে প্রয়োগ করুন (মধ্য-সাইকেলে রিফান্ড নয়)
  • Quantity increases (আরও সিট): সঙ্গে সঙ্গে প্রয়োগ করুন প্রোরেশনসহ
  • Quantity decreases: নবায়নে কার্যকর করুন
  • ঐচ্ছিক: "no proration" কেবল বিশেষ ক্ষেত্রে (যেমন বাৎসরিক কনট্রাক্ট) অনুমোদিত করুন, দুর্ঘটনায় নয়

AppMaster-এ কোড ছাড়া Stripe সাবস্ক্রিপশন তৈরি করলে প্ল্যান-চেঞ্জ ফ্লো ও অ্যাক্সেস-নিয়ন্ত্রণ নিয়ম মিলাতে ভুলবেন না। যদি আপগ্রেড এখনই চার্জ করা উচিত, তাহলে Stripe নিশ্চিত না করা পর্যন্ত প্রিমিয়াম ফিচার আনলক করবেন না—বিশেষ করে যদি প্রোরেশন ইনভয়েস পেন্ডিং থাকে।

মাঝপথে পরিবর্তন সিট বা ইউজেজ টায়ার নিয়ে জটিল হতে পারে। টিম কেউ ২৫তম দিনে ২০ সিট যোগ করে, তারপর ২৭তম দিনে ১৫ সিট সরিয়ে ফেললে, যদি আপনার লজিক অসংগঠিত হয়, আপনি অতিরিক্ত সিট অনলি চার্জ না করে দিতে পারেন বা বিভ্রান্তিকর ক্রেডিট তৈরি করতে পারেন যা রিফান্ড ও সাপোর্ট টিকিট ট্রিগার করে।

Explain proration before the customer clicks

প্রোরেশন-বিরোধ সাধারণত সারপ্রাইজ ইনভয়েস থেকেই আসে, খারাপ উদ্দেশ্য থেকে নয়। নিশ্চিত করুন কনফার্ম বাটনের কাছে একটি ছোট বাক্য আছে যা আপনার পলিসি ও সময় মেলে:

  • “Upgrades start today and you’ll be charged a prorated amount now.”
  • “Downgrades start on your next billing date.”
  • “Adding seats bills immediately; removing seats takes effect next cycle.”

স্পষ্ট প্রত্যাশা চার্জব্যাক, রিফান্ড, এবং “কেন আমাকে দ্বিগুণ চার্জ করা হলো?” প্রশ্ন কমায়।

Failed payments and retries: get dunning and access right

ব্যর্থ পেমেন্ট হচ্ছে সেই জায়গা যেখানে সাবস্ক্রিপশন সেটআপগুলি চুপচাপ আয় লিক করে। যদি আপনার অ্যাপ ব্যর্থ চার্জের পর অনন্তকাল অ্যাক্সেস খোলা রাখে, আপনি সেবা প্রদান করছেন কিন্তু পয়সা পাচ্ছেন না। যদি আপনি খুব দ্রুত অ্যাক্সেস কেটে দেন, আপনি সাপোর্ট টিকেট ও অনাবশ্যক চর্ন তৈরি করবেন।

Know the states that matter

একটি ব্যর্থ চার্জের পর, Stripe সাবস্ক্রিপশনকে past_due এবং পরে unpaid-এ নিয়ে যেতে পারে (অথবা সেটিংস অনুযায়ী ক্যান্সেল করে)। এই স্টেটগুলোকে আলাদা করে বিবেচনা করুন। past_due সাধারণত বোঝায় গ্রাহক পুনরুদ্ধারযোগ্য এবং Stripe রিট্রাই করছে। unpaid সাধারণত বোঝায় ইনভয়েস পেইড হচ্ছে না এবং সেবা বন্ধ করা উচিত।

কোড ছাড়া Stripe সাবস্ক্রিপশনে একটি সাধারণ ভুল হলো কেবল একটি ফিল্ড (যেমন “subscription is active”) চেক করা এবং ইনভয়েস ব্যর্থতায় প্রতিক্রিয়া না করা। অ্যাক্সেসকে বিলিং সিগন্যাল অনুসরণ করাতে হবে, অনুমান নয়।

A simple dunning plan that protects revenue

আপনার রিট্রাই শিডিউল ও গ্রেস পিরিয়ড আগে থেকেই নির্ধারণ করুন, তারপর সেগুলোকে এমন নিয়ম হিসেবে এনকোড করুন যা আপনার অ্যাপ প্রয়োগ করতে পারে। Stripe কনফিগার করা থাকলে রিট্রাই হ্যান্ডেল করে, কিন্তু রিট্রাই উইন্ডো চলাকালে অ্যাক্সেস কী হবে তা আপনার অ্যাপই ঠিক করে।

একটি ব্যবহারিক মডেল:

  • On invoice.payment_failed: অ্যাকাউন্টকে “payment issue” হিসেবে মার্ক করুন, একটি ছোট গ্রেস পিরিয়ড (যেমন ৩–৭ দিন) অ্যাক্সেস রাখুন
  • যখন সাবস্ক্রিপশন past_due-এ আছে: ইন-অ্যাপ ব্যানার দেখান এবং “update card” মেসেজ পাঠান
  • যখন পেমেন্ট সফল হয় (invoice.paid বা invoice.payment_succeeded): payment issue ফ্ল্যাগ পরিষ্কার করে পূর্ণ অ্যাক্সেস ফিরিয়ে দিন
  • যখন সাবস্ক্রিপশন unpaid হয় (অথবা ক্যান্সেল করা হয়): read-only বা মূল ক্রিয়াকলাপ ব্লক করুন, কেবল বিলিং পেজ লুকানো নয়
  • সাপোর্ট দেখতে পায় সে জন্য সর্বশেষ ইনভয়েস স্ট্যাটাস ও পরবর্তী রিট্রাই সময় লগ করুন

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

“Update card” ফ্লোতে, গ্রাহক নতুন ডিটেইলস দিলে স্বয়ংক্রিয়ভাবে সমস্য ঠিক হয়েছে ধরে নিবেন না। শুধুমাত্র Stripe যখন পেইড ইনভয়েস বা সফল পেমেন্ট ইভেন্ট দেখায় তখনই recovery নিশ্চিত করুন। AppMaster-এ এটি একটি স্পষ্ট Business Process হতে পারে: পেমেন্ট সাফল্য webhook এলে ব্যবহারকারীকে আবার active করুন, ফিচার আনলক করুন, এবং একটি কনফার্মেশন মেসেজ পাঠান।

Example scenario: one customer journey, four common pitfalls

Choose a source of truth
Stripe-কে বিলিং সত্যি রাখুন এবং আপনার ডাটাবেসকে অ্যাক্সেস-সত্যি রেখে পরিষ্কার আপডেট করুন।
চেষ্টা করে দেখুন

Maya ১৪ দিনের ট্রায়াল নেয়। সে একটি কার্ড দেয়, ট্রায়াল শুরু করে, ১০তম দিনে আপগ্রেড করে, তারপর তার ব্যাংক পরে রিনিউয়াল decline করে। এটি স্বাভাবিক এবং ঠিকই সেই জায়গা যেখানে আয় লিক হয়।

Step-by-step timeline (and what your app should do)

  1. Trial starts: Stripe সাবস্ক্রিপশন তৈরি করে এবং একটি trial end সেট করে। সাধারণত আপনি customer.subscription.created এবং (আপনার সেটআপ অনুযায়ী) একটি আসন্ন ইনভয়েস দেখবেন। আপনার অ্যাপকে ট্রায়ালে থাকার কারণে অ্যাক্সেস দিতে হবে এবং ট্রায়াল শেষ কখন তা রেকর্ড করতে হবে যাতে অ্যাক্সেস স্বয়ংক্রিয়ভাবে পরিবর্তন হয়।

Pitfall 1: কেবল "signup success"-এ অ্যাক্সেস দেওয়া এবং ট্রায়াল শেষ হলে কখনই আপডেট না করা।

  1. Upgrade during trial: Maya দিন ১০-এ Basic থেকে Pro-তে যায়। Stripe সাবস্ক্রিপশন আপডেট করে এবং একটি ইনভয়েস বা প্রোরেশন তৈরি করতে পারে। আপনি customer.subscription.updated, invoice.created, invoice.finalized, এবং যদি টাকা উঠলে invoice.paid দেখতে পারেন।

Pitfall 2: “plan changed”-কে সঙ্গে সঙ্গেই পেইড অ্যাক্সেস ধরে নেওয়া, যদিও ইনভয়েস এখনও ওপেন বা পরে পেমেন্ট ফেইল হতে পারে।

  1. Renewal: দিন ১৪-এ প্রথম পেইড পিরিয়ড শুরু হয়, তারপর পরবর্তী মাসে রিনিউয়াল ইনভয়েস চেষ্টা করা হয়।

Pitfall 3: একটি ওয়েবহুকের উপর ভরসা করা এবং অন্যগুলো মিস করা, ফলে আপনি হয় invoice.payment_failed-এর পরও অ্যাক্সেস নাও সরাতে পারেন, বা ডুপ্লিকেট ও আউট-অফ-অর্ডার ইভেন্টের কারণে invoice.paid-এর পরও সরিয়ে ফেলতে পারেন।

  1. Card fails: Stripe ইনভয়েসকে unpaid চিহ্নিত করে এবং আপনার কনফিগারেশন অনুযায়ী রিট্রাই শুরু করে।

Pitfall 4: খুব দ্রুত ইউজারকে লক করে দেওয়া বদলে ছোট একটি গ্রেস পিরিয়ড ও স্পষ্ট “update card” পথ না রাখা।

What to store so support can fix issues fast

একটি ছোট audit trail রাখুন: Stripe customer ID, subscription ID, current status, trial_end, current_period_end, latest invoice ID, last successful payment date, এবং শেষ প্রক্রিয়াকৃত webhook event ID সহ টাইমস্ট্যাম্প।

Maya যদি সাপোর্ট-এ যোগাযোগ করে, আপনার টিম দ্রুত দুই প্রশ্নের উত্তর দিতে পারা উচিত: এখন Stripe কী বলছে, এবং আমাদের অ্যাপ শেষবার কী প্রয়োগ করেছিল?

QA checklist: validate billing behavior before you launch

Go from idea to working flow
বিলিং, স্ট্যাটাস এবং আপগ্রেড স্ক্রিনসহ একটি ন্যূনতম সাবস্ক্রিপশন ফ্লো চালু করুন।
প্রোটোটাইপ অ্যাপ

বিলিংকে একটা ফিচার হিসেবে টেস্ট করুন, একটা সুইচ হিসেবে নয়। অধিকাংশ আয় লিক ঘটে Stripe ইভেন্টগুলোর এবং আপনার অ্যাপের অ্যাক্সেস সিদ্ধান্তের মধ্যকার ফাঁকগুলোতে।

শুরুতে “Stripe চার্জ করতে পারে?” এবং “অ্যাপ অ্যাক্সেস দেয় কি?” আলাদা করে দেখুন এবং উভয়ই সেই একই পরিবেশে টেস্ট করুন যেখানে আপনি চালাতে যাচ্ছেন।

Pre-launch setup checks

  • টেস্ট বনাম লাইভ আলাদা আছে কি না নিশ্চিত করুন: কী, webhook endpoint, products/prices, environment variables
  • webhook endpoint সিকিউরিটি যাচাই করুন: signature verification চালু আছে এবং unsigned বা ম্যালফর্মড ইভেন্ট প্রত্যাখ্যান করা হচ্ছে
  • idempotency যাচাই করুন: পুনরাবৃত্ত ইভেন্ট অতিরিক্ত entitlements, ইনভয়েস, বা ইমেইল তৈরি না করে
  • লগিং ব্যবহারযোগ্য রাখুন: event ID, customer, subscription, এবং আপনার চূড়ান্ত অ্যাক্সেস সিদ্ধান্ত স্টোর করুন
  • ম্যাপিং যাচাই করুন: প্রতিটি ইউজার অ্যাকাউন্ট ঠিক এক Stripe customer-এ ম্যাপ করে (অথবা আপনার কাছে একটি স্পষ্ট multi-customer নিয়ম আছে)

AppMaster-এ এটি সাধারণত মানে হচ্ছে আপনার Stripe ইন্টিগ্রেশন, এনভায়রনমেন্ট সেটিংস, এবং Business Process ফ্লো নিশ্চিত করা যা প্রতিটি webhook ইভেন্ট ও ফলস্বরূপ অ্যাক্সেস পরিবর্তনের জন্য একটি পরিষ্কার audit trail রেকর্ড করে।

Subscription behavior test cases

এইগুলো একটি সংক্ষিপ্ত স্ক্রিপ্ট করা QA সেশনের মতো চালান। বাস্তব ভূমিকা ব্যবহার করুন (একজন সাধারণ ব্যবহারকারী, একজন অ্যাডমিন) এবং লিখে রাখুন আপনার প্রডাক্টে “অ্যাক্সেস অন/অফ” মানে কী।

  • Trials: একটি ট্রায়াল শুরু করুন, ট্রায়ালে ক্যান্সেল করুন, এটি শেষ হতে দিন, একবার বাড়ান, নিশ্চিত করুন কনভার্শন কেবল পেমেন্ট সফল হলে হয়
  • Proration: মাঝপথে আপগ্রেড করুন, মাঝপথে ডাউনগ্রেড করুন, একই দিনে দুই প্ল্যান পরিবর্তন করুন; ইনভয়েস ও অ্যাক্সেস আপনার পলিসির সাথে মিলছে কি না নিশ্চিত করুন
  • Credits/refunds: একটি ক্রেডিট বা রিফান্ড ইস্যু করুন এবং নিশ্চিত করুন আপনি চিরকাল প্রিমিয়াম অ্যাক্সেস রাখছেন না (অথবা অত্যন্ত আগেই সরিয়ে ফেলছেন না)
  • Failed payments: একটি রিনিউয়াল ব্যর্থ করার সিমুলেশন করুন, রিট্রাই টাইমিং ও গ্রেস পিরিয়ড যাচাই করুন, নিশ্চিত করুন কখন অ্যাক্সেস সীমিত বা সরানো হচ্ছে
  • Recovery: ব্যর্থ পেমেন্টের পর পেমেন্ট সম্পন্ন করুন এবং নিশ্চিত করুন অ্যাক্সেস সঙ্গে সঙ্গেই ফিরে আসে (এবং কেবল একবার)

প্রতিটি টেস্টের জন্য তিনটি তথ্য ধরুন: Stripe-এর ইভেন্ট টাইমলাইন, আপনার ডাটাবেস স্টেট, এবং ব্যবহারকারী অ্যাপে আসলে কী করতে পারে। যখন এই তিনটি অসঙ্গত হয়, আপনি লিক খুঁজে পেয়েছেন।

Next steps: implement safely and keep billing predictable

আপনার বিলিং নিয়মগুলো সাধারণ ভাষায় লিখুন এবং সুনির্দিষ্ট রাখুন: কখন অ্যাক্সেস শুরু হয়, কখন বন্ধ হয়, কীকে “paid” ধরা হবে, ট্রায়াল কবে শেষ হবে, এবং প্ল্যান পরিবর্তনে কী হবে। যদি দুইজন মানুষ তা পড়ে ভিন্ন ফল কল্পনা করে, আপনার ওয়ার্কফ্লো টাকা লিক করবে।

ওই নিয়মগুলোকে একটি পুনরাবৃত্ত টেস্ট পরিকল্পনায় রূপান্তর করুন যেটা আপনি প্রতিবার বিলিং লজিক বদলে চালাবেন। কয়েকটি ডেডিকেটেড Stripe টেস্ট কাস্টমার ও একটি নির্দিষ্ট স্ক্রিপ্ট কিছুটা অনির্ধারিত “ক্লিক করে দেখে নিন” থেকে বহুগুণ ভালো।

পরীক্ষার সময় audit trail রাখুন। সাপোর্ট ও ফাইন্যান্স দ্রুত উত্তর চাবে যেমন “এই ইউজার কেন অ্যাক্সেস রেখে দেয়া ছিল?” বা “কেন আমরা দ্বিগুণ চার্জ করেছি?” মূল সাবস্ক্রিপশন ও ইনভয়েস পরিবর্তনগুলো লগ করুন (স্ট্যাটাস, current period তারিখ, trial end, latest invoice, payment intent outcome), এবং webhook event ID স্টোর করুন যাতে আপনি কি ঘটেছে প্রমাণ করতে পারেন এবং একই ইভেন্ট দুইবার প্রসেস হওয়া এড়াতে পারেন।

যদি আপনি কোড ছাড়া এটি বাস্তবায়ন করছেন, AppMaster (appmaster.io) আপনার স্ট্রাকচার কনসিস্টেন্ট রাখতে সাহায্য করতে পারে। আপনি Data Designer-এ (PostgreSQL) বিলিং ডেটা মডেল করতে পারবেন, Business Process Editor-এ idempotency চেকসহ Stripe webhooks প্রসেস করতে পারবেন, এবং এমন একটি একক “source of truth” ফিল্ড দিয়ে অ্যাক্সেস নিয়ন্ত্রণ করতে পারবেন যা আপনার ওয়েব ও মোবাইল UI পড়ে।

একটি রাল অনুভূতির ড্রাই রান দিয়ে শেষ করুন: একজন টিমমেট সাইন আপ করে, অ্যাপ ব্যবহার করে, আপগ্রেড করে, একটি পেমেন্ট ফেল করে, তারপর সেটা ঠিক করে। যদি প্রতিটি ধাপ আপনার লিখিত নিয়মের সাথে মিলে, আপনি প্রস্তুত।

Next step: AppMaster-এ একটি ন্যূনতম Stripe সাবস্ক্রিপশন ফ্লো তৈরি করে QA চেকলিস্ট অনুসারে চালিয়ে দেখুন।

শুরু করা সহজ
কিছু আশ্চর্যজনকতৈরি করুন

বিনামূল্যের পরিকল্পনা সহ অ্যাপমাস্টারের সাথে পরীক্ষা করুন।
আপনি যখন প্রস্তুত হবেন তখন আপনি সঠিক সদস্যতা বেছে নিতে পারেন৷

এবার শুরু করা যাক