activemerchant 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,84 @@
1
+ require File.dirname(__FILE__) + '/payflow/payflow_common_api'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PayflowGateway < Gateway
6
+ include PayflowCommonAPI
7
+
8
+ def authorize(money, credit_card, options = {})
9
+ if result = test_result_from_cc_number(credit_card.number)
10
+ return result
11
+ end
12
+
13
+ request = build_sale_or_authorization_request('Authorization', money, credit_card, options)
14
+ commit(request)
15
+ end
16
+
17
+ def purchase(money, credit_card, options = {})
18
+ if result = test_result_from_cc_number(credit_card.number)
19
+ return result
20
+ end
21
+
22
+ request = build_sale_or_authorization_request('Sale', money, credit_card, options)
23
+ commit(request)
24
+ end
25
+
26
+ def express
27
+ @express ||= PayflowExpressGateway.new(@options)
28
+ end
29
+
30
+ def self.supported_cardtypes
31
+ [:visa, :master, :american_express, :jcb, :discover, :diners_club]
32
+ end
33
+
34
+ private
35
+ def build_sale_or_authorization_request(action, money, credit_card, options)
36
+ xml = Builder::XmlMarkup.new :indent => 2
37
+ xml.tag! action do
38
+ xml.tag! 'PayData' do
39
+ xml.tag! 'Invoice' do
40
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
41
+ xml.tag! 'InvNum', options[:order_id] unless options[:order_id].blank?
42
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
43
+
44
+ billing_address = options[:billing_address] || options[:address]
45
+ shipping_address = options[:shipping_address] || billing_address
46
+
47
+ add_address(xml, 'BillTo', billing_address, options)
48
+ add_address(xml, 'ShipTo', shipping_address, options)
49
+
50
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => currency(money)
51
+ end
52
+
53
+ xml.tag! 'Tender' do
54
+ add_credit_card(xml, credit_card)
55
+ end
56
+ end
57
+ end
58
+ xml.target!
59
+ end
60
+
61
+ def add_credit_card(xml, credit_card)
62
+ xml.tag! 'Card' do
63
+ xml.tag! 'CardType', CARD_MAPPING[credit_card.type.to_sym]
64
+ xml.tag! 'CardNum', credit_card.number
65
+ xml.tag! 'ExpDate', expdate(credit_card)
66
+ xml.tag! 'NameOnCard', credit_card.name
67
+ xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value?
68
+ end
69
+ end
70
+
71
+ def expdate(creditcard)
72
+ year = sprintf("%.4i", creditcard.year)
73
+ month = sprintf("%.2i", creditcard.month)
74
+
75
+ "#{year}#{month}"
76
+ end
77
+
78
+ def build_response(success, message, response, options = {})
79
+ Response.new(success, message, response, options)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,17 @@
1
+ subject=/C=US/O=RSA Data Security, Inc./OU=Secure Server Certification Authority
2
+ notBefore=Nov 9 00:00:00 1994 GMT
3
+ notAfter=Jan 7 23:59:59 2010 GMT
4
+ -----BEGIN CERTIFICATE-----
5
+ MIICNDCCAaECEAKtZn5ORf5eV288mBle3cAwDQYJKoZIhvcNAQECBQAwXzELMAkG
6
+ A1UEBhMCVVMxIDAeBgNVBAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYD
7
+ VQQLEyVTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk0
8
+ MTEwOTAwMDAwMFoXDTEwMDEwNzIzNTk1OVowXzELMAkGA1UEBhMCVVMxIDAeBgNV
9
+ BAoTF1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2Vy
10
+ dmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGbMA0GCSqGSIb3DQEBAQUAA4GJ
11
+ ADCBhQJ+AJLOesGugz5aqomDV6wlAXYMra6OLDfO6zV4ZFQD5YRAUcm/jwjiioII
12
+ 0haGN1XpsSECrXZogZoFokvJSyVmIlZsiAeP94FZbYQHZXATcXY+m3dM41CJVphI
13
+ uR2nKRoTLkoRWZweFdVJVCxzOmmCsZc5nG1wZ0jl3S3WyB57AgMBAAEwDQYJKoZI
14
+ hvcNAQECBQADfgBl3X7hsuyw4jrg7HFGmhkRuNPHoLQDQCYCPgmc4RKz0Vr2N6W3
15
+ YQO2WxZpO8ZECAyIUwxrl0nHPjXcbLm7qt9cuzovk2C2qUtN8iD3zV9/ZHuO3ABc
16
+ 1/p3yjkWWW8O6tO1g39NTUJWdrTJXwT4OPjr0l91X817/OWOgHz8UA==
17
+ -----END CERTIFICATE-----
@@ -0,0 +1,190 @@
1
+ require 'digest/sha1'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ module PayflowCommonAPI
6
+ def self.included(base)
7
+ base.class_inheritable_accessor :default_currency
8
+ base.default_currency = 'USD'
9
+
10
+ # The certification_id is required by PayPal to make direct HTTPS posts to their servers.
11
+ # You can obtain a certification id by emailing: payflowintegrator@paypal.com
12
+ base.class_inheritable_accessor :certification_id
13
+ base.class_inheritable_accessor :partner
14
+
15
+ # Set the default partner to PayPal
16
+ base.partner = 'PayPal'
17
+ end
18
+
19
+ XMLNS = 'http://www.paypal.com/XMLPay'
20
+ TEST_URL = 'https://pilot-payflowpro.verisign.com/transaction'
21
+ LIVE_URL = 'https://payflowpro.verisign.com/transaction'
22
+
23
+ CARD_MAPPING = {
24
+ :visa => 'Visa',
25
+ :master => 'MasterCard',
26
+ :discover => 'Discover',
27
+ :american_express => 'Amex',
28
+ :jcb => 'JCB',
29
+ :diners_club => 'DinersClub',
30
+ :switch => 'Switch',
31
+ :solo => 'Solo'
32
+ }
33
+
34
+ def initialize(options = {})
35
+ requires!(options, :login, :password)
36
+ @options = {
37
+ :certification_id => self.class.certification_id,
38
+ :partner => self.class.partner
39
+ }.update(options)
40
+
41
+ super
42
+ end
43
+
44
+ def test?
45
+ @options[:test] || Base.gateway_mode == :test
46
+ end
47
+
48
+ def capture(money, authorization, options = {})
49
+ request = build_void_or_capture_request('Capture', authorization)
50
+ commit(request)
51
+ end
52
+
53
+ def void(authorization, options = {})
54
+ request = build_void_or_capture_request('Void', authorization)
55
+ commit(request)
56
+ end
57
+
58
+ private
59
+ def build_request(body)
60
+ xml = Builder::XmlMarkup.new :indent => 2
61
+ xml.instruct!
62
+ xml.tag! 'XMLPayRequest', 'Timeout' => 30, 'version' => "2.1", "xmlns" => XMLNS do
63
+ xml.tag! 'RequestData' do
64
+ xml.tag! 'Vendor', @options[:login]
65
+ xml.tag! 'Partner', @options[:partner]
66
+ xml.tag! 'Transactions' do
67
+ xml.tag! 'Transaction' do
68
+ xml.tag! 'Verbosity', 'MEDIUM'
69
+ xml << body
70
+ end
71
+ end
72
+ end
73
+ xml.tag! 'RequestAuth' do
74
+ xml.tag! 'UserPass' do
75
+ xml.tag! 'User', @options[:login]
76
+ xml.tag! 'Password', @options[:password]
77
+ end
78
+ end
79
+ end
80
+ xml.target!
81
+ end
82
+
83
+ def build_void_or_capture_request(action, authorization)
84
+ xml = Builder::XmlMarkup.new :indent => 2
85
+ xml.tag! action do
86
+ xml.tag! 'PNRef', authorization
87
+ end
88
+ xml.target!
89
+ end
90
+
91
+ def add_paypal_details(xml, options)
92
+ xml.tag! 'PayPal' do
93
+ xml.tag! 'EMail', options[:email]
94
+ xml.tag! 'ReturnURL', options[:return_url]
95
+ xml.tag! 'CancelURL', options[:cancel_return_url]
96
+ end
97
+ end
98
+
99
+ def add_address(xml, tag, address, options)
100
+ return if address.nil?
101
+ xml.tag! tag do
102
+ xml.tag! 'Name', address[:name] unless options[:name].blank?
103
+ xml.tag! 'Email', options[:email] unless options[:email].blank?
104
+ xml.tag! 'Phone', address[:phone] unless address[:phone].blank?
105
+ xml.tag! 'Address' do
106
+ xml.tag! 'Street', address[:address1] unless address[:address1].blank?
107
+ xml.tag! 'City', address[:city] unless address[:city].blank?
108
+ xml.tag! 'State', address[:state] unless address[:state].blank?
109
+ xml.tag! 'Country', address[:country] unless address[:country].blank?
110
+ xml.tag! 'Zip', address[:zip] unless address[:zip].blank?
111
+ end
112
+ end
113
+ end
114
+
115
+ def ssl_post(url, data, headers)
116
+ uri = URI.parse(url)
117
+
118
+ http = Net::HTTP.new(uri.host, uri.port)
119
+
120
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
121
+ http.verify_depth = 5
122
+ http.use_ssl = true
123
+ http.ca_file = File.dirname(__FILE__) + '/f73e89fd.0'
124
+
125
+ http.post(uri.path, data, headers).body
126
+ end
127
+
128
+ def parse(data)
129
+ response = {}
130
+ xml = REXML::Document.new(data)
131
+ root = REXML::XPath.first(xml, "//ResponseData")
132
+
133
+ if REXML::XPath.first(root, "//TransactionResult/attribute::Duplicate")
134
+ response[:duplicate] = true
135
+ end
136
+
137
+ root.elements.to_a.each do |node|
138
+ parse_element(response, node)
139
+ end
140
+
141
+ response
142
+ end
143
+
144
+ def parse_element(response, node)
145
+ if node.has_elements?
146
+ node.elements.each{|e| parse_element(response, e) }
147
+ else
148
+ response[node.name.underscore.to_sym] = node.text
149
+ end
150
+ end
151
+
152
+ def generate_request_token
153
+ Digest::SHA1.hexdigest(rand.to_s).slice(0,32)
154
+ end
155
+
156
+ def currency(money)
157
+ money.respond_to?(:currency) ? money.currency : self.default_currency
158
+ end
159
+
160
+ def build_headers(content_length)
161
+ {
162
+ "Content-Type" => "text/xml",
163
+ "Content-Length" => content_length.to_s,
164
+ "X-VPS-Timeout" => "30",
165
+ "X-VPS-VIT-Client-Certification-Id" => @options[:certification_id].to_s,
166
+ "X-VPS-VIT-Integration-Product" => "ActiveMerchant",
167
+ "X-VPS-VIT-Runtime-Version" => RUBY_VERSION,
168
+ "X-VPS-Request-ID" => generate_request_token
169
+ }
170
+ end
171
+
172
+ def commit(request_body)
173
+ request = build_request(request_body)
174
+ headers = build_headers(request_body.size)
175
+
176
+ url = test? ? TEST_URL : LIVE_URL
177
+ data = ssl_post(url, request, headers)
178
+ @response = parse(data)
179
+
180
+ success = @response[:result] == "0"
181
+ message = @response[:message]
182
+
183
+ build_response(success, message, @response,
184
+ :test => test?,
185
+ :authorization => @response[:pn_ref]
186
+ )
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,30 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PayflowExpressResponse < Response
4
+ def email
5
+ @params['e_mail']
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' => nil,
19
+ 'address1' => @params['street'],
20
+ 'address2' => nil,
21
+ 'city' => @params['city'],
22
+ 'state' => @params['state'],
23
+ 'country' => @params['country'],
24
+ 'zip' => @params['zip'],
25
+ 'phone' => nil
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,123 @@
1
+ require File.dirname(__FILE__) + '/payflow/payflow_common_api'
2
+ require File.dirname(__FILE__) + '/payflow/payflow_express_response'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class PayflowExpressGateway < Gateway
7
+ include PayflowCommonAPI
8
+
9
+ LIVE_REDIRECT_URL = 'https://www.paypal.com/cgibin/webscr?cmd=_express-checkout&token='
10
+ TEST_REDIRECT_URL = 'https://test-expresscheckout.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 authorize(money, options = {})
21
+ requires!(options, :token, :payer_id)
22
+ request = build_sale_or_authorization_request('Authorization', money, options)
23
+ commit(request)
24
+ end
25
+
26
+ def purchase(money, options = {})
27
+ requires!(options, :token, :payer_id)
28
+ request = build_sale_or_authorization_request('Sale', money, options)
29
+ commit(request)
30
+ end
31
+
32
+ def setup_authorization(money, options = {})
33
+ requires!(options, :return_url, :cancel_return_url)
34
+
35
+ request = build_setup_express_sale_or_authorization_request('Authorization', money, options)
36
+ commit(request)
37
+ end
38
+
39
+ def setup_purchase(money, options = {})
40
+ requires!(options, :return_url, :cancel_return_url)
41
+
42
+ request = build_setup_express_sale_or_authorization_request('Sale', money, options)
43
+ commit(request)
44
+ end
45
+
46
+ def details_for(token)
47
+ request = build_get_express_details_request(token)
48
+ commit(request)
49
+ end
50
+
51
+ private
52
+ def build_get_express_details_request(token)
53
+ xml = Builder::XmlMarkup.new :indent => 2
54
+ xml.tag! 'GetExpressCheckout' do
55
+ xml.tag! 'Authorization' do
56
+ xml.tag! 'PayData' do
57
+ xml.tag! 'Tender' do
58
+ xml.tag! 'PayPal' do
59
+ xml.tag! 'Token', token
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ xml.target!
66
+ end
67
+
68
+ def build_setup_express_sale_or_authorization_request(action, money, options = {})
69
+ xml = Builder::XmlMarkup.new :indent => 2
70
+ xml.tag! 'SetExpressCheckout' do
71
+ xml.tag! action do
72
+ xml.tag! 'PayData' do
73
+ xml.tag! 'Invoice' do
74
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
75
+ xml.tag! 'InvNum', options[:order_id] unless options[:order_id].blank?
76
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
77
+
78
+ billing_address = options[:billing_address] || options[:address]
79
+ shipping_address = options[:shipping_address] || billing_address
80
+
81
+ add_address(xml, 'BillTo', billing_address, options)
82
+ add_address(xml, 'ShipTo', shipping_address, options)
83
+
84
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => currency(money)
85
+ end
86
+
87
+ xml.tag! 'Tender' do
88
+ add_paypal_details(xml, options)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ xml.target!
94
+ end
95
+
96
+ def build_sale_or_authorization_request(action, money, options)
97
+ xml = Builder::XmlMarkup.new :indent => 2
98
+ xml.tag! 'DoExpressCheckout' do
99
+ xml.tag! action do
100
+ xml.tag! 'PayData' do
101
+ xml.tag! 'Invoice' do
102
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => currency(money)
103
+ end
104
+ xml.tag! 'Tender' do
105
+ xml.tag! 'PayPal' do
106
+ xml.tag! 'Token', options[:token]
107
+ xml.tag! 'PayerID', options[:payer_id]
108
+ xml.tag! 'NotifyURL', options[:notify_url]
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ xml.target!
115
+ end
116
+
117
+ def build_response(success, message, response, options = {})
118
+ PayflowExpressResponse.new(success, message, response, options)
119
+ end
120
+ end
121
+ end
122
+ end
123
+
@@ -0,0 +1,9 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PayflowExpressUkGateway < PayflowExpressGateway
4
+ self.default_currency = 'GBP'
5
+ self.partner = 'PayPalUk'
6
+ end
7
+ end
8
+ end
9
+