Integrarea metodelor de plată Stripe și PayPal în Ruby on Rails

Publicat: 2022-03-11

O caracteristică cheie pentru marile companii de comerț electronic, cum ar fi AliExpress, Ebay și Amazon, este o modalitate sigură de a gestiona plățile, care este esențială pentru afacerea lor. Dacă această caracteristică eșuează, consecințele ar fi devastatoare. Acest lucru se aplică liderilor din industrie și dezvoltatorilor Ruby on Rails care lucrează la aplicații de comerț electronic.

Securitatea cibernetică este esențială pentru prevenirea atacurilor, iar o modalitate de a face procesul de tranzacție mai sigur este să ceri unui serviciu terță parte să o gestioneze. Includerea gateway-urilor de plată în aplicația dvs. este o modalitate de a atinge acest obiectiv, deoarece acestea oferă autorizarea utilizatorului, criptarea datelor și un tablou de bord, astfel încât să puteți urmări starea tranzacției din mers.

Există o varietate de servicii de gateway de plată pe web, dar în acest articol mă voi concentra pe integrarea Stripe și PayPal într-o aplicație Rails. Ca să menționăm câteva altele: Amazon Payments, Square, SecurePay, WorldPay, Authorize.Net, 2Checkout.com, Braintree, Amazon sau BlueSnap.

Cum funcționează integrarea Gateway-ului de plată

Reprezentare generală pentru tranzacții care implică gateway-uri de plată
Reprezentare generală pentru tranzacții care implică gateway-uri de plată

În general, va exista un formular/buton în aplicația dvs. în care utilizatorul se poate autentifica/introduce datele cărții de credit. PayPal și Stripe fac deja acest prim pas mai sigur utilizând formulare iframe sau popups -up care împiedică aplicația dvs. să stocheze informații sensibile ale cardului de credit al utilizatorului, deoarece vor returna un simbol care reprezintă această tranzacție. De asemenea, unii utilizatori s-ar putea să se simtă deja mai încrezători în procesarea plăților, știind că un serviciu terț se ocupă de procesul de tranzacție, așa că acesta poate fi, de asemenea, o atracție pentru aplicația dvs.

După autentificarea informațiilor despre utilizator, un gateway de plată va confirma plata contactând un procesator de plăți care comunică cu băncile în vederea decontării plăților. Acest lucru asigură că tranzacția este debitată/creditată corespunzător.

Stripe folosește un formular de card de credit care solicită numărul cardului de credit, CVV și data de expirare. Deci, utilizatorul trebuie să completeze informațiile cardului de credit în intrările securizate Stripe. După furnizarea acestor informații, back-end-ul aplicației dvs. procesează această plată printr-un simbol.

Spre deosebire de Stripe, PayPal redirecționează utilizatorul către pagina de conectare PayPal. Utilizatorul autorizează și selectează metoda de plată prin PayPal și, din nou, back-end-ul tău va gestiona jetoanele în loc de datele sensibile ale utilizatorului.

Este important de menționat că, pentru aceste două gateway-uri de plată, back-end-ul dvs. ar trebui să solicite continuarea execuției tranzacției prin Stripe sau API-urile PayPal, care vor da un răspuns OK/NOK, astfel încât aplicația dvs. ar trebui să redirecționeze utilizatorul către o pagină de succes sau de eroare în consecință.

Intenția acestui articol este de a oferi un ghid rapid pentru integrarea acestor două gateway-uri de plată într-o singură aplicație. Pentru toate testele, vom folosi sandbox-uri și conturi de test furnizate de Stripe și PayPal pentru a simula plățile.

Înființat

Înainte de a integra gateway-uri de plată, vom face o configurare pentru inițializarea aplicației prin adăugarea de pietre prețioase, tabele de baze de date și o pagină de index. Acest proiect a fost creat folosind versiunea Rails 5.2.3 și Ruby 2.6.3.

Notă: puteți verifica noile funcții Rails 6 în articolul nostru recent.

Pasul 1: Inițializați o aplicație Rails.

Inițializați proiectul rulând inițializarea proiectului cu comanda rails cu numele aplicației dvs.:

 rails new YOUR_APP_NAME

Și cd în folderul aplicației dvs.

Pasul 2: Instalați pietre prețioase.

Pe lângă pietrele Stripe și PayPal, au fost adăugate alte câteva pietre:

  • devise : utilizat pentru autentificarea și autorizarea utilizatorului
  • haml : instrument de modelare pentru randarea paginilor utilizatorului
  • jquery-rails : pentru jquery în scripturile front-end
  • money-rails : pentru afișarea valorilor monetare formatate

Adăugați la fișierul dvs. Gemfile :

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

După ce l-ai adăugat, rulează în CLI:

 bundle install

Pasul 3: Inițializați pietrele prețioase.

Unele dintre aceste pietre prețioase vor necesita inițializare pe lângă instalarea lor prin bundle .

Dispozitiv de instalare:

 rails g devise:install

Inițializarea money-rails :

 rails g money_rails:initializer

Inițializați jquery-rails adăugând în partea de jos a app/assets/javascripts/application.js următoarele:

 //= require jquery //= require jquery_ujs

Pasul 4: Tabele și migrații

Trei tabele vor fi utilizate în acest proiect Utilizatori , Produse și Comenzi .

  • Users : vor fi generați prin devise
  • Coloane Products :
    • name
    • price_cents
    • Stripe_plan_name : un ID care reprezintă un plan de abonament creat în Stripe, astfel încât utilizatorii să se poată abona la acesta. Acest câmp este obligatoriu numai pentru produsele asociate unui plan Stripe.
    • paypal_plan_name : La fel ca stripe_plan_name , dar pentru PayPal
  • Coloane Orders :
    • product_id
    • user_id
    • status : Aceasta va informa dacă comanda este în așteptare, eșuată sau plătită.
    • token : Acesta este un token generat din API-uri (fie Stripe, fie PayPal) pentru a inițializa o tranzacție.
    • price_cents : Similar cu produsul, dar folosit pentru ca această valoare să fie persistentă în înregistrarea comenzii
    • payment_gateway : Stochează care gateway de plată este utilizat pentru comanda PayPal sau Stripe
    • customer_id : Acesta va fi folosit pentru Stripe pentru a stoca clientul Stripe pentru un abonament și va fi explicat cu mai multe detalii într-o secțiune ulterioară.

Pentru generarea acestor tabele, trebuie generate câteva migrări:

Pentru crearea tabelului Users . Alerga:

 rails g devise User

Pentru crearea tabelului Produse . Generați o migrare rulând:

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

Deschideți fișierul dvs. de migrare creat, care ar trebui să fie localizat la db/migrate/ și faceți modificări pentru ca migrarea să arate similar cu acesta:

 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

Pentru crearea tabelului Comenzi . Generați o migrare rulând:

 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

Din nou, deschideți fișierul de migrare creat, care ar trebui să fie localizat la db/migrate/ și faceți modificări la acel fișier pentru a-l face să arate similar cu acesta:

 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

Rulați migrarea bazei de date executând:

 rails db:migrate

Pasul 5: Creați modele.

Modelul utilizatorului este deja creat din instalarea proiectării și nu vor fi necesare modificări asupra acestuia. În plus, vor fi create două modele pentru Produs și Comandă .

Produs. Adăugați un fișier nou, app/models/product.rb , cu:

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

Ordin. Adăugați un fișier nou, app/models/order.rb , cu:

 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

Pasul 6: Populați baza de date.

Un utilizator și două produse vor fi create în consolă. Înregistrările comenzilor vor fi create conform testelor de plată.

  • rails s
  • În browser, accesați http://localhost:3000
  • Veți fi redirecționat către o pagină de înscriere.
  • Înregistrați un utilizator completând adresa de e-mail și parola acestuia.
  • În terminalul dvs., vor fi solicitate următoarele jurnale care arată că a fost creat un utilizator în baza de date:
 User Create (0.1ms) INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at") VALUES (?, ?, ?, ?) …
  • Creați două produse fără abonamente rulând rails c și adăugând:
    • Product.create(name: "Awesome T-Shirt", price_cents: 3000)
    • Product.create(name: "Awesome Sneakers", price_cents: 5000)

Pasul 7: Creați o pagină de index

Pagina principală a proiectului include selecția de produse pentru achiziții sau abonamente. În plus, are și o secțiune pentru selectarea metodei de plată (Stripe sau PayPal). Un buton de trimitere este, de asemenea, utilizat pentru fiecare tip de gateway de plată, deoarece pentru PayPal vom adăuga propriul design de buton prin biblioteca sa JavaScript.

Mai întâi, creați rutele pentru index și submit în config/routes.rb .

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

Creați și adăugați index acțiuni și submit în app/controllers/orders_controller.rb . Acțiunea orders#index stochează două variabile pentru a fi consumate în front-end: @products_purchase care are o listă de produse fără planuri și @products_subscription care are produse atât cu planuri PayPal, cât și 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

Creați un fișier în app/views/orders/index.html.haml . Acest fișier conține toate intrările pe care le vom trimite către backend prin metoda de trimitere și interacțiunea pentru gateway-uri de plată și selecția produselor. Iată câteva atribute ale numelui de intrare:

  • Orders[product_id] stochează ID-ul produsului.
  • Orders[payment_gateway] conține gateway-ul de plată cu valori Stripe sau PayPal pentru celălalt.
 %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; }

Dacă rulați aplicația cu rails s și vă vizitați pagina în http://localhost:3000 . Ar trebui să puteți vedea pagina după cum urmează:

Pagina de index brută fără integrare Stripe și PayPal
Pagina de index brută fără integrare Stripe și PayPal

Stocarea acreditărilor pentru Gateway de plată

Cheile PayPal și Stripe vor fi stocate într-un fișier care nu este urmărit de Git. Există două tipuri de chei stocate în acest fișier pentru fiecare gateway de plată și, deocamdată, vom folosi o valoare inactivă pentru ele. Indicații suplimentare pentru crearea acestor chei sunt prezentate în secțiunile ulterioare.

Pasul 1: Adăugați acest lucru în .gitignore .

 /config/application.yml

Pasul 2: creați un fișier cu acreditările dvs. în config/application.yml . Ar trebui să conțină toate cheile de testare/sandbox PayPal și Stripe pentru accesarea acestor API-uri.

 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

Pasul 3: Pentru a stoca variabilele din fișierul config/application.yml când pornește aplicația, adăugați aceste linii în config/application.rb în interiorul clasei Application , astfel încât să fie disponibile în ENV .

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

Configurație Stripe

Vom adăuga o bijuterie pentru utilizarea API-ului Stripe: stripe-rails . Crearea unui cont Stripe este, de asemenea, necesară pentru ca taxele și abonamentele să poată fi procesate. Dacă este necesar, puteți consulta metodele API pentru Stripe API în documentația oficială.

Pasul 1: Adăugați bijuteria cu șinele dungi la proiectul dvs.

Bijuteria stripe-rails va oferi o interfață pentru toate solicitările API utilizate în acest proiect.

Adăugați asta în Gemfile :

 gem 'stripe-rails'

Alerga:

 bundle install

Pasul 2: generați cheile API.

Pentru a avea cheile API pentru comunicarea cu Stripe, va trebui să vă creați un cont în Stripe. Pentru a testa aplicația, este posibil să utilizați modul de testare, astfel încât nu trebuie să completați informații despre afaceri reale în procesul de creare a contului Stripe.

  • Creați un cont în Stripe dacă nu aveți unul (https://dashboard.stripe.com/).
  • În timp ce vă aflați încă în tabloul de bord Stripe, după ce vă conectați, activați Vizualizarea datelor de testare .
  • La https://dashboard.stripe.com/test/apikeys, înlocuiți YOUR_CREDENTIAL_HERE pentru valorile STRIPE_PUBLISHABLE_KEY și STRIPE_SECRET_KEY din /config/application.yml cu conținutul din Publishable Key și Cheia Secret key .

Pasul 3: Inițializați modulul Stripe

Pe lângă înlocuirea cheilor, mai trebuie să inițializam modulul Stripe, astfel încât să folosească cheile deja setate în ENV -ul nostru.

Creați un fișier în config/initializers/stripe.rb cu:

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

Pasul 4: Integrați Stripe în partea din față.

Vom adăuga biblioteca Stripe JavaScript și logica pentru trimiterea unui token care reprezintă informațiile despre cardul de credit al utilizatorului și va fi procesat în back-end-ul nostru.

În fișierul index.html.haml , adăugați-l în partea de sus a fișierului. Aceasta va folosi modulul Stripe (furnizat de bijuterie) pentru a adăuga biblioteca javascript Stripe la pagina utilizatorului.

 = stripe_javascript_tag

Stripe utilizează câmpuri de intrare securizate care sunt create prin intermediul API-ului lor. Deoarece sunt create într-un iframe creat prin acest API, nu va trebui să vă faceți griji cu privire la posibilele vulnerabilități care manipulează informațiile despre cardul de credit al utilizatorului. În plus, back-end-ul dvs. nu va putea procesa/stoca date sensibile ale utilizatorului și va primi doar un simbol care reprezintă aceste informații.

Aceste câmpuri de intrare sunt create prin apelarea stripe.elements().create('card') . După aceea, este necesar doar să apelați obiectul returnat cu mount() trecând ca argument id-ul/clasa elementului HTML în care ar trebui să fie montate aceste intrări. Mai multe informații pot fi găsite la Stripe.

Când utilizatorul apasă butonul de trimitere cu metoda de plată Stripe, un alt apel API care returnează o promisiune este efectuat pe elementul de card Stripe creat:

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

Variabila result a acestei funcții, dacă nu are o eroare de proprietate atribuită, va avea un token care poate fi preluat accesând atributul result.token.id . Acest token va fi trimis la back-end.

Pentru a face aceste modificări, înlocuiți codul comentat // YOUR STRIPE AND PAYPAL CODE WILL BE HERE în index.html.haml cu:

 (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

Dacă vizitați pagina dvs., ar trebui să arate așa cu noile câmpuri de introducere securizate Stripe:

Pagina de index integrată cu câmpuri de introducere securizate Stripe.
Pagina de index integrată cu câmpuri de introducere securizate Stripe.

Pasul 5: Testează-ți aplicația.

Completați formularul de card de credit cu un card de testare (https://stripe.com/docs/testing) și trimiteți pagina. Verificați dacă acțiunea de submit este apelată cu toți parametrii ( product_id , payment_gateway și token ) din ieșirea serverului dvs.

Stripe Charges

Taxele Stripe reprezintă tranzacții unice. Prin urmare, după o tranzacție de taxare Stripe, veți primi bani direct de la client. Acesta este ideal pentru vânzarea de produse care nu sunt asociate cu planuri. Într-o secțiune ulterioară, voi arăta cum să faci același tip de tranzacție cu PayPal, dar numele PayPal pentru acest tip de tranzacție este Plată .

În această secțiune voi furniza și tot scheletul pentru manipularea și trimiterea unei comenzi. Creăm o comandă în acțiunea de submit când este trimis formularul Stripe. Această comandă va avea inițial starea în așteptare , așa că dacă ceva nu merge bine în timpul procesării acestei comenzi, comanda va fi în continuare în așteptare .

Dacă apare vreo eroare din apelurile Stripe API, setăm comanda într-o stare eșuată , iar dacă taxa este finalizată cu succes, aceasta va fi în starea plătită . Utilizatorul este, de asemenea, redirecționat în funcție de răspunsul Stripe API, așa cum se arată în graficul următor:

Tranzacții Stripe.
Tranzacții Stripe.

În plus, atunci când se efectuează o taxă Stripe, se returnează un ID. Vom stoca acest ID, astfel încât să îl puteți căuta ulterior în tabloul de bord Stripe, dacă este necesar. Acest ID poate fi folosit și în cazul în care comanda trebuie rambursată. Așa ceva nu va fi explorat în acest articol.

Pasul 1: Creați serviciul Stripe.

Vom folosi o clasă singleton pentru a reprezenta operațiunile Stripe folosind API-ul Stripe. Pentru a crea o taxă, este apelată metoda Stripe::Charge.create , iar atributul ID obiect returnat va fi stocat în înregistrarea comenzii charge_id . Această funcție de create este apelată prin transmiterea simbolului originat în front-end, prețul comenzii și o descriere.

Deci, creați un nou folder app/services/orders și adăugați un serviciu Stripe: app/services/orders/stripe.rb care conține clasa singleton Orders::Stripe , care are o intrare în metoda 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

Pasul 2: implementați acțiunea de trimitere și apelați serviciul Stripe.

În orders_controller.rb , adăugați următoarele în acțiunea de submit , care practic va apela serviciul Orders::Stripe.execute . Rețineți că au fost adăugate și două noi funcții private: prepare_new_order și 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

Pasul 3: Testați aplicația.

Verificați dacă acțiunea de trimitere, atunci când este apelată cu un card de testare valid, efectuează o redirecționare către un mesaj de succes. În plus, verificați în tabloul de bord Stripe dacă comanda este afișată și.

Abonamente Stripe

Pot fi create abonamente sau planuri pentru plăți recurente. Cu acest tip de produs, utilizatorul este taxat zilnic, săptămânal, lunar sau anual automat conform configurației planului. În această secțiune, vom folosi câmpul pentru produs stripe_plan_name pentru a stoca ID-ul planului - de fapt, este posibil să alegem ID-ul și îl vom numi premium-plan - care va fi folosit pentru a crea relație customer <-> subscription .

De asemenea, vom crea o nouă coloană pentru tabelul utilizatori numit stripe_customer_id , care va fi completată cu proprietatea id a unui obiect client Stripe. Un client Stripe este creat atunci când este apelată funcția Stripe::Customer.create și, de asemenea, puteți verifica clienții creați și conectați la contul dvs. în (https://dashboard.stripe.com/test/customers). Clienții sunt creați prin trecerea unui parametru source care, în cazul nostru, este tokenul generat în front end care este trimis la trimiterea formularului.

Obiectul client obținut din ultimul apel Stripe API menționat, este folosit și pentru crearea unui abonament care se face prin apelarea customer.subscriptions.create și transmiterea ID-ului planului ca parametru.

În plus, bijuteria stripe-rails oferă interfața pentru a prelua și actualiza un client din Stripe, care se face apelând Stripe::Customer.retrieve și, respectiv, Stripe::Customer.update .

Deci, atunci când o înregistrare de utilizator are deja un stripe_customer_id , în loc să creăm un nou client folosind Stripe::Customer.create , vom apela Stripe::Customer.retrieve trecând stripe_customer_id ca parametru, urmat de un Stripe::Customer.update , iar în acest caz, trecerea jetonului un parametru.

În primul rând, vom crea un plan folosind Stripe API, astfel încât să putem crea un nou produs de abonament folosind câmpul stripe_plan_name . Ulterior, vom face modificări în orders_controller și serviciul Stripe, astfel încât crearea și execuția abonamentelor Stripe să fie gestionată.

Pasul 1: Creați un plan utilizând API-ul Stripe.

Deschideți consola folosind rails c . Creați un abonament pentru contul Stripe cu:

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

Dacă rezultatul returnat în acest pas este adevărat, înseamnă că planul a fost creat cu succes și îl puteți accesa în tabloul dvs. Stripe.

Pasul 2: Creați un produs în baza de date cu câmpul stripe_plan_name setat.

Acum, creați un produs cu stripe_plan_name setat ca premium-plan în baza de date:

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

Pasul 3: Generați o migrare pentru adăugarea unei coloane stripe_customer_id în tabelul users .

Rulați următoarele în terminal:

 rails generate migration AddStripeCustomerIdToUser stripe_customer_id:string rails db:migrate

Pasul 4: Implementați logica abonamentului în clasa de serviciu Stripe.

Adăugați încă două funcții în metodele private ale app/services/orders/stripe.rb : execute_subscription este responsabil pentru crearea abonamentelor în obiectul clientului. Funcția find_or_create_customer este responsabilă să returneze clientul deja creat sau prin returnarea unui client nou creat.

 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

În cele din urmă, în funcția execute din același fișier ( app/services/orders/stripe.rb ), vom apela mai întâi find_or_create_customer și apoi vom executa abonamentul apelând execute_subscription trecând clientul anterior recuperat/creat. Așadar, înlocuiți comentariul #SUBSCRIPTIONS WILL BE HANDLED HERE în metoda execute cu următorul cod:

 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)

Pasul 5: Testează-ți aplicația.

Vizitați site-ul dvs. web, selectați produsul cu abonament Premium Plan și completați un card de testare valid. După trimitere, ar trebui să vă redirecționeze către o pagină de succes. În plus, verificați în tabloul de bord Stripe dacă abonamentul a fost creat cu succes.

Configurare PayPal

Așa cum am făcut în Stripe, vom adăuga și o bijuterie pentru utilizarea API-ului PayPal: paypal-sdk-rest și este, de asemenea, necesară crearea unui cont PayPal. Un flux de lucru descriptiv pentru PayPal folosind această bijuterie poate fi consultat în documentația oficială PayPal API.

Pasul 1: Adăugați bijuteria paypal-sdk-rest la proiectul dvs.

Adăugați asta în Gemfile :

 gem 'paypal-sdk-rest'

Alerga:

 bundle install

Pasul 2: generați cheile API.

Pentru a avea cheile API pentru comunicarea cu PayPal, va trebui să vă creați un cont PayPal. Asa de:

  • Creați un cont (sau utilizați contul dvs. PayPal) la https://developer.paypal.com/.
  • Încă sunteți conectat la contul dvs., creați două conturi sandbox la https://developer.paypal.com/developer/accounts/:
    • Personal (Cont de cumpărător) – Acesta va fi folosit în testele dumneavoastră pentru efectuarea plăților și abonamentelor.
    • Business (Cont de comerciant) – Acesta va fi legat de aplicație, care va avea cheile API pe care le căutăm. În plus, toate tranzacțiile pot fi urmărite în acest cont.
  • Creați o aplicație la https://developer.paypal.com/developer/applications folosind contul anterior de business sandbox.
  • După acest pas, veți primi două chei pentru PayPal: Client ID și Secret .
  • În config/application.yml , înlocuiți YOUR_CREDENTIAL_HERE din PAYPAL_CLIENT_ID și PAYPAL_CLIENT_SECRET cu cheile pe care tocmai le-ați primit.

Pasul 3: Inițializați modulul PayPal.

Similar cu Stripe, pe lângă înlocuirea cheilor în application.yml , mai trebuie să inițializam modulul PayPal, astfel încât să poată folosi cheile deja setate în variabila ENV . În acest scop, creați un fișier în config/initializers/paypal.rb cu:

 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

Pasul 4: Integrați PayPal în front-end.

În index.html.haml adăugați acest lucru în partea de sus a fișierului:

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

Spre deosebire de Stripe, PayPal folosește doar un buton care, atunci când este apăsat, deschide o fereastră pop-up securizată în care utilizatorul se poate autentifica și trece la plata/abonament. Acest buton poate fi redat apelând metoda paypal.Button(PARAM1).render(PARAM2) .

  • PARAM1 este un obiect cu configurația mediului și două funcții de apel invers ca proprietăți: createOrder și onApprove .
  • PARAM2 indică identificatorul elementului HTML la care trebuie atașat butonul PayPal.

Deci, tot în același fișier, înlocuiți codul comentat YOUR PAYPAL CODE WILL BE HERE cu:

 (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'); }());

Pasul 5: Testează-ți aplicația.

Vizitați pagina dvs. și verificați dacă butonul PayPal este redat atunci când selectați PayPal ca metodă de plată.

Tranzacții PayPal

Logica pentru tranzacțiile PayPal, spre deosebire de Stripe, este puțin mai complexă, implicând mai multe solicitări provenite de la front-end la back-end. De aceea există această secțiune. Voi explica mai mult sau mai puțin (fără niciun cod) cum vor fi implementate funcțiile descrise în metodele createOrder și onApprove și ce se așteaptă și în procesele back-end.

Pasul 1: Când utilizatorul face clic pe butonul de trimitere PayPal, o fereastră pop-up PayPal care solicită acreditările utilizatorului este deschisă, dar în stare de încărcare. Este apelată funcția callback createOrder .

Popup PayPal, stare de încărcare
Popup PayPal, stare de încărcare

Pasul 2: În această funcție, vom efectua o solicitare către back-end-ul nostru, care va crea o plată/abonament. Acesta este chiar începutul unei tranzacții și încă nu vor fi aplicate taxe, așa că tranzacția este de fapt într-o stare în așteptare . Back-end-ul nostru ar trebui să ne returneze un token, care va fi generat folosind modulul PayPal (furnizat prin bijuteria paypal-rest-sdk ).

Pasul 3: Încă în callback createOrder , returnăm acest token generat în back-end-ul nostru și, dacă totul este în regulă, fereastra pop-up PayPal va afișa următoarele, solicitând acreditările utilizatorului:

Popup PayPal, acreditările utilizatorului
Popup PayPal, acreditările utilizatorului

Pasul 4: După ce utilizatorul s-a autentificat și a selectat metoda de plată, fereastra pop-up își va schimba starea în următoarea:

Popup PayPal, tranzacție autorizată
Popup PayPal, tranzacție autorizată

Pasul 5: Funcția onApprove callback este acum apelată. L-am definit astfel: onApprove: function(data) . Obiectul data va avea informațiile de plată pentru a-l executa. În acest callback, o altă solicitare către funcția noastră de back-end va fi efectuată de data aceasta trecând obiectul de date pentru a executa comanda PayPal.

Pasul 6: Back-end-ul nostru execută această tranzacție și returnează 200 (dacă are succes).

Pasul 7: Când back-end-ul nostru revine, trimitem formularul. Aceasta este a treia cerere pe care o facem back-end-ului nostru.

Rețineți că, spre deosebire de Stripe, există trei solicitări adresate back-end-ului nostru în acest proces. Și vom păstra starea comenzii sincronizată în consecință:

  • createOrder callback: este creată o tranzacție și este creată și o înregistrare a comenzii; prin urmare, este într-o stare în așteptare ca implicită.
  • onApprove callback: tranzacția este executată și comanda noastră va fi setată ca paypal_executed .
  • Pagina de comandă este trimisă: Tranzacția a fost deja executată, așa că nu se schimbă nimic. Înregistrarea comenzii își va schimba starea în plătit .

Întregul proces este descris în graficul următor:

Tranzacții PayPal
Tranzacții PayPal

Plăți PayPal

Plățile PayPal urmează aceeași logică ca și taxele Stripe, deci reprezintă tranzacții unice, dar, așa cum sa menționat în secțiunea anterioară, au o logică de flux diferită. Acestea sunt modificările care vor trebui efectuate pentru gestionarea plăților PayPal:

Pasul 1: Creați noi rute pentru PayPal și executați plăți.

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. cu urmatoarele:

 ... 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.

  • Vizitați pagina de index.
  • Selectați un produs de plată/debit și PayPal ca metodă de plată.
  • Faceți clic pe butonul de trimitere PayPal.
  • În fereastra pop-up PayPal:
    • Utilizați acreditările pentru contul de cumpărător pe care l-ați creat.
    • Conectați-vă și confirmați comanda.
    • Fereastra pop-up ar trebui să se închidă.
  • Verificați dacă sunteți redirecționat către o pagină de succes.
  • În cele din urmă, verificați dacă comanda a fost efectuată în contul PayPal, conectându-vă cu contul dvs. de afaceri la https://www.sandbox.paypal.com/signin și verificând tabloul de bord https://www.sandbox.paypal.com/listing /tranzacții.

Abonamente PayPal

Planurile/acordurile/abonamentele PayPal urmează aceeași logică ca și abonamentele Stripe și sunt create pentru plăți recurente. Cu acest tip de produs utilizatorul este taxat zilnic, săptămânal, lunar sau anual automat în funcție de configurația sa.

Vom folosi câmpul pentru produsul paypal_plan_name , pentru a stoca ID-ul planului furnizat de PayPal. În acest caz, altfel decât Stripe, nu alegem ID-ul, iar PayPal returnează această valoare la care va fi folosită pentru a actualiza ultimul produs creat în baza noastră de date.

Pentru crearea unui abonament, nu sunt necesare informații despre customer în niciun pas, deoarece metoda onApprove se ocupă probabil de această legătură în implementarea sa de bază. Deci mesele noastre vor rămâne aceleași.

Pasul 1: Creați un plan utilizând API-ul PayPal.

Deschideți consola folosind rails c . Creați un abonament pentru contul dvs. PayPal cu:

 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)

Pasul 2: Actualizați ultimul produs din baza de date paypal_plan_name cu plan.id returnat.

Alerga:

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

Pasul 3: Adăugați rute pentru abonamentul PayPal.

Adăugați două rute noi în 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

Pasul 4: Gestionați crearea și execuția în serviciul PayPal.

Adăugați încă două funcții pentru crearea și executarea abonamentelor în Orders::Paypal of 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

În create_subscription , inițializam un acord apelând metoda PayPal::SDK::REST::Agreement.new și trecând product.paypal_plan_name ca unul dintre atributele sale. După aceea, îl creăm, iar acum va fi setat un token pentru acest ultim obiect. De asemenea, returnăm jetonul în partea din față.

În execute_subscription , găsim înregistrarea order creată în apelul anterior. După aceea, inițializam un nou acord, setăm simbolul acestui obiect anterior și îl executăm. Dacă acest ultim pas este efectuat cu succes, starea comenzii este setată la paypal_executed . Și acum revenim la front-end ID-ul acordului care este, de asemenea, stocat în order.chager_id .

Pasul 5: Adăugați acțiuni pentru crearea și executarea abonamentelor în orders_controller .

Schimbați app/controllers/orders_controller.rb . În partea de sus a clasei, în primul rând, și apoi actualizați callback prepare_new_order pentru a fi executat și înainte ca paypal_create_subscription să fie apelat:

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

De asemenea, în același fișier adăugați cele două funcții publice astfel încât acestea să apeleze serviciul Orders::Paypal cu un flux similar cu cel pe care îl avem deja în plățile 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 ...

Pasul 6: Adăugarea de gestionare a abonamentelor pentru createOrder și onApprove în front-end.

În cele din urmă, în index.html.haml , înlocuiți funcția paypal.Buttons cu următoarea, care va umple cele două else goale pe care le aveam înainte:

 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');

Crearea și execuția pentru abonamente au o logică similară cu cea folosită pentru plăți. O diferență este că, atunci când se execută plăți, datele din funcția de apel invers onApprove au deja un paymentID de plată care reprezintă codul de charge_id pentru a trimite formularul prin submitOrderPaypal(data.paymentID) . Pentru abonamente, obținem charge_id numai după ce îl executăm prin solicitarea unui POST pe paypal_execute_subscription_url , așa că putem apela submitOrderPaypal(executeData.id) .

Pasul 7: Testați aplicația.

  • Vizitați pagina de index.
  • Selectați un produs cu abonament și PayPal ca metodă de plată.
  • Faceți clic pe butonul de trimitere PayPal.
  • În fereastra pop-up PayPal:
    • Utilizați acreditările pentru contul de cumpărător pe care l-ați creat.
    • Conectați-vă și confirmați comanda.
    • Fereastra pop-up ar trebui să se închidă.
  • Verificați dacă sunteți redirecționat către o pagină de succes.
  • În cele din urmă, verificați dacă comanda a fost efectuată în contul PayPal, conectându-vă cu contul dvs. de afaceri la https://www.sandbox.paypal.com/signin și verificând tabloul de bord https://www.sandbox.paypal.com/listing/ tranzactii.

Concluzie

După ce ați citit acest articol, ar trebui să puteți integra plăți/taxări, precum și tranzacțiile de abonamente pentru PayPal și Stripe în aplicația dvs. Rails. Există o mulțime de puncte care ar putea fi îmbunătățite pe care nu le-am adăugat în acest articol de dragul conciziei. Am organizat totul pe baza unei presupuneri de dificultate:

  • Mai ușor:
    • Utilizați Transport Layer Security (TLS) pentru ca cererile dvs. să utilizeze HTTPS.
    • Implementați configurații ale mediului de producție atât pentru PayPal, cât și pentru Stripe.
    • Adăugați o pagină nouă, astfel încât utilizatorii să poată accesa un istoric al comenzilor anterioare.
  • Mediu:
    • Rambursați sau anulați abonamentele.
    • Oferiți o soluție pentru plățile utilizatorilor neînregistrați.
  • Mai tare:
    • Furnizați o modalitate de a elimina conturile și de a păstra simbolul și customer_id -ul acestora dacă utilizatorul dorește să revină. Dar după un anumit număr de zile, eliminați aceste date, astfel încât aplicația dvs. să fie mai compatibilă cu PCI.
    • Treceți la PayPal versiunea 2 API în partea de server (https://developer.paypal.com/docs/api/payments/v2/) Bijuteria pe care am folosit-o în acest tutorial paypal-sdk-rest , are doar o versiune beta pentru versiune 2, astfel încât să poată fi folosit cu precauție (https://github.com/paypal/PayPal-Ruby-SDK/tree/2.0-beta).
    • Includeți cererile idempotente.
      • Stripe: https://stripe.com/docs/api/idempotent_requests
      • PayPal: https://developer.paypal.com/docs/api-basics/#api-idempotency

De asemenea, vă recomand să citiți despre elementul Stripe Checkout, care este o altă modalitate de a integra Stripe în front-end. Spre deosebire de Stripe Elements, pe care le-am folosit în acest tutorial, Stripe Checkout deschide o fereastră pop-up după ce face clic pe un buton (similar cu PayPal) în care utilizatorul completează informațiile despre cardul de credit SAU alege să plătească cu Google Pay/Apple Pay https://stripe.com /docs/web.

O a doua recomandare de lectură sunt paginile de securitate pentru ambele Gateway-uri de plată.

  • Pentru Stripe
  • Pentru PayPal

În sfârșit, mulțumesc că ai citit acest articol! De asemenea, puteți verifica proiectul meu GitHub folosit pentru acest exemplu de proiect. Acolo, am adăugat și teste rspec în timpul dezvoltării.