yetanothernguyen-activemerchant 1.16.0 → 1.21.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +95 -0
- data/CONTRIBUTORS +29 -0
- data/lib/active_merchant/billing/credit_card.rb +105 -19
- data/lib/active_merchant/billing/credit_card_methods.rb +5 -1
- data/lib/active_merchant/billing/gateway.rb +1 -1
- data/lib/active_merchant/billing/gateways/authorize_net.rb +24 -2
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +104 -18
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +110 -4
- data/lib/active_merchant/billing/gateways/beanstream.rb +29 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +9 -4
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +4 -0
- data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
- data/lib/active_merchant/billing/gateways/certo_direct.rb +279 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +9 -9
- data/lib/active_merchant/billing/gateways/elavon.rb +2 -1
- data/lib/active_merchant/billing/gateways/epay.rb +12 -6
- data/lib/active_merchant/billing/gateways/eway_managed.rb +46 -12
- data/lib/active_merchant/billing/gateways/exact.rb +5 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +3 -3
- data/lib/active_merchant/billing/gateways/ipay88.rb +157 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +3 -3
- data/lib/active_merchant/billing/gateways/itransact.rb +450 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +1 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +4 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +244 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +94 -56
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +277 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +57 -34
- data/lib/active_merchant/billing/gateways/pay_junction.rb +6 -1
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +2 -2
- data/lib/active_merchant/billing/gateways/payflow.rb +10 -2
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +8 -5
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +43 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +93 -40
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
- data/lib/active_merchant/billing/gateways/qbms.rb +4 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +97 -22
- data/lib/active_merchant/billing/gateways/realex.rb +5 -1
- data/lib/active_merchant/billing/gateways/samurai.rb +121 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +136 -49
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +1 -1
- data/lib/active_merchant/billing/gateways/skip_jack.rb +7 -2
- data/lib/active_merchant/billing/gateways/stripe.rb +51 -19
- data/lib/active_merchant/billing/gateways/usa_epay.rb +13 -184
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1496 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +206 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +2 -2
- data/lib/active_merchant/billing/gateways/viaklix.rb +1 -1
- data/lib/active_merchant/billing/gateways/worldpay.rb +1 -1
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +6 -2
- data/lib/active_merchant/billing/integrations/authorize_net_sim/helper.rb +228 -0
- data/lib/active_merchant/billing/integrations/authorize_net_sim/notification.rb +340 -0
- data/lib/active_merchant/billing/integrations/authorize_net_sim.rb +38 -0
- data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +4 -4
- data/lib/active_merchant/billing/integrations/dwolla/helper.rb +31 -0
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +55 -0
- data/lib/active_merchant/billing/integrations/dwolla/return.rb +38 -0
- data/lib/active_merchant/billing/integrations/dwolla.rb +30 -0
- data/lib/active_merchant/billing/integrations/helper.rb +19 -2
- data/lib/active_merchant/billing/integrations/ipay88/helper.rb +120 -0
- data/lib/active_merchant/billing/integrations/ipay88/return.rb +121 -0
- data/lib/active_merchant/billing/integrations/ipay88.rb +40 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +1 -1
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +100 -0
- data/lib/active_merchant/billing/integrations/payflow_link/notification.rb +78 -0
- data/lib/active_merchant/billing/integrations/payflow_link.rb +21 -0
- data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +4 -4
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +18 -2
- data/lib/active_merchant/billing/integrations/two_checkout.rb +1 -2
- data/lib/active_merchant/railtie.rb +7 -7
- data/lib/active_merchant/railtie.rb.orig +19 -0
- data/lib/active_merchant/version.rb +1 -1
- data/lib/active_merchant.rb +23 -10
- data/lib/active_merchant.rb.orig +78 -0
- metadata +147 -63
- data/lib/active_merchant/common/connection.rb +0 -177
- data/lib/active_merchant/common/country.rb +0 -328
- data/lib/active_merchant/common/error.rb +0 -26
- data/lib/active_merchant/common/post_data.rb +0 -24
- data/lib/active_merchant/common/posts_data.rb +0 -63
- data/lib/active_merchant/common/requires_parameters.rb +0 -16
- data/lib/active_merchant/common/utils.rb +0 -22
- data/lib/active_merchant/common/validateable.rb +0 -81
- data/lib/active_merchant/common.rb +0 -14
- data/lib/certs/cacert.pem +0 -7815
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
1
2
|
module ActiveMerchant #:nodoc:
|
2
3
|
module Billing #:nodoc:
|
3
4
|
# ==== Customer Information Manager (CIM)
|
@@ -39,6 +40,7 @@ module ActiveMerchant #:nodoc:
|
|
39
40
|
:create_customer_payment_profile => 'createCustomerPaymentProfile',
|
40
41
|
:create_customer_shipping_address => 'createCustomerShippingAddress',
|
41
42
|
:get_customer_profile => 'getCustomerProfile',
|
43
|
+
:get_customer_profile_ids => 'getCustomerProfileIds',
|
42
44
|
:get_customer_payment_profile => 'getCustomerPaymentProfile',
|
43
45
|
:get_customer_shipping_address => 'getCustomerShippingAddress',
|
44
46
|
:delete_customer_profile => 'deleteCustomerProfile',
|
@@ -75,7 +77,8 @@ module ActiveMerchant #:nodoc:
|
|
75
77
|
|
76
78
|
ECHECK_TYPES = {
|
77
79
|
:ccd => 'CCD',
|
78
|
-
:ppd => 'PPD'
|
80
|
+
:ppd => 'PPD',
|
81
|
+
:web => 'WEB'
|
79
82
|
}
|
80
83
|
|
81
84
|
self.homepage_url = 'http://www.authorize.net/'
|
@@ -93,6 +96,7 @@ module ActiveMerchant #:nodoc:
|
|
93
96
|
# * <tt>:login</tt> -- The Authorize.Net API Login ID (REQUIRED)
|
94
97
|
# * <tt>:password</tt> -- The Authorize.Net Transaction Key. (REQUIRED)
|
95
98
|
# * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
|
99
|
+
# * <tt>:delimiter</tt> -- The delimiter used in the direct response. Default is ',' (comma).
|
96
100
|
# Otherwise, perform transactions against the production server.
|
97
101
|
def initialize(options = {})
|
98
102
|
requires!(options, :login, :password)
|
@@ -107,11 +111,28 @@ module ActiveMerchant #:nodoc:
|
|
107
111
|
# It is *CRITICAL* that you save this ID. There is no way to retrieve this through the API. You will not
|
108
112
|
# be able to create another Customer Profile with the same information.
|
109
113
|
#
|
114
|
+
#
|
115
|
+
#
|
110
116
|
# ==== Options
|
117
|
+
#
|
118
|
+
# * <tt>:profile</tt> -- A hash containing at least one of the CONDITIONAL profile options below (REQUIRED)
|
119
|
+
#
|
120
|
+
# ==== Profile
|
111
121
|
#
|
112
|
-
#
|
122
|
+
# * <tt>:email</tt> -- Email address associated with the customer profile (CONDITIONAL)
|
123
|
+
# * <tt>:description</tt> -- Description of the customer or customer profile (CONDITIONAL)
|
124
|
+
# * <tt>:merchant_customer_id</tt> -- Merchant assigned ID for the customer (CONDITIONAL)
|
125
|
+
# * <tt>:payment_profile</tt> -- A hash containing the elements of the new payment profile (optional)
|
126
|
+
#
|
127
|
+
# ==== Payment Profile
|
128
|
+
#
|
129
|
+
# * <tt>:payment</tt> -- A hash containing information on payment. Either :credit_card or :bank_account (optional)
|
113
130
|
def create_customer_profile(options)
|
114
|
-
|
131
|
+
requires!(options, :profile)
|
132
|
+
requires!(options[:profile], :email) unless options[:profile][:merchant_customer_id] || options[:profile][:description]
|
133
|
+
requires!(options[:profile], :description) unless options[:profile][:email] || options[:profile][:merchant_customer_id]
|
134
|
+
requires!(options[:profile], :merchant_customer_id) unless options[:profile][:description] || options[:profile][:email]
|
135
|
+
|
115
136
|
request = build_request(:create_customer_profile, options)
|
116
137
|
commit(:create_customer_profile, request)
|
117
138
|
end
|
@@ -203,6 +224,11 @@ module ActiveMerchant #:nodoc:
|
|
203
224
|
commit(:get_customer_profile, request)
|
204
225
|
end
|
205
226
|
|
227
|
+
def get_customer_profile_ids(options = {})
|
228
|
+
request = build_request(:get_customer_profile_ids, options)
|
229
|
+
commit(:get_customer_profile_ids, request)
|
230
|
+
end
|
231
|
+
|
206
232
|
# Retrieve a customer payment profile for an existing customer profile.
|
207
233
|
#
|
208
234
|
# Returns a Response whose params hash contains all the payment profile information. Sensitive information such as credit card
|
@@ -332,7 +358,11 @@ module ActiveMerchant #:nodoc:
|
|
332
358
|
# - :type = (:void, :refund, :prior_auth_capture) (REQUIRED)
|
333
359
|
# - :type = (:auth_only, :capture_only, :auth_capture) (NOT USED)
|
334
360
|
#
|
335
|
-
# * <tt
|
361
|
+
# * <tt>:card_code</tt> -- CVV/CCV code (OPTIONAL)
|
362
|
+
# - :type = (:void, :refund, :prior_auth_capture) (NOT USED)
|
363
|
+
# - :type = (:auth_only, :capture_only, :auth_capture) (OPTIONAL)
|
364
|
+
#
|
365
|
+
# * <tt>:customer_shipping_address_id</tt> -- Payment gateway assigned ID associated with the customer shipping address (CONDITIONAL)
|
336
366
|
# - :type = (:void, :refund) (OPTIONAL)
|
337
367
|
# - :type = (:auth_only, :capture_only, :auth_capture) (NOT USED)
|
338
368
|
# - :type = (:prior_auth_capture) (OPTIONAL)
|
@@ -383,6 +413,10 @@ module ActiveMerchant #:nodoc:
|
|
383
413
|
#
|
384
414
|
# * <tt>:bank_routing_number_masked</tt> -- The last four gidits of the routing number to be refunded (CONDITIONAL - must be used with :bank_account_number_masked)
|
385
415
|
# * <tt>:bank_account_number_masked</tt> -- The last four digis of the bank account number to be refunded, Ex. XXXX1234 (CONDITIONAL - must be used with :bank_routing_number_masked)
|
416
|
+
#
|
417
|
+
# * <tt>:tax</tt> - A hash containing tax information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
|
418
|
+
# * <tt>:duty</tt> - A hash containting duty information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
|
419
|
+
# * <tt>:shipping</tt> - A hash containing shipping information for the refund (OPTIONAL - <tt>:amount</tt>, <tt>:name</tt> (31 characters), <tt>:description</tt> (255 characters))
|
386
420
|
def create_customer_profile_transaction_for_refund(options)
|
387
421
|
requires!(options, :transaction)
|
388
422
|
options[:transaction][:type] = :refund
|
@@ -424,8 +458,9 @@ module ActiveMerchant #:nodoc:
|
|
424
458
|
#
|
425
459
|
# * <tt>:customer_profile_id</tt> -- The Customer Profile ID of the customer to use in this transaction. (REQUIRED)
|
426
460
|
# * <tt>:customer_payment_profile_id</tt> -- The Customer Payment Profile ID of the Customer Payment Profile to be verified. (REQUIRED)
|
427
|
-
# * <tt>:customer_address_id</tt> -- The Customer Address ID of the Customer Shipping Address to be verified.
|
428
|
-
# * <tt>:
|
461
|
+
# * <tt>:customer_address_id</tt> -- The Customer Address ID of the Customer Shipping Address to be verified. (OPTIONAL)
|
462
|
+
# * <tt>:card_code</tt> -- If the payment profile is a credit card, the CCV/CVV code to validate with (OPTIONAL)
|
463
|
+
# * <tt>:validation_mode</tt> -- <tt>:live</tt> or <tt>:test</tt> In Test Mode, only field validation is performed. (REQUIRED
|
429
464
|
# In Live Mode, a transaction is generated and submitted to the processor with the amount of $0.01. If successful, the transaction is immediately voided. (REQUIRED)
|
430
465
|
def validate_customer_payment_profile(options)
|
431
466
|
requires!(options, :customer_profile_id, :customer_payment_profile_id, :validation_mode)
|
@@ -466,6 +501,14 @@ module ActiveMerchant #:nodoc:
|
|
466
501
|
def build_create_customer_profile_request(xml, options)
|
467
502
|
add_profile(xml, options[:profile])
|
468
503
|
|
504
|
+
xml.tag!('validationMode', CIM_VALIDATION_MODES[options[:validation_mode]]) if options[:validation_mode]
|
505
|
+
|
506
|
+
if options.has_key?(:payment_profile)
|
507
|
+
xml.tag!('paymentProfile') do
|
508
|
+
add_payment_profile(xml, options[:payment_profile])
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
469
512
|
xml.target!
|
470
513
|
end
|
471
514
|
|
@@ -513,6 +556,10 @@ module ActiveMerchant #:nodoc:
|
|
513
556
|
xml.target!
|
514
557
|
end
|
515
558
|
|
559
|
+
def build_get_customer_profile_ids_request(xml, options)
|
560
|
+
xml.target!
|
561
|
+
end
|
562
|
+
|
516
563
|
def build_get_customer_payment_profile_request(xml, options)
|
517
564
|
xml.tag!('customerProfileId', options[:customer_profile_id])
|
518
565
|
xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id])
|
@@ -564,6 +611,7 @@ module ActiveMerchant #:nodoc:
|
|
564
611
|
xml.tag!('customerProfileId', options[:customer_profile_id])
|
565
612
|
xml.tag!('customerPaymentProfileId', options[:customer_payment_profile_id])
|
566
613
|
xml.tag!('customerShippingAddressId', options[:customer_address_id]) if options[:customer_address_id]
|
614
|
+
tag_unless_blank(xml, 'cardCode', options[:card_code])
|
567
615
|
xml.tag!('validationMode', CIM_VALIDATION_MODES[options[:validation_mode]]) if options[:validation_mode]
|
568
616
|
|
569
617
|
xml.target!
|
@@ -606,7 +654,7 @@ module ActiveMerchant #:nodoc:
|
|
606
654
|
tag_unless_blank(xml,'customerShippingAddressId', transaction[:customer_shipping_address_id])
|
607
655
|
xml.tag!('transId', transaction[:trans_id])
|
608
656
|
when :refund
|
609
|
-
#TODO - add
|
657
|
+
#TODO - add lineItems and extraOptions fields
|
610
658
|
xml.tag!('amount', transaction[:amount])
|
611
659
|
tag_unless_blank(xml, 'customerProfileId', transaction[:customer_profile_id])
|
612
660
|
tag_unless_blank(xml, 'customerPaymentProfileId', transaction[:customer_payment_profile_id])
|
@@ -615,6 +663,9 @@ module ActiveMerchant #:nodoc:
|
|
615
663
|
tag_unless_blank(xml, 'bankRoutingNumberMasked', transaction[:bank_routing_number_masked])
|
616
664
|
tag_unless_blank(xml, 'bankAccountNumberMasked', transaction[:bank_account_number_masked])
|
617
665
|
xml.tag!('transId', transaction[:trans_id])
|
666
|
+
add_tax(xml, transaction[:tax]) if transaction[:tax]
|
667
|
+
add_duty(xml, transaction[:duty]) if transaction[:duty]
|
668
|
+
add_shipping(xml, transaction[:shipping]) if transaction[:shipping]
|
618
669
|
when :prior_auth_capture
|
619
670
|
xml.tag!('amount', transaction[:amount])
|
620
671
|
xml.tag!('transId', transaction[:trans_id])
|
@@ -623,12 +674,37 @@ module ActiveMerchant #:nodoc:
|
|
623
674
|
xml.tag!('customerProfileId', transaction[:customer_profile_id])
|
624
675
|
xml.tag!('customerPaymentProfileId', transaction[:customer_payment_profile_id])
|
625
676
|
xml.tag!('approvalCode', transaction[:approval_code]) if transaction[:type] == :capture_only
|
677
|
+
tag_unless_blank(xml, 'cardCode', transaction[:card_code])
|
626
678
|
end
|
627
|
-
add_order(xml, transaction[:order]) if transaction[:order]
|
679
|
+
add_order(xml, transaction[:order]) if transaction[:order].present?
|
628
680
|
end
|
629
681
|
end
|
630
682
|
end
|
683
|
+
|
684
|
+
def add_tax(xml, tax)
|
685
|
+
xml.tag!('tax') do
|
686
|
+
xml.tag!('amount', tax[:amount]) if tax[:amount]
|
687
|
+
xml.tag!('name', tax[:name]) if tax[:name]
|
688
|
+
xml.tag!('description', tax[:description]) if tax[:description]
|
689
|
+
end
|
690
|
+
end
|
691
|
+
|
692
|
+
def add_duty(xml, duty)
|
693
|
+
xml.tag!('duty') do
|
694
|
+
xml.tag!('amount', duty[:amount]) if duty[:amount]
|
695
|
+
xml.tag!('name', duty[:name]) if duty[:name]
|
696
|
+
xml.tag!('description', duty[:description]) if duty[:description]
|
697
|
+
end
|
698
|
+
end
|
631
699
|
|
700
|
+
def add_shipping(xml, shipping)
|
701
|
+
xml.tag!('shipping') do
|
702
|
+
xml.tag!('amount', shipping[:amount]) if shipping[:amount]
|
703
|
+
xml.tag!('name', shipping[:name]) if shipping[:name]
|
704
|
+
xml.tag!('description', shipping[:description]) if shipping[:description]
|
705
|
+
end
|
706
|
+
end
|
707
|
+
|
632
708
|
def add_order(xml, order)
|
633
709
|
xml.tag!('order') do
|
634
710
|
xml.tag!('invoiceNumber', order[:invoice_number]) if order[:invoice_number]
|
@@ -702,6 +778,10 @@ module ActiveMerchant #:nodoc:
|
|
702
778
|
xml.tag!('cardNumber', credit_card.number)
|
703
779
|
# The expiration date of the credit card used for the subscription
|
704
780
|
xml.tag!('expirationDate', expdate(credit_card))
|
781
|
+
# Note that Authorize.net does not save CVV codes as part of the
|
782
|
+
# payment profile. Any transactions/validations after the payment
|
783
|
+
# profile is created that wish to use CVV verification must pass
|
784
|
+
# the CVV code to authorize.net again.
|
705
785
|
xml.tag!('cardCode', credit_card.verification_value) if credit_card.verification_value?
|
706
786
|
end
|
707
787
|
end
|
@@ -756,24 +836,23 @@ module ActiveMerchant #:nodoc:
|
|
756
836
|
message = response_params['messages']['message']['text']
|
757
837
|
test_mode = test? || message =~ /Test Mode/
|
758
838
|
success = response_params['messages']['result_code'] == 'Ok'
|
839
|
+
response_params['direct_response'] = parse_direct_response(response_params['direct_response']) if response_params['direct_response']
|
840
|
+
transaction_id = response_params['direct_response']['transaction_id'] if response_params['direct_response']
|
759
841
|
|
760
|
-
|
842
|
+
Response.new(success, message, response_params,
|
761
843
|
:test => test_mode,
|
762
|
-
:authorization => response_params['customer_profile_id'] || (response_params['profile'] ? response_params['profile']['customer_profile_id'] : nil)
|
844
|
+
:authorization => transaction_id || response_params['customer_profile_id'] || (response_params['profile'] ? response_params['profile']['customer_profile_id'] : nil)
|
763
845
|
)
|
764
|
-
|
765
|
-
response.params['direct_response'] = parse_direct_response(response) if response.params['direct_response']
|
766
|
-
response
|
767
846
|
end
|
768
847
|
|
769
848
|
def tag_unless_blank(xml, tag_name, data)
|
770
849
|
xml.tag!(tag_name, data) unless data.blank? || data.nil?
|
771
850
|
end
|
772
851
|
|
773
|
-
def parse_direct_response(
|
774
|
-
|
775
|
-
|
776
|
-
|
852
|
+
def parse_direct_response(params)
|
853
|
+
delimiter = @options[:delimiter] || ','
|
854
|
+
direct_response = {'raw' => params}
|
855
|
+
direct_response_fields = params.split(delimiter)
|
777
856
|
direct_response.merge(
|
778
857
|
{
|
779
858
|
'response_code' => direct_response_fields[0],
|
@@ -815,7 +894,14 @@ module ActiveMerchant #:nodoc:
|
|
815
894
|
'purchase_order_number' => direct_response_fields[36],
|
816
895
|
'md5_hash' => direct_response_fields[37],
|
817
896
|
'card_code' => direct_response_fields[38],
|
818
|
-
'cardholder_authentication_verification_response' => direct_response_fields[39]
|
897
|
+
'cardholder_authentication_verification_response' => direct_response_fields[39],
|
898
|
+
# The following direct response fields are only available in version 3.1 of the
|
899
|
+
# transaction response. Check your merchant account settings for details.
|
900
|
+
'account_number' => direct_response_fields[50] || '',
|
901
|
+
'card_type' => direct_response_fields[51] || '',
|
902
|
+
'split_tender_id' => direct_response_fields[52] || '',
|
903
|
+
'requested_amount' => direct_response_fields[53] || '',
|
904
|
+
'balance_on_card' => direct_response_fields[54] || '',
|
819
905
|
}
|
820
906
|
)
|
821
907
|
end
|
@@ -2,6 +2,7 @@ module ActiveMerchant #:nodoc:
|
|
2
2
|
module Billing #:nodoc:
|
3
3
|
module BeanstreamCore
|
4
4
|
URL = 'https://www.beanstream.com/scripts/process_transaction.asp'
|
5
|
+
RECURRING_URL = 'https://www.beanstream.com/scripts/recurring_billing.asp'
|
5
6
|
SECURE_PROFILE_URL = 'https://www.beanstream.com/scripts/payment_profile.asp'
|
6
7
|
SP_SERVICE_VERSION = '1.1'
|
7
8
|
|
@@ -37,6 +38,27 @@ module ActiveMerchant #:nodoc:
|
|
37
38
|
'9' => 'I'
|
38
39
|
}
|
39
40
|
|
41
|
+
PERIODS = {
|
42
|
+
:days => 'D',
|
43
|
+
:weeks => 'W',
|
44
|
+
:months => 'M',
|
45
|
+
:years => 'Y'
|
46
|
+
}
|
47
|
+
|
48
|
+
PERIODICITIES = {
|
49
|
+
:daily => [:days, 1],
|
50
|
+
:weekly => [:weeks, 1],
|
51
|
+
:biweekly => [:weeks, 2],
|
52
|
+
:monthly => [:months, 1],
|
53
|
+
:bimonthly => [:months, 2],
|
54
|
+
:yearly => [:years, 1]
|
55
|
+
}
|
56
|
+
|
57
|
+
RECURRING_OPERATION = {
|
58
|
+
:update => 'M',
|
59
|
+
:cancel => 'C'
|
60
|
+
}
|
61
|
+
|
40
62
|
def self.included(base)
|
41
63
|
base.default_currency = 'CAD'
|
42
64
|
|
@@ -90,7 +112,11 @@ module ActiveMerchant #:nodoc:
|
|
90
112
|
|
91
113
|
private
|
92
114
|
def purchase_action(source)
|
93
|
-
(
|
115
|
+
if source.is_a?(Check)
|
116
|
+
:check_purchase
|
117
|
+
else
|
118
|
+
:purchase
|
119
|
+
end
|
94
120
|
end
|
95
121
|
|
96
122
|
def void_action(original_transaction_type)
|
@@ -203,11 +229,66 @@ module ActiveMerchant #:nodoc:
|
|
203
229
|
post[:status] = options[:status]
|
204
230
|
end
|
205
231
|
|
232
|
+
def add_recurring_amount(post, money)
|
233
|
+
post[:amount] = amount(money)
|
234
|
+
end
|
235
|
+
|
236
|
+
def add_recurring_invoice(post, options)
|
237
|
+
post[:rbApplyTax1] = options[:apply_tax1]
|
238
|
+
end
|
239
|
+
|
240
|
+
def add_recurring_operation_type(post, operation)
|
241
|
+
post[:operationType] = RECURRING_OPERATION[operation]
|
242
|
+
end
|
243
|
+
|
244
|
+
def add_recurring_service(post, options)
|
245
|
+
post[:serviceVersion] = '1.0'
|
246
|
+
post[:merchantId] = @options[:login]
|
247
|
+
post[:passCode] = @options[:recurring_api_key]
|
248
|
+
post[:rbAccountId] = options[:account_id]
|
249
|
+
end
|
250
|
+
|
251
|
+
def add_recurring_type(post, options)
|
252
|
+
# XXX requires!
|
253
|
+
post[:trnRecurring] = 1
|
254
|
+
period, increment = interval(options)
|
255
|
+
post[:rbBillingPeriod] = PERIODS[period]
|
256
|
+
post[:rbBillingIncrement] = increment
|
257
|
+
|
258
|
+
if options.include? :start_date
|
259
|
+
post[:rbCharge] = 0
|
260
|
+
post[:rbFirstBilling] = options[:start_date].strftime('%m%d%Y')
|
261
|
+
end
|
262
|
+
|
263
|
+
if count = options[:occurrences] || options[:payments]
|
264
|
+
post[:rbExpiry] = (options[:start_date] || Date.current).advance(period => count).strftime('%m%d%Y')
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def interval(options)
|
269
|
+
if options.include? :periodicity
|
270
|
+
requires!(options, [:periodicity, *PERIODICITIES.keys])
|
271
|
+
PERIODICITIES[options[:periodicity]]
|
272
|
+
elsif options.include? :interval
|
273
|
+
interval = options[:interval]
|
274
|
+
if interval.respond_to? :parts
|
275
|
+
parts = interval.parts
|
276
|
+
raise ArgumentError.new("Cannot recur with mixed interval (#{interval}). Use only one of: days, weeks, months or years") if parts.length > 1
|
277
|
+
parts.first
|
278
|
+
elsif interval.kind_of? Hash
|
279
|
+
requires!(interval, :unit)
|
280
|
+
unit, length = interval.values_at(:unit, :length)
|
281
|
+
length ||= 1
|
282
|
+
[unit, length]
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
206
287
|
def parse(body)
|
207
288
|
results = {}
|
208
289
|
if !body.nil?
|
209
290
|
body.split(/&/).each do |pair|
|
210
|
-
key,val = pair.split(/=/)
|
291
|
+
key, val = pair.split(/=/)
|
211
292
|
results[key.to_sym] = val.nil? ? nil : CGI.unescape(val)
|
212
293
|
end
|
213
294
|
end
|
@@ -221,11 +302,22 @@ module ActiveMerchant #:nodoc:
|
|
221
302
|
|
222
303
|
results
|
223
304
|
end
|
224
|
-
|
305
|
+
|
306
|
+
def recurring_parse(data)
|
307
|
+
REXML::Document.new(data).root.elements.to_a.inject({}) do |response, element|
|
308
|
+
response[element.name.to_sym] = element.text
|
309
|
+
response
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
225
313
|
def commit(params, use_profile_api = false)
|
226
314
|
post(post_data(params,use_profile_api),use_profile_api)
|
227
315
|
end
|
228
316
|
|
317
|
+
def recurring_commit(params)
|
318
|
+
recurring_post(post_data(params, false))
|
319
|
+
end
|
320
|
+
|
229
321
|
def post(data, use_profile_api=nil)
|
230
322
|
response = parse(ssl_post((use_profile_api ? SECURE_PROFILE_URL : URL), data))
|
231
323
|
response[:customer_vault_id] = response[:customerCode] if response[:customerCode]
|
@@ -236,7 +328,12 @@ module ActiveMerchant #:nodoc:
|
|
236
328
|
:avs_result => { :code => (AVS_CODES.include? response[:avsId]) ? AVS_CODES[response[:avsId]] : response[:avsId] }
|
237
329
|
)
|
238
330
|
end
|
239
|
-
|
331
|
+
|
332
|
+
def recurring_post(data)
|
333
|
+
response = recurring_parse(ssl_post(RECURRING_URL, data))
|
334
|
+
build_response(recurring_success?(response), recurring_message_from(response), response)
|
335
|
+
end
|
336
|
+
|
240
337
|
def authorization_from(response)
|
241
338
|
"#{response[:trnId]};#{response[:trnAmount]};#{response[:trnType]}"
|
242
339
|
end
|
@@ -245,10 +342,18 @@ module ActiveMerchant #:nodoc:
|
|
245
342
|
response[:messageText] || response[:responseMessage]
|
246
343
|
end
|
247
344
|
|
345
|
+
def recurring_message_from(response)
|
346
|
+
response[:message]
|
347
|
+
end
|
348
|
+
|
248
349
|
def success?(response)
|
249
350
|
response[:responseType] == 'R' || response[:trnApproved] == '1' || response[:responseCode] == '1'
|
250
351
|
end
|
251
352
|
|
353
|
+
def recurring_success?(response)
|
354
|
+
response[:code] == '1'
|
355
|
+
end
|
356
|
+
|
252
357
|
def add_source(post, source)
|
253
358
|
if source.is_a?(String) or source.is_a?(Integer)
|
254
359
|
post[:customerCode] = source
|
@@ -276,6 +381,7 @@ module ActiveMerchant #:nodoc:
|
|
276
381
|
|
277
382
|
params.reject{|k, v| v.blank?}.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
|
278
383
|
end
|
384
|
+
|
279
385
|
end
|
280
386
|
end
|
281
387
|
end
|
@@ -19,7 +19,6 @@ module ActiveMerchant #:nodoc:
|
|
19
19
|
# To learn more about storing credit cards with the Beanstream gateway, please read the BEAN_Payment_Profiles.pdf (I had to phone BeanStream to request it.)
|
20
20
|
#
|
21
21
|
# == Notes
|
22
|
-
# * Recurring billing is not yet implemented.
|
23
22
|
# * Adding of order products information is not implemented.
|
24
23
|
# * Ensure that country and province data is provided as a code such as "CA", "US", "QC".
|
25
24
|
# * login is the Beanstream merchant ID, username and password should be enabled in your Beanstream account and passed in using the <tt>:user</tt> and <tt>:password</tt> options.
|
@@ -95,6 +94,35 @@ module ActiveMerchant #:nodoc:
|
|
95
94
|
commit(post)
|
96
95
|
end
|
97
96
|
|
97
|
+
def recurring(money, source, options = {})
|
98
|
+
post = {}
|
99
|
+
add_amount(post, money)
|
100
|
+
add_invoice(post, options)
|
101
|
+
add_credit_card(post, source)
|
102
|
+
add_address(post, options)
|
103
|
+
add_transaction_type(post, purchase_action(source))
|
104
|
+
add_recurring_type(post, options)
|
105
|
+
commit(post)
|
106
|
+
end
|
107
|
+
|
108
|
+
def update_recurring(amount, source, options = {})
|
109
|
+
post = {}
|
110
|
+
add_recurring_amount(post, amount)
|
111
|
+
add_recurring_invoice(post, options)
|
112
|
+
add_credit_card(post, source)
|
113
|
+
add_address(post, options)
|
114
|
+
add_recurring_operation_type(post, :update)
|
115
|
+
add_recurring_service(post, options)
|
116
|
+
recurring_commit(post)
|
117
|
+
end
|
118
|
+
|
119
|
+
def cancel_recurring(options = {})
|
120
|
+
post = {}
|
121
|
+
add_recurring_operation_type(post, :cancel)
|
122
|
+
add_recurring_service(post, options)
|
123
|
+
recurring_commit(post)
|
124
|
+
end
|
125
|
+
|
98
126
|
def interac
|
99
127
|
@interac ||= BeanstreamInteracGateway.new(@options)
|
100
128
|
end
|
@@ -18,10 +18,11 @@ module ActiveMerchant #:nodoc:
|
|
18
18
|
def initialize(options = {})
|
19
19
|
requires!(options, :merchant_id, :public_key, :private_key)
|
20
20
|
@options = options
|
21
|
+
@merchant_account_id = options[:merchant_account_id]
|
21
22
|
Braintree::Configuration.merchant_id = options[:merchant_id]
|
22
23
|
Braintree::Configuration.public_key = options[:public_key]
|
23
24
|
Braintree::Configuration.private_key = options[:private_key]
|
24
|
-
Braintree::Configuration.environment = test? ? :sandbox : :production
|
25
|
+
Braintree::Configuration.environment = (options[:environment] || (test? ? :sandbox : :production)).to_sym
|
25
26
|
Braintree::Configuration.logger.level = Logger::ERROR if Braintree::Configuration.logger
|
26
27
|
Braintree::Configuration.custom_user_agent = "ActiveMerchant #{ActiveMerchant::VERSION}"
|
27
28
|
super
|
@@ -175,7 +176,11 @@ module ActiveMerchant #:nodoc:
|
|
175
176
|
:postal_match => result.transaction.avs_postal_code_response_code
|
176
177
|
}
|
177
178
|
response_options[:cvv_result] = result.transaction.cvv_response_code
|
178
|
-
|
179
|
+
if result.transaction.status == "gateway_rejected"
|
180
|
+
message = "Transaction declined - gateway rejected"
|
181
|
+
else
|
182
|
+
message = "#{result.transaction.processor_response_code} #{result.transaction.processor_response_text}"
|
183
|
+
end
|
179
184
|
else
|
180
185
|
message = message_from_result(result)
|
181
186
|
end
|
@@ -276,8 +281,8 @@ module ActiveMerchant #:nodoc:
|
|
276
281
|
:submit_for_settlement => options[:submit_for_settlement]
|
277
282
|
}
|
278
283
|
}
|
279
|
-
if options
|
280
|
-
parameters[:merchant_account_id] =
|
284
|
+
if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
|
285
|
+
parameters[:merchant_account_id] = merchant_account_id
|
281
286
|
end
|
282
287
|
if credit_card_or_vault_id.is_a?(String) || credit_card_or_vault_id.is_a?(Integer)
|
283
288
|
parameters[:customer_id] = credit_card_or_vault_id
|
@@ -11,6 +11,10 @@ module ActiveMerchant #:nodoc:
|
|
11
11
|
def api_url
|
12
12
|
'https://secure.braintreepaymentgateway.com/api/transact.php'
|
13
13
|
end
|
14
|
+
|
15
|
+
def add_processor(post, options)
|
16
|
+
post[:processor_id] = options[:processor] unless options[:processor].nil?
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Billing #:nodoc:
|
3
|
+
class CardSaveGateway < IridiumGateway
|
4
|
+
#CardSave lets you handle failovers on payments by providing 3 gateways in case one happens to be down
|
5
|
+
#URLS = ['https://gw1.cardsaveonlinepayments.com:4430/','https://gw2.cardsaveonlinepayments.com:4430/','https://gw3.cardsaveonlinepayments.com:4430/']
|
6
|
+
|
7
|
+
self.money_format = :cents
|
8
|
+
self.default_currency = 'GBP'
|
9
|
+
self.supported_cardtypes = [ :visa, :switch, :maestro, :master, :solo, :american_express, :jcb ]
|
10
|
+
self.supported_countries = [ 'GB' ]
|
11
|
+
self.homepage_url = 'http://www.cardsave.net/'
|
12
|
+
self.display_name = 'CardSave'
|
13
|
+
|
14
|
+
def initialize(options={})
|
15
|
+
super
|
16
|
+
@test_url = 'https://gw1.cardsaveonlinepayments.com:4430/'
|
17
|
+
@live_url = 'https://gw1.cardsaveonlinepayments.com:4430/'
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|