Ruby on Rails多商家支付网关集成求助:含三类主流网关
Hey there! As someone who’s built Rails e-commerce integrations with these exact gateways for multi-seller platforms, let me walk you through practical, actionable steps—no overly technical jargon, just what you need to get started.
First, let’s lay the groundwork: since each seller will have unique payment credentials, you can’t hardcode these values. We’ll set up a database model to store each seller’s gateway configs.
Step 1: Database Setup for Multi-Seller Credentials
Generate a model to link sellers to their payment gateways:
rails generate model PaymentGateway seller:references gateway_type:string api_credentials:jsonb is_active:boolean rails db:migrate
Add this association to your Seller model:
class Seller < ApplicationRecord has_many :payment_gateways end
This lets each seller add multiple gateways (and mark one as their active payment method).
1. PayPal Payflow Pro
What Sellers Need to Provide
Sellers will get these credentials from their PayPal Payflow account (or sandbox for testing):
- Partner (PayPal-provided ID, usually "PayPal" for sandbox)
- Vendor (Seller’s unique merchant ID)
- User (Same as Vendor unless they created a separate user)
- Password (Their Payflow account password)
Integration with Active Merchant
We’ll use the Active Merchant gem—it standardizes payment gateway interactions, making it easy to support multiple gateways without rewriting core logic.
Add to your Gemfile:
gem 'active_merchant'
Run bundle install
Code Example: Payment Processing Service
Create a service class to handle gateway initialization and payment actions (keeps your controllers clean):
# app/services/payment_processor_service.rb class PaymentProcessorService def initialize(seller, payment_details) @seller = seller @payment_details = payment_details # { amount: 99.99, credit_card: card_obj, order_id: "ORD-123" } @active_gateway = seller.payment_gateways.find_by(is_active: true) @gateway = initialize_gateway end # Authorize a payment (holds funds, can capture later) def authorize_payment response = @gateway.authorize( @payment_details[:amount], @payment_details[:credit_card], order_id: @payment_details[:order_id] ) format_response(response) end # Capture authorized funds def capture_payment(authorization_id, amount) response = @gateway.capture(amount, authorization_id) format_response(response) end private def initialize_gateway case @active_gateway.gateway_type when "paypal_payflow" creds = @active_gateway.api_credentials ActiveMerchant::Billing::PayflowGateway.new( partner: creds["partner"], vendor: creds["vendor"], user: creds["user"], password: creds["password"], test: Rails.env.development? # Use sandbox in dev ) # We'll add other gateways here next end end def format_response(response) if response.success? { success: true, transaction_id: response.authorization || response.transaction_id } else { success: false, error: response.message } end end end
How to Use This in Your Controller
# app/controllers/orders_controller.rb def create @seller = Seller.find(params[:seller_id]) # Build a credit card object (never store raw card data!) credit_card = ActiveMerchant::Billing::CreditCard.new( number: params[:cc][:number], month: params[:cc][:month], year: params[:cc][:year], verification_value: params[:cc][:cvv], first_name: params[:cc][:first_name], last_name: params[:cc][:last_name] ) if credit_card.valid? payment_service = PaymentProcessorService.new(@seller, { amount: params[:order][:total_amount].to_f, credit_card: credit_card, order_id: "ORD-#{SecureRandom.uuid}" }) result = payment_service.authorize_payment if result[:success] # Save order with authorization ID, set status to "authorized" @order = @seller.orders.create!( total_amount: params[:order][:total_amount].to_f, authorization_id: result[:transaction_id], status: "authorized" ) redirect_to @order, notice: "Payment authorized successfully!" else flash[:alert] = "Payment failed: #{result[:error]}" render :new end else flash[:alert] = "Invalid credit card details: #{credit_card.errors.full_messages.join(', ')}" render :new end end
2. Authorize.net
What Sellers Need to Provide
- API Login ID
- Transaction Key (from their Authorize.net account/sandbox)
Integration (Still Using Active Merchant)
No extra gems needed—Active Merchant supports Authorize.net’s AIM (Advanced Integration Method) out of the box. Just add this case to the initialize_gateway method in your service class:
when "authorize_net" creds = @active_gateway.api_credentials ActiveMerchant::Billing::AuthorizeNetGateway.new( login: creds["api_login_id"], password: creds["transaction_key"], test: Rails.env.development? )
The authorize_payment and capture_payment methods work exactly the same as Payflow—this is the beauty of using Active Merchant!
3. CyberSource
What Sellers Need to Provide
- Merchant ID
- API Key ID
- Secret Key (generated in CyberSource’s Business Center/sandbox)
Integration with CyberSource’s Official Gem
CyberSource’s REST API is best handled with their official gem. Add to your Gemfile:
gem 'cybersource_rest_client'
Run bundle install
Update the Payment Service for CyberSource
Since CyberSource’s API structure is different, add a dedicated method to handle it:
# In app/services/payment_processor_service.rb def authorize_payment if @active_gateway.gateway_type == "cybersource" authorize_cybersource else # Existing logic for other gateways response = @gateway.authorize(@payment_details[:amount], @payment_details[:credit_card], order_id: @payment_details[:order_id]) format_response(response) end end private def authorize_cybersource creds = @active_gateway.api_credentials # Configure CyberSource client config = CyberSource::Configuration.new config.authentication_type = "http_signature" config.merchant_id = creds["merchant_id"] config.api_key_id = creds["api_key_id"] config.secret_key = creds["secret_key"] config.environment = Rails.env.development? ? "sandbox" : "production" api_client = CyberSource::ApiClient.new(config) payments_api = CyberSource::PaymentsApi.new(api_client) # Build payment request request = CyberSource::CreatePaymentRequest.new( client_reference_information: CyberSource::Ptsv2paymentsClientReferenceInformation.new(code: @payment_details[:order_id]), order_information: CyberSource::Ptsv2paymentsOrderInformation.new( amount_details: CyberSource::Ptsv2paymentsOrderInformationAmountDetails.new( total_amount: @payment_details[:amount].to_s, currency: "USD" # Let sellers set currency if needed ) ), payment_information: CyberSource::Ptsv2paymentsPaymentInformation.new( card: CyberSource::Ptsv2paymentsPaymentInformationCard.new( number: @payment_details[:credit_card].number, expiration_month: @payment_details[:credit_card].month.to_s, expiration_year: @payment_details[:credit_card].year.to_s, security_code: @payment_details[:credit_card].verification_value ) ) ) begin response = payments_api.create_payment(request) { success: true, transaction_id: response.id } rescue CyberSource::ApiError => e error_data = JSON.parse(e.response_body) { success: false, error: error_data["message"] || "Payment failed" } end end
Key Tips for Multi-Seller Setup
- Validate Seller Credentials: When a seller adds a gateway, run a test transaction (e.g., authorize $0.01 then immediately void it) to ensure their credentials work.
- PCI Compliance: Never store raw credit card numbers in your database. Active Merchant and CyberSource handle encryption, so only store transaction/authorization IDs.
- Error Handling: Each gateway returns different error messages—format them into user-friendly language for both sellers and buyers.
- Logging: Log all payment requests and responses (without sensitive data) to debug issues quickly.
内容的提问来源于stack exchange,提问作者Sanjay

