activemerchant 1.29.1 → 1.34.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.
- data/CHANGELOG +143 -0
- data/CONTRIBUTORS +43 -0
- data/README.md +59 -51
- data/lib/active_merchant/billing/check.rb +15 -14
- data/lib/active_merchant/billing/credit_card.rb +14 -5
- data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
- data/lib/active_merchant/billing/gateway.rb +2 -2
- data/lib/active_merchant/billing/gateways/authorize_net.rb +36 -8
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +17 -5
- data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
- data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -2
- data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
- data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -187
- data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +7 -3
- data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +156 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
- data/lib/active_merchant/billing/gateways/data_cash.rb +3 -3
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +114 -171
- data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
- data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +314 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +0 -4
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
- data/lib/active_merchant/billing/gateways/iridium.rb +8 -2
- data/lib/active_merchant/billing/gateways/litle.rb +354 -105
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +28 -7
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +4 -6
- data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
- data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
- data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
- data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
- data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +7 -5
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +43 -18
- data/lib/active_merchant/billing/gateways/orbital.rb +190 -53
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
- data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
- data/lib/active_merchant/billing/gateways/paymill.rb +179 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +12 -7
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +14 -9
- data/lib/active_merchant/billing/gateways/paypal_express.rb +59 -18
- data/lib/active_merchant/billing/gateways/pin.rb +165 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
- data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
- data/lib/active_merchant/billing/gateways/sage.rb +10 -5
- data/lib/active_merchant/billing/gateways/sage_pay.rb +7 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +233 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +49 -21
- data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -4
- data/lib/active_merchant/billing/gateways/webpay.rb +8 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
- data/lib/active_merchant/billing/gateways/worldpay.rb +60 -24
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
- data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
- data/lib/active_merchant/billing/integrations/dwolla/common.rb +23 -0
- data/lib/active_merchant/billing/integrations/dwolla/helper.rb +18 -6
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +16 -7
- data/lib/active_merchant/billing/integrations/dwolla/return.rb +16 -5
- data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
- data/lib/active_merchant/billing/integrations/notification.rb +13 -8
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +19 -3
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
- data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
- data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
- data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
- data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
- data/lib/active_merchant/billing/integrations/pxpay/helper.rb +1 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +78 -15
- data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
- data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
- data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
- data/lib/active_merchant/billing/integrations/robokassa/common.rb +1 -1
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +7 -3
- data/lib/active_merchant/billing/integrations/world_pay.rb +15 -8
- data/lib/active_merchant/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +124 -50
- metadata.gz.sig +0 -0
|
@@ -3,21 +3,47 @@ require 'digest/md5'
|
|
|
3
3
|
module ActiveMerchant #:nodoc:
|
|
4
4
|
module Billing #:nodoc:
|
|
5
5
|
class BluePayGateway < Gateway
|
|
6
|
-
class_attribute :
|
|
6
|
+
class_attribute :rebilling_url, :ignore_http_status
|
|
7
7
|
|
|
8
8
|
self.live_url = 'https://secure.bluepay.com/interfaces/bp20post'
|
|
9
9
|
self.rebilling_url = 'https://secure.bluepay.com/interfaces/bp20rebadmin'
|
|
10
10
|
|
|
11
11
|
self.ignore_http_status = true
|
|
12
12
|
|
|
13
|
-
RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3
|
|
14
|
-
AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38
|
|
15
|
-
|
|
16
13
|
CARD_CODE_ERRORS = %w( N S )
|
|
17
14
|
AVS_ERRORS = %w( A E N R W Z )
|
|
18
15
|
AVS_REASON_CODES = %w(27 45)
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
FRAUD_REVIEW_STATUSES = %w( E 0 )
|
|
18
|
+
|
|
19
|
+
FIELD_MAP = {
|
|
20
|
+
'TRANS_ID' => :transaction_id,
|
|
21
|
+
'STATUS' => :response_code,
|
|
22
|
+
'AVS' => :avs_result_code,
|
|
23
|
+
'CVV2'=> :card_code,
|
|
24
|
+
'AUTH_CODE' => :authorization,
|
|
25
|
+
'MESSAGE' => :message,
|
|
26
|
+
'REBID' => :rebid,
|
|
27
|
+
'TRANS_TYPE' => :trans_type,
|
|
28
|
+
'PAYMENT_ACCOUNT_MASK' => :acct_mask,
|
|
29
|
+
'CARD_TYPE' => :card_type,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
REBILL_FIELD_MAP = {
|
|
33
|
+
'REBILL_ID' => :rebill_id,
|
|
34
|
+
'ACCOUNT_ID'=> :account_id,
|
|
35
|
+
'USER_ID' => :user_id,
|
|
36
|
+
'TEMPLATE_ID' => :template_id,
|
|
37
|
+
'STATUS' => :status,
|
|
38
|
+
'CREATION_DATE' => :creation_date,
|
|
39
|
+
'NEXT_DATE' => :next_date,
|
|
40
|
+
'LAST_DATE' => :last_date,
|
|
41
|
+
'SCHED_EXPR' => :schedule,
|
|
42
|
+
'CYCLES_REMAIN' => :cycles_remain,
|
|
43
|
+
'REB_AMOUNT' => :rebill_amount,
|
|
44
|
+
'NEXT_AMOUNT' => :next_amount,
|
|
45
|
+
'USUAL_DATE' => :undoc_usual_date, # Not found in the bp20rebadmin API doc.
|
|
46
|
+
}
|
|
21
47
|
|
|
22
48
|
self.supported_countries = ['US']
|
|
23
49
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
|
@@ -25,7 +51,6 @@ module ActiveMerchant #:nodoc:
|
|
|
25
51
|
self.display_name = 'BluePay'
|
|
26
52
|
self.money_format = :dollars
|
|
27
53
|
|
|
28
|
-
|
|
29
54
|
# Creates a new BluepayGateway
|
|
30
55
|
#
|
|
31
56
|
# The gateway requires that a valid Account ID and Secret Key be passed
|
|
@@ -54,24 +79,12 @@ module ActiveMerchant #:nodoc:
|
|
|
54
79
|
# * <tt>options</tt> -- A hash of optional parameters.
|
|
55
80
|
def authorize(money, payment_object, options = {})
|
|
56
81
|
post = {}
|
|
57
|
-
post
|
|
58
|
-
if payment_object != nil && payment_object.class() != String
|
|
59
|
-
payment_object.class() == ActiveMerchant::Billing::Check ?
|
|
60
|
-
add_check(post, payment_object) :
|
|
61
|
-
add_creditcard(post, payment_object)
|
|
62
|
-
else
|
|
63
|
-
post[:MASTER_ID] = payment_object
|
|
64
|
-
end
|
|
82
|
+
add_payment_method(post, payment_object)
|
|
65
83
|
add_invoice(post, options)
|
|
66
84
|
add_address(post, options)
|
|
67
85
|
add_customer_data(post, options)
|
|
68
|
-
if options[:rebill]
|
|
69
|
-
|
|
70
|
-
post[:REB_AMOUNT] = amount(options[:rebill_amount])
|
|
71
|
-
post[:REB_FIRST_DATE] = options[:rebill_start_date]
|
|
72
|
-
post[:REB_EXPR] = options[:rebill_expression]
|
|
73
|
-
post[:REB_CYCLES] = options[:rebill_cycles]
|
|
74
|
-
end
|
|
86
|
+
add_rebill(post, options) if options[:rebill]
|
|
87
|
+
add_duplicate_override(post, options)
|
|
75
88
|
post[:TRANS_TYPE] = 'AUTH'
|
|
76
89
|
commit('AUTH_ONLY', money, post)
|
|
77
90
|
end
|
|
@@ -89,24 +102,12 @@ module ActiveMerchant #:nodoc:
|
|
|
89
102
|
# * <tt>options</tt> -- A hash of optional parameters.,
|
|
90
103
|
def purchase(money, payment_object, options = {})
|
|
91
104
|
post = {}
|
|
92
|
-
post
|
|
93
|
-
if payment_object != nil && payment_object.class() != String
|
|
94
|
-
payment_object.class() == ActiveMerchant::Billing::Check ?
|
|
95
|
-
add_check(post, payment_object) :
|
|
96
|
-
add_creditcard(post, payment_object)
|
|
97
|
-
else
|
|
98
|
-
post[:MASTER_ID] = payment_object
|
|
99
|
-
end
|
|
105
|
+
add_payment_method(post, payment_object)
|
|
100
106
|
add_invoice(post, options)
|
|
101
107
|
add_address(post, options)
|
|
102
108
|
add_customer_data(post, options)
|
|
103
|
-
if options[:rebill]
|
|
104
|
-
|
|
105
|
-
post[:REB_AMOUNT] = amount(options[:rebill_amount])
|
|
106
|
-
post[:REB_FIRST_DATE] = options[:rebill_start_date]
|
|
107
|
-
post[:REB_EXPR] = options[:rebill_expression]
|
|
108
|
-
post[:REB_CYCLES] = options[:rebill_cycles]
|
|
109
|
-
end
|
|
109
|
+
add_rebill(post, options) if options[:rebill]
|
|
110
|
+
add_duplicate_override(post, options)
|
|
110
111
|
post[:TRANS_TYPE] = 'SALE'
|
|
111
112
|
commit('AUTH_CAPTURE', money, post)
|
|
112
113
|
end
|
|
@@ -154,20 +155,17 @@ module ActiveMerchant #:nodoc:
|
|
|
154
155
|
# If the payment_object is a token, then the transaction type will reverse a previous capture or purchase transaction, returning the funds to the customer. If the amount is nil, a full credit will be processed. This is referred to a REFUND transaction in BluePay.
|
|
155
156
|
# If the payment_object is either a CreditCard or Check object, then the transaction type will be an unmatched credit placing funds in the specified account. This is referred to a CREDIT transaction in BluePay.
|
|
156
157
|
# * <tt>options</tt> -- A hash of parameters.
|
|
157
|
-
def refund(money,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
payment_object.class() == ActiveMerchant::Billing::Check ?
|
|
162
|
-
add_check(post, payment_object) :
|
|
163
|
-
add_creditcard(post, payment_object)
|
|
164
|
-
post[:TRANS_TYPE] = 'CREDIT'
|
|
165
|
-
else
|
|
166
|
-
post[:MASTER_ID] = payment_object
|
|
167
|
-
post[:TRANS_TYPE] = 'REFUND'
|
|
158
|
+
def refund(money, identification, options = {})
|
|
159
|
+
if(identification && !identification.kind_of?(String))
|
|
160
|
+
deprecated "refund should only be used to refund a referenced transaction"
|
|
161
|
+
return credit(money, identification, options)
|
|
168
162
|
end
|
|
169
163
|
|
|
170
|
-
|
|
164
|
+
post = {}
|
|
165
|
+
post[:PAYMENT_ACCOUNT] = ''
|
|
166
|
+
post[:MASTER_ID] = identification
|
|
167
|
+
post[:TRANS_TYPE] = 'REFUND'
|
|
168
|
+
post[:NAME1] = (options[:first_name] ? options[:first_name] : "")
|
|
171
169
|
post[:NAME2] = options[:last_name] if options[:last_name]
|
|
172
170
|
post[:ZIP] = options[:zip] if options[:zip]
|
|
173
171
|
add_invoice(post, options)
|
|
@@ -176,9 +174,24 @@ module ActiveMerchant #:nodoc:
|
|
|
176
174
|
commit('CREDIT', money, post)
|
|
177
175
|
end
|
|
178
176
|
|
|
179
|
-
def credit(money,
|
|
180
|
-
|
|
181
|
-
|
|
177
|
+
def credit(money, payment_object, options = {})
|
|
178
|
+
if(payment_object && payment_object.kind_of?(String))
|
|
179
|
+
deprecated "credit should only be used to credit a payment method"
|
|
180
|
+
return refund(money, payment_object, options)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
post = {}
|
|
184
|
+
post[:PAYMENT_ACCOUNT] = ''
|
|
185
|
+
add_payment_method(post, payment_object)
|
|
186
|
+
post[:TRANS_TYPE] = 'CREDIT'
|
|
187
|
+
|
|
188
|
+
post[:NAME1] = (options[:first_name] ? options[:first_name] : "")
|
|
189
|
+
post[:NAME2] = options[:last_name] if options[:last_name]
|
|
190
|
+
post[:ZIP] = options[:zip] if options[:zip]
|
|
191
|
+
add_invoice(post, options)
|
|
192
|
+
add_address(post, options)
|
|
193
|
+
add_customer_data(post, options)
|
|
194
|
+
commit('CREDIT', money, post)
|
|
182
195
|
end
|
|
183
196
|
|
|
184
197
|
# Create a new recurring payment.
|
|
@@ -214,9 +227,12 @@ module ActiveMerchant #:nodoc:
|
|
|
214
227
|
# A money object of 1995 cents would be passed into the 'money' parameter.
|
|
215
228
|
def recurring(money, payment_object, options = {})
|
|
216
229
|
requires!(options, :rebill_start_date, :rebill_expression)
|
|
217
|
-
options[:rebill] =
|
|
218
|
-
|
|
219
|
-
|
|
230
|
+
options[:rebill] = true
|
|
231
|
+
if money
|
|
232
|
+
purchase(money, payment_object, options)
|
|
233
|
+
else
|
|
234
|
+
authorize(money, payment_object, options)
|
|
235
|
+
end
|
|
220
236
|
end
|
|
221
237
|
|
|
222
238
|
# View a recurring payment
|
|
@@ -252,11 +268,11 @@ module ActiveMerchant #:nodoc:
|
|
|
252
268
|
requires!(options, :rebill_id)
|
|
253
269
|
post[:REBILL_ID] = options[:rebill_id]
|
|
254
270
|
post[:TRANS_TYPE] = 'SET'
|
|
255
|
-
post[:REB_AMOUNT] = amount(options[:rebill_amount]) if
|
|
256
|
-
post[:NEXT_DATE] = options[:rebill_next_date]
|
|
257
|
-
post[:REB_EXPR] = options[:rebill_expression]
|
|
258
|
-
post[:REB_CYCLES] = options[:rebill_cycles]
|
|
259
|
-
post[:NEXT_AMOUNT] = options[:rebill_next_amount]
|
|
271
|
+
post[:REB_AMOUNT] = amount(options[:rebill_amount]) if options[:rebill_amount]
|
|
272
|
+
post[:NEXT_DATE] = options[:rebill_next_date]
|
|
273
|
+
post[:REB_EXPR] = options[:rebill_expression]
|
|
274
|
+
post[:REB_CYCLES] = options[:rebill_cycles]
|
|
275
|
+
post[:NEXT_AMOUNT] = options[:rebill_next_amount]
|
|
260
276
|
commit('rebill', 'nil', post)
|
|
261
277
|
end
|
|
262
278
|
|
|
@@ -279,145 +295,155 @@ module ActiveMerchant #:nodoc:
|
|
|
279
295
|
private
|
|
280
296
|
|
|
281
297
|
def commit(action, money, fields)
|
|
282
|
-
fields[:AMOUNT] = amount(money) unless
|
|
283
|
-
|
|
284
|
-
action == 'rebill' ? begin url = rebilling_url; fields[:TAMPER_PROOF_SEAL] = calc_rebill_tps(fields) end : begin url = live_url; fields[:TAMPER_PROOF_SEAL] = calc_tps(amount(money), fields) end
|
|
298
|
+
fields[:AMOUNT] = amount(money) unless(fields[:TRANS_TYPE] == 'VOID' || action == 'rebill')
|
|
299
|
+
fields[:MODE] = (test? ? 'TEST' : 'LIVE')
|
|
285
300
|
fields[:ACCOUNT_ID] = @options[:login]
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if (response.has_key?('TRANS_ID'))
|
|
291
|
-
response_id = response['TRANS_ID'].to_s()
|
|
292
|
-
elsif (response.has_key?('rebill_id'))
|
|
293
|
-
response_id = response['rebill_id'][0]
|
|
301
|
+
|
|
302
|
+
if action == 'rebill'
|
|
303
|
+
url = rebilling_url
|
|
304
|
+
fields[:TAMPER_PROOF_SEAL] = calc_rebill_tps(fields)
|
|
294
305
|
else
|
|
295
|
-
|
|
306
|
+
url = live_url
|
|
307
|
+
fields[:TAMPER_PROOF_SEAL] = calc_tps(amount(money), fields)
|
|
296
308
|
end
|
|
297
|
-
|
|
298
|
-
cvv2 = (!response[CARD_CODE_RESPONSE_CODE].empty? ? response[CARD_CODE_RESPONSE_CODE] : '')
|
|
299
|
-
Response.new(success?(response), message, response,
|
|
300
|
-
:test => test_mode,
|
|
301
|
-
:authorization => response_id,
|
|
302
|
-
:fraud_review => fraud_review?(response),
|
|
303
|
-
:avs_result => { :code => avs },
|
|
304
|
-
:cvv_result => cvv2
|
|
305
|
-
)
|
|
309
|
+
parse(ssl_post(url, post_data(action, fields)))
|
|
306
310
|
end
|
|
307
311
|
|
|
308
|
-
def
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
312
|
+
def parse_recurring(response_fields, opts={}) # expected status?
|
|
313
|
+
parsed = {}
|
|
314
|
+
response_fields.each do |k,v|
|
|
315
|
+
mapped_key = REBILL_FIELD_MAP.include?(k) ? REBILL_FIELD_MAP[k] : k
|
|
316
|
+
parsed[mapped_key] = v
|
|
313
317
|
end
|
|
314
|
-
end
|
|
315
318
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
end
|
|
319
|
+
success = parsed[:status] != 'error'
|
|
320
|
+
message = parsed[:status]
|
|
319
321
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
+
Response.new(success, message, parsed,
|
|
323
|
+
:test => test?,
|
|
324
|
+
:authorization => parsed[:rebill_id])
|
|
322
325
|
end
|
|
323
326
|
|
|
324
327
|
def parse(body)
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
fields['MESSAGE'][0] =~ /Expired/ ? message = "The credit card has expired" : message = fields['MESSAGE'] if message == fields['MESSAGE']
|
|
331
|
-
fields.delete('MESSAGE')
|
|
332
|
-
end
|
|
333
|
-
fields.has_key?('STATUS') ? begin status = fields['STATUS']; fields.delete('STATUS') end : status = ''
|
|
334
|
-
fields.has_key?('AVS') ? begin avs = fields['AVS']; fields.delete('AVS') end : avs = ''
|
|
335
|
-
fields.has_key?('CVV2') ? begin cvv2 = fields['CVV2']; fields.delete('CVV2') end : cvv2 = ''
|
|
336
|
-
fields.has_key?('MASTER_ID') ? begin trans_id = fields['MASTER_ID']; fields.delete('MASTER_ID') end : trans_id = ''
|
|
337
|
-
fields[:avs_result_code] = avs
|
|
338
|
-
fields[:card_code] = cvv2
|
|
339
|
-
fields[:response_code] = status
|
|
340
|
-
fields[:response_reason_code] = ''
|
|
341
|
-
fields[:response_reason_text] = message
|
|
342
|
-
fields[:transaction_id] = trans_id
|
|
343
|
-
return fields
|
|
328
|
+
# The bp20api has max one value per form field.
|
|
329
|
+
response_fields = Hash[CGI::parse(body).map{|k,v| [k.upcase,v.first]}]
|
|
330
|
+
|
|
331
|
+
if response_fields.include? "REBILL_ID"
|
|
332
|
+
return parse_recurring(response_fields)
|
|
344
333
|
end
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
334
|
+
|
|
335
|
+
parsed = {}
|
|
336
|
+
response_fields.each do |k,v|
|
|
337
|
+
mapped_key = FIELD_MAP.include?(k) ? FIELD_MAP[k] : k
|
|
338
|
+
parsed[mapped_key] = v
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# normalize message
|
|
342
|
+
message = message_from(parsed)
|
|
343
|
+
success = parsed[:response_code] == '1'
|
|
344
|
+
Response.new(success, message, parsed,
|
|
345
|
+
:test => test?,
|
|
346
|
+
:authorization => (parsed[:rebid] && parsed[:rebid] != '' ? parsed[:rebid] : parsed[:transaction_id]),
|
|
347
|
+
:fraud_review => FRAUD_REVIEW_STATUSES.include?(parsed[:response_code]),
|
|
348
|
+
:avs_result => { :code => parsed[:avs_result_code] },
|
|
349
|
+
:cvv_result => parsed[:card_code]
|
|
350
|
+
)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def message_from(parsed)
|
|
354
|
+
message = parsed[:message]
|
|
355
|
+
if(parsed[:response_code].to_i == 2)
|
|
356
|
+
if CARD_CODE_ERRORS.include?(parsed[:card_code])
|
|
357
|
+
message = CVVResult.messages[parsed[:card_code]]
|
|
358
|
+
elsif AVS_ERRORS.include?(parsed[:avs_result_code])
|
|
359
|
+
message = AVSResult.messages[ parsed[:avs_result_code] ]
|
|
360
|
+
else
|
|
361
|
+
message = message.chomp('.')
|
|
362
|
+
end
|
|
363
|
+
elsif message == "Missing ACCOUNT_ID"
|
|
364
|
+
message = "The merchant login ID or password is invalid"
|
|
365
|
+
elsif message =~ /Approved/
|
|
366
|
+
message = "This transaction has been approved"
|
|
367
|
+
elsif message =~ /Expired/
|
|
368
|
+
message = "The credit card has expired"
|
|
350
369
|
end
|
|
351
|
-
|
|
370
|
+
message
|
|
352
371
|
end
|
|
353
372
|
|
|
354
373
|
def add_invoice(post, options)
|
|
355
|
-
post[:ORDER_ID] = options[:order_id]
|
|
356
|
-
post[:INVOICE_ID] = options[:invoice]
|
|
357
|
-
post[:invoice_num] = options[:order_id]
|
|
358
|
-
post[:MEMO] = options[:description]
|
|
359
|
-
post[:description] = options[:description]
|
|
374
|
+
post[:ORDER_ID] = options[:order_id]
|
|
375
|
+
post[:INVOICE_ID] = options[:invoice]
|
|
376
|
+
post[:invoice_num] = options[:order_id]
|
|
377
|
+
post[:MEMO] = options[:description]
|
|
378
|
+
post[:description] = options[:description]
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def add_payment_method(post, payment_object)
|
|
382
|
+
post[:MASTER_ID] = ''
|
|
383
|
+
case payment_object
|
|
384
|
+
when String
|
|
385
|
+
post[:MASTER_ID] = payment_object
|
|
386
|
+
when Check
|
|
387
|
+
add_check(post, payment_object)
|
|
388
|
+
else
|
|
389
|
+
add_creditcard(post, payment_object)
|
|
390
|
+
end
|
|
360
391
|
end
|
|
361
392
|
|
|
362
393
|
def add_creditcard(post, creditcard)
|
|
363
394
|
post[:PAYMENT_TYPE] = 'CREDIT'
|
|
364
395
|
post[:PAYMENT_ACCOUNT] = creditcard.number
|
|
365
|
-
post[:CARD_CVV2] = creditcard.verification_value
|
|
366
|
-
creditcard.verification_value?
|
|
396
|
+
post[:CARD_CVV2] = creditcard.verification_value
|
|
367
397
|
post[:CARD_EXPIRE] = expdate(creditcard)
|
|
368
398
|
post[:NAME1] = creditcard.first_name
|
|
369
399
|
post[:NAME2] = creditcard.last_name
|
|
370
400
|
end
|
|
371
401
|
|
|
402
|
+
CHECK_ACCOUNT_TYPES = {
|
|
403
|
+
"checking" => "C",
|
|
404
|
+
"savings" => "S"
|
|
405
|
+
}
|
|
406
|
+
|
|
372
407
|
def add_check(post, check)
|
|
373
408
|
post[:PAYMENT_TYPE] = 'ACH'
|
|
374
|
-
post[:PAYMENT_ACCOUNT] = check.account_type
|
|
409
|
+
post[:PAYMENT_ACCOUNT] = [CHECK_ACCOUNT_TYPES[check.account_type], check.routing_number, check.account_number].join(":")
|
|
375
410
|
post[:NAME1] = check.first_name
|
|
376
411
|
post[:NAME2] = check.last_name
|
|
377
412
|
end
|
|
378
413
|
|
|
379
414
|
def add_customer_data(post, options)
|
|
380
|
-
post[:EMAIL] = options[:email]
|
|
381
|
-
post[:CUSTOM_ID] = options[:customer]
|
|
415
|
+
post[:EMAIL] = options[:email]
|
|
416
|
+
post[:CUSTOM_ID] = options[:customer]
|
|
382
417
|
end
|
|
383
418
|
|
|
384
|
-
def
|
|
385
|
-
|
|
386
|
-
post[:duplicate_window] = duplicate_window
|
|
387
|
-
post[:DUPLICATE_OVERRIDE] = duplicate_window
|
|
388
|
-
end
|
|
419
|
+
def add_duplicate_override(post, options)
|
|
420
|
+
post[:DUPLICATE_OVERRIDE] = options[:duplicate_override]
|
|
389
421
|
end
|
|
390
422
|
|
|
391
423
|
def add_address(post, options)
|
|
392
|
-
if address = options[:billing_address] || options[:address]
|
|
393
|
-
post[:NAME1] = address[:first_name]
|
|
394
|
-
post[:NAME2] = address[:last_name]
|
|
424
|
+
if address = (options[:shipping_address] || options[:billing_address] || options[:address])
|
|
395
425
|
post[:ADDR1] = address[:address1]
|
|
396
426
|
post[:ADDR2] = address[:address2]
|
|
397
427
|
post[:COMPANY_NAME] = address[:company]
|
|
398
428
|
post[:PHONE] = address[:phone]
|
|
399
429
|
post[:CITY] = address[:city]
|
|
400
|
-
post[:STATE] = address[:state].blank?
|
|
401
|
-
post[:ZIP] = address[:zip]
|
|
402
|
-
post[:COUNTRY] = address[:country]
|
|
403
|
-
end
|
|
404
|
-
if address = options[:shipping_address]
|
|
405
|
-
post[:NAME1] = address[:first_name]
|
|
406
|
-
post[:NAME2] = address[:last_name]
|
|
407
|
-
post[:ADDR1] = address[:address1]
|
|
408
|
-
post[:ADDR1] = address[:address1]
|
|
409
|
-
post[:COMPANY_NAME] = address[:company]
|
|
410
|
-
post[:PHONE] = address[:phone]
|
|
430
|
+
post[:STATE] = (address[:state].blank? ? 'n/a' : address[:state])
|
|
411
431
|
post[:ZIP] = address[:zip]
|
|
412
|
-
post[:CITY] = address[:city]
|
|
413
432
|
post[:COUNTRY] = address[:country]
|
|
414
|
-
post[:STATE] = address[:state].blank? ? 'n/a' : address[:state]
|
|
415
433
|
end
|
|
416
434
|
end
|
|
417
435
|
|
|
436
|
+
def add_rebill(post, options)
|
|
437
|
+
post[:DO_REBILL] = '1'
|
|
438
|
+
post[:REB_AMOUNT] = amount(options[:rebill_amount])
|
|
439
|
+
post[:REB_FIRST_DATE] = options[:rebill_start_date]
|
|
440
|
+
post[:REB_EXPR] = options[:rebill_expression]
|
|
441
|
+
post[:REB_CYCLES] = options[:rebill_cycles]
|
|
442
|
+
end
|
|
443
|
+
|
|
418
444
|
def post_data(action, parameters = {})
|
|
419
445
|
post = {}
|
|
420
|
-
post[:version] = '
|
|
446
|
+
post[:version] = '1'
|
|
421
447
|
post[:login] = ''
|
|
422
448
|
post[:tran_key] = ''
|
|
423
449
|
post[:relay_response] = "FALSE"
|
|
@@ -427,60 +453,48 @@ module ActiveMerchant #:nodoc:
|
|
|
427
453
|
post[:encap_char] = "$"
|
|
428
454
|
post[:card_num] = '4111111111111111'
|
|
429
455
|
post[:exp_date] = '1212'
|
|
430
|
-
post[:solution_ID] = application_id if
|
|
431
|
-
|
|
432
|
-
request
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
def message_from(results)
|
|
436
|
-
if results[:response_code] == 2
|
|
437
|
-
return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
|
|
438
|
-
if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
|
|
439
|
-
return AVSResult.messages[ results[:avs_result_code] ]
|
|
440
|
-
end
|
|
441
|
-
return (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '')
|
|
442
|
-
end
|
|
443
|
-
if results.has_key?(:response_reason_text)
|
|
444
|
-
return results[:response_reason_text].to_s()
|
|
445
|
-
end
|
|
446
|
-
if !results.has_key?('STATUS')
|
|
447
|
-
return results[RESPONSE_REASON_TEXT] ? results[RESPONSE_REASON_TEXT].chomp('.') : ''
|
|
448
|
-
end
|
|
456
|
+
post[:solution_ID] = application_id if(application_id && application_id != "ActiveMerchant")
|
|
457
|
+
post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
|
449
458
|
end
|
|
450
459
|
|
|
451
460
|
def expdate(creditcard)
|
|
452
|
-
year =
|
|
453
|
-
month =
|
|
461
|
+
year = format(creditcard.year, :two_digits)
|
|
462
|
+
month = format(creditcard.month, :two_digits)
|
|
454
463
|
|
|
455
|
-
"#{month}#{year
|
|
464
|
+
"#{month}#{year}"
|
|
456
465
|
end
|
|
457
466
|
|
|
458
467
|
def calc_tps(amount, post)
|
|
459
|
-
post[:NAME1]
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
468
|
+
post[:NAME1] ||= ''
|
|
469
|
+
Digest::MD5.hexdigest(
|
|
470
|
+
[
|
|
471
|
+
@options[:password],
|
|
472
|
+
@options[:login],
|
|
473
|
+
post[:TRANS_TYPE],
|
|
474
|
+
amount,
|
|
475
|
+
post[:MASTER_ID],
|
|
476
|
+
post[:NAME1],
|
|
477
|
+
post[:PAYMENT_ACCOUNT]
|
|
478
|
+
].join("")
|
|
479
|
+
)
|
|
465
480
|
end
|
|
466
481
|
|
|
467
482
|
def calc_rebill_tps(post)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
483
|
+
Digest::MD5.hexdigest(
|
|
484
|
+
[
|
|
485
|
+
@options[:password],
|
|
486
|
+
@options[:login],
|
|
487
|
+
post[:TRANS_TYPE],
|
|
488
|
+
post[:REBILL_ID]
|
|
489
|
+
].join("")
|
|
490
|
+
)
|
|
471
491
|
end
|
|
472
492
|
|
|
473
493
|
def handle_response(response)
|
|
474
|
-
if ignore_http_status
|
|
494
|
+
if ignore_http_status || (200...300).include?(response.code.to_i)
|
|
475
495
|
return response.body
|
|
476
|
-
else
|
|
477
|
-
case response.code.to_i
|
|
478
|
-
when 200...300
|
|
479
|
-
response.body
|
|
480
|
-
else
|
|
481
|
-
raise ResponseError.new(response)
|
|
482
|
-
end
|
|
483
496
|
end
|
|
497
|
+
raise ResponseError.new(response)
|
|
484
498
|
end
|
|
485
499
|
end
|
|
486
500
|
end
|
|
@@ -34,7 +34,7 @@ module ActiveMerchant #:nodoc:
|
|
|
34
34
|
money = amount(money)
|
|
35
35
|
case normalize(credit_card_or_reference)
|
|
36
36
|
when /1$/, AUTHORIZATION
|
|
37
|
-
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
|
|
37
|
+
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true, :authorization => AUTHORIZATION)
|
|
38
38
|
when /2$/
|
|
39
39
|
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
|
|
40
40
|
else
|
|
@@ -68,8 +68,10 @@ module ActiveMerchant #:nodoc:
|
|
|
68
68
|
Braintree::Configuration.custom_user_agent = "ActiveMerchant #{ActiveMerchant::VERSION}"
|
|
69
69
|
|
|
70
70
|
if wiredump_device
|
|
71
|
-
Braintree::Configuration.logger = wiredump_device
|
|
71
|
+
Braintree::Configuration.logger = ((Logger === wiredump_device) ? wiredump_device : Logger.new(wiredump_device))
|
|
72
72
|
Braintree::Configuration.logger.level = Logger::DEBUG
|
|
73
|
+
else
|
|
74
|
+
Braintree::Configuration.logger.level = Logger::WARN
|
|
73
75
|
end
|
|
74
76
|
end
|
|
75
77
|
|
|
@@ -135,7 +137,8 @@ module ActiveMerchant #:nodoc:
|
|
|
135
137
|
{
|
|
136
138
|
:braintree_customer => (customer_hash(result.customer) if result.success?),
|
|
137
139
|
:customer_vault_id => (result.customer.id if result.success?)
|
|
138
|
-
}
|
|
140
|
+
},
|
|
141
|
+
:authorization => (result.customer.id if result.success?)
|
|
139
142
|
)
|
|
140
143
|
end
|
|
141
144
|
end
|
|
@@ -169,7 +172,7 @@ module ActiveMerchant #:nodoc:
|
|
|
169
172
|
end
|
|
170
173
|
end
|
|
171
174
|
|
|
172
|
-
def unstore(customer_vault_id)
|
|
175
|
+
def unstore(customer_vault_id, options = {})
|
|
173
176
|
commit do
|
|
174
177
|
Braintree::Customer.delete(customer_vault_id)
|
|
175
178
|
Response.new(true, "OK")
|
|
@@ -337,6 +340,7 @@ module ActiveMerchant #:nodoc:
|
|
|
337
340
|
"bin" => transaction.credit_card_details.bin,
|
|
338
341
|
"last_4" => transaction.credit_card_details.last_4,
|
|
339
342
|
"card_type" => transaction.credit_card_details.card_type,
|
|
343
|
+
"token" => transaction.credit_card_details.token
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
{
|