portaldacalheta.pt
  • หลัก
  • ทีมแบบกระจาย
  • เคล็ดลับและเครื่องมือ
  • ชีวิตนักออกแบบ
  • นวัตกรรม
ส่วนหน้าของเว็บ

การผสานรวมวิธีการชำระเงิน Stripe และ PayPal ใน Ruby on Rails



คุณลักษณะสำคัญสำหรับ บริษัท อีคอมเมิร์ซขนาดใหญ่เช่น AliExpress, Ebay และ Amazon คือวิธีจัดการการชำระเงินที่ปลอดภัยซึ่งเป็นสิ่งจำเป็นสำหรับธุรกิจของพวกเขา หากคุณสมบัตินี้ล้มเหลวผลที่ตามมาจะร้ายแรง สิ่งนี้ใช้กับผู้นำในอุตสาหกรรมและ นักพัฒนา Ruby on Rails ทำงานบนแอพอีคอมเมิร์ซ

การรักษาความปลอดภัยทางไซเบอร์เป็นสิ่งสำคัญในการป้องกันการโจมตีและวิธีที่จะทำให้กระบวนการทำธุรกรรมปลอดภัยยิ่งขึ้นคือการขอให้บริการของบุคคลที่สามจัดการ การรวมเกตเวย์การชำระเงินไว้ในแอปพลิเคชันของคุณเป็นวิธีที่จะบรรลุเป้าหมายนี้เนื่องจากมีการอนุญาตผู้ใช้การเข้ารหัสข้อมูลและแดชบอร์ดเพื่อให้คุณสามารถติดตามสถานะการทำธุรกรรมได้ทันที



มีบริการเกตเวย์การชำระเงินที่หลากหลายบนเว็บ แต่ในบทความนี้ฉันจะเน้นไปที่การบูรณาการ ลาย และ PayPal ไปยังแอปพลิเคชัน Rails หากต้องการพูดถึงคนอื่น ๆ : Amazon Payments, Square, SecurePay, WorldPay, Authorize.Net, 2Checkout.com, Braintree, Amazon หรือ BlueSnap



การรวมเกตเวย์การชำระเงินทำงานอย่างไร

การแสดงทั่วไปสำหรับธุรกรรมที่เกี่ยวข้องกับเกตเวย์การชำระเงิน
การแสดงทั่วไปสำหรับธุรกรรมที่เกี่ยวข้องกับเกตเวย์การชำระเงิน

โดยทั่วไปจะมีแบบฟอร์ม / ปุ่มในแอปพลิเคชันของคุณซึ่งผู้ใช้สามารถเข้าสู่ระบบ / ใส่ข้อมูลบัตรเครดิตได้ PayPal และ Stripe ทำให้ขั้นตอนแรกนี้ปลอดภัยยิ่งขึ้นโดยใช้ iframe แบบฟอร์มหรือ popups ซึ่งป้องกันไม่ให้แอปพลิเคชันของคุณจัดเก็บข้อมูลบัตรเครดิตของผู้ใช้ที่ละเอียดอ่อนเนื่องจากจะส่งคืนโทเค็นที่แสดงธุรกรรมนี้ ผู้ใช้บางรายอาจรู้สึกมั่นใจมากขึ้นในการดำเนินการชำระเงินโดยทราบว่าบริการของบุคคลที่สามกำลังจัดการขั้นตอนการทำธุรกรรมดังนั้นนี่อาจเป็นสิ่งดึงดูดสำหรับใบสมัครของคุณ



หลังจากตรวจสอบสิทธิ์ข้อมูลผู้ใช้แล้วเกตเวย์การชำระเงินจะยืนยันการชำระเงินโดยติดต่อผู้ประมวลผลการชำระเงินซึ่งติดต่อกับธนาคารเพื่อชำระเงิน เพื่อให้แน่ใจว่าธุรกรรมถูกหัก / เครดิตอย่างถูกต้อง

Stripe ใช้แบบฟอร์มบัตรเครดิตที่ถามหมายเลขบัตรเครดิตประวัติย่อและวันหมดอายุ ดังนั้นผู้ใช้จะต้องกรอกข้อมูลบัตรเครดิตในอินพุต Stripe ที่ปลอดภัย หลังจากให้ข้อมูลนี้แล้วแอปพลิเคชันของคุณจะประมวลผลการชำระเงินนี้ผ่านโทเค็น



ไม่เหมือน Stripe ตรงที่ PayPal เปลี่ยนเส้นทางผู้ใช้ไปยังหน้าเข้าสู่ระบบ PayPal ผู้ใช้อนุญาตและเลือกวิธีการชำระเงินผ่าน PayPal และอีกครั้งส่วนหลังของคุณจะจัดการโทเค็นแทนข้อมูลที่ละเอียดอ่อนของผู้ใช้

สิ่งสำคัญคือต้องระบุว่าสำหรับเกตเวย์การชำระเงินทั้งสองนี้ส่วนหลังของคุณควรขอให้ดำเนินการทำธุรกรรมผ่าน Stripe หรือ PayPal API ซึ่งจะตอบตกลง / NOK ดังนั้นแอปพลิเคชันของคุณควรเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าสำเร็จหรือหน้าข้อผิดพลาดตามนั้น



วัตถุประสงค์ของบทความนี้คือเพื่อให้คำแนะนำโดยย่อสำหรับการรวมเกตเวย์การชำระเงินทั้งสองนี้ไว้ในแอปพลิเคชันเดียว สำหรับการทดสอบทั้งหมดเราจะใช้แซนด์บ็อกซ์และบัญชีทดสอบที่ Stripe และ PayPal จัดหาให้เพื่อจำลองการชำระเงิน

ติดตั้ง

ก่อนที่จะรวมเกตเวย์การชำระเงินเราจะทำการตั้งค่าสำหรับการเริ่มต้นแอปพลิเคชันโดยการเพิ่มอัญมณีตารางฐานข้อมูลและหน้าดัชนี โครงการนี้สร้างขึ้นโดยใช้ Rails เวอร์ชัน 5.2.3 และ Ruby 2.6.3



บันทึก: คุณสามารถตรวจสอบใหม่ คุณลักษณะ Rails 6 ในบทความล่าสุดของเรา .

ขั้นตอนที่ 1: เริ่มต้นแอปพลิเคชัน Rails



เริ่มต้นโครงการโดยการรันการเริ่มต้นโครงการด้วย rails คำสั่งด้วยชื่อแอปของคุณ:

rails new YOUR_APP_NAME

และ cd ในโฟลเดอร์แอปพลิเคชันของคุณ



ขั้นตอนที่ 2: ติดตั้งอัญมณี

นอกจากอัญมณี Stripe และ PayPal แล้วยังมีการเพิ่มอัญมณีอื่น ๆ อีกเล็กน้อย:

  • devise: ใช้สำหรับการตรวจสอบผู้ใช้และการอนุญาต
  • haml: เครื่องมือสร้างเทมเพลตสำหรับการแสดงผลหน้าผู้ใช้
  • jquery-rails: สำหรับ jquery ในสคริปต์ส่วนหน้า
  • money-rails: สำหรับการแสดงค่าเงินที่จัดรูปแบบ

เพิ่มใน Gemfile:

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

หลังจากเพิ่มแล้วให้รันใน CLI ของคุณ:

bundle install

ขั้นตอนที่ 3: เริ่มต้นอัญมณี

อัญมณีเหล่านี้บางส่วนจะต้องมีการเริ่มต้นนอกเหนือจากการติดตั้งผ่าน bundle

การติดตั้งอุปกรณ์:

rails g devise:install

การเริ่มต้น money-rails:

rails g money_rails:initializer

เริ่มต้น jquery-rails โดยต่อท้าย app/assets/javascripts/application.js ดังต่อไปนี้:

//= require jquery //= require jquery_ujs

ขั้นตอนที่ 4: ตารางและการโยกย้าย

สามตารางจะถูกใช้ในโครงการนี้ ผู้ใช้ , ผลิตภัณฑ์ และ คำสั่งซื้อ .

  • Users: จะถูกสร้างขึ้นโดยการประดิษฐ์
  • Products คอลัมน์:
    • name
    • price_cents
    • Stripe_plan_name: ID ที่แสดงแผนการสมัครสมาชิกที่สร้างขึ้นใน Stripe เพื่อให้ผู้ใช้สมัครสมาชิกได้ ฟิลด์นี้จำเป็นสำหรับผลิตภัณฑ์ที่เกี่ยวข้องกับแผน Stripe เท่านั้น
    • paypal_plan_name: เหมือนกับ stripe_plan_name แต่สำหรับ PayPal
  • Orders คอลัมน์:
    • product_id
    • user_id
    • status: สิ่งนี้จะแจ้งให้ทราบว่าคำสั่งซื้ออยู่ระหว่างดำเนินการล้มเหลวหรือชำระเงิน
    • token: นี่คือโทเค็นที่สร้างขึ้นจาก API (ไม่ว่าจะเป็น Stripe หรือ PayPal) เพื่อเริ่มต้นธุรกรรม
    • price_cents: คล้ายกับผลิตภัณฑ์ แต่ใช้เพื่อทำให้ค่านี้คงอยู่ในบันทึกคำสั่งซื้อ
    • payment_gateway: ร้านค้าที่ใช้เกตเวย์การชำระเงินสำหรับการสั่งซื้อ PayPal หรือ Stripe
    • customer_id: จะใช้สำหรับ Stripe เพื่อจัดเก็บลูกค้า Stripe สำหรับการสมัครสมาชิกและจะมีการอธิบายรายละเอียดเพิ่มเติมในส่วนต่อไป

ในการสร้างตารางเหล่านี้ต้องมีการสร้างการย้ายข้อมูลเล็กน้อย:

สำหรับการสร้างไฟล์ ตารางผู้ใช้ . วิ่ง:

rails g devise User

สำหรับการสร้างไฟล์ ตารางผลิตภัณฑ์ . สร้างการย้ายข้อมูลโดยเรียกใช้:

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

เปิดไฟล์การย้ายข้อมูลที่คุณสร้างขึ้นซึ่งควรอยู่ที่ db/migrate/ และทำการเปลี่ยนแปลงเพื่อให้การย้ายข้อมูลของคุณมีลักษณะคล้ายกับสิ่งนี้:

class CreateProducts

สำหรับการสร้างไฟล์ ตารางคำสั่งซื้อ . สร้างการย้ายข้อมูลโดยเรียกใช้:

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

อีกครั้งเปิดไฟล์การย้ายข้อมูลที่คุณสร้างขึ้นซึ่งควรอยู่ที่ db/migrate/ และทำการเปลี่ยนแปลงไฟล์นั้นเพื่อให้มีลักษณะคล้ายกับสิ่งนี้:

class CreateOrders

เรียกใช้การย้ายฐานข้อมูลโดยดำเนินการ:

rails db:migrate

ขั้นตอนที่ 5: สร้างแบบจำลอง

โมเดลผู้ใช้ถูกสร้างขึ้นแล้วจากการติดตั้งอุปกรณ์และไม่จำเป็นต้องมีการเปลี่ยนแปลงใด ๆ นอกจากนั้นจะมีการสร้างโมเดลสองรุ่นสำหรับ สินค้า และ ใบสั่ง .

สินค้า. เพิ่มไฟล์ใหม่ app/models/product.rb ด้วย:

class Product

ใบสั่ง. เพิ่มไฟล์ใหม่ app/models/order.rb ด้วย:

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

ขั้นตอนที่ 6: เติมฐานข้อมูล

ผู้ใช้และผลิตภัณฑ์สองรายการจะถูกสร้างขึ้นในคอนโซล บันทึกการสั่งซื้อจะถูกสร้างขึ้นตามการทดสอบการชำระเงิน

  • เรียกใช้ rails s
  • ในเบราว์เซอร์ของคุณไปที่ http://localhost:3000
  • คุณจะถูกเปลี่ยนเส้นทางไปยังหน้าลงชื่อสมัครใช้
  • ลงทะเบียนผู้ใช้โดยกรอกที่อยู่อีเมลและรหัสผ่าน
  • ในเทอร์มินัลของคุณบันทึกต่อไปนี้จะถูกแจ้งว่ามีการสร้างผู้ใช้ในฐานข้อมูลของคุณ:
User Create (0.1ms) INSERT INTO 'users' ('email', 'encrypted_password', 'created_at', 'updated_at') VALUES (?, ?, ?, ?) …
  • สร้างผลิตภัณฑ์สองรายการโดยไม่ต้องสมัครสมาชิกโดยเรียกใช้ rails c และเพิ่ม:
    • Product.create(name: 'Awesome T-Shirt', price_cents: 3000)
    • Product.create(name: 'Awesome Sneakers', price_cents: 5000)

ขั้นตอนที่ 7: สร้างหน้าดัชนี

หน้าหลักสำหรับโครงการประกอบด้วยการเลือกผลิตภัณฑ์สำหรับการซื้อหรือการสมัครสมาชิก นอกจากนี้ยังมีส่วนสำหรับการเลือกวิธีการชำระเงิน (Stripe หรือ PayPal) นอกจากนี้ยังใช้ปุ่มส่งสำหรับเกตเวย์การชำระเงินแต่ละประเภทสำหรับ PayPal เราจะเพิ่มการออกแบบปุ่มของตัวเองผ่านไลบรารี JavaScript

ขั้นแรกสร้างเส้นทางสำหรับ index และ submit ใน config/routes.rb.

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

สร้างและเพิ่มการดำเนินการ index และ submit ในตัวควบคุมคำสั่งซื้อ app/controllers/orders_controller.rb. orders#index การดำเนินการเก็บสองตัวแปรที่จะใช้ในส่วนหน้า: @products_purchase ซึ่งมีรายการผลิตภัณฑ์ที่ไม่มีแผนและ @products_subscription ซึ่งมีผลิตภัณฑ์ที่มีทั้งแผน PayPal และ Stripe

class OrdersController

สร้างไฟล์ใน app/views/orders/index.html.haml. ไฟล์นี้มีอินพุตทั้งหมดที่เราจะส่งไปยังส่วนหลังของเราผ่านวิธีการส่งและการโต้ตอบสำหรับเกตเวย์การชำระเงินและการเลือกผลิตภัณฑ์ แอตทริบิวต์ชื่ออินพุตบางส่วนมีดังนี้:

  • Orders[product_id] จัดเก็บรหัสผลิตภัณฑ์
  • Orders[payment_gateway] มีช่องทางการชำระเงินที่มีค่า Stripe หรือ PayPal สำหรับอีกช่องทางหนึ่ง
%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; }

หากคุณเรียกใช้แอปพลิเคชันของคุณด้วย rails s และเยี่ยมชมเพจของคุณใน http://localhost:3000. คุณควรจะเห็นหน้าดังต่อไปนี้:

หน้าดัชนีดิบที่ไม่มีการรวม Stripe และ PayPal
หน้าดัชนีดิบที่ไม่มีการรวม Stripe และ PayPal

ที่เก็บข้อมูลรับรองเกตเวย์การชำระเงิน

คีย์ PayPal และ Stripe จะถูกเก็บไว้ในไฟล์ที่ Git ไม่ติดตาม มีคีย์สองประเภทที่เก็บไว้ในไฟล์นี้สำหรับเกตเวย์การชำระเงินแต่ละอันและสำหรับตอนนี้เราจะใช้ค่าดัมมี่สำหรับคีย์เหล่านี้ คำแนะนำเพิ่มเติมสำหรับการสร้างคีย์เหล่านี้แสดงไว้ในส่วนต่อไป

ขั้นตอนที่ 1: เพิ่มสิ่งนี้ใน .gitignore.

/config/application.yml

ขั้นตอนที่ 2: สร้างไฟล์ด้วยข้อมูลรับรองของคุณใน config/application.yml ควรมี PayPal และ Stripe sandbox / คีย์ทดสอบทั้งหมดสำหรับการเข้าถึง API เหล่านี้

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

ขั้นตอนที่ 3: เพื่อเก็บตัวแปรจากไฟล์ config/application.yml เมื่อแอปพลิเคชันเริ่มต้นให้เพิ่มบรรทัดเหล่านี้ใน config/application.rb ภายใน Application คลาสจึงจะพร้อมใช้งานใน ENV

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

การกำหนดค่า Stripe

เราจะเพิ่มอัญมณีสำหรับการใช้ Stripe API: stripe-rails จำเป็นต้องสร้างบัญชี Stripe เพื่อให้สามารถดำเนินการเรียกเก็บเงินและการสมัครสมาชิกได้ หากต้องการคุณสามารถดูวิธีการ API สำหรับ Stripe API ได้ในไฟล์ เอกสารอย่างเป็นทางการ .

ขั้นตอนที่ 1: เพิ่มแถบรางอัญมณีลงในโครงการของคุณ

แถบรางอัญมณี จะจัดเตรียมอินเทอร์เฟซสำหรับคำขอ API ทั้งหมดที่ใช้ในโครงการนี้

เพิ่มสิ่งนี้ใน Gemfile:

gem 'stripe-rails'

วิ่ง:

bundle install

ขั้นตอนที่ 2: สร้างคีย์ API ของคุณ

ในการมีคีย์ API สำหรับสื่อสารกับ Stripe คุณจะต้องสร้างบัญชีใน Stripe ในการทดสอบแอปพลิเคชันคุณสามารถใช้โหมดการทดสอบได้ดังนั้นจึงไม่จำเป็นต้องกรอกข้อมูลธุรกิจจริงในขั้นตอนการสร้างบัญชี Stripe

  • สร้างบัญชีใน Stripe หากคุณไม่มี ( https://dashboard.stripe.com/ ).
  • ในขณะที่ยังอยู่ในแผงควบคุม Stripe หลังจากเข้าสู่ระบบแล้วให้สลับ ดูข้อมูลการทดสอบ บน.
  • ที่ https://dashboard.stripe.com/test/apikeys แทนที่ YOUR_CREDENTIAL_HERE สำหรับค่า STRIPE_PUBLISHABLE_KEY และ STRIPE_SECRET_KEY ใน /config/application.yml ด้วยเนื้อหาจาก Publishable Key และ Secret key.

ขั้นตอนที่ 3: เริ่มต้นโมดูล Stripe

นอกเหนือจากการเปลี่ยนคีย์แล้วเรายังต้องเริ่มต้นโมดูล Stripe เพื่อให้ใช้คีย์ที่ตั้งค่าไว้แล้วใน ENV

สร้างไฟล์ใน config/initializers/stripe.rb กับ:

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

ขั้นตอนที่ 4: รวม Stripe ไว้ที่ส่วนหน้า

เราจะเพิ่มไลบรารี Stripe JavaScript และตรรกะในการส่งโทเค็นซึ่งแสดงถึงข้อมูลบัตรเครดิตของผู้ใช้และจะถูกประมวลผลในส่วนหลังของเรา

ใน index.html.haml เพิ่มไฟล์นี้ไว้ที่ด้านบนสุดของไฟล์ การดำเนินการนี้จะใช้โมดูล Stripe (ให้มาโดย gem) เพื่อเพิ่มไลบรารี Stripe javascript ในหน้าของผู้ใช้

= stripe_javascript_tag

Stripe ใช้ช่องป้อนข้อมูลที่ปลอดภัยซึ่งสร้างขึ้นผ่าน API ตามที่สร้างขึ้นใน iframe สร้างผ่าน API นี้คุณจะไม่ต้องกังวลเกี่ยวกับช่องโหว่ที่อาจเกิดขึ้นในการจัดการข้อมูลบัตรเครดิตของผู้ใช้ นอกจากนี้ส่วนหลังของคุณจะไม่สามารถประมวลผล / จัดเก็บข้อมูลที่ละเอียดอ่อนของผู้ใช้และจะได้รับโทเค็นที่แสดงถึงข้อมูลนี้เท่านั้น

ช่องป้อนข้อมูลเหล่านี้สร้างขึ้นโดยการเรียก stripe.elements().create('card') หลังจากนั้นจำเป็นต้องเรียกวัตถุที่ส่งคืนด้วย mount() โดยการส่งผ่านเป็นอาร์กิวเมนต์ id / class ขององค์ประกอบ HTML ที่ควรติดตั้งอินพุตเหล่านี้ สามารถดูข้อมูลเพิ่มเติมได้ที่ ลาย .

เมื่อผู้ใช้กดปุ่มส่งด้วยวิธีการชำระเงิน Stripe การเรียก API อื่นที่ส่งคืนสัญญาจะดำเนินการกับองค์ประกอบการ์ด Stripe ที่สร้างขึ้น:

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

result ตัวแปรของฟังก์ชั่นนี้หากไม่มีการกำหนดข้อผิดพลาดคุณสมบัติจะมีโทเค็นซึ่งสามารถเรียกค้นได้โดยการเข้าถึงแอตทริบิวต์ result.token.id โทเค็นนี้จะถูกส่งไปที่ส่วนหลัง

ในการทำการเปลี่ยนแปลงเหล่านี้ให้แทนที่โค้ดที่แสดงความคิดเห็น // YOUR STRIPE AND PAYPAL CODE WILL BE HERE ใน index.html.haml กับ:

(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

หากคุณเยี่ยมชมเพจของคุณควรมีลักษณะดังต่อไปนี้พร้อมกับช่องป้อนข้อมูล Stripe secure ใหม่:

หน้าดัชนีรวมกับช่องป้อนข้อมูลที่ปลอดภัยของ Stripe
หน้าดัชนีรวมกับช่องป้อนข้อมูลที่ปลอดภัยของ Stripe

ขั้นตอนที่ 5: ทดสอบแอปพลิเคชันของคุณ

กรอกแบบฟอร์มบัตรเครดิตด้วยบัตรทดสอบ ( https://stripe.com/docs/testing ) และส่งหน้า ตรวจสอบว่า submit การกระทำถูกเรียกด้วยพารามิเตอร์ทั้งหมด ( product_id , ช่องทางการชำระเงิน และ โทเค็น ) ในเอาต์พุตเซิร์ฟเวอร์ของคุณ

Stripe ค่าธรรมเนียม

ค่าธรรมเนียม Stripe แสดงถึงธุรกรรมครั้งเดียว ดังนั้นหลังจากการทำธุรกรรมการเรียกเก็บเงิน Stripe คุณจะได้รับเงินจากลูกค้าโดยตรง เหมาะอย่างยิ่งสำหรับการขายผลิตภัณฑ์ที่ไม่เกี่ยวข้องกับแผน ในส่วนต่อไปฉันจะแสดงวิธีการทำธุรกรรมประเภทเดียวกันกับ PayPal แต่ชื่อของ PayPal สำหรับธุรกรรมประเภทนี้คือ การชำระเงิน .

ในส่วนนี้ฉันจะจัดเตรียมโครงกระดูกทั้งหมดสำหรับจัดการและส่งคำสั่งซื้อ เราสร้างคำสั่งซื้อใน submit การดำเนินการเมื่อส่งแบบฟอร์ม Stripe คำสั่งนี้เริ่มแรกจะมี รอดำเนินการ สถานะดังนั้นหากมีสิ่งผิดปกติเกิดขึ้นขณะดำเนินการคำสั่งซื้อนี้คำสั่งซื้อจะยังคงเป็น รอดำเนินการ .

หากข้อผิดพลาดใด ๆ เกิดขึ้นจากการเรียก Stripe API เราจะกำหนดลำดับในรูปแบบ ล้มเหลว สถานะและหากการเรียกเก็บเงินเสร็จสมบูรณ์จะอยู่ในรูปแบบ จ่าย สถานะ. ผู้ใช้จะถูกเปลี่ยนเส้นทางตามการตอบสนองของ Stripe API ดังที่แสดงในกราฟต่อไปนี้:

การทำธุรกรรมแบบ Stripe
การทำธุรกรรมแบบ Stripe

นอกจากนี้เมื่อดำเนินการเรียกเก็บเงิน Stripe ID จะถูกส่งกลับ เราจะจัดเก็บ ID นี้เพื่อให้คุณสามารถค้นหาได้ในภายหลังในแดชบอร์ด Stripe ของคุณหากจำเป็น นอกจากนี้ยังสามารถใช้รหัสนี้หากต้องคืนเงินคำสั่งซื้อ สิ่งดังกล่าวจะไม่ถูกสำรวจในบทความนี้

ขั้นตอนที่ 1: สร้างบริการ Stripe

เราจะใช้คลาสซิงเกิลเพื่อแสดงการดำเนินการของ Stripe โดยใช้ Stripe API ในการสร้างการเรียกเก็บเงินวิธีการ Stripe::Charge.create ถูกเรียกและแอตทริบิวต์ ID อ็อบเจ็กต์ที่ส่งคืนจะถูกเก็บไว้ในเรกคอร์ดคำสั่ง charge_id นี้ create ฟังก์ชันถูกเรียกโดยการส่งโทเค็นที่มาในส่วนหน้าราคาคำสั่งซื้อและคำอธิบาย

ดังนั้นสร้างโฟลเดอร์ใหม่ app/services/orders และเพิ่มบริการ Stripe: app/services/orders/stripe.rb มี Orders::Stripe คลาส singleton ซึ่งมีรายการในเมธอด 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

ขั้นตอนที่ 2: ใช้การดำเนินการส่งและเรียกใช้บริการ Stripe

ใน orders_controller.rb ให้เพิ่มสิ่งต่อไปนี้ใน submit การดำเนินการซึ่งโดยทั่วไปจะเรียกใช้บริการ Orders::Stripe.execute โปรดทราบว่ามีการเพิ่มฟังก์ชั่นส่วนตัวใหม่สองฟังก์ชัน: prepare_new_order และ 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

ขั้นตอนที่ 3: ทดสอบแอปพลิเคชันของคุณ

ตรวจสอบว่าการดำเนินการส่งเมื่อเรียกด้วยการ์ดทดสอบที่ถูกต้องทำการเปลี่ยนเส้นทางไปยังข้อความสำเร็จหรือไม่ นอกจากนี้ตรวจสอบในไฟล์ แผงหน้าปัดลาย หากมีการแสดงคำสั่งซื้อด้วย

การสมัครสมาชิก Stripe

การสมัครสมาชิกหรือแผนสามารถสร้างขึ้นสำหรับการชำระเงินที่เกิดขึ้นประจำ สำหรับผลิตภัณฑ์ประเภทนี้ผู้ใช้จะถูกเรียกเก็บเงินรายวันรายสัปดาห์รายเดือนหรือรายปีโดยอัตโนมัติตาม การกำหนดค่าแผน . ในส่วนนี้เราจะใช้ฟิลด์สำหรับผลิตภัณฑ์ stripe_plan_name ในการจัดเก็บ ID แผน - จริงๆแล้วเป็นไปได้ที่เราจะเลือก ID และเราจะเรียกมันว่า premium-plan - ซึ่งจะใช้เพื่อสร้างความสัมพันธ์ customer subscription

นอกจากนี้เราจะสร้างคอลัมน์ใหม่สำหรับตารางผู้ใช้ที่เรียกว่า stripe_customer_id ซึ่งจะเต็มไปด้วยคุณสมบัติ id ของอ็อบเจ็กต์ลูกค้า Stripe ลูกค้า Stripe ถูกสร้างขึ้นเมื่อฟังก์ชัน Stripe::Customer.create ถูกเรียกและคุณยังสามารถตรวจสอบลูกค้าที่สร้างและเชื่อมโยงกับบัญชีของคุณได้ใน ( https://dashboard.stripe.com/test/customers ). ลูกค้าถูกสร้างขึ้นโดยการส่ง source พารามิเตอร์ซึ่งในกรณีของเราคือโทเค็นที่สร้างขึ้นในส่วนหน้าซึ่งถูกส่งเมื่อส่งแบบฟอร์ม

ออบเจ็กต์ของลูกค้าที่ได้รับจากการเรียก Stripe API ที่กล่าวถึงล่าสุดยังใช้สำหรับการสร้างการสมัครสมาชิกซึ่งทำได้โดยการเรียก customer.subscriptions.create และส่งรหัสแผนเป็นพารามิเตอร์

นอกจากนี้ stripe-rails gem มีอินเทอร์เฟซสำหรับดึงข้อมูลและอัปเดตลูกค้าจาก Stripe ซึ่งทำได้โดยการโทร Stripe::Customer.retrieve และ Stripe::Customer.update ตามลำดับ

ดังนั้นเมื่อบันทึกผู้ใช้มี stripe_customer_id แล้วแทนที่จะสร้างลูกค้าใหม่โดยใช้ Stripe::Customer.create เราจะเรียก Stripe::Customer.retrieve ผ่าน stripe_customer_id เป็นพารามิเตอร์ตามด้วย Stripe::Customer.update และในกรณีนี้ให้ส่งโทเค็นพารามิเตอร์

อันดับแรกเราจะสร้างแผนโดยใช้ Stripe API เพื่อให้เราสามารถสร้างผลิตภัณฑ์สมัครสมาชิกใหม่โดยใช้ฟิลด์ stripe_plan_name หลังจากนั้นเราจะทำการแก้ไขในส่วน orders_controller และบริการ Stripe เพื่อให้การสร้างและดำเนินการสมัครสมาชิก Stripe ได้รับการจัดการ

ขั้นตอนที่ 1: สร้างแผนโดยใช้ Stripe API

เปิดคอนโซลของคุณโดยใช้คำสั่ง rails c สร้างการสมัครสำหรับบัญชี Stripe ของคุณด้วย:

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

หากผลลัพธ์ที่ส่งคืนในขั้นตอนนี้เป็นจริงแสดงว่าสร้างแผนสำเร็จแล้วและคุณสามารถเข้าถึงได้ในไฟล์ แผงหน้าปัดลาย .

ขั้นตอนที่ 2: สร้างผลิตภัณฑ์ในฐานข้อมูลด้วย stripe_plan_name ชุดสนาม

ตอนนี้สร้างผลิตภัณฑ์ด้วย stripe_plan_name ตั้งเป็น premium-plan ในฐานข้อมูล:

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

ขั้นตอนที่ 3: สร้างการย้ายข้อมูลเพื่อเพิ่มคอลัมน์ stripe_customer_id ใน users โต๊ะ.

เรียกใช้สิ่งต่อไปนี้ในเทอร์มินัล:

rails generate migration AddStripeCustomerIdToUser stripe_customer_id:string rails db:migrate

ขั้นตอนที่ 4: ใช้ตรรกะการสมัครสมาชิกในคลาสบริการ Stripe

เพิ่มอีกสองฟังก์ชันในวิธีส่วนตัวของ app/services/orders/stripe.rb: execute_subscription มีหน้าที่สร้างการสมัครรับข้อมูลในวัตถุของลูกค้า ฟังก์ชั่น find_or_create_customer มีหน้าที่ส่งคืนลูกค้าที่สร้างไว้แล้วหรือส่งคืนลูกค้าที่สร้างขึ้นใหม่

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

สุดท้ายใน execute ฟังก์ชันในไฟล์เดียวกัน (app/services/orders/stripe.rb) เราจะเรียก find_or_create_customer จากนั้นดำเนินการสมัครสมาชิกโดยเรียก execute_subscription โดยส่งผ่านลูกค้าที่เรียก / สร้างขึ้นก่อนหน้านี้ ดังนั้นแทนที่ความคิดเห็น #SUBSCRIPTIONS WILL BE HANDLED HERE ใน execute วิธีการด้วยรหัสต่อไปนี้:

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)

ขั้นตอนที่ 5: ทดสอบแอปพลิเคชันของคุณ

เยี่ยมชมเว็บไซต์ของคุณเลือกผลิตภัณฑ์การสมัครสมาชิก Premium Plan และกรอกข้อมูลบัตรทดสอบที่ถูกต้อง หลังจากส่งแล้วควรนำคุณไปยังหน้าที่ประสบความสำเร็จ นอกจากนี้ตรวจสอบในไฟล์ แผงหน้าปัดลาย หากสร้างการสมัครสมาชิกสำเร็จ

การกำหนดค่า PayPal

เช่นเดียวกับที่เราทำใน Stripe เราจะเพิ่มอัญมณีสำหรับการใช้ PayPal API: paypal-sdk-rest และจำเป็นต้องสร้างบัญชี PayPal ด้วย ขั้นตอนการทำงานเชิงพรรณนาสำหรับ PayPal โดยใช้อัญมณีนี้สามารถปรึกษาได้ในทางการ เอกสาร PayPal API .

ขั้นตอนที่ 1: เพิ่ม paypal-sdk-rest อัญมณีสำหรับโครงการของคุณ

เพิ่มสิ่งนี้ใน Gemfile:

gem 'paypal-sdk-rest'

วิ่ง:

bundle install

ขั้นตอนที่ 2: สร้างคีย์ API ของคุณ

ในการมีคีย์ API สำหรับการสื่อสารกับ PayPal คุณจะต้องสร้างบัญชี PayPal ดังนั้น:

  • สร้างบัญชี (หรือใช้บัญชี PayPal ของคุณ) ที่ https://developer.paypal.com/ .
  • ยังคงลงชื่อเข้าใช้บัญชีของคุณสร้างบัญชีแซนด์บ็อกซ์สองบัญชีที่ https://developer.paypal.com/developer/accounts/ :
    • ส่วนบุคคล (บัญชีผู้ซื้อ) - จะใช้ในการทดสอบการชำระเงินและการสมัครสมาชิก
    • ธุรกิจ (บัญชีผู้ค้า) - จะเชื่อมโยงกับแอปพลิเคชันซึ่งจะมีคีย์ API ที่เรากำลังมองหา นอกจากนั้นคุณสามารถติดตามธุรกรรมทั้งหมดได้ในบัญชีนี้
  • สร้างแอปที่ https://developer.paypal.com/developer/applications โดยใช้บัญชีแซนด์บ็อกซ์ของธุรกิจก่อนหน้านี้
  • หลังจากขั้นตอนนี้คุณจะได้รับสองคีย์สำหรับ PayPal: Client ID และ Secret.
  • ใน config/application.yml แทนที่ YOUR_CREDENTIAL_HERE จาก PAYPAL_CLIENT_ID และ PAYPAL_CLIENT_SECRET ด้วยกุญแจที่คุณเพิ่งได้รับ

ขั้นตอนที่ 3: เริ่มต้นโมดูล PayPal

คล้ายกับ Stripe นอกเหนือจากการแทนที่คีย์ใน application.yml เรายังต้องเริ่มต้นโมดูล PayPal เพื่อให้สามารถใช้คีย์ที่ตั้งค่าไว้แล้วใน ENV ตัวแปร. เพื่อจุดประสงค์นี้ให้สร้างไฟล์ใน config/initializers/paypal.rb กับ:

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

ขั้นตอนที่ 4: รวม PayPal ไว้ที่ส่วนหน้า

ใน index.html.haml เพิ่มสิ่งนี้ที่ด้านบนของไฟล์:

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

ซึ่งแตกต่างจาก Stripe ตรงที่ PayPal ใช้เพียงปุ่มซึ่งเมื่อคลิกแล้วจะเปิดป๊อปอัปที่ปลอดภัยซึ่งผู้ใช้สามารถเข้าสู่ระบบและดำเนินการชำระเงิน / สมัครสมาชิก ปุ่มนี้สามารถแสดงผลได้โดยเรียกเมธอด paypal.Button(PARAM1).render(PARAM2)

  • PARAM1 เป็นวัตถุที่มีการกำหนดค่าสภาพแวดล้อมและฟังก์ชันการเรียกกลับสองฟังก์ชันเป็นคุณสมบัติ: createOrder และ onApprove.
  • PARAM2 ระบุตัวระบุองค์ประกอบ HTML ที่ควรแนบปุ่ม PayPal

ดังนั้นยังคงอยู่ในไฟล์เดียวกันแทนที่รหัสที่แสดงความคิดเห็น YOUR PAYPAL CODE WILL BE HERE กับ:

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

ขั้นตอนที่ 5: ทดสอบแอปพลิเคชันของคุณ

ไปที่หน้าของคุณและตรวจสอบว่าปุ่ม PayPal แสดงขึ้นมาหรือไม่เมื่อคุณเลือก PayPal เป็นวิธีการชำระเงิน

ธุรกรรม PayPal

ตรรกะสำหรับธุรกรรม PayPal ซึ่งแตกต่างจาก Stripe มีความซับซ้อนกว่าเล็กน้อยโดยเกี่ยวข้องกับคำขอเพิ่มเติมที่มาจากส่วนหน้าไปยังส่วนหลัง นั่นคือเหตุผลที่มีส่วนนี้ ฉันจะอธิบายไม่มากก็น้อย (โดยไม่มีรหัส) ว่าฟังก์ชันที่อธิบายไว้ใน createOrder เป็นอย่างไร และ onApprove วิธีการที่จะนำไปใช้และสิ่งที่คาดหวังในกระบวนการส่วนหลังด้วย

ขั้นตอนที่ 1: เมื่อผู้ใช้คลิกปุ่มส่ง PayPal ป๊อปอัปของ PayPal ที่ขอข้อมูลรับรองผู้ใช้จะเปิดขึ้น แต่อยู่ในสถานะโหลด ฟังก์ชันเรียกกลับ createOrder ถูกเรียก.

ป๊อปอัพ PayPal สถานะกำลังโหลด
ป๊อปอัพ PayPal สถานะกำลังโหลด

ขั้นตอนที่ 2: ในฟังก์ชั่นนี้เราจะดำเนินการร้องขอไปยังส่วนหลังของเราซึ่งจะสร้างการชำระเงิน / การสมัครสมาชิก นี่คือจุดเริ่มต้นของการทำธุรกรรมและจะไม่มีการเรียกเก็บเงินใด ๆ ทั้งสิ้นดังนั้นธุรกรรมจึงอยู่ในรูปแบบ รอดำเนินการ สถานะ. แบ็คเอนด์ของเราควรคืนโทเค็นให้เราซึ่งจะสร้างขึ้นโดยใช้โมดูล PayPal (ให้ผ่าน paypal-rest-sdk gem)

ขั้นตอนที่ 3: ยังอยู่ createOrder โทรกลับเราจะส่งคืนโทเค็นนี้ที่สร้างขึ้นในส่วนหลังของเราและหากทุกอย่างเรียบร้อยป๊อปอัปของ PayPal จะแสดงสิ่งต่อไปนี้โดยขอข้อมูลรับรองผู้ใช้:

ป๊อปอัพ PayPal ข้อมูลรับรองผู้ใช้
ป๊อปอัพ PayPal ข้อมูลรับรองผู้ใช้

ขั้นตอนที่ 4: หลังจากผู้ใช้เข้าสู่ระบบและเลือกวิธีการชำระเงินป๊อปอัปจะเปลี่ยนสถานะเป็นดังต่อไปนี้:

ป๊อปอัพ PayPal ธุรกรรมที่ได้รับอนุญาต
ป๊อปอัพ PayPal ธุรกรรมที่ได้รับอนุญาต

ขั้นตอนที่ 5: onApprove เรียกใช้ฟังก์ชันเรียกกลับแล้ว เราได้กำหนดไว้ดังต่อไปนี้: onApprove: function(data). data วัตถุจะมีข้อมูลการชำระเงินเพื่อดำเนินการ ในการโทรกลับนี้จะมีการร้องขออีกครั้งไปยังฟังก์ชันแบ็คเอนด์ของเราในครั้งนี้โดยส่งผ่านออบเจ็กต์ข้อมูลเพื่อดำเนินการตามคำสั่งของ PayPal

ขั้นตอนที่ 6: แบ็คเอนด์ของเราดำเนินการธุรกรรมนี้และส่งคืน 200 (หากสำเร็จ)

ขั้นตอนที่ 7: เมื่อส่วนหลังของเราส่งคืนเราจะส่งแบบฟอร์ม นี่เป็นคำขอที่สามที่เราส่งไปยังส่วนหลังของเรา

โปรดทราบว่าแตกต่างจาก Stripe ตรงที่มีคำขอสามรายการที่ส่งไปยังส่วนหลังของเราในกระบวนการนี้ และเราจะทำให้สถานะการบันทึกคำสั่งซื้อของเราตรงกัน:

  • createOrder โทรกลับ: มีการสร้างธุรกรรมและสร้างบันทึกการสั่งซื้อด้วย ดังนั้นจึงอยู่ในรูปแบบ รอดำเนินการ สถานะเป็นค่าเริ่มต้น
  • onApprove โทรกลับ: ธุรกรรมถูกดำเนินการและคำสั่งของเราจะถูกตั้งค่าเป็น paypal_execute .
  • ส่งหน้าคำสั่งซื้อ: ธุรกรรมได้ดำเนินการไปแล้วจึงไม่มีอะไรเปลี่ยนแปลง บันทึกคำสั่งซื้อจะเปลี่ยนสถานะเป็น จ่าย .

กระบวนการทั้งหมดนี้อธิบายไว้ในกราฟต่อไปนี้:

ธุรกรรม PayPal
ธุรกรรม PayPal

การชำระเงินด้วย PayPal

การชำระเงินด้วย PayPal เป็นไปตามตรรกะเดียวกันกับการเรียกเก็บเงินแบบ Stripe ดังนั้นจึงเป็นตัวแทนของการทำธุรกรรมครั้งเดียว แต่ดังที่ได้กล่าวไว้ในหัวข้อก่อนหน้านี้มีตรรกะการไหลที่แตกต่างกัน นี่คือการเปลี่ยนแปลงที่จะต้องดำเนินการสำหรับการจัดการการชำระเงินด้วย PayPal:

ขั้นตอนที่ 1: สร้างเส้นทางใหม่สำหรับ PayPal และดำเนินการชำระเงิน

เพิ่มเส้นทางต่อไปนี้ใน 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

สิ่งนี้จะสร้างเส้นทางใหม่สองเส้นทางสำหรับการสร้างและดำเนินการชำระเงินซึ่งจะจัดการใน paypal_create_payment และ paypal_execute_payment วิธีการควบคุมคำสั่งซื้อ

ขั้นตอนที่ 2: สร้างบริการ PayPal

เพิ่มคลาสซิงเกิลตัน Orders::Paypal ที่: app/services/orders/paypal.rb.

บริการนี้ในขั้นต้นจะมีหน้าที่รับผิดชอบสามประการ:

  • create_payment วิธีสร้างการชำระเงินโดยการโทร PayPal::SDK::REST::Payment.new ก โทเค็น ถูกสร้างขึ้นและส่งกลับไปยังส่วนหน้า
  • execute_payment วิธีดำเนินการชำระเงินโดยการค้นหาวัตถุการชำระเงินที่สร้างไว้ก่อนหน้าผ่าน PayPal::SDK::REST::Payment.find(payment_id) ซึ่งใช้ไฟล์ payment_id เป็นอาร์กิวเมนต์ที่มีค่าเดียวกับ charge_id เก็บไว้ในขั้นตอนก่อนหน้าในวัตถุคำสั่ง หลังจากนั้นเราโทรไปที่ execute ในออบเจ็กต์การชำระเงินโดยมีผู้ชำระเงินที่ระบุเป็นพารามิเตอร์ ผู้ชำระเงินนี้จะได้รับโดยส่วนหน้าหลังจากที่ผู้ใช้ให้ข้อมูลรับรองและเลือกวิธีการชำระเงินในป๊อปอัป
  • finish วิธีค้นหาคำสั่งซื้อโดยเฉพาะ charge_id การค้นหาคำสั่งซื้อที่เพิ่งสร้างขึ้นในไฟล์ paypal_execute สถานะ. หากพบบันทึกจะถูกทำเครื่องหมายว่าชำระแล้ว
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

ขั้นตอนที่ 3: เรียกใช้บริการ PayPal ในตัวควบคุมในการดำเนินการส่ง

เพิ่มการโทรกลับสำหรับ prepare_new_order ก่อนดำเนินการ paypal_create_payment (ซึ่งจะถูกเพิ่มในขั้นตอนถัดไป) โดยการเพิ่มสิ่งต่อไปนี้ในไฟล์ app/controllers/orders_controller.rb:

class OrdersController

อีกครั้งในไฟล์เดียวกันให้เรียกใช้บริการ PayPal ในการดำเนินการส่งโดยแทนที่รหัสที่แสดงความคิดเห็น #PAYPAL WILL BE HANDLED HERE. ดังต่อไปนี้:

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

ขั้นตอนที่ 4: สร้างการดำเนินการสำหรับจัดการคำขอ

ยังคงอยู่ใน app/controllers/orders_controller.rb สร้างการดำเนินการใหม่สองรายการ (ซึ่งควรเป็นสาธารณะ) สำหรับจัดการคำขอไปยัง paypal_create_payment และ paypal_execute_payment เส้นทาง:

  • paypal_create_payment วิธีการ: จะเรียกวิธีการบริการของเรา create_payment. หากส่งคืนสำเร็จก็จะส่งคืนคำสั่งซื้อ โทเค็น สร้างโดย Orders::Paypal.create_payment.
  • paypal_execute_payment วิธีการ: จะเรียกวิธีการบริการของเรา execute_payment (ซึ่งดำเนินการชำระเงินของเรา) หากดำเนินการชำระเงินสำเร็จจะส่งคืน 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 ...

ขั้นตอนที่ 5: ใช้ฟังก์ชันเรียกกลับส่วนหน้าสำหรับ createOrder และ onApprove.

ทำให้ paypal.Button.render ของคุณ การโทรมีลักษณะดังนี้:

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

ดังที่ได้กล่าวไว้ในหัวข้อก่อนหน้านี้เราเรียกว่า paypal_create_payment_url สำหรับ createOrder โทรกลับและ paypal_execute_payment_url สำหรับ onApprove โทรกลับ. โปรดสังเกตว่าหากคำขอสุดท้ายส่งคืนสำเร็จเราจะส่งคำสั่งซื้อซึ่งเป็นคำขอที่สามที่ส่งไปยังเซิร์ฟเวอร์

ใน createOrder ตัวจัดการฟังก์ชันเราส่งคืนโทเค็น (ได้รับจากส่วนหลัง) ใน onApprove โทรกลับเรามีคุณสมบัติสองอย่างที่ส่งผ่านไปยังส่วนหลังของเรา paymentID และ payerID. สิ่งเหล่านี้จะถูกใช้เพื่อดำเนินการชำระเงิน

สุดท้ายสังเกตว่าเรามีสองว่าง else ประโยคเมื่อฉันกำลังออกจากที่ว่างสำหรับส่วนถัดไปซึ่งเราจะเพิ่มการสมัครสมาชิก PayPal

หากคุณเข้าชมเพจของคุณหลังจากที่ผสานรวมส่วน front-end JavaScript และเลือก PayPal เป็นวิธีการชำระเงินควรมีลักษณะดังนี้:

หน้าดัชนีหลังจากรวมเข้ากับ PayPal
หน้าดัชนีหลังจากรวมเข้ากับ PayPal

ขั้นตอนที่ 6: ทดสอบแอปพลิเคชันของคุณ

  • ไปที่หน้าดัชนี
  • เลือกผลิตภัณฑ์ชำระเงิน / เรียกเก็บเงินและ PayPal เป็นวิธีการชำระเงิน
  • คลิกที่ปุ่มส่ง PayPal
  • ในป๊อปอัป PayPal:
    • ใช้ข้อมูลรับรองสำหรับบัญชีผู้ซื้อที่คุณสร้างขึ้น
    • เข้าสู่ระบบและยืนยันคำสั่งซื้อของคุณ
    • ป๊อปอัปควรปิด
  • ตรวจสอบว่าคุณถูกเปลี่ยนเส้นทางไปยังหน้าความสำเร็จหรือไม่
  • สุดท้ายตรวจสอบว่ามีการดำเนินการสั่งซื้อในบัญชี PayPal หรือไม่โดยลงชื่อเข้าใช้ด้วยบัญชีธุรกิจของคุณที่ https://www.sandbox.paypal.com/signin และตรวจสอบแดชบอร์ด https://www.sandbox.paypal.com/listing/transactions .

การสมัครสมาชิก PayPal

แผน / ข้อตกลง / การสมัครสมาชิกของ PayPal เป็นไปตามตรรกะเดียวกันกับการสมัครสมาชิก Stripe และสร้างขึ้นสำหรับการชำระเงินที่เกิดขึ้นประจำ ด้วยผลิตภัณฑ์ประเภทนี้ผู้ใช้จะถูกเรียกเก็บเงินรายวันรายสัปดาห์รายเดือนหรือรายปีโดยอัตโนมัติตาม การกำหนดค่า .

เราจะใช้ฟิลด์สำหรับผลิตภัณฑ์ paypal_plan_name เพื่อจัดเก็บ ID แผนที่ PayPal ให้ไว้ ในกรณีนี้แตกต่างจาก Stripe ตรงที่เราไม่ได้เลือก ID และ PayPal จะส่งคืนค่านี้ซึ่งจะใช้ในการอัปเดตผลิตภัณฑ์ล่าสุดที่สร้างในฐานข้อมูลของเรา

สำหรับการสร้างการสมัครสมาชิกไม่มี customer จำเป็นต้องมีข้อมูลในขั้นตอนใด ๆ เช่นวิธีการ onApprove อาจจัดการการเชื่อมโยงนี้ในการนำไปใช้งาน ดังนั้นตารางของเราจะยังคงเหมือนเดิม

ขั้นตอนที่ 1: สร้างแผนโดยใช้ PayPal API

เปิดคอนโซลของคุณโดยใช้คำสั่ง rails c สร้างการสมัครสำหรับบัญชี PayPal ของคุณด้วย:

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)

ขั้นตอนที่ 2: อัปเดตผลิตภัณฑ์ล่าสุดในฐานข้อมูล paypal_plan_name พร้อมส่งคืน plan.id.

วิ่ง:

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

ขั้นตอนที่ 3: เพิ่มเส้นทางสำหรับการสมัครสมาชิก PayPal

เพิ่มสองเส้นทางใหม่ใน 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

ขั้นตอนที่ 4: จัดการการสร้างและดำเนินการในบริการ PayPal

เพิ่มอีกสองฟังก์ชันสำหรับการสร้างและดำเนินการสมัครสมาชิกใน Orders::Paypal ของ 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

ใน create_subscription เราเริ่มต้นข้อตกลงโดยเรียกเมธอด PayPal::SDK::REST::Agreement.new และผ่าน product.paypal_plan_name เป็นหนึ่งในคุณลักษณะของมัน หลังจากนั้นเราสร้างมันและตอนนี้โทเค็นจะถูกตั้งค่าสำหรับออบเจ็กต์สุดท้ายนี้ เรายังส่งคืนโทเค็นไปที่ส่วนหน้า

ใน execute_subscription เราพบ order บันทึกที่สร้างขึ้นในการโทรครั้งก่อน หลังจากนั้นเราเริ่มต้นข้อตกลงใหม่เราตั้งค่าโทเค็นของวัตถุก่อนหน้านี้และดำเนินการ หากขั้นตอนสุดท้ายนี้ดำเนินการสำเร็จสถานะคำสั่งซื้อจะถูกตั้งค่าเป็น paypal_execute . และตอนนี้เรากลับไปที่ส่วนหน้าของรหัสข้อตกลงซึ่งเก็บไว้ใน order.chager_id

ขั้นตอนที่ 5: เพิ่มการดำเนินการสำหรับสร้างและดำเนินการสมัครสมาชิกใน orders_controller

เปลี่ยน app/controllers/orders_controller.rb. ที่ด้านบนสุดของคลาสอันดับแรกจากนั้นอัปเดตการติดต่อกลับ prepare_new_order ที่จะดำเนินการก่อนหน้านี้ paypal_create_subscription ถูกเรียก:

class OrdersController

นอกจากนี้ในไฟล์เดียวกันจะเพิ่มฟังก์ชันสาธารณะสองฟังก์ชันเพื่อให้เรียกว่า Orders::Paypal บริการที่มีขั้นตอนเดียวกันกับที่เรามีอยู่แล้วในการชำระเงินด้วย 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 ...

ขั้นตอนที่ 6: การเพิ่มตัวจัดการการสมัครสมาชิกสำหรับ createOrder และ onApprove การเรียกกลับในส่วนหน้า

สุดท้ายใน index.html.haml แทนที่ paypal.Buttons ฟังก์ชันต่อไปนี้ซึ่งจะเติมสองว่าง else เรามีมาก่อน:

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

การสร้างและการดำเนินการสำหรับการสมัครสมาชิกมีตรรกะที่คล้ายกันกับที่ใช้สำหรับการชำระเงิน ความแตกต่างอย่างหนึ่งคือเมื่อดำเนินการชำระเงินข้อมูลจากฟังก์ชันเรียกกลับ onApprove มี paymentID แล้ว เป็นตัวแทนของ charge_id เพื่อส่งแบบฟอร์มผ่าน submitOrderPaypal(data.paymentID). สำหรับการสมัครสมาชิกเราได้รับ charge_id หลังจากดำเนินการแล้วโดยขอ POST บน paypal_execute_subscription_url เพื่อให้เราโทรได้ submitOrderPaypal(executeData.id)

ขั้นตอนที่ 7: ทดสอบแอปพลิเคชันของคุณ

  • ไปที่หน้าดัชนี
  • เลือกผลิตภัณฑ์สมัครสมาชิกและ PayPal เป็นวิธีการชำระเงิน
  • คลิกที่ปุ่มส่ง PayPal
  • ในป๊อปอัป PayPal:
    • ใช้ข้อมูลรับรองสำหรับบัญชีผู้ซื้อที่คุณสร้างขึ้น
    • เข้าสู่ระบบและยืนยันคำสั่งซื้อของคุณ
    • ป๊อปอัปควรปิด
  • ตรวจสอบว่าคุณถูกเปลี่ยนเส้นทางไปยังหน้าความสำเร็จหรือไม่
  • สุดท้ายตรวจสอบว่ามีการดำเนินการสั่งซื้อในบัญชี PayPal หรือไม่โดยลงชื่อเข้าใช้ด้วยบัญชีธุรกิจของคุณที่ https://www.sandbox.paypal.com/signin และตรวจสอบแดชบอร์ด https://www.sandbox.paypal.com/listing/transactions .

สรุป

หลังจากอ่านบทความนี้คุณควรจะสามารถรวมการชำระเงิน / ค่าใช้จ่ายตลอดจนธุรกรรมการสมัครสมาชิกสำหรับ PayPal และ Stripe ในแอปพลิเคชัน Rails ของคุณ มีหลายประเด็นที่ควรปรับปรุงซึ่งฉันไม่ได้เพิ่มในบทความนี้เพราะความสั้น ฉันจัดระเบียบทุกอย่างตามข้อสันนิษฐานของความยาก:

  • ง่ายกว่า:
    • ใช้ Transport Layer Security (TLS) เพื่อให้คำขอของคุณใช้ HTTPS
    • ใช้การกำหนดค่าสภาพแวดล้อมการผลิตสำหรับทั้ง PayPal และ Stripe
    • เพิ่มหน้าใหม่เพื่อให้ผู้ใช้สามารถเข้าถึงประวัติการสั่งซื้อก่อนหน้านี้
  • ปานกลาง:
    • คืนเงินหรือยกเลิกการสมัครสมาชิก
    • จัดเตรียมโซลูชันสำหรับการชำระเงินของผู้ใช้ที่ไม่ได้ลงทะเบียน
  • ยากกว่า:
    • ให้วิธีลบบัญชีและเก็บรักษาไว้ โทเค็น และ รหัสลูกค้า หากผู้ใช้ต้องการกลับมา แต่หลังจากผ่านไปสักระยะหนึ่งให้ลบข้อมูลนี้ออกเพื่อให้แอปพลิเคชันของคุณสอดคล้องกับ PCI มากขึ้น
    • ย้ายไปที่ PayPal เวอร์ชัน 2 API ในฝั่งเซิร์ฟเวอร์ ( https://developer.paypal.com/docs/api/payments/v2/ ) อัญมณีที่เราใช้ในบทช่วยสอนนี้ paypal-sdk-rest มีเฉพาะรุ่นเบต้าสำหรับเวอร์ชัน 2 เพื่อให้สามารถใช้งานได้อย่างระมัดระวัง ( https://github.com/paypal/PayPal-Ruby-SDK/tree/2.0-beta ).
    • รวมคำขอที่มีศักยภาพ
      • ลาย: https://stripe.com/docs/api/idempotent_requests
      • PayPal: https://developer.paypal.com/docs/api-basics/#api-idempotency

ฉันขอแนะนำให้อ่านเกี่ยวกับองค์ประกอบ Stripe Checkout ซึ่งเป็นอีกวิธีหนึ่งในการรวม Stripe ไว้ที่ส่วนหน้า ซึ่งแตกต่างจาก Stripe Elements ที่เราใช้ในบทช่วยสอนนี้ Stripe Checkout จะเปิดป๊อปอัปหลังจากคลิกที่ปุ่ม (คล้ายกับ PayPal) ที่ผู้ใช้กรอกข้อมูลบัตรเครดิตหรือเลือกชำระเงินด้วย Google Pay / Apple Pay https://stripe.com/docs/web .

คำแนะนำในการอ่านครั้งที่สองคือหน้าการรักษาความปลอดภัยสำหรับทั้งเกตเวย์การชำระเงิน

  • สำหรับ ลาย
  • สำหรับ PayPal

สุดท้ายนี้ขอขอบคุณที่อ่านบทความนี้! คุณยังสามารถตรวจสอบไฟล์ โครงการ GitHub ที่ใช้สำหรับตัวอย่างโครงการนี้ . ที่นั่นฉันเพิ่ม rspec การทดสอบเช่นกันในขณะที่พัฒนา

ทำความเข้าใจพื้นฐาน

Stripe คืออะไรและทำงานอย่างไร?

Stripe เป็น บริษัท ที่พัฒนาซอฟต์แวร์สำหรับบุคคลหรือธุรกิจเพื่อดำเนินการชำระเงินที่ปลอดภัยผ่านอินเทอร์เน็ต

ราง 4 กับราง 5

ความแตกต่างระหว่าง PayPal และ Stripe คืออะไร?

พวกเขาเสนอแอปพลิเคชันที่แตกต่างกันเกี่ยวกับการชำระเงินและมีค่าธรรมเนียมในการใช้บริการที่แตกต่างกัน

โทเค็นวิธีการชำระเงินคืออะไร?

การชำระเงินโทเค็นเป็นกระบวนการจัดการข้อมูลที่ละเอียดอ่อนจากผู้ใช้และเปลี่ยนเป็นโทเค็นดังนั้นจึงไม่มีข้อมูลที่ละเอียดอ่อนรั่วไหล

PayPal เป็นเกตเวย์การชำระเงินหรือตัวประมวลผลหรือไม่

PayPal ไม่ใช่เกตเวย์ แต่เป็นโซลูชันสำหรับผู้ค้าที่สมบูรณ์ อย่างไรก็ตามจะใช้เกตเวย์การชำระเงินที่เรียกว่า Payflow

Stripe เป็นเกตเวย์การชำระเงินหรือตัวประมวลผลหรือไม่

Stripe เป็นเกตเวย์การชำระเงินที่จัดการบัตรของลูกค้า

ผู้จัดการบัญชี SMB

อื่น ๆ

ผู้จัดการบัญชี SMB
คำแนะนำฉบับสมบูรณ์เกี่ยวกับการดำเนินโครงการที่มีอยู่อย่างราบรื่น

คำแนะนำฉบับสมบูรณ์เกี่ยวกับการดำเนินโครงการที่มีอยู่อย่างราบรื่น

ผู้คนและทีมงาน

โพสต์ยอดนิยม
เอกสาร Agile: การปรับสมดุลความเร็วและการรักษาความรู้
เอกสาร Agile: การปรับสมดุลความเร็วและการรักษาความรู้
ทำลายหลักการออกแบบ (ด้วยอินโฟกราฟิก)
ทำลายหลักการออกแบบ (ด้วยอินโฟกราฟิก)
วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
วิธีจัดโครงสร้างลำดับชั้นการพิมพ์ที่มีประสิทธิภาพ
ฮาร์ดแวร์ที่คล่องตัวพร้อมการพัฒนาซอฟต์แวร์ในตัว
ฮาร์ดแวร์ที่คล่องตัวพร้อมการพัฒนาซอฟต์แวร์ในตัว
วิธีการรวม OAuth 2 เข้ากับ Django / DRF Back-end ของคุณโดยไม่บ้า
วิธีการรวม OAuth 2 เข้ากับ Django / DRF Back-end ของคุณโดยไม่บ้า
 
GWT Toolkit: สร้างส่วนหน้า JavaScript ที่มีประสิทธิภาพโดยใช้ Java
GWT Toolkit: สร้างส่วนหน้า JavaScript ที่มีประสิทธิภาพโดยใช้ Java
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
แหล่งข้อมูลสำหรับธุรกิจขนาดเล็กสำหรับ COVID-19: เงินกู้เงินช่วยเหลือและสินเชื่อ
Libation Frontiers: เจาะลึกอุตสาหกรรมไวน์โลก
Libation Frontiers: เจาะลึกอุตสาหกรรมไวน์โลก
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
เรียนรู้ Markdown: เครื่องมือการเขียนสำหรับนักพัฒนาซอฟต์แวร์
พบกับ Phoenix: กรอบงานคล้ายรางสำหรับเว็บแอปสมัยใหม่บน Elixir
พบกับ Phoenix: กรอบงานคล้ายรางสำหรับเว็บแอปสมัยใหม่บน Elixir
โพสต์ยอดนิยม
  • อุปกรณ์ Android ตรวจสอบไม่มีอุปกรณ์
  • วิธีหาลูกค้าที่ปรึกษา
  • ข้อใดต่อไปนี้อธิบายกลุ่มเครื่องมือที่นักพัฒนาใช้เขียนแอปได้ดีที่สุด
  • บทนำสู่การจัดการโครงการแบบ Agile
  • วิธีทำหุ่นยนต์
  • http //api.streamin.to/pair
  • แอพสากลสำหรับมือถือ windows 10
หมวดหมู่
  • ทีมแบบกระจาย
  • เคล็ดลับและเครื่องมือ
  • ชีวิตนักออกแบบ
  • นวัตกรรม
  • © 2022 | สงวนลิขสิทธิ์

    portaldacalheta.pt