socialgekon.com
  • Hoved
  • Trender
  • Agilt Talent
  • Baksiden
  • Brand Design
Web Front-End

Integrering av Stripe og PayPal betalingsmåter i Ruby on Rails

En nøkkelfunksjon for store e-handelsselskaper som AliExpress, Ebay og Amazon er en sikker måte å håndtere betalinger på, noe som er viktig for deres virksomhet. Hvis denne funksjonen mislykkes, vil konsekvensene være ødeleggende. Dette gjelder bransjeledere og Ruby on Rails-utviklere jobber med e-handelsapps.

Cybersikkerhet er viktig for å forhindre angrep, og en måte å gjøre transaksjonsprosessen sikrere er å be en tredjepartstjeneste om å håndtere den. Inkludering av betalingsportaler i applikasjonen din er en måte å oppnå dette målet på, da de gir brukerautorisasjon, datakryptering og et dashbord slik at du kan følge transaksjonsstatus på farten.

Det finnes en rekke betalingstjenester på nettet, men i denne artikkelen vil jeg fokusere på å integrere Stripe og PayPal til et Rails-program. For å nevne noen få andre: Amazon Payments, Square, SecurePay, WorldPay, Authorize.Net, 2Checkout.com, Braintree, Amazon eller BlueSnap.



Hvordan Payment Gateway Integration fungerer

Generell representasjon for transaksjoner som involverer betalingsportaler
Generell representasjon for transaksjoner som involverer betalingsportaler

Generelt vil det være et skjema / knapp i applikasjonen din der brukeren kan logge inn / sette inn kredittkortdata. PayPal og Stripe gjør allerede dette første trinnet sikrere ved å bruke iframe skjemaer eller popups som forhindrer søknaden din fra å lagre sensitiv brukerkredittkortinformasjon, da de vil returnere et token som representerer denne transaksjonen. Noen brukere kan også allerede føle seg tryggere på å behandle betalinger ved å vite at en tredjepartstjeneste håndterer transaksjonsprosessen, så dette kan også være en attraksjon for søknaden din.

Etter autentisering av brukerinformasjonen, vil en betalingsgateway bekrefte betalingen ved å kontakte en betalingsbehandler som kommuniserer med bankene for å gjøre opp betalinger. Dette sikrer at transaksjonen belastes / godskrives ordentlig.

Stripe bruker et kredittkortskjema som ber om kredittkortnummer, CV og utløpsdato. Så brukeren må fylle ut kredittkortinformasjon i de sikrede Stripe-inngangene. Etter at du har gitt denne informasjonen, behandler søknadsforsvaret denne betalingen gjennom et token.

I motsetning til Stripe, viderekobler PayPal brukeren til PayPal-påloggingssiden. Brukeren autoriserer og velger betalingsmåte via PayPal, og igjen vil din bakre håndtere poletter i stedet for brukersensitive data.

Det er viktig å nevne at for disse to betalingsportalene, bør bakenden din be om å fortsette transaksjonskjøringen gjennom Stripe eller PayPal API-er, noe som vil gi et OK / NOK-svar, så søknaden din bør omdirigere brukeren til en vellykket eller feilside tilsvarende.

Hensikten med denne artikkelen er å gi en rask guide for å integrere disse to betalingsportalene i en enkelt applikasjon. For alle tester vil vi bruke sandkasser og testkontoer levert av Stripe og PayPal for å simulere betalinger.

Oppsett

Før vi integrerer betalingsportaler, vil vi gjøre et oppsett for å initialisere applikasjonen ved å legge til perler, databasetabeller og en indeksside. Dette prosjektet ble opprettet ved hjelp av Rails versjon 5.2.3 og Ruby 2.6.3.

Merk: Du kan sjekke ut nytt Rails 6 har i vår siste artikkel .

Trinn 1: Initialiser et Rails-program.

Initialiser prosjektet ved å kjøre prosjektinitialiseringen med rails kommando med appnavnet ditt:

rails new YOUR_APP_NAME

Og cd i applikasjonsmappen din.

Steg 2: Installer perler.

Foruten Stripe og PayPal perler, ble det lagt til noen få andre perler:

  • devise: brukes til brukerautentisering og autorisasjon
  • haml: malverktøy for gjengivelse av brukersider
  • jquery-rails: for jquery i front-end-manusene
  • money-rails: for visning av formaterte pengeverdier

Legg til Gemfile:

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

Etter at du har lagt den til, kjør i CLI:

bundle install

Trinn 3: Initialiser edelstener.

Noen av disse perlene vil kreve initialisering i tillegg til å installere dem gjennom bundle.

Installere utarbeide:

rails g devise:install

Initialiserer money-rails:

rails g money_rails:initializer

Initialiser jquery-rails ved å legge til bunnen av app/assets/javascripts/application.js følgende:

//= require jquery //= require jquery_ujs

Trinn 4: Tabeller og migrasjoner

Tre bord vil bli brukt i dette prosjektet Brukere , Produkter , og Bestillinger .

  • Users: Vil bli generert gjennom utforming
  • Products kolonner:
    • name
    • price_cents
    • Stripe_plan_name: En ID som representerer en abonnementsplan opprettet i Stripe, slik at brukerne kan abonnere på den. Dette feltet er bare obligatorisk for produkter som er tilknyttet en Stripe-plan.
    • paypal_plan_name: Det samme som stripe_plan_name men for PayPal
  • Orders kolonner:
    • product_id
    • user_id
    • status: Dette vil informere om bestillingen venter, mislykkes eller betales.
    • token: Dette er et token generert fra API-ene (enten Stripe eller PayPal) for å initialisere en transaksjon.
    • price_cents: Ligner på produktet, men brukes for å gjøre denne verdien vedvarende i ordreposten
    • payment_gateway: Lagrer hvilken betalingsgateway som brukes for bestillingen PayPal eller Stripe
    • customer_id: Dette vil bli brukt til Stripe for å lagre Stripe-kunden for et abonnement, og det vil bli forklart mer detaljert i et senere avsnitt.

For å generere disse tabellene, må det genereres noen migreringer:

For å skape Brukertabell . Løpe:

rails g devise User

For å skape Produkter tabell . Generer en migrering ved å kjøre:

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

Åpne den opprettede migreringsfilen din, som skal være plassert på db/migrate/, og gjør endringer for at migrasjonen din skal ligne på denne:

class CreateProducts

For å skape Bestillingsbord . Generer en migrering ved å kjøre:

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

Åpne igjen den opprettede migreringsfilen din som skal være på db/migrate/ og gjør endringer i den filen for å få den til å ligne på denne:

class CreateOrders

Kjør databasemigrasjoner ved å utføre:

rails db:migrate

Trinn 5: Lag modeller.

Brukermodellen er allerede opprettet fra planlegge installasjon, og det vil ikke være behov for endringer på den. I tillegg til det vil det bli laget to modeller for Produkt og Rekkefølge .

Produkt. Legg til en ny fil, app/models/product.rb, med:

class Product

Rekkefølge. Legg til en ny fil, app/models/order.rb, med:

class Order { 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

Trinn 6: Befolk databasen.

En bruker og to produkter vil bli opprettet i konsollen. Ordreoppføringer vil bli opprettet i henhold til betalingstester.

  • Kjør rails s
  • Gå til http://localhost:3000 i nettleseren din
  • Du blir omdirigert til en registreringsside.
  • Registrer en bruker ved å fylle ut e-postadressen og passordet.
  • I terminalen din blir følgende logger bedt om å vise at en bruker ble opprettet i databasen din:
User Create (0.1ms) INSERT INTO 'users' ('email', 'encrypted_password', 'created_at', 'updated_at') VALUES (?, ?, ?, ?) …
  • Opprett to produkter uten abonnementer ved å kjøre rails c og legger til:
    • Product.create(name: 'Awesome T-Shirt', price_cents: 3000)
    • Product.create(name: 'Awesome Sneakers', price_cents: 5000)

Trinn 7: Opprett en indeksside

Hovedsiden for prosjektet inkluderer produktvalg for kjøp eller abonnement. I tillegg har den også en seksjon for valg av betalingsmåte (Stripe eller PayPal). En send-knapp brukes også for hver betalingstypetype, for PayPal vil vi legge til sin egen knappedesign gjennom JavaScript-biblioteket.

Først oppretter du rutene for index og submit i config/routes.rb.

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

Opprett og legg til handlinger index og submit i ordrekontrolløren app/controllers/orders_controller.rb. orders#index action lagrer to variabler som skal konsumeres i front-enden: @products_purchase som har en liste over produkter uten planer og @products_subscription som har produkter med både PayPal- og Stripe-planer.

class OrdersController

Opprett en fil i app/views/orders/index.html.haml. Denne filen inneholder alle inngangene vi skal sende til vår bakside gjennom innsendingsmetoden, og samspillet for betalingsportaler og produktvalg. Her er noen inngangsnavnattributter:

  • Orders[product_id] lagrer produkt-ID.
  • Orders[payment_gateway] inneholder betalingsportalen med enten Stripe- eller PayPal-verdier for den andre.
%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; }

Hvis du kjører søknaden din med rails s og besøk siden din i http://localhost:3000. Du bør kunne se siden som følger:

Rå indeks side uten Stripe og PayPal integrasjon
Rå indeks side uten Stripe og PayPal integrasjon

Lager for legitimasjon for betalingsgateway

PayPal og Stripe-nøkler lagres i en fil som ikke spores av Git. Det er to typer nøkler som er lagret i denne filen for hver betalingsportal, og foreløpig bruker vi en dummy-verdi for dem. Ytterligere anvisninger for å lage disse nøklene er presentert i ytterligere seksjoner.

Trinn 1: Legg til dette i .gitignore.

/config/application.yml

Steg 2: Opprett en fil med legitimasjonen din i config/application.yml. Den skal inneholde alle PayPal- og Stripe-sandkasse- / testnøkler for å få tilgang til disse API-ene.

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

Trinn 3: For å lagre variablene fra filen config/application.yml når applikasjonen starter, legg til disse linjene i config/application.rb inne i Application klasse slik at de vil være tilgjengelige i ENV.

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

Stripe-konfigurasjon

Vi vil legge til en perle for bruk av Stripe API: stripe-rails. Det er også nødvendig å opprette en Stripe-konto slik at gebyrer og abonnementer kan behandles. Hvis du må, kan du konsultere API-metodene for Stripe API i offisiell dokumentasjon .

Trinn 1: Legg stripe-perlen til prosjektet ditt.

De stripeskinner perle vil gi et grensesnitt for alle API-forespørsler som brukes i dette prosjektet.

Legg til dette i Gemfile:

gem 'stripe-rails'

Løpe:

bundle install

Steg 2: Generer API-nøklene dine.

For å ha API-nøklene for å kommunisere med Stripe, må du opprette en konto i Stripe. For å teste applikasjonen er det mulig å bruke testmodus, så ingen reell forretningsinformasjon må fylles ut i løpet av opprettelsen av Stripe-konto.

  • Opprett en konto i Stripe hvis du ikke har en ( https://dashboard.stripe.com/ ).
  • Mens du fortsatt er på Stripe-dashbordet, bytter du etter å ha logget på Se testdata på.
  • På https://dashboard.stripe.com/test/apikeys , erstatt YOUR_CREDENTIAL_HERE for verdiene STRIPE_PUBLISHABLE_KEY og STRIPE_SECRET_KEY i /config/application.yml med innholdet fra Publishable Key og Secret key.

Trinn 3: Initialiser Stripe-modulen

I tillegg til å erstatte nøklene, trenger vi fortsatt å initialisere Stripe-modulen, slik at den bruker nøklene som allerede er angitt i ENV.

Opprett en fil i config/initializers/stripe.rb med:

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

Trinn 4: Integrer Stripe i frontenden.

Vi vil legge til Stripe JavaScript-biblioteket og logikken for å sende et token som representerer brukerens kredittkortinformasjon og vil bli behandlet i vår bakside.

I index.html.haml fil, legg dette til øverst i filen. Dette vil bruke Stripe-modulen (levert av perlen) for å legge til Stripe javascript-biblioteket til brukerens side.

= stripe_javascript_tag

Stripe bruker sikre inndatafelt som er opprettet gjennom API-en. Når de er opprettet i en iframe opprettet gjennom dette API-et, trenger du ikke å bekymre deg for mulige sårbarheter som håndterer brukerens kredittkortinformasjon. I tillegg vil ikke bakenden din kunne behandle / lagre brukerfølsomme data, og den vil bare motta et token som representerer denne informasjonen.

Disse inntastingsfeltene opprettes ved å ringe stripe.elements().create('card'). Etter det er det bare nødvendig å ringe det returnerte objektet med mount() ved å sende som argument HTML-element-id / klasse der disse inngangene skal monteres. Mer informasjon finner du på Stripe .

Når brukeren trykker på sendeknappen med Stripe-betalingsmetoden, utføres en annen API-samtale som returnerer et løfte på det opprettede Stripe-kortelementet:

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

result variabelen til denne funksjonen, hvis den ikke har tildelt en eiendomsfeil, vil ha et token som kan hentes ved å få tilgang til attributtet result.token.id. Dette token vil bli sendt til bakenden.

For å gjøre disse endringene, erstatt den kommenterte koden // YOUR STRIPE AND PAYPAL CODE WILL BE HERE i index.html.haml med:

(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($('').val(result.token.id)); // Set order type $('#order-type').val('stripe'); $form.submit(); } }); return false; }); }()); //YOUR PAYPAL CODE WILL BE HERE

Hvis du besøker siden din, bør det se ut som følger med de nye Stripe sikre inndatafeltene:

Indekside integrert med Stripesikre inndatafelt.
Indekside integrert med Stripesikre inndatafelt.

Trinn 5: Test søknaden din.

Fyll ut kredittkortskjemaet med et testkort ( https://stripe.com/docs/testing ) og send inn siden. Sjekk om submit handling kalles med alle parametere ( Produkt ID , betaling_gateway , og token ) i serverutgangen.

Stripe Charges

Stripgebyr representerer engangstransaksjoner. Derfor vil du motta penger direkte fra klienten etter en Stripe-belastningstransaksjon. Dette er ideelt for salg av produkter som ikke er knyttet til planer. I en senere del vil jeg vise hvordan du gjør samme transaksjonstype med PayPal, men PayPal har navnet for denne typen transaksjoner innbetaling .

I denne delen vil jeg også gi alt skjelettet for å håndtere og sende inn en ordre. Vi oppretter en ordre i submit handling når Stripe-skjemaet sendes inn. Denne ordren vil i utgangspunktet ha Avventer status, så hvis noe går galt mens du behandler denne bestillingen, vil bestillingen fortsatt være Avventer .

Hvis det oppstår feil fra Stripe API-anrop, setter vi rekkefølgen i a mislyktes tilstand, og hvis belastningen er fullført, vil den være i betalt stat. Brukeren blir også omdirigert i henhold til Stripe API-svaret som vist i følgende graf:

Stripetransaksjoner.
Stripetransaksjoner.

I tillegg, når en stripe-belastning utføres, returneres en ID. Vi lagrer denne ID-en slik at du senere kan se etter den i Stripe-dashbordet ditt hvis nødvendig. Denne ID-en kan også brukes hvis ordren må refunderes. En slik ting vil ikke bli utforsket i denne artikkelen.

Trinn 1: Opprett Stripe-tjenesten.

Vi bruker en singleton-klasse for å representere Stripe-operasjoner ved hjelp av Stripe API. For å lage en kostnad, er metoden Stripe::Charge.create kalles, og det returnerte objekt-ID-attributtet lagres i ordreposten charge_id. Dette create funksjon kalles ved å sende tokenet som stammer fra frontend, bestillingsprisen og en beskrivelse.

Så opprett en ny mappe app/services/orders, og legg til en stripetjeneste: app/services/orders/stripe.rb inneholder Orders::Stripe singleton-klasse, som har en oppføring i metoden 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

Steg 2: Gjennomfør innsendingshandlingen og ring Stripe-tjenesten.

I orders_controller.rb, legg til følgende i submit handling, som i utgangspunktet vil kalle tjenesten Orders::Stripe.execute. Merk at to nye private funksjoner også ble lagt til: prepare_new_order og 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

Trinn 3: Test søknaden din.

Sjekk om innsendingshandlingen, når den ringes med et gyldig testkort, utfører en viderekobling til en vellykket melding. I tillegg sjekker du inn Stripe dashbord hvis bestillingen også vises.

Stripe-abonnementer

Abonnementer eller planer kan opprettes for gjentatte betalinger. Med denne typen produkter belastes brukeren daglig, ukentlig, månedlig eller årlig i henhold til plankonfigurasjon . I denne delen vil vi bruke feltet for produkt stripe_plan_name for å lagre plan-ID - faktisk er det mulig for oss å velge ID, og ​​vi vil kalle det premium-plan —som vil bli brukt for å opprette forholdet customer subscription.

Vi vil også opprette en ny kolonne for brukertabellen kalt stripe_customer_id som fylles med id-egenskapen til et Stripe-kundeobjekt. En Stripe-kunde opprettes når funksjonen Stripe::Customer.create kalles, og du kan også sjekke kundene som er opprettet og koblet til kontoen din i ( https://dashboard.stripe.com/test/customers ). Kunder opprettes ved å sende et source parameter som i vårt tilfelle er tokenet som genereres i frontenden som sendes når skjemaet sendes inn.

Kundeobjektet hentet fra sistnevnte Stripe API-anrop, brukes også til å opprette et abonnement som gjøres ved å ringe customer.subscriptions.create og sende plan-ID som parameter.

I tillegg vil stripe-rails gem gir grensesnittet for å hente og oppdatere en kunde fra Stripe, som gjøres ved å ringe Stripe::Customer.retrieve og henholdsvis Stripe::Customer.update

Så når en brukerpost allerede har en stripe_customer_id, i stedet for å opprette en ny kunde ved hjelp av Stripe::Customer.create, vil vi ringe Stripe::Customer.retrieve passerer stripe_customer_id som parameter, etterfulgt av a Stripe::Customer.update, og i dette tilfellet å sende token en parameter.

For det første skal vi lage en plan ved hjelp av Stripe API, slik at vi kan lage et nytt abonnementsprodukt ved hjelp av feltet stripe_plan_name. Etterpå vil vi gjøre endringer i orders_controller og Stripe-tjeneste slik at opprettelse og gjennomføring av Stripe-abonnementer håndteres.

Trinn 1: Lag en plan ved hjelp av Stripe API.

Åpne konsollen ved hjelp av kommandoen rails c . Opprett abonnement for Stripe-kontoen din med:

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

Hvis det returnerte resultatet i dette trinnet er sant, betyr det at planen ble opprettet, og du kan få tilgang til den i din Stripe dashbord .

Steg 2: Opprett et produkt i databasen med stripe_plan_name feltsett.

Lag nå et produkt med stripe_plan_name angitt som premium-plan i databasen:

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

Trinn 3: Generer en migrering for å legge til en kolonne stripe_customer_id i users bord.

Kjør følgende i terminalen:

rails generate migration AddStripeCustomerIdToUser stripe_customer_id:string rails db:migrate

Trinn 4: Implementer abonnementslogikken i Stripe-serviceklassen.

Legg til to funksjoner til i de private metodene til app/services/orders/stripe.rb: execute_subscription er ansvarlig for å lage abonnementene i kundens objekt. Funksjonen find_or_create_customer er ansvarlig for å returnere den allerede opprettede kunden eller ved å returnere en nyopprettet kunde.

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

Til slutt, i execute funksjon i samme fil (app/services/orders/stripe.rb), vil vi først ringe find_or_create_customer og deretter utføre abonnementet ved å ringe execute_subscription ved å passere den forrige hentede / opprettede kunden. Så erstatt kommentaren #SUBSCRIPTIONS WILL BE HANDLED HERE i execute metode med følgende kode:

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)

Trinn 5: Test søknaden din.

Besøk nettstedet ditt, velg abonnementsproduktet Premium Plan, og fyll ut et gyldig testkort. Etter at du har sendt den, skal den omdirigere deg til en vellykket side. I tillegg sjekker du inn Stripe dashbord hvis abonnementet ble opprettet.

PayPal-konfigurasjon

Som vi gjorde i Stripe, vil vi også legge til en perle for bruk av PayPal API: paypal-sdk-rest, og det er også nødvendig å opprette en PayPal-konto. En beskrivende arbeidsflyt for PayPal som bruker denne perlen, kan konsulteres i tjenestemannen PayPal API-dokumentasjon .

Trinn 1: Legg til paypal-sdk-rest perle til prosjektet ditt.

Legg til dette i Gemfile:

gem 'paypal-sdk-rest'

Løpe:

bundle install

Steg 2: Generer API-nøklene dine.

For å ha API-nøklene for å kommunisere med PayPal, må du opprette en PayPal-konto. Så:

  • Opprett en konto (eller bruk PayPal-kontoen din) på https://developer.paypal.com/ .
  • Fortsatt logget på kontoen din, opprett to sandkassokontoer på https://developer.paypal.com/developer/accounts/ :
    • Personlig (kjøperkonto) - Dette vil bli brukt i testene dine for å foreta betalinger og abonnementer.
    • Business (Merchant Account) - Dette vil bli koblet til applikasjonen, som vil ha API-nøklene vi leter etter. I tillegg til det kan alle transaksjoner følges i denne kontoen.
  • Opprett en app på https://developer.paypal.com/developer/applications bruker den forrige forretningssandkaskontoen.
  • Etter dette trinnet vil du motta to nøkler for PayPal: Client ID og Secret.
  • I config/application.yml, erstatt YOUR_CREDENTIAL_HERE fra PAYPAL_CLIENT_ID og PAYPAL_CLIENT_SECRET med nøklene du nettopp har mottatt.

Trinn 3: Initialiser PayPal-modulen.

I likhet med Stripe, foruten å erstatte nøklene i application.yml, må vi fortsatt initialisere PayPal-modulen slik at den kan bruke nøklene som allerede er angitt i ENV variabel. For dette formålet, opprett en fil i config/initializers/paypal.rb med:

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

Trinn 4: Integrer PayPal i frontenden.

I index.html.haml legg dette til toppen av filen:

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

I motsetning til Stripe bruker PayPal bare en knapp som, når du klikker på den, åpner en sikker popup der brukeren kan logge på og fortsette med betaling / abonnement. Denne knappen kan gjengis ved å ringe metoden paypal.Button(PARAM1).render(PARAM2).

  • PARAM1 er et objekt med miljøkonfigurasjonen og to tilbakeringingsfunksjoner som egenskaper: createOrder og onApprove.
  • PARAM2 angir HTML-elementidentifikatoren som PayPal-knappen skal festes til.

Så, fortsatt i samme fil, erstatt den kommenterte koden YOUR PAYPAL CODE WILL BE HERE med:

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

Trinn 5: Test søknaden din.

Besøk siden din og sjekk om PayPal-knappen blir gjengitt når du velger PayPal som betalingsmåte.

PayPal-transaksjoner

Logikken for PayPal-transaksjoner, i motsetning til Stripe, er litt mer kompleks ved å involvere flere forespørsler fra frontenden til bakenden. Derfor eksisterer denne delen. Jeg vil forklare mer eller mindre (uten kode) hvordan funksjonene beskrevet i createOrder og onApprove metoder skal implementeres og hva som forventes i backend-prosessene også.

Trinn 1: Når brukeren klikker på PayPal-sendeknappen, er en PayPal-popup som ber om brukerlegitimasjon åpen, men i lastetilstand. Funksjonen tilbakeringing createOrder er kalt.

PayPal popup, lastestatus
PayPal popup, lastestatus

Steg 2: I denne funksjonen vil vi utføre en forespørsel til back-enden som vil opprette en betaling / abonnement. Dette er begynnelsen på en transaksjon, og ingen gebyrer vil bli påført ennå, så transaksjonen er faktisk i en Avventer stat. Vår bakside skal gi oss et token som genereres ved hjelp av PayPal-modul (levert gjennom paypal-rest-sdk perlen).

Trinn 3: Fortsatt i createOrder tilbakeringing, vi returnerer dette tokenet som er generert i back-enden, og hvis alt er i orden, vil PayPal-popup-vinduet gjengi følgende og be om brukerlegitimasjon:

PayPal popup, brukerlegitimasjon
PayPal popup, brukerlegitimasjon

Trinn 4: Etter at brukeren har logget på og valgt betalingsmåte, vil popup-en endre statusen til følgende:

PayPal popup, autorisert transaksjon
PayPal popup, autorisert transaksjon

Trinn 5: onApprove funksjon tilbakeringing kalles nå. Vi har definert det som følgende: onApprove: function(data). data objektet vil ha betalingsinformasjonen for å kunne utføre den. I denne tilbakeringingen vil en annen forespørsel til back-end-funksjonen bli utført denne gangen og sende dataobjektet for å utføre PayPal-bestillingen.

Trinn 6: Vår bakside utfører denne transaksjonen og returnerer 200 (hvis vellykket).

Trinn 7: Når bakenden kommer tilbake, sender vi inn skjemaet. Dette er den tredje forespørselen vi stiller til vår bakside.

Vær oppmerksom på at, i motsetning til Stripe, er det tre forespørsler om back-enden vår i denne prosessen. Og vi vil holde status for ordreoppføringen synkronisert tilsvarende:

  • createOrder tilbakeringing: Det opprettes en transaksjon, og det opprettes også en ordreoppføring; derfor er det i en Avventer status som standard.
  • onApprove tilbakeringing: Transaksjonen blir utført og bestillingen vår blir satt til paypal_utført .
  • Bestillingssiden er sendt: Transaksjonen ble allerede utført, så ingenting endres. Bestillingsposten endrer status til betalt .

Hele denne prosessen er beskrevet i følgende graf:

PayPal-transaksjoner
PayPal-transaksjoner

PayPal-betalinger

PayPal-betalinger følger samme logikk som Stripe Charges, så de representerer engangstransaksjoner, men som nevnt i forrige avsnitt har de en annen flytlogikk. Dette er endringene som må utføres for å håndtere PayPal-betalinger:

Trinn 1: Lag nye ruter for PayPal og utfør betalinger.

Legg til følgende ruter i 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

Dette vil opprette to nye ruter for å opprette og utføre betalinger som vil bli håndtert i paypal_create_payment og paypal_execute_payment bestiller kontrollermetoder.

Steg 2: Opprett PayPal-tjenesten.

Legg til singleton-klassen Orders::Paypal på: app/services/orders/paypal.rb.

Denne tjenesten vil i utgangspunktet ha tre ansvarsområder:

  • create_payment metoden oppretter en betaling ved å ringe PayPal::SDK::REST::Payment.new. EN token genereres og returneres til frontend.
  • execute_payment metoden utfører betalingen ved først å finne det forrige opprettede betalingsobjektet gjennom PayPal::SDK::REST::Payment.find(payment_id) som bruker betaling_id som et argument som har samme verdi som charge_id lagret i forrige trinn i ordreobjektet. Etter det ringer vi execute i betalingsobjektet med en gitt betaler som parameter. Denne betaleren gis av grensesnittet etter at brukeren har oppgitt legitimasjon og valgt en betalingsmåte i popup-vinduet.
  • finish metoden finner en ordre etter en bestemt charge_id spørring etter nylig opprettede bestillinger i paypal_utført stat. Hvis en post blir funnet, blir den merket som betalt.
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

Trinn 3: Ring PayPal-tjenesten i kontrolleren i innsendingshandlingen.

Legg til en tilbakeringing for prepare_new_order før handlingen paypal_create_payment (som vil bli lagt til i neste trinn) blir bedt om ved å legge til følgende i filen app/controllers/orders_controller.rb:

class OrdersController

Igjen, i samme fil, ring PayPal-tjenesten i innsendingshandlingen ved å erstatte den kommenterte koden #PAYPAL WILL BE HANDLED HERE. med følgende:

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

Trinn 4: Lag handlingene for håndtering av forespørsler.

Likevel, i app/controllers/orders_controller.rb fil, opprett to nye handlinger (som skal være offentlige) for håndtering av forespørsler til paypal_create_payment og paypal_execute_payment ruter:

  • paypal_create_payment metode: Kaller tjenestemetoden vår create_payment. Hvis det returnerer vellykket, vil det returnere bestillingen token opprettet av Orders::Paypal.create_payment.
  • paypal_execute_payment metode: Kaller tjenestemetoden vår execute_payment (som utfører betalingene våre). Hvis betalingen er vellykket, returnerer den 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 ...

Trinn 5: Implementere front-end tilbakeringingsfunksjonene for createOrder og onApprove.

Lag din paypal.Button.render ring ser slik ut:

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

Som nevnt i forrige avsnitt kaller vi paypal_create_payment_url for createOrder tilbakeringing og paypal_execute_payment_url for onApprove Ring tilbake. Legg merke til at hvis den siste forespørselen returnerer suksess, sender vi inn bestillingen, som er den tredje forespørselen som er sendt til serveren.

I createOrder funksjonsbehandler, returnerer vi et token (hentet fra bakenden). I onApprove tilbakeringing, vi har to egenskaper sendt til back-end paymentID og payerID. Disse vil bli brukt for å utføre betalingen.

Merk til slutt at vi har to tomme else klausuler når jeg gir plass til neste avsnitt der vi skal legge til PayPal-abonnementer.

Hvis du besøker siden din etter å ha integrert front-end JavaScript-delen og velger PayPal som betalingsmåte, bør det se slik ut:

Indekside etter integrering med PayPal
Indekside etter integrering med PayPal

Trinn 6: Test søknaden din.

  • Besøk indeksiden.
  • Velg et betalings- / avgiftsprodukt og PayPal som betalingsmåte.
  • Klikk på Send PayPal-knappen.
  • I PayPal-popup:
    • Bruk legitimasjonen til kjøperkontoen du opprettet.
    • Logg inn og bekreft bestillingen.
    • Popup-vinduet skal lukkes.
  • Sjekk om du blir omdirigert til en suksessside.
  • Til slutt, sjekk om bestillingen ble utført på PayPal-kontoen ved å logge på med bedriftskontoen din på https://www.sandbox.paypal.com/signin og sjekke dashbordet https://www.sandbox.paypal.com/listing/transactions .

PayPal-abonnementer

PayPal-planer / avtaler / abonnementer følger samme logikk som Stripe-abonnementer, og er opprettet for gjentatte betalinger. Med denne typen produkter belastes brukeren daglig, ukentlig, månedlig eller årlig i henhold til brukerens konfigurasjon .

Vi bruker feltet for produkt paypal_plan_name for å lagre plan-ID levert av PayPal. I dette tilfellet, forskjellig fra Stripe, velger vi ikke ID-en, og PayPal returnerer denne verdien som vil bli brukt til å oppdatere det siste produktet som ble opprettet i databasen vår.

For å opprette et abonnement, ingen customer informasjon kreves i ethvert trinn, som metoden onApprove håndterer sannsynligvis denne koblingen i den underliggende implementeringen. Så bordene våre vil forbli de samme.

Trinn 1: Lag en plan ved hjelp av PayPal API.

Åpne konsollen ved hjelp av kommandoen rails c . Opprett et abonnement for PayPal-kontoen din med:

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)

Steg 2: Oppdater det siste produktet i databasen paypal_plan_name med den returnerte plan.id.

Løpe:

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

Trinn 3: Legg til ruter for PayPal-abonnement.

Legg til to nye ruter i 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

Trinn 4: Håndter oppretting og utførelse i PayPal-tjenesten.

Legg til to funksjoner til for å opprette og utføre abonnementer i Orders::Paypal av 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

I create_subscription initialiserer vi en avtale ved å kalle metoden PayPal::SDK::REST::Agreement.new og passerer product.paypal_plan_name som en av egenskapene. Etterpå lager vi det, og nå settes et token for dette siste objektet. Vi returnerer også token til frontenden.

I execute_subscription finner vi order posten som ble opprettet i forrige samtale. Etter det initialiserer vi en ny avtale, vi setter tegnet på dette forrige objektet og utfører det. Hvis dette siste trinnet er vellykket, er ordrestatus satt til paypal_utført . Og nå går vi tilbake til frontend avtalen ID som også er lagret i order.chager_id.

Trinn 5: Legg til handlinger for å opprette og utføre abonnementer i orders_controller.

Endre app/controllers/orders_controller.rb. Først i toppen av klassen, og oppdater deretter tilbakeringingen prepare_new_order skal også utføres før paypal_create_subscription er kalt:

class OrdersController

Legg også til de to offentlige funksjonene i samme fil, slik at de kaller Orders::Paypal tjeneste med en lignende flyt som vi allerede har i PayPal-betalinger:

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

Trinn 6: Legger til abonnementshåndtering for createOrder og onApprove tilbakeringinger i frontenden.

Endelig, i index.html.haml, erstatt paypal.Buttons funksjon med følgende, som vil fylle de to tomme else vi hadde fø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');

Opprettelse og utførelse for abonnement har en lignende logikk som brukt for betalinger. En forskjell er at dataene fra tilbakeringingsfunksjonen onApprove når du utfører betalinger har allerede en paymentID som representerer charge_id å sende skjemaet gjennom submitOrderPaypal(data.paymentID). For abonnementer får vi charge_id bare etter å ha utført den ved å be om en POST på paypal_execute_subscription_url, så vi kan ringe submitOrderPaypal(executeData.id).

Trinn 7: Test søknaden din.

  • Besøk indeksiden.
  • Velg et abonnementsprodukt og PayPal som betalingsmåte.
  • Klikk på Send PayPal-knappen.
  • I PayPal-popup:
    • Bruk legitimasjonen til kjøperkontoen du opprettet.
    • Logg inn og bekreft bestillingen.
    • Popup-vinduet skal lukkes.
  • Sjekk om du blir omdirigert til en suksessside.
  • Kontroller til slutt om bestillingen ble utført på PayPal-kontoen ved å logge på med bedriftskontoen din på https://www.sandbox.paypal.com/signin og sjekke dashbordet https://www.sandbox.paypal.com/listing/transactions .

Konklusjon

Etter å ha lest denne artikkelen, bør du kunne integrere betalinger / avgifter samt abonnementstransaksjoner for PayPal og Stripe i Rails-applikasjonen. Det er mange punkter som kan forbedres, som jeg ikke la til i denne artikkelen for kortfattethet. Jeg organiserte alt basert på en antagelse om vanskeligheter:

  • Lettere:
    • Bruk Transport Layer Security (TLS) slik at dine forespørsler bruker HTTPS.
    • Implementere produksjonsmiljøkonfigurasjoner for både PayPal og Stripe.
    • Legg til en ny side slik at brukere kan få tilgang til en historie med tidligere ordrer.
  • Medium:
    • Refunder eller kanseller abonnement.
    • Gi en løsning for ikke-registrerte brukerbetalinger.
  • Hardere:
    • Gi en måte å fjerne kontoer og beholde token og Kunde ID hvis brukeren ønsker å komme tilbake. Men etter en viss mengde dager, fjern disse dataene slik at applikasjonen din er mer PCI-kompatibel.
    • Gå til PayPal versjon 2 API på serversiden ( https://developer.paypal.com/docs/api/payments/v2/ ) Perlen vi brukte i denne opplæringen paypal-sdk-hvile , har bare en betaversjon for versjon 2, slik at den kan brukes med forsiktighet ( https://github.com/paypal/PayPal-Ruby-SDK/tree/2.0-beta ).
    • Inkluder idempotente forespørsler.
      • Stripe: https://stripe.com/docs/api/idempotent_requests
      • PayPal: https://developer.paypal.com/docs/api-basics/#api-idempotency

Jeg anbefaler også å lese om Stripe Checkout-element, som er en annen måte å integrere Stripe i frontenden. I motsetning til Stripe Elements, som vi brukte i denne opplæringen, åpner Stripe Checkout en popup etter å ha klikket på en knapp (ligner på PayPal) der brukeren fyller ut kredittkortinformasjon ELLER velger å betale med Google Pay / Apple Pay https://stripe.com/docs/web .

En annen leseanbefaling er sikkerhetssidene for begge Payment Gateways.

  • Til Stripe
  • Til PayPal

Til slutt, takk for at du leser denne artikkelen! Du kan også sjekke min GitHub-prosjekt brukt til dette prosjekteksemplet . Der la jeg til rspec tester også mens du utvikler.

Forstå det grunnleggende

Hva er Stripe og hvordan fungerer det?

Stripe er et selskap som utvikler programvare for enkeltpersoner eller virksomheter for å utføre sikre betalinger over internett.

Hva er forskjellen mellom PayPal og Stripe?

De tilbyr forskjellige applikasjoner som involverer betaling, og de har forskjellige gebyrer for å bruke tjenestene sine.

Hva er et betalingsmåte-token?

Betalingstokenisering er en prosess for å håndtere sensitive data fra brukere og transformere dem til tokens, så det er ingen sensitiv datalekkasje.

Er PayPal en betalingsportal eller prosessor?

PayPal er ikke en gateway, men en komplett selgerløsning. Imidlertid bruker den en betalingsgateway kalt Payflow.

Er Stripe en betalingsgateway eller prosessor?

Stripe er en betalingsport som håndterer kundenes kort.

Hold deg kult: Hvordan ta designfeedback strategisk

Ux Design

Hold deg kult: Hvordan ta designfeedback strategisk
En veiledning i designflyt for utviklere: Lever bedre UI / UX i tide

En veiledning i designflyt for utviklere: Lever bedre UI / UX i tide

Livsstil

Populære Innlegg
Veiledning i videospillfysikk - Del I: En introduksjon til stiv kroppsdynamikk
Veiledning i videospillfysikk - Del I: En introduksjon til stiv kroppsdynamikk
Navigere i nyansene ved due diligence for investeringer
Navigere i nyansene ved due diligence for investeringer
Slik tar du nydelig landskapsfotografering med en iPhone
Slik tar du nydelig landskapsfotografering med en iPhone
Introduksjon til Deep Learning Trading in Hedge Funds
Introduksjon til Deep Learning Trading in Hedge Funds
Figma vs. Sketch vs. Axure - En oppgavebasert gjennomgang
Figma vs. Sketch vs. Axure - En oppgavebasert gjennomgang
 
Tre helsevesensteknologiinnovasjoner: Få bedre resultater og lavere kostnader
Tre helsevesensteknologiinnovasjoner: Få bedre resultater og lavere kostnader
Omfavne Sass: Hvorfor du bør slutte å bruke Vanilla CSS
Omfavne Sass: Hvorfor du bør slutte å bruke Vanilla CSS
Hvordan lagre Instagram-bilder på en iPhone
Hvordan lagre Instagram-bilder på en iPhone
Cybersecurity: Hva enhver administrerende direktør og økonomidirektør bør vite
Cybersecurity: Hva enhver administrerende direktør og økonomidirektør bør vite
Hvordan øke hastigheten på iPhone
Hvordan øke hastigheten på iPhone
Kategorier
Fremtidens ArbeidKpi Og AnalyticsDesign ProsessProduktets LivssyklusMobil DesignProsjektledelseAgilt TalentWeb Front-EndInnleggLagring

© 2023 | Alle Rettigheter Reservert

socialgekon.com