কম্পিউটার টিউটোরিয়াল

স্ট্রাইপ চেকআউট (Stripe Checkout) দিয়ে রেইলসে সিমলেস ওয়ান-টাইম পারচেজ ইন্টিগ্রেশন

মিলিয়ন মিলিয়ন কোম্পানি দ্বারা ব্যবহৃত, স্ট্রাইপ (Stripe) অ্যাপ্লিকেশনের জন্য পেমেন্ট ইনফ্রাস্ট্রাকচার প্রদান করে সাবস্ক্রিপশন এবং ওয়ান-টাইম পারচেজ হ্যান্ডেল করার জন্য। স্ট্রাইপ চেকআউট (Stripe Checkout) আমাদের সহজে কার্ড পেমেন্ট এক্সেপ্ট করতে দেয় একটি হোস্টেড পেমেন্টস পেজ (hosted payments page) দিয়ে, যা কনভার্সন বাড়ানোর জন্য ক্র্যাফটেড। এটিকে ওয়েবহুকস (webhooks) এর সাথে কম্বাইন করে, ডেভেলপাররা প্রোডাক্ট এবং সাবস্ক্রিপশন বেচে সেগুলো ডিজিটালি ডেলিভার করতে পারে।

যদিও টেকনিক্যালি পemment আপনার নিজে হ্যান্ডেল করা সম্ভব একটি এক্সিস্টিং প্রোভাইডার ব্যবহার করে, স্ট্রাইপ কিছু সুবিধা প্রদান করে। শুরুতে, এটি দ্রুত। স্ট্রাইপের ৪,০০০+ মানুষ কাজ করছে পেমেন্টকে যতটা সম্ভব সিম্পল, সিকিউর, এবং কনভেনিয়েন্ট बनाने জন্য।

অতিরিক্তভাবে, আপনার পেমেন্ট 'powered by Stripe' হওয়া কাস্টমার ট্রাস্ট বিল্ড করতে এবং কনভার্সন বাড়াতে একটি সহজ উপায়। কাস্টমাররা সাধারণত তাদের কার্ড বা ব্যাংক ইনফরমেশন প্রতিটি ওয়েবসাইটে দিতে হিচকিচায়, এবং যথার্থভাবে।

স্ট্রাইপ অনলাইন পেমেন্ট স্পেসে একমাত্র প্রোভাইডার নয়। Paddle অনলাইন পেমেন্ট স্পেসে আরেকটি বড় প্লেয়ার। Paddle স্ট্রাইপের মত অনেক ফিচার অফার করে, কিন্তু কিছুটা বেশি ফি এবং anecdotalভাবে খারাপ ডেভেলপার এক্সপেরিয়েন্সের সাথে। অন্যান্য কিছু প্রতিযোগী স্ট্রাইপের অল্টারনেটিভ হলেও, তাদের প্রোডাক্টের বিশাল জনপ্রিয়তা অনলাইন পেমেন্টের জন্য স্ট্রাইপকে একটি সহজ চয়স করে তোলে।

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

সেটআপ (Setup)

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

স্ট্রাইপ অ্যাকাউন্ট তৈরি করা

শুরু করতে, আপনাকে স্ট্রাইপের ওয়েবসাইটে যেতে হবে একটি অ্যাকাউন্ট তৈরি করতে। আপনার ইনফরমেশন বা আপনার বিজনেসের ইনফরমেশন (যদি প্রযোজ্য হয়) দিয়ে সাইন আপ করুন।

স্ট্রাইপ চেকআউট (Stripe Checkout) দিয়ে রেইলসে সিমলেস ওয়ান-টাইম পারচেজ ইন্টিগ্রেশন স্ট্রাইপ সাইন-আপ পেজের স্ক্রিনশট

এই আর্টিকেল আপনাকে অ্যাকাউন্ট তৈরি করার এক্স্যাক্ট ডিটেইলস Через গাইড করবে না, কিন্তু তাদের ডকুমেন্টেশন আপনার যেকোনো প্রশ্নের উত্তর দেবে। আমরা বিশেষভাবে তাদের payments and payouts প্রোডাক্ট বা আরও স্পেসিফিক্যালি Stripe Checkout-এ আগ্রহী।

বেসিক রেইলস অ্যাপ তৈরি করা

একবার আপনার স্ট্রাইপ অ্যাকাউন্ট সেট আপ হলে, ইন্টিগ্রেশনের জন্য একটি বেসিক রেইলস অ্যাপ তৈরি করার টাইম। আপনি যদি এক্সিস্টিং অ্যাপ ইন্টিগ্রেট করেন বা শুধু স্ট্রাইপ পάρ্টে আগ্রহী হন, "Basic Stripe Integration"-এ স্কিপ করুন।

এই উদাহরণের জন্য আমি নিচের ভার্সনগুলো ব্যবহার করব:

  • Rails 6.1
  • Ruby 3.0.0

আপনার রুবি এবং রেইলস ইতিমধ্যে ইনস্টল করা থাকলে, আগে বড়ুন এবং চালান:

rails new roommate-board

আমি অ্যাপের জন্য roommate-board নাম বেছে নিলাম, কিন্তু আপনি অন্য কিছু বেছে নিতে পারেন। শুধু উদাহরণ কোডে যেখানেও এই নাম দেখবেন সেখানে স왑 আউট করুন।

তازه তৈরি করা ডিরেক্টরিতে চেঞ্জ করুন:

cd roommate-board

তারপর অ্যাপ চালান:

rails s

আপনি যদি localhost:3000 ভিজিট করলে টিপিক্যাল রেইলস ওয়েলকাম পেজ দেখেন, তবে অভিনন্দন, আমরা কোডিং শুরু করার জন্য প্রস্তুত!

প্রথমে, আমরা Devise যোগ করব যুজার অথেন্টিকেশন হ্যান্ডেল করার জন্য। সিম্পলি gem 'devise' আপনার Gemfile-এ যোগ করুন এবং তারপর চালান:

bundle install

এরপর, Devise জেনারেটর ব্যবহার করে সেট আপ করুন:

rails generate devise:install

এরপর, Devise-কে User মডেলের সাথে কানেক্ট করুন:

rails generate devise User

এবং অবশেষে, মাইগ্রেশন চালান:

rails db:migrate

রুমমেট বোর্ড তৈরি করা

আপনি এটি পড়ছেন মানে আপনি স্ট্রাইপ ইন্টিগ্রেশনে বেশি আগ্রহী, ফ্রন্ট-এন্ড ডিজাইন কম, তাই আমরা স্টাইলিং নিয়ে চিন্তা করব না।

আমাদের পরবর্তী ধাপ হলো পোস্ট করার জন্য মডেল তৈরি করা! আমরা রেইলসের হ্যান্ডি জেনারেটর ব্যবহার করব মডেল, মাইগ্রেশন, কন্ট্রোলার, এবং রুট তৈরি করার জন্য। শুধু চালান:

rails generate scaffold Post address:string rent:integer content:text

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

rails db:migrate

এরপর, আমরা পোস্টের index view কে অ্যাপ্লিকেশনের রুট (root) বানাব সুবিধার জন্য। config/routes.rb-এ নিচের লাইনটি যোগ করুন:

root 'posts#index'

এখনো এটি খুব খালি, এবং সাইন ইন, সাইন আউট, বা সাইন আপ করার কোনো স্পষ্ট উপায় নেই। ফাংশন্যালিটি ইতিমধ্যে আছে, তাই শুধু হেডারে কিছু লিংক যোগ করি যাতে ইউজারকে স্পষ্ট হয়। app/views/layouts/application.html.erb-এ, আমরা নেসেসারি লিংকগুলো যোগ করব। পরিবর্তন করার পর আমার ফাইলটি এমন দেখাচ্ছে:

<!DOCTYPE html>
<html>
<head>
  <title>RoommateBoard</title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
  <header>
    <nav>
      <a href="/#" class="block">
        <h1>Roommate Board</h1>
      </a>
      <% if user_signed_in? %>
        <%= link_to "Manage Posts", manage_posts_url %>
        <%= link_to "Sign Out", destroy_user_session_url, :method => 'delete' %>
      <% else %>
        <%= link_to "New Post", new_user_registration_url %>
      <% end %>
    </nav>
  </header>
  <%= yield %>
</body>
</html>

এটি হোমপেজের লিংক দেয়, এবং ব্যবহারকারীরা "New Post"-এ ক্লিক করলে সাইন-আপ পেজে যাবে। যদি তারা সাইন ইন করা থাকে, এটি "Manage Posts" বাটন এবং "Sign Out" বাটনে পরিবর্তন হয়। কোনো স্টাইলিং ছাড়া এবং সাইন ইন না করা অবস্থায়, রুট পেজ এখন এমন দেখাচ্ছে:

স্ট্রাইপ চেকআউট (Stripe Checkout) দিয়ে রেইলসে সিমলেস ওয়ান-টাইম পারচেজ ইন্টিগ্রেশন বেসিক পোস্টস ইনডেক্স পেজের স্ক্রিনশট

এরপর, আমরা প্রতিটি পোস্টিংকে একটি ইউনিক ইউজারের সাথে স্কোপ (scope) করব। এসেনশিয়ালি, আমরা একটি belongs_to অ্যাসোসিয়েশন তৈরি করব একটি Posting এবং User-এর মধ্যে, সাথে কিছু রিলেভেন্ট লজিক। আমরা রেইলসের হ্যান্ডি মাইগ্রেশন জেনারেটর দিয়ে শুরু করব; শুধু চালান:

rails g migration AddUserIdToPosts

এখন db/migrate/-এ মাইগ্রেশন ফাইলটি এডিট করুন যেন এটি এমন দেখে:

class AddUserIdToPosts < ActiveRecord::Migration[6.1]
  def change
    add_column :posts, :user_id, :integer
  end
end

শেষে, মাইগ্রেশন চালান:

rails db:migrate

এরপর, আমরা মডেলগুলোতে অ্যাসোসিয়েশন যোগ করব। app/models/post.rb-এ নিচের লাইনটি যোগ করুন:

belongs_to :user

এবং app/models/user.rb-এ নিচেরটি যোগ করুন:

has_many :posts

এই বাইডিরেকশনাল অ্যাসোসিয়েশন আমাদের কিছু হ্যান্ডি রেইলস মেথড দেয়, যেগুলো আমরা create এবং new মেথডে ব্যবহার করতে যাচ্ছি। app/controllers/posts_controller.rb (posts কন্ট্রোলার) নেভিগেট করুন এবং new মেথডটি দেখুন। @post = Post.new এর বদলে @post = current_user.posts.build ব্যবহার করুন।

create মেথডে, আমরা কিছু সিমিলার করব। @post = Post.new(post_params) কে @post = current_user.posts.build(post_params) দিয়ে রিপ্লেস করুন। একসাথে, new এবং create মেথডগুলো এমন দেখাবে:

# GET /posts/new
def new
  @post = current_user.posts.build
end

# POST /posts or /posts.json
def create
  @post = current_user.posts.build(post_params)
  respond_to do |format|
    if @post.save
      format.html { redirect_to @post, notice: "Post was successfully created." }
      format.json { render :show, status: :created, location: @post }
    else
      format.html { render :new, status: :unprocessable_entity }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

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

def user_owns_post?
  @post.user == current_user
end

edit মেথডে, নিচের কোডটি যোগ করুন (এটি সেখানে একমাত্র কোড হবে):

unless user_owns_post?
  # Redirect them to an error page
  redirect_to posts_path, flash: { error: "You are not the owner of that post!" }
end

destroy মেথডে, শুরুর দিকে এটি যোগ করুন:

unless user_owns_post?
  # Redirect them to an error page
  redirect_to posts_path, flash: { error: "You are not the owner of that post!" }
end

এরপর, আমাদের একটি ইউজারের তাদের এক্সিস্টিং পোস্ট ম্যানেজ করার ফাংশন্যালিটি লাগবে। এন্ড গোল হলো একজন ইউজার পোস্ট তৈরি করতে পারবে এবং পেমেন্ট করার আগে এটি ড্রাফ্ট স্টেটে থাকবে। একবার তারা পেমেন্ট করলে, এটি তাদের জন্য এক্টিভ হবে! PostsController-এ, একটি নতুন মেথড যোগ করুন:

def manage
  @posts = current_user.posts
end

এরপর, একটি রুট যোগ করুন যাতে ইউজার সেখানে পৌঁছাতে পারে! config/routes.rb-এ, নিচেরটি যোগ করুন:

get "/manage_posts/" =>'posts#manage'

শেষে, আমরা পোস্ট ম্যানেজমেন্টের জন্য ভিউ তৈরি করব! একটি নতুন ফাইল যোগ করুন, app/views/posts/manage.html.erb। তারপর, app/views/posts/index.html.erb-এর সম্পূর্ণ কন্টেন্ট কপি করে সেখানে পেস্ট করুন। শুধু হেডার "Posts" থেকে "Manage Posts" এ পরিবর্তন করুন। এটি এসেনশিয়ালি একটি ইনডেক্স পেজ, কিন্তু আমাদের কন্ট্রোলার লজিকের কারনে শুধু একটি নির্দিষ্ট ইউজারের পোস্টগুলো ইনডেক্সড। টেকনিক্যালি, আমরা এটি ইন্ডিভিজুয়াল ইনডেক্স পেজেও করতে পারতাম, কিন্তু এই সেপারেশন পরবর্তীতে অন্যান্য ফাংশন্যালিটি যোগ করা সহজ করবে। উদাহরণস্বরূপ, আমরা এখন এই ম্যানেজমেন্ট পেজে একটি নতুন পোস্ট তৈরি করার লিংক যোগ করব।

হেডারের নিচে, সিম্পলি নিচেরটি যোগ করুন:

<%= link_to "New Post", new_post_url%>

এই ছিল সেটআপের জন্য সব প্রয়োজনীয়! সবকিছু প্রপারলি কাজ করছে কিনা যাচাই করার জন্য একবার গিয়ে আসা ভালো Idee। আপনাকে এখন নিচের কাজগুলো করতে পারা উচিত:

  • ইউজার অ্যাকাউন্ট তৈরি করা
  • সাইন ইন
  • সাইন আউট
  • এক্সিস্টিং পোস্টিংর ইনডেক্স দেখা
  • নতুন পোস্টিং তৈরি করা

যদি সবকিছু আপনার এক্সপেক্টেশন অনুযায়ী কাজ করে, তবে স্ট্রাইপ ইন্টিগ্রেশনে যাওয়ার টাইম!

স্ট্রাইপ ইন্টিগ্রেশন (Stripe Integration)

স্ট্রাইপ রুবি জেম যোগ করা

শুরু করতে, আমরা শুধু স্ট্রাইপ রুবি জেম যোগ করব। আপনার Gemfile-এ নিচের লাইনটি যোগ করুন:

gem 'stripe'

তারপর চালান:

bundle install

পরবর্তী অংশের জন্য, আপনাকে আপনার স্ট্রাইপ API কী লাগবে। স্ট্রাইপ কনসোলে, সাইডবারে "Developer"-এ ক্লিক করুন। "API Keys" অপশনটি দেখাবে, সেটাতে ক্লিক করুন। আপনার "Secret Key" নোট করুন, আমাদের তা শীঘ্রই লাগবে।

কিন্তু প্রথমে, config/initializers-এ একটি ইনিশিয়ালাইজার তৈরি করুন। stripe.rb নামে একটি তৈরি করুন। এই ফাইলে, একটি সিঙ্গেল লাইন যোগ করুন যা এমন দেখাবে (আপনার সিক্রেট কী স্ট্রিং হিসেবে সাবস্টিটিউট করে):

Stripe.api_key = 

স্ট্রাইপ ক্রেডেনশিয়াল সংরক্ষণ করা

এই পদ্ধতিতে আমাদের ক্রেডেনশিয়াল সংরক্ষণ করা ইনসিকিউর (insecure)। আমরা প্রোডাকশন সিক্রেটস প্লেইনটেক্সটে স্টোর করা উচিত না, যেখানে সেগুলো গিট (git) দ্বারা ট্র্যাক হয় এবং কোডবেস পড়ার যেকোনো কারো কাছে অ্যাক্সেসযোগ্য। সৌভাগ্যক্রমে, রেইলস ক্রেডেনশিয়াল সিকিউরলি স্টোর করার একটি উপায় প্রদান করে।

আপনার শেলে, EDITOR=vim bin/rails credentials:edit চালান ক্রেডেনশিয়াল ফাইলটি আনক্রিপ্ট করে ভিম (vim) এ খোলার জন্য। আপনার কীবোর্ডে 'i' কী টিপুন ইনসার্ট মোডে সুইচ করতে। একটি নতুন সেকশন যোগ করুন যেটি এমন দেখাবে:

stripe:
  secret: your-secret-key
  public: your-public-key

এরপর, ফাইলটি সেভ করুন এবং ভিম থেকে এক্সিট করুন। এটি করার কিছু উপায় রয়েছে, কিন্তু আমার ফেভারিট হলো escape কী টিপুন (ইনসার্ট মোড ছাড়ার জন্য) এবং তারপর টাইপ করুন :wq, এরপর এন্টার কী। আপনি যদি জানতে চান রেইলস কীভাবে এনক্রিপ্টেড ক্রেডেনশিয়াল হ্যান্ডেল করে, এটি একটি ভালো রিসোর্স।

এখন ক্রেডেনশিয়ালগুলো সফলভাবে স্টোর হয়েছে, ইনসিকিউর ইনিশিয়ালাইজার কোডকে নিচেরটি দিয়ে রিপ্লেস করুন:

Stripe.api_key = Rails.application.credentials[:stripe][:secret]

প্রোডাক্ট থেকে স্ট্রাইপ চেকআউট লিঙ্ক করা

স্ট্রাইপকে পেমেন্টের জন্য লিভারেজ করার কিছু ভিন্ন উপায় রয়েছে, কিন্তু একটি দুর্দান্ত অপশন হলো স্ট্রাইপ চেকআউট (Stripe Checkout)। স্ট্রাইপ চেকআউট একটি হোস্টেড পেমেন্ট পেজ (hosted payment page), অর্থাৎ আপনাকে আক্টুয়াল ট্রানজ্যাকশনের জন্য কোনো ইউজার ইন্টারফেস তৈরি করতে হয় না। একজন ইউজার একটি বাটনে ক্লিক করবে, স্ট্রাইপে রিডাইরেক্ট হবে, এবং পেমেন্ট সম্পন্ন হলে আবার আপনার অ্যাপ্লিকেশনে রিডাইরেক্ট হবে। এটি কনটেক্সট ম্যানেজ করা কিছুটা চ্যালেঞ্জিং করে তোলে, কিন্তু পেমেন্ট ফর্ম তৈরি করার বোঝা দূর করে এবং স্ট্রাইপকে কনভার্সন ম্যাক্সিমাইজ করার জন্য অনেক কাজ করার সুযোগ দেয়। আপনি সহজে কার্ড বাদে পেমেন্ট টাইপ এক্সেপ্ট করতে পারেন, যেমন ACH ট্রানজ্যাকশন বা অনেক ইন্টারন্যাশনাল পেমেন্ট মেথড।

শুরু করতে, চেকআউট প্রসেস হ্যান্ডেল করার জন্য একটি কন্ট্রোলার তৈরি করুন। app/controllers/checkout_controller.rb তৈরি করুন। এতে, আমরা একটি মেথড লিখব চেকআউট সেশন তৈরি হ্যান্ডেল করার জন্য।

def create
  @session = Stripe::Checkout::Session.create({
    success_url: root_url,
    cancel_url: manage_posts_url,
    payment_method_types: ['card'],
    line_items: [{
      name: "Roommate Posting",
      amount: 2000,
      currency: "usd",
      quantity: 1
    }],
    mode: 'payment',
    metadata: {post_id: params[:post_id]},
    customer_email: current_user.email,
    success_url: manage_posts_url,
    cancel_url: manage_posts_url
  })
  respond_to do |format|
    format.js
  end
end

এটি একটি চেকআউট সেশন তৈরি করে স্ট্রাইপের ম্যাজিক করার জন্য নেসেসারি কনটেক্সট সহ। আমরা একটি সিঙ্গেল লাইন আইটেম পাস করছি, যা আমরা এখানে হার্ডকোড করেছি যেহেতু আমাদের অ্যাপ্লিকেশনে শুধু একটি প্রোডাক্ট। কিন্তু এটি একটি সহজ জায়গা হবে একটি পাসড প্যারামিটার ব্যবহার করে চেকআউট কাস্টমাইজ করার জন্য একটি নির্দিষ্ট প্রোডাক্টের জন্য। "Amount" ভেরিয়েবলটি প্রোডাক্টের খরচ সেন্টে (in cents)। এটি মেনশন করা ওয়ার্চ যে আমরা করেন্ট ইউজারের ইমেইল পাস করছি সিম্পলিসিটির জন্য। লাস্ট 중요한 জিনিস হলো আমরা একটি পোস্টের আইডি metadata-এ পাস করছি। এটি আমাদের ইউজারের পারচেজ ফুলফিল (fulfill) করা সহজ করবে ওয়েবহুকস সেকশনে!

এরপর, আমাদের মেথডটি কল করার একটি উপায় লাগবে।

config/routes.rb-এ, নিচের লাইনটি যোগ করুন কন্ট্রোলারের জন্য একটি রুট তৈরি করতে।

post 'checkout/create' => 'checkout#create', as: "checkout_create"

এরপর, আমরা ম্যানেজ পোস্টস ভিউতে যেকোনো পোস্টের জন্য পেমেন্ট সাবমিট করার একটি বাটন যোগ করব। app/views/manage.html.erb-এ, হেডারে একটি এক্সট্রা কলাম যোগ করুন এটিকে লাস্টে যোগ করে:

<th>Payment</th>

এছাড়া, <th colspan="3"></th> কে <th colspan="4"></th> এ সুইচ করুন।

এরপর, টেবিল বডিতে পেমেন্ট বাটনটির জন্য আরেকটি আইটেম যোগ করুন। বডির চতুর্থ আইটেম হিসেবে, নিচেরটি যোগ করুন:

<td><%= button_to "Submit Payment", checkout_create_path, params: {:post_id => post.id }, remote: true %></td>

সারাশ, ম্যানেজ পোস্টস ভিউটি এখন এমন দেখাচ্ছে:

<p id="notice"><%= notice %></p>
<h1>Manage Posts</h1>
<%= link_to "New Post", new_post_url%>
<table>
  <thead>
    <tr>
      <th>Address</th>
      <th>Rent</th>
      <th>Content</th>
      <th>Payment</th>
      <th colspan="4"></th>
    </tr>
  </thead>
  <tbody>
    <% @posts.each do |post| %>
    <tr>
      <td><%= post.address %></td>
      <td><%= post.rent %></td>
      <td><%= post.content %></td>
      <td><%= button_to "Submit Payment", checkout_create_path, params: {:post_id => post.id }, remote: true %></td>
      <td><%= link_to 'Show', post %></td>
      <td><%= link_to 'Edit', edit_post_path(post) %></td>
      <td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
    </tr>
    <% end %>
  </tbody>
</table>
<br>
<%= link_to 'New Post', new_post_path %>

JavaScript

স্ট্রাইপ জাভাস্ক্রিপ্ট প্যাকেজ ইনক্লুড যোগ করতে ভুলবেন না app/views/application.html.erb-এ এই লাইন দিয়ে:

<script src="https://js.stripe.com/v3/"></script>

এরপর, আপনাকে একটি নতুন ফাইল (এবং ডিরেক্টরি!) যোগ করতে হবে app/views/checkout/create.js.erb-এ। এই ফাইলে, শুধু নিচের কোডটি যোগ করুন যাতে বাটনে ক্লিক করলে কন্ট্রোলারের সাহায্যে চেকআউট সেশন তৈরি হয়।

var stripe = Stripe("<%= Rails.application.credentials[:stripe][:public] %>")
stripe.redirectToCheckout({ sessionId: '<%= @session.id %>' }).then(function (result) {
  console.log(result.error_message)
});

ওয়েবহুকস সেটআপ করা

এখন, আমাদের কাছে ইউজাররা পোস্টের জন্য পেমেন্ট করার একটি উপায় আছে! যাইহোক, আমাদের কাছে অ্যাপ্লিকেশন জানার কোনো উপায় নেই কোন পোস্ট পেইড (paid) হয়েছে কিনা বা পেইড হলে সেটি অ্যাক্টিভেট করা। শুরুতে, পোস্ট মডেলে একটি বুলিয়ান (Boolean) যোগ করুন পোস্টটি পেইড হয়েছে কিনা ইন্ডিকেট করার জন্য। রেইলস মাইগ্রেশন জেনারেটর ব্যবহার করতে, চালান:

rails g migration AddPaymentDetailsToPost

এই মাইগ্রেশনটি খুলুন এবং নিচের লাইনটি যোগ করুন:

add_column :posts, :is_paid, :boolean, :default => false

এটি পোস্টস টেবিল/মডেলে একটি অ্যাট্রিবিউট/কলাম যোগ করে is_paid নামে। এই অ্যাট্রিবিউট একটি বুলিয়ান যা ডিফল্ট false, অর্থাৎ যখনই একটি পোস্ট তৈরি হয়, এটি মার্ক করা হয় পেইড নয়। যখন একটি পোস্ট পেইড হয়, আমরা ম্যানুয়ালি বুলিয়ান ফ্লিপ করব। কিন্তু প্রথমে, আপনার লিখা মাইগ্রেশনটি চালান:

rails db:migrate

যেহেতু পেমেন্ট ইনস্ট্যান্টলি প্রসেস হয় না, আমরা স্ট্রাইপ থেকে সফল API রেসপন্সের উপর নির্ভর করতে পারি না একটি জব পেইড হয়েছে কিনা নির্ধারণ করতে। বদলে, আমরা আমাদের অ্যাপ্লিকেশনের একটি এন্ডপয়েন্ট ইন্ডিকেট করতে পারি স্ট্রাইপকে যাতে পেমেন্ট প্রসেসিং শেষ হলে একটি POST রিকোয়েস্ট করে। এই প্রসেসটিকে সাধারণত ওয়েবহুকস (webhooks) বলা হয় এবং আসলে এটি শোনার চেয়ে সহজ!

শুরু করতে, app/controllers/-এ একটি নতুন কন্ট্রোলার তৈরি করুন WebhooksController নামে। এই app/controllers/webhooks_controller.rb-এ, নিচের কোডটি লিখুন:

class WebhooksController < ApplicationController
  skip_before_action :verify_authenticity_token
  def create
    payload = request.body.read
    sig_header = request.env['HTTP_STRIPE_SIGNATURE']
    event = nil
    begin
      event = Stripe::Webhook.construct_event(
        payload,
        sig_header,
        Rails.application.credentials[:stripe][:webhook]
      )
    rescue JSON::ParserError => e
      status 400
      return
    rescue Stripe::SignatureVerificationError => e
      # Invalid signature
      puts "Signature error"
      p e
      return
    end
    # Handle the event
    case event.type
    when 'checkout.session.completed'
      session = event.data.object
      post = Post.find_by(id: session.metadata.post_id)
      post.is_paid = true
      post.save!
    end
    render json: { message: 'success' }
  end
end

নেসেসারি বয়লারপ্লেট ছাড়া, এই মেথড একটি স্পেসিফিক ইভেন্ট টাইপ হ্যান্ডেল করবে, যেটি checkout.session.completed নামে। রেইলস সাইডে বাকি কাজ হলো config/routes.rb-এ রুট যোগ করা:

resources :webhooks, only: [:create]

শেষে, আপনাকে আপনার স্ট্রাইপ অ্যাকাউন্টকে এই এন্ডপয়েন্টের সাথে কনেক্ট করতে হবে স্ট্রাইপ ড্যাশবোর্ডে। কারণ আপনাকে স্ট্রাইপ ড্যাশবোর্ডে একটি URL সাপ্লাই করতে হবে, এটি লোকালি কাজ করবে না! আপনাকে অবশ্যই এটি একটি ইন্টারনেট-অ্যাক্সেসিবল এন্ডপয়েন্টে ডিপ্লয় করতে হবে ওয়েবহুকস কাজ করার জন্য।

"Developers"-এ ফিরে যান স্ট্রাইপ ড্যাশবোর্ডে, কিন্তু এই বার, বাম প্যানেলে "Webhooks"-এ সিলেক্ট করুন। "Endpoints" সেকশনে, "Add Endpoint"-এ ক্লিক করুন। আপনার অ্যাপ্লিকেশনের URL /webhooks অ্যেন্ড করে সাপ্লাই করুন এবং ইভেন্ট "checkout.session.completed" অ্যাসাইন করুন।

এই ছিল স্ট্রাইপ ইন্টিগ্রেশনের জন্য সব! আমাদের মক অ্যাপ্লিকেশনের লাস্ট প্র্যাকটিক্যাল ধাপ হলো ইনডেক্স পেজ শুধু পেইড পোস্টগুলো ডিসপ্লে করবে। এটি সহজে করা যায় app/controllers/posts_controller.rb-এর index মেথডে। মেথডটি এভাবে পরিবর্তন করুন:

def index
  @posts = Post.where(:is_paid => true)
end

এখন, ব্যবহারকারীরা একটি পোস্ট তৈরি করতে পারবে, স্ট্রাইপ চেকআউট দিয়ে পেমেন্ট করতে পারবে, এবং এটি অটোমেটিক্যালি অ্যাপ্লিকেশনের হোমপেজে ডিসপ্লে হবে!

প্রোডাকশনে সুইচ করা

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

খুব সম্ভব আপনার ইনিশিয়াল সেটআপে আপনি স্ট্রাইপের টেস্ট কীগুলো ব্যবহার করেছেন। যদি আপনি করে থাকেন, স্ট্রাইপ ড্যাশবোর্ডের API Keys সেকশন এমন দেখাবে।

স্ট্রাইপ চেকআউট (Stripe Checkout) দিয়ে রেইলসে সিমলেস ওয়ান-টাইম পারচেজ ইন্টিগ্রেশন স্ট্রাইপ ড্যাশবোর্ড API Keys-এর স্ক্রিনশট

সিম্পলি "viewing test data" এর বगलındaki টগল ক্লিক করুন আপনার প্রোডাকশন সিক্রেট এবং পাবলিক কী রিভিল করতে। আপনাকে রেইলস ক্রেডেনশিয়াল ম্যানেজার আগের মত খুলতে হবে এবং টেস্ট কীগুলো রিপ্লেস করতে হবে প্রোডাকশন কী দিয়ে আপনার অ্যাপ্লিকেশন লাইভ ডেটা প্রসেস করতে। টেস্ট এনভায়রনমেন্ট সাহায্যকারী, যাইহোক, ফেক ক্রেডিট কার্ড নম্বর দিয়ে টেস্ট ট্রানজ্যাকশন রান করার জন্য। আপনার যদি একাধিক এনভায়রনমেন্ট থাকে বা এটি często সুইচ করার প্ল্যান থাকে, ক্রেডেনশিয়াল ম্যানেজারে আরেকটি key/value pair তৈরি করা ওয়ার্চ এবং ডাইনামিক্যালি আপনার কোডে ব্যবহার করা।

উপসংহার

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

Stripe Payment Links স্ট্রাইপের একটি ব্র্যান্ড-নিউ প্রোডাক্ট যেটি আমাদের চেকআউট ইন্টিগ্রেশনকে প্রায় অপ্রয়োজনীয় করতে পারে। আমরা যা করলাম সেটি ছিল ইউজারকে একটি হোস্টেড চেকআউট পেজে রিডাইরেক্ট করা, এবং একটি সিম্পল লিংক সেটাকে আরও সহজ করতে পারে। পেমেন্ট লিংকস একটি নো-কোড সলিউশন যা রিটেলারদের দিকে টার্গেটেড মনে হয় কিন্তু পটেনশিয়ালি এই ইউজ কেসের জন্যও কাজ করতে পারে। রেগার্ডলেস, স্ট্রাইপ চেকআউট এখনো কিছুটা বেশি ফ্লেক্সিবিলিটি এবং মার্কেটপ্লেসে অ্যাডপশন বoste, তাই এটি পুরোপুরি বুঝা গুরুত্বপূর্ণ।

অনেক বিজনেস যা সাথে লড়াই করে সেটি হলো ট্যাক্স হ্যান্ডল করা, বিশেষত ইন্টারন্যাশনালি। স্ট্রাইপ সম্প্রতি একটি নতুন ফিচার אינ্ট্রোডিউস করেছে যা এটি বিজনেসের জন্য অটোমেটিক্যালি হ্যান্ডেল করবে, কিন্তু এটি এখনো বেটা। একবার উপলব্ধ হলে, এটি স্ট্রাইপ ব্যবহার করে পেমেন্ট প্রসেসিং করা যেকোনো কাউন্টের একাউন্টিং বোঝা অনেক হ্রাস করবে!

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

  1. রেলসে ফ্ল্যাশ মেসেজ মাস্টার করুন: একটি সম্পূর্ণ গাইড

  2. পাওয়ারফুল রুবি CLI টুল বিল্ড করুন: একটি স্টেপ-বাই-স্টেপ গাইড

  3. রুবি পার্সিং মास্টার: স্ক্র্যাচ থেকে নিজস্ব পার্সার বানান

  4. রেইলসে OmniAuth-Twitter দিয়ে টুইটার লগইন ইন্টিগ্রেট করুন: ধাপে ধাপে গাইড