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 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
@@ -301,3 +301,7 @@ MiGS gateway (April 2012)
301
301
  ePay integration (April 2012)
302
302
 
303
303
  * Michael (ePay)
304
+
305
+ Litle gateway (May 2012)
306
+
307
+ * Gregory Drake (GregDrake)
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
- :authorization => find(doc, "//Transaction/Id"),
156
+ :transaction_id => find(doc, "//Transaction/Id"),
157
157
  :avs_result => find(doc, "//Transaction/AvsRespCode"),
158
158
  :cvv_result => find(doc, "//Transaction/Cvv2Resp"),
159
- :order_id => find(doc, "//OrderFormDoc/Transaction/Id"),
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
- # :login => your username
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, payment_source, options = {})
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
- if payment_source.is_a?(String)
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) unless options[:shipping_address].empty?
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, options)
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, payment_source, options)
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
- add_payment_source(xml, payment_source)
289
- add_purchase_service(xml, payment_source, options)
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', VERSION
420
- xml.tag! 'clientEnvironment' , RUBY_PLATFORM
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', address[:first_name]
442
- xml.tag! 'lastName', address[:last_name]
443
- xml.tag! 'street1', address[:address1]
444
- xml.tag! 'street2', address[:address2]
445
- xml.tag! 'city', address[:city]
446
- xml.tag! 'state', address[:state]
447
- xml.tag! 'postalCode', address[:zip]
448
- xml.tag! 'country', address[:country]
449
- xml.tag! 'company', address[:company] unless address[:company].blank?
450
- xml.tag! 'companyTaxID', address[:companyTaxID] unless address[:company_tax_id].blank?
451
- xml.tag! 'phoneNumber', address[:phone_number] unless address[:phone_number].blank?
452
- xml.tag! 'email', options[:email] unless options[:email].blank?
453
- xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank?
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 add_check(xml, check)
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', @ptions[:vat_reg_number]) unless options[:vat_reg_number].blank?
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, source, options)
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' => "urn:schemas-cybersource-com:transaction-data-#{XSD_VERSION}"} do
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
- request = build_request(request, options)
606
- post_response = ssl_post(test? ? TEST_URL : LIVE_URL, request)
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
- def determine_funding_source(source)
656
- case
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