activemerchant 1.32.1 → 1.33.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +41 -0
- data/CONTRIBUTORS +8 -0
- data/README.md +6 -4
- data/lib/active_merchant/billing/check.rb +4 -3
- data/lib/active_merchant/billing/credit_card.rb +7 -3
- data/lib/active_merchant/billing/gateways/authorize_net.rb +27 -7
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
- data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -185
- data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
- data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +94 -12
- data/lib/active_merchant/billing/gateways/litle.rb +41 -11
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +27 -6
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +2 -2
- 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/orbital.rb +181 -48
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
- data/lib/active_merchant/billing/gateways/paymill.rb +5 -5
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +11 -6
- data/lib/active_merchant/billing/gateways/paypal_express.rb +25 -7
- data/lib/active_merchant/billing/gateways/pin.rb +5 -5
- data/lib/active_merchant/billing/gateways/sage.rb +10 -5
- 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_pay.rb +1 -0
- data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +8 -3
- data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
- data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
- data/lib/active_merchant/billing/integrations/dwolla/common.rb +21 -0
- data/lib/active_merchant/billing/integrations/dwolla/helper.rb +15 -6
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +11 -6
- data/lib/active_merchant/billing/integrations/dwolla/return.rb +12 -4
- data/lib/active_merchant/billing/integrations/notification.rb +13 -8
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +13 -1
- data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
- 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/quickpay/notification.rb +68 -5
- data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
- 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/version.rb +1 -1
- metadata +14 -4
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,46 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
== Version 1.33.0 (May 30, 2013)
|
4
|
+
|
5
|
+
* Netaxept: Completely revamped to use the "M" service type [rbjordan3, ntalbott]
|
6
|
+
* Litle: Void authorizations via an auth reversal [jrust]
|
7
|
+
* Add RBK Money integration [england]
|
8
|
+
* Direcpay: Update test url [ashish-d]
|
9
|
+
* PayPal Express gateway: Add support for creating billing agreements [fabiokr]
|
10
|
+
* PayPal Express gateway: Add reference authorizations [fabiokr]
|
11
|
+
* Add Cardstream Modern gateway [ExxKA]
|
12
|
+
* Pin: Fix special headers [duff]
|
13
|
+
* PayPal Express gateway: Remember the billing agreement id as Response#authorization [duff]
|
14
|
+
* PayPal Express gateway: Allow an amount of 0 [duff]
|
15
|
+
* PayPal Express gateway: Reduce parameter requirements [duff]
|
16
|
+
* Quickpay integration: Update notification parser to handle API v6 [larspind]
|
17
|
+
* Sage gateway: Deprecate #credit call [duff]
|
18
|
+
* Update notification generator to better match current notification class [lulalala]
|
19
|
+
* Paymill gateway: Change .com -> .de [louiskearns]
|
20
|
+
* Quickpay integration: Fix v6 response parsing [larspind]
|
21
|
+
* First Data e4: Add TransArmor store/tokenization support [gabetax]
|
22
|
+
* MerchantWarrior: Format expiration month/year correctly [klebervirgilio]
|
23
|
+
* Add iconv for ActiveSupport 2.3 under Ruby 2.0 [sanemat]
|
24
|
+
* Add Transnational gateway [bvandenbos]
|
25
|
+
* Authorize.Net: Add Check as payment method [andrunix]
|
26
|
+
* Merchant e-Solutions: Add ref number and recurring support [carlaares]
|
27
|
+
* Bogus gateway: Add authorization to purchase response [hron]
|
28
|
+
* Bluepay gateway: Fix Check support; general cleanup [ntalbott]
|
29
|
+
* Dwolla: Fix security issues and enable guest checkout [capablemonkey, schonfeld]
|
30
|
+
* SagePay gateway: Per-transaction 3D-secure selection [ExxKA]
|
31
|
+
* Barclays ePDQ: Handle incorrectly encoded response [jordanwheeler, aprofeit]
|
32
|
+
* Orbital: Bug fixes; add CustomerEmail, Retry Logic, Managed Billing, and Destination Address [juicedM3
|
33
|
+
* Distinguish invalid vs empty issue_numbers on CreditCards [drasch]
|
34
|
+
* Float Gemfiles to latest Rails [sanemat]
|
35
|
+
* USA ePay Advanced: Fix Check support [RyanScottLewis]
|
36
|
+
* Authorize.Net: Match up Check fields better with eCheck.Net requirements [ntalbott]
|
37
|
+
* Bluepay: Updated to bp20post api [cagerton, melari]
|
38
|
+
* Net Registry: Deprecate credit method [jduff]
|
39
|
+
* Sage: Don't include T_customer_number unless it is numeric [melari]
|
40
|
+
* Auth.net: Don't include cust_id unless it is numeric [melari]
|
41
|
+
* Epay: Deprecate credit method [melari]
|
42
|
+
* New PayU.in Integration [PayU, melari]
|
43
|
+
|
3
44
|
== Version 1.32.1 (April 4, 2013)
|
4
45
|
|
5
46
|
* CC5 and Garanti: Remove $KCODE modifications [melari]
|
data/CONTRIBUTORS
CHANGED
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Ruby applications which deal with financial transactions. It is maintained by th
|
|
12
12
|
[Shopify](http://www.shopify.com) and [Spreedly](https://spreedly.com) teams, with much help
|
13
13
|
from an ever-growing set of contributors.
|
14
14
|
|
15
|
-
See
|
15
|
+
See [GettingStarted.md](GettingStarted.md) if you want to learn more about using Active Merchant in your
|
16
16
|
applications.
|
17
17
|
|
18
18
|
## Installation
|
@@ -72,7 +72,7 @@ credit card details.
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
For more in-depth documentation and tutorials, see
|
75
|
+
For more in-depth documentation and tutorials, see [GettingStarted.md](GettingStarted.md) and the
|
76
76
|
[API documentation](http://rubydoc.info/github/Shopify/active_merchant/master/file/README.md).
|
77
77
|
|
78
78
|
## Supported Direct Payment Gateways
|
@@ -135,7 +135,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
135
135
|
* [PayGate PayXML](http://paygate.co.za/) - US, ZA
|
136
136
|
* [PayJunction](http://www.payjunction.com/) - US
|
137
137
|
* [PaymentExpress](http://www.paymentexpress.com/) - AU, MY, NZ, SG, ZA, UK, US
|
138
|
-
* [
|
138
|
+
* [PAYMILL](https://www.paymill.com) - AD, AT, BE, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GR, HU, IE, IL, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, SE, SI, SK, TR, VA
|
139
139
|
* [PayPal Express Checkout](https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside) - US, CA, SG, AU
|
140
140
|
* [PayPal Payflow Pro](https://www.paypal.com/cgi-bin/webscr?cmd=_payflow-pro-overview-outside) - US, CA, SG, AU
|
141
141
|
* [PayPal Website Payments Pro (UK)](https://www.paypal.com/uk/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - UK
|
@@ -165,6 +165,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
165
165
|
* [Spreedly Core](https://spreedlycore.com/) - AD, AE, AT, AU, BD, BE, BG, BN, CA, CH, CY, CZ, DE, DK, EE, EG, ES, FI, FR, GB, GI, GR, HK, HU, ID, IE, IL, IM, IN, IS, IT, JO, KW, LB, LI, LK, LT, LU, LV, MC, MT, MU, MV, MX, MY, NL, NO, NZ, OM, PH, PL, PT, QA, RO, SA, SE, SG, SI, SK, SM, TR, TT, UM, US, VA, VN, ZA
|
166
166
|
* [Stripe](https://stripe.com/) - US
|
167
167
|
* [TransFirst](http://www.transfirst.com/) - US
|
168
|
+
* [Transnational](http://www.tnbci.com/) - US
|
168
169
|
* [TrustCommerce](http://www.trustcommerce.com/) - US
|
169
170
|
* [USA ePay](http://www.usaepay.com/) - US
|
170
171
|
* [Verifi](http://www.verifi.com/) - US
|
@@ -193,7 +194,8 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
193
194
|
* [Paxum](https://www.paxum.com/)
|
194
195
|
* [PayPal Website Payments Standard](https://www.paypal.com/cgi-bin/webscr?cmd#_wp-standard-overview-outside)
|
195
196
|
* [Paysbuy](https://www.paysbuy.com/) - TH
|
196
|
-
* [
|
197
|
+
* [RBK Money](https://rbkmoney.ru/) - RU
|
198
|
+
* [Robokassa](http://robokassa.ru/) - RU
|
197
199
|
* [SagePay Form](http://www.sagepay.com/products_services/sage_pay_go/integration/form)
|
198
200
|
* [Suomen Maksuturva](https://www.maksuturva.fi/services/vendor_services/integration_guidelines.html)
|
199
201
|
* [Valitor](http://www.valitor.is/) - IS
|
@@ -4,12 +4,13 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
# of necessary attributes such as checkholder's name, routing and account numbers, but it is
|
5
5
|
# not backed by any database.
|
6
6
|
#
|
7
|
-
# You may use Check in place of CreditCard with any gateway that supports it.
|
8
|
-
# +BraintreeGateway+ supports the Check object.
|
7
|
+
# You may use Check in place of CreditCard with any gateway that supports it.
|
9
8
|
class Check
|
10
9
|
include Validateable
|
11
10
|
|
12
|
-
attr_accessor :first_name, :last_name,
|
11
|
+
attr_accessor :first_name, :last_name,
|
12
|
+
:bank_name, :routing_number, :account_number,
|
13
|
+
:account_holder_type, :account_type, :number
|
13
14
|
|
14
15
|
# Used for Canadian bank accounts
|
15
16
|
attr_accessor :institution_number, :transit_number
|
@@ -257,9 +257,13 @@ module ActiveMerchant #:nodoc:
|
|
257
257
|
def validate_switch_or_solo_attributes #:nodoc:
|
258
258
|
if %w[switch solo].include?(brand)
|
259
259
|
unless valid_month?(@start_month) && valid_start_year?(@start_year) || valid_issue_number?(@issue_number)
|
260
|
-
|
261
|
-
|
262
|
-
|
260
|
+
if @issue_number.blank?
|
261
|
+
errors.add :start_month, "is invalid" unless valid_month?(@start_month)
|
262
|
+
errors.add :start_year, "is invalid" unless valid_start_year?(@start_year)
|
263
|
+
errors.add :issue_number, "cannot be empty"
|
264
|
+
else
|
265
|
+
errors.add :issue_number, "is invalid" unless valid_issue_number?(@issue_number)
|
266
|
+
end
|
263
267
|
end
|
264
268
|
end
|
265
269
|
end
|
@@ -83,13 +83,13 @@ module ActiveMerchant #:nodoc:
|
|
83
83
|
# ==== Parameters
|
84
84
|
#
|
85
85
|
# * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
|
86
|
-
# * <tt>
|
86
|
+
# * <tt>paysource</tt> -- The CreditCard or Check details for the transaction.
|
87
87
|
# * <tt>options</tt> -- A hash of optional parameters.
|
88
|
-
def authorize(money,
|
88
|
+
def authorize(money, paysource, options = {})
|
89
89
|
post = {}
|
90
90
|
add_currency_code(post, money, options)
|
91
91
|
add_invoice(post, options)
|
92
|
-
|
92
|
+
add_payment_source(post, paysource, options)
|
93
93
|
add_address(post, options)
|
94
94
|
add_customer_data(post, options)
|
95
95
|
add_duplicate_window(post)
|
@@ -102,13 +102,13 @@ module ActiveMerchant #:nodoc:
|
|
102
102
|
# ==== Parameters
|
103
103
|
#
|
104
104
|
# * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
|
105
|
-
# * <tt>
|
105
|
+
# * <tt>paysource</tt> -- The CreditCard or Check details for the transaction.
|
106
106
|
# * <tt>options</tt> -- A hash of optional parameters.
|
107
|
-
def purchase(money,
|
107
|
+
def purchase(money, paysource, options = {})
|
108
108
|
post = {}
|
109
109
|
add_currency_code(post, money, options)
|
110
110
|
add_invoice(post, options)
|
111
|
-
|
111
|
+
add_payment_source(post, paysource, options)
|
112
112
|
add_address(post, options)
|
113
113
|
add_customer_data(post, options)
|
114
114
|
add_duplicate_window(post)
|
@@ -349,6 +349,26 @@ module ActiveMerchant #:nodoc:
|
|
349
349
|
post[:last_name] = creditcard.last_name
|
350
350
|
end
|
351
351
|
|
352
|
+
def add_payment_source(params, source, options={})
|
353
|
+
if card_brand(source) == "check"
|
354
|
+
add_check(params, source, options)
|
355
|
+
else
|
356
|
+
add_creditcard(params, source)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
def add_check(post, check, options)
|
361
|
+
post[:method] = "ECHECK"
|
362
|
+
post[:bank_name] = check.bank_name
|
363
|
+
post[:bank_aba_code] = check.routing_number
|
364
|
+
post[:bank_acct_num] = check.account_number
|
365
|
+
post[:bank_acct_type] = check.account_type
|
366
|
+
post[:echeck_type] = "WEB"
|
367
|
+
post[:bank_acct_name] = check.name
|
368
|
+
post[:bank_check_number] = check.number if check.number.present?
|
369
|
+
post[:recurring_billing] = (options[:recurring] ? "TRUE" : "FALSE")
|
370
|
+
end
|
371
|
+
|
352
372
|
def add_customer_data(post, options)
|
353
373
|
if options.has_key? :email
|
354
374
|
post[:email] = options[:email]
|
@@ -356,7 +376,7 @@ module ActiveMerchant #:nodoc:
|
|
356
376
|
end
|
357
377
|
|
358
378
|
if options.has_key? :customer
|
359
|
-
post[:cust_id] = options[:customer]
|
379
|
+
post[:cust_id] = options[:customer] if Float(options[:customer]) rescue nil
|
360
380
|
end
|
361
381
|
|
362
382
|
if options.has_key? :ip
|
@@ -134,7 +134,14 @@ module ActiveMerchant #:nodoc:
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def parse
|
137
|
-
|
137
|
+
require 'iconv' unless String.method_defined?(:encode)
|
138
|
+
if String.method_defined?(:encode)
|
139
|
+
doc = REXML::Document.new(@response.encode("UTF-8", "ISO-8859-1"))
|
140
|
+
else
|
141
|
+
ic = Iconv.new('UTF-8', 'ISO-8859-1')
|
142
|
+
doc = REXML::Document.new(ic.iconv(@response))
|
143
|
+
end
|
144
|
+
|
138
145
|
auth_type = find(doc, "//Transaction/Type").to_s
|
139
146
|
|
140
147
|
message = find(doc, "//Message/Text")
|
@@ -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,117 +295,133 @@ 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
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
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)
|
333
|
+
end
|
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
|
344
339
|
end
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
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]
|
424
|
+
if address = (options[:shipping_address] || options[:billing_address] || options[:address])
|
393
425
|
post[:NAME1] = address[:first_name]
|
394
426
|
post[:NAME2] = address[:last_name]
|
395
427
|
post[:ADDR1] = address[:address1]
|
@@ -397,27 +429,23 @@ module ActiveMerchant #:nodoc:
|
|
397
429
|
post[:COMPANY_NAME] = address[:company]
|
398
430
|
post[:PHONE] = address[:phone]
|
399
431
|
post[:CITY] = address[:city]
|
400
|
-
post[:STATE] = address[:state].blank?
|
432
|
+
post[:STATE] = (address[:state].blank? ? 'n/a' : address[:state])
|
401
433
|
post[:ZIP] = address[:zip]
|
402
434
|
post[:COUNTRY] = address[:country]
|
403
435
|
end
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
post[:CITY] = address[:city]
|
413
|
-
post[:COUNTRY] = address[:country]
|
414
|
-
post[:STATE] = address[:state].blank? ? 'n/a' : address[:state]
|
415
|
-
end
|
436
|
+
end
|
437
|
+
|
438
|
+
def add_rebill(post, options)
|
439
|
+
post[:DO_REBILL] = '1'
|
440
|
+
post[:REB_AMOUNT] = amount(options[:rebill_amount])
|
441
|
+
post[:REB_FIRST_DATE] = options[:rebill_start_date]
|
442
|
+
post[:REB_EXPR] = options[:rebill_expression]
|
443
|
+
post[:REB_CYCLES] = options[:rebill_cycles]
|
416
444
|
end
|
417
445
|
|
418
446
|
def post_data(action, parameters = {})
|
419
447
|
post = {}
|
420
|
-
post[:version] = '
|
448
|
+
post[:version] = '1'
|
421
449
|
post[:login] = ''
|
422
450
|
post[:tran_key] = ''
|
423
451
|
post[:relay_response] = "FALSE"
|
@@ -427,60 +455,48 @@ module ActiveMerchant #:nodoc:
|
|
427
455
|
post[:encap_char] = "$"
|
428
456
|
post[:card_num] = '4111111111111111'
|
429
457
|
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
|
458
|
+
post[:solution_ID] = application_id if(application_id && application_id != "ActiveMerchant")
|
459
|
+
post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
449
460
|
end
|
450
461
|
|
451
462
|
def expdate(creditcard)
|
452
|
-
year =
|
453
|
-
month =
|
463
|
+
year = format(creditcard.year, :two_digits)
|
464
|
+
month = format(creditcard.month, :two_digits)
|
454
465
|
|
455
|
-
"#{month}#{year
|
466
|
+
"#{month}#{year}"
|
456
467
|
end
|
457
468
|
|
458
469
|
def calc_tps(amount, post)
|
459
|
-
post[:NAME1]
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
470
|
+
post[:NAME1] ||= ''
|
471
|
+
Digest::MD5.hexdigest(
|
472
|
+
[
|
473
|
+
@options[:password],
|
474
|
+
@options[:login],
|
475
|
+
post[:TRANS_TYPE],
|
476
|
+
amount,
|
477
|
+
post[:MASTER_ID],
|
478
|
+
post[:NAME1],
|
479
|
+
post[:PAYMENT_ACCOUNT]
|
480
|
+
].join("")
|
481
|
+
)
|
465
482
|
end
|
466
483
|
|
467
484
|
def calc_rebill_tps(post)
|
468
|
-
|
469
|
-
|
470
|
-
|
485
|
+
Digest::MD5.hexdigest(
|
486
|
+
[
|
487
|
+
@options[:password],
|
488
|
+
@options[:login],
|
489
|
+
post[:TRANS_TYPE],
|
490
|
+
post[:REBILL_ID]
|
491
|
+
].join("")
|
492
|
+
)
|
471
493
|
end
|
472
494
|
|
473
495
|
def handle_response(response)
|
474
|
-
if ignore_http_status
|
496
|
+
if ignore_http_status || (200...300).include?(response.code.to_i)
|
475
497
|
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
498
|
end
|
499
|
+
raise ResponseError.new(response)
|
484
500
|
end
|
485
501
|
end
|
486
502
|
end
|