This repository has been archived by the owner on Mar 3, 2022. It is now read-only.
forked from SiyuanHe/active_merchant
/
paypal.rb
139 lines (113 loc) · 6.04 KB
/
paypal.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
require File.dirname(__FILE__) + '/paypal/paypal_common_api'
require File.dirname(__FILE__) + '/paypal_express'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class PaypalGateway < Gateway
include PaypalCommonAPI
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
self.supported_countries = ['US']
self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside'
self.display_name = 'PayPal Website Payments Pro (US)'
def store(credit_card, options = {})
requires!(options, :ip)
options[:credit_card] = credit_card
response = create_profile(nil, options)
if response.success?
response_suspend = suspend_profile(response.params['ProfileID'])
if !response_suspend.success?
raise Error, "exception happened when storing credit_card to paypal"
end
end
response
end
def authorize(money, credit_card_or_referenced_id, options = {})
requires!(options, :ip)
commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Authorization', money, credit_card_or_referenced_id, options)
end
def purchase(money, credit_card_or_referenced_id, options = {})
requires!(options, :ip)
commit define_transaction_type(credit_card_or_referenced_id), build_sale_or_authorization_request('Sale', money, credit_card_or_referenced_id, options)
end
def express
@express ||= PaypalExpressGateway.new(@options)
end
private
def define_transaction_type(transaction_arg)
if transaction_arg.is_a?(String)
return 'DoReferenceTransaction'
else
return 'DoDirectPayment'
end
end
def build_sale_or_authorization_request(action, money, credit_card_or_referenced_id, options)
transaction_type = define_transaction_type(credit_card_or_referenced_id)
reference_id = credit_card_or_referenced_id if transaction_type == "DoReferenceTransaction"
billing_address = options[:billing_address] || options[:address]
currency_code = options[:currency] || currency(money)
xml = Builder::XmlMarkup.new :indent => 2
xml.tag! transaction_type + 'Req', 'xmlns' => PAYPAL_NAMESPACE do
xml.tag! transaction_type + 'Request', 'xmlns:n2' => EBAY_NAMESPACE do
xml.tag! 'n2:Version', API_VERSION
xml.tag! 'n2:' + transaction_type + 'RequestDetails' do
xml.tag! 'n2:ReferenceID', reference_id if transaction_type == 'DoReferenceTransaction'
xml.tag! 'n2:PaymentAction', action
xml.tag! 'n2:PaymentDetails' do
xml.tag! 'n2:OrderTotal', localized_amount(money, currency_code), 'currencyID' => currency_code
# All of the values must be included together and add up to the order total
if [:subtotal, :shipping, :handling, :tax].all?{ |o| options.has_key?(o) }
xml.tag! 'n2:ItemTotal', localized_amount(options[:subtotal], currency_code), 'currencyID' => currency_code
xml.tag! 'n2:ShippingTotal', localized_amount(options[:shipping], currency_code),'currencyID' => currency_code
xml.tag! 'n2:HandlingTotal', localized_amount(options[:handling], currency_code),'currencyID' => currency_code
xml.tag! 'n2:TaxTotal', localized_amount(options[:tax], currency_code), 'currencyID' => currency_code
end
xml.tag! 'n2:NotifyURL', options[:notify_url]
xml.tag! 'n2:OrderDescription', options[:description]
xml.tag! 'n2:InvoiceID', options[:order_id]
xml.tag! 'n2:ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank?
add_address(xml, 'n2:ShipToAddress', options[:shipping_address]) if options[:shipping_address]
end
add_credit_card(xml, credit_card_or_referenced_id, billing_address, options) unless transaction_type == 'DoReferenceTransaction'
xml.tag! 'n2:IPAddress', options[:ip]
end
end
end
xml.target!
end
def add_credit_card(xml, credit_card, address, options)
xml.tag! 'n2:CreditCard' do
xml.tag! 'n2:CreditCardType', credit_card_type(card_brand(credit_card))
xml.tag! 'n2:CreditCardNumber', credit_card.number
xml.tag! 'n2:ExpMonth', format(credit_card.month, :two_digits)
xml.tag! 'n2:ExpYear', format(credit_card.year, :four_digits)
xml.tag! 'n2:CVV2', credit_card.verification_value
if [ 'switch', 'solo' ].include?(card_brand(credit_card).to_s)
xml.tag! 'n2:StartMonth', format(credit_card.start_month, :two_digits) unless credit_card.start_month.blank?
xml.tag! 'n2:StartYear', format(credit_card.start_year, :four_digits) unless credit_card.start_year.blank?
xml.tag! 'n2:IssueNumber', format(credit_card.issue_number, :two_digits) unless credit_card.issue_number.blank?
end
xml.tag! 'n2:CardOwner' do
xml.tag! 'n2:PayerName' do
xml.tag! 'n2:FirstName', credit_card.first_name
xml.tag! 'n2:LastName', credit_card.last_name
end
xml.tag! 'n2:Payer', options[:email]
add_address(xml, 'n2:Address', address)
end
end
end
def credit_card_type(type)
case type
when 'visa' then 'Visa'
when 'master' then 'MasterCard'
when 'discover' then 'Discover'
when 'american_express' then 'Amex'
when 'switch' then 'Switch'
when 'solo' then 'Solo'
end
end
def build_response(success, message, response, options = {})
Response.new(success, message, response, options)
end
end
end
end