activemerchant 1.22.0 → 1.23.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.tar.gz.sig +0 -0
- data/CHANGELOG +19 -5
- data/CONTRIBUTORS +4 -0
- data/README.md +1 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +2 -2
- data/lib/active_merchant/billing/gateways/cyber_source.rb +106 -342
- data/lib/active_merchant/billing/gateways/litle.rb +275 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +1 -1
- data/lib/active_merchant/billing/gateways/payment_express.rb +59 -12
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -2
- data/lib/active_merchant/billing/integrations/two_checkout.rb +1 -1
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +51 -34
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +71 -46
- data/lib/active_merchant/version.rb +1 -1
- metadata +168 -127
- metadata.gz.sig +2 -3
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
2
2
|
|
3
|
+
== Version 1.23.0 (May 23, 2012)
|
4
|
+
|
5
|
+
* Add Litle gateway [GregDrake]
|
6
|
+
* PaymentExpress gateway: add support for BillingId and DpsBillingId for token [mikel]
|
7
|
+
* 2checkout integration: Add ability to auto settle [craigchristenson]
|
8
|
+
* 2checkout integration: Switch default mode to single page [craigchristenson]
|
9
|
+
* Cybersource: Revert - Add retrieve method to pull details on a
|
10
|
+
stored card [jduff]
|
11
|
+
* Cybersource: Revert - Add recurring payment support [jduff]
|
12
|
+
* PaymentExpress: add Cvc2Presence flag when submitting verification
|
13
|
+
value [jduff]
|
14
|
+
* SecurePayAU: fix CreditCard check [jduff]
|
15
|
+
* Barclays: fix order capture [csaunders/ntalbott/jduff]
|
16
|
+
|
3
17
|
== Version 1.22.0 (May 17, 2012)
|
4
18
|
|
5
19
|
* Remove version restriction for money gem [ylansegal]
|
@@ -666,7 +680,7 @@
|
|
666
680
|
* Fix errors on base of CreditCard [josh.bassett]
|
667
681
|
* Update product to use Rubigen instead of stolen Rails generator [cody]
|
668
682
|
* Mimic directory structure of unit tests in remote tests [cody]
|
669
|
-
* Restructure the location of the remote tests [cody]
|
683
|
+
* Restructure the location of the remote tests [cody]
|
670
684
|
* Ensure DataCash order_id is limited to 30 characters [cody]
|
671
685
|
* Return the pretty messages from PayJunction based on the return code [cody]
|
672
686
|
* make CreditCard.require_verification_value = true the default [cody]
|
@@ -732,7 +746,7 @@
|
|
732
746
|
* Enhance credit card error messages [manfred]
|
733
747
|
* Use HashWithIndifferentAccess for CreditCard for compatibility with Rails applications [michael.j.mangino]
|
734
748
|
* Fix nil exception when no response reason text is found in Authorize.net [cody]
|
735
|
-
* Add support for PayJunction [Matt Sanders]
|
749
|
+
* Add support for PayJunction [Matt Sanders]
|
736
750
|
* 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.
|
737
751
|
* Remove switch patterns from card detection that were eliminated on July 1, 2007 [cody]
|
738
752
|
* Format the issue number in Payflow requests to always be 2 digits [cody]
|
@@ -770,7 +784,7 @@
|
|
770
784
|
* Update and test PslCardGateway [cody]
|
771
785
|
* Add Laser card type [cody]
|
772
786
|
* Update Nochex documentation [cody]
|
773
|
-
* Sanitize the Realex order_id [cody]
|
787
|
+
* Sanitize the Realex order_id [cody]
|
774
788
|
* Add support for Irish Realex payment gateway [John Ward, cody]
|
775
789
|
* Move credit_card helper method to the test_helper [cody]
|
776
790
|
* Update PayflowExpressResponse to match the interface of the PayflowExpressResponse. Add :no_shipping and :address_override options to PayflowExpress [cody]
|
@@ -828,7 +842,7 @@
|
|
828
842
|
* Update DataCash tests and format merchant reference number to meet DataCash's requirements [MoneySpyder, cody]
|
829
843
|
* Add Datacash gateway [MoneySpyder, cody]
|
830
844
|
* VERIFY_PEER on all SSL requests [cody]
|
831
|
-
* Add support for 2Checkout [cody]
|
845
|
+
* Add support for 2Checkout [cody]
|
832
846
|
|
833
847
|
== Version 1.0.3
|
834
848
|
|
@@ -859,7 +873,7 @@
|
|
859
873
|
* Moneris now uses the same layout as the authorized.net plugin
|
860
874
|
* Added authorized.net
|
861
875
|
* Changed default to :test mode. Set to production with ActiveMerchant::Billing::Base.gateway_mode = :production
|
862
|
-
* More refactoring
|
876
|
+
* More refactoring
|
863
877
|
* 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.
|
864
878
|
* Added Moneris support
|
865
879
|
* Credit card in memory object resembling a AR object
|
data/CONTRIBUTORS
CHANGED
data/README.md
CHANGED
@@ -108,6 +108,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
|
|
108
108
|
* [iTransact](http://www.itransact.com/) - US
|
109
109
|
* [JetPay](http://www.jetpay.com) - US
|
110
110
|
* [LinkPoint](http://www.linkpoint.com/) - US
|
111
|
+
* [Litle](http://www.litle.com/) - US
|
111
112
|
* [Merchant e-Solutions](http://merchante-solutions.com/) - US
|
112
113
|
* [MerchantWare](http://merchantwarehouse.com/merchantware) - US
|
113
114
|
* [MasterCard Internet Gateway Service (MiGS)](http://mastercard.com/mastercardsps) - AU, AE, BD, BN, EG, HK, ID, IN, JO, KW, LB, LK, MU, MV, MY, NZ, OM, PH, QA, SA, SG, TT, VN
|
@@ -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
|
@@ -3,37 +3,35 @@ module ActiveMerchant #:nodoc:
|
|
3
3
|
# See the remote and mocked unit test files for example usage. Pay special attention to the contents of the options hash.
|
4
4
|
#
|
5
5
|
# Initial setup instructions can be found in http://cybersource.com/support_center/implementation/downloads/soap_api/SOAP_toolkits.pdf
|
6
|
-
#
|
7
|
-
# Debugging
|
6
|
+
#
|
7
|
+
# Debugging
|
8
8
|
# If you experience an issue with this gateway be sure to examine the transaction information from a general transaction search inside the CyberSource Business
|
9
|
-
# Center for the full error messages including field names.
|
9
|
+
# Center for the full error messages including field names.
|
10
10
|
#
|
11
11
|
# Important Notes
|
12
|
-
# * AVS and CVV only work against the production server. You will always get back X for AVS and no response for CVV against the test server.
|
13
|
-
# * Nexus is the list of states or provinces where you have a physical presence. Nexus is used to calculate tax. Leave blank to tax everyone.
|
14
|
-
# * If you want to calculate VAT for overseas customers you must supply a registration number in the options hash as vat_reg_number.
|
12
|
+
# * AVS and CVV only work against the production server. You will always get back X for AVS and no response for CVV against the test server.
|
13
|
+
# * Nexus is the list of states or provinces where you have a physical presence. Nexus is used to calculate tax. Leave blank to tax everyone.
|
14
|
+
# * If you want to calculate VAT for overseas customers you must supply a registration number in the options hash as vat_reg_number.
|
15
15
|
# * productCode is a value in the line_items hash that is used to tell CyberSource what kind of item you are selling. It is used when calculating tax/VAT.
|
16
16
|
# * All transactions use dollar values.
|
17
17
|
class CyberSourceGateway < Gateway
|
18
18
|
TEST_URL = 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor'
|
19
19
|
LIVE_URL = 'https://ics2ws.ic3.com/commerce/1.x/transactionProcessor'
|
20
|
-
|
21
|
-
XSD_VERSION = "1.69"
|
22
|
-
|
20
|
+
|
23
21
|
# visa, master, american_express, discover
|
24
22
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
|
25
23
|
self.supported_countries = ['US']
|
26
24
|
self.default_currency = 'USD'
|
27
25
|
self.homepage_url = 'http://www.cybersource.com'
|
28
26
|
self.display_name = 'CyberSource'
|
29
|
-
|
27
|
+
|
30
28
|
# map credit card to the CyberSource expected representation
|
31
29
|
@@credit_card_codes = {
|
32
30
|
:visa => '001',
|
33
31
|
:master => '002',
|
34
32
|
:american_express => '003',
|
35
33
|
:discover => '004'
|
36
|
-
}
|
34
|
+
}
|
37
35
|
|
38
36
|
# map response codes to something humans can read
|
39
37
|
@@response_codes = {
|
@@ -45,17 +43,17 @@ module ActiveMerchant #:nodoc:
|
|
45
43
|
:r152 => "The request was received, but a service timed out",
|
46
44
|
:r200 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the AVS check",
|
47
45
|
:r201 => "The issuing bank has questions about the request",
|
48
|
-
:r202 => "Expired card",
|
49
|
-
:r203 => "General decline of the card",
|
50
|
-
:r204 => "Insufficient funds in the account",
|
51
|
-
:r205 => "Stolen or lost card",
|
52
|
-
:r207 => "Issuing bank unavailable",
|
53
|
-
:r208 => "Inactive card or card not authorized for card-not-present transactions",
|
54
|
-
:r209 => "American Express Card Identifiction Digits (CID) did not match",
|
55
|
-
:r210 => "The card has reached the credit limit",
|
56
|
-
:r211 => "Invalid card verification number",
|
57
|
-
:r221 => "The customer matched an entry on the processor's negative file",
|
58
|
-
:r230 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check",
|
46
|
+
:r202 => "Expired card",
|
47
|
+
:r203 => "General decline of the card",
|
48
|
+
:r204 => "Insufficient funds in the account",
|
49
|
+
:r205 => "Stolen or lost card",
|
50
|
+
:r207 => "Issuing bank unavailable",
|
51
|
+
:r208 => "Inactive card or card not authorized for card-not-present transactions",
|
52
|
+
:r209 => "American Express Card Identifiction Digits (CID) did not match",
|
53
|
+
:r210 => "The card has reached the credit limit",
|
54
|
+
:r211 => "Invalid card verification number",
|
55
|
+
:r221 => "The customer matched an entry on the processor's negative file",
|
56
|
+
:r230 => "The authorization request was approved by the issuing bank but declined by CyberSource because it did not pass the card verification check",
|
59
57
|
:r231 => "Invalid account number",
|
60
58
|
:r232 => "The card type is not accepted by the payment processor",
|
61
59
|
:r233 => "General decline by the processor",
|
@@ -74,44 +72,44 @@ module ActiveMerchant #:nodoc:
|
|
74
72
|
:r247 => "You requested a credit for a capture that was previously voided",
|
75
73
|
:r250 => "The request was received, but a time-out occurred with the payment processor",
|
76
74
|
:r254 => "Your CyberSource account is prohibited from processing stand-alone refunds",
|
77
|
-
:r255 => "Your CyberSource account is not configured to process the service in the country you specified"
|
75
|
+
:r255 => "Your CyberSource account is not configured to process the service in the country you specified"
|
78
76
|
}
|
79
77
|
|
80
78
|
# These are the options that can be used when creating a new CyberSource Gateway object.
|
79
|
+
#
|
80
|
+
# :login => your username
|
81
81
|
#
|
82
|
-
# :
|
83
|
-
#
|
84
|
-
# :password => the transaction key you generated in the Business Center
|
82
|
+
# :password => the transaction key you generated in the Business Center
|
85
83
|
#
|
86
84
|
# :test => true sets the gateway to test mode
|
87
85
|
#
|
88
|
-
# :vat_reg_number => your VAT registration number
|
86
|
+
# :vat_reg_number => your VAT registration number
|
89
87
|
#
|
90
88
|
# :nexus => "WI CA QC" sets the states/provinces where you have a physical presense for tax purposes
|
91
89
|
#
|
92
|
-
# :ignore_avs => true don't want to use AVS so continue processing even if AVS would have failed
|
90
|
+
# :ignore_avs => true don't want to use AVS so continue processing even if AVS would have failed
|
93
91
|
#
|
94
|
-
# :ignore_cvv => true don't want to use CVV so continue processing even if CVV would have failed
|
92
|
+
# :ignore_cvv => true don't want to use CVV so continue processing even if CVV would have failed
|
95
93
|
def initialize(options = {})
|
96
94
|
requires!(options, :login, :password)
|
97
95
|
@options = options
|
98
96
|
super
|
99
|
-
end
|
97
|
+
end
|
100
98
|
|
101
99
|
# Should run against the test servers or not?
|
102
100
|
def test?
|
103
101
|
@options[:test] || Base.gateway_mode == :test
|
104
102
|
end
|
105
|
-
|
106
|
-
# Request an authorization for an amount from CyberSource
|
103
|
+
|
104
|
+
# Request an authorization for an amount from CyberSource
|
107
105
|
#
|
108
|
-
# You must supply an :order_id in the options hash
|
106
|
+
# You must supply an :order_id in the options hash
|
109
107
|
def authorize(money, creditcard, options = {})
|
110
108
|
requires!(options, :order_id, :email)
|
111
109
|
setup_address_hash(options)
|
112
110
|
commit(build_auth_request(money, creditcard, options), options )
|
113
111
|
end
|
114
|
-
|
112
|
+
|
115
113
|
def auth_reversal(money, identification, options = {})
|
116
114
|
commit(build_auth_reversal_request(money, identification, options), options)
|
117
115
|
end
|
@@ -123,18 +121,13 @@ module ActiveMerchant #:nodoc:
|
|
123
121
|
end
|
124
122
|
|
125
123
|
# Purchase is an auth followed by a capture
|
126
|
-
# You must supply an order_id in the options hash
|
127
|
-
def purchase(money,
|
124
|
+
# You must supply an order_id in the options hash
|
125
|
+
def purchase(money, creditcard, options = {})
|
128
126
|
requires!(options, :order_id, :email)
|
129
127
|
setup_address_hash(options)
|
130
|
-
|
131
|
-
requires!(options, [:type, :credit_card, :check])
|
132
|
-
commit(build_subscription_purchase_request(money, payment_source, options), options)
|
133
|
-
else
|
134
|
-
commit(build_purchase_request(money, payment_source, options), options)
|
135
|
-
end
|
128
|
+
commit(build_purchase_request(money, creditcard, options), options)
|
136
129
|
end
|
137
|
-
|
130
|
+
|
138
131
|
def void(identification, options = {})
|
139
132
|
commit(build_void_request(identification, options), options)
|
140
133
|
end
|
@@ -142,80 +135,17 @@ module ActiveMerchant #:nodoc:
|
|
142
135
|
def refund(money, identification, options = {})
|
143
136
|
commit(build_credit_request(money, identification, options), options)
|
144
137
|
end
|
145
|
-
|
138
|
+
|
146
139
|
def credit(money, identification, options = {})
|
147
140
|
deprecated CREDIT_DEPRECATION_MESSAGE
|
148
141
|
refund(money, identification, options)
|
149
142
|
end
|
150
143
|
|
151
|
-
# Creates or updates a cybersource customer profile, aka a subscription with type "on-demand"
|
152
|
-
# to charge the card while creating a profile, pass options[:setup_fee] => money
|
153
|
-
def store(credit_card_or_reference, options = {})
|
154
|
-
|
155
|
-
requires!(options, :order_id)
|
156
|
-
setup_address_hash(options)
|
157
|
-
|
158
|
-
if credit_card_or_reference.respond_to?(:number)
|
159
|
-
# create subscription
|
160
|
-
requires!(options, :billing_address, :email)
|
161
|
-
requires!(options[:billing_address], :first_name, :last_name)
|
162
|
-
|
163
|
-
# set subscription options for storing the credit card
|
164
|
-
options[:subscription] ||={}
|
165
|
-
options[:subscription].merge!(:frequency => "on-demand", :amount => 0, :auto_renew => false)
|
166
|
-
|
167
|
-
setup_address_hash(options)
|
168
|
-
request = build_create_subscription_request(credit_card_or_reference, options)
|
169
|
-
else
|
170
|
-
# update subscription
|
171
|
-
request = build_update_subscription_request(credit_card_or_reference, options)
|
172
|
-
end
|
173
|
-
|
174
|
-
commit(request, options)
|
175
|
-
end
|
176
|
-
|
177
|
-
# retrieves a customer subscription/profile
|
178
|
-
def retrieve(reference, options = {})
|
179
|
-
requires!(options, :order_id)
|
180
|
-
commit(build_retrieve_subscription_request(reference, options), options)
|
181
|
-
end
|
182
|
-
|
183
|
-
# removes a customer subscription/profile
|
184
|
-
def unstore(reference, options = {})
|
185
|
-
requires!(options, :order_id)
|
186
|
-
commit(build_delete_subscription_request(reference, options), options)
|
187
|
-
end
|
188
|
-
|
189
|
-
# Creates or updates a Cybersource recurring payment profile/subscription
|
190
|
-
def recurring(money, credit_card_or_reference, options = {})
|
191
|
-
requires!(options, :order_id, :subscription)
|
192
|
-
requires!(options[:subscription], [:frequency, "on-demand", "weekly", "bi-weekly", "semi-monthly", "quarterly", "quad-weekly", "semi-annually", "annually"])
|
193
|
-
|
194
|
-
options[:subscription].merge!(:amount => money)
|
195
|
-
|
196
|
-
setup_address_hash(options)
|
197
|
-
|
198
|
-
if credit_card_or_reference.respond_to?(:number)
|
199
|
-
# create subscription
|
200
|
-
requires!(options, :billing_address, :email)
|
201
|
-
requires!(options[:billing_address], :first_name, :last_name)
|
202
|
-
|
203
|
-
setup_address_hash(options)
|
204
|
-
request = build_create_subscription_request(credit_card_or_reference, options)
|
205
|
-
else
|
206
|
-
# update subscription
|
207
|
-
request = build_update_subscription_request(credit_card_or_reference, options)
|
208
|
-
end
|
209
|
-
|
210
|
-
commit(request, options)
|
211
|
-
end
|
212
|
-
|
213
|
-
|
214
144
|
# CyberSource requires that you provide line item information for tax calculations
|
215
145
|
# If you do not have prices for each item or want to simplify the situation then pass in one fake line item that costs the subtotal of the order
|
216
146
|
#
|
217
|
-
# The line_item hash goes in the options hash and should look like
|
218
|
-
#
|
147
|
+
# The line_item hash goes in the options hash and should look like
|
148
|
+
#
|
219
149
|
# :line_items => [
|
220
150
|
# {
|
221
151
|
# :declared_value => '1',
|
@@ -235,23 +165,22 @@ module ActiveMerchant #:nodoc:
|
|
235
165
|
#
|
236
166
|
# This functionality is only supported by this particular gateway may
|
237
167
|
# be changed at any time
|
238
|
-
def calculate_tax(options)
|
168
|
+
def calculate_tax(creditcard, options)
|
239
169
|
requires!(options, :line_items)
|
240
|
-
|
241
170
|
setup_address_hash(options)
|
242
|
-
commit(build_tax_calculation_request(options), options)
|
171
|
+
commit(build_tax_calculation_request(creditcard, options), options)
|
243
172
|
end
|
244
|
-
|
245
|
-
private
|
246
|
-
# Create all address hash key value pairs so that we still function if we were only provided with one or two of them
|
173
|
+
|
174
|
+
private
|
175
|
+
# Create all address hash key value pairs so that we still function if we were only provided with one or two of them
|
247
176
|
def setup_address_hash(options)
|
248
177
|
options[:billing_address] = options[:billing_address] || options[:address] || {}
|
249
178
|
options[:shipping_address] = options[:shipping_address] || {}
|
250
179
|
end
|
251
|
-
|
180
|
+
|
252
181
|
def build_auth_request(money, creditcard, options)
|
253
182
|
xml = Builder::XmlMarkup.new :indent => 2
|
254
|
-
add_address(xml, options[:billing_address], options)
|
183
|
+
add_address(xml, creditcard, options[:billing_address], options)
|
255
184
|
add_purchase_data(xml, money, true, options)
|
256
185
|
add_creditcard(xml, creditcard)
|
257
186
|
add_auth_service(xml)
|
@@ -259,17 +188,17 @@ module ActiveMerchant #:nodoc:
|
|
259
188
|
xml.target!
|
260
189
|
end
|
261
190
|
|
262
|
-
def build_tax_calculation_request(options)
|
191
|
+
def build_tax_calculation_request(creditcard, options)
|
263
192
|
xml = Builder::XmlMarkup.new :indent => 2
|
264
|
-
add_address(xml, options[:billing_address], options, false)
|
265
|
-
add_address(xml, options[:shipping_address], options, true)
|
193
|
+
add_address(xml, creditcard, options[:billing_address], options, false)
|
194
|
+
add_address(xml, creditcard, options[:shipping_address], options, true)
|
266
195
|
add_line_item_data(xml, options)
|
267
196
|
add_purchase_data(xml, 0, false, options)
|
268
|
-
add_tax_service(xml
|
197
|
+
add_tax_service(xml)
|
269
198
|
add_business_rules_data(xml)
|
270
199
|
xml.target!
|
271
200
|
end
|
272
|
-
|
201
|
+
|
273
202
|
def build_capture_request(money, authorization, options)
|
274
203
|
order_id, request_id, request_token = authorization.split(";")
|
275
204
|
options[:order_id] = order_id
|
@@ -279,22 +208,22 @@ module ActiveMerchant #:nodoc:
|
|
279
208
|
add_capture_service(xml, request_id, request_token)
|
280
209
|
add_business_rules_data(xml)
|
281
210
|
xml.target!
|
282
|
-
end
|
211
|
+
end
|
283
212
|
|
284
|
-
def build_purchase_request(money,
|
213
|
+
def build_purchase_request(money, creditcard, options)
|
285
214
|
xml = Builder::XmlMarkup.new :indent => 2
|
286
|
-
add_address(xml, options[:billing_address], options)
|
215
|
+
add_address(xml, creditcard, options[:billing_address], options)
|
287
216
|
add_purchase_data(xml, money, true, options)
|
288
|
-
|
289
|
-
add_purchase_service(xml,
|
217
|
+
add_creditcard(xml, creditcard)
|
218
|
+
add_purchase_service(xml, options)
|
290
219
|
add_business_rules_data(xml)
|
291
220
|
xml.target!
|
292
221
|
end
|
293
|
-
|
222
|
+
|
294
223
|
def build_void_request(identification, options)
|
295
224
|
order_id, request_id, request_token = identification.split(";")
|
296
225
|
options[:order_id] = order_id
|
297
|
-
|
226
|
+
|
298
227
|
xml = Builder::XmlMarkup.new :indent => 2
|
299
228
|
add_void_service(xml, request_id, request_token)
|
300
229
|
xml.target!
|
@@ -312,84 +241,11 @@ module ActiveMerchant #:nodoc:
|
|
312
241
|
def build_credit_request(money, identification, options)
|
313
242
|
order_id, request_id, request_token = identification.split(";")
|
314
243
|
options[:order_id] = order_id
|
315
|
-
|
244
|
+
|
316
245
|
xml = Builder::XmlMarkup.new :indent => 2
|
317
246
|
add_purchase_data(xml, money, true, options)
|
318
247
|
add_credit_service(xml, request_id, request_token)
|
319
|
-
|
320
|
-
xml.target!
|
321
|
-
end
|
322
|
-
|
323
|
-
def build_create_subscription_request(payment_source, options)
|
324
|
-
xml = Builder::XmlMarkup.new :indent => 2
|
325
|
-
add_address(xml, options[:billing_address], options)
|
326
|
-
add_purchase_data(xml, options[:setup_fee], true, options)
|
327
|
-
|
328
|
-
|
329
|
-
case determine_funding_source(payment_source)
|
330
|
-
when :credit_card then add_creditcard(xml, payment_source)
|
331
|
-
when :check then add_check(xml, payment_source)
|
332
|
-
else raise ArgumentError, "Unsupported funding source provided"
|
333
|
-
end
|
334
|
-
|
335
|
-
add_subscription(xml, options, payment_source)
|
336
|
-
add_subscription_create_service(xml, options)
|
337
|
-
add_business_rules_data(xml)
|
338
|
-
xml.target!
|
339
|
-
end
|
340
|
-
|
341
|
-
def build_update_subscription_request(identification, options)
|
342
|
-
reference_code, subscription_id, request_token = identification.split(";")
|
343
|
-
options[:subscription] ||= {}
|
344
|
-
options[:subscription][:subscription_id] = subscription_id
|
345
|
-
|
346
|
-
xml = Builder::XmlMarkup.new :indent => 2
|
347
|
-
add_address(xml, options[:billing_address], options) unless options[:billing_address].blank?
|
348
|
-
add_purchase_data(xml, options[:setup_fee], true, options) unless options[:setup_fee].blank?
|
349
|
-
add_creditcard(xml, options[:credit_card]) if options[:credit_card]
|
350
|
-
add_subscription(xml, options)
|
351
|
-
add_subscription_update_service(xml, options)
|
352
|
-
add_business_rules_data(xml)
|
353
|
-
xml.target!
|
354
|
-
end
|
355
|
-
|
356
|
-
def build_retrieve_subscription_request(identification, options)
|
357
|
-
reference_code, subscription_id, request_token = identification.split(";")
|
358
|
-
options[:subscription] ||= {}
|
359
|
-
options[:subscription][:subscription_id] = subscription_id
|
360
|
-
|
361
|
-
xml = Builder::XmlMarkup.new :indent => 2
|
362
|
-
add_subscription(xml, options)
|
363
|
-
add_subscription_retrieve_service(xml, options)
|
364
|
-
xml.target!
|
365
|
-
end
|
366
|
-
|
367
|
-
def build_delete_subscription_request(identification, options)
|
368
|
-
reference_code, subscription_id, request_token = identification.split(";")
|
369
|
-
options[:subscription] ||= {}
|
370
|
-
options[:subscription][:subscription_id] = subscription_id
|
371
|
-
|
372
|
-
xml = Builder::XmlMarkup.new :indent => 2
|
373
|
-
add_subscription(xml, options)
|
374
|
-
add_subscription_delete_service(xml, options)
|
375
|
-
xml.target!
|
376
|
-
end
|
377
|
-
|
378
|
-
def build_subscription_purchase_request(money, identification, options)
|
379
|
-
reference_code, subscription_id, request_token = identification.split(";")
|
380
|
-
options[:subscription] ||= {}
|
381
|
-
options[:subscription][:subscription_id] = subscription_id
|
382
|
-
|
383
|
-
xml = Builder::XmlMarkup.new :indent => 2
|
384
|
-
add_purchase_data(xml, money, true, options)
|
385
|
-
add_subscription(xml, options)
|
386
|
-
|
387
|
-
case options[:type]
|
388
|
-
when :credit_card then add_cc_purchase_service(xml, options)
|
389
|
-
when :check then add_check_service(xml)
|
390
|
-
end
|
391
|
-
|
392
|
-
add_business_rules_data(xml)
|
248
|
+
|
393
249
|
xml.target!
|
394
250
|
end
|
395
251
|
|
@@ -397,13 +253,13 @@ module ActiveMerchant #:nodoc:
|
|
397
253
|
xml.tag! 'businessRules' do
|
398
254
|
xml.tag!('ignoreAVSResult', 'true') if @options[:ignore_avs]
|
399
255
|
xml.tag!('ignoreCVResult', 'true') if @options[:ignore_cvv]
|
400
|
-
end
|
256
|
+
end
|
401
257
|
end
|
402
|
-
|
258
|
+
|
403
259
|
def add_line_item_data(xml, options)
|
404
260
|
options[:line_items].each_with_index do |value, index|
|
405
261
|
xml.tag! 'item', {'id' => index} do
|
406
|
-
xml.tag! 'unitPrice', amount(value[:declared_value])
|
262
|
+
xml.tag! 'unitPrice', amount(value[:declared_value])
|
407
263
|
xml.tag! 'quantity', value[:quantity]
|
408
264
|
xml.tag! 'productCode', value[:code] || 'shipping_only'
|
409
265
|
xml.tag! 'productName', value[:description]
|
@@ -411,51 +267,37 @@ module ActiveMerchant #:nodoc:
|
|
411
267
|
end
|
412
268
|
end
|
413
269
|
end
|
414
|
-
|
270
|
+
|
415
271
|
def add_merchant_data(xml, options)
|
416
272
|
xml.tag! 'merchantID', @options[:login]
|
417
273
|
xml.tag! 'merchantReferenceCode', options[:order_id]
|
418
274
|
xml.tag! 'clientLibrary' ,'Ruby Active Merchant'
|
419
|
-
xml.tag! 'clientLibraryVersion',
|
420
|
-
xml.tag! 'clientEnvironment' ,
|
421
|
-
end
|
422
|
-
|
423
|
-
def add_payment_source(xml, source, options={})
|
424
|
-
case determine_funding_source(source)
|
425
|
-
#when :subscription then add_customer_vault_id(params, source)
|
426
|
-
when :credit_card then add_creditcard(xml, source)
|
427
|
-
when :check then add_check(xml, source)
|
428
|
-
end
|
275
|
+
xml.tag! 'clientLibraryVersion', '1.0'
|
276
|
+
xml.tag! 'clientEnvironment' , 'Linux'
|
429
277
|
end
|
430
278
|
|
431
|
-
def add_purchase_data(xml, money, include_grand_total = false, options={})
|
432
|
-
money ||=0
|
279
|
+
def add_purchase_data(xml, money = 0, include_grand_total = false, options={})
|
433
280
|
xml.tag! 'purchaseTotals' do
|
434
281
|
xml.tag! 'currency', options[:currency] || currency(money)
|
435
|
-
xml.tag!('grandTotalAmount', amount(money)) if include_grand_total
|
282
|
+
xml.tag!('grandTotalAmount', amount(money)) if include_grand_total
|
436
283
|
end
|
437
284
|
end
|
438
285
|
|
439
|
-
def add_address(xml, address, options, shipTo = false)
|
286
|
+
def add_address(xml, creditcard, address, options, shipTo = false)
|
440
287
|
xml.tag! shipTo ? 'shipTo' : 'billTo' do
|
441
|
-
xml.tag! 'firstName',
|
442
|
-
xml.tag! 'lastName',
|
443
|
-
xml.tag! 'street1',
|
444
|
-
xml.tag! 'street2',
|
445
|
-
xml.tag! 'city',
|
446
|
-
xml.tag! 'state',
|
447
|
-
xml.tag! 'postalCode',
|
448
|
-
xml.tag! 'country',
|
449
|
-
xml.tag! '
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank?
|
455
|
-
end
|
456
|
-
end
|
457
|
-
|
458
|
-
def add_creditcard(xml, creditcard)
|
288
|
+
xml.tag! 'firstName', creditcard.first_name
|
289
|
+
xml.tag! 'lastName', creditcard.last_name
|
290
|
+
xml.tag! 'street1', address[:address1]
|
291
|
+
xml.tag! 'street2', address[:address2]
|
292
|
+
xml.tag! 'city', address[:city]
|
293
|
+
xml.tag! 'state', address[:state]
|
294
|
+
xml.tag! 'postalCode', address[:zip]
|
295
|
+
xml.tag! 'country', address[:country]
|
296
|
+
xml.tag! 'email', options[:email]
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def add_creditcard(xml, creditcard)
|
459
301
|
xml.tag! 'card' do
|
460
302
|
xml.tag! 'accountNumber', creditcard.number
|
461
303
|
xml.tag! 'expirationMonth', format(creditcard.month, :two_digits)
|
@@ -465,35 +307,15 @@ module ActiveMerchant #:nodoc:
|
|
465
307
|
end
|
466
308
|
end
|
467
309
|
|
468
|
-
def
|
469
|
-
#convert check object account type into cybs account type code
|
470
|
-
if check.account_type == "checking"
|
471
|
-
accountType = check.account_holder_type == "business" ? 'X' : 'C'
|
472
|
-
else
|
473
|
-
accountType = 'S'
|
474
|
-
end
|
475
|
-
|
476
|
-
xml.tag! 'check' do
|
477
|
-
xml.tag! 'accountNumber', check.account_number
|
478
|
-
xml.tag! 'accountType', accountType
|
479
|
-
xml.tag! 'bankTransitNumber', check.routing_number
|
480
|
-
xml.tag! 'checkNumber', check.number if check.number
|
481
|
-
end
|
482
|
-
end
|
483
|
-
|
484
|
-
def add_check_service(xml)
|
485
|
-
xml.tag! 'ecDebitService', {'run' => 'true'}
|
486
|
-
end
|
487
|
-
|
488
|
-
def add_tax_service(xml, options)
|
310
|
+
def add_tax_service(xml)
|
489
311
|
xml.tag! 'taxService', {'run' => 'true'} do
|
490
|
-
xml.tag!('nexus', options[:nexus]) unless options[:nexus].blank?
|
491
|
-
xml.tag!('sellerRegistration', @
|
312
|
+
xml.tag!('nexus', @options[:nexus]) unless @options[:nexus].blank?
|
313
|
+
xml.tag!('sellerRegistration', @options[:vat_reg_number]) unless @options[:vat_reg_number].blank?
|
492
314
|
end
|
493
315
|
end
|
494
316
|
|
495
317
|
def add_auth_service(xml)
|
496
|
-
xml.tag! 'ccAuthService', {'run' => 'true'}
|
318
|
+
xml.tag! 'ccAuthService', {'run' => 'true'}
|
497
319
|
end
|
498
320
|
|
499
321
|
def add_capture_service(xml, request_id, request_token)
|
@@ -503,18 +325,11 @@ module ActiveMerchant #:nodoc:
|
|
503
325
|
end
|
504
326
|
end
|
505
327
|
|
506
|
-
def add_purchase_service(xml,
|
507
|
-
case determine_funding_source(source)
|
508
|
-
when :credit_card then add_cc_purchase_service(xml, options)
|
509
|
-
when :check then add_check_service(xml)
|
510
|
-
end
|
511
|
-
end
|
512
|
-
|
513
|
-
def add_cc_purchase_service(xml, options)
|
328
|
+
def add_purchase_service(xml, options)
|
514
329
|
xml.tag! 'ccAuthService', {'run' => 'true'}
|
515
330
|
xml.tag! 'ccCaptureService', {'run' => 'true'}
|
516
331
|
end
|
517
|
-
|
332
|
+
|
518
333
|
def add_void_service(xml, request_id, request_token)
|
519
334
|
xml.tag! 'voidService', {'run' => 'true'} do
|
520
335
|
xml.tag! 'voidRequestID', request_id
|
@@ -536,47 +351,7 @@ module ActiveMerchant #:nodoc:
|
|
536
351
|
end
|
537
352
|
end
|
538
353
|
|
539
|
-
|
540
|
-
def add_subscription_create_service(xml, options)
|
541
|
-
add_cc_purchase_service(xml, options) if options[:setup_fee]
|
542
|
-
xml.tag! 'paySubscriptionCreateService', {'run' => 'true'}
|
543
|
-
end
|
544
|
-
|
545
|
-
def add_subscription_update_service(xml, options)
|
546
|
-
add_cc_purchase_service(xml, options) if options[:setup_fee]
|
547
|
-
xml.tag! 'paySubscriptionUpdateService', {'run' => 'true'}
|
548
|
-
end
|
549
|
-
|
550
|
-
def add_subscription_retrieve_service(xml, options)
|
551
|
-
xml.tag! 'paySubscriptionRetrieveService', {'run' => 'true'}
|
552
|
-
end
|
553
|
-
|
554
|
-
def add_subscription_delete_service(xml, options)
|
555
|
-
xml.tag! 'paySubscriptionDeleteService', {'run' => 'true'}
|
556
|
-
end
|
557
|
-
|
558
|
-
def add_subscription(xml, options, payment_source=nil)
|
559
|
-
if payment_source
|
560
|
-
xml.tag! 'subscription' do
|
561
|
-
xml.tag! 'paymentMethod', determine_funding_source(payment_source).to_s.gsub(/_/, " ")
|
562
|
-
end
|
563
|
-
end
|
564
|
-
|
565
|
-
xml.tag! 'recurringSubscriptionInfo' do
|
566
|
-
xml.tag! 'subscriptionID', options[:subscription][:subscription_id]
|
567
|
-
xml.tag! 'status', options[:subscription][:status] if options[:subscription][:status]
|
568
|
-
xml.tag! 'amount', options[:subscription][:amount] if options[:subscription][:amount]
|
569
|
-
xml.tag! 'numberOfPayments', options[:subscription][:occurrences] if options[:subscription][:occurrences]
|
570
|
-
xml.tag! 'automaticRenew', options[:subscription][:auto_renew] if options[:subscription][:auto_renew]
|
571
|
-
xml.tag! 'frequency', options[:subscription][:frequency] if options[:subscription][:frequency]
|
572
|
-
xml.tag! 'startDate', options[:subscription][:start_date].strftime("%Y%m%d") if options[:subscription][:start_date]
|
573
|
-
xml.tag! 'endDate', options[:subscription][:end_date].strftime("%Y%m%d") if options[:subscription][:end_date]
|
574
|
-
xml.tag! 'approvalRequired', options[:subscription][:approval_required] || false
|
575
|
-
xml.tag! 'event', options[:subscription][:event] if options[:subscription][:event]
|
576
|
-
xml.tag! 'billPayment', options[:subscription][:bill_payment] if options[:subscription][:bill_payment]
|
577
|
-
end
|
578
|
-
end
|
579
|
-
|
354
|
+
|
580
355
|
# Where we actually build the full SOAP request using builder
|
581
356
|
def build_request(body, options)
|
582
357
|
xml = Builder::XmlMarkup.new :indent => 2
|
@@ -591,32 +366,31 @@ module ActiveMerchant #:nodoc:
|
|
591
366
|
end
|
592
367
|
end
|
593
368
|
xml.tag! 's:Body', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema'} do
|
594
|
-
xml.tag! 'requestMessage', {'xmlns' =>
|
369
|
+
xml.tag! 'requestMessage', {'xmlns' => 'urn:schemas-cybersource-com:transaction-data-1.32'} do
|
595
370
|
add_merchant_data(xml, options)
|
596
371
|
xml << body
|
597
372
|
end
|
598
373
|
end
|
599
374
|
end
|
600
|
-
xml.target!
|
375
|
+
xml.target!
|
601
376
|
end
|
602
|
-
|
377
|
+
|
603
378
|
# Contact CyberSource, make the SOAP request, and parse the reply into a Response object
|
604
379
|
def commit(request, options)
|
605
|
-
|
606
|
-
|
607
|
-
response = parse(post_response)
|
380
|
+
response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, build_request(request, options)))
|
381
|
+
|
608
382
|
success = response[:decision] == "ACCEPT"
|
609
|
-
message = @@response_codes[('r' + response[:reasonCode]).to_sym] rescue response[:message]
|
383
|
+
message = @@response_codes[('r' + response[:reasonCode]).to_sym] rescue response[:message]
|
610
384
|
authorization = success ? [ options[:order_id], response[:requestID], response[:requestToken] ].compact.join(";") : nil
|
611
|
-
|
612
|
-
Response.new(success, message, response,
|
613
|
-
:test => test?,
|
385
|
+
|
386
|
+
Response.new(success, message, response,
|
387
|
+
:test => test?,
|
614
388
|
:authorization => authorization,
|
615
389
|
:avs_result => { :code => response[:avsCode] },
|
616
390
|
:cvv_result => response[:cvCode]
|
617
391
|
)
|
618
392
|
end
|
619
|
-
|
393
|
+
|
620
394
|
# Parse the SOAP response
|
621
395
|
# Technique inspired by the Paypal Gateway
|
622
396
|
def parse(xml)
|
@@ -624,19 +398,19 @@ module ActiveMerchant #:nodoc:
|
|
624
398
|
xml = REXML::Document.new(xml)
|
625
399
|
if root = REXML::XPath.first(xml, "//c:replyMessage")
|
626
400
|
root.elements.to_a.each do |node|
|
627
|
-
case node.name
|
401
|
+
case node.name
|
628
402
|
when 'c:reasonCode'
|
629
403
|
reply[:message] = reply(node.text)
|
630
404
|
else
|
631
405
|
parse_element(reply, node)
|
632
406
|
end
|
633
407
|
end
|
634
|
-
elsif root = REXML::XPath.first(xml, "//soap:Fault")
|
408
|
+
elsif root = REXML::XPath.first(xml, "//soap:Fault")
|
635
409
|
parse_element(reply, root)
|
636
410
|
reply[:message] = "#{reply[:faultcode]}: #{reply[:faultstring]}"
|
637
411
|
end
|
638
412
|
return reply
|
639
|
-
end
|
413
|
+
end
|
640
414
|
|
641
415
|
def parse_element(reply, node)
|
642
416
|
if node.has_elements?
|
@@ -645,22 +419,12 @@ module ActiveMerchant #:nodoc:
|
|
645
419
|
if node.parent.name =~ /item/
|
646
420
|
parent = node.parent.name + (node.parent.attributes["id"] ? "_" + node.parent.attributes["id"] : '')
|
647
421
|
reply[(parent + '_' + node.name).to_sym] = node.text
|
648
|
-
else
|
422
|
+
else
|
649
423
|
reply[node.name.to_sym] = node.text
|
650
424
|
end
|
651
425
|
end
|
652
426
|
return reply
|
653
427
|
end
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
when source.is_a?(String) then :subscription
|
658
|
-
when CreditCard.card_companies.keys.include?(card_brand(source)) then :credit_card
|
659
|
-
when card_brand(source) == 'check' then :check
|
660
|
-
else raise ArgumentError, "Unsupported funding source provided"
|
661
|
-
end
|
662
|
-
end
|
663
|
-
|
664
|
-
end
|
665
|
-
end
|
666
|
-
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
end
|