activemerchant 1.35.1 → 1.36.0

Sign up to get free protection for your applications and to get access to all the features.
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