Ruby on Rails'de Stripe ve PayPal Ödeme Yöntemlerini Entegre Etme
Yayınlanan: 2022-03-11AliExpress, Ebay ve Amazon gibi büyük e-ticaret şirketleri için önemli bir özellik, işletmeleri için gerekli olan ödemeleri ele almanın güvenli bir yoludur. Bu özellik başarısız olursa, sonuçlar yıkıcı olacaktır. Bu, sektör liderleri ve e-Ticaret uygulamaları üzerinde çalışan Ruby on Rails geliştiricileri için geçerlidir.
Siber güvenlik, saldırıları önlemek için çok önemlidir ve işlem sürecini daha güvenli hale getirmenin bir yolu, üçüncü taraf bir hizmetten bunu işlemesini istemektir. Uygulamanıza ödeme ağ geçitlerini dahil etmek, kullanıcı yetkilendirmesi, veri şifreleme ve işlem durumunu anında takip edebilmeniz için bir kontrol paneli sağladıkları için bu hedefe ulaşmanın bir yoludur.
Web'de çeşitli ödeme ağ geçidi hizmetleri vardır, ancak bu makalede Stripe ve PayPal'ı bir Rails uygulamasına entegre etmeye odaklanacağım. Diğer birkaçından bahsetmek gerekirse: Amazon Payments, Square, SecurePay, WorldPay, Authorize.Net, 2Checkout.com, Braintree, Amazon veya BlueSnap.
Ödeme Ağ Geçidi Entegrasyonu Nasıl Çalışır?

Genel olarak, başvurunuzda kullanıcının oturum açabileceği/kredi kartı bilgilerini girebileceği bir form/düğme olacaktır. PayPal ve Stripe, bu işlemi temsil eden bir jeton döndüreceklerinden, uygulamanızın hassas kullanıcı kredi kartı bilgilerini saklamasını engelleyen iframe
formları veya popups
kullanarak bu ilk adımı zaten daha güvenli hale getiriyor. Ayrıca bazı kullanıcılar, işlem sürecini üçüncü taraf bir hizmetin yürüttüğünü bilerek ödemeleri işleme konusunda kendilerini daha güvende hissedebilirler, bu nedenle bu, uygulamanız için de bir çekicilik olabilir.
Kullanıcı bilgilerinin kimliğini doğruladıktan sonra, ödeme ağ geçidi, ödemeleri kapatmak için bankalarla iletişim kuran bir ödeme işlemcisi ile iletişime geçerek ödemeyi onaylayacaktır. Bu, işlemin uygun şekilde borçlandırılmasını/alınmasını sağlar.
Stripe, kredi kartı numarası, özgeçmiş ve son kullanma tarihini soran bir kredi kartı formu kullanır. Bu nedenle kullanıcının güvenli Stripe girişlerinde kredi kartı bilgilerini doldurması gerekir. Bu bilgileri sağladıktan sonra, uygulamanızın arka ucu bu ödemeyi bir belirteç aracılığıyla işler.
Stripe'ın aksine PayPal, kullanıcıyı PayPal oturum açma sayfasına yönlendirir. Kullanıcı, PayPal aracılığıyla ödeme yöntemini yetkilendirir ve seçer ve yine, arka ucunuz, kullanıcıya duyarlı veriler yerine belirteçleri işleyecektir.
Bu iki ödeme ağ geçidi için, arka ucunuzun Stripe veya PayPal API'leri aracılığıyla işlem yürütmeye devam etmesini istemesi gerektiğini ve bunun bir OK/NOK yanıtı vereceğini belirtmek önemlidir, bu nedenle uygulamanız kullanıcıyı buna göre başarılı veya hata sayfasına yönlendirmelidir.
Bu makalenin amacı, bu iki ödeme ağ geçidini tek bir uygulamada entegre etmek için hızlı bir kılavuz sağlamaktır. Tüm testler için, ödemeleri simüle etmek için Stripe ve PayPal tarafından sağlanan korumalı alanları ve test hesaplarını kullanacağız.
Kurmak
Ödeme ağ geçitlerini entegre etmeden önce, gems, veritabanı tabloları ve bir dizin sayfası ekleyerek uygulamayı başlatmak için bir kurulum yapacağız. Bu proje, Rails sürüm 5.2.3 ve Ruby 2.6.3 kullanılarak oluşturulmuştur.
Not: Son makalemizde yeni Rails 6 özelliklerine göz atabilirsiniz.
Adım 1: Bir Rails uygulamasını başlatın.
Uygulama adınızla birlikte rails
komutuyla proje başlatmayı çalıştırarak projeyi başlatın:
rails new YOUR_APP_NAME
Ve uygulama klasörünüzdeki cd
.
Adım 2: Mücevherleri yükleyin.
Stripe ve PayPal mücevherlerinin yanı sıra birkaç mücevher daha eklendi:
-
devise
: kullanıcı kimlik doğrulaması ve yetkilendirme için kullanılır -
haml
: kullanıcı sayfalarını oluşturmak için şablon oluşturma aracı -
jquery-rails
: ön uç komut dosyalarındakijquery
için -
money-rails
: biçimlendirilmiş para değerlerini görüntülemek için
Gemfile
:
gem "devise", ">= 4.7.1" gem "haml" gem "jquery-rails" gem "money-rails"
Ekledikten sonra CLI'nizde çalıştırın:
bundle install
Adım 3: Mücevherleri başlatın.
Bu taşlardan bazıları, bunları bundle
yoluyla kurmanın yanı sıra başlatma gerektirecektir.
Kurulum cihazı:
rails g devise:install
money-rails
başlatılması:
rails g money_rails:initializer
app/assets/javascripts/application.js
altına aşağıdakini ekleyerek jquery-rails
başlatın:
//= require jquery //= require jquery_ujs
4. Adım: Tablolar ve taşıma işlemleri
Bu projede Kullanıcılar , Ürünler ve Siparişler için üç tablo kullanılacaktır .
-
Users
: Cihaz aracılığıyla oluşturulacak -
Products
sütunları:-
name
-
price_cents
-
Stripe_plan_name
: Kullanıcıların abone olabilmesi için Stripe'te oluşturulan bir abonelik planını temsil eden bir kimlik. Bu alan yalnızca Stripe planıyla ilişkili ürünler için gereklidir. -
paypal_plan_name
:stripe_plan_name
ile aynı ama PayPal için
-
-
Orders
sütunları:-
product_id
-
user_id
-
status
: Bu, siparişin beklemede, başarısız veya ödenmiş olup olmadığını bildirecektir. -
token
: Bu, bir işlemi başlatmak için API'lerden (Stripe veya PayPal) oluşturulan bir jetondur. -
price_cents
: Ürüne benzer, ancak bu değeri sipariş kaydında kalıcı kılmak için kullanılır -
payment_gateway
: PayPal veya Stripe siparişi için hangi ödeme ağ geçidinin kullanıldığını depolar -
customer_id
: Bu, Stripe müşterisini bir abonelik için saklamak amacıyla Stripe için kullanılacaktır ve daha sonraki bir bölümde daha ayrıntılı olarak açıklanacaktır.
-
Bu tabloları oluşturmak için birkaç geçiş oluşturulmalıdır:
Kullanıcılar tablosunu oluşturmak için. Koşmak:
rails g devise User
Ürünler tablosunu oluşturmak için. Çalıştırarak bir taşıma oluşturun:
rails generate migration CreateProducts name:string stripe_plan_name:string paypal_plan_name:string
db/migrate/
olması gereken oluşturduğunuz geçiş dosyanızı açın ve geçişinizin şuna benzer görünmesi için değişiklikler yapın:
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
Siparişler tablosunu oluşturmak için. Çalıştırarak bir taşıma oluşturun:
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
Yine, db/migrate/
olması gereken oluşturduğunuz taşıma dosyanızı açın ve buna benzer görünmesi için bu dosyada değişiklikler yapın:
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
Aşağıdakileri yürüterek veritabanı geçişlerini çalıştırın:
rails db:migrate
Adım 5: Modeller oluşturun.
Kullanıcı modeli, cihaz kurulumundan zaten oluşturulmuştur ve üzerinde herhangi bir değişiklik yapılması gerekmeyecektir. Bunun yanında Ürün ve Sipariş için iki model oluşturulacaktır.
Ürün. app/models/product.rb
adlı yeni bir dosya ekleyin:
class Product < ActiveRecord::Base monetize :price_cents has_many :orders end
Sipariş. app/models/order.rb
adlı yeni bir dosya ekleyin:
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
Adım 6: Veritabanını doldurun.
Konsolda bir kullanıcı ve iki ürün oluşturulacaktır. Ödeme testlerine göre sipariş kayıtları oluşturulacaktır.
- Run
rails s
- Tarayıcınızda
http://localhost:3000
adresini ziyaret edin. - Bir kayıt sayfasına yönlendirileceksiniz.
- Bir kullanıcıyı e-posta adresini ve şifresini girerek kaydedin.
- Terminalinizde, veritabanınızda bir kullanıcının oluşturulduğunu gösteren aşağıdaki günlükler istenecektir:
User Create (0.1ms) INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at") VALUES (?, ?, ?, ?) …
-
rails c
çalıştırıp şunu ekleyerek abonelik olmadan iki ürün oluşturun:-
Product.create(name: "Awesome T-Shirt", price_cents: 3000)
-
Product.create(name: "Awesome Sneakers", price_cents: 5000)
-
7. Adım: Bir dizin sayfası oluşturun
Projenin ana sayfası, satın almalar veya abonelikler için ürün seçimini içerir. Ek olarak, ödeme yöntemi seçimi (Stripe veya PayPal) için bir bölümü de vardır. Her ödeme ağ geçidi türü için bir gönder düğmesi de kullanılır, çünkü PayPal için JavaScript kitaplığı aracılığıyla kendi düğme tasarımını ekleyeceğiz.
İlk olarak, index
için yolları oluşturun ve config/routes.rb
submit
.
Rails.application.routes.draw do devise_for :users get '/', to: 'orders#index' post '/orders/submit', to: 'orders#submit' end
Eylemler index
oluşturun ve ekleyin ve order controller app/controllers/orders_controller.rb
submit
orders#index
eylemi, ön uçta tüketilecek iki değişkeni saklar: planı olmayan ürünlerin listesini içeren @products_purchase
ve hem PayPal hem de Stripe planlarına sahip ürünleri olan @products_subscription
.
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
app/views/orders/index.html.haml
içinde bir dosya oluşturun. Bu dosya, gönderme yöntemi aracılığıyla arka ucumuza göndereceğimiz tüm girdileri ve ödeme ağ geçitleri ve ürün seçimi için etkileşimi içerir. İşte birkaç giriş adı özelliği:
-
Orders[product_id]
, ürün kimliğini saklar. -
Orders[payment_gateway]
, diğeri için Stripe veya PayPal değerlerine sahip ödeme ağ geçidini içerir.
%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; }
Uygulamanızı rails s
ile çalıştırırsanız ve http://localhost:3000
sayfanızı ziyaret edin. Sayfayı aşağıdaki gibi görebilmeniz gerekir:

Ödeme Ağ Geçidi Kimlik Bilgileri Deposu
PayPal ve Stripe anahtarları, Git tarafından izlenmeyen bir dosyada saklanacaktır. Her ödeme ağ geçidi için bu dosyada iki tür anahtar saklanır ve şimdilik onlar için sahte bir değer kullanacağız. Bu anahtarları oluşturmak için ek yönergeler sonraki bölümlerde sunulmuştur.
Adım 1: Bunu .gitignore
içine ekleyin.
/config/application.yml
Adım 2: config/application.yml
içinde kimlik bilgilerinizle bir dosya oluşturun. Bu API'lere erişmek için tüm PayPal ve Stripe korumalı alan/test anahtarlarınızı içermelidir.
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
Adım 3: Uygulama başladığında config/application.yml
dosyasındaki değişkenleri saklamak için, ENV
kullanılabilir olmaları için bu satırları config/application.rb
içine Application
sınıfına ekleyin.
config_file = Rails.application.config_for(:application) config_file.each do |key,value| ENV[key] = value end unless config_file.nil?
Şerit Yapılandırması
Stripe API'sini kullanmak için bir mücevher ekleyeceğiz: stripe-rails
. Ücretlerin ve aboneliklerin işlenebilmesi için bir Stripe hesabı oluşturulması da gereklidir. Gerekirse, resmi belgelerde Stripe API için API yöntemlerine başvurabilirsiniz.
Adım 1: Strip-rays gem'i projenize ekleyin.
Stripe-Rails gem, bu projede kullanılan tüm API istekleri için bir arayüz sağlayacaktır.
Bunu Gemfile
:
gem 'stripe-rails'
Koşmak:
bundle install
Adım 2: API anahtarlarınızı oluşturun.
Stripe ile iletişim kurmak için API anahtarlarına sahip olmak için Stripe'de bir hesap oluşturmanız gerekir. Uygulamayı test etmek için test modunu kullanmak mümkündür, bu nedenle Stripe hesabı oluşturma sürecinde gerçek işletme bilgilerinin doldurulması gerekmez.
- Hesabınız yoksa Stripe'ta bir hesap oluşturun (https://dashboard.stripe.com/).
- Hala Stripe panosundayken, oturum açtıktan sonra Test Verilerini Görüntüle'yi açın .
- https://dashboard.stripe.com/test/apikeys adresinde,
STRIPE_SECRET_KEY
içindekiSTRIPE_PUBLISHABLE_KEY
veYOUR_CREDENTIAL_HERE
değerleri için/config/application.yml
değeriniPublishable Key
veSecret key
öğesinden gelen içerikle değiştirin.
3. Adım: Stripe modülünü başlatın
Anahtarları değiştirmeye ek olarak, yine de Stripe modülünü başlatmamız gerekiyor, böylece zaten ENV
ayarlanmış anahtarları kullanır.
config/initializers/stripe.rb
bir dosya oluşturun:
Rails.application.configure do config.stripe.secret_key = ENV["STRIPE_SECRET_KEY"] config.stripe.publishable_key = ENV["STRIPE_PUBLISHABLE_KEY"] end
Adım 4: Stripe'ı ön uca entegre edin.
Stripe JavaScript kitaplığını ve kullanıcı kredi kartı bilgilerini temsil eden bir jeton gönderme mantığını ekleyeceğiz ve arka ucumuzda işlenecek.
index.html.haml
dosyasında, bunu dosyanızın en üstüne ekleyin. Bu, Stripe javascript kitaplığını kullanıcının sayfasına eklemek için Stripe modülünü (gem tarafından sağlanır) kullanır.
= stripe_javascript_tag
Stripe, API'leri aracılığıyla oluşturulan güvenli giriş alanlarını kullanır. Bu API aracılığıyla oluşturulan bir iframe
içinde oluşturuldukları için, kullanıcı kredi kartı bilgilerini işleyen olası güvenlik açıkları konusunda endişelenmenize gerek kalmayacak. Ek olarak, arka ucunuz herhangi bir kullanıcıya duyarlı veriyi işleyemez/saklayamaz ve yalnızca bu bilgiyi temsil eden bir belirteç alır.
Bu giriş alanları, stripe.elements().create('card')
çağrılarak oluşturulur. Bundan sonra, bu girdilerin monte edilmesi gereken HTML öğesi kimliğini/sınıfını argüman olarak ileterek, döndürülen nesneyi mount()
ile çağırmak yeterlidir. Daha fazla bilgi Stripe'de bulunabilir.
Kullanıcı, Stripe ödeme yöntemiyle gönder düğmesine bastığında, oluşturulan Stripe kartı öğesinde bir söz veren başka bir API çağrısı gerçekleştirilir:
stripe.createToken(card).then(function(result)
Bu işlevin result
değişkeni, atanmış bir özellik hatasına sahip değilse, result.token.id
özniteliğine erişilerek alınabilecek bir simgeye sahip olacaktır. Bu belirteç arka uca gönderilecek.
Bu değişiklikleri yapmak için, yorum yapılan kodu // STRİPE VE PAYPAL KODUNUZU index.html.haml
// YOUR STRIPE AND PAYPAL CODE WILL BE HERE
ile değiştirin:
(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
Sayfanızı ziyaret ederseniz, yeni Stripe güvenli giriş alanlarıyla aşağıdaki gibi görünmelidir:

Adım 5: Uygulamanızı test edin.
Kredi kartı formunu bir test kartı (https://stripe.com/docs/testing) ile doldurun ve sayfayı gönderin. Sunucu çıktınızdaki tüm parametrelerle ( product_id , Payment_gateway ve token ) submit
eyleminin çağrıldığını kontrol edin.
Şerit Ücretleri
Şerit ücretleri bir kerelik işlemleri temsil eder. Bu nedenle, Stripe ücretlendirme işleminden sonra müşteriden doğrudan para alırsınız. Bu, planlarla ilişkili olmayan ürünleri satmak için idealdir. Daha sonraki bir bölümde, PayPal ile aynı işlem türünün nasıl yapıldığını göstereceğim, ancak PayPal'ın bu işlem türü için adı Payment .
Bu bölümde ayrıca bir siparişi işlemek ve göndermek için tüm iskeleti sağlayacağım. Stripe formu gönderildiğinde submit
eyleminde bir sipariş oluştururuz. Bu sipariş başlangıçta bekleme durumunda olacaktır, bu nedenle bu sipariş işlenirken bir şeyler ters giderse, sipariş hala beklemede olacaktır.
Stripe API çağrılarından herhangi bir hata oluşursa, siparişi başarısız bir durumda kurarız ve ücretlendirme başarılı bir şekilde tamamlanırsa, ödenmiş durumda olacaktır. Kullanıcı ayrıca aşağıdaki grafikte gösterildiği gibi Stripe API yanıtına göre yönlendirilir:

Ek olarak, bir Stripe şarjı gerçekleştirildiğinde, bir kimlik döndürülür. Bu kimliği daha sonra gerekirse Stripe kontrol panelinizde arayabilmeniz için saklayacağız. Bu kimlik, siparişin geri ödenmesi gerektiğinde de kullanılabilir. Bu yazıda böyle bir şey incelenmeyecek.
Adım 1: Stripe hizmetini oluşturun.
Stripe API'sini kullanarak Stripe işlemlerini temsil etmek için bir singleton sınıfı kullanacağız. Bir ücret oluşturmak için Stripe::Charge.create
yöntemi çağrılır ve döndürülen nesne kimliği niteliği, charge_id
sipariş kaydında saklanır. Bu create
işlevi, ön uçtan kaynaklanan belirteç, sipariş fiyatı ve bir açıklama iletilerek çağrılır.
Bu nedenle, yeni bir app/services/orders
klasörü oluşturun ve bir Stripe hizmeti ekleyin: app/services/orders/stripe.rb
, execute
yönteminde bir girişi olan Orders::Stripe
singleton sınıfını içerir.
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
Adım 2: Gönder eylemini uygulayın ve Stripe hizmetini arayın.
orders_controller.rb
, temelde Orders::Stripe.execute
hizmetini çağıracak olan submit
eylemine aşağıdakini ekleyin. İki yeni özel işlevin de eklendiğini unutmayın: prepare_new_order
ve 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
Adım 3: Uygulamanızı test edin.
Geçerli bir test kartıyla çağrıldığında, gönderme eyleminin başarılı bir mesaja yeniden yönlendirme yapıp yapmadığını kontrol edin. Ayrıca, siparişin de gösterilip gösterilmediğini Stripe panonuzda kontrol edin.
Şerit Abonelikler
Yinelenen ödemeler için abonelikler veya planlar oluşturulabilir. Bu ürün çeşidi ile kullanıcıya plan konfigürasyonuna göre otomatik olarak günlük, haftalık, aylık veya yıllık olarak ücretlendirme yapılır. Bu bölümde, plan kimliğini saklamak için ürün stripe_plan_name
alanını kullanacağız—aslında, kimliği seçmemiz mümkün ve buna premium-plan
ki bu da plan kimliğini oluşturmak için kullanılacak. ilişki customer <-> subscription
.
Ayrıca, Stripe müşteri nesnesinin id özelliği ile doldurulacak stripe_customer_id
adlı kullanıcı tablosu için yeni bir sütun oluşturacağız. Stripe::Customer.create
işlevi çağrıldığında bir Stripe müşterisi oluşturulur ve ayrıca (https://dashboard.stripe.com/test/customers) adresinde oluşturulan ve hesabınıza bağlanan müşterileri de kontrol edebilirsiniz. Müşteriler, bizim durumumuzda, form gönderildiğinde gönderilen ön uçta oluşturulan belirteç olan bir source
parametresi geçirilerek oluşturulur.
En son bahsedilen Stripe API çağrısından elde edilen customer.subscriptions.create
nesnesi, client.subscriptions.create çağırılarak ve plan ID'sini parametre olarak geçirerek yapılan bir abonelik oluşturmak için de kullanılır.
Ek olarak, stripe-rails
gem, sırasıyla Stripe::Customer.retrieve
ve Stripe::Customer.update
çağrılarak yapılan Stripe'den bir müşteriyi almak ve güncellemek için arabirim sağlar.
Bu nedenle, bir kullanıcı kaydında zaten stripe_customer_id
, Stripe::Customer.create
kullanarak yeni bir müşteri oluşturmak yerine, stripe_customer_id
parametresini geçirerek Stripe::Customer.retrieve
çağıracağız, ardından Stripe::Customer.update
ve bu durumda belirteci bir parametre iletmek.

Öncelikle stripe_plan_name
alanını kullanarak yeni bir abonelik ürünü oluşturabilmemiz için Stripe API kullanarak bir plan oluşturacağız. Daha sonra, Stripe aboneliklerinin oluşturulması ve yürütülmesi için orders_controller
ve Stripe hizmetinde değişiklikler yapacağız.
Adım 1: Stripe API'sini kullanarak bir plan oluşturun.
Komut rails c
. Stripe hesabınız için abonelik oluşturun:
Stripe::Plan.create({ amount: 10000, interval: 'month', product: { name: 'Premium plan', }, currency: 'usd', id: 'premium-plan', })
Bu adımda döndürülen sonuç doğruysa, plan başarıyla oluşturuldu ve buna Stripe panonuzdan erişebilirsiniz.
Adım 2: stripe_plan_name
alan seti ile veritabanında bir ürün oluşturun.
Şimdi, veritabanında premium-plan
olarak ayarlanmış stripe_plan_name
ile bir ürün oluşturun:
Product.create(price_cents: 10000, name: 'Premium Plan', stripe_plan_name: 'premium-plan')
Adım 3: users
tablosuna stripe_customer_id
sütunu eklemek için bir taşıma oluşturun.
Terminalde aşağıdakileri çalıştırın:
rails generate migration AddStripeCustomerIdToUser stripe_customer_id:string rails db:migrate
Adım 4: Abonelik mantığını Stripe hizmet sınıfında uygulayın.
app/services/orders/stripe.rb
özel yöntemlerine iki işlev daha ekleyin: execute_subscription
, müşterinin nesnesindeki abonelikleri oluşturmaktan sorumludur. find_or_create_customer
işlevi, önceden oluşturulmuş müşteriyi veya yeni oluşturulan bir müşteriyi iade etmekten sorumludur.
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
Son olarak, aynı dosyadaki ( app/services/orders/stripe.rb
) execute
işlevinde, önce find_or_create_customer
ve ardından bir önceki alınan/oluşturulan müşteriyi geçerek execute_subscription
çağırarak aboneliği yürüteceğiz. Bu nedenle, execute
yönteminde #SUBSCRIPTIONS WILL BE HANDLED HERE
yorumunu aşağıdaki kodla değiştirin:
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)
Adım 5: Uygulamanızı test edin.
Web sitenizi ziyaret edin, abonelik ürünü Premium Plan
seçin ve geçerli bir test kartı doldurun. Gönderdikten sonra, sizi başarılı bir sayfaya yönlendirmelidir. Ayrıca, aboneliğin başarıyla oluşturulup oluşturulmadığını Stripe panonuzda kontrol edin.
PayPal Yapılandırması
Stripe'de yaptığımız gibi, PayPal API'sini kullanmak için bir mücevher ekleyeceğiz: paypal-sdk-rest
ve ayrıca bir PayPal hesabı oluşturmak gerekiyor. Bu mücevheri kullanan PayPal için açıklayıcı bir iş akışına resmi PayPal API belgelerinde başvurulabilir.
Adım 1: paypal-sdk-rest
gem'i projenize ekleyin.
Bunu Gemfile
:
gem 'paypal-sdk-rest'
Koşmak:
bundle install
Adım 2: API anahtarlarınızı oluşturun.
PayPal ile iletişim kurmak için API anahtarlarına sahip olmak için bir PayPal hesabı oluşturmanız gerekir. Böyle:
- https://developer.paypal.com/ adresinde bir hesap oluşturun (veya PayPal hesabınızı kullanın).
- Hâlâ hesabınızda oturum açmış durumdayken, https://developer.paypal.com/developer/accounts/ adresinde iki korumalı alan hesabı oluşturun:
- Kişisel (Alıcı Hesabı) – Bu, ödeme ve abonelik yapmak için yaptığınız testlerde kullanılacaktır.
- İşletme (Tüccar Hesabı) – Bu, aradığımız API anahtarlarına sahip olacak uygulamaya bağlanacaktır. Bunun yanında tüm işlemler bu hesaptan takip edilebilmektedir.
- Önceki iş sanal alan hesabını kullanarak https://developer.paypal.com/developer/applications adresinde bir uygulama oluşturun.
- Bu adımdan sonra PayPal için iki anahtar alacaksınız:
Client ID
veSecret
. -
config/application.yml
dosyasında,PAYPAL_CLIENT_ID
yerineYOUR_CREDENTIAL_HERE
vePAYPAL_CLIENT_SECRET
yeni aldığınız anahtarlarla değiştirin.
Adım 3: PayPal modülünü başlatın.
Stripe'e benzer şekilde, application.yml
içindeki anahtarları değiştirmenin yanı sıra, ENV
değişkenimizde zaten ayarlanmış anahtarları kullanabilmesi için PayPal modülünü başlatmamız gerekiyor. Bu amaçla, config/initializers/paypal.rb
bir dosya oluşturun:
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
Adım 4: PayPal'ı ön uca entegre edin.
index.html.haml
dosyasında bunu dosyanın en üstüne ekleyin:
%script(src="https://www.paypal.com/sdk/js?client-id=#{ENV['PAYPAL_CLIENT_ID']}")
Stripe'ın aksine PayPal, tıklandığında kullanıcının oturum açabileceği ve ödeme/aboneliğe geçebileceği güvenli bir açılır pencere açan yalnızca bir düğme kullanır. Bu düğme, paypal.Button(PARAM1).render(PARAM2)
yöntemi çağrılarak oluşturulabilir.
-
PARAM1
, ortam yapılandırmasına ve özellikler olarak iki geri çağırma işlevine sahip bir nesnedir:createOrder
veonApprove
. -
PARAM2
, PayPal düğmesinin eklenmesi gereken HTML öğesi tanımlayıcısını belirtir.
Bu nedenle, yine aynı dosyada, yorum yapılan kodu, YOUR PAYPAL CODE WILL BE HERE
ile değiştirin:
(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'); }());
Adım 5: Uygulamanızı test edin.
Sayfanızı ziyaret edin ve ödeme yöntemi olarak PayPal'ı seçtiğinizde PayPal düğmesinin görüntülenip görüntülenmediğini kontrol edin.
PayPal İşlemleri
PayPal işlemlerinin mantığı, Stripe'ın aksine, ön uçtan arka uca daha fazla istek içerdiğinden biraz daha karmaşıktır. Bu bölüm bu yüzden var. createOrder
ve onApprove
yöntemlerinde açıklanan fonksiyonların nasıl uygulanacağını ve back-end süreçlerinde de neler beklendiğini aşağı yukarı (kodsuz) anlatacağım.
Adım 1: Kullanıcı PayPal gönder düğmesini tıkladığında, kullanıcı kimlik bilgilerini isteyen bir PayPal açılır penceresi açılır ancak yükleme durumundadır. createOrder
geri çağırma işlevi çağrılır.

Adım 2: Bu fonksiyonda, arka uçumuza bir ödeme/abonelik oluşturacak bir istek gerçekleştireceğiz. Bu, bir işlemin en başlangıcıdır ve henüz herhangi bir ücret uygulanmaz, bu nedenle işlem aslında bekleme durumundadır. Arka uçumuz bize PayPal modülü ( paypal-rest-sdk
gem aracılığıyla sağlanır) kullanılarak oluşturulacak bir jeton döndürmelidir.
Adım 3: Hala createOrder
geri aramasındayız, arka ucumuzda oluşturulan bu jetonu iade ediyoruz ve her şey yolundaysa, PayPal açılır penceresi aşağıdakileri görüntüleyerek kullanıcı kimlik bilgilerini istiyor:

Adım 4: Kullanıcı oturum açtıktan ve ödeme yöntemini seçtikten sonra, açılır pencerenin durumu şu şekilde değişecektir:

Adım 5: onApprove
işlevi geri çağrısı şimdi çağrılır. Bunu şu şekilde tanımladık: onApprove: function(data)
. data
nesnesi, onu yürütmek için ödeme bilgilerine sahip olacaktır. Bu geri aramada, PayPal siparişini yürütmek için veri nesnesini geçerek bu sefer arka uç işlevimize başka bir istek gerçekleştirilecektir.
Adım 6: Arka uçumuz bu işlemi yürütür ve 200 (başarılıysa) döndürür.
7. Adım: Arka ucumuz döndüğünde formu göndeririz. Bu, arka uçumuza yaptığımız üçüncü talep.
Stripe'ın aksine, bu süreçte arka uçumuza yapılan üç istek olduğunu unutmayın. Ve sipariş kaydı durumumuzu buna göre senkronize tutacağız:
-
createOrder
geri araması: Bir işlem oluşturulur ve ayrıca bir sipariş kaydı da oluşturulur; bu nedenle, varsayılan olarak bekleme durumundadır. -
onApprove
callback: İşlem gerçekleştirilir ve siparişimiz paypal_executed olarak ayarlanır. - Sipariş sayfası gönderilir: İşlem zaten yürütülmüştür, bu nedenle hiçbir şey değişmez. Sipariş kaydı, durumunu ödenmiş olarak değiştirecektir.
Tüm bu süreç aşağıdaki grafikte açıklanmıştır:

PayPal Ödemeleri
PayPal ödemeleri, Stripe Ücretleri ile aynı mantığı takip eder, bu nedenle tek seferlik işlemleri temsil ederler, ancak önceki bölümde belirtildiği gibi farklı bir akış mantığına sahiptirler. PayPal ödemelerini işlemek için yapılması gereken değişiklikler şunlardır:
Adım 1: PayPal için yeni rotalar oluşturun ve ödemeleri gerçekleştirin.
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 callingPayPal::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 throughPayPal::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 callexecute
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.
Takip ederek:
... 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 methodcreate_payment
. If that returns successfully, it will return the order token created byOrders::Paypal.create_payment
. - The
paypal_execute_payment
method: Will call our service methodexecute_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:

Step 6: Test your application.
- Dizin sayfasını ziyaret edin.
- Bir ödeme/ödeme ürünü ve ödeme yöntemi olarak PayPal seçin.
- PayPal gönder düğmesine tıklayın.
- PayPal açılır penceresinde:
- Oluşturduğunuz alıcı hesabı için kimlik bilgilerini kullanın.
- Giriş yapın ve siparişinizi onaylayın.
- Pop-up kapanmalıdır.
- Bir başarı sayfasına yönlendirilip yönlendirilmediğinizi kontrol edin.
- Son olarak, https://www.sandbox.paypal.com/signin adresinde işletme hesabınızla oturum açıp https://www.sandbox.paypal.com/listing panosunu kontrol ederek siparişin PayPal hesabında gerçekleştirilip gerçekleştirilmediğini kontrol edin. /işlemler.
PayPal Abonelikleri
PayPal planları/sözleşmeleri/abonelikleri, Stripe abonelikleriyle aynı mantığı izler ve yinelenen ödemeler için oluşturulur. Bu tip ürünlerde kullanıcı konfigürasyonuna göre günlük, haftalık, aylık veya yıllık olarak otomatik olarak ücretlendirilir.
PayPal tarafından sağlanan plan kimliğini saklamak için paypal_plan_name
ürününün alanını kullanacağız. Bu durumda, Stripe'tan farklı olarak, kimliği seçmeyiz ve PayPal, veritabanımızda oluşturulan son ürünü güncellemek için kullanılacak olan bu değeri döndürür.
Bir abonelik oluşturmak için, onApprove
yöntemi muhtemelen bu bağlantıyı temel uygulamasında ele aldığından, herhangi bir adımda customer
bilgisi gerekmez. Yani tablolarımız aynı kalacak.
Adım 1: PayPal API'sini kullanarak bir plan oluşturun.
Komut rails c
. PayPal hesabınız için aşağıdakilerle bir abonelik oluşturun:
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)
Adım 2: Paypal_plan_name veritabanındaki son ürünü, iade edilen paypal_plan_name
ile plan.id
.
Koşmak:
Product.last.update(paypal_plan_name: plan.id)
Adım 3: PayPal aboneliği için yollar ekleyin.
config/routes.rb
iki yeni rota ekleyin:
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
Adım 4: PayPal hizmetinde oluşturma ve yürütme işlemlerini gerçekleştirin.
app/services/orders/paypal.rb
Orders::Paypal
Paypal'da abonelik oluşturmak ve yürütmek için iki işlev daha ekleyin:
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
create_subscription
içinde, PayPal::SDK::REST::Agreement.new
yöntemini çağırarak ve product.paypal_plan_name
niteliklerinden biri olarak geçirerek bir sözleşme başlatırız. Daha sonra onu oluşturuyoruz ve şimdi bu son nesne için bir belirteç ayarlanacak. Ayrıca belirteci ön uca iade ediyoruz.
execute_subscription
içinde bir önceki çağrıda oluşturulan order
kaydını buluyoruz. Bundan sonra yeni bir sözleşme başlatıyoruz, bu önceki nesnenin jetonunu ayarlıyoruz ve yürütüyoruz. Bu son adım başarıyla gerçekleştirilirse, sipariş durumu paypal_executed olarak ayarlanır. Şimdi de order.chager_id
içinde saklanan sözleşme kimliğini ön uca döndürüyoruz.
Adım 5: orders_controller
içinde abonelikler oluşturmak ve yürütmek için eylemler ekleyin.
app/controllers/orders_controller.rb
değiştirin. Sınıfın en üstünde, ilk olarak ve sonra paypal_create_subscription
çağrılmadan önce de yürütülmek üzere prepare_new_order
geri aramasını güncelleyin:
class OrdersController < ApplicationController before_action :authenticate_user! before_action :prepare_new_order, only: [:paypal_create_payment, :paypal_create_subscription]
Ayrıca, aynı dosyaya iki genel işlevi ekleyin, böylece PayPal ödemelerinde zaten sahip olduğumuza benzer bir akışla Orders::Paypal
hizmetini çağırırlar:
... 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 ...
Adım 6: Ön uçta createOrder
ve onApprove
geri aramaları için abonelik işleyicileri ekleme.
Son olarak, index.html.haml
'da paypal.Buttons
işlevini aşağıdaki ile değiştirin; bu, else
önce sahip olduğumuz iki boş yeri dolduracaktır:
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');
Abonelikler için oluşturma ve yürütme, ödemeler için kullanılana benzer bir mantığa sahiptir. Bir fark, ödemeleri yürütürken, onApprove
geri arama işlevinden alınan verilerin, formu submitOrderPaypal(data.paymentID)
aracılığıyla göndermek için paymentID
temsil eden bir ödeme charge_id
sahip olmasıdır. Abonelikler için, charge_id
ancak paypal_execute_subscription_url üzerinde bir POST
isteyerek yürüttükten sonra paypal_execute_subscription_url
, böylece submitOrderPaypal(executeData.id)
.
Adım 7: Uygulamanızı test edin.
- Dizin sayfasını ziyaret edin.
- Bir abonelik ürünü ve ödeme yöntemi olarak PayPal seçin.
- PayPal gönder düğmesine tıklayın.
- PayPal açılır penceresinde:
- Oluşturduğunuz alıcı hesabı için kimlik bilgilerini kullanın.
- Giriş yapın ve siparişinizi onaylayın.
- Pop-up kapanmalıdır.
- Bir başarı sayfasına yönlendirilip yönlendirilmediğinizi kontrol edin.
- Son olarak, https://www.sandbox.paypal.com/signin adresindeki işletme hesabınızla oturum açarak ve https://www.sandbox.paypal.com/listing/ panosunu kontrol ederek siparişin PayPal hesabında gerçekleştirilip gerçekleştirilmediğini kontrol edin. işlemler.
Çözüm
Bu makaleyi okuduktan sonra, PayPal ve Stripe için ödemelerin/ücretlerin yanı sıra abonelik işlemlerini Rails uygulamanıza entegre edebilmelisiniz. Kısa olması için bu yazıda eklemediğim iyileştirilebilecek birçok nokta var. Her şeyi bir zorluk varsayımına göre düzenledim:
- Daha kolay:
- İsteklerinizin HTTPS kullanması için Aktarım Katmanı Güvenliği'ni (TLS) kullanın.
- Hem PayPal hem de Stripe için üretim ortamı yapılandırmalarını uygulayın.
- Kullanıcıların önceki siparişlerin geçmişine erişebilmesi için yeni bir sayfa ekleyin.
- Orta:
- Abonelikleri iade edin veya iptal edin.
- Kayıtlı olmayan kullanıcı ödemeleri için bir çözüm sağlayın.
- Daha güçlü:
- Kullanıcı geri gelmek isterse, hesapları kaldırmak ve belirteçlerini ve müşteri_kimliğini korumak için bir yol sağlayın. Ancak belirli bir süre sonra, uygulamanızın daha PCI uyumlu olması için bu verileri kaldırın.
- Sunucu tarafında PayPal sürüm 2 API'sine geç 2, böylece dikkatli bir şekilde kullanılabilir (https://github.com/paypal/PayPal-Ruby-SDK/tree/2.0-beta).
- İdempotent istekleri dahil edin.
- Şerit: https://stripe.com/docs/api/idempotent_requests
- PayPal: https://developer.paypal.com/docs/api-basics/#api-idempotency
Ayrıca, Stripe'i ön uca entegre etmenin başka bir yolu olan Stripe Checkout öğesi hakkında okumanızı da tavsiye ederim. Bu eğitimde kullandığımız Stripe Elements'in aksine Stripe Checkout, bir düğmeyi (PayPal'a benzer) tıkladıktan sonra kullanıcının kredi kartı bilgilerini doldurduğu VEYA Google Pay/Apple Pay ile ödemeyi seçtiği bir açılır pencere açar https://stripe.com /belgeler/web.
İkinci bir okuma önerisi, her iki Ödeme Ağ Geçidinin güvenlik sayfalarıdır.
- Şerit için
- PayPal için
Son olarak, bu makaleyi okuduğunuz için teşekkürler! Bu proje örneği için kullandığım GitHub projemi de inceleyebilirsiniz. Orada, geliştirirken rspec testleri de ekledim.