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,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
+