yetanothernguyen-activemerchant 1.16.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +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
|
+
|