n8_activemerchant 1.9.3

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 (158) hide show
  1. data/CHANGELOG +574 -0
  2. data/CONTRIBUTORS +175 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +151 -0
  5. data/gem-public_cert.pem +20 -0
  6. data/lib/active_merchant.rb +49 -0
  7. data/lib/active_merchant/billing.rb +9 -0
  8. data/lib/active_merchant/billing/avs_result.rb +98 -0
  9. data/lib/active_merchant/billing/base.rb +57 -0
  10. data/lib/active_merchant/billing/check.rb +68 -0
  11. data/lib/active_merchant/billing/credit_card.rb +161 -0
  12. data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
  13. data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
  14. data/lib/active_merchant/billing/cvv_result.rb +38 -0
  15. data/lib/active_merchant/billing/expiry_date.rb +34 -0
  16. data/lib/active_merchant/billing/gateway.rb +169 -0
  17. data/lib/active_merchant/billing/gateways.rb +18 -0
  18. data/lib/active_merchant/billing/gateways/authorize_net.rb +654 -0
  19. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +736 -0
  20. data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
  21. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +244 -0
  22. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  23. data/lib/active_merchant/billing/gateways/bogus.rb +102 -0
  24. data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
  25. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  26. data/lib/active_merchant/billing/gateways/braintree_blue.rb +210 -0
  27. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  28. data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
  29. data/lib/active_merchant/billing/gateways/cyber_source.rb +406 -0
  30. data/lib/active_merchant/billing/gateways/data_cash.rb +593 -0
  31. data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
  32. data/lib/active_merchant/billing/gateways/elavon.rb +134 -0
  33. data/lib/active_merchant/billing/gateways/epay.rb +263 -0
  34. data/lib/active_merchant/billing/gateways/eway.rb +277 -0
  35. data/lib/active_merchant/billing/gateways/exact.rb +222 -0
  36. data/lib/active_merchant/billing/gateways/first_pay.rb +172 -0
  37. data/lib/active_merchant/billing/gateways/garanti.rb +222 -0
  38. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  39. data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
  40. data/lib/active_merchant/billing/gateways/iridium.rb +253 -0
  41. data/lib/active_merchant/billing/gateways/jetpay.rb +270 -0
  42. data/lib/active_merchant/billing/gateways/linkpoint.rb +449 -0
  43. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
  44. data/lib/active_merchant/billing/gateways/merchant_ware.rb +283 -0
  45. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  46. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +220 -0
  47. data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
  48. data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
  49. data/lib/active_merchant/billing/gateways/netaxept.rb +234 -0
  50. data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
  51. data/lib/active_merchant/billing/gateways/ogone.rb +279 -0
  52. data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
  53. data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
  54. data/lib/active_merchant/billing/gateways/paybox_direct.rb +203 -0
  55. data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
  56. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
  57. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
  58. data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
  59. data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
  60. data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
  61. data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
  62. data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
  63. data/lib/active_merchant/billing/gateways/paypal.rb +121 -0
  64. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +326 -0
  65. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
  66. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  67. data/lib/active_merchant/billing/gateways/paypal_express.rb +145 -0
  68. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
  69. data/lib/active_merchant/billing/gateways/paysimple/paysimple.rb +333 -0
  70. data/lib/active_merchant/billing/gateways/paysimple/usaepay.wsdl +1596 -0
  71. data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
  72. data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
  73. data/lib/active_merchant/billing/gateways/psl_card.rb +304 -0
  74. data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
  75. data/lib/active_merchant/billing/gateways/realex.rb +200 -0
  76. data/lib/active_merchant/billing/gateways/sage.rb +146 -0
  77. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  78. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +116 -0
  79. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  80. data/lib/active_merchant/billing/gateways/sage_pay.rb +315 -0
  81. data/lib/active_merchant/billing/gateways/sallie_mae.rb +144 -0
  82. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  83. data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
  84. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
  85. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
  86. data/lib/active_merchant/billing/gateways/skip_jack.rb +453 -0
  87. data/lib/active_merchant/billing/gateways/smart_ps.rb +265 -0
  88. data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
  89. data/lib/active_merchant/billing/gateways/transax.rb +25 -0
  90. data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
  91. data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
  92. data/lib/active_merchant/billing/gateways/usa_epay_soap.rb +154 -0
  93. data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
  94. data/lib/active_merchant/billing/gateways/viaklix.rb +189 -0
  95. data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
  96. data/lib/active_merchant/billing/integrations.rb +17 -0
  97. data/lib/active_merchant/billing/integrations/action_view_helper.rb +68 -0
  98. data/lib/active_merchant/billing/integrations/bogus.rb +23 -0
  99. data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
  100. data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
  101. data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
  102. data/lib/active_merchant/billing/integrations/chronopay.rb +23 -0
  103. data/lib/active_merchant/billing/integrations/chronopay/helper.rb +120 -0
  104. data/lib/active_merchant/billing/integrations/chronopay/notification.rb +158 -0
  105. data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
  106. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  107. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +188 -0
  108. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  109. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  110. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  111. data/lib/active_merchant/billing/integrations/gestpay.rb +25 -0
  112. data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
  113. data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
  114. data/lib/active_merchant/billing/integrations/gestpay/notification.rb +85 -0
  115. data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
  116. data/lib/active_merchant/billing/integrations/helper.rb +96 -0
  117. data/lib/active_merchant/billing/integrations/hi_trust.rb +27 -0
  118. data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
  119. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
  120. data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
  121. data/lib/active_merchant/billing/integrations/nochex.rb +88 -0
  122. data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
  123. data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
  124. data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
  125. data/lib/active_merchant/billing/integrations/notification.rb +62 -0
  126. data/lib/active_merchant/billing/integrations/paypal.rb +39 -0
  127. data/lib/active_merchant/billing/integrations/paypal/helper.rb +119 -0
  128. data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
  129. data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
  130. data/lib/active_merchant/billing/integrations/quickpay.rb +17 -0
  131. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
  132. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
  133. data/lib/active_merchant/billing/integrations/return.rb +37 -0
  134. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  135. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  136. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +109 -0
  137. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +204 -0
  138. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +27 -0
  139. data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
  140. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  141. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  142. data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
  143. data/lib/active_merchant/billing/response.rb +32 -0
  144. data/lib/active_merchant/common.rb +14 -0
  145. data/lib/active_merchant/common/connection.rb +162 -0
  146. data/lib/active_merchant/common/country.rb +328 -0
  147. data/lib/active_merchant/common/error.rb +26 -0
  148. data/lib/active_merchant/common/post_data.rb +24 -0
  149. data/lib/active_merchant/common/posts_data.rb +61 -0
  150. data/lib/active_merchant/common/requires_parameters.rb +16 -0
  151. data/lib/active_merchant/common/utils.rb +18 -0
  152. data/lib/active_merchant/common/validateable.rb +76 -0
  153. data/lib/active_merchant/version.rb +3 -0
  154. data/lib/activemerchant.rb +1 -0
  155. data/lib/certs/cacert.pem +7815 -0
  156. data/lib/support/gateway_support.rb +58 -0
  157. data/lib/support/outbound_hosts.rb +25 -0
  158. metadata +270 -0
@@ -0,0 +1,120 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class PaySecureGateway < Gateway
4
+ URL = 'https://clearance.commsecure.com.au/cgi-bin/PSDirect'
5
+
6
+ self.money_format = :cents
7
+
8
+ # Currently Authorization and Capture is not implemented because
9
+ # capturing requires the original credit card information
10
+ TRANSACTIONS = {
11
+ :purchase => 'PURCHASE',
12
+ :authorization => 'AUTHORISE',
13
+ :capture => 'ADVICE',
14
+ :credit => 'REFUND'
15
+ }
16
+
17
+ SUCCESS = 'Accepted'
18
+ SUCCESS_MESSAGE = 'The transaction was approved'
19
+
20
+ self.supported_countries = ['AU']
21
+ self.homepage_url = 'http://www.commsecure.com.au/paysecure.shtml'
22
+ self.display_name = 'PaySecure'
23
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
24
+
25
+ def initialize(options = {})
26
+ requires!(options, :login, :password)
27
+ @options = options
28
+ super
29
+ end
30
+
31
+ def purchase(money, credit_card, options = {})
32
+ requires!(options, :order_id)
33
+
34
+ post = {}
35
+ add_amount(post, money)
36
+ add_invoice(post, options)
37
+ add_credit_card(post, credit_card)
38
+
39
+ commit(:purchase, money, post)
40
+ end
41
+
42
+ private
43
+ # Used for capturing, which is currently not supported.
44
+ def add_reference(post, identification)
45
+ auth, trans_id = identification.split(";")
46
+ post[:authnum] = auth
47
+ post[:transid] = trans_id
48
+ end
49
+
50
+ def add_amount(post, money)
51
+ post[:amount] = amount(money)
52
+ end
53
+
54
+ def add_invoice(post, options)
55
+ post[:merchant_transid] = options[:order_id].to_s.slice(0,21)
56
+ post[:memnum] = options[:invoice]
57
+ post[:custnum] = options[:customer]
58
+ post[:clientdata] = options[:description]
59
+ end
60
+
61
+ def add_credit_card(post, credit_card)
62
+ post[:cardnum] = credit_card.number
63
+ post[:cardname] = credit_card.name
64
+ post[:expiry] = expdate(credit_card)
65
+ post[:cvv2] = credit_card.verification_value
66
+ end
67
+
68
+ def expdate(credit_card)
69
+ year = sprintf("%.4i", credit_card.year)
70
+ month = sprintf("%.2i", credit_card.month)
71
+
72
+ "#{month}#{year[-2..-1]}"
73
+ end
74
+
75
+ def commit(action, money, parameters)
76
+ response = parse( ssl_post(URL, post_data(action, parameters)) )
77
+
78
+ Response.new(successful?(response), message_from(response), response,
79
+ :test => test_response?(response),
80
+ :authorization => authorization_from(response)
81
+ )
82
+
83
+ end
84
+
85
+ def successful?(response)
86
+ response[:status] == SUCCESS
87
+ end
88
+
89
+ def authorization_from(response)
90
+ [ response[:authnum], response[:transid] ].compact.join(";")
91
+ end
92
+
93
+ def test_response?(response)
94
+ !!(response[:transid] =~ /SimProxy/)
95
+ end
96
+
97
+ def message_from(response)
98
+ successful?(response) ? SUCCESS_MESSAGE : response[:errorstring]
99
+ end
100
+
101
+ def parse(body)
102
+ response = {}
103
+ body.to_s.each_line do |l|
104
+ key, value = l.split(":", 2)
105
+ response[key.to_s.downcase.to_sym] = value.strip
106
+ end
107
+ response
108
+ end
109
+
110
+ def post_data(action, parameters = {})
111
+ parameters[:request_type] = TRANSACTIONS[action]
112
+ parameters[:merchant_id] = @options[:login]
113
+ parameters[:password] = @options[:password]
114
+
115
+ parameters.reject{|k,v| v.blank?}.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&")
116
+ end
117
+ end
118
+ end
119
+ end
120
+
@@ -0,0 +1,203 @@
1
+ require 'iconv'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class PayboxDirectGateway < Gateway
6
+ TEST_URL = 'https://ppps.paybox.com/PPPS.php'
7
+ TEST_URL_BACKUP = 'https://ppps1.paybox.com/PPPS.php'
8
+ LIVE_URL = 'https://ppps.paybox.com/PPPS.php'
9
+ LIVE_URL_BACKUP = 'https://ppps1.paybox.com/PPPS.php'
10
+
11
+ # Payment API Version
12
+ API_VERSION = '00104'
13
+
14
+ # Transactions hash
15
+ TRANSACTIONS = {
16
+ :authorization => '00001',
17
+ :capture => '00002',
18
+ :purchase => '00003',
19
+ :unreferenced_credit => '00004',
20
+ :void => '00005',
21
+ :refund => '00014'
22
+ }
23
+
24
+ CURRENCY_CODES = {
25
+ "AUD"=> '036',
26
+ "CAD"=> '124',
27
+ "CZK"=> '203',
28
+ "DKK"=> '208',
29
+ "HKD"=> '344',
30
+ "ICK"=> '352',
31
+ "JPY"=> '392',
32
+ "NOK"=> '578',
33
+ "SGD"=> '702',
34
+ "SEK"=> '752',
35
+ "CHF"=> '756',
36
+ "GBP"=> '826',
37
+ "USD"=> '840',
38
+ "EUR"=> '978'
39
+ }
40
+
41
+ SUCCESS_CODES = ['00000']
42
+ UNAVAILABILITY_CODES = ['00001', '00097', '00098']
43
+ FRAUD_CODES = ['00102','00104','00105','00134','00138','00141','00143','00156','00157','00159']
44
+ SUCCESS_MESSAGE = 'The transaction was approved'
45
+ FAILURE_MESSAGE = 'The transaction failed'
46
+
47
+ # Money is referenced in cents
48
+ self.money_format = :cents
49
+ self.default_currency = 'EUR'
50
+
51
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
52
+ self.supported_countries = ['FR']
53
+
54
+ # The card types supported by the payment gateway
55
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club, :jcb]
56
+
57
+ # The homepage URL of the gateway
58
+ self.homepage_url = 'http://www.paybox.com/'
59
+
60
+ # The name of the gateway
61
+ self.display_name = 'Paybox Direct'
62
+
63
+ def initialize(options = {})
64
+ requires!(options, :login, :password)
65
+ @options = options
66
+ super
67
+ end
68
+
69
+ def authorize(money, creditcard, options = {})
70
+ post = {}
71
+ add_invoice(post, options)
72
+ add_creditcard(post, creditcard)
73
+ commit('authorization', money, post)
74
+ end
75
+
76
+ def purchase(money, creditcard, options = {})
77
+ post = {}
78
+ add_invoice(post, options)
79
+ add_creditcard(post, creditcard)
80
+ commit('purchase', money, post)
81
+ end
82
+
83
+ def capture(money, authorization, options = {})
84
+ requires!(options, :order_id)
85
+ post = {}
86
+ add_invoice(post, options)
87
+ post[:numappel] = authorization[0,10]
88
+ post[:numtrans] = authorization[10,10]
89
+ commit('capture', money, post)
90
+ end
91
+
92
+ def void(identification, options = {})
93
+ requires!(options, :order_id, :amount)
94
+ post ={}
95
+ add_invoice(post, options)
96
+ add_reference(post, identification)
97
+ post[:porteur] = '000000000000000'
98
+ post[:dateval] = '0000'
99
+ commit('void', options[:amount], post)
100
+ end
101
+
102
+ def credit(money, identification, options = {})
103
+ post = {}
104
+ add_invoice(post, options)
105
+ add_reference(post, identification)
106
+ commit('refund', money, post)
107
+ end
108
+
109
+ def test?
110
+ @options[:test] || Base.gateway_mode == :test
111
+ end
112
+
113
+ private
114
+
115
+ def add_invoice(post, options)
116
+ post[:reference] = options[:order_id]
117
+ end
118
+
119
+ def add_creditcard(post, creditcard)
120
+ post[:porteur] = creditcard.number
121
+ post[:dateval] = expdate(creditcard)
122
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
123
+ end
124
+
125
+ def add_reference(post, identification)
126
+ post[:numappel] = identification[0,10]
127
+ post[:numtrans] = identification[10,10]
128
+ end
129
+
130
+ def parse(body)
131
+ body = Iconv.iconv("UTF-8","LATIN1", body.to_s).join
132
+ results = {}
133
+ body.split(/&/).each do |pair|
134
+ key,val = pair.split(/\=/)
135
+ results[key.downcase.to_sym] = CGI.unescape(val) if val
136
+ end
137
+ results
138
+ end
139
+
140
+ def commit(action, money = nil, parameters = nil)
141
+ parameters[:montant] = ('0000000000' + (money ? amount(money) : ''))[-10..-1]
142
+ parameters[:devise] = CURRENCY_CODES[options[:currency] || currency(money)]
143
+ request_data = post_data(action,parameters)
144
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, request_data))
145
+ response = parse(ssl_post(test? ? TEST_URL_BACKUP : LIVE_URL_BACKUP, request_data)) if service_unavailable?(response)
146
+ Response.new(success?(response), message_from(response), response.merge(
147
+ :timestamp => parameters[:dateq]),
148
+ :test => test?,
149
+ :authorization => response[:numappel].to_s + response[:numtrans].to_s,
150
+ :fraud_review => fraud_review?(response),
151
+ :sent_params => parameters.delete_if{|key,value| ['porteur','dateval','cvv'].include?(key.to_s)}
152
+ )
153
+ end
154
+
155
+ def success?(response)
156
+ SUCCESS_CODES.include?(response[:codereponse])
157
+ end
158
+
159
+ def fraud_review?(response)
160
+ FRAUD_CODES.include?(response[:codereponse])
161
+ end
162
+
163
+ def service_unavailable?(response)
164
+ UNAVAILABILITY_CODES.include?(response[:codereponse])
165
+ end
166
+
167
+ def message_from(response)
168
+ success?(response) ? SUCCESS_MESSAGE : (response[:commentaire] || FAILURE_MESSAGE)
169
+ end
170
+
171
+ def post_data(action, parameters = {})
172
+
173
+ parameters.update(
174
+ :version => API_VERSION,
175
+ :type => TRANSACTIONS[action.to_sym],
176
+ :dateq => Time.now.strftime('%d%m%Y%H%M%S'),
177
+ :numquestion => unique_id(parameters[:order_id]),
178
+ :site => @options[:login].to_s[0,7],
179
+ :rang => @options[:login].to_s[7..-1],
180
+ :cle => @options[:password],
181
+ :pays => '',
182
+ :archivage => parameters[:order_id]
183
+ )
184
+
185
+ parameters.collect { |key, value| "#{key.to_s.upcase}=#{CGI.escape(value.to_s)}" }.join("&")
186
+ end
187
+
188
+ def unique_id(seed = 0)
189
+ randkey = "#{seed}#{Time.now.usec}".to_i % 2147483647 # Max paybox value for the question number
190
+
191
+ "0000000000#{randkey}"[-10..-1]
192
+ end
193
+
194
+ def expdate(credit_card)
195
+ year = sprintf("%.4i", credit_card.year)
196
+ month = sprintf("%.2i", credit_card.month)
197
+
198
+ "#{month}#{year[-2..-1]}"
199
+ end
200
+
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,236 @@
1
+ require File.dirname(__FILE__) + '/payflow/payflow_common_api'
2
+ require File.dirname(__FILE__) + '/payflow/payflow_response'
3
+ require File.dirname(__FILE__) + '/payflow_express'
4
+
5
+ module ActiveMerchant #:nodoc:
6
+ module Billing #:nodoc:
7
+ class PayflowGateway < Gateway
8
+ include PayflowCommonAPI
9
+
10
+ RECURRING_ACTIONS = Set.new([:add, :modify, :cancel, :inquiry, :reactivate, :payment])
11
+
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :discover, :diners_club]
13
+ self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside'
14
+ self.display_name = 'PayPal Payflow Pro'
15
+
16
+ def authorize(money, credit_card_or_reference, options = {})
17
+ request = build_sale_or_authorization_request(:authorization, money, credit_card_or_reference, options)
18
+
19
+ commit(request)
20
+ end
21
+
22
+ def purchase(money, credit_card_or_reference, options = {})
23
+ request = build_sale_or_authorization_request(:purchase, money, credit_card_or_reference, options)
24
+
25
+ commit(request)
26
+ end
27
+
28
+ def credit(money, identification_or_credit_card, options = {})
29
+ if identification_or_credit_card.is_a?(String)
30
+ # Perform referenced credit
31
+ request = build_reference_request(:credit, money, identification_or_credit_card, options)
32
+ else
33
+ # Perform non-referenced credit
34
+ request = build_credit_card_request(:credit, money, identification_or_credit_card, options)
35
+ end
36
+
37
+ commit(request)
38
+ end
39
+
40
+ # Adds or modifies a recurring Payflow profile. See the Payflow Pro Recurring Billing Guide for more details:
41
+ # https://www.paypal.com/en_US/pdf/PayflowPro_RecurringBilling_Guide.pdf
42
+ #
43
+ # Several options are available to customize the recurring profile:
44
+ #
45
+ # * <tt>profile_id</tt> - is only required for editing a recurring profile
46
+ # * <tt>starting_at</tt> - takes a Date, Time, or string in mmddyyyy format. The date must be in the future.
47
+ # * <tt>name</tt> - The name of the customer to be billed. If not specified, the name from the credit card is used.
48
+ # * <tt>periodicity</tt> - The frequency that the recurring payments will occur at. Can be one of
49
+ # :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly
50
+ # * <tt>payments</tt> - The term, or number of payments that will be made
51
+ # * <tt>comment</tt> - A comment associated with the profile
52
+ def recurring(money, credit_card, options = {})
53
+ options[:name] = credit_card.name if options[:name].blank? && credit_card
54
+ request = build_recurring_request(options[:profile_id] ? :modify : :add, money, options) do |xml|
55
+ add_credit_card(xml, credit_card) if credit_card
56
+ end
57
+ commit(request, :recurring)
58
+ end
59
+
60
+ def cancel_recurring(profile_id)
61
+ request = build_recurring_request(:cancel, 0, :profile_id => profile_id)
62
+ commit(request, :recurring)
63
+ end
64
+
65
+ def recurring_inquiry(profile_id, options = {})
66
+ request = build_recurring_request(:inquiry, nil, options.update( :profile_id => profile_id ))
67
+ commit(request, :recurring)
68
+ end
69
+
70
+ def express
71
+ @express ||= PayflowExpressGateway.new(@options)
72
+ end
73
+
74
+ private
75
+ def build_sale_or_authorization_request(action, money, credit_card_or_reference, options)
76
+ if credit_card_or_reference.is_a?(String)
77
+ build_reference_sale_or_authorization_request(action, money, credit_card_or_reference, options)
78
+ else
79
+ build_credit_card_request(action, money, credit_card_or_reference, options)
80
+ end
81
+ end
82
+
83
+ def build_reference_sale_or_authorization_request(action, money, reference, options)
84
+ xml = Builder::XmlMarkup.new
85
+ xml.tag! TRANSACTIONS[action] do
86
+ xml.tag! 'PayData' do
87
+ xml.tag! 'Invoice' do
88
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
89
+ end
90
+ xml.tag! 'Tender' do
91
+ xml.tag! 'Card' do
92
+ xml.tag! 'ExtData', 'Name' => 'ORIGID', 'Value' => reference
93
+ end
94
+ end
95
+ end
96
+ end
97
+ xml.target!
98
+ end
99
+
100
+ def build_credit_card_request(action, money, credit_card, options)
101
+ xml = Builder::XmlMarkup.new
102
+ xml.tag! TRANSACTIONS[action] do
103
+ xml.tag! 'PayData' do
104
+ xml.tag! 'Invoice' do
105
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
106
+ xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
107
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
108
+
109
+ billing_address = options[:billing_address] || options[:address]
110
+ add_address(xml, 'BillTo', billing_address, options) if billing_address
111
+ add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
112
+
113
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
114
+ end
115
+
116
+ xml.tag! 'Tender' do
117
+ add_credit_card(xml, credit_card)
118
+ end
119
+ end
120
+ end
121
+ xml.target!
122
+ end
123
+
124
+ def add_credit_card(xml, credit_card)
125
+ xml.tag! 'Card' do
126
+ xml.tag! 'CardType', credit_card_type(credit_card)
127
+ xml.tag! 'CardNum', credit_card.number
128
+ xml.tag! 'ExpDate', expdate(credit_card)
129
+ xml.tag! 'NameOnCard', credit_card.first_name
130
+ xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value?
131
+
132
+ if requires_start_date_or_issue_number?(credit_card)
133
+ xml.tag!('ExtData', 'Name' => 'CardStart', 'Value' => startdate(credit_card)) unless credit_card.start_month.blank? || credit_card.start_year.blank?
134
+ xml.tag!('ExtData', 'Name' => 'CardIssue', 'Value' => format(credit_card.issue_number, :two_digits)) unless credit_card.issue_number.blank?
135
+ end
136
+ xml.tag! 'ExtData', 'Name' => 'LASTNAME', 'Value' => credit_card.last_name
137
+ end
138
+ end
139
+
140
+ def credit_card_type(credit_card)
141
+ return '' if card_brand(credit_card).blank?
142
+
143
+ CARD_MAPPING[card_brand(credit_card).to_sym]
144
+ end
145
+
146
+ def expdate(creditcard)
147
+ year = sprintf("%.4i", creditcard.year)
148
+ month = sprintf("%.2i", creditcard.month)
149
+
150
+ "#{year}#{month}"
151
+ end
152
+
153
+ def startdate(creditcard)
154
+ year = format(creditcard.start_year, :two_digits)
155
+ month = format(creditcard.start_month, :two_digits)
156
+
157
+ "#{month}#{year}"
158
+ end
159
+
160
+ def build_recurring_request(action, money, options)
161
+ unless RECURRING_ACTIONS.include?(action)
162
+ raise StandardError, "Invalid Recurring Profile Action: #{action}"
163
+ end
164
+
165
+ xml = Builder::XmlMarkup.new
166
+ xml.tag! 'RecurringProfiles' do
167
+ xml.tag! 'RecurringProfile' do
168
+ xml.tag! action.to_s.capitalize do
169
+ unless [:cancel, :inquiry].include?(action)
170
+ xml.tag! 'RPData' do
171
+ xml.tag! 'Name', options[:name] unless options[:name].nil?
172
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
173
+ xml.tag! 'PayPeriod', get_pay_period(options)
174
+ xml.tag! 'Term', options[:payments] unless options[:payments].nil?
175
+ xml.tag! 'Comment', options[:comment] unless options[:comment].nil?
176
+
177
+
178
+ if initial_tx = options[:initial_transaction]
179
+ requires!(initial_tx, [:type, :authorization, :purchase])
180
+ requires!(initial_tx, :amount) if initial_tx[:type] == :purchase
181
+
182
+ xml.tag! 'OptionalTrans', TRANSACTIONS[initial_tx[:type]]
183
+ xml.tag! 'OptionalTransAmt', amount(initial_tx[:amount]) unless initial_tx[:amount].blank?
184
+ end
185
+
186
+ xml.tag! 'Start', format_rp_date(options[:starting_at] || Date.today + 1 )
187
+ xml.tag! 'EMail', options[:email] unless options[:email].nil?
188
+
189
+ billing_address = options[:billing_address] || options[:address]
190
+ add_address(xml, 'BillTo', billing_address, options) if billing_address
191
+ add_address(xml, 'ShipTo', options[:shipping_address], options) if options[:shipping_address]
192
+ end
193
+ xml.tag! 'Tender' do
194
+ yield xml
195
+ end
196
+ end
197
+ if action != :add
198
+ xml.tag! "ProfileID", options[:profile_id]
199
+ end
200
+ if action == :inquiry
201
+ xml.tag! "PaymentHistory", ( options[:history] ? 'Y' : 'N' )
202
+ end
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ def get_pay_period(options)
209
+ requires!(options, [:periodicity, :bimonthly, :monthly, :biweekly, :weekly, :yearly, :daily, :semimonthly, :quadweekly, :quarterly, :semiyearly])
210
+ case options[:periodicity]
211
+ when :weekly then 'Weekly'
212
+ when :biweekly then 'Bi-weekly'
213
+ when :semimonthly then 'Semi-monthly'
214
+ when :quadweekly then 'Every four weeks'
215
+ when :monthly then 'Monthly'
216
+ when :quarterly then 'Quarterly'
217
+ when :semiyearly then 'Semi-yearly'
218
+ when :yearly then 'Yearly'
219
+ end
220
+ end
221
+
222
+ def format_rp_date(time)
223
+ case time
224
+ when Time, Date then time.strftime("%m%d%Y")
225
+ else
226
+ time.to_s
227
+ end
228
+ end
229
+
230
+ def build_response(success, message, response, options = {})
231
+ PayflowResponse.new(success, message, response, options)
232
+ end
233
+ end
234
+ end
235
+ end
236
+