activemerchant 1.16.0 → 1.17.0

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