activemerchant 1.16.0 → 1.17.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.
@@ -0,0 +1,270 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class OptimalPaymentGateway < Gateway
4
+ TEST_URL = 'https://webservices.test.optimalpayments.com/creditcardWS/CreditCardServlet/v1'
5
+ LIVE_URL = 'https://webservices.optimalpayments.com/creditcardWS/CreditCardServlet/v1'
6
+
7
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
8
+ self.supported_countries = ['CA', 'US', 'GB']
9
+
10
+ # The card types supported by the payment gateway
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :solo] # :switch?
12
+
13
+ # The homepage URL of the gateway
14
+ self.homepage_url = 'http://www.optimalpayments.com/'
15
+
16
+ # The name of the gateway
17
+ self.display_name = 'Optimal Payments'
18
+
19
+ def initialize(options = {})
20
+ #requires!(options, :login, :password)
21
+ @options = options
22
+ super
23
+ end
24
+
25
+ def authorize(money, card_or_auth, options = {})
26
+ parse_card_or_auth(card_or_auth, options)
27
+ commit("cc#{@stored_data}Authorize", money, options)
28
+ end
29
+ alias stored_authorize authorize # back-compat
30
+
31
+ def purchase(money, card_or_auth, options = {})
32
+ parse_card_or_auth(card_or_auth, options)
33
+ commit("cc#{@stored_data}Purchase", money, options)
34
+ end
35
+ alias stored_purchase purchase # back-compat
36
+
37
+ def refund(money, authorization, options = {})
38
+ options[:confirmationNumber] = authorization
39
+ commit('ccCredit', money, options)
40
+ end
41
+
42
+ def void(authorization, options = {})
43
+ options[:confirmationNumber] = authorization
44
+ commit('ccAuthorizeReversal', nil, options)
45
+ end
46
+
47
+ def capture(money, authorization, options = {})
48
+ options[:confirmationNumber] = authorization
49
+ commit('ccSettlement', money, options)
50
+ end
51
+
52
+ private
53
+
54
+ def parse_card_or_auth(card_or_auth, options)
55
+ if card_or_auth.respond_to?(:number)
56
+ @credit_card = card_or_auth
57
+ @stored_data = ""
58
+ else
59
+ options[:confirmationNumber] = card_or_auth
60
+ @stored_data = "StoredData"
61
+ end
62
+ end
63
+
64
+ def parse(body)
65
+ REXML::Document.new(body || '')
66
+ end
67
+
68
+ def commit(action, money, post)
69
+ post[:order_id] ||= 'order_id'
70
+
71
+ xml = case action
72
+ when 'ccAuthorize', 'ccPurchase', 'ccVerification'
73
+ cc_auth_request(money, post)
74
+ when 'ccCredit', 'ccSettlement'
75
+ cc_post_auth_request(money, post)
76
+ when 'ccStoredDataAuthorize', 'ccStoredDataPurchase'
77
+ cc_stored_data_request(money, post)
78
+ when 'ccAuthorizeReversal'
79
+ cc_auth_reversal_request(post)
80
+ #when 'ccCancelSettle', 'ccCancelCredit', 'ccCancelPayment'
81
+ # cc_cancel_request(money, post)
82
+ #when 'ccPayment'
83
+ # cc_payment_request(money, post)
84
+ #when 'ccAuthenticate'
85
+ # cc_authenticate_request(money, post)
86
+ else
87
+ raise 'Unknown Action'
88
+ end
89
+ txnRequest = URI.encode(xml)
90
+ response = parse(ssl_post(test? ? TEST_URL : LIVE_URL, "txnMode=#{action}&txnRequest=#{txnRequest}"))
91
+
92
+ Response.new(successful?(response), message_from(response), hash_from_xml(response),
93
+ :test => test?,
94
+ :authorization => authorization_from(response)
95
+ )
96
+ end
97
+
98
+ def successful?(response)
99
+ REXML::XPath.first(response, '//decision').text == 'ACCEPTED' rescue false
100
+ end
101
+
102
+ def message_from(response)
103
+ REXML::XPath.each(response, '//detail') do |detail|
104
+ if detail.is_a?(REXML::Element) && detail.elements['tag'].text == 'InternalResponseDescription'
105
+ return detail.elements['value'].text
106
+ end
107
+ end
108
+ nil
109
+ end
110
+
111
+ def authorization_from(response)
112
+ REXML::XPath.first(response, '//confirmationNumber').text rescue nil
113
+ end
114
+
115
+ def hash_from_xml(response)
116
+ hsh = {}
117
+ %w(confirmationNumber authCode
118
+ decision code description
119
+ actionCode avsResponse cvdResponse
120
+ txnTime duplicateFound
121
+ ).each do |tag|
122
+ node = REXML::XPath.first(response, "//#{tag}")
123
+ hsh[tag] = node.text if node
124
+ end
125
+ REXML::XPath.each(response, '//detail') do |detail|
126
+ next unless detail.is_a?(REXML::Element)
127
+ tag = detail.elements['tag'].text
128
+ value = detail.elements['value'].text
129
+ hsh[tag] = value
130
+ end
131
+ hsh
132
+ end
133
+
134
+ def xml_document(root_tag)
135
+ xml = Builder::XmlMarkup.new :indent => 2
136
+ xml.tag!(root_tag, schema) do
137
+ yield xml
138
+ end
139
+ xml.target!
140
+ end
141
+
142
+ def cc_auth_request(money, opts)
143
+ xml_document('ccAuthRequestV1') do |xml|
144
+ build_merchant_account(xml, @options)
145
+ xml.merchantRefNum opts[:order_id]
146
+ xml.amount(money/100.0)
147
+ build_card(xml, opts)
148
+ build_billing_details(xml, opts)
149
+ end
150
+ end
151
+
152
+ def cc_auth_reversal_request(opts)
153
+ xml_document('ccAuthReversalRequestV1') do |xml|
154
+ build_merchant_account(xml, @options)
155
+ xml.confirmationNumber opts[:confirmationNumber]
156
+ xml.merchantRefNum opts[:order_id]
157
+ end
158
+ end
159
+
160
+ def cc_post_auth_request(money, opts)
161
+ xml_document('ccPostAuthRequestV1') do |xml|
162
+ build_merchant_account(xml, @options)
163
+ xml.confirmationNumber opts[:confirmationNumber]
164
+ xml.merchantRefNum opts[:order_id]
165
+ xml.amount(money/100.0)
166
+ end
167
+ end
168
+
169
+ def cc_stored_data_request(money, opts)
170
+ xml_document('ccStoredDataRequestV1') do |xml|
171
+ build_merchant_account(xml, @options)
172
+ xml.merchantRefNum opts[:order_id]
173
+ xml.confirmationNumber opts[:confirmationNumber]
174
+ xml.amount(money/100.0)
175
+ end
176
+ end
177
+
178
+ # untested
179
+ #
180
+ # def cc_cancel_request(opts)
181
+ # xml_document('ccCancelRequestV1') do |xml|
182
+ # build_merchant_account(xml, @options)
183
+ # xml.confirmationNumber opts[:confirmationNumber]
184
+ # end
185
+ # end
186
+ #
187
+ # def cc_payment_request(money, opts)
188
+ # xml_document('ccPaymentRequestV1') do |xml|
189
+ # build_merchant_account(xml, @options)
190
+ # xml.merchantRefNum opts[:order_id]
191
+ # xml.amount(money/100.0)
192
+ # build_card(xml, opts)
193
+ # build_billing_details(xml, opts)
194
+ # end
195
+ # end
196
+ #
197
+ # def cc_authenticate_request(opts)
198
+ # xml_document('ccAuthenticateRequestV1') do |xml|
199
+ # build_merchant_account(xml, @options)
200
+ # xml.confirmationNumber opts[:confirmationNumber]
201
+ # xml.paymentResponse 'myPaymentResponse'
202
+ # end
203
+ # end
204
+
205
+ def schema
206
+ { 'xmlns' => 'http://www.optimalpayments.com/creditcard/xmlschema/v1',
207
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
208
+ 'xsi:schemaLocation' => 'http://www.optimalpayments.com/creditcard/xmlschema/v1'
209
+ }
210
+ end
211
+
212
+ def build_merchant_account(xml, opts)
213
+ xml.tag! 'merchantAccount' do
214
+ xml.tag! 'accountNum' , opts[:account]
215
+ xml.tag! 'storeID' , opts[:login]
216
+ xml.tag! 'storePwd' , opts[:password]
217
+ end
218
+ end
219
+
220
+ def build_card(xml, opts)
221
+ xml.tag! 'card' do
222
+ xml.tag! 'cardNum' , @credit_card.number
223
+ xml.tag! 'cardExpiry' do
224
+ xml.tag! 'month' , @credit_card.month
225
+ xml.tag! 'year' , @credit_card.year
226
+ end
227
+ if type = card_type(@credit_card.type)
228
+ xml.tag! 'cardType' , type
229
+ end
230
+ if @credit_card.verification_value
231
+ xml.tag! 'cvdIndicator' , '1' # Value Provided
232
+ xml.tag! 'cvd' , @credit_card.verification_value
233
+ end
234
+ end
235
+ end
236
+
237
+ def build_billing_details(xml, opts)
238
+ xml.tag! 'billingDetails' do
239
+ addr = opts[:billing_address]
240
+ xml.tag! 'cardPayMethod', 'WEB'
241
+ if addr[:name]
242
+ xml.tag! 'firstName', CGI.escape(addr[:name].split(' ').first) # TODO: parse properly
243
+ xml.tag! 'lastName' , CGI.escape(addr[:name].split(' ').last )
244
+ end
245
+ xml.tag! 'street' , CGI.escape(addr[:address1]) if addr[:address1] && !addr[:address1].empty?
246
+ xml.tag! 'street2', CGI.escape(addr[:address2]) if addr[:address2] && !addr[:address2].empty?
247
+ xml.tag! 'city' , CGI.escape(addr[:city] ) if addr[:city] && !addr[:city].empty?
248
+ xml.tag! 'state' , CGI.escape(addr[:state] ) if addr[:state] && !addr[:state].empty?
249
+ xml.tag! 'country', CGI.escape(addr[:country] ) if addr[:country] && !addr[:country].empty?
250
+ xml.tag! 'zip' , CGI.escape(addr[:zip] ) # this one's actually required
251
+ xml.tag! 'phone' , CGI.escape(addr[:phone] ) if addr[:phone] && !addr[:phone].empty?
252
+ #xml.tag! 'email' , ''
253
+ end
254
+ end
255
+
256
+ def card_type(key)
257
+ { 'visa' => 'VI',
258
+ 'master' => 'MC',
259
+ 'american_express'=> 'AM',
260
+ 'discover' => 'DI',
261
+ 'diners_club' => 'DC',
262
+ #'switch' => '',
263
+ 'solo' => 'SO'
264
+ }[key]
265
+ end
266
+
267
+ end
268
+ end
269
+ end
270
+
@@ -80,8 +80,8 @@ module ActiveMerchant #:nodoc:
80
80
  def initialize(options = {})
81
81
  unless options[:ip_authentication] == true
82
82
  requires!(options, :login, :password, :merchant_id)
83
- @options = options
84
83
  end
84
+ @options = options
85
85
  super
86
86
  end
87
87
 
@@ -167,6 +167,7 @@ module ActiveMerchant #:nodoc:
167
167
  xml.tag! :CurrencyCode, currency_code(currency)
168
168
  xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen.
169
169
 
170
+ xml.tag! :CardSecValInd, 1 if creditcard.verification_value? && %w( visa discover ).include?(creditcard.type)
170
171
  xml.tag! :CardSecVal, creditcard.verification_value if creditcard.verification_value?
171
172
  end
172
173
 
@@ -223,11 +224,11 @@ module ActiveMerchant #:nodoc:
223
224
  end
224
225
 
225
226
  def success?(response)
226
- if response[:message_type] == "R"
227
+ if response[:message_type].nil? || response[:message_type] == "R"
227
228
  response[:proc_status] == SUCCESS
228
229
  else
229
230
  response[:proc_status] == SUCCESS &&
230
- response[:resp_code] == APPROVED
231
+ response[:resp_code] == APPROVED
231
232
  end
232
233
  end
233
234
 
@@ -247,7 +248,7 @@ module ActiveMerchant #:nodoc:
247
248
  xml.tag! :NewOrder do
248
249
  xml.tag! :OrbitalConnectionUsername, @options[:login] unless ip_authentication?
249
250
  xml.tag! :OrbitalConnectionPassword, @options[:password] unless ip_authentication?
250
- xml.tag! :IndustryType, "EC" # E-Commerce transaction
251
+ xml.tag! :IndustryType, parameters[:industry_type] || "EC"
251
252
  xml.tag! :MessageType, action
252
253
  xml.tag! :BIN, '000002' # PNS Tampa
253
254
  xml.tag! :MerchantID, @options[:merchant_id]
@@ -289,7 +290,6 @@ module ActiveMerchant #:nodoc:
289
290
  end
290
291
 
291
292
  def build_void_request_xml(money, authorization, parameters = {})
292
- requires!(parameters, :transaction_index)
293
293
  tx_ref_num, order_id = authorization.split(';')
294
294
  xml = Builder::XmlMarkup.new(:indent => 2)
295
295
  xml.instruct!(:xml, :version => '1.0', :encoding => 'UTF-8')
@@ -63,10 +63,13 @@ module ActiveMerchant #:nodoc:
63
63
  def initialize(options = {})
64
64
  requires!(options, :login, :password)
65
65
 
66
+ headers = {'X-PP-AUTHORIZATION' => options.delete(:auth_signature), 'X-PAYPAL-MESSAGE-PROTOCOL' => 'SOAP11'} if options[:auth_signature]
66
67
  @options = {
67
68
  :pem => pem_file,
68
- :signature => signature
69
+ :signature => signature,
70
+ :headers => headers || {}
69
71
  }.update(options)
72
+
70
73
 
71
74
  if @options[:pem].blank? && @options[:signature].blank?
72
75
  raise ArgumentError, "An API Certificate or API Signature is required to make requests to PayPal"
@@ -280,7 +283,7 @@ module ActiveMerchant #:nodoc:
280
283
  xml.instruct!
281
284
  xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do
282
285
  xml.tag! 'env:Header' do
283
- add_credentials(xml)
286
+ add_credentials(xml) unless @options[:headers] && @options[:headers]['X-PP-AUTHORIZATION']
284
287
  end
285
288
 
286
289
  xml.tag! 'env:Body' do
@@ -320,7 +323,7 @@ module ActiveMerchant #:nodoc:
320
323
  end
321
324
 
322
325
  def commit(action, request)
323
- response = parse(action, ssl_post(endpoint_url, build_request(request)))
326
+ response = parse(action, ssl_post(endpoint_url, build_request(request), @options[:headers]))
324
327
 
325
328
  build_response(successful?(response), message_from(response), response,
326
329
  :test => test?,
@@ -80,6 +80,8 @@ module ActiveMerchant #:nodoc:
80
80
  xml.tag! 'n2:ButtonSource', application_id.to_s.slice(0,32) unless application_id.blank?
81
81
  xml.tag! 'n2:InvoiceID', options[:order_id]
82
82
  xml.tag! 'n2:OrderDescription', options[:description]
83
+
84
+ add_items_xml(xml, options, currency_code) if options[:items]
83
85
  end
84
86
  end
85
87
  end
@@ -115,25 +117,13 @@ module ActiveMerchant #:nodoc:
115
117
  xml.tag! 'n2:OrderDescription', options[:description]
116
118
  xml.tag! 'n2:InvoiceID', options[:order_id]
117
119
 
118
- if options[:items]
119
- options[:items].each do |item|
120
- xml.tag! 'n2:PaymentDetailsItem' do
121
- xml.tag! 'n2:Name', item[:name]
122
- xml.tag! 'n2:Number', item[:number]
123
- xml.tag! 'n2:Quantity', item[:quantity]
124
- if item[:amount]
125
- xml.tag! 'n2:Amount', localized_amount(item[:amount], currency_code), 'currencyID' => currency_code
126
- end
127
- xml.tag! 'n2:Description', item[:description]
128
- xml.tag! 'n2:ItemURL', item[:url]
129
- end
130
- end
131
- end
120
+ add_items_xml(xml, options, currency_code) if options[:items]
121
+
122
+ add_address(xml, 'n2:ShipToAddress', options[:shipping_address] || options[:address])
132
123
 
133
124
  xml.tag! 'n2:PaymentAction', action
134
125
  end
135
126
 
136
- add_address(xml, 'n2:Address', options[:shipping_address] || options[:address])
137
127
  xml.tag! 'n2:AddressOverride', options[:address_override] ? '1' : '0'
138
128
  xml.tag! 'n2:NoShipping', options[:no_shipping] ? '1' : '0'
139
129
  xml.tag! 'n2:ReturnURL', options[:return_url]
@@ -172,6 +162,23 @@ module ActiveMerchant #:nodoc:
172
162
  def build_response(success, message, response, options = {})
173
163
  PaypalExpressResponse.new(success, message, response, options)
174
164
  end
165
+
166
+ private
167
+
168
+ def add_items_xml(xml, options, currency_code)
169
+ options[:items].each do |item|
170
+ xml.tag! 'n2:PaymentDetailsItem' do
171
+ xml.tag! 'n2:Name', item[:name]
172
+ xml.tag! 'n2:Number', item[:number]
173
+ xml.tag! 'n2:Quantity', item[:quantity]
174
+ if item[:amount]
175
+ xml.tag! 'n2:Amount', localized_amount(item[:amount], currency_code), 'currencyID' => currency_code
176
+ end
177
+ xml.tag! 'n2:Description', item[:description]
178
+ xml.tag! 'n2:ItemURL', item[:url]
179
+ end
180
+ end
181
+ end
175
182
  end
176
183
  end
177
184
  end
@@ -8,30 +8,91 @@ module ActiveMerchant #:nodoc:
8
8
 
9
9
  self.default_currency = 'DKK'
10
10
  self.money_format = :cents
11
- self.supported_cardtypes = [ :dankort, :forbrugsforeningen, :visa, :master, :american_express, :diners_club, :jcb, :maestro ]
11
+ self.supported_cardtypes = [:dankort, :forbrugsforeningen, :visa, :master, :american_express, :diners_club, :jcb, :maestro]
12
12
  self.supported_countries = ['DK', 'SE']
13
13
  self.homepage_url = 'http://quickpay.dk/'
14
14
  self.display_name = 'Quickpay'
15
15
 
16
- PROTOCOL = 3
17
-
18
16
  MD5_CHECK_FIELDS = {
19
- :authorize => [:protocol, :msgtype, :merchant, :ordernumber, :amount, :currency, :autocapture, :cardnumber, :expirationdate, :cvd, :cardtypelock, :testmode],
20
- :capture => [:protocol, :msgtype, :merchant, :amount, :transaction],
21
- :cancel => [:protocol, :msgtype, :merchant, :transaction],
22
- :refund => [:protocol, :msgtype, :merchant, :amount, :transaction],
23
- :subscribe => [:protocol, :msgtype, :merchant, :ordernumber, :cardnumber, :expirationdate, :cvd, :cardtypelock, :description, :testmode],
24
- :recurring => [:protocol, :msgtype, :merchant, :ordernumber, :amount, :currency, :autocapture, :transaction],
25
- :status => [:protocol, :msgtype, :merchant, :transaction],
26
- :chstatus => [:protocol, :msgtype, :merchant],
17
+ 3 => {
18
+ :authorize => %w(protocol msgtype merchant ordernumber amount
19
+ currency autocapture cardnumber expirationdate
20
+ cvd cardtypelock testmode),
21
+
22
+ :capture => %w(protocol msgtype merchant amount transaction),
23
+
24
+ :cancel => %w(protocol msgtype merchant transaction),
25
+
26
+ :refund => %w(protocol msgtype merchant amount transaction),
27
+
28
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
29
+ expirationdate cvd cardtypelock description testmode),
30
+
31
+ :recurring => %w(protocol msgtype merchant ordernumber amount
32
+ currency autocapture transaction),
33
+
34
+ :status => %w(protocol msgtype merchant transaction),
35
+
36
+ :chstatus => %w(protocol msgtype merchant)
37
+ },
38
+
39
+ 4 => {
40
+ :authorize => %w(protocol msgtype merchant ordernumber amount
41
+ currency autocapture cardnumber expirationdate cvd
42
+ cardtypelock testmode fraud_remote_addr
43
+ fraud_http_accept fraud_http_accept_language
44
+ fraud_http_accept_encoding fraud_http_accept_charset
45
+ fraud_http_referer fraud_http_user_agent apikey),
46
+
47
+ :capture => %w(protocol msgtype merchant amount transaction
48
+ fraud_remote_addr fraud_http_accept
49
+ fraud_http_accept_language fraud_http_accept_encoding
50
+ fraud_http_accept_charset fraud_http_referer
51
+ fraud_http_user_agent apikey),
52
+
53
+ :cancel => %w(protocol msgtype merchant transaction fraud_remote_addr
54
+ fraud_http_accept fraud_http_accept_language
55
+ fraud_http_accept_encoding fraud_http_accept_charset
56
+ fraud_http_referer fraud_http_user_agent apikey),
57
+
58
+ :refund => %w(protocol msgtype merchant amount transaction
59
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
60
+ fraud_http_accept_encoding fraud_http_accept_charset
61
+ fraud_http_referer fraud_http_user_agent apikey),
62
+
63
+ :subscribe => %w(protocol msgtype merchant ordernumber cardnumber
64
+ expirationdate cvd cardtypelock description testmode
65
+ fraud_remote_addr fraud_http_accept fraud_http_accept_language
66
+ fraud_http_accept_encoding fraud_http_accept_charset
67
+ fraud_http_referer fraud_http_user_agent apikey),
68
+
69
+ :recurring => %w(protocol msgtype merchant ordernumber amount currency
70
+ autocapture transaction fraud_remote_addr fraud_http_accept
71
+ fraud_http_accept_language fraud_http_accept_encoding
72
+ fraud_http_accept_charset fraud_http_referer
73
+ fraud_http_user_agent apikey),
74
+
75
+ :status => %w(protocol msgtype merchant transaction fraud_remote_addr
76
+ fraud_http_accept fraud_http_accept_language
77
+ fraud_http_accept_encoding fraud_http_accept_charset
78
+ fraud_http_referer fraud_http_user_agent apikey),
79
+
80
+ :chstatus => %w(protocol msgtype merchant fraud_remote_addr fraud_http_accept
81
+ fraud_http_accept_language fraud_http_accept_encoding
82
+ fraud_http_accept_charset fraud_http_referer
83
+ fraud_http_user_agent apikey)
84
+ }
27
85
  }
28
86
 
29
87
  APPROVED = '000'
30
88
 
31
89
  # The login is the QuickpayId
32
- # The password is the md5checkword from the Quickpay admin interface
90
+ # The password is the md5checkword from the Quickpay manager
91
+ # To use the API-key from the Quickpay manager, specify :api-key
92
+ # Using the API-key, requires that you use version 4. Specify :version => 4 in options.
33
93
  def initialize(options = {})
34
94
  requires!(options, :login, :password)
95
+ @protocol = options.delete(:version) || 3 # default to protocol version 3
35
96
  @options = options
36
97
  super
37
98
  end
@@ -43,6 +104,7 @@ module ActiveMerchant #:nodoc:
43
104
  add_invoice(post, options)
44
105
  add_creditcard_or_reference(post, credit_card_or_reference, options)
45
106
  add_autocapture(post, false)
107
+ add_fraud_parameters(post, options)
46
108
  add_testmode(post)
47
109
 
48
110
  commit(recurring_or_authorize(credit_card_or_reference), post)
@@ -54,6 +116,7 @@ module ActiveMerchant #:nodoc:
54
116
  add_amount(post, money, options)
55
117
  add_creditcard_or_reference(post, credit_card_or_reference, options)
56
118
  add_invoice(post, options)
119
+ add_fraud_parameters(post, options)
57
120
  add_autocapture(post, true)
58
121
 
59
122
  commit(recurring_or_authorize(credit_card_or_reference), post)
@@ -64,6 +127,7 @@ module ActiveMerchant #:nodoc:
64
127
 
65
128
  add_reference(post, authorization)
66
129
  add_amount_without_currency(post, money)
130
+ add_fraud_parameters(post, options)
67
131
 
68
132
  commit(:capture, post)
69
133
  end
@@ -72,6 +136,7 @@ module ActiveMerchant #:nodoc:
72
136
  post = {}
73
137
 
74
138
  add_reference(post, identification)
139
+ add_fraud_parameters(post, options)
75
140
 
76
141
  commit(:cancel, post)
77
142
  end
@@ -81,6 +146,7 @@ module ActiveMerchant #:nodoc:
81
146
 
82
147
  add_amount_without_currency(post, money)
83
148
  add_reference(post, identification)
149
+ add_fraud_parameters(post, options)
84
150
 
85
151
  commit(:refund, post)
86
152
  end
@@ -96,6 +162,7 @@ module ActiveMerchant #:nodoc:
96
162
  add_creditcard(post, creditcard, options)
97
163
  add_invoice(post, options)
98
164
  add_description(post, options)
165
+ add_fraud_parameters(post, options)
99
166
  add_testmode(post)
100
167
 
101
168
  commit(:subscribe, post)
@@ -150,6 +217,18 @@ module ActiveMerchant #:nodoc:
150
217
  def add_testmode(post)
151
218
  post[:testmode] = test? ? '1' : '0'
152
219
  end
220
+
221
+ def add_fraud_parameters(post, options)
222
+ if @protocol == 4
223
+ post[:fraud_remote_addr] = options[:fraud_remote_addr] if options[:fraud_remote_addr]
224
+ post[:fraud_http_accept] = options[:fraud_http_accept] if options[:fraud_http_accept]
225
+ post[:fraud_http_accept_language] = options[:fraud_http_accept_language] if options[:fraud_http_accept_language]
226
+ post[:fraud_http_accept_encoding] = options[:fraud_http_accept_encoding] if options[:fraud_http_accept_encoding]
227
+ post[:fraud_http_accept_charset] = options[:fraud_http_accept_charset] if options[:fraud_http_accept_charset]
228
+ post[:fraud_http_referer] = options[:fraud_http_referer] if options[:fraud_http_referer]
229
+ post[:fraud_http_user_agent] = options[:fraud_http_user_agent] if options[:fraud_http_user_agent]
230
+ end
231
+ end
153
232
 
154
233
  def commit(action, params)
155
234
  response = parse(ssl_post(URL, post_data(action, params)))
@@ -177,27 +256,22 @@ module ActiveMerchant #:nodoc:
177
256
  end
178
257
 
179
258
  def message_from(response)
180
- case response[:qpstat]
181
- when '008' # Error in request data
182
- response[:qpstatmsg].to_s
183
- #.scan(/[A-Z][a-z0-9 \/]+/).to_sentence
184
- else
185
- response[:qpstatmsg].to_s
186
- end
259
+ response[:qpstatmsg].to_s
187
260
  end
188
261
 
189
262
  def post_data(action, params = {})
190
- params[:protocol] = PROTOCOL
263
+ params[:protocol] = @protocol
191
264
  params[:msgtype] = action.to_s
192
265
  params[:merchant] = @options[:login]
266
+ params[:apikey] = @options[:apikey] if @options[:apikey]
193
267
  params[:md5check] = generate_check_hash(action, params)
194
268
 
195
269
  params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
196
270
  end
197
271
 
198
272
  def generate_check_hash(action, params)
199
- string = MD5_CHECK_FIELDS[action].collect do |key|
200
- params[key]
273
+ string = MD5_CHECK_FIELDS[@protocol][action].collect do |key|
274
+ params[key.to_sym]
201
275
  end.join('')
202
276
 
203
277
  # Add the md5checkword