activemerchant 1.29.3 → 1.30.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.
Files changed (47) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +39 -0
  3. data/CONTRIBUTORS +19 -0
  4. data/README.md +43 -41
  5. data/lib/active_merchant/billing/check.rb +15 -11
  6. data/lib/active_merchant/billing/credit_card.rb +5 -1
  7. data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
  8. data/lib/active_merchant/billing/gateway.rb +1 -1
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +9 -1
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +15 -4
  11. data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
  12. data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
  13. data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
  14. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +6 -2
  15. data/lib/active_merchant/billing/gateways/braintree_blue.rb +5 -2
  16. data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
  17. data/lib/active_merchant/billing/gateways/eway.rb +114 -171
  18. data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
  19. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +222 -0
  20. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
  21. data/lib/active_merchant/billing/gateways/litle.rb +50 -19
  22. data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
  23. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
  24. data/lib/active_merchant/billing/gateways/moneris.rb +2 -4
  25. data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
  26. data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
  27. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  28. data/lib/active_merchant/billing/gateways/optimal_payment.rb +18 -3
  29. data/lib/active_merchant/billing/gateways/orbital.rb +9 -5
  30. data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
  31. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/paypal_express.rb +2 -0
  33. data/lib/active_merchant/billing/gateways/pin.rb +157 -0
  34. data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
  35. data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
  36. data/lib/active_merchant/billing/gateways/sage_pay.rb +6 -0
  37. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  38. data/lib/active_merchant/billing/gateways/spreedly_core.rb +235 -0
  39. data/lib/active_merchant/billing/gateways/stripe.rb +1 -0
  40. data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
  41. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +4 -1
  42. data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
  43. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
  44. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +14 -14
  45. data/lib/active_merchant/version.rb +1 -1
  46. metadata +109 -49
  47. metadata.gz.sig +0 -0
@@ -1,7 +1,10 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class MerchantWareGateway < Gateway
4
+ class_attribute :v4_live_url
5
+
4
6
  self.live_url = self.test_url = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx'
7
+ self.v4_live_url = 'https://ps1.merchantware.net/Merchantware/ws/RetailTransaction/v4/Credit.asmx'
5
8
 
6
9
  self.supported_countries = ['US']
7
10
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
@@ -12,13 +15,19 @@ module ActiveMerchant #:nodoc:
12
15
  "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
13
16
  "xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/"
14
17
  }
18
+ ENV_NAMESPACES_V4 = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
19
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
20
+ "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/"
21
+ }
22
+
15
23
  TX_NAMESPACE = "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail"
24
+ TX_NAMESPACE_V4 = "http://schemas.merchantwarehouse.com/merchantware/40/Credit/"
16
25
 
17
26
  ACTIONS = {
18
27
  :purchase => "IssueKeyedSale",
19
28
  :authorize => "IssueKeyedPreAuth",
20
29
  :capture => "IssuePostAuth",
21
- :void => "IssueVoid",
30
+ :void => "VoidPreAuthorization",
22
31
  :credit => "IssueKeyedRefund",
23
32
  :reference_credit => "IssueRefundByReference"
24
33
  }
@@ -80,11 +89,10 @@ module ActiveMerchant #:nodoc:
80
89
  # * <tt>authorization</tt> - The authorization string returned from the initial authorization or purchase.
81
90
  def void(authorization, options = {})
82
91
  reference, options[:order_id] = split_reference(authorization)
83
-
84
- request = soap_request(:void) do |xml|
85
- add_reference(xml, reference)
92
+ request = v4_soap_request(:void) do |xml|
93
+ add_reference_token(xml, reference)
86
94
  end
87
- commit(:void, request)
95
+ commit(:void, request, true)
88
96
  end
89
97
 
90
98
  # Refund an amount back a cardholder
@@ -108,7 +116,6 @@ module ActiveMerchant #:nodoc:
108
116
  perform_reference_credit(money, reference, options)
109
117
  end
110
118
 
111
-
112
119
  private
113
120
 
114
121
  def soap_request(action)
@@ -125,6 +132,22 @@ module ActiveMerchant #:nodoc:
125
132
  xml.target!
126
133
  end
127
134
 
135
+ def v4_soap_request(action)
136
+ xml = Builder::XmlMarkup.new :indent => 2
137
+ xml.instruct!
138
+ xml.tag! "soap:Envelope", ENV_NAMESPACES_V4 do
139
+ xml.tag! "soap:Body" do
140
+ xml.tag! ACTIONS[:void], "xmlns" => TX_NAMESPACE_V4 do
141
+ xml.tag! "merchantName", @options[:name]
142
+ xml.tag! "merchantSiteId", @options[:login]
143
+ xml.tag! "merchantKey", @options[:password]
144
+ yield xml
145
+ end
146
+ end
147
+ end
148
+ xml.target!
149
+ end
150
+
128
151
  def build_purchase_request(action, money, credit_card, options)
129
152
  requires!(options, :order_id)
130
153
 
@@ -195,6 +218,10 @@ module ActiveMerchant #:nodoc:
195
218
  xml.tag! "strReferenceCode", reference
196
219
  end
197
220
 
221
+ def add_reference_token(xml, reference)
222
+ xml.tag! "token", reference
223
+ end
224
+
198
225
  def add_address(xml, options)
199
226
  if address = options[:billing_address] || options[:address]
200
227
  xml.tag! "strAVSStreetAddress", address[:address1]
@@ -258,11 +285,19 @@ module ActiveMerchant #:nodoc:
258
285
  response
259
286
  end
260
287
 
261
- def commit(action, request)
288
+ def soap_action(action, v4 = false)
289
+ v4 ? "#{TX_NAMESPACE_V4}#{ACTIONS[action]}" : "#{TX_NAMESPACE}/#{ACTIONS[action]}"
290
+ end
291
+
292
+ def url(v4 = false)
293
+ v4 ? v4_live_url : live_url
294
+ end
295
+
296
+ def commit(action, request, v4 = false)
262
297
  begin
263
- data = ssl_post(self.live_url, request,
298
+ data = ssl_post(url(v4), request,
264
299
  "Content-Type" => 'text/xml; charset=utf-8',
265
- "SOAPAction" => "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail/#{ACTIONS[action]}"
300
+ "SOAPAction" => soap_action(action, v4)
266
301
  )
267
302
  response = parse(action, data)
268
303
  rescue ActiveMerchant::ResponseError => e
@@ -0,0 +1,190 @@
1
+ require 'digest/md5'
2
+ require 'rexml/document'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class MerchantWarriorGateway < Gateway
7
+ TOKEN_TEST_URL = 'https://base.merchantwarrior.com/token/'
8
+ TOKEN_LIVE_URL = 'https://api.merchantwarrior.com/token/'
9
+
10
+ POST_TEST_URL = 'https://base.merchantwarrior.com/post/'
11
+ POST_LIVE_URL = 'https://api.merchantwarrior.com/post/'
12
+
13
+ self.supported_countries = ['AU']
14
+ self.supported_cardtypes = [:visa, :master, :american_express,
15
+ :diners_club, :discover]
16
+ self.homepage_url = 'http://www.merchantwarrior.com/'
17
+ self.display_name = 'MerchantWarrior'
18
+
19
+ self.money_format = :dollars
20
+ self.default_currency = 'AUD'
21
+
22
+ def initialize(options = {})
23
+ requires!(options, :merchant_uuid, :api_key, :api_passphrase)
24
+ super
25
+ end
26
+
27
+ def authorize(money, payment_method, options = {})
28
+ post = {}
29
+ add_amount(post, money, options)
30
+ add_product(post, options)
31
+ add_address(post, options)
32
+ add_payment_method(post, payment_method)
33
+ commit('processAuth', post)
34
+ end
35
+
36
+ def purchase(money, payment_method, options = {})
37
+ post = {}
38
+ add_amount(post, money, options)
39
+ add_product(post, options)
40
+ add_address(post, options)
41
+ add_payment_method(post, payment_method)
42
+ commit('processCard', post)
43
+ end
44
+
45
+ def capture(money, identification)
46
+ post = {}
47
+ add_amount(post, money, options)
48
+ add_transaction(post, identification)
49
+ post.merge!('captureAmount' => money.to_s)
50
+ commit('processCapture', post)
51
+ end
52
+
53
+ def refund(money, identification)
54
+ post = {}
55
+ add_amount(post, money, options)
56
+ add_transaction(post, identification)
57
+ post['refundAmount'] = money
58
+ commit('refundCard', post)
59
+ end
60
+
61
+ def store(creditcard, options = {})
62
+ post = {
63
+ 'cardName' => creditcard.name,
64
+ 'cardNumber' => creditcard.number,
65
+ 'cardExpiryMonth' => sprintf('%02d', creditcard.month),
66
+ 'cardExpiryYear' => sprintf('%02d', creditcard.year)
67
+ }
68
+ commit('addCard', post)
69
+ end
70
+
71
+ private
72
+
73
+ def add_transaction(post, identification)
74
+ post['transactionID'] = identification
75
+ end
76
+
77
+ def add_address(post, options)
78
+ return unless(address = options[:address])
79
+
80
+ post['customerName'] = address[:name]
81
+ post['customerCountry'] = address[:country]
82
+ post['customerState'] = address[:state]
83
+ post['customerCity'] = address[:city]
84
+ post['customerAddress'] = address[:address1]
85
+ post['customerPostCode'] = address[:zip]
86
+ end
87
+
88
+ def add_product(post, options)
89
+ post['transactionProduct'] = options[:transaction_product]
90
+ end
91
+
92
+ def add_payment_method(post, payment_method)
93
+ if payment_method.respond_to?(:number)
94
+ add_creditcard(post, payment_method)
95
+ else
96
+ add_token(post, payment_method)
97
+ end
98
+ end
99
+
100
+ def add_token(post, token)
101
+ post['cardID'] = token
102
+ end
103
+
104
+ def add_creditcard(post, creditcard)
105
+ post['paymentCardNumber'] = creditcard.number
106
+ post['paymentCardName'] = creditcard.name
107
+ post['paymentCardExpiry'] = creditcard.expiry_date.expiration.strftime("%m%y")
108
+ end
109
+
110
+ def add_amount(post, money, options)
111
+ currency = (options[:currency] || currency(money))
112
+
113
+ post['transactionAmount'] = money.to_s
114
+ post['transactionCurrency'] = currency
115
+ post['hash'] = verification_hash(money, currency)
116
+ end
117
+
118
+ def verification_hash(money, currency)
119
+ Digest::MD5.hexdigest(
120
+ (
121
+ @options[:api_passphrase].to_s +
122
+ @options[:merchant_uuid].to_s +
123
+ money.to_s +
124
+ currency
125
+ ).downcase
126
+ )
127
+ end
128
+
129
+ def parse(body)
130
+ xml = REXML::Document.new(body)
131
+
132
+ response = {}
133
+ xml.root.elements.to_a.each do |node|
134
+ parse_element(response, node)
135
+ end
136
+ response
137
+ end
138
+
139
+ def parse_element(response, node)
140
+ if node.has_elements?
141
+ node.elements.each{|element| parse_element(response, element)}
142
+ else
143
+ response[node.name.underscore.to_sym] = node.text
144
+ end
145
+ end
146
+
147
+ def commit(action, post)
148
+ add_auth(action, post)
149
+
150
+ response = parse(ssl_post(url_for(action, post), post_data(post)))
151
+
152
+ Response.new(
153
+ success?(response),
154
+ response[:response_message],
155
+ response,
156
+ :test => test?,
157
+ :authorization => (response[:card_id] || response[:transaction_id])
158
+ )
159
+ end
160
+
161
+ def add_auth(action, post)
162
+ post['merchantUUID'] = @options[:merchant_uuid]
163
+ post['apiKey'] = @options[:api_key]
164
+ unless token?(post)
165
+ post['method'] = action
166
+ end
167
+ end
168
+
169
+ def url_for(action, post)
170
+ if token?(post)
171
+ [(test? ? TOKEN_TEST_URL : TOKEN_LIVE_URL), action].join("/")
172
+ else
173
+ (test? ? POST_TEST_URL : POST_LIVE_URL)
174
+ end
175
+ end
176
+
177
+ def token?(post)
178
+ (post["cardID"] || post["cardName"])
179
+ end
180
+
181
+ def success?(response)
182
+ (response[:response_code] == '0')
183
+ end
184
+
185
+ def post_data(post)
186
+ post.collect{|k,v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
187
+ end
188
+ end
189
+ end
190
+ end
@@ -70,15 +70,13 @@ module ActiveMerchant #:nodoc:
70
70
  commit 'completion', crediting_params(authorization, :comp_amount => amount(money))
71
71
  end
72
72
 
73
- # Voiding requires the original transaction ID and order ID of some open
74
- # transaction. Closed transactions must be refunded. Note that the only
75
- # methods which may be voided are +capture+ and +purchase+.
73
+ # Voiding cancels an open authorization.
76
74
  #
77
75
  # Concatenate your transaction number and order_id by using a semicolon
78
76
  # (';'). This is to keep the Moneris interface consistent with other
79
77
  # gateways. (See +capture+ for details.)
80
78
  def void(authorization, options = {})
81
- commit 'purchasecorrection', crediting_params(authorization)
79
+ capture(0, authorization, options)
82
80
  end
83
81
 
84
82
  # Performs a refund. This method requires that the original transaction
@@ -34,7 +34,7 @@ module ActiveMerchant #:nodoc:
34
34
  #Transactions currently accepted by NAB Transact XML API
35
35
  TRANSACTIONS = {
36
36
  :purchase => 0, #Standard Payment
37
- :credit => 4, #Refund
37
+ :refund => 4, #Refund
38
38
  :void => 6, #Client Reversal (Void)
39
39
  :authorization => 10, #Preauthorise
40
40
  :capture => 11 #Preauthorise Complete (Advice)
@@ -66,6 +66,10 @@ module ActiveMerchant #:nodoc:
66
66
  end
67
67
  end
68
68
 
69
+ def refund(money, authorization, options = {})
70
+ commit :refund, build_reference_request(money, authorization)
71
+ end
72
+
69
73
  def store(creditcard, options = {})
70
74
  requires!(options, :billing_id, :amount)
71
75
  commit_periodic(build_periodic_item(:addcrn, options[:amount], creditcard, options))
@@ -104,10 +108,23 @@ module ActiveMerchant #:nodoc:
104
108
  xml.target!
105
109
  end
106
110
 
111
+ def build_reference_request(money, reference)
112
+ xml = Builder::XmlMarkup.new
113
+
114
+ transaction_id, order_id, preauth_id, original_amount = reference.split('*')
115
+
116
+ xml.tag! 'amount', (money ? amount(money) : original_amount)
117
+ xml.tag! 'currency', options[:currency] || currency(money)
118
+ xml.tag! 'txnID', transaction_id
119
+ xml.tag! 'purchaseOrderNo', order_id
120
+ xml.tag! 'preauthID', preauth_id
121
+
122
+ xml.target!
123
+ end
124
+
107
125
  #Generate payment request XML
108
126
  # - API is set to allow multiple Txn's but currentlu only allows one
109
127
  # - txnSource = 23 - (XML)
110
-
111
128
  def build_request(action, body)
112
129
  xml = Builder::XmlMarkup.new
113
130
  xml.instruct!
@@ -210,7 +227,7 @@ module ActiveMerchant #:nodoc:
210
227
  end
211
228
 
212
229
  def authorization_from(response)
213
- response[:txn_id]
230
+ [response[:txn_id], response[:purchase_order_no], response[:preauth_id], response[:amount]].join('*')
214
231
  end
215
232
 
216
233
  def message_from(response)
@@ -177,6 +177,7 @@ module ActiveMerchant #:nodoc:
177
177
 
178
178
  def post_data(action, parameters = {})
179
179
  parameters[:account_id] = @options[:login]
180
+ parameters[:site_tag] = @options[:site_tag] if @options[:site_tag].present?
180
181
  parameters[:pay_type] = 'C'
181
182
  parameters[:tran_type] = TRANSACTIONS[action]
182
183
 
@@ -0,0 +1,223 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ #
4
+ # NETPAY Gateway
5
+ #
6
+ # Support for NETPAY's HTTP Connector payment gateway in Mexico.
7
+ #
8
+ # The gateway sends requests as HTTP POST and receives the response details
9
+ # in the HTTP header, making the process really rather simple.
10
+ #
11
+ # Support for calls to the authorize and capture methods have been included
12
+ # as per the Netpay manuals, however, your millage may vary with these
13
+ # methods. At the time of writing (January 2013) they were not fully
14
+ # supported by the production or test gateways. This situation is
15
+ # expected to change within a few weeks/months.
16
+ #
17
+ # Purchases can be cancelled (`#void`) only within 24 hours of the
18
+ # transaction. After this, a refund should be performed instead.
19
+ #
20
+ # In addition to the regular ActiveMerchant transaction options, NETPAY
21
+ # also supports a `:mode` parameter. This allows testing to be peformed
22
+ # in production and force specific results.
23
+ #
24
+ # * 'P' - Production
25
+ # * 'A' - Approved
26
+ # * 'D' - Declined
27
+ # * 'R' - Random (Approved or Declined)
28
+ # * 'T' - Test
29
+ #
30
+ # For example:
31
+ #
32
+ # response = @gateway.purchase(1000, card, :mode => 'D')
33
+ # response.success # false
34
+ #
35
+ class NetpayGateway < Gateway
36
+ self.test_url = 'http://200.57.87.243:8855'
37
+ self.live_url = 'https://suite.netpay.com.mx/acquirerprd'
38
+
39
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
40
+ self.supported_countries = ['MX']
41
+
42
+ self.default_currency = 'MXN'
43
+
44
+ # The card types supported by the payment gateway
45
+ self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
46
+
47
+ # The homepage URL of the gateway
48
+ self.homepage_url = 'http://www.netpay.com.mx'
49
+
50
+ # The name of the gateway
51
+ self.display_name = 'NETPAY Gateway'
52
+
53
+ CURRENCY_CODES = {
54
+ "MXN" => '484'
55
+ }
56
+
57
+ # The header keys that we will provide in the response params hash
58
+ RESPONSE_KEYS = ['ResponseMsg', 'ResponseText', 'ResponseCode', 'TimeIn', 'TimeOut', 'AuthCode', 'OrderId', 'CardTypeName', 'MerchantId', 'IssuerAuthDate']
59
+
60
+ def initialize(options = {})
61
+ requires!(options, :store_id, :login, :password)
62
+ super
63
+ end
64
+
65
+ # Send an authorization request
66
+ def authorize(money, creditcard, options = {})
67
+ post = {}
68
+ add_invoice(post, options)
69
+ add_creditcard(post, creditcard)
70
+ add_customer_data(post, options)
71
+ add_amount(post, money, options)
72
+
73
+ commit('PreAuth', post, options)
74
+ end
75
+
76
+ # Capture an authorization
77
+ def capture(money, authorization, options = {})
78
+ post = {}
79
+ add_order_id(post, order_id_from(authorization))
80
+ add_amount(post, money, options)
81
+
82
+ commit('PostAuth', post, options)
83
+ end
84
+
85
+ # Cancel an auth/purchase within first 24 hours
86
+ def void(authorization, options = {})
87
+ post = {}
88
+ order_id, amount, currency = split_authorization(authorization)
89
+ add_order_id(post, order_id)
90
+ post['Total'] = (options[:amount] || amount)
91
+ post['CurrencyCode'] = currency
92
+
93
+ commit('Refund', post, options)
94
+ end
95
+
96
+ # Make a purchase.
97
+ def purchase(money, creditcard, options = {})
98
+ post = {}
99
+ add_invoice(post, options)
100
+ add_creditcard(post, creditcard)
101
+ add_customer_data(post, options)
102
+ add_amount(post, money, options)
103
+
104
+ commit('Auth', post, options)
105
+ end
106
+
107
+ # Perform a Credit transaction.
108
+ def refund(money, authorization, options = {})
109
+ post = {}
110
+ add_order_id(post, order_id_from(authorization))
111
+ add_amount(post, money, options)
112
+
113
+ #commit('Refund', post, options)
114
+ commit('Credit', post, options)
115
+ end
116
+
117
+ private
118
+
119
+ def add_login_data(post)
120
+ post['StoreId'] = @options[:store_id]
121
+ post['UserName'] = @options[:login]
122
+ post['Password'] = @options[:password]
123
+ end
124
+
125
+ def add_action(post, action, options)
126
+ post['ResourceName'] = action
127
+ post['ContentType'] = 'Transaction'
128
+ post['Mode'] = options[:mode] || 'P'
129
+ end
130
+
131
+ def add_order_id(post, order_id)
132
+ post['OrderId'] = order_id
133
+ end
134
+
135
+ def add_amount(post, money, options)
136
+ post['Total'] = amount(money)
137
+ post['CurrencyCode'] = currency_code(options[:currency] || currency(money))
138
+ end
139
+
140
+ def add_customer_data(post, options)
141
+ post['IPAddress'] = options[:ip] unless options[:ip].blank?
142
+ end
143
+
144
+ def add_invoice(post, options)
145
+ post['Comments'] = options[:description] if options[:description]
146
+ end
147
+
148
+ def add_creditcard(post, creditcard)
149
+ post['CardNumber'] = creditcard.number
150
+ post['ExpDate'] = expdate(creditcard)
151
+ post['CustomerName'] = creditcard.name
152
+ post['CVV2'] = creditcard.verification_value unless creditcard.verification_value.nil?
153
+ end
154
+
155
+ def build_authorization(request_params, response_params)
156
+ [response_params['OrderId'], request_params['Total'], request_params['CurrencyCode']].join('|')
157
+ end
158
+
159
+ def split_authorization(authorization)
160
+ order_id, amount, currency = authorization.split("|")
161
+ [order_id, amount, currency]
162
+ end
163
+
164
+ def order_id_from(authorization)
165
+ split_authorization(authorization).first
166
+ end
167
+
168
+ def expdate(credit_card)
169
+ year = sprintf("%.4i", credit_card.year)
170
+ month = sprintf("%.2i", credit_card.month)
171
+
172
+ "#{month}/#{year[-2..-1]}"
173
+ end
174
+
175
+ def url
176
+ test? ? test_url : live_url
177
+ end
178
+
179
+ def parse(response, request_params)
180
+ response_params = params_from_response(response)
181
+
182
+ success = (response_params['ResponseCode'] == '00')
183
+ message = response_params['ResponseText'] || response_params['ResponseMsg']
184
+ options = @options.merge(:test => test?,
185
+ :authorization => build_authorization(request_params, response_params))
186
+
187
+ Response.new(success, message, response_params, options)
188
+ end
189
+
190
+ def commit(action, parameters, options)
191
+ add_login_data(parameters)
192
+ add_action(parameters, action, options)
193
+
194
+ post = parameters.collect{|key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
195
+ parse(ssl_post(url, post), parameters)
196
+ end
197
+
198
+ # Override the regular handle response so we can access the headers
199
+ def handle_response(response)
200
+ case response.code.to_i
201
+ when 200...300
202
+ response
203
+ else
204
+ raise ResponseError.new(response)
205
+ end
206
+ end
207
+
208
+ # Return a hash containing all the useful, or informative values from netpay
209
+ def params_from_response(response)
210
+ params = {}
211
+ RESPONSE_KEYS.each do |k|
212
+ params[k] = response[k] unless response[k].to_s.empty?
213
+ end
214
+ params
215
+ end
216
+
217
+ def currency_code(currency)
218
+ return currency if currency =~ /^\d+$/
219
+ CURRENCY_CODES[currency]
220
+ end
221
+ end
222
+ end
223
+ end