activemerchant 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/CHANGELOG +40 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +93 -0
  4. data/lib/active_merchant.rb +59 -0
  5. data/lib/active_merchant/billing/base.rb +52 -0
  6. data/lib/active_merchant/billing/credit_card.rb +217 -0
  7. data/lib/active_merchant/billing/gateway.rb +100 -0
  8. data/lib/active_merchant/billing/gateways.rb +15 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +236 -0
  10. data/lib/active_merchant/billing/gateways/bogus.rb +92 -0
  11. data/lib/active_merchant/billing/gateways/eway.rb +235 -0
  12. data/lib/active_merchant/billing/gateways/linkpoint.rb +445 -0
  13. data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
  14. data/lib/active_merchant/billing/gateways/payflow.rb +84 -0
  15. data/lib/active_merchant/billing/gateways/payflow/f73e89fd.0 +17 -0
  16. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +190 -0
  17. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +30 -0
  18. data/lib/active_merchant/billing/gateways/payflow_express.rb +123 -0
  19. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +9 -0
  20. data/lib/active_merchant/billing/gateways/payflow_uk.rb +17 -0
  21. data/lib/active_merchant/billing/gateways/paypal.rb +90 -0
  22. data/lib/active_merchant/billing/gateways/paypal/api_cert_chain.crt +35 -0
  23. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +208 -0
  24. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +30 -0
  25. data/lib/active_merchant/billing/gateways/paypal_express.rb +115 -0
  26. data/lib/active_merchant/billing/gateways/psigate.rb +265 -0
  27. data/lib/active_merchant/billing/gateways/trust_commerce.rb +330 -0
  28. data/lib/active_merchant/billing/gateways/usa_epay.rb +189 -0
  29. data/lib/active_merchant/billing/integrations.rb +12 -0
  30. data/lib/active_merchant/billing/integrations/action_view_helper.rb +65 -0
  31. data/lib/active_merchant/billing/integrations/bogus.rb +17 -0
  32. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  33. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  34. data/lib/active_merchant/billing/integrations/chronopay.rb +17 -0
  35. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +81 -0
  36. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +156 -0
  37. data/lib/active_merchant/billing/integrations/gestpay.rb +21 -0
  38. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  39. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +72 -0
  40. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +83 -0
  41. data/lib/active_merchant/billing/integrations/helper.rb +79 -0
  42. data/lib/active_merchant/billing/integrations/nochex.rb +21 -0
  43. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  44. data/lib/active_merchant/billing/integrations/nochex/notification.rb +101 -0
  45. data/lib/active_merchant/billing/integrations/notification.rb +52 -0
  46. data/lib/active_merchant/billing/integrations/paypal.rb +35 -0
  47. data/lib/active_merchant/billing/integrations/paypal/helper.rb +103 -0
  48. data/lib/active_merchant/billing/integrations/paypal/notification.rb +187 -0
  49. data/lib/active_merchant/billing/response.rb +28 -0
  50. data/lib/active_merchant/lib/country.rb +297 -0
  51. data/lib/active_merchant/lib/posts_data.rb +21 -0
  52. data/lib/active_merchant/lib/requires_parameters.rb +17 -0
  53. data/lib/active_merchant/lib/validateable.rb +76 -0
  54. data/lib/tasks/cia.rb +90 -0
  55. metadata +129 -0
@@ -0,0 +1,17 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PayflowUkGateway < PayflowGateway
4
+ self.default_currency = 'GBP'
5
+ self.partner = 'PayPalUk'
6
+
7
+ def express
8
+ @express ||= PayflowExpressUkGateway.new(@options)
9
+ end
10
+
11
+ def self.supported_cardtypes
12
+ [:visa, :master, :american_express, :discover, :solo, :switch]
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/paypal/paypal_common_api'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PaypalGateway < Gateway
6
+ include PaypalCommonAPI
7
+
8
+ def self.supported_cardtypes
9
+ [:visa, :master, :american_express, :discover]
10
+ end
11
+
12
+ def authorize(money, credit_card, options = {})
13
+ requires!(options, :ip)
14
+
15
+ if result = test_result_from_cc_number(credit_card.number)
16
+ return result
17
+ end
18
+
19
+ commit 'DoDirectPayment', build_sale_or_authorization_request('Authorization', money, credit_card, options)
20
+ end
21
+
22
+ def purchase(money, credit_card, options = {})
23
+ requires!(options, :ip)
24
+
25
+ if result = test_result_from_cc_number(credit_card.number)
26
+ return result
27
+ end
28
+
29
+ commit 'DoDirectPayment', build_sale_or_authorization_request('Sale', money, credit_card, options)
30
+ end
31
+
32
+ def express
33
+ @express ||= PaypalExpressGateway.new(@options)
34
+ end
35
+
36
+ private
37
+ def build_sale_or_authorization_request(action, money, credit_card, options)
38
+ xml = Builder::XmlMarkup.new :indent => 2
39
+
40
+ xml.tag! 'DoDirectPaymentReq', 'xmlns' => 'urn:ebay:api:PayPalAPI' do
41
+ xml.tag! 'DoDirectPaymentRequest', 'xmlns:n2' => 'urn:ebay:apis:eBLBaseComponents' do
42
+ xml.tag! 'n2:Version', '2.0'
43
+ xml.tag! 'n2:DoDirectPaymentRequestDetails' do
44
+ xml.tag! 'n2:PaymentAction', action
45
+ xml.tag! 'n2:PaymentDetails' do
46
+ xml.tag! 'n2:OrderTotal', amount(money), 'currencyID' => currency(money)
47
+ xml.tag! 'n2:NotifyURL', options[:notify_url]
48
+ end
49
+ add_credit_card(xml, credit_card, options[:billing_address] || options[:address])
50
+ xml.tag! 'n2:IPAddress', options[:ip]
51
+ end
52
+ end
53
+ end
54
+
55
+ xml.target!
56
+ end
57
+
58
+ def add_credit_card(xml, credit_card, address)
59
+ xml.tag! 'n2:CreditCard' do
60
+ xml.tag! 'n2:CreditCardType', credit_card_type(credit_card.type)
61
+ xml.tag! 'n2:CreditCardNumber', credit_card.number
62
+ xml.tag! 'n2:ExpMonth', sprintf("%.2i", credit_card.month)
63
+ xml.tag! 'n2:ExpYear', sprintf("%.4i", credit_card.year)
64
+ xml.tag! 'n2:CVV2', credit_card.verification_value
65
+
66
+ xml.tag! 'n2:CardOwner' do
67
+ xml.tag! 'n2:PayerName' do
68
+ xml.tag! 'n2:FirstName', credit_card.first_name
69
+ xml.tag! 'n2:LastName', credit_card.last_name
70
+ end
71
+ add_address(xml, address)
72
+ end
73
+ end
74
+ end
75
+
76
+ def credit_card_type(type)
77
+ case type
78
+ when 'visa' then 'Visa'
79
+ when 'master' then 'MasterCard'
80
+ when 'discover' then 'Discover'
81
+ when 'american_express' then 'Amex'
82
+ end
83
+ end
84
+
85
+ def build_response(success, message, response, options = {})
86
+ Response.new(success, message, response, options)
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,35 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDgzCCAuygAwIBAgIQJUuKhThCzONY+MXdriJupDANBgkqhkiG9w0BAQUFADBf
3
+ MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsT
4
+ LkNsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkw
5
+ HhcNOTcwNDE3MDAwMDAwWhcNMTExMDI0MjM1OTU5WjCBujEfMB0GA1UEChMWVmVy
6
+ aVNpZ24gVHJ1c3QgTmV0d29yazEXMBUGA1UECxMOVmVyaVNpZ24sIEluYy4xMzAx
7
+ BgNVBAsTKlZlcmlTaWduIEludGVybmF0aW9uYWwgU2VydmVyIENBIC0gQ2xhc3Mg
8
+ MzFJMEcGA1UECxNAd3d3LnZlcmlzaWduLmNvbS9DUFMgSW5jb3JwLmJ5IFJlZi4g
9
+ TElBQklMSVRZIExURC4oYyk5NyBWZXJpU2lnbjCBnzANBgkqhkiG9w0BAQEFAAOB
10
+ jQAwgYkCgYEA2IKA6NYZAn0fhRg5JaJlK+G/1AXTvOY2O6rwTGxbtueqPHNFVbLx
11
+ veqXQu2aNAoV1Klc9UAl3dkHwTKydWzEyruj/lYncUOqY/UwPpMo5frxCTvzt01O
12
+ OfdcSVq4wR3Tsor+cDCVQsv+K1GLWjw6+SJPkLICp1OcTzTnqwSye28CAwEAAaOB
13
+ 4zCB4DAPBgNVHRMECDAGAQH/AgEAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQEw
14
+ KjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL0NQUzA0BgNV
15
+ HSUELTArBggrBgEFBQcDAQYIKwYBBQUHAwIGCWCGSAGG+EIEAQYKYIZIAYb4RQEI
16
+ ATALBgNVHQ8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgEGMDEGA1UdHwQqMCgwJqAk
17
+ oCKGIGh0dHA6Ly9jcmwudmVyaXNpZ24uY29tL3BjYTMuY3JsMA0GCSqGSIb3DQEB
18
+ BQUAA4GBAAgB7ORolANC8XPxI6I63unx2sZUxCM+hurPajozq+qcBBQHNgYL+Yhv
19
+ 1RPuKSvD5HKNRO3RrCAJLeH24RkFOLA9D59/+J4C3IYChmFOJl9en5IeDCSk9dBw
20
+ E88mw0M9SR2egi5SX7w+xmYpAY5Okiy8RnUDgqxz6dl+C2fvVFIa
21
+ -----END CERTIFICATE-----
22
+ -----BEGIN CERTIFICATE-----
23
+ MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
24
+ A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
25
+ cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
26
+ MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
27
+ BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
28
+ YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
29
+ ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
30
+ BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
31
+ I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
32
+ CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
33
+ lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
34
+ AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
35
+ -----END CERTIFICATE-----
@@ -0,0 +1,208 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ # This class is an abstract base class for both PaypalGateway and
4
+ # PaypalExpressGateway
5
+ module PaypalCommonAPI
6
+ def self.included(base)
7
+ base.cattr_accessor :pem_file
8
+ end
9
+
10
+ TEST_URL = 'https://api.sandbox.paypal.com/2.0/'
11
+ LIVE_URL = 'https://api-aa.paypal.com/2.0/'
12
+
13
+ ENVELOPE_NAMESPACES = { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
14
+ 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
15
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
16
+ }
17
+ CREDENTIALS_NAMESPACES = { 'xmlns' => 'urn:ebay:api:PayPalAPI',
18
+ 'xmlns:n1' => 'urn:ebay:apis:eBLBaseComponents',
19
+ 'env:mustUnderstand' => '0'
20
+ }
21
+
22
+ # <tt>:pem</tt> The text of your PayPal PEM file. Note
23
+ # this is not the path to file, but its
24
+ # contents. If you are only using one PEM
25
+ # file on your site you can declare it
26
+ # globally and then you won't need to
27
+ # include this option
28
+ def initialize(options = {})
29
+ requires!(options, :login, :password)
30
+
31
+ @options = {
32
+ :pem => self.class.pem_file
33
+ }.update(options)
34
+
35
+ super
36
+ end
37
+
38
+ def test?
39
+ @options[:test] || Base.gateway_mode == :test
40
+ end
41
+
42
+ def capture(money, authorization, options = {})
43
+ commit 'DoCapture', build_capture_request(money, authorization, options)
44
+ end
45
+
46
+ def void(authorization, options = {})
47
+ commit 'DoVoid', build_void_request(authorization, options)
48
+ end
49
+
50
+ private
51
+
52
+ def build_capture_request(money, authorization, options)
53
+ xml = Builder::XmlMarkup.new :indent => 2
54
+
55
+ xml.tag! 'DoCaptureReq', 'xmlns' => 'urn:ebay:api:PayPalAPI' do
56
+ xml.tag! 'DoCaptureRequest', 'xmlns:n2' => 'urn:ebay:apis:eBLBaseComponents' do
57
+ xml.tag! 'n2:Version', '2.0'
58
+ xml.tag! 'AuthorizationID', authorization
59
+ xml.tag! 'Amount', amount(money), 'currencyID' => currency(money)
60
+ xml.tag! 'CompleteType', 'Complete'
61
+ xml.tag! 'Note', options[:description]
62
+ end
63
+ end
64
+
65
+ xml.target!
66
+ end
67
+
68
+ def build_void_request(authorization, options)
69
+ xml = Builder::XmlMarkup.new :indent => 2
70
+
71
+ xml.tag! 'DoVoidReq', 'xmlns' => 'urn:ebay:api:PayPalAPI' do
72
+ xml.tag! 'DoVoidRequest', 'xmlns:n2' => 'urn:ebay:apis:eBLBaseComponents' do
73
+ xml.tag! 'n2:Version', '2.0'
74
+ xml.tag! 'AuthorizationID', authorization
75
+ xml.tag! 'Note', options[:description]
76
+ end
77
+ end
78
+
79
+ xml.target!
80
+ end
81
+
82
+ def ssl_post(data)
83
+ uri = URI.parse(test? ? TEST_URL : LIVE_URL)
84
+
85
+ http = Net::HTTP.new(uri.host, uri.port)
86
+
87
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
88
+ http.use_ssl = true
89
+ http.cert = OpenSSL::X509::Certificate.new(@options[:pem])
90
+ http.key = OpenSSL::PKey::RSA.new(@options[:pem])
91
+ http.ca_file = File.dirname(__FILE__) + '/api_cert_chain.crt'
92
+
93
+ http.post(uri.path, data).body
94
+ end
95
+
96
+ def parse(action, xml)
97
+ response = {}
98
+ xml = REXML::Document.new(xml)
99
+ if root = REXML::XPath.first(xml, "//#{action}Response")
100
+ root.elements.to_a.each do |node|
101
+ case node.name
102
+ when 'Errors'
103
+ response[:message] = node.elements.to_a('//LongMessage').collect{|error| error.text}.join('.')
104
+ else
105
+ parse_element(response, node)
106
+ end
107
+ end
108
+ elsif root = REXML::XPath.first(xml, "//SOAP-ENV:Fault")
109
+ parse_element(response, root)
110
+ response[:message] = "#{response[:faultcode]}: #{response[:faultstring]} - #{response[:detail]}"
111
+ end
112
+
113
+ response
114
+ end
115
+
116
+ def parse_element(response, node)
117
+ if node.has_elements?
118
+ node.elements.each{|e| parse_element(response, e) }
119
+ else
120
+ response[node.name.underscore.to_sym] = node.text
121
+ node.attributes.each do |k, v|
122
+ response["#{node.name.underscore}_#{k.underscore}".to_sym] = v if k == 'currencyID'
123
+ end
124
+ end
125
+ end
126
+
127
+ def response_type_for(action)
128
+ case action
129
+ when 'Authorization', 'Purchase'
130
+ 'DoDirectPaymentResponse'
131
+ when 'Void'
132
+ 'DoVoidResponse'
133
+ when 'Capture'
134
+ 'DoCaptureResponse'
135
+ end
136
+ end
137
+
138
+ def build_request(body)
139
+ xml = Builder::XmlMarkup.new :indent => 2
140
+
141
+ xml.instruct!
142
+ xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do
143
+ xml.tag! 'env:Header' do
144
+ add_credentials(xml)
145
+ end
146
+
147
+ xml.tag! 'env:Body' do
148
+ xml << body
149
+ end
150
+ end
151
+ xml.target!
152
+ end
153
+
154
+ def add_credentials(xml)
155
+ xml.tag! 'RequesterCredentials', CREDENTIALS_NAMESPACES do
156
+ xml.tag! 'n1:Credentials' do
157
+ xml.tag! 'Username', @options[:login]
158
+ xml.tag! 'Password', @options[:password]
159
+ xml.tag! 'Subject', @options[:subject]
160
+ end
161
+ end
162
+ end
163
+
164
+ def response_type_for(action)
165
+ case action
166
+ when 'Authorization', 'Purchase'
167
+ 'DoDirectPaymentResponse'
168
+ when 'Void'
169
+ 'DoVoidResponse'
170
+ when 'Capture'
171
+ 'DoCaptureResponse'
172
+ end
173
+ end
174
+
175
+ def add_address(xml, address)
176
+ return if address.nil?
177
+ xml.tag! 'n2:Address' do
178
+ xml.tag! 'n2:Name', address[:name]
179
+ xml.tag! 'n2:Street1', address[:address1]
180
+ xml.tag! 'n2:Street2', address[:address2]
181
+ xml.tag! 'n2:CityName', address[:city]
182
+ xml.tag! 'n2:StateOrProvince', address[:state]
183
+ xml.tag! 'n2:Country', address[:country]
184
+ xml.tag! 'n2:PostalCode', address[:zip]
185
+ xml.tag! 'n2:Phone', address[:phone]
186
+ end
187
+ end
188
+
189
+ def currency(money)
190
+ money.respond_to?(:currency) ? money.currency : 'USD'
191
+ end
192
+
193
+ def commit(action, request)
194
+ data = ssl_post build_request(request)
195
+
196
+ @response = parse(action, data)
197
+
198
+ success = @response[:ack] == "Success"
199
+ message = @response[:message] || @response[:ack]
200
+
201
+ build_response(success, message, @response,
202
+ :test => test?,
203
+ :authorization => @response[:transaction_id]
204
+ )
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,30 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaypalExpressResponse < Response
4
+ def email
5
+ @params['payer']
6
+ end
7
+
8
+ def token
9
+ @params['token']
10
+ end
11
+
12
+ def payer_id
13
+ @params['payer_id']
14
+ end
15
+
16
+ def address
17
+ { 'name' => @params['name'],
18
+ 'company' => @params['payer_business'],
19
+ 'address1' => @params['street1'],
20
+ 'address2' => @params['street2'],
21
+ 'city' => @params['city_name'],
22
+ 'state' => @params['state_or_province'],
23
+ 'country' => @params['country'],
24
+ 'zip' => @params['postal_code'],
25
+ 'phone' => nil
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/paypal/paypal_common_api'
2
+ require File.dirname(__FILE__) + '/paypal/paypal_express_response'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class PaypalExpressGateway < Gateway
7
+ include PaypalCommonAPI
8
+
9
+ LIVE_REDIRECT_URL = 'https://www.paypal.com/cgibin/webscr?cmd=_express-checkout&token='
10
+ TEST_REDIRECT_URL = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='
11
+
12
+ def redirect_url
13
+ test? ? TEST_REDIRECT_URL : LIVE_REDIRECT_URL
14
+ end
15
+
16
+ def redirect_url_for(token)
17
+ "#{redirect_url}#{token}"
18
+ end
19
+
20
+ def setup_authorization(money, options = {})
21
+ requires!(options, :return_url, :cancel_return_url)
22
+
23
+ commit 'SetExpressCheckout', build_setup_request('Authorization', money, options)
24
+ end
25
+
26
+ def setup_purchase(money, options = {})
27
+ requires!(options, :return_url, :cancel_return_url)
28
+
29
+ commit 'SetExpressCheckout', build_setup_request('Sale', money, options)
30
+ end
31
+
32
+ def details_for(token)
33
+ commit 'GetExpressCheckoutDetails', build_get_details_request(token)
34
+ end
35
+
36
+ def authorize(money, options = {})
37
+ requires!(options, :token, :payer_id)
38
+
39
+ commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Authorization', money, options)
40
+ end
41
+
42
+ def purchase(money, token, payer_id, options = {})
43
+ requires!(options, :token, :payer_id)
44
+
45
+ commit 'DoExpressCheckoutPayment', build_sale_or_authorization_request('Sale', money, options)
46
+ end
47
+
48
+ private
49
+ def build_get_details_request(token)
50
+ xml = Builder::XmlMarkup.new :indent => 2
51
+ xml.tag! 'GetExpressCheckoutDetailsReq', 'xmlns' => 'urn:ebay:api:PayPalAPI' do
52
+ xml.tag! 'GetExpressCheckoutDetailsRequest', 'xmlns:n2' => 'urn:ebay:apis:eBLBaseComponents' do
53
+ xml.tag! 'n2:Version', '2.0'
54
+ xml.tag! 'Token', token
55
+ end
56
+ end
57
+
58
+ xml.target!
59
+ end
60
+
61
+ def build_sale_or_authorization_request(action, money, options)
62
+ xml = Builder::XmlMarkup.new :indent => 2
63
+ xml.tag! 'DoExpressCheckoutPaymentReq', 'xmlns' => 'urn:ebay:api:PayPalAPI' do
64
+ xml.tag! 'DoExpressCheckoutPaymentRequest', 'xmlns:n2' => 'urn:ebay:apis:eBLBaseComponents' do
65
+ xml.tag! 'n2:Version', '2.0'
66
+ xml.tag! 'n2:DoExpressCheckoutPaymentRequestDetails' do
67
+ xml.tag! 'n2:PaymentAction', action
68
+ xml.tag! 'n2:Token', options[:token]
69
+ xml.tag! 'n2:PayerID', options[:payer_id]
70
+ xml.tag! 'n2:PaymentDetails' do
71
+ xml.tag! 'n2:OrderTotal', amount(money), 'currencyID' => currency(money)
72
+ xml.tag! 'n2:NotifyURL', options[:notify_url]
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ xml.target!
79
+ end
80
+
81
+ def build_setup_request(action, money, options)
82
+ xml = Builder::XmlMarkup.new :indent => 2
83
+ xml.tag! 'SetExpressCheckoutReq', 'xmlns' => 'urn:ebay:api:PayPalAPI' do
84
+ xml.tag! 'SetExpressCheckoutRequest', 'xmlns:n2' => 'urn:ebay:apis:eBLBaseComponents' do
85
+ xml.tag! 'n2:Version', '2.0'
86
+ xml.tag! 'n2:SetExpressCheckoutRequestDetails' do
87
+ xml.tag! 'n2:PaymentAction', action
88
+ xml.tag! 'n2:OrderTotal', amount(money), 'currencyID' => currency(money)
89
+ xml.tag! 'n2:MaxAmount', amount(options[:max_amount]), 'currencyID' => currency(options[:max_amount]) if options[:max_amount]
90
+ add_address(xml, options[:billing_address] || options[:address])
91
+ #xml.tag! 'n2:AddressOverride', 1
92
+ #xml.tag! 'n2:NoShipping', 1
93
+ xml.tag! 'n2:PageStyle', options[:page_style] unless options[:page_style].blank?
94
+ xml.tag! 'n2:ReturnURL', options[:return_url]
95
+ xml.tag! 'n2:CancelURL', options[:cancel_return_url]
96
+ xml.tag! 'n2:IPAddress', options[:ip]
97
+ xml.tag! 'n2:OrderDescription', options[:description]
98
+ xml.tag! 'n2:BuyerEmail', options[:email] unless options[:email].blank?
99
+ xml.tag! 'n2:InvoiceID', options[:order_id]
100
+
101
+ # This should be set to the same locale as the shop
102
+ # localeCode - String
103
+ end
104
+ end
105
+ end
106
+
107
+ xml.target!
108
+ end
109
+
110
+ def build_response(success, message, response, options = {})
111
+ PaypalExpressResponse.new(success, message, response, options)
112
+ end
113
+ end
114
+ end
115
+ end