Skip to content
samqiu edited this page Oct 28, 2012 · 11 revisions

Demo

I have built an Demo to use alipay.

Donatecn

Source code is here


Configuration

First define your api key, account and email in config/environment.rb. (If you haven’t them, you can get them here: https://www.alipay.com/himalayas/practicality_customer.htm)


ActiveMerchant::Billing::Integrations::Alipay::KEY
ActiveMerchant::Billing::Integrations::Alipay::ACCOUNT
ActiveMerchant::Billing::Integrations::Alipay::EMAIL

Service

Alipay has three payment service:
1. create_direct_pay_by_user 即时到账
2. create_partner_trade_by_buyer 担保交易
3. trade_create_by_buyer 标准双接口


Request Form

1. CREATE_DIRECT_PAY_BY_USER 即时到账


<% payment_service_for 'payment code', ActiveMerchant::Billing::Integrations::Alipay::ACCOUNT,
                            :service => :alipay,
                            :html => { :id => 'payment-form', :method => :get } do |service| %>
  <% service.total_fee 0.02 %>
  <% service.seller :email => ActiveMerchant::Billing::Integrations::Alipay::EMAIL %>
  <% service.notify_url url_for(:only_path => false, :action => 'notify') %>
  <% service.return_url url_for(:only_path => false, :action => 'done') %>
  <% service.show_url url_for(:only_path => false, :action => 'show') %>
  <% service.body 'payment body' %>
  <% service.charset "utf-8" %>
  <% service.service ActiveMerchant::Billing::Integrations::Alipay::Helper::CREATE_DIRECT_PAY_BY_USER %>
  <% service.payment_type 1 %>
  <% service.subject 'payment subject' %>
  <% service.sign %>
<% end %>
<%= button_to_function "Submit", "document.getElementById('payment-form').submit()" %>

payment code is the out_trade_no, it must be unique.
total_fee is the total fee of order.
payment subject is the subject of the payment.
payment body is the body of the payment.

For rails3 project, you have to remove the snowman tag, use


<%= button_to_function "Submit", "document.getElementById('payment-form').firstChild.remove();document.getElementById('payment-form').submit()" %>

instead

2. CREATE_PARTNER_TRADE_BY_BUYER 担保交易


<% payment_service_for 'payment code', ActiveMerchant::Billing::Integrations::Alipay::ACCOUNT,
                            :service => :alipay,
                            :html => { :id => 'payment-form', :method => :get } do |service| %>
  <% service.discount -0.01 %>
  <% service.price 0.01 %>
  <% service.quantity 2 %>
  <% service.seller :email => ActiveMerchant::Billing::Integrations::Alipay::EMAIL %>
  <%# service.buyer :id => 'buyer_id' %>
  <% service.notify_url url_for(:only_path => false, :action => 'notify') %>
  <% service.return_url url_for(:only_path => false, :action => 'done') %>
  <% service.show_url url_for(:only_path => false, :action => 'show') %>
  <% service.body 'payment body' %>
  <% service.charset "utf-8" %>
  <% service.service ActiveMerchant::Billing::Integrations::Alipay::Helper::CREATE_PARTNER_TRADE_BY_BUYER %>
  <% service.payment_type 1 %>
  <% service.subject 'payment subject' %>
  <% service.agent ActiveMerchant::Billing::Integrations::Alipay::ACCOUNT %>
  <% service.logistics :type => 'EXPRESS', :fee => 0.10, :payment => 'BUYER_PAY' %>
  <% service.receive :name => '黄志敏', :address => '上海市静安中华大厦1808室', :zip => 'xxxxxx', :phone => 'xxxxxxxxxxx', :mobile => 'xxxxxxxxxxx' %>
  <% service.sign %>
<% end %>
<%= button_to_function "Submit", "document.getElementById('payment-form').submit();" %>

logistics defines how to send the goods.
receive defines where the goods send to.

3. TRADE_CREATE_BY_BUYER 标准双接口


<% payment_service_for 'payment code', ActiveMerchant::Billing::Integrations::Alipay::ACCOUNT,
                            :service => :alipay,
                            :html => { :id => 'payment-form', :method => :get } do |service| %>
  <% service.discount -0.01 %>
  <% service.price 0.01 %>
  <% service.quantity 2 %>
  <% service.seller :email => ActiveMerchant::Billing::Integrations::Alipay::EMAIL %>
  <% service.notify_url url_for(:only_path => false, :action => 'notify') %>
  <% service.return_url url_for(:only_path => false, :action => 'done') %>
  <% service.show_url url_for(:only_path => false, :action => 'show') %>
  <% service.body 'payment body' %>
  <% service.charset "utf-8" %>
  <% service.service ActiveMerchant::Billing::Integrations::Alipay::Helper::TRADE_CREATE_BY_BUYER %>
  <% service.payment_type 1 %>
  <% service.subject 'payment subject' %>
  <% service.logistics :type => 'EXPRESS', :fee => 0.10, :payment => 'BUYER_PAY' %>
  <% service.receive :name => '黄志敏', :address => '上海市静安中华大厦1808室', :zip => 'xxxxxx', :phone => 'xxxxxxxxxxx', :mobile => 'xxxxxxxxxxx' %>
  <% service.sign %>
<% end %>
<%= button_to_function "Submit", "document.getElementById('payment-form').submit();" %>

Notify action


notification = ActiveMerchant::Billing::Integrations::Alipay::Notification.new(request.raw_post)

AlipayTxn.create(:notify_id => notification.notify_id,
                 :total_fee => notification.total_fee,
                 :status => notification.trade_status,
                 :trade_no => notification.trade_no,
                 :received_at => notification.notify_time)

notification.acknowledge

case notification.status
when "WAIT_BUYER_PAY"
  @order.pend_payment!
when "WAIT_SELLER_SEND_GOODS"
  @order.pend_shipment!
when "WAIT_BUYER_CONFIRM_GOODS"
  @order.confirm_shipment!
when "TRADE_FINISHED"
  @order.pay!
else
  @order.fail_payment!
end

Return action


def done
  r = ActiveMerchant::Billing::Integrations::Alipay::Return.new(request.query_string)
  unless @result = r.success?
    logger.warn(r.message)
  end
end

Interface

for helper


CREATE_DIRECT_PAY_BY_USER = 'create_direct_pay_by_user'
CREATE_PARTNER_TRADE_BY_BUYER = 'create_partner_trade_by_buyer'
TRADE_CREATE_BY_BUYER = 'trade_create_by_buyer'

###################################################
# common
###################################################
mapping :account, 'partner'
mapping :order, 'out_trade_no'
mapping :seller, :email => 'seller_email',
                 :id => 'seller_id'
mapping :buyer, :email => 'buyer_email',
                :id => 'buyer_id'
mapping :notify_url, 'notify_url'
mapping :return_url, 'return_url'
mapping :show_url, 'show_url'
mapping :body, 'body'
mapping :subject, 'subject'
mapping :charset, '_input_charset'
mapping :service, 'service'
mapping :payment_type, 'payment_type'

#################################################
# create direct pay by user
#################################################
mapping :total_fee, 'total_fee'
mapping :paymethod, 'paymethod'
mapping :defaultbank, 'defaultbank'
mapping :royalty, :type => 'royalty_type',
                  :parameters => 'royalty_parameters'
mapping :it_b_pay, 'it_b_pay'

#################################################
# create partner trade by buyer and trade create by user
#################################################
mapping :price, 'price'
mapping :quantity, 'quantity'
mapping :discount, 'discount'
['', '_1', '_2', '_3'].each do |postfix|
  self.class_eval <<-EOF
  mapping :logistics#{postfix}, :type => 'logistics_type#{postfix}',
                                :fee => 'logistics_fee#{postfix}',
                                :payment => 'logistics_payment#{postfix}'
  EOF
end
mapping :receive, :name => 'receive_name',
                  :address => 'receive_address',
                  :zip => 'receive_zip',
                  :phone => 'receive_phone',
                  :mobile => 'receive_mobile'
mapping :t_b_pay, 't_b_pay'
mapping :t_s_send_1, 't_s_send_1'
mapping :t_s_send_2, 't_s_send_2'

#################################################
# create partner trade by buyer
#################################################
mapping :agent, 'agent'
mapping :buyer_msg, 'buyer_msg'

for notification


['notify_type', 'notify_id', 'out_trade_no', 'trade_no', 'payment_type', 'subject', 'body',
  'seller_email', 'seller_id', 'buyer_email', 'buyer_id', 'logistics_type', 'logistics_payment',
  'receive_name', 'receive_address', 'receive_zip', 'receive_phone', 'receive_mobile'].each do |param|
  self.class_eval <<-EOF
    def #{param}
      params['#{param}']
    end
  EOF
end

['price', 'discount', 'quantity', 'total_fee', 'coupon_discount', 'logistics_fee'].each do |param|
  self.class_eval <<-EOF
    def #{param}
      params['#{param}']
    end
  EOF
end

['trade_status', 'refund_status', 'logistics_status'].each do |param|
  self.class_eval <<-EOF
    def #{param}
      params['#{param}']
    end
  EOF
end

['notify_time', 'gmt_create', 'gmt_payment', 'gmt_close', 'gmt_refund', 'gmt_send_goods', 'gmt_logistics_modify'].each do |param|
  self.class_eval <<-EOF
    def #{param}
      Time.parse params['#{param}']
    end
  EOF
end

['use_coupon', 'is_total_fee_adjust'].each do |param|
  self.class_eval <<-EOF
    def #{param}?
      'T' == params['#{param}']
    end
  EOF
end
Clone this wiki locally