activemerchant 1.35.1 → 1.36.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,16 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ == Version 1.36.0 (August 2, 2013)
4
+
5
+ * Fat Zebra: More consistent handling of tokens [adrianmacneil]
6
+ * Add Platron integration [alexwl]
7
+ * Litle: Support wiredump_device [pierre]
8
+ * Litle: support paypage registrations [pierre]
9
+ * SecureNet: Cleanup and refactoring [duff]
10
+ * Mercury: Proper refund and void support [opendining]
11
+ * PaymentExpress: Return token in authorization [ntalbott]
12
+ * Stripe: Support for partial application fee refunds [melari, odorcicd]
13
+
3
14
  == Version 1.35.1 (July 22, 2013)
4
15
 
5
16
  * Stripe: Allow application_fees to be refunded via the refund_application_fee flag [melari]
data/CONTRIBUTORS CHANGED
@@ -408,3 +408,7 @@ Barclays ePDQ Extra Plus (June 2013)
408
408
  MerchantWare V4 (July 2013)
409
409
 
410
410
  * Aleksei Gusev (hron)
411
+
412
+ Platron integration (July 2013)
413
+
414
+ * Alexey Kiryushin (alexwl)
data/README.md CHANGED
@@ -197,6 +197,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
197
197
  * [Paxum](https://www.paxum.com/)
198
198
  * [PayPal Website Payments Standard](https://www.paypal.com/cgi-bin/webscr?cmd#_wp-standard-overview-outside)
199
199
  * [Paysbuy](https://www.paysbuy.com/) - TH
200
+ * [Platron](https://www.platron.ru/) - RU
200
201
  * [RBK Money](https://rbkmoney.ru/) - RU
201
202
  * [Robokassa](http://robokassa.ru/) - RU
202
203
  * [SagePay Form](http://www.sagepay.com/products_services/sage_pay_go/integration/form)
@@ -161,7 +161,11 @@ module ActiveMerchant #:nodoc:
161
161
 
162
162
  def localized_amount(money, currency)
163
163
  amount = amount(money)
164
- CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s) ? amount.split('.').first : amount
164
+ non_fractional_currency?(currency) ? amount.split('.').first : amount
165
+ end
166
+
167
+ def non_fractional_currency?(currency)
168
+ CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s)
165
169
  end
166
170
 
167
171
  def currency(money)
@@ -858,7 +858,7 @@ module ActiveMerchant #:nodoc:
858
858
  end
859
859
 
860
860
  def format_extra_options(options)
861
- options.map{ |k, v| "#{k}=#{v}" }.join(',') unless options.nil?
861
+ options.map{ |k, v| "#{k}=#{v}" }.join('&') unless options.nil?
862
862
  end
863
863
 
864
864
  def parse_direct_response(params)
@@ -13,15 +13,14 @@ module ActiveMerchant #:nodoc:
13
13
 
14
14
  self.homepage_url = 'https://www.fatzebra.com.au/'
15
15
  self.display_name = 'Fat Zebra'
16
-
16
+
17
17
  # Setup a new instance of the gateway.
18
18
  #
19
19
  # The options hash should include :username and :token
20
20
  # You can find your username and token at https://dashboard.fatzebra.com.au
21
21
  # Under the Your Account section
22
22
  def initialize(options = {})
23
- requires!(options, :username)
24
- requires!(options, :token)
23
+ requires!(options, :username, :token)
25
24
  @username = options[:username]
26
25
  @token = options[:token]
27
26
  super
@@ -29,11 +28,11 @@ module ActiveMerchant #:nodoc:
29
28
 
30
29
  # To create a purchase on a credit card use:
31
30
  #
32
- # purchase(money, creditcard , { ... })
31
+ # purchase(money, creditcard)
33
32
  #
34
33
  # To charge a tokenized card
35
34
  #
36
- # purchase(money, {:token => "abzy87u", :cvv => "123"}, { ... }})
35
+ # purchase(money, "abzy87u", :cvv => "123")
37
36
  def purchase(money, creditcard, options = {})
38
37
  post = {}
39
38
 
@@ -61,6 +60,8 @@ module ActiveMerchant #:nodoc:
61
60
  end
62
61
 
63
62
  # Tokenize a credit card
63
+ #
64
+ # The token is returned in the Response#authorization
64
65
  def store(creditcard)
65
66
  post = {}
66
67
  add_creditcard(post, creditcard)
@@ -69,6 +70,7 @@ module ActiveMerchant #:nodoc:
69
70
  end
70
71
 
71
72
  private
73
+
72
74
  # Add the money details to the request
73
75
  def add_amount(post, money, options)
74
76
  post[:amount] = money
@@ -81,42 +83,61 @@ module ActiveMerchant #:nodoc:
81
83
  post[:card_expiry] = "#{creditcard.month}/#{creditcard.year}"
82
84
  post[:cvv] = creditcard.verification_value if creditcard.verification_value?
83
85
  post[:card_holder] = creditcard.name if creditcard.name
86
+ elsif creditcard.is_a?(String)
87
+ post[:card_token] = creditcard
88
+ post[:cvv] = options[:cvv]
89
+ elsif creditcard.is_a?(Hash)
90
+ deprecated "Passing the credit card as a Hash is deprecated. Use a String and put the (optional) CVV in the options hash instead."
91
+ post[:card_token] = creditcard[:token]
92
+ post[:cvv] = creditcard[:cvv]
84
93
  else
85
- post[:card_token] = creditcard[:token]
86
- post[:cvv] = creditcard[:cvv]
94
+ raise ArgumentError.new("Unknown credit card format #{creditcard.inspect}")
87
95
  end
88
96
  end
89
97
 
90
98
  # Post the data to the gateway
91
99
  def commit(method, uri, parameters=nil)
92
- raw_response = response = nil
93
- success = false
94
- begin
95
- raw_response = ssl_request(method, get_url(uri), parameters.to_json, headers)
96
- response = parse(raw_response)
97
- success = response["successful"] && (response["response"]["successful"] || response["response"]["token"])
100
+ response = begin
101
+ parse(ssl_request(method, get_url(uri), parameters.to_json, headers))
98
102
  rescue ResponseError => e
99
- if e.response.code == "401"
100
- return Response.new(false, "Invalid Login")
101
- end
102
-
103
- raw_response = e.response.body
104
- response = parse(raw_response)
105
- rescue JSON::ParserError
106
- response = json_error(raw_response)
103
+ return Response.new(false, "Invalid Login") if(e.response.code == "401")
104
+ parse(e.response.body)
107
105
  end
108
106
 
109
- message = response["response"]["message"]
110
- unless response["successful"]
111
- # There is an error, so we will show that instead
112
- message = response["errors"].empty? ? "Unknown Error" : response["errors"].join(", ")
107
+ success = success_from(response)
108
+ Response.new(
109
+ success,
110
+ message_from(response),
111
+ response,
112
+ :test => response["test"],
113
+ :authorization => authorization_from(response, success)
114
+ )
115
+ end
116
+
117
+ def success_from(response)
118
+ (
119
+ response["successful"] &&
120
+ response["response"] &&
121
+ (response["response"]["successful"] || response["response"]["token"])
122
+ )
123
+ end
124
+
125
+ def authorization_from(response, success)
126
+ if success
127
+ (response["response"]["id"] || response["response"]["token"])
128
+ else
129
+ nil
113
130
  end
131
+ end
114
132
 
115
- Response.new(success,
116
- message,
117
- response,
118
- :test => response.has_key?("test") ? response["test"] : false,
119
- :authorization => response["response"]["id"] || response["response"]["token"])
133
+ def message_from(response)
134
+ if !response["errors"].empty?
135
+ response["errors"].join(", ")
136
+ elsif response["response"]["message"]
137
+ response["response"]["message"]
138
+ else
139
+ "Unknown Error"
140
+ end
120
141
  end
121
142
 
122
143
  # Parse the returned JSON, if parse errors are raised then return a detailed error.
@@ -146,7 +167,7 @@ module ActiveMerchant #:nodoc:
146
167
  "Authorization" => "Basic " + Base64.strict_encode64(@username.to_s + ":" + @token.to_s).strip,
147
168
  "User-Agent" => "Fat Zebra v1.0/ActiveMerchant #{ActiveMerchant::VERSION}"
148
169
  }
149
- end
170
+ end
150
171
  end
151
172
  end
152
173
  end
@@ -57,7 +57,15 @@ module ActiveMerchant #:nodoc:
57
57
  begin
58
58
  require 'LitleOnline'
59
59
  rescue LoadError
60
- raise "Could not load the LitleOnline gem (>= 08.13.2). Use `gem install LitleOnline` to install it."
60
+ raise "Could not load the LitleOnline gem (> 08.15.0). Use `gem install LitleOnline` to install it."
61
+ end
62
+
63
+ if wiredump_device
64
+ LitleOnline::Configuration.logger = ((Logger === wiredump_device) ? wiredump_device : Logger.new(wiredump_device))
65
+ LitleOnline::Configuration.logger.level = Logger::DEBUG
66
+ else
67
+ LitleOnline::Configuration.logger = Logger.new(STDOUT)
68
+ LitleOnline::Configuration.logger.level = Logger::WARN
61
69
  end
62
70
 
63
71
  @litle = LitleOnline::LitleOnlineRequest.new
@@ -109,8 +117,8 @@ module ActiveMerchant #:nodoc:
109
117
  build_response(:credit, @litle.credit(to_pass))
110
118
  end
111
119
 
112
- def store(creditcard, options = {})
113
- to_pass = create_token_hash(creditcard, options)
120
+ def store(creditcard_or_paypage_registration_id, options = {})
121
+ to_pass = create_token_hash(creditcard_or_paypage_registration_id, options)
114
122
  build_response(:registerToken, @litle.register_token_request(to_pass), %w(000 801 802))
115
123
  end
116
124
 
@@ -286,9 +294,15 @@ module ActiveMerchant #:nodoc:
286
294
  hash
287
295
  end
288
296
 
289
- def create_token_hash(creditcard, options)
297
+ def create_token_hash(creditcard_or_paypage_registration_id, options)
290
298
  hash = create_hash(0, options)
291
- hash['accountNumber'] = creditcard.number
299
+
300
+ if creditcard_or_paypage_registration_id.is_a?(String)
301
+ hash['paypageRegistrationId'] = creditcard_or_paypage_registration_id
302
+ else
303
+ hash['accountNumber'] = creditcard_or_paypage_registration_id.number
304
+ end
305
+
292
306
  hash
293
307
  end
294
308
 
@@ -59,12 +59,22 @@ module ActiveMerchant #:nodoc:
59
59
  def refund(money, authorization, options = {})
60
60
  requires!(options, :credit_card) unless @use_tokenization
61
61
 
62
- request = build_authorized_request('VoidSale', money, authorization, options[:credit_card], options)
63
- commit(options[:void], request)
62
+ request = build_authorized_request('Return', money, authorization, options[:credit_card], options)
63
+ commit('Return', request)
64
64
  end
65
65
 
66
66
  def void(authorization, options={})
67
- refund(nil, authorization, options.merge(:void => true))
67
+ requires!(options, :credit_card) unless @use_tokenization
68
+
69
+ if options[:try_reversal]
70
+ request = build_authorized_request('VoidSale', nil, authorization, options[:credit_card], options.merge(:reversal => true))
71
+ response = commit('VoidSale', request)
72
+
73
+ return response if response.success?
74
+ end
75
+
76
+ request = build_authorized_request('VoidSale', nil, authorization, options[:credit_card], options)
77
+ commit('VoidSale', request)
68
78
  end
69
79
 
70
80
  private
@@ -94,7 +104,7 @@ module ActiveMerchant #:nodoc:
94
104
  xml = Builder::XmlMarkup.new
95
105
 
96
106
  invoice_no, ref_no, auth_code, acq_ref_data, process_data, record_no, amount = split_authorization(authorization)
97
- ref_no = invoice_no if options[:void]
107
+ ref_no = invoice_no if options[:reversal]
98
108
 
99
109
  xml.tag! "TStream" do
100
110
  xml.tag! "Transaction" do
@@ -111,8 +121,8 @@ module ActiveMerchant #:nodoc:
111
121
  add_address(xml, options)
112
122
  xml.tag! 'TranInfo' do
113
123
  xml.tag! "AuthCode", auth_code
114
- xml.tag! "AcqRefData", acq_ref_data
115
- xml.tag! "ProcessData", process_data
124
+ xml.tag! "AcqRefData", acq_ref_data if options[:reversal]
125
+ xml.tag! "ProcessData", process_data if options[:reversal]
116
126
  end
117
127
  end
118
128
  end
@@ -121,7 +131,7 @@ module ActiveMerchant #:nodoc:
121
131
 
122
132
  def add_invoice(xml, invoice_no, ref_no, options)
123
133
  if /^\d+$/ !~ invoice_no.to_s
124
- raise ArgumentError.new("#{invoice_no} is not numeric as required by Mercury")
134
+ raise ArgumentError.new("order_id '#{invoice_no}' is not numeric as required by Mercury")
125
135
  end
126
136
 
127
137
  xml.tag! 'InvoiceNo', invoice_no
@@ -285,9 +285,9 @@ module ActiveMerchant #:nodoc:
285
285
  response = parse( ssl_post(self.live_url, request.to_s) )
286
286
 
287
287
  # Return a response
288
- PaymentExpressResponse.new(response[:success] == APPROVED, response[:card_holder_help_text], response,
288
+ PaymentExpressResponse.new(response[:success] == APPROVED, message_from(response), response,
289
289
  :test => response[:test_mode] == '1',
290
- :authorization => response[:dps_txn_ref]
290
+ :authorization => authorization_from(action, response)
291
291
  )
292
292
  end
293
293
 
@@ -312,6 +312,19 @@ module ActiveMerchant #:nodoc:
312
312
  response
313
313
  end
314
314
 
315
+ def message_from(response)
316
+ (response[:card_holder_help_text] || response[:response_text])
317
+ end
318
+
319
+ def authorization_from(action, response)
320
+ case action
321
+ when :validate
322
+ (response[:billing_id] || response[:dps_billing_id])
323
+ else
324
+ response[:dps_txn_ref]
325
+ end
326
+ end
327
+
315
328
  def format_date(month, year)
316
329
  "#{format(month, :two_digits)}#{format(year, :two_digits)}"
317
330
  end
@@ -542,7 +542,7 @@ module ActiveMerchant #:nodoc:
542
542
  xml.tag! 'n2:Number', item[:number]
543
543
  xml.tag! 'n2:Quantity', item[:quantity]
544
544
  if item[:amount]
545
- xml.tag! 'n2:Amount', localized_amount(item[:amount], currency_code), 'currencyID' => currency_code
545
+ xml.tag! 'n2:Amount', item_amount(item[:amount], currency_code), 'currencyID' => currency_code
546
546
  end
547
547
  xml.tag! 'n2:Description', item[:description]
548
548
  xml.tag! 'n2:ItemURL', item[:url]
@@ -657,6 +657,14 @@ module ActiveMerchant #:nodoc:
657
657
  def date_to_iso(date)
658
658
  (date.is_a?(Date) ? date.to_time : date).utc.iso8601
659
659
  end
660
+
661
+ def item_amount(amount, currency_code)
662
+ if amount.to_i < 0 && non_fractional_currency?(currency_code)
663
+ amount(amount).to_f.floor
664
+ else
665
+ localized_amount(amount, currency_code)
666
+ end
667
+ end
660
668
  end
661
669
  end
662
670
  end
@@ -5,53 +5,28 @@ module ActiveMerchant #:nodoc:
5
5
  API_VERSION = "4.0"
6
6
 
7
7
  TRANSACTIONS = {
8
- :auth_only => "0000", #
9
- :partial_auth_only => "0001",
10
- :auth_capture => "0100", #
11
- :partial_auth_capture => "0101",
8
+ :auth_only => "0000",
9
+ :auth_capture => "0100",
12
10
  :prior_auth_capture => "0200",
13
- :capture_only => "0300", #
14
- :void => "0400", #
15
- :partial_void => "0401",
16
- :credit => "0500", #
17
- :credit_authonly => "0501",
18
- :credit_priorauthcapture => "0502",
19
- :force_credit => "0600",
20
- :force_credit_authonly => "0601",
21
- :force_credit_priorauthcapture => "0602",
22
- :verification => "0700",
23
- :auth_increment => "0800",
24
- :issue => "0900",
25
- :activate => "0901",
26
- :redeem => "0902",
27
- :redeem_partial => "0903",
28
- :deactivate => "0904",
29
- :reactivate => "0905",
30
- :inquiry_balance => "0906"
11
+ :void => "0400",
12
+ :credit => "0500"
31
13
  }
32
14
 
33
- XML_ATTRIBUTES = { 'xmlns' => "http://gateway.securenet.com/API/Contracts",
34
- 'xmlns:i' => "http://www.w3.org/2001/XMLSchema-instance"
15
+ XML_ATTRIBUTES = {
16
+ 'xmlns' => "http://gateway.securenet.com/API/Contracts",
17
+ 'xmlns:i' => "http://www.w3.org/2001/XMLSchema-instance"
35
18
  }
36
19
  NIL_ATTRIBUTE = { 'i:nil' => "true" }
37
20
 
38
- # SUCCESS = "true"
39
- # SENSITIVE_FIELDS = [ :verification_str2, :expiry_date, :card_number ]
40
-
41
21
  self.supported_countries = ['US']
42
22
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
43
23
  self.homepage_url = 'http://www.securenet.com/'
44
24
  self.display_name = 'SecureNet'
45
- # self.wiredump_device = STDOUT
46
25
 
47
- # self.test_url = 'https://certify.securenet.com/api/Gateway.svc'
48
26
  self.test_url = 'https://certify.securenet.com/API/gateway.svc/webHttp/ProcessTransaction'
49
27
  self.live_url = 'https://gateway.securenet.com/api/Gateway.svc'
50
28
 
51
- APPROVED, DECLINED, ERROR = 1, 2, 3
52
-
53
- RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT = 0, 2, 3
54
- AVS_RESULT_CODE, CARD_CODE_RESPONSE_CODE, TRANSACTION_ID = 5, 6, 8
29
+ APPROVED, DECLINED = 1, 2
55
30
 
56
31
  CARD_CODE_ERRORS = %w( N S )
57
32
  AVS_ERRORS = %w( A E N R W Z )
@@ -62,150 +37,87 @@ module ActiveMerchant #:nodoc:
62
37
  end
63
38
 
64
39
  def authorize(money, creditcard, options = {})
65
- commit(build_sale_or_authorization_request(creditcard, options, :auth_only), money)
40
+ commit(build_sale_or_authorization(creditcard, options, :auth_only, money))
66
41
  end
67
42
 
68
43
  def purchase(money, creditcard, options = {})
69
- commit(build_sale_or_authorization_request(creditcard, options, :auth_capture), money)
44
+ commit(build_sale_or_authorization(creditcard, options, :auth_capture, money))
45
+ end
46
+
47
+ def capture(money, authorization, options = {})
48
+ commit(build_capture_refund_void(authorization, options, :prior_auth_capture, money))
70
49
  end
71
50
 
72
- def capture(money, creditcard, authorization, options = {})
73
- commit(build_capture_request(authorization, creditcard, options, :prior_auth_capture), money)
51
+ def void(authorization, options = {})
52
+ commit(build_capture_refund_void(authorization, options, :void))
74
53
  end
75
54
 
76
- def void(money, creditcard, authorization, options = {})
77
- commit(build_void_request(authorization, creditcard, options, :void), money)
55
+ def refund(money, authorization, options = {})
56
+ commit(build_capture_refund_void(authorization, options, :credit, money))
78
57
  end
79
58
 
80
- def credit(money, creditcard, authorization, options = {})
81
- commit(build_credit_request(authorization, creditcard, options, :credit), money)
59
+ def credit(money, authorization, options = {})
60
+ deprecated CREDIT_DEPRECATION_MESSAGE
61
+ refund(money, authorization, options)
82
62
  end
83
63
 
64
+
84
65
  private
85
- def commit(request, money)
86
- xml = build_request(request, money)
66
+ def commit(request)
67
+ xml = build_request(request)
87
68
  data = ssl_post(self.test_url, xml, "Content-Type" => "text/xml")
88
69
  response = parse(data)
89
70
 
90
71
  test_mode = test?
91
72
  Response.new(success?(response), message_from(response), response,
92
73
  :test => test_mode,
93
- :authorization => response[:transactionid],
74
+ :authorization => build_authorization(response),
94
75
  :avs_result => { :code => response[:avs_result_code] },
95
76
  :cvv_result => response[:card_code_response_code]
96
77
  )
97
78
  end
98
79
 
99
- def build_request(request, money)
80
+ def build_request(request)
100
81
  xml = Builder::XmlMarkup.new
101
82
 
102
83
  xml.instruct!
103
84
  xml.tag!("TRANSACTION", XML_ATTRIBUTES) do
104
- xml.tag! 'AMOUNT', amount(money)
105
85
  xml << request
106
86
  end
107
87
 
108
88
  xml.target!
109
89
  end
110
90
 
111
- def build_sale_or_authorization_request(creditcard, options, action)
91
+ def build_sale_or_authorization(creditcard, options, action, money)
112
92
  xml = Builder::XmlMarkup.new
113
93
 
94
+ xml.tag! 'AMOUNT', amount(money)
114
95
  add_credit_card(xml, creditcard)
115
- xml.tag! 'CODE', TRANSACTIONS[action]
116
- add_customer_data(xml, options)
96
+ add_required_params(xml, action, options)
117
97
  add_address(xml, creditcard, options)
118
- xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
119
- xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
120
98
  add_invoice(xml, options)
121
- add_merchant_key(xml, options)
122
- xml.tag! 'METHOD', 'CC'
123
- xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
124
- xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
125
- xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
126
- xml.tag! 'TEST', 'TRUE'
127
- xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
128
- xml.tag! 'TRANSACTION_SERVICE', 0
129
-
130
- xml.target!
131
- end
132
-
133
- def build_capture_or_credit_request(identification, options)
134
- xml = Builder::XmlMarkup.new
135
-
136
- add_identification(xml, identification)
137
- add_customer_data(xml, options)
99
+ add_more_required_params(xml, options)
138
100
 
139
101
  xml.target!
140
102
  end
141
103
 
142
- def build_capture_request(authorization, creditcard, options, action)
104
+ def build_capture_refund_void(authorization, options, action, money = nil)
143
105
  xml = Builder::XmlMarkup.new
144
106
 
145
- add_credit_card(xml, creditcard)
146
- xml.tag! 'CODE', TRANSACTIONS[action]
147
- add_customer_data(xml, options)
148
- xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
149
- xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
150
- add_merchant_key(xml, options)
151
- xml.tag! 'METHOD', 'CC'
152
- xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
153
- xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
154
- xml.tag! 'REF_TRANSID', authorization
155
- xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
156
- xml.tag! 'TEST', 'TRUE'
157
- xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
158
- xml.tag! 'TRANSACTION_SERVICE', 0
159
-
160
- xml.target!
161
- end
162
-
163
- def build_credit_request(authorization, creditcard, options, action)
164
- # requires!(options, :card_number)
165
- xml = Builder::XmlMarkup.new
166
-
167
- add_credit_card(xml, creditcard)
168
- xml.tag! 'CODE', TRANSACTIONS[action]
169
- add_customer_data(xml, options)
170
- xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
171
- xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
172
- add_merchant_key(xml, options)
173
- xml.tag! 'METHOD', 'CC'
174
- xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
175
- xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
176
- xml.tag! 'REF_TRANSID', authorization
177
- xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
178
- xml.tag! 'TEST', 'TRUE'
179
- xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
180
- xml.tag! 'TRANSACTION_SERVICE', 0
181
-
182
- xml.target!
183
- end
107
+ transaction_id, amount_in_ref, last_four = split_authorization(authorization)
184
108
 
185
- def build_void_request(authorization, creditcard, options, action)
186
- xml = Builder::XmlMarkup.new
109
+ xml.tag! 'AMOUNT', amount(money) || amount_in_ref
110
+ xml.tag!("CARD") do
111
+ xml.tag! 'CARDNUMBER', last_four
112
+ end
187
113
 
188
- add_credit_card(xml, creditcard)
189
- xml.tag! 'CODE', TRANSACTIONS[action]
190
- add_customer_data(xml, options)
191
- xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
192
- xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
193
- add_merchant_key(xml, options)
194
- xml.tag! 'METHOD', 'CC'
195
- xml.tag! 'ORDERID', options[:order_id]#'30'.to_i.to_s#'22'# @options[:order_id]
196
- xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
197
- xml.tag! 'REF_TRANSID', authorization
198
- xml.tag! 'RETAIL_LANENUM', '0' # Docs say string, but it's an integer!?
199
- xml.tag! 'TEST', 'TRUE'
200
- xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
201
- xml.tag! 'TRANSACTION_SERVICE', 0
114
+ add_required_params(xml, action, options)
115
+ xml.tag! 'REF_TRANSID', transaction_id
116
+ add_more_required_params(xml, options)
202
117
 
203
118
  xml.target!
204
119
  end
205
120
 
206
- #########################################################################
207
- # FUNCTIONS RELATED TO BUILDING THE XML
208
- #########################################################################
209
121
  def add_credit_card(xml, creditcard)
210
122
  xml.tag!("CARD") do
211
123
  xml.tag! 'CARDCODE', creditcard.verification_value if creditcard.verification_value?
@@ -241,7 +153,6 @@ module ActiveMerchant #:nodoc:
241
153
  xml.tag! 'COUNTRY', address[:country].to_s
242
154
  if options.has_key? :email
243
155
  xml.tag! 'EMAIL', options[:email]
244
- # xml.tag! 'EMAIL', 'myemail@yahoo.com'
245
156
  xml.tag! 'EMAILRECEIPT', 'FALSE'
246
157
  end
247
158
  xml.tag! 'FIRSTNAME', creditcard.first_name
@@ -283,9 +194,24 @@ module ActiveMerchant #:nodoc:
283
194
  end
284
195
  end
285
196
 
286
- #########################################################################
287
- # FUNCTIONS RELATED TO THE RESPONSE
288
- #########################################################################
197
+ def add_required_params(xml, action, options)
198
+ xml.tag! 'CODE', TRANSACTIONS[action]
199
+ add_customer_data(xml, options)
200
+ xml.tag! 'DCI', 0 # No duplicate checking will be done, except for ORDERID
201
+ xml.tag! 'INSTALLMENT_SEQUENCENUM', 1
202
+ add_merchant_key(xml, options)
203
+ xml.tag! 'METHOD', 'CC'
204
+ xml.tag! 'ORDERID', options[:order_id]
205
+ xml.tag! 'OVERRIDE_FROM', 0 # Docs say not required, but doesn't work without it
206
+ end
207
+
208
+ def add_more_required_params(xml, options)
209
+ xml.tag! 'RETAIL_LANENUM', '0'
210
+ xml.tag! 'TEST', 'TRUE'
211
+ xml.tag! 'TOTAL_INSTALLMENTCOUNT', 0
212
+ xml.tag! 'TRANSACTION_SERVICE', 0
213
+ end
214
+
289
215
  def success?(response)
290
216
  response[:response_code].to_i == APPROVED
291
217
  end
@@ -302,9 +228,7 @@ module ActiveMerchant #:nodoc:
302
228
  def parse(xml)
303
229
  response = {}
304
230
  xml = REXML::Document.new(xml)
305
- root = REXML::XPath.first(xml, "//GATEWAYRESPONSE")# ||
306
- # root = REXML::XPath.first(xml, "//ProcessTransactionResponse")# ||
307
- # REXML::XPath.first(xml, "//ErrorResponse")
231
+ root = REXML::XPath.first(xml, "//GATEWAYRESPONSE")
308
232
  if root
309
233
  root.elements.to_a.each do |node|
310
234
  recurring_parse_element(response, node)
@@ -322,6 +246,14 @@ module ActiveMerchant #:nodoc:
322
246
  end
323
247
  end
324
248
 
249
+ def split_authorization(authorization)
250
+ transaction_id, amount, last_four = authorization.split("|")
251
+ [transaction_id, amount, last_four]
252
+ end
253
+
254
+ def build_authorization(response)
255
+ [response[:transactionid], response[:transactionamount], response[:last4_digits]].join("|")
256
+ end
325
257
 
326
258
  end
327
259
  end