tlconnor-activemerchant 1.20.4 → 1.23.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +86 -6
- data/CONTRIBUTORS +33 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +2 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +4 -4
- data/lib/active_merchant/billing/gateways/blue_pay.rb +492 -11
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +46 -19
- data/lib/active_merchant/billing/gateways/certo_direct.rb +1 -1
- data/lib/active_merchant/billing/gateways/elavon.rb +2 -0
- data/lib/active_merchant/billing/gateways/epay.rb +3 -1
- data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
- data/lib/active_merchant/billing/gateways/litle.rb +275 -0
- data/lib/active_merchant/billing/gateways/migs.rb +259 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +4 -30
- data/lib/active_merchant/billing/gateways/moneris_us.rb +211 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/ogone.rb +104 -12
- data/lib/active_merchant/billing/gateways/orbital.rb +15 -6
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +1 -4
- data/lib/active_merchant/billing/gateways/payflow.rb +8 -3
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +4 -1
- data/lib/active_merchant/billing/gateways/payflow_express.rb +4 -2
- data/lib/active_merchant/billing/gateways/payment_express.rb +60 -13
- data/lib/active_merchant/billing/gateways/paypal.rb +3 -18
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +333 -3
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +245 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +14 -65
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
- data/lib/active_merchant/billing/gateways/realex.rb +5 -7
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -2
- data/lib/active_merchant/billing/gateways/stripe.rb +1 -9
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +2 -2
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -5
- data/lib/active_merchant/billing/gateways/viaklix.rb +7 -2
- data/lib/active_merchant/billing/gateways/vindicia.rb +359 -0
- data/lib/active_merchant/billing/integrations/dotpay.rb +22 -0
- data/lib/active_merchant/billing/integrations/dotpay/helper.rb +77 -0
- data/lib/active_merchant/billing/integrations/dotpay/notification.rb +86 -0
- data/lib/active_merchant/billing/integrations/dotpay/return.rb +11 -0
- data/lib/active_merchant/billing/integrations/epay.rb +21 -0
- data/lib/active_merchant/billing/integrations/epay/helper.rb +55 -0
- data/lib/active_merchant/billing/integrations/epay/notification.rb +110 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +2 -1
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +2 -3
- data/lib/active_merchant/billing/integrations/robokassa.rb +49 -0
- data/lib/active_merchant/billing/integrations/robokassa/common.rb +19 -0
- data/lib/active_merchant/billing/integrations/robokassa/helper.rb +50 -0
- data/lib/active_merchant/billing/integrations/robokassa/notification.rb +55 -0
- data/lib/active_merchant/billing/integrations/robokassa/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +25 -3
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +58 -26
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +71 -46
- data/lib/active_merchant/billing/integrations/verkkomaksut.rb +20 -0
- data/lib/active_merchant/billing/integrations/verkkomaksut/helper.rb +87 -0
- data/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb +59 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +28 -5
data/CHANGELOG
CHANGED
@@ -1,5 +1,79 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
* PayPal gateway: Support for incomplete captures [mbulat]
|
4
|
+
|
5
|
+
== Version 1.23.0 (May 23, 2012)
|
6
|
+
|
7
|
+
* Add Litle gateway [GregDrake]
|
8
|
+
* PaymentExpress gateway: add support for BillingId and DpsBillingId for token [mikel]
|
9
|
+
* 2checkout integration: Add ability to auto settle [craigchristenson]
|
10
|
+
* 2checkout integration: Switch default mode to single page [craigchristenson]
|
11
|
+
* Cybersource: Revert - Add retrieve method to pull details on a
|
12
|
+
stored card [jduff]
|
13
|
+
* Cybersource: Revert - Add recurring payment support [jduff]
|
14
|
+
* PaymentExpress: add Cvc2Presence flag when submitting verification
|
15
|
+
value [jduff]
|
16
|
+
* SecurePayAU: fix CreditCard check [jduff]
|
17
|
+
* Barclays: fix order capture [csaunders/ntalbott/jduff]
|
18
|
+
|
19
|
+
== Version 1.22.0 (May 17, 2012)
|
20
|
+
|
21
|
+
* Remove version restriction for money gem [ylansegal]
|
22
|
+
* Add iTransact XML gateway [motske]
|
23
|
+
* PayPal Express Gateway: add options[:landing_page] [markus]
|
24
|
+
* USA ePay: Fix handling of AVS [duff]
|
25
|
+
* Ogone: Add store method to create an alias without making a purchase [joelcogen]
|
26
|
+
* Spelling fix: purcahse -> purchase [mnoack]
|
27
|
+
* ePay: Added more useful results for authorization errors [Dennis O'Connor]
|
28
|
+
* Add Robokassa integration [nashby]
|
29
|
+
* PayPal Gateway: Add recurring API [dscataglini]
|
30
|
+
* Braintree: Add support for :verify_card option on store [brentmc79]
|
31
|
+
* Moneris: cannot void a preauthorization [eddanger]
|
32
|
+
* Add Moneris US gateway [eddanger]
|
33
|
+
* Add Dotpay integration [kacperix]
|
34
|
+
* Payflow: Add description, comment and comment2 tags [ksnyder]
|
35
|
+
* Dotpay: Fix field mapping [kacperix]
|
36
|
+
* Authorize.Net CIM: Optionally add 'order' details to transactions [pote]
|
37
|
+
* Braintree: Allow including billing address when storing a customer [brentmc79]
|
38
|
+
* PayPal Gateway: Refactored PaymentDetails & PaymentDetailsItem common code [dscataglini]
|
39
|
+
* Viaklix/Elavon: Separate "demo accounts" from "test transactions" [mltsy]
|
40
|
+
* PayPal Gateway: Add transaction_details, balance, authorize_transaction, and manage_pending_transaction API calls [dscataglini]
|
41
|
+
* PayPal Gateway: Add support for TransactionSearch & DoReferenceTransaction [dscataglini]
|
42
|
+
* Cybersource: Add recurring payment support [jaredmoory]
|
43
|
+
* Tidy up gateway lists [ashokak]
|
44
|
+
* Paybox: remove Iconv usage [ntalbott]
|
45
|
+
* Dotpay: Add amount mapping, pin setter, and support for test? [kacperix]
|
46
|
+
* Braintree Blue: Make address country map to alpha2 [ntalbott]
|
47
|
+
* Use GB as the alpha2 country code for the UK [ntalbott]
|
48
|
+
* Realex: Handle XML response with unescaped ampersand [ntalbott]
|
49
|
+
* Add Vindicia gateway [steved555]
|
50
|
+
* Payment Express: use %w[] for country list [parndt]
|
51
|
+
* Braintree Blue: Match remote test up with change to :country [braintreeps]
|
52
|
+
* PayPal Integration: Fix received_at method time parsing [subbarao]
|
53
|
+
* Add MiGS Gateway [mnoack, nagash]
|
54
|
+
* Quickpay integration: Fix payment_service_for helper [TheMaster]
|
55
|
+
* Braintree Blue gateway: Improve update method [brentmc79]
|
56
|
+
* 2checkout integration: Add mode mapping & line items helper [AlexanderZaytsev]
|
57
|
+
* USA ePay Advanced gateway: Fix expiration date format. [cctalbott]
|
58
|
+
* Add ePay integration [ePay]
|
59
|
+
* 2checkout integration: Add support for single page payment routine [AlexanderZaytsev]
|
60
|
+
* Ogone: Add support for 3D Secure [rymai, ZenCocoon]
|
61
|
+
* Stripe gateway: Remove authorize and capture methods since they are not supported [jduff]
|
62
|
+
* Stripe gateway: default test to false if no livemode parameter is specified [jduff]
|
63
|
+
* Paybox Direct gateway: 'card absent' and 'do not honour' should be considered failures, not fraudulent [jduff]
|
64
|
+
* Add Verkkomaksut integration [akonan]
|
65
|
+
* Remove trailing spaces from generator templates [akonan]
|
66
|
+
* Payflow gateway: Allow modification of RetryNumDays [jrust]
|
67
|
+
* Payflow gateway: Don't auto-set start_date on modification [jrust]
|
68
|
+
* Bluepay gateway: Add ACH & recurring support [jslingerland]
|
69
|
+
* Orbital gateway: Don't send AVS address details for any country besides US, CA, GB and UK [Soleone]
|
70
|
+
* Payflow Express gateway: Better amount handling [jduff]
|
71
|
+
* Barclays gateway: Allow American Express [duff]
|
72
|
+
* Ogone gateway: Remove duplicated method [ntalbott]
|
73
|
+
* Cybersource gateway: Add retrieve method to pull details on a stored card [fabiokr]
|
74
|
+
|
75
|
+
== Version 1.21.0 (March 7, 2012)
|
76
|
+
|
3
77
|
* Stripe: Add support for passing IP [collision]
|
4
78
|
* Merchant e-Solutions: pass expiration date when purchasing with a stored credit card [chrisyoung]
|
5
79
|
* Braintree: Fix passing custom processor ids to old accounts [maxsilver]
|
@@ -12,7 +86,6 @@
|
|
12
86
|
* Authorize.Net CIM: Add option for setting a custom delimiter [bmorton]
|
13
87
|
* Authorize.Net CIM: Add 3.1 response fields [bmorton]
|
14
88
|
* Authorize.Net CIM: Misc fixes and doc improvements [bmorton]
|
15
|
-
* Moneris: Add AVS/CVV support [odorcicd]
|
16
89
|
* Authorize.Net CIM: Fix error when order is blank [KeeperPat]
|
17
90
|
* Beanstream: Add recurring payments support [castiglione]
|
18
91
|
* Make ePay password optional [ePay]
|
@@ -27,6 +100,13 @@
|
|
27
100
|
* Viaklix: Add discover as a supported card type [waelchatila]
|
28
101
|
* Improvements to testing infrastructure for integrations [jduff]
|
29
102
|
* Add NAB Transact (AU) Gateway [tommeier]
|
103
|
+
* PayPal Express: Add Support for Reference Transactions using BAIDs [kenmazaika]
|
104
|
+
* Authorize.Net CIM: Add support for optional refund fields [nilmethod]
|
105
|
+
* SecurePayTech: Fix EnableCSC parameter so CVV codes are checked. [tlconnor]
|
106
|
+
* SecurePayTech: Add remote tests for CSC checking. [tlconnor]
|
107
|
+
* Samurai: Add option to retain payment methods once stored [brentmc79]
|
108
|
+
* PayPal Express Gateway: Add support for Digital Goods / Micropayments [kenmazaika]
|
109
|
+
|
30
110
|
|
31
111
|
== Version 1.20.4 (February 22, 2012)
|
32
112
|
|
@@ -602,7 +682,7 @@
|
|
602
682
|
* Fix errors on base of CreditCard [josh.bassett]
|
603
683
|
* Update product to use Rubigen instead of stolen Rails generator [cody]
|
604
684
|
* Mimic directory structure of unit tests in remote tests [cody]
|
605
|
-
* Restructure the location of the remote tests [cody]
|
685
|
+
* Restructure the location of the remote tests [cody]
|
606
686
|
* Ensure DataCash order_id is limited to 30 characters [cody]
|
607
687
|
* Return the pretty messages from PayJunction based on the return code [cody]
|
608
688
|
* make CreditCard.require_verification_value = true the default [cody]
|
@@ -668,7 +748,7 @@
|
|
668
748
|
* Enhance credit card error messages [manfred]
|
669
749
|
* Use HashWithIndifferentAccess for CreditCard for compatibility with Rails applications [michael.j.mangino]
|
670
750
|
* Fix nil exception when no response reason text is found in Authorize.net [cody]
|
671
|
-
* Add support for PayJunction [Matt Sanders]
|
751
|
+
* Add support for PayJunction [Matt Sanders]
|
672
752
|
* Change billing_address to shipping_address in PayPal Integration helper, as billing_address was incorrect. Addresses passed to billing_address for the PayPal helper will no longer be added to the form. This will break existing code, as the address will not be passed.
|
673
753
|
* Remove switch patterns from card detection that were eliminated on July 1, 2007 [cody]
|
674
754
|
* Format the issue number in Payflow requests to always be 2 digits [cody]
|
@@ -706,7 +786,7 @@
|
|
706
786
|
* Update and test PslCardGateway [cody]
|
707
787
|
* Add Laser card type [cody]
|
708
788
|
* Update Nochex documentation [cody]
|
709
|
-
* Sanitize the Realex order_id [cody]
|
789
|
+
* Sanitize the Realex order_id [cody]
|
710
790
|
* Add support for Irish Realex payment gateway [John Ward, cody]
|
711
791
|
* Move credit_card helper method to the test_helper [cody]
|
712
792
|
* Update PayflowExpressResponse to match the interface of the PayflowExpressResponse. Add :no_shipping and :address_override options to PayflowExpress [cody]
|
@@ -764,7 +844,7 @@
|
|
764
844
|
* Update DataCash tests and format merchant reference number to meet DataCash's requirements [MoneySpyder, cody]
|
765
845
|
* Add Datacash gateway [MoneySpyder, cody]
|
766
846
|
* VERIFY_PEER on all SSL requests [cody]
|
767
|
-
* Add support for 2Checkout [cody]
|
847
|
+
* Add support for 2Checkout [cody]
|
768
848
|
|
769
849
|
== Version 1.0.3
|
770
850
|
|
@@ -795,7 +875,7 @@
|
|
795
875
|
* Moneris now uses the same layout as the authorized.net plugin
|
796
876
|
* Added authorized.net
|
797
877
|
* Changed default to :test mode. Set to production with ActiveMerchant::Billing::Base.gateway_mode = :production
|
798
|
-
* More refactoring
|
878
|
+
* More refactoring
|
799
879
|
* Refactored a bit so that there is space for billing and shipping area. None of the shipping aids are fleshed out yet. Needs more work.
|
800
880
|
* Added Moneris support
|
801
881
|
* Credit card in memory object resembling a AR object
|
data/CONTRIBUTORS
CHANGED
@@ -272,3 +272,36 @@ Authorize.Net SIM Integration (February, 2012)
|
|
272
272
|
NAB Transact (AU) Gateway (February, 2012)
|
273
273
|
|
274
274
|
* Tom Meier (tommeier)
|
275
|
+
|
276
|
+
iTransact XML Gateway (March, 2012)
|
277
|
+
|
278
|
+
* Kevin Motschiedler (motske)
|
279
|
+
|
280
|
+
Robokassa Integration (March, 2012)
|
281
|
+
|
282
|
+
* Vasiliy Ermolovich (nashby)
|
283
|
+
|
284
|
+
Moneris US Gateway (March, 2012)
|
285
|
+
|
286
|
+
* Michael Wood (eddanger)
|
287
|
+
|
288
|
+
Dotpay Integration (March, 2012)
|
289
|
+
|
290
|
+
* Przemysław Ciąćka (kacperix)
|
291
|
+
|
292
|
+
Vindicia gateway (April 2012)
|
293
|
+
|
294
|
+
* Steven Davidovitz (steved555)
|
295
|
+
|
296
|
+
MiGS gateway (April 2012)
|
297
|
+
|
298
|
+
* Michael Noack (mnoack)
|
299
|
+
* Justin Jones (nagash)
|
300
|
+
|
301
|
+
ePay integration (April 2012)
|
302
|
+
|
303
|
+
* Michael (ePay)
|
304
|
+
|
305
|
+
Litle gateway (May 2012)
|
306
|
+
|
307
|
+
* Gregory Drake (GregDrake)
|
@@ -486,6 +486,8 @@ module ActiveMerchant #:nodoc:
|
|
486
486
|
add_merchant_authentication(xml)
|
487
487
|
# Merchant-assigned reference ID for the request
|
488
488
|
xml.tag!('refId', options[:ref_id]) if options[:ref_id]
|
489
|
+
# Order options
|
490
|
+
add_order(xml, options[:order]) if options[:order]
|
489
491
|
send("build_#{action}_request", xml, options)
|
490
492
|
end
|
491
493
|
end
|
@@ -4,9 +4,9 @@ module ActiveMerchant #:nodoc:
|
|
4
4
|
TEST_URL = 'https://secure2.mde.epdq.co.uk:11500'
|
5
5
|
LIVE_URL = 'https://secure2.epdq.co.uk:11500'
|
6
6
|
|
7
|
-
self.supported_countries = ['
|
7
|
+
self.supported_countries = ['GB']
|
8
8
|
self.default_currency = 'GBP'
|
9
|
-
self.supported_cardtypes = [:visa, :master, :maestro, :switch ]
|
9
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :maestro, :switch ]
|
10
10
|
self.money_format = :cents
|
11
11
|
self.homepage_url = 'http://www.barclaycard.co.uk/business/accepting-payments/epdq-mpi/'
|
12
12
|
self.display_name = 'Barclays ePDQ'
|
@@ -153,10 +153,10 @@ module ActiveMerchant #:nodoc:
|
|
153
153
|
{
|
154
154
|
:success => success,
|
155
155
|
:message => message,
|
156
|
-
:
|
156
|
+
:transaction_id => find(doc, "//Transaction/Id"),
|
157
157
|
:avs_result => find(doc, "//Transaction/AvsRespCode"),
|
158
158
|
:cvv_result => find(doc, "//Transaction/Cvv2Resp"),
|
159
|
-
:
|
159
|
+
:authorization => find(doc, "//OrderFormDoc/Id"),
|
160
160
|
:raw_response => @response
|
161
161
|
}
|
162
162
|
end
|
@@ -1,11 +1,492 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module ActiveMerchant #:nodoc:
|
4
|
+
module Billing #:nodoc:
|
5
|
+
class BluePayGateway < Gateway
|
6
|
+
class_attribute :live_url, :rebilling_url, :ignore_http_status
|
7
|
+
|
8
|
+
self.live_url = 'https://secure.bluepay.com/interfaces/bp20post'
|
9
|
+
self.rebilling_url = 'https://secure.bluepay.com/interfaces/bp20rebadmin'
|
10
|
+
|
11
|
+
self.ignore_http_status = true
|
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
|
+
CARD_CODE_ERRORS = %w( N S )
|
17
|
+
AVS_ERRORS = %w( A E N R W Z )
|
18
|
+
AVS_REASON_CODES = %w(27 45)
|
19
|
+
|
20
|
+
class_attribute :duplicate_window
|
21
|
+
|
22
|
+
self.supported_countries = ['US']
|
23
|
+
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
24
|
+
self.homepage_url = 'http://www.bluepay.com/'
|
25
|
+
self.display_name = 'BluePay'
|
26
|
+
self.money_format = :dollars
|
27
|
+
|
28
|
+
|
29
|
+
# Creates a new BluepayGateway
|
30
|
+
#
|
31
|
+
# The gateway requires that a valid Account ID and Secret Key be passed
|
32
|
+
# in the +options+ hash.
|
33
|
+
#
|
34
|
+
# ==== Options
|
35
|
+
#
|
36
|
+
# * <tt>:account_id</tt> -- The BluePay gateway Account ID (REQUIRED)
|
37
|
+
# * <tt>:secret_key</tt> -- The BluePay gateway Secret Key (REQUIRED)
|
38
|
+
# * <tt>:test</tt> -- set to true for TEST mode or false for LIVE mode
|
39
|
+
def initialize(options = {})
|
40
|
+
requires!(options, :login, :password)
|
41
|
+
@options = options
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
45
|
+
# Performs an authorization, which reserves the funds on the customer's credit card. This does not actually take funds from the customer
|
46
|
+
# This is referred to an AUTH transaction in BluePay
|
47
|
+
#
|
48
|
+
# ==== Parameters
|
49
|
+
#
|
50
|
+
# * <tt>money</tt> -- The amount to be authorized as an Integer value in cents.
|
51
|
+
# * <tt>payment_object</tt> -- This can either be one of three things:
|
52
|
+
# A CreditCard object,
|
53
|
+
# A Check object,
|
54
|
+
# or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
|
55
|
+
# * <tt>options</tt> -- A hash of optional parameters.
|
56
|
+
def authorize(money, payment_object, options = {})
|
57
|
+
post = {}
|
58
|
+
post[:MASTER_ID] = ''
|
59
|
+
if payment_object != nil && payment_object.class() != String
|
60
|
+
payment_object.class() == ActiveMerchant::Billing::Check ?
|
61
|
+
add_check(post, payment_object) :
|
62
|
+
add_creditcard(post, payment_object)
|
63
|
+
else
|
64
|
+
post[:MASTER_ID] = payment_object
|
65
|
+
end
|
66
|
+
add_invoice(post, options)
|
67
|
+
add_address(post, options)
|
68
|
+
add_customer_data(post, options)
|
69
|
+
if options[:rebill] != nil
|
70
|
+
post[:DO_REBILL] = '1'
|
71
|
+
post[:REB_AMOUNT] = amount(options[:rebill_amount])
|
72
|
+
post[:REB_FIRST_DATE] = options[:rebill_start_date]
|
73
|
+
post[:REB_EXPR] = options[:rebill_expression]
|
74
|
+
post[:REB_CYCLES] = options[:rebill_cycles]
|
75
|
+
end
|
76
|
+
post[:TRANS_TYPE] = 'AUTH'
|
77
|
+
commit('AUTH_ONLY', money, post)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Perform a purchase, which is essentially an authorization and capture in a single operation.
|
81
|
+
# This is referred to a SALE transaction in BluePay
|
82
|
+
#
|
83
|
+
# ==== Parameters
|
84
|
+
#
|
85
|
+
# * <tt>money</tt> -- The amount to be purchased as an Integer value in cents.
|
86
|
+
# * <tt>payment_object</tt> -- This can either be one of three things:
|
87
|
+
# A CreditCard object,
|
88
|
+
# A Check object,
|
89
|
+
# or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
|
90
|
+
# * <tt>options</tt> -- A hash of optional parameters.,
|
91
|
+
def purchase(money, payment_object, options = {})
|
92
|
+
post = {}
|
93
|
+
post[:MASTER_ID] = ''
|
94
|
+
if payment_object != nil && payment_object.class() != String
|
95
|
+
payment_object.class() == ActiveMerchant::Billing::Check ?
|
96
|
+
add_check(post, payment_object) :
|
97
|
+
add_creditcard(post, payment_object)
|
98
|
+
else
|
99
|
+
post[:MASTER_ID] = payment_object
|
100
|
+
end
|
101
|
+
add_invoice(post, options)
|
102
|
+
add_address(post, options)
|
103
|
+
add_customer_data(post, options)
|
104
|
+
if options[:rebill] != nil
|
105
|
+
post[:DO_REBILL] = '1'
|
106
|
+
post[:REB_AMOUNT] = amount(options[:rebill_amount])
|
107
|
+
post[:REB_FIRST_DATE] = options[:rebill_start_date]
|
108
|
+
post[:REB_EXPR] = options[:rebill_expression]
|
109
|
+
post[:REB_CYCLES] = options[:rebill_cycles]
|
110
|
+
end
|
111
|
+
post[:TRANS_TYPE] = 'SALE'
|
112
|
+
commit('AUTH_CAPTURE', money, post)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Captures the funds from an authorize transaction.
|
116
|
+
# This is referred to a CAPTURE transaction in BluePay
|
117
|
+
#
|
118
|
+
# ==== Parameters
|
119
|
+
#
|
120
|
+
# * <tt>money</tt> -- The amount to be captured as an Integer value in cents.
|
121
|
+
# * <tt>identification</tt> -- The Master ID, or token, returned from the previous authorize transaction.
|
122
|
+
def capture(money, identification, options = {})
|
123
|
+
post = {}
|
124
|
+
add_address(post, options)
|
125
|
+
add_customer_data(post, options)
|
126
|
+
post[:MASTER_ID] = identification
|
127
|
+
post[:TRANS_TYPE] = 'CAPTURE'
|
128
|
+
commit('PRIOR_AUTH_CAPTURE', money, post)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Void a previous transaction
|
132
|
+
# This is referred to a VOID transaction in BluePay
|
133
|
+
#
|
134
|
+
# ==== Parameters
|
135
|
+
#
|
136
|
+
# * <tt>identification</tt> - The Master ID, or token, returned from a previous authorize transaction.
|
137
|
+
def void(identification, options = {})
|
138
|
+
post = {}
|
139
|
+
post[:MASTER_ID] = identification
|
140
|
+
post[:TRANS_TYPE] = 'VOID'
|
141
|
+
commit('VOID', nil, post)
|
142
|
+
end
|
143
|
+
|
144
|
+
# Performs a credit.
|
145
|
+
#
|
146
|
+
# This transaction indicates that money should flow from the merchant to the customer.
|
147
|
+
#
|
148
|
+
# ==== Parameters
|
149
|
+
#
|
150
|
+
# * <tt>money</tt> -- The amount to be credited to the customer as an Integer value in cents.
|
151
|
+
# * <tt>payment_object</tt> -- This can either be one of three things:
|
152
|
+
# A CreditCard object,
|
153
|
+
# A Check object,
|
154
|
+
# or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
|
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.
|
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.
|
157
|
+
# * <tt>options</tt> -- A hash of parameters.
|
158
|
+
def refund(money, payment_object, options = {})
|
159
|
+
post = {}
|
160
|
+
post[:PAYMENT_ACCOUNT] = ''
|
161
|
+
if payment_object != nil && payment_object.class() != String
|
162
|
+
payment_object.class() == ActiveMerchant::Billing::Check ?
|
163
|
+
add_check(post, payment_object) :
|
164
|
+
add_creditcard(post, payment_object)
|
165
|
+
post[:TRANS_TYPE] = 'CREDIT'
|
166
|
+
else
|
167
|
+
post[:MASTER_ID] = payment_object
|
168
|
+
post[:TRANS_TYPE] = 'REFUND'
|
169
|
+
end
|
170
|
+
|
171
|
+
options[:first_name] ? post[:NAME1] = options[:first_name] : post[:NAME1] = ''
|
172
|
+
post[:NAME2] = options[:last_name] if options[:last_name]
|
173
|
+
post[:ZIP] = options[:zip] if options[:zip]
|
174
|
+
add_invoice(post, options)
|
175
|
+
add_address(post, options)
|
176
|
+
add_customer_data(post, options)
|
177
|
+
commit('CREDIT', money, post)
|
178
|
+
end
|
179
|
+
|
180
|
+
def credit(money, identification, options = {})
|
181
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
182
|
+
refund(money, identification, options)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Create a new recurring payment.
|
186
|
+
#
|
187
|
+
# ==== Parameters
|
188
|
+
#
|
189
|
+
# * <tt>money</tt> -- The amount to charge the customer at the time of the recurring payment setup, in cents. Set to zero if you do not want the customer to be charged at this time.
|
190
|
+
# * <tt>payment_object</tt> -- This can either be one of three things:
|
191
|
+
# A CreditCard object,
|
192
|
+
# A Check object,
|
193
|
+
# or a token. The token is called the Master ID. This is a unique transaction ID returned from a previous transaction. This token associates all the stored information for a previous transaction.
|
194
|
+
# * <tt>options</tt> -- A hash of optional parameters.,
|
195
|
+
|
196
|
+
# ==== Options
|
197
|
+
#
|
198
|
+
# * <tt>:rebill_start_date</tt> is a string that tells the gateway when to start the rebill. (REQUIRED)
|
199
|
+
# Has two valid formats:
|
200
|
+
# "YYYY-MM-DD HH:MM:SS" Hours, minutes, and seconds are optional.
|
201
|
+
# "XX UNITS" Relative date as explained below. Marked from the time of the
|
202
|
+
# transaction (i.e.: 10 DAYS, 1 MONTH, 1 YEAR)
|
203
|
+
# * <tt>:rebill_expression</tt> is the period of time in-between rebillings. (REQUIRED)
|
204
|
+
# It uses the same "XX UNITS" format as rebill_start_date, explained above.
|
205
|
+
# Optional parameters include:
|
206
|
+
# * <tt>rebill_cycles</tt>: Number of times to rebill. Don't send or set to nil for infinite rebillings (or
|
207
|
+
# until canceled).
|
208
|
+
# * <tt>rebill_amount</tt>: Amount to rebill. Defaults to amount of transaction for rebillings.
|
209
|
+
#
|
210
|
+
# For example, to charge the customer $19.95 now and then charge $39.95 in 60 days every 3 months for 5 times, the options hash would be as follows:
|
211
|
+
# :rebill_start_date => '60 DAYS',
|
212
|
+
# :rebill_expression => '3 MONTHS',
|
213
|
+
# :rebill_cycles => '5',
|
214
|
+
# :rebill_amount => '39.95'
|
215
|
+
# A money object of 1995 cents would be passed into the 'money' parameter.
|
216
|
+
def recurring(money, payment_object, options = {})
|
217
|
+
requires!(options, :rebill_start_date, :rebill_expression)
|
218
|
+
options[:rebill] = '1'
|
219
|
+
money == nil ? authorize(money, payment_object, options) :
|
220
|
+
purchase(money, payment_object, options)
|
221
|
+
end
|
222
|
+
|
223
|
+
# View a recurring payment
|
224
|
+
#
|
225
|
+
# This will pull data associated with a current recurring billing
|
226
|
+
#
|
227
|
+
# ==== Parameters
|
228
|
+
#
|
229
|
+
# * <tt>rebill_id</tt> -- A string containing the rebill_id of the recurring billing that is already active (REQUIRED)
|
230
|
+
def status_recurring(rebill_id)
|
231
|
+
post = {}
|
232
|
+
requires!(rebill_id)
|
233
|
+
post[:REBILL_ID] = rebill_id
|
234
|
+
post[:TRANS_TYPE] = 'GET'
|
235
|
+
commit('rebill', 'nil', post)
|
236
|
+
end
|
237
|
+
|
238
|
+
# Update a recurring payment's details.
|
239
|
+
#
|
240
|
+
# This transaction updates an existing recurring billing
|
241
|
+
#
|
242
|
+
# ==== Options
|
243
|
+
#
|
244
|
+
# * <tt>:rebill_id</tt> -- The 12 digit rebill ID used to update a particular rebilling cycle. (REQUIRED)
|
245
|
+
# * <tt>:rebill_amount</tt> -- A string containing the new rebilling amount.
|
246
|
+
# * <tt>:rebill_next_date</tt> -- A string containing the new rebilling next date.
|
247
|
+
# * <tt>:rebill_expression</tt> -- A string containing the new rebilling expression.
|
248
|
+
# * <tt>:rebill_cycles</tt> -- A string containing the new rebilling cycles.
|
249
|
+
# * <tt>:rebill_next_amount</tt> -- A string containing the next rebilling amount to charge the customer. This ONLY affects the next scheduled charge; all other rebillings will continue at the regular (rebill_amount) amount.
|
250
|
+
# Take a look above at the recurring_payment method for similar examples on how to use.
|
251
|
+
def update_recurring(options = {})
|
252
|
+
post = {}
|
253
|
+
requires!(options, :rebill_id)
|
254
|
+
post[:REBILL_ID] = options[:rebill_id]
|
255
|
+
post[:TRANS_TYPE] = 'SET'
|
256
|
+
post[:REB_AMOUNT] = amount(options[:rebill_amount]) if !options[:rebill_amount].nil?
|
257
|
+
post[:NEXT_DATE] = options[:rebill_next_date] if !options[:rebill_next_date].nil?
|
258
|
+
post[:REB_EXPR] = options[:rebill_expression] if !options[:rebill_expression].nil?
|
259
|
+
post[:REB_CYCLES] = options[:rebill_cycles] if !options[:rebill_cycles].nil?
|
260
|
+
post[:NEXT_AMOUNT] = options[:rebill_next_amount] if !options[:rebill_next_amount].nil?
|
261
|
+
commit('rebill', 'nil', post)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Cancel a recurring payment.
|
265
|
+
#
|
266
|
+
# This transaction cancels an existing recurring billing.
|
267
|
+
#
|
268
|
+
# ==== Parameters
|
269
|
+
#
|
270
|
+
# * <tt>rebill_id</tt> -- A string containing the rebill_id of the recurring billing that you wish to cancel/stop (REQUIRED)
|
271
|
+
def cancel_recurring(rebill_id)
|
272
|
+
post = {}
|
273
|
+
requires!(rebill_id)
|
274
|
+
post[:REBILL_ID] = rebill_id
|
275
|
+
post[:TRANS_TYPE] = 'SET'
|
276
|
+
post[:STATUS] = 'stopped'
|
277
|
+
commit('rebill', 'nil', post)
|
278
|
+
end
|
279
|
+
|
280
|
+
private
|
281
|
+
|
282
|
+
def commit(action, money, fields)
|
283
|
+
fields[:AMOUNT] = amount(money) unless (fields[:TRANS_TYPE] == 'VOID' or action == 'rebill')
|
284
|
+
test? == true || @options[:test] == true ? fields[:MODE] = 'TEST' : fields[:MODE] = 'LIVE'
|
285
|
+
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
|
286
|
+
fields[:ACCOUNT_ID] = @options[:login]
|
287
|
+
data = ssl_post url, post_data(action, fields)
|
288
|
+
response = parse(data)
|
289
|
+
message = message_from(response)
|
290
|
+
test_mode = test? || fields[:MODE] == 'TEST'
|
291
|
+
if (response.has_key?('TRANS_ID'))
|
292
|
+
response_id = response['TRANS_ID'].to_s()
|
293
|
+
elsif (response.has_key?('rebill_id'))
|
294
|
+
response_id = response['rebill_id'][0]
|
295
|
+
else
|
296
|
+
response_id = response[TRANSACTION_ID]
|
297
|
+
end
|
298
|
+
response.has_key?('AVS') ? avs = response['AVS'] : avs = ''
|
299
|
+
response[AVS_RESULT_CODE] != '' ? avs = response[AVS_RESULT_CODE] : avs = ''
|
300
|
+
response.has_key?('CVV2') ? cvv2 = response['CVV2'] : cvv2 = ''
|
301
|
+
response[CARD_CODE_RESPONSE_CODE] != '' ? cvv2 = response[CARD_CODE_RESPONSE_CODE] : cvv2 = ''
|
302
|
+
Response.new(success?(response), message, response,
|
303
|
+
:test => test_mode,
|
304
|
+
:authorization => response_id,
|
305
|
+
:fraud_review => fraud_review?(response),
|
306
|
+
:avs_result => { :code => avs },
|
307
|
+
:cvv_result => cvv2
|
308
|
+
)
|
309
|
+
end
|
310
|
+
|
311
|
+
def success?(response)
|
312
|
+
if (response['STATUS'] == '1' || message_from(response) =~ /approved/ || response.has_key?('rebill_id') || response[RESPONSE_REASON_TEXT] =~ /approved/)
|
313
|
+
return true
|
314
|
+
else
|
315
|
+
return false
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
def fraud_review?(response)
|
320
|
+
response['STATUS'] == 'E' || response['STATUS'] == '0' || response[RESPONSE_REASON_TEXT] =~ /being reviewed/
|
321
|
+
end
|
322
|
+
|
323
|
+
def get_rebill_id(response)
|
324
|
+
return response['REBID'] if response_has.key?('REBID')
|
325
|
+
end
|
326
|
+
|
327
|
+
def parse(body)
|
328
|
+
fields = CGI::parse(body)
|
329
|
+
if fields.has_key?('MESSAGE') or fields.has_key?('rebill_id')
|
330
|
+
if fields.has_key?('MESSAGE')
|
331
|
+
fields['MESSAGE'][0] == "Missing ACCOUNT_ID" ? message = "The merchant login ID or password is invalid" : message = fields['MESSAGE']
|
332
|
+
fields['MESSAGE'][0] =~ /Approved/ ? message = "This transaction has been approved" : message = fields['MESSAGE'] if message == fields['MESSAGE']
|
333
|
+
fields['MESSAGE'][0] =~ /Expired/ ? message = "The credit card has expired" : message = fields['MESSAGE'] if message == fields['MESSAGE']
|
334
|
+
fields.delete('MESSAGE')
|
335
|
+
end
|
336
|
+
fields.has_key?('STATUS') ? begin status = fields['STATUS']; fields.delete('STATUS') end : status = ''
|
337
|
+
fields.has_key?('AVS') ? begin avs = fields['AVS']; fields.delete('AVS') end : avs = ''
|
338
|
+
fields.has_key?('CVV2') ? begin cvv2 = fields['CVV2']; fields.delete('CVV2') end : cvv2 = ''
|
339
|
+
fields.has_key?('MASTER_ID') ? begin trans_id = fields['MASTER_ID']; fields.delete('MASTER_ID') end : trans_id = ''
|
340
|
+
fields[:avs_result_code] = avs
|
341
|
+
fields[:card_code] = cvv2
|
342
|
+
fields[:response_code] = status
|
343
|
+
fields[:response_reason_code] = ''
|
344
|
+
fields[:response_reason_text] = message
|
345
|
+
fields[:transaction_id] = trans_id
|
346
|
+
return fields
|
347
|
+
end
|
348
|
+
# parse response if using other old API
|
349
|
+
hash = Hash.new
|
350
|
+
fields = fields.first[0].split(",")
|
351
|
+
fields.each_index do |x|
|
352
|
+
hash[x] = fields[x].tr('$','')
|
353
|
+
end
|
354
|
+
hash
|
355
|
+
end
|
356
|
+
|
357
|
+
def add_invoice(post, options)
|
358
|
+
post[:ORDER_ID] = options[:order_id] if options.has_key? :order_id
|
359
|
+
post[:INVOICE_ID] = options[:invoice] if options.has_key? :invoice
|
360
|
+
post[:invoice_num] = options[:order_id] if options.has_key? :order_id
|
361
|
+
post[:MEMO] = options[:description] if options.has_key? :description
|
362
|
+
post[:description] = options[:description] if options.has_key? :description
|
363
|
+
end
|
364
|
+
|
365
|
+
def add_creditcard(post, creditcard)
|
366
|
+
post[:PAYMENT_TYPE] = 'CREDIT'
|
367
|
+
post[:PAYMENT_ACCOUNT] = creditcard.number
|
368
|
+
post[:CARD_CVV2] = creditcard.verification_value if
|
369
|
+
creditcard.verification_value?
|
370
|
+
post[:CARD_EXPIRE] = expdate(creditcard)
|
371
|
+
post[:NAME1] = creditcard.first_name
|
372
|
+
post[:NAME2] = creditcard.last_name
|
373
|
+
end
|
374
|
+
|
375
|
+
def add_check(post, check)
|
376
|
+
post[:PAYMENT_TYPE] = 'ACH'
|
377
|
+
post[:PAYMENT_ACCOUNT] = check.account_type + ":" + check.routing_number + ":" + check.account_number
|
378
|
+
post[:NAME1] = check.first_name
|
379
|
+
post[:NAME2] = check.last_name
|
380
|
+
end
|
381
|
+
|
382
|
+
def add_customer_data(post, options)
|
383
|
+
post[:EMAIL] = options[:email] if options.has_key? :email
|
384
|
+
post[:CUSTOM_ID] = options[:customer] if options.has_key? :customer
|
385
|
+
end
|
386
|
+
|
387
|
+
def add_duplicate_window(post)
|
388
|
+
unless duplicate_window.nil?
|
389
|
+
post[:duplicate_window] = duplicate_window
|
390
|
+
post[:DUPLICATE_OVERRIDE] = duplicate_window
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def add_address(post, options)
|
395
|
+
if address = options[:billing_address] || options[:address]
|
396
|
+
post[:NAME1] = address[:first_name]
|
397
|
+
post[:NAME2] = address[:last_name]
|
398
|
+
post[:ADDR1] = address[:address1]
|
399
|
+
post[:ADDR2] = address[:address2]
|
400
|
+
post[:COMPANY_NAME] = address[:company]
|
401
|
+
post[:PHONE] = address[:phone]
|
402
|
+
post[:CITY] = address[:city]
|
403
|
+
post[:STATE] = address[:state].blank? ? 'n/a' : address[:state]
|
404
|
+
post[:ZIP] = address[:zip]
|
405
|
+
post[:COUNTRY] = address[:country]
|
406
|
+
end
|
407
|
+
if address = options[:shipping_address]
|
408
|
+
post[:NAME1] = address[:first_name]
|
409
|
+
post[:NAME2] = address[:last_name]
|
410
|
+
post[:ADDR1] = address[:address1]
|
411
|
+
post[:ADDR1] = address[:address1]
|
412
|
+
post[:COMPANY_NAME] = address[:company]
|
413
|
+
post[:PHONE] = address[:phone]
|
414
|
+
post[:ZIP] = address[:zip]
|
415
|
+
post[:CITY] = address[:city]
|
416
|
+
post[:COUNTRY] = address[:country]
|
417
|
+
post[:STATE] = address[:state].blank? ? 'n/a' : address[:state]
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def post_data(action, parameters = {})
|
422
|
+
post = {}
|
423
|
+
post[:version] = '3.0'
|
424
|
+
post[:login] = ''
|
425
|
+
post[:tran_key] = ''
|
426
|
+
post[:relay_response] = "FALSE"
|
427
|
+
post[:type] = action
|
428
|
+
post[:delim_data] = "TRUE"
|
429
|
+
post[:delim_char] = ","
|
430
|
+
post[:encap_char] = "$"
|
431
|
+
post[:card_num] = '4111111111111111'
|
432
|
+
post[:exp_date] = '1212'
|
433
|
+
post[:solution_ID] = application_id if application_id.present? && application_id != "ActiveMerchant"
|
434
|
+
request = post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
435
|
+
request
|
436
|
+
end
|
437
|
+
|
438
|
+
def message_from(results)
|
439
|
+
if results[:response_code] == 2
|
440
|
+
return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
|
441
|
+
if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
|
442
|
+
return AVSResult.messages[ results[:avs_result_code] ]
|
443
|
+
end
|
444
|
+
return (results[:response_reason_text] ? results[:response_reason_text].chomp('.') : '')
|
445
|
+
end
|
446
|
+
if results.has_key?(:response_reason_text)
|
447
|
+
return results[:response_reason_text].to_s()
|
448
|
+
end
|
449
|
+
if !results.has_key?('STATUS')
|
450
|
+
return results[RESPONSE_REASON_TEXT] ? results[RESPONSE_REASON_TEXT].chomp('.') : ''
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
def expdate(creditcard)
|
455
|
+
year = sprintf("%.4i", creditcard.year)
|
456
|
+
month = sprintf("%.2i", creditcard.month)
|
457
|
+
|
458
|
+
"#{month}#{year[-2..-1]}"
|
459
|
+
end
|
460
|
+
|
461
|
+
def calc_tps(amount, post)
|
462
|
+
post[:NAME1] = '' if post[:NAME1].nil?
|
463
|
+
digest = Digest::MD5.hexdigest(@options[:password] +
|
464
|
+
@options[:login] + post[:TRANS_TYPE] +
|
465
|
+
amount.to_s() + post[:MASTER_ID].to_s() +
|
466
|
+
post[:NAME1].to_s() + post[:PAYMENT_ACCOUNT].to_s())
|
467
|
+
return digest
|
468
|
+
end
|
469
|
+
|
470
|
+
|
471
|
+
def calc_rebill_tps(post)
|
472
|
+
digest = Digest::MD5.hexdigest(@options[:password] +
|
473
|
+
@options[:login] + post[:TRANS_TYPE] + post[:REBILL_ID][0].to_s())
|
474
|
+
return digest
|
475
|
+
end
|
476
|
+
|
477
|
+
def handle_response(response)
|
478
|
+
if ignore_http_status then
|
479
|
+
return response.body
|
480
|
+
else
|
481
|
+
case response.code.to_i
|
482
|
+
when 200...300
|
483
|
+
response.body
|
484
|
+
else
|
485
|
+
raise ResponseError.new(response)
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
end
|
491
|
+
end
|
492
|
+
end
|