Mengintegrasikan Metode Pembayaran Stripe dan PayPal di Ruby on Rails

Diterbitkan: 2022-03-11

Fitur utama untuk perusahaan eCommerce besar seperti AliExpress, Ebay, dan Amazon adalah cara yang aman untuk menangani pembayaran, yang penting untuk bisnis mereka. Jika fitur ini gagal, konsekuensinya akan sangat menghancurkan. Ini berlaku untuk para pemimpin industri dan pengembang Ruby on Rails yang mengerjakan aplikasi eCommerce.

Keamanan siber sangat penting untuk mencegah serangan, dan cara untuk membuat proses transaksi lebih aman adalah dengan meminta layanan pihak ketiga untuk menanganinya. Menyertakan gateway pembayaran dalam aplikasi Anda adalah cara untuk mencapai tujuan ini, karena mereka menyediakan otorisasi pengguna, enkripsi data, dan dasbor sehingga Anda dapat mengikuti status transaksi dengan cepat.

Ada berbagai layanan gateway pembayaran di web, tetapi dalam artikel ini, saya akan berfokus pada integrasi Stripe dan PayPal ke aplikasi Rails. Untuk menyebutkan beberapa lainnya: Pembayaran Amazon, Square, SecurePay, WorldPay, Authorize.Net, 2Checkout.com, Braintree, Amazon, atau BlueSnap.

Cara Kerja Integrasi Gateway Pembayaran

Representasi umum untuk transaksi yang melibatkan gateway pembayaran
Representasi umum untuk transaksi yang melibatkan gateway pembayaran

Secara umum, akan ada formulir/tombol di aplikasi Anda di mana pengguna dapat masuk/memasukkan data kartu kredit. PayPal dan Stripe telah membuat langkah pertama ini lebih aman dengan menggunakan formulir iframe atau popups yang mencegah aplikasi Anda menyimpan informasi kartu kredit pengguna yang sensitif karena mereka akan mengembalikan token yang mewakili transaksi ini. Beberapa pengguna juga mungkin sudah merasa lebih percaya diri untuk memproses pembayaran dengan mengetahui bahwa ada layanan pihak ketiga yang menangani proses transaksi, sehingga ini juga dapat menjadi daya tarik aplikasi Anda.

Setelah mengautentikasi info pengguna, gateway pembayaran akan mengonfirmasi pembayaran dengan menghubungi pemroses pembayaran yang berkomunikasi dengan bank untuk menyelesaikan pembayaran. Ini memastikan bahwa transaksi didebit/dikreditkan dengan benar.

Stripe menggunakan formulir kartu kredit yang menanyakan nomor kartu kredit, cvv, dan tanggal kedaluwarsa. Jadi pengguna harus mengisi informasi kartu kredit di input Stripe yang diamankan. Setelah memberikan informasi ini, bagian belakang aplikasi Anda memproses pembayaran ini melalui token.

Tidak seperti Stripe, PayPal mengarahkan pengguna ke halaman login PayPal. Pengguna mengotorisasi dan memilih metode pembayaran melalui PayPal, dan sekali lagi, bagian belakang Anda akan menangani token alih-alih data sensitif pengguna.

Penting untuk disebutkan bahwa, untuk kedua gateway pembayaran ini, bagian belakang Anda harus meminta untuk melanjutkan eksekusi transaksi melalui API Stripe atau PayPal yang akan memberikan respons OK/NOK, jadi aplikasi Anda harus mengarahkan pengguna ke halaman yang berhasil atau salah.

Maksud dari artikel ini adalah untuk memberikan panduan cepat untuk mengintegrasikan kedua gateway pembayaran ini dalam satu aplikasi. Untuk semua pengujian, kami akan menggunakan kotak pasir dan akun pengujian yang disediakan oleh Stripe dan PayPal untuk mensimulasikan pembayaran.

Mempersiapkan

Sebelum mengintegrasikan gateway pembayaran, kami akan melakukan pengaturan untuk menginisialisasi aplikasi dengan menambahkan permata, tabel database, dan halaman indeks. Proyek ini dibuat menggunakan Rails versi 5.2.3 dan Ruby 2.6.3.

Catatan: Anda dapat melihat fitur Rails 6 baru di artikel terbaru kami.

Langkah 1: Inisialisasi aplikasi Rails.

Inisialisasi proyek dengan menjalankan inisialisasi proyek dengan perintah rails dengan nama aplikasi Anda:

 rails new YOUR_APP_NAME

Dan cd di folder aplikasi Anda.

Langkah 2: Instal permata.

Selain permata Stripe dan PayPal, beberapa permata lain ditambahkan:

  • devise : digunakan untuk otentikasi dan otorisasi pengguna
  • haml : alat templating untuk merender halaman pengguna
  • jquery-rails : untuk jquery di skrip front-end
  • money-rails : untuk menampilkan nilai uang yang diformat

Tambahkan ke Gemfile Anda:

 gem "devise", ">= 4.7.1" gem "haml" gem "jquery-rails" gem "money-rails"

Setelah menambahkannya, jalankan di CLI Anda:

 bundle install

Langkah 3: Inisialisasi permata.

Beberapa permata ini akan memerlukan inisialisasi selain menginstalnya melalui bundle .

Menginstal merancang:

 rails g devise:install

Inisialisasi money-rails :

 rails g money_rails:initializer

Inisialisasi jquery-rails dengan menambahkan ke bagian bawah app/assets/javascripts/application.js berikut ini:

 //= require jquery //= require jquery_ujs

Langkah 4: Tabel dan migrasi

Tiga tabel akan digunakan dalam proyek ini Pengguna , Produk , dan Pesanan .

  • Users : Akan dihasilkan melalui perangkat
  • Kolom Products :
    • name
    • price_cents
    • Stripe_plan_name : ID yang mewakili paket langganan yang dibuat di Stripe, sehingga pengguna dapat berlangganan. Bidang ini hanya diperlukan untuk produk yang terkait dengan rencana Stripe.
    • paypal_plan_name : Sama dengan stripe_plan_name tetapi untuk PayPal
  • Kolom Orders :
    • product_id
    • user_id
    • status : Ini akan menginformasikan jika pesanan tertunda, gagal, atau dibayar.
    • token : Ini adalah token yang dihasilkan dari API (baik Stripe atau PayPal) untuk menginisialisasi transaksi.
    • price_cents : Mirip dengan produk, tetapi digunakan untuk membuat nilai ini tetap ada dalam catatan pesanan
    • payment_gateway : Menyimpan gateway pembayaran mana yang digunakan untuk pesanan PayPal atau Stripe
    • customer_id : Ini akan digunakan untuk Stripe untuk menyimpan pelanggan Stripe untuk langganan, dan akan dijelaskan lebih detail di bagian selanjutnya.

Untuk menghasilkan tabel ini, beberapa migrasi harus dibuat:

Untuk membuat tabel Pengguna . Lari:

 rails g devise User

Untuk membuat tabel Produk . Hasilkan migrasi dengan menjalankan:

 rails generate migration CreateProducts name:string stripe_plan_name:string paypal_plan_name:string

Buka file migrasi yang Anda buat, yang seharusnya berada di db/migrate/ , dan buat perubahan agar migrasi Anda terlihat seperti ini:

 class CreateProducts < ActiveRecord::Migration[5.2] def change create_table :products do |t| t.string :name t.string :stripe_plan_name t.string :paypal_plan_name end add_money :products, :price, currency: { present: true } end end

Untuk membuat tabel Pesanan . Hasilkan migrasi dengan menjalankan:

 rails generate migration CreateOrders product_id:integer user_id:integer status:integer token:string charge_id:string error_message:string customer_id:string payment_gateway:integer

Sekali lagi, buka file migrasi yang Anda buat yang seharusnya berada di db/migrate/ dan buat perubahan pada file itu agar terlihat seperti ini:

 class CreateOrders < ActiveRecord::Migration[5.2] def change create_table :orders do |t| t.integer :product_id t.integer :user_id t.integer :status, default: 0 t.string :token t.string :charge_id t.string :error_message t.string :customer_id t.integer :payment_gateway t.timestamps end add_money :orders, :price, currency: { present: false } end end

Jalankan migrasi database dengan menjalankan:

 rails db:migrate

Langkah 5: Buat model.

Model pengguna sudah dibuat dari instalasi perangkat, dan tidak ada perubahan yang diperlukan untuk itu. Selain itu akan dibuat dua model yaitu Product dan Order .

Produk. Tambahkan file baru, app/models/product.rb , dengan:

 class Product < ActiveRecord::Base monetize :price_cents has_many :orders end

Memesan. Tambahkan file baru, app/models/order.rb , dengan:

 class Order < ApplicationRecord enum status: { pending: 0, failed: 1, paid: 2, paypal_executed: 3} enum payment_gateway: { stripe: 0, paypal: 1 } belongs_to :product belongs_to :user scope :recently_created, -> { where(created_at: 1.minutes.ago..DateTime.now) } def set_paid self.status = Order.statuses[:paid] end def set_failed self.status = Order.statuses[:failed] end def set_paypal_executed self.status = Order.statuses[:paypal_executed] end end

Langkah 6: Isi database.

Seorang pengguna dan dua produk akan dibuat di konsol. Catatan pesanan akan dibuat sesuai dengan tes pembayaran.

  • Jalankan rails s
  • Di browser Anda, kunjungi http://localhost:3000
  • Anda akan diarahkan ke halaman pendaftaran.
  • Daftarkan pengguna dengan mengisi alamat email dan kata sandi mereka.
  • Di terminal Anda, log berikut akan diminta untuk menunjukkan bahwa pengguna telah dibuat di database Anda:
 User Create (0.1ms) INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at") VALUES (?, ?, ?, ?) …
  • Buat dua produk tanpa langganan dengan menjalankan rails c dan menambahkan:
    • Product.create(name: "Awesome T-Shirt", price_cents: 3000)
    • Product.create(name: "Awesome Sneakers", price_cents: 5000)

Langkah 7: Buat halaman indeks

Halaman utama untuk proyek ini mencakup pemilihan produk untuk pembelian atau langganan. Selain itu, ia juga memiliki bagian untuk pemilihan metode pembayaran (Stripe atau PayPal). Tombol kirim juga digunakan untuk setiap jenis gateway pembayaran karena untuk PayPal kami akan menambahkan desain tombolnya sendiri melalui pustaka JavaScript-nya.

Pertama, buat rute untuk index dan submit di config/routes.rb .

 Rails.application.routes.draw do devise_for :users get '/', to: 'orders#index' post '/orders/submit', to: 'orders#submit' end

Buat dan tambahkan index tindakan dan submit di app/controllers/orders_controller.rb . orders#index action menyimpan dua variabel untuk dikonsumsi di front-end: @products_purchase yang memiliki daftar produk tanpa paket dan @products_subscription yang memiliki produk dengan paket PayPal dan Stripe.

 class OrdersController < ApplicationController before_action :authenticate_user! def index products = Product.all @products_purchase = products.where(stripe_plan_name:nil, paypal_plan_name:nil) @products_subscription = products - @products_purchase end def submit end end

Buat file di app/views/orders/index.html.haml . File ini berisi semua input yang akan kami kirim ke back end kami melalui metode submit, dan interaksi untuk gateway pembayaran dan pemilihan produk. Berikut adalah beberapa atribut nama masukan:

  • Orders[product_id] menyimpan id produk.
  • Orders[payment_gateway] berisi gateway pembayaran dengan nilai Stripe atau PayPal untuk yang lain.
 %div %h1 List of products = form_tag({:controller => "orders", :action => "submit" }, {:id => 'order-details'}) do %input{id:'order-type', :type=>"hidden", :value=>"stripe", :name=>'orders[payment_gateway]'} .form_row %h4 Charges/Payments - @products_purchase.each do |product| %div{'data-charges-and-payments-section': true} = radio_button_tag 'orders[product_id]', product.id, @products_purchase.first == product %span{id: "radioButtonName#{product.id}"} #{product.name} %span{id: "radioButtonPrice#{product.id}", :'data-price' => "#{product.price_cents}"} #{humanized_money_with_symbol product.price} %br %h4 Subscriptions - @products_subscription.each do |product| %div = radio_button_tag 'orders[product_id]', product.id, false %span{id: "radioButtonName#{product.id}"} #{product.name} %span{id: "radioButtonPrice#{product.id}", :'data-price' => "#{product.price_cents}"} #{humanized_money_with_symbol product.price} %br %hr %h1 Payment Method .form_row %div = radio_button_tag 'payment-selection', 'stripe', true, onclick: "changeTab();" %span Stripe %br %div = radio_button_tag 'payment-selection', 'paypal', false, onclick: "changeTab();" %span Paypal %br %br %div{id:'tab-stripe', class:'paymentSelectionTab active'} %div{id:'card-element'} %div{id:'card-errors', role:"alert"} %br %br = submit_tag "Buy it!", id: "submit-stripe" %div{id:'tab-paypal', class:'paymentSelectionTab'} %div{id: "submit-paypal"} %br %br %hr :javascript function changeTab() { var newActiveTabID = $('input[name="payment-selection"]:checked').val(); $('.paymentSelectionTab').removeClass('active'); $('#tab-' + newActiveTabID).addClass('active'); } :css #card-element { width:500px; } .paymentSelectionTab { display: none; } .paymentSelectionTab.active { display: block !important; }

Jika Anda menjalankan aplikasi Anda dengan rails s dan mengunjungi halaman Anda di http://localhost:3000 . Anda harus dapat melihat halaman sebagai berikut:

Halaman indeks mentah tanpa integrasi Stripe dan PayPal
Halaman indeks mentah tanpa integrasi Stripe dan PayPal

Penyimpanan Kredensial Gateway Pembayaran

Kunci PayPal dan Stripe akan disimpan dalam file yang tidak dilacak oleh Git. Ada dua jenis kunci yang disimpan dalam file ini untuk setiap gateway pembayaran, dan untuk saat ini, kami akan menggunakan nilai dummy untuk mereka. Petunjuk tambahan untuk membuat kunci ini disajikan di bagian selanjutnya.

Langkah 1: Tambahkan ini di .gitignore .

 /config/application.yml

Langkah 2: Buat file dengan kredensial Anda di config/application.yml . Itu harus berisi semua kotak pasir/kunci uji PayPal dan Stripe Anda untuk mengakses API ini.

 test: &default PAYPAL_ENV: sandbox PAYPAL_CLIENT_ID: YOUR_CREDENTIAL_HERE PAYPAL_CLIENT_SECRET: YOUR_CREDENTIAL_HERE STRIPE_PUBLISHABLE_KEY: YOUR_CREDENTIAL_HERE STRIPE_SECRET_KEY: YOUR_CREDENTIAL_HERE development: <<: *default

Langkah 3: Untuk menyimpan variabel dari file config/application.yml saat aplikasi dimulai, tambahkan baris ini di config/application.rb di dalam kelas Application sehingga mereka akan tersedia di ENV .

 config_file = Rails.application.config_for(:application) config_file.each do |key,value| ENV[key] = value end unless config_file.nil?

Konfigurasi Garis

Kami akan menambahkan permata untuk menggunakan Stripe API: stripe-rails . Membuat akun Stripe juga diperlukan agar tagihan dan langganan dapat diproses. Jika perlu, Anda dapat berkonsultasi dengan metode API untuk Stripe API di dokumentasi resmi.

Langkah 1: Tambahkan permata stripe-rails ke proyek Anda.

Permata stripe-rails akan menyediakan antarmuka untuk semua permintaan API yang digunakan dalam proyek ini.

Tambahkan ini di Gemfile :

 gem 'stripe-rails'

Lari:

 bundle install

Langkah 2: Buat kunci API Anda.

Untuk memiliki kunci API untuk berkomunikasi dengan Stripe, Anda harus membuat akun di Stripe. Untuk menguji aplikasi, dimungkinkan untuk menggunakan mode pengujian, jadi tidak ada info bisnis nyata yang harus diisi dalam proses pembuatan akun Stripe.

  • Buat akun di Stripe jika Anda belum memilikinya (https://dashboard.stripe.com/).
  • Saat masih di dasbor Stripe, setelah masuk, aktifkan Lihat Data Uji .
  • Di https://dashboard.stripe.com/test/apikeys, ganti YOUR_CREDENTIAL_HERE untuk nilai STRIPE_PUBLISHABLE_KEY dan STRIPE_SECRET_KEY di /config/application.yml dengan konten dari Publishable Key dan Secret key .

Langkah 3: Inisialisasi modul Stripe

Selain mengganti kunci, kita masih perlu menginisialisasi modul Stripe, agar menggunakan kunci yang sudah diatur di ENV kita.

Buat file di config/initializers/stripe.rb dengan:

 Rails.application.configure do config.stripe.secret_key = ENV["STRIPE_SECRET_KEY"] config.stripe.publishable_key = ENV["STRIPE_PUBLISHABLE_KEY"] end

Langkah 4: Integrasikan Stripe di ujung depan.

Kami akan menambahkan perpustakaan Stripe JavaScript dan logika untuk mengirim token yang mewakili informasi kartu kredit pengguna dan akan diproses di bagian belakang kami.

Dalam file index.html.haml , tambahkan ini ke bagian atas file Anda. Ini akan menggunakan modul Stripe (disediakan oleh permata) untuk menambahkan perpustakaan javascript Stripe ke halaman pengguna.

 = stripe_javascript_tag

Stripe menggunakan bidang input aman yang dibuat melalui API mereka. Karena dibuat dalam iframe yang dibuat melalui API ini, Anda tidak perlu khawatir tentang kemungkinan kerentanan yang menangani informasi kartu kredit pengguna. Selain itu, bagian belakang Anda tidak akan dapat memproses/menyimpan data sensitif pengguna apa pun, dan hanya akan menerima token yang mewakili informasi ini.

Bidang masukan ini dibuat dengan memanggil stripe.elements().create('card') . Setelah itu, Anda hanya perlu memanggil objek yang dikembalikan dengan mount() dengan meneruskan sebagai argumen id/kelas elemen HTML tempat input ini harus dipasang. Informasi lebih lanjut dapat ditemukan di Stripe.

Saat pengguna menekan tombol kirim dengan metode pembayaran Stripe, panggilan API lain yang mengembalikan janji dilakukan pada elemen kartu Stripe yang dibuat:

 stripe.createToken(card).then(function(result)

Variabel result dari fungsi ini, jika tidak memiliki kesalahan properti yang ditetapkan, akan memiliki token yang dapat diambil dengan mengakses atribut result.token.id . Token ini akan dikirim ke back end.

Untuk melakukan perubahan ini, ganti kode yang dikomentari // YOUR STRIPE AND PAYPAL CODE WILL BE HERE di index.html.haml dengan:

 (function setupStripe() { //Initialize stripe with publishable key var stripe = Stripe("#{ENV['STRIPE_PUBLISHABLE_KEY']}"); //Create Stripe credit card elements. var elements = stripe.elements(); var card = elements.create('card'); //Add a listener in order to check if card.addEventListener('change', function(event) { //the div card-errors contains error details if any var displayError = document.getElementById('card-errors'); document.getElementById('submit-stripe').disabled = false; if (event.error) { // Display error displayError.textContent = event.error.message; } else { // Clear error displayError.textContent = ''; } }); // Mount Stripe card element in the #card-element div. card.mount('#card-element'); var form = document.getElementById('order-details'); // This will be called when the #submit-stripe button is clicked by the user. form.addEventListener('submit', function(event) { $('#submit-stripe').prop('disabled', true); event.preventDefault(); stripe.createToken(card).then(function(result) { if (result.error) { // Inform that there was an error. var errorElement = document.getElementById('card-errors'); errorElement.textContent = result.error.message; } else { // Now we submit the form. We also add a hidden input storing // the token. So our back-end can consume it. var $form = $("#order-details"); // Add a hidden input orders[token] $form.append($('<input type="hidden" name="orders[token]"/>').val(result.token.id)); // Set order type $('#order-type').val('stripe'); $form.submit(); } }); return false; }); }()); //YOUR PAYPAL CODE WILL BE HERE

Jika Anda mengunjungi halaman Anda, itu akan terlihat seperti berikut dengan bidang input aman Stripe baru:

Halaman indeks terintegrasi dengan bidang input aman Stripe.
Halaman indeks terintegrasi dengan bidang input aman Stripe.

Langkah 5: Uji aplikasi Anda.

Isi formulir kartu kredit dengan kartu pengujian (https://stripe.com/docs/testing) dan kirimkan halaman. Periksa apakah tindakan submit dipanggil dengan semua parameter ( product_id , payment_gateway , dan token ) di output server Anda.

Biaya Garis

Biaya stripe mewakili transaksi satu kali. Oleh karena itu, setelah transaksi biaya Stripe, Anda akan menerima uang dari klien secara langsung. Ini sangat ideal untuk menjual produk yang tidak terkait dengan rencana. Di bagian selanjutnya, saya akan menunjukkan cara melakukan jenis transaksi yang sama dengan PayPal, tetapi nama PayPal untuk jenis transaksi ini adalah Pembayaran .

Di bagian ini saya juga akan menyediakan semua kerangka untuk menangani dan mengirimkan pesanan. Kami membuat pesanan dalam tindakan submit saat formulir Garis dikirimkan. Pesanan ini awalnya akan berstatus tertunda , jadi jika terjadi kesalahan saat memproses pesanan ini, pesanan akan tetap tertunda .

Jika ada kesalahan yang muncul dari panggilan API Stripe, kami menyetel pesanan dalam status gagal , dan jika tagihan berhasil diselesaikan, pesanan akan berada dalam status berbayar . Pengguna juga dialihkan sesuai dengan respons Stripe API seperti yang ditunjukkan pada grafik berikut:

Transaksi garis.
Transaksi garis.

Selain itu, ketika biaya Stripe dilakukan, ID dikembalikan. Kami akan menyimpan ID ini sehingga nanti Anda dapat mencarinya di dasbor Stripe Anda jika diperlukan. ID ini juga dapat digunakan jika pesanan harus dikembalikan. Hal seperti itu tidak akan dieksplorasi dalam artikel ini.

Langkah 1: Buat layanan Stripe.

Kami akan menggunakan kelas tunggal untuk mewakili operasi Stripe menggunakan API Stripe. Untuk membuat tagihan, metode Stripe::Charge.create dipanggil, dan atribut ID objek yang dikembalikan akan disimpan dalam catatan pesanan charge_id . Fungsi create ini dipanggil dengan melewatkan token yang berasal dari front end, harga pesanan, dan deskripsi.

Jadi, buat folder baru app/services/orders , dan tambahkan layanan Stripe: app/services/orders/stripe.rb yang berisi kelas tunggal Orders::Stripe , yang memiliki entri dalam metode execute .

 class Orders::Stripe INVALID_STRIPE_OPERATION = 'Invalid Stripe Operation' def self.execute(order:, user:) product = order.product # Check if the order is a plan if product.stripe_plan_name.blank? charge = self.execute_charge(price_cents: product.price_cents, description: product.name, card_token: order.token) else #SUBSCRIPTIONS WILL BE HANDLED HERE end unless charge&.id.blank? # If there is a charge with id, set order paid. order.charge_id = charge.id order.set_paid end rescue Stripe::StripeError => e # If a Stripe error is raised from the API, # set status failed and an error message order.error_message = INVALID_STRIPE_OPERATION order.set_failed end private def self.execute_charge(price_cents:, description:, card_token:) Stripe::Charge.create({ amount: price_cents.to_s, currency: "usd", description: description, source: card_token }) end end

Langkah 2: Terapkan tindakan kirim dan panggil layanan Stripe.

Di orders_controller.rb , tambahkan yang berikut ini dalam tindakan submit , yang pada dasarnya akan memanggil layanan Orders::Stripe.execute . Perhatikan bahwa dua fungsi pribadi baru juga ditambahkan: prepare_new_order dan order_params .

 def submit @order = nil #Check which type of order it is if order_params[:payment_gateway] == "stripe" prepare_new_order Orders::Stripe.execute(order: @order, user: current_user) elsif order_params[:payment_gateway] == "paypal" #PAYPAL WILL BE HANDLED HERE end ensure if @order&.save if @order.paid? # Success is rendered when order is paid and saved return render html: SUCCESS_MESSAGE elsif @order.failed? && [email protected]_message.blank? # Render error only if order failed and there is an error_message return render html: @order.error_message end end render html: FAILURE_MESSAGE end private # Initialize a new order and and set its user, product and price. def prepare_new_order @order = Order.new(order_params) @order.user_id = current_user.id @product = Product.find(@order.product_id) @order.price_cents = @product.price_cents end def order_params params.require(:orders).permit(:product_id, :token, :payment_gateway, :charge_id) end

Langkah 3: Uji aplikasi Anda.

Periksa apakah tindakan kirim, saat dipanggil dengan kartu pengujian yang valid, melakukan pengalihan ke pesan yang berhasil. Selain itu, periksa di dasbor Stripe Anda jika pesanan juga ditampilkan.

Berlangganan Garis

Langganan atau paket dapat dibuat untuk pembayaran berulang. Dengan produk jenis ini, pengguna dikenakan biaya harian, mingguan, bulanan atau tahunan secara otomatis sesuai dengan konfigurasi paket. Pada bagian ini, kita akan menggunakan field product stripe_plan_name untuk menyimpan ID plan—sebenarnya kita bisa memilih ID tersebut, dan kita akan menyebutnya sebagai premium-plan —yang akan digunakan untuk membuat customer <-> subscription .

Kami juga akan membuat kolom baru untuk tabel pengguna bernama stripe_customer_id yang akan diisi dengan properti id dari objek pelanggan Stripe. Pelanggan Stripe dibuat saat fungsi Stripe::Customer.create dipanggil, dan Anda juga dapat memeriksa pelanggan yang dibuat dan ditautkan ke akun Anda di (https://dashboard.stripe.com/test/customers). Pelanggan dibuat dengan melewati parameter source yang, dalam kasus kami, adalah token yang dihasilkan di ujung depan yang dikirim saat formulir dikirimkan.

Objek pelanggan yang diperoleh dari panggilan API Stripe yang disebutkan terakhir, juga digunakan untuk membuat langganan yang dilakukan dengan memanggil customer.subscriptions.create dan meneruskan ID paket sebagai parameter.

Selain itu, permata stripe-rails menyediakan antarmuka untuk mengambil dan memperbarui pelanggan dari Stripe, yang dilakukan dengan memanggil Stripe::Customer.retrieve dan Stripe::Customer.update , masing-masing.

Jadi, ketika catatan pengguna sudah memiliki stripe_customer_id , alih-alih membuat pelanggan baru menggunakan Stripe::Customer.create , kami akan memanggil Stripe::Customer.retrieve dengan meneruskan stripe_customer_id sebagai parameter, diikuti oleh Stripe::Customer.update , dan dalam hal ini, meneruskan token sebuah parameter.

Pertama kita akan membuat rencana menggunakan API Stripe sehingga kita dapat membuat produk langganan baru menggunakan bidang stripe_plan_name . Setelah itu, kami akan melakukan modifikasi pada layanan orders_controller dan Stripe sehingga pembuatan dan eksekusi langganan Stripe dapat ditangani.

Langkah 1: Buat rencana menggunakan Stripe API.

Buka konsol Anda menggunakan rails c . Buat langganan untuk akun Stripe Anda dengan:

 Stripe::Plan.create({ amount: 10000, interval: 'month', product: { name: 'Premium plan', }, currency: 'usd', id: 'premium-plan', })

Jika hasil yang dikembalikan dalam langkah ini adalah benar, itu berarti rencana telah berhasil dibuat, dan Anda dapat mengaksesnya di dasbor Stripe Anda.

Langkah 2: Buat produk di database dengan set bidang stripe_plan_name .

Sekarang, buat produk dengan stripe_plan_name ditetapkan sebagai premium-plan di database:

 Product.create(price_cents: 10000, name: 'Premium Plan', stripe_plan_name: 'premium-plan')

Langkah 3: Buat migrasi untuk menambahkan kolom stripe_customer_id di tabel users .

Jalankan yang berikut ini di terminal:

 rails generate migration AddStripeCustomerIdToUser stripe_customer_id:string rails db:migrate

Langkah 4: Terapkan logika berlangganan di kelas layanan Stripe.

Tambahkan dua fungsi lagi dalam metode pribadi app/services/orders/stripe.rb : execute_subscription bertanggung jawab untuk membuat langganan di objek pelanggan. Fungsi find_or_create_customer bertanggung jawab untuk mengembalikan pelanggan yang sudah dibuat atau dengan mengembalikan pelanggan yang baru dibuat.

 def self.execute_subscription(plan:, token:, customer:) customer.subscriptions.create({ plan: plan }) end def self.find_or_create_customer(card_token:, customer_id:, email:) if customer_id stripe_customer = Stripe::Customer.retrieve({ id: customer_id }) if stripe_customer stripe_customer = Stripe::Customer.update(stripe_customer.id, { source: card_token}) end else stripe_customer = Stripe::Customer.create({ email: email, source: card_token }) end stripe_customer end

Terakhir, dalam fungsi execute di file yang sama ( app/services/orders/stripe.rb ), pertama-tama kita akan memanggil find_or_create_customer dan kemudian menjalankan langganan dengan memanggil execute_subscription dengan meneruskan pelanggan yang diambil/dibuat sebelumnya. Jadi, ganti komentar #SUBSCRIPTIONS WILL BE HANDLED HERE pada metode execute dengan kode berikut:

 customer = self.find_or_create_customer(card_token: order.token, customer_id: user.stripe_customer_id, email: user.email) if customer user.update(stripe_customer_id: customer.id) order.customer_id = customer.id charge = self.execute_subscription(plan: product.stripe_plan_name, customer: customer)

Langkah 5: Uji aplikasi Anda.

Kunjungi situs web Anda, pilih Paket Premium Plan produk langganan , dan isi kartu tes yang valid. Setelah mengirimkan, itu akan mengarahkan Anda ke halaman yang sukses. Selain itu, periksa di dasbor Stripe Anda jika langganan berhasil dibuat.

Konfigurasi PayPal

Seperti yang kami lakukan di Stripe, kami juga akan menambahkan permata untuk menggunakan API PayPal: paypal-sdk-rest , dan membuat akun PayPal juga diperlukan. Alur kerja deskriptif untuk PayPal yang menggunakan permata ini dapat dilihat di dokumentasi API PayPal resmi.

Langkah 1: Tambahkan permata paypal-sdk-rest ke proyek Anda.

Tambahkan ini di Gemfile :

 gem 'paypal-sdk-rest'

Lari:

 bundle install

Langkah 2: Buat kunci API Anda.

Untuk memiliki kunci API untuk berkomunikasi dengan PayPal, Anda harus membuat akun PayPal. Jadi:

  • Buat akun (atau gunakan akun PayPal Anda) di https://developer.paypal.com/.
  • Masih masuk ke akun Anda, buat dua akun kotak pasir di https://developer.paypal.com/developer/accounts/:
    • Pribadi (Akun Pembeli) – Ini akan digunakan dalam pengujian Anda untuk melakukan pembayaran dan langganan.
    • Bisnis (Akun Pedagang) – Ini akan ditautkan ke aplikasi, yang akan memiliki kunci API yang kita cari. Selain itu, semua transaksi dapat diikuti di akun ini.
  • Buat aplikasi di https://developer.paypal.com/developer/applications menggunakan akun sandbox bisnis sebelumnya.
  • Setelah langkah ini, Anda akan menerima dua kunci untuk PayPal: Client ID dan Secret .
  • Di config/application.yml , ganti YOUR_CREDENTIAL_HERE dari PAYPAL_CLIENT_ID dan PAYPAL_CLIENT_SECRET dengan kunci yang baru saja Anda terima.

Langkah 3: Inisialisasi modul PayPal.

Mirip dengan Stripe, selain mengganti kunci di application.yml , kita masih perlu menginisialisasi modul PayPal agar bisa menggunakan kunci yang sudah diatur di variabel ENV kita. Untuk tujuan ini, buat file di config/initializers/paypal.rb dengan:

 PayPal::SDK.configure( mode: ENV['PAYPAL_ENV'], client_id: ENV['PAYPAL_CLIENT_ID'], client_secret: ENV['PAYPAL_CLIENT_SECRET'], ) PayPal::SDK.logger.level = Logger::INFO

Langkah 4: Integrasikan PayPal di bagian depan.

Di index.html.haml tambahkan ini ke bagian atas file:

 %script(src="https://www.paypal.com/sdk/js?client-id=#{ENV['PAYPAL_CLIENT_ID']}")

Tidak seperti Stripe, PayPal hanya menggunakan tombol yang, ketika diklik, membuka sembulan aman tempat pengguna dapat masuk dan melanjutkan ke pembayaran/langganan. Tombol ini dapat dirender dengan memanggil metode paypal.Button(PARAM1).render(PARAM2) .

  • PARAM1 adalah objek dengan konfigurasi lingkungan dan dua fungsi panggilan balik sebagai properti: createOrder dan onApprove .
  • PARAM2 menunjukkan pengidentifikasi elemen HTML yang harus dilampirkan tombol PayPal.

Jadi, masih dalam file yang sama, ganti kode yang dikomentari YOUR PAYPAL CODE WILL BE HERE dengan:

 (function setupPaypal() { function isPayment() { return $('[data-charges-and-payments-section] input[name="orders[product_id]"]:checked').length } function submitOrderPaypal(chargeID) { var $form = $("#order-details"); // Add a hidden input orders[charge_id] $form.append($('<input type="hidden" name="orders[charge_id]"/>').val(chargeID)); // Set order type $('#order-type').val('paypal'); $form.submit(); } paypal.Buttons({ env: "#{ENV['PAYPAL_ENV']}", createOrder: function() { }, onApprove: function(data) { } }).render('#submit-paypal'); }());

Langkah 5: Uji aplikasi Anda.

Kunjungi halaman Anda dan periksa apakah tombol PayPal ditampilkan saat Anda memilih PayPal sebagai metode pembayaran.

Transaksi PayPal

Logika untuk transaksi PayPal, tidak seperti Stripe, sedikit lebih rumit dengan melibatkan lebih banyak permintaan yang berasal dari ujung depan hingga ujung belakang. Itu sebabnya bagian ini ada. Saya akan menjelaskan kurang lebih (tanpa kode apa pun) bagaimana fungsi yang dijelaskan dalam metode createOrder dan onApprove akan diimplementasikan dan apa yang diharapkan dalam proses back-end juga.

Langkah 1: Ketika pengguna mengklik tombol kirim PayPal, popup PayPal yang meminta kredensial pengguna terbuka tetapi dalam keadaan memuat. Fungsi callback createOrder dipanggil.

Munculan PayPal, status pemuatan
Munculan PayPal, status pemuatan

Langkah 2: Dalam fungsi ini, kami akan melakukan permintaan ke back-end kami yang akan membuat pembayaran/langganan. Ini adalah awal dari sebuah transaksi, dan belum ada biaya yang akan dikenakan, sehingga transaksi tersebut sebenarnya dalam status tertunda . Bagian belakang kami harus mengembalikan token kepada kami, yang akan dihasilkan menggunakan modul PayPal (disediakan melalui permata paypal-rest-sdk ).

Langkah 3: Masih dalam panggilan balik createOrder , kami mengembalikan token yang dihasilkan di back-end kami, dan Jika semuanya baik-baik saja, pop-up PayPal akan menampilkan yang berikut, meminta kredensial pengguna:

Munculan PayPal, kredensial pengguna
Munculan PayPal, kredensial pengguna

Langkah 4: Setelah pengguna login dan memilih metode pembayaran, popup akan berubah statusnya sebagai berikut:

Popup PayPal, transaksi resmi
Popup PayPal, transaksi resmi

Langkah 5: Panggilan balik fungsi onApprove sekarang dipanggil. Kami telah mendefinisikannya sebagai berikut: onApprove: function(data) . Objek data akan memiliki informasi pembayaran untuk mengeksekusinya. Dalam panggilan balik ini, permintaan lain ke fungsi back-end kami akan dilakukan kali ini dengan melewati objek data untuk menjalankan pesanan PayPal.

Langkah 6: Bagian belakang kami mengeksekusi transaksi ini dan mengembalikan 200 (jika berhasil).

Langkah 7: Ketika back end kami kembali, kami mengirimkan formulir. Ini adalah permintaan ketiga yang kami buat ke bagian belakang kami.

Perhatikan bahwa, tidak seperti Stripe, ada tiga permintaan yang dibuat ke back-end kami dalam proses ini. Dan kami akan terus menyinkronkan status catatan pesanan kami:

  • createOrder callback: Transaksi dibuat, dan catatan pesanan juga dibuat; oleh karena itu, statusnya tertunda sebagai default.
  • onApprove callback: Transaksi dijalankan dan pesanan kami akan ditetapkan sebagai paypal_executed .
  • Halaman pesanan dikirimkan: Transaksi sudah dijalankan, jadi tidak ada yang berubah. Catatan pesanan akan berubah statusnya menjadi dibayar .

Keseluruhan proses ini digambarkan dalam grafik berikut:

transaksi PayPal
transaksi PayPal

Pembayaran PayPal

Pembayaran PayPal mengikuti logika yang sama dengan Stripe Charges, jadi pembayaran tersebut mewakili transaksi satu kali, tetapi seperti yang disebutkan di bagian sebelumnya, pembayaran tersebut memiliki logika aliran yang berbeda. Ini adalah perubahan yang perlu dilakukan untuk menangani pembayaran PayPal:

Langkah 1: Buat rute baru untuk PayPal dan lakukan pembayaran.

Add the following routes in config/routes.rb :

 post 'orders/paypal/create_payment' => 'orders#paypal_create_payment', as: :paypal_create_payment post 'orders/paypal/execute_payment' => 'orders#paypal_execute_payment', as: :paypal_execute_payment

This will create two new routes for creating and executing payments which will be handled in the paypal_create_payment and paypal_execute_payment orders controller methods.

Step 2: Create the PayPal service.

Add the singleton class Orders::Paypal at: app/services/orders/paypal.rb .

This service will initially have three responsibilities:

  • The create_payment method creates a payment by calling PayPal::SDK::REST::Payment.new . A token is generated and returned to the front-end.
  • The execute_payment method executes the payment by first finding the previous created payment object through PayPal::SDK::REST::Payment.find(payment_id) which uses the payment_id as an argument which has the same value as the charge_id stored in the previous step in the order object. After that, we call execute in the payment object with a given payer as the parameter. This payer is given by the front end after the user has provided credentials and selected a payment method in the popup.
  • The finish method finds an order by a specific charge_id querying for recently created orders in the paypal_executed state. If a record is found, it is marked as paid.
 class Orders::Paypal def self.finish(charge_id) order = Order.paypal_executed.recently_created.find_by(charge_id: charge_id) return nil if order.nil? order.set_paid order end def self.create_payment(order:, product:) payment_price = (product.price_cents/100.0).to_s currency = "USD" payment = PayPal::SDK::REST::Payment.new({ intent: "sale", payer: { payment_method: "paypal" }, redirect_urls: { return_url: "/", cancel_url: "/" }, transactions: [{ item_list: { items: [{ name: product.name, sku: product.name, price: payment_price, currency: currency, quantity: 1 } ] }, amount: { total: payment_price, currency: currency }, description: "Payment for: #{product.name}" }] }) if payment.create order.token = payment.token order.charge_id = payment.id return payment.token if order.save end end def self.execute_payment(payment_id:, payer_id:) order = Order.recently_created.find_by(charge_id: payment_id) return false unless order payment = PayPal::SDK::REST::Payment.find(payment_id) if payment.execute( payer_id: payer_id ) order.set_paypal_executed return order.save end end

Step 3: Call the PayPal service in the controller in the submit action.

Add a callback for prepare_new_order before the action paypal_create_payment (which will be added in the next step) is requested by adding the following in the file app/controllers/orders_controller.rb :

 class OrdersController < ApplicationController before_action :authenticate_user! before_action :prepare_new_order, only: [:paypal_create_payment] ...

Again, in the same file, call PayPal service in the submit action by replacing the commented code #PAYPAL WILL BE HANDLED HERE. dengan berikut ini:

 ... elsif order_params[:payment_gateway] == "paypal" @order = Orders::Paypal.finish(order_params[:token]) end ...

Step 4: Create the actions for handling requests.

Still, in the app/controllers/orders_controller.rb file, create two new actions (which should be public) for handling requests to paypal_create_payment and paypal_execute_payment routes:

  • The paypal_create_payment method: Will call our service method create_payment . If that returns successfully, it will return the order token created by Orders::Paypal.create_payment .
  • The paypal_execute_payment method: Will call our service method execute_payment (which executes our payments). If the payment is performed successfully, it returns 200.
 ... def paypal_create_payment result = Orders::Paypal.create_payment(order: @order, product: @product) if result render json: { token: result }, status: :ok else render json: {error: FAILURE_MESSAGE}, status: :unprocessable_entity end end def paypal_execute_payment if Orders::Paypal.execute_payment(payment_id: params[:paymentID], payer_id: params[:payerID]) render json: {}, status: :ok else render json: {error: FAILURE_MESSAGE}, status: :unprocessable_entity end end ...

Step 5: Implement the front-end callback functions for createOrder and onApprove .

Make your paypal.Button.render call look like this:

 paypal.Buttons({ env: "#{ENV['PAYPAL_ENV']}", createOrder: function() { $('#order-type').val("paypal"); if (isPayment()) { return $.post("#{paypal_create_payment_url}", $('#order-details').serialize()).then(function(data) { return data.token; }); } else { } }, onApprove: function(data) { if (isPayment()) { return $.post("#{paypal_execute_payment_url}", { paymentID: data.paymentID, payerID: data.payerID }).then(function() { submitOrderPaypal(data.paymentID) }); } else { } } }).render('#submit-paypal');

As mentioned in the previous section, we call paypal_create_payment_url for the createOrder callback and paypal_execute_payment_url for the onApprove callback. Notice that if the last request returns success, we submit the order, which is the third request made to the server.

In the createOrder function handler, we return a token (obtained from the back end). In the onApprove callback, we have two properties passed down to our back-end paymentID and payerID . These will be used in order to execute the payment.

Finally, notice that we have two empty else clauses as I'm leaving room for the next section where we will be adding PayPal subscriptions.

If you visit your page after integrating the front-end JavaScript section and select PayPal as the payment method, it should look like the following:

Index page after integration with PayPal
Index page after integration with PayPal

Step 6: Test your application.

  • Kunjungi halaman indeks.
  • Pilih produk pembayaran/tagihan dan PayPal sebagai metode pembayaran.
  • Klik tombol kirim PayPal.
  • Di munculan PayPal:
    • Gunakan kredensial untuk akun pembeli yang Anda buat.
    • Masuk dan konfirmasi pesanan Anda.
    • Munculan harus ditutup.
  • Periksa apakah Anda diarahkan ke halaman sukses.
  • Terakhir, periksa apakah pesanan dilakukan di akun PayPal dengan masuk menggunakan akun bisnis Anda di https://www.sandbox.paypal.com/signin dan memeriksa dasbor https://www.sandbox.paypal.com/listing /transaksi.

Langganan PayPal

Paket/perjanjian/langganan PayPal mengikuti logika yang sama dengan langganan Stripe, dan dibuat untuk pembayaran berulang. Dengan produk jenis ini pengguna dikenakan biaya harian, mingguan, bulanan atau tahunan secara otomatis sesuai dengan konfigurasinya.

Kami akan menggunakan bidang untuk produk paypal_plan_name , untuk menyimpan ID paket yang disediakan oleh PayPal. Dalam hal ini, berbeda dari Stripe, kami tidak memilih ID, dan PayPal mengembalikan nilai ini yang akan digunakan untuk memperbarui produk terakhir yang dibuat di database kami.

Untuk membuat langganan, tidak ada informasi customer yang diperlukan dalam langkah apa pun, karena metode onApprove mungkin menangani hubungan ini dalam implementasi dasarnya. Jadi meja kita akan tetap sama.

Langkah 1: Buat rencana menggunakan API PayPal.

Buka konsol Anda menggunakan rails c . Buat langganan untuk akun PayPal Anda dengan:

 plan = PayPal::SDK::REST::Plan.new({ name: 'Premium Plan', description: 'Premium Plan', type: 'fixed', payment_definitions: [{ name: 'Premium Plan', type: 'REGULAR', frequency_interval: '1', frequency: 'MONTH', cycles: '12', amount: { currency: 'USD', value: '100.00' } }], merchant_preferences: { cancel_url: 'http://localhost:3000/', return_url: 'http://localhost:3000/', max_fail_attempts: '0', auto_bill_amount: 'YES', initial_fail_amount_action: 'CONTINUE' } }) plan.create plan_update = { op: 'replace', path: '/', value: { state: 'ACTIVE' } } plan.update(plan_update)

Langkah 2: Update produk terakhir di database paypal_plan_name dengan plan.id yang dikembalikan.

Lari:

 Product.last.update(paypal_plan_name: plan.id)

Langkah 3: Tambahkan rute untuk berlangganan PayPal.

Tambahkan dua rute baru di config/routes.rb :

 post 'orders/paypal/create_subscription' => 'orders#paypal_create_subscription', as: :paypal_create_subscription post 'orders/paypal/execute_subscription' => 'orders#paypal_execute_subscription', as: :paypal_execute_subscription

Langkah 4: Tangani pembuatan dan eksekusi di layanan PayPal.

Tambahkan dua fungsi lagi untuk membuat dan menjalankan langganan di Orders::Paypal dari app/services/orders/paypal.rb :

 def self.create_subscription(order:, product:) agreement = PayPal::SDK::REST::Agreement.new({ name: product.name, description: "Subscription for: #{product.name}", start_date: (Time.now.utc + 1.minute).iso8601, payer: { payment_method: "paypal" }, plan: { id: product.paypal_plan_name } }) if agreement.create order.token = agreement.token return agreement.token if order.save end end def self.execute_subscription(token:) order = Order.recently_created.find_by(token: token) return false unless order agreement = PayPal::SDK::REST::Agreement.new agreement.token = token if agreement.execute order.charge_id = agreement.id order.set_paypal_executed return order.charge_id if order.save end end

Dalam create_subscription , kami menginisialisasi perjanjian dengan memanggil metode PayPal::SDK::REST::Agreement.new dan meneruskan product.paypal_plan_name sebagai salah satu atributnya. Setelah itu, kita buat, dan sekarang token akan ditetapkan untuk objek terakhir ini. Kami juga mengembalikan token ke ujung depan.

Dalam execute_subscription , kami menemukan catatan order yang dibuat pada panggilan sebelumnya. Setelah itu, kami menginisialisasi perjanjian baru, kami menetapkan token objek sebelumnya ini dan menjalankannya. Jika langkah terakhir ini berhasil dilakukan, status pesanan diatur ke paypal_executed . Dan sekarang kita kembali ke front end ID perjanjian yang juga disimpan di order.chager_id .

Langkah 5: Tambahkan tindakan untuk membuat dan menjalankan langganan di orders_controller .

Ubah app/controllers/orders_controller.rb . Di bagian atas Kelas, pertama, lalu perbarui callback prepare_new_order untuk juga dieksekusi sebelum paypal_create_subscription dipanggil:

 class OrdersController < ApplicationController before_action :authenticate_user! before_action :prepare_new_order, only: [:paypal_create_payment, :paypal_create_subscription]

Juga, dalam file yang sama tambahkan dua fungsi publik sehingga mereka memanggil Layanan Orders::Paypal dengan aliran yang sama seperti yang sudah kita miliki di pembayaran PayPal:

 ... def paypal_create_subscription result = Orders::Paypal.create_subscription(order: @order, product: @product) if result render json: { token: result }, status: :ok else render json: {error: FAILURE_MESSAGE}, status: :unprocessable_entity end end def paypal_execute_subscription result = Orders::Paypal.execute_subscription(token: params[:subscriptionToken]) if result render json: { id: result}, status: :ok else render json: {error: FAILURE_MESSAGE}, status: :unprocessable_entity end end ...

Langkah 6: Menambahkan penangan langganan untuk callback createOrder dan onApprove di front end.

Terakhir, di index.html.haml , ganti fungsi paypal.Buttons dengan yang berikut, yang akan mengisi dua kosong else kita miliki sebelumnya:

 paypal.Buttons({ env: "#{ENV['PAYPAL_ENV']}", createOrder: function() { $('#order-type').val("paypal"); if (isPayment()) { return $.post("#{paypal_create_payment_url}", $('#order-details').serialize()).then(function(data) { return data.token; }); } else { return $.post("#{paypal_create_subscription_url}", $('#order-details').serialize()).then(function(data) { return data.token; }); } }, onApprove: function(data) { if (isPayment()) { return $.post("#{paypal_execute_payment_url}", { paymentID: data.paymentID, payerID: data.payerID }).then(function() { submitOrderPaypal(data.paymentID) }); } else { return $.post("#{paypal_execute_subscription_url}", { subscriptionToken: data.orderID }).then(function(executeData) { submitOrderPaypal(executeData.id) }); } } }).render('#submit-paypal');

Pembuatan dan eksekusi untuk langganan memiliki logika yang sama seperti yang digunakan untuk pembayaran. Salah satu perbedaannya adalah ketika melakukan pembayaran, data dari fungsi callback onApprove sudah memiliki ID charge_id paymentID mengirimkan formulir melalui submitOrderPaypal(data.paymentID) . Untuk langganan, kami mendapatkan charge_id hanya setelah menjalankannya dengan meminta POST di paypal_execute_subscription_url , sehingga kami dapat memanggil submitOrderPaypal(executeData.id) .

Langkah 7: Uji aplikasi Anda.

  • Kunjungi halaman indeks.
  • Pilih produk langganan dan PayPal sebagai metode pembayaran.
  • Klik tombol kirim PayPal.
  • Di munculan PayPal:
    • Gunakan kredensial untuk akun pembeli yang Anda buat.
    • Masuk dan konfirmasi pesanan Anda.
    • Munculan harus ditutup.
  • Periksa apakah Anda diarahkan ke halaman sukses.
  • Terakhir, periksa apakah pesanan dilakukan di akun PayPal dengan masuk menggunakan akun bisnis Anda di https://www.sandbox.paypal.com/signin dan memeriksa dasbor https://www.sandbox.paypal.com/listing/ transaksi.

Kesimpulan

Setelah membaca artikel ini, Anda seharusnya dapat mengintegrasikan pembayaran/biaya serta transaksi langganan untuk PayPal dan Stripe di aplikasi Rails Anda. Ada banyak poin yang bisa diperbaiki yang tidak saya tambahkan dalam artikel ini demi singkatnya. Saya mengatur semuanya berdasarkan asumsi kesulitan:

  • Lebih mudah:
    • Gunakan Transport Layer Security (TLS) agar permintaan Anda menggunakan HTTPS.
    • Terapkan konfigurasi lingkungan produksi untuk PayPal dan Stripe.
    • Tambahkan halaman baru sehingga pengguna dapat mengakses riwayat pesanan sebelumnya.
  • Sedang:
    • Pengembalian dana atau batalkan langganan.
    • Memberikan solusi untuk pembayaran pengguna yang tidak terdaftar.
  • Lebih sulit:
    • Berikan cara untuk menghapus akun dan mempertahankan token dan customer_id mereka jika pengguna ingin kembali. Tetapi setelah beberapa hari, hapus data ini agar aplikasi Anda lebih sesuai dengan PCI.
    • Pindah ke PayPal versi 2 API di sisi server (https://developer.paypal.com/docs/api/payments/v2/) Permata yang kami gunakan dalam tutorial ini paypal-sdk-rest , hanya memiliki versi beta untuk versi 2, sehingga dapat digunakan dengan hati-hati (https://github.com/paypal/PayPal-Ruby-SDK/tree/2.0-beta).
    • Sertakan permintaan idempoten.
      • Garis: https://stripe.com/docs/api/idempotent_requests
      • PayPal: https://developer.paypal.com/docs/api-basics/#api-idempotency

Saya juga merekomendasikan membaca tentang elemen Stripe Checkout, yang merupakan cara lain untuk mengintegrasikan Stripe di ujung depan. Tidak seperti Stripe Elements, yang kami gunakan dalam tutorial ini, Stripe Checkout membuka popup setelah mengklik tombol (mirip dengan PayPal) tempat pengguna mengisi info kartu kredit ATAU memilih untuk membayar dengan Google Pay/Apple Pay https://stripe.com /dokumen/web.

Rekomendasi bacaan kedua adalah halaman keamanan untuk kedua Gateway Pembayaran.

  • Untuk Garis
  • Untuk PayPal

Akhirnya, terima kasih telah membaca artikel ini! Anda juga dapat memeriksa proyek GitHub saya yang digunakan untuk sampel proyek ini. Di sana, saya menambahkan tes rspec juga saat mengembangkan.