activemerchant 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +58 -0
  3. data/CONTRIBUTERS +25 -0
  4. data/MIT-LICENSE +3 -3
  5. data/README +16 -10
  6. data/Rakefile +4 -3
  7. data/lib/active_merchant.rb +7 -1
  8. data/lib/active_merchant/billing/check.rb +16 -9
  9. data/lib/active_merchant/billing/gateway.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +702 -0
  11. data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
  12. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +233 -0
  13. data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
  14. data/lib/active_merchant/billing/gateways/braintree.rb +10 -1
  15. data/lib/active_merchant/billing/gateways/cyber_source.rb +26 -2
  16. data/lib/active_merchant/billing/gateways/data_cash.rb +255 -59
  17. data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
  18. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +214 -0
  19. data/lib/active_merchant/billing/gateways/net_registry.rb +1 -0
  20. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +2 -2
  21. data/lib/active_merchant/billing/gateways/payflow_express.rb +3 -11
  22. data/lib/active_merchant/billing/gateways/payment_express.rb +2 -2
  23. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +39 -21
  24. data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
  25. data/lib/active_merchant/billing/gateways/paypal_express.rb +3 -12
  26. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
  27. data/lib/active_merchant/billing/gateways/protx.rb +25 -25
  28. data/lib/active_merchant/billing/gateways/sage.rb +145 -0
  29. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
  30. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +110 -0
  31. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
  32. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +3 -1
  33. data/lib/active_merchant/billing/gateways/skip_jack.rb +2 -0
  34. data/lib/active_merchant/billing/gateways/trust_commerce.rb +1 -1
  35. data/lib/active_merchant/billing/gateways/wirecard.rb +304 -0
  36. data/lib/active_merchant/billing/integrations.rb +8 -2
  37. data/lib/active_merchant/billing/integrations/action_view_helper.rb +18 -4
  38. data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +4 -2
  39. data/lib/active_merchant/billing/integrations/notification.rb +10 -1
  40. data/lib/active_merchant/lib/posts_data.rb +12 -3
  41. data/script/destroy +0 -0
  42. data/script/generate +0 -0
  43. data/test/extra/binding_of_caller.rb +0 -0
  44. data/test/extra/breakpoint.rb +0 -0
  45. data/test/fixtures.yml +24 -0
  46. data/test/remote/gateways/remote_authorize_net_cim_test.rb +459 -0
  47. data/test/remote/gateways/remote_beanstream_interac_test.rb +53 -0
  48. data/test/remote/gateways/remote_beanstream_test.rb +150 -0
  49. data/test/remote/gateways/remote_braintree_test.rb +22 -0
  50. data/test/remote/gateways/remote_cyber_source_test.rb +28 -3
  51. data/test/remote/gateways/remote_data_cash_test.rb +250 -48
  52. data/test/remote/gateways/remote_modern_payments_cim_test.rb +58 -0
  53. data/test/remote/gateways/remote_modern_payments_test.rb +43 -0
  54. data/test/remote/gateways/remote_sage_bankcard_test.rb +109 -0
  55. data/test/remote/gateways/remote_sage_test.rb +87 -0
  56. data/test/remote/gateways/remote_sage_virtual_check_test.rb +62 -0
  57. data/test/remote/gateways/remote_wirecard_test.rb +76 -0
  58. data/test/remote/integrations/remote_paypal_integration_test.rb +15 -3
  59. data/test/test_helper.rb +31 -13
  60. data/test/unit/check_test.rb +14 -2
  61. data/test/unit/credit_card_methods_test.rb +18 -0
  62. data/test/unit/gateways/authorize_net_cim_test.rb +641 -0
  63. data/test/unit/gateways/beanstream_interac_test.rb +51 -0
  64. data/test/unit/gateways/beanstream_test.rb +108 -0
  65. data/test/unit/gateways/braintree_test.rb +2 -5
  66. data/test/unit/gateways/cyber_source_test.rb +18 -0
  67. data/test/unit/gateways/data_cash_test.rb +32 -4
  68. data/test/unit/gateways/gateway_test.rb +8 -1
  69. data/test/unit/gateways/modern_payments_cim_test.rb +171 -0
  70. data/test/unit/gateways/net_registry_test.rb +6 -0
  71. data/test/unit/gateways/payflow_express_test.rb +18 -2
  72. data/test/unit/gateways/paypal_express_test.rb +154 -0
  73. data/test/unit/gateways/paypal_test.rb +140 -0
  74. data/test/unit/gateways/sage_bankcard_test.rb +162 -0
  75. data/test/unit/gateways/sage_virtual_check_test.rb +71 -0
  76. data/test/unit/gateways/secure_pay_au_test.rb +58 -1
  77. data/test/unit/gateways/skip_jack_test.rb +8 -0
  78. data/test/unit/gateways/verifi_test.rb +0 -1
  79. data/test/unit/gateways/wirecard_test.rb +232 -0
  80. data/test/unit/integrations/action_view_helper_test.rb +3 -0
  81. data/test/unit/integrations/notifications/hi_trust_notification_test.rb +23 -2
  82. data/test/unit/integrations/notifications/notification_test.rb +13 -0
  83. data/test/unit/posts_data_test.rb +20 -6
  84. metadata +40 -5
  85. metadata.gz.sig +0 -0
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/modern_payments_cim'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class ModernPaymentsGateway < Gateway
6
+ self.supported_countries = ModernPaymentsCimGateway.supported_countries
7
+ self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes
8
+ self.homepage_url = ModernPaymentsCimGateway.homepage_url
9
+ self.display_name = ModernPaymentsCimGateway.display_name
10
+
11
+ def initialize(options = {})
12
+ requires!(options, :login, :password)
13
+ @options = options
14
+ super
15
+ end
16
+
17
+ def purchase(money, credit_card, options = {})
18
+ customer_response = cim.create_customer(options)
19
+ return customer_response unless customer_response.success?
20
+
21
+ customer_id = customer_response.params["create_customer_result"]
22
+
23
+ card_response = cim.modify_customer_credit_card(customer_id, credit_card)
24
+ return card_response unless card_response.success?
25
+
26
+ cim.authorize_credit_card_payment(customer_id, money)
27
+ end
28
+
29
+ private
30
+ def cim
31
+ @cim ||= ModernPaymentsCimGateway.new(@options)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,214 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class ModernPaymentsCimGateway < Gateway #:nodoc:
4
+ TEST_URL = "https://secure.modpay.com/netservices/test/ModpayTest.asmx"
5
+ LIVE_URL = 'https://secure.modpay.com/ws/modpay.asmx'
6
+
7
+ LIVE_XMLNS = "http://secure.modpay.com:81/ws/"
8
+ TEST_XMLNS = "https://secure.modpay.com/netservices/test/"
9
+
10
+ self.supported_countries = ['US']
11
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
12
+ self.homepage_url = 'http://www.modpay.com'
13
+ self.display_name = 'Modern Payments'
14
+
15
+ SUCCESS_MESSAGE = "Transaction accepted"
16
+ FAILURE_MESSAGE = "Transaction failed"
17
+ ERROR_MESSAGE = "Transaction error"
18
+
19
+ PAYMENT_METHOD = {
20
+ :check => 1,
21
+ :credit_card => 2
22
+ }
23
+
24
+ def initialize(options = {})
25
+ requires!(options, :login, :password)
26
+ @options = options
27
+ super
28
+ end
29
+
30
+ def create_customer(options = {})
31
+ post = {}
32
+ add_customer_data(post, options)
33
+ add_address(post, options)
34
+
35
+ commit('CreateCustomer', post)
36
+ end
37
+
38
+ def modify_customer_credit_card(customer_id, credit_card)
39
+ raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
40
+
41
+ post = {}
42
+ add_customer_id(post, customer_id)
43
+ add_credit_card(post, credit_card)
44
+
45
+ commit('ModifyCustomerCreditCard', post)
46
+ end
47
+
48
+ def authorize_credit_card_payment(customer_id, amount)
49
+ raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
50
+
51
+ post = {}
52
+ add_customer_id(post, customer_id)
53
+ add_amount(post, amount)
54
+
55
+ commit('AuthorizeCreditCardPayment', post)
56
+ end
57
+
58
+ def create_payment(customer_id, amount, options = {})
59
+ raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
60
+
61
+ post = {}
62
+ add_customer_id(post, customer_id)
63
+ add_amount(post, amount)
64
+ add_payment_details(post, options)
65
+
66
+ commit('CreatePayment', post)
67
+ end
68
+
69
+ private
70
+ def add_payment_details(post, options)
71
+ post[:pmtDate] = (options[:payment_date] || Time.now.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
72
+ post[:pmtType] = PAYMENT_METHOD[options[:payment_method] || :credit_card]
73
+ end
74
+
75
+ def add_amount(post, money)
76
+ post[:pmtAmount] = amount(money)
77
+ end
78
+
79
+ def add_customer_id(post, customer_id)
80
+ post[:custId] = customer_id
81
+ end
82
+
83
+ def add_customer_data(post, options)
84
+ post[:acctNum] = options[:customer]
85
+ end
86
+
87
+ def add_address(post, options)
88
+ address = options[:billing_address] || options[:address] || {}
89
+
90
+ if name = address[:name]
91
+ segments = name.split(' ')
92
+ post[:lastName] = segments.pop
93
+ post[:firstName] = segments.join(' ')
94
+ else
95
+ post[:firstName] = address[:first_name]
96
+ post[:lastName] = address[:last_name]
97
+ end
98
+
99
+ post[:address] = address[:address1]
100
+ post[:city] = address[:city]
101
+ post[:state] = address[:state]
102
+ post[:zip] = address[:zip]
103
+ post[:phone] = address[:phone]
104
+ post[:fax] = address[:fax]
105
+ post[:email] = address[:email]
106
+ end
107
+
108
+ def add_credit_card(post, credit_card)
109
+ post[:ccName] = credit_card.name
110
+ post[:ccNum] = credit_card.number
111
+ post[:expMonth] = credit_card.month
112
+ post[:expYear] = credit_card.year
113
+ end
114
+
115
+ def build_request(action, params)
116
+ xml = Builder::XmlMarkup.new :indent => 2
117
+ xml.instruct!
118
+ xml.tag! 'env:Envelope',
119
+ { 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
120
+ 'xmlns:env' => 'http://schemas.xmlsoap.org/soap/envelope/',
121
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance' } do
122
+
123
+ xml.tag! 'env:Body' do
124
+ xml.tag! action, { "xmlns" => xmlns(action) } do
125
+ xml.tag! "clientId", @options[:login]
126
+ xml.tag! "clientCode", @options[:password]
127
+ params.each {|key, value| xml.tag! key, value }
128
+ end
129
+ end
130
+ end
131
+ xml.target!
132
+ end
133
+
134
+ def xmlns(action)
135
+ if test? && action == 'AuthorizeCreditCardPayment'
136
+ TEST_XMLNS
137
+ else
138
+ LIVE_XMLNS
139
+ end
140
+ end
141
+
142
+ def url(action)
143
+ if test? && action == 'AuthorizeCreditCardPayment'
144
+ TEST_URL
145
+ else
146
+ LIVE_URL
147
+ end
148
+ end
149
+
150
+ def commit(action, params)
151
+ data = ssl_post(url(action), build_request(action, params),
152
+ { 'Content-Type' =>'text/xml; charset=utf-8',
153
+ 'SOAPAction' => "#{xmlns(action)}#{action}" }
154
+ )
155
+
156
+ response = parse(action, data)
157
+ Response.new(successful?(action, response), message_from(action, response), response,
158
+ :test => test?,
159
+ :authorization => authorization_from(action, response),
160
+ :avs_result => { :code => response[:avs_code] }
161
+ )
162
+ end
163
+
164
+ def authorization_from(action, response)
165
+ response[result_key(action)]
166
+ end
167
+
168
+ def result_key(action)
169
+ action == "AuthorizeCreditCardPayment" ? :trans_id : "#{action.underscore}_result".to_sym
170
+ end
171
+
172
+ def successful?(action, response)
173
+ response[result_key(action)].to_i > 0
174
+ end
175
+
176
+ def message_from(action, response)
177
+ if response[:faultcode]
178
+ ERROR_MESSAGE
179
+ elsif successful?(action, response)
180
+ SUCCESS_MESSAGE
181
+ else
182
+ FAILURE_MESSAGE
183
+ end
184
+ end
185
+
186
+ def parse(action, xml)
187
+ response = {}
188
+ response[:action] = action
189
+
190
+ xml = REXML::Document.new(xml)
191
+ if root = REXML::XPath.first(xml, "//#{action}Response")
192
+ root.elements.to_a.each do |node|
193
+ parse_element(response, node)
194
+ end
195
+ elsif root = REXML::XPath.first(xml, "//soap:Fault")
196
+ root.elements.to_a.each do |node|
197
+ response[node.name.underscore.to_sym] = node.text
198
+ end
199
+ end
200
+
201
+ response
202
+ end
203
+
204
+ def parse_element(response, node)
205
+ if node.has_elements?
206
+ node.elements.each{|e| parse_element(response, e) }
207
+ else
208
+ response[node.name.underscore.to_sym] = node.text
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+
@@ -72,6 +72,7 @@ module ActiveMerchant
72
72
  # described in "Programming for NetRegistry's E-commerce
73
73
  # Gateway." [http://rubyurl.com/hNG]
74
74
  def capture(money, authorization, options = {})
75
+ requires!(options, :credit_card)
75
76
  credit_card = options[:credit_card]
76
77
 
77
78
  params = {
@@ -28,8 +28,8 @@ module ActiveMerchant #:nodoc:
28
28
  end
29
29
 
30
30
  XMLNS = 'http://www.paypal.com/XMLPay'
31
- TEST_URL = 'https://pilot-payflowpro.verisign.com'
32
- LIVE_URL = 'https://payflowpro.verisign.com'
31
+ TEST_URL = 'https://pilot-payflowpro.paypal.com'
32
+ LIVE_URL = 'https://payflowpro.paypal.com'
33
33
 
34
34
  CARD_MAPPING = {
35
35
  :visa => 'Visa',
@@ -1,25 +1,17 @@
1
1
  require File.dirname(__FILE__) + '/payflow/payflow_common_api'
2
2
  require File.dirname(__FILE__) + '/payflow/payflow_express_response'
3
+ require File.dirname(__FILE__) + '/paypal_express_common'
3
4
 
4
5
  module ActiveMerchant #:nodoc:
5
6
  module Billing #:nodoc:
6
7
  class PayflowExpressGateway < Gateway
7
8
  include PayflowCommonAPI
9
+ include PaypalExpressCommon
8
10
 
9
- LIVE_REDIRECT_URL = 'https://www.paypal.com/cgibin/webscr?cmd=_express-checkout&token='
10
- TEST_REDIRECT_URL = 'https://test-expresscheckout.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='
11
-
11
+ self.test_redirect_url = 'https://test-expresscheckout.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='
12
12
  self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=xpt/merchant/ExpressCheckoutIntro-outside'
13
13
  self.display_name = 'PayPal Express Checkout'
14
14
 
15
- def redirect_url
16
- test? ? TEST_REDIRECT_URL : LIVE_REDIRECT_URL
17
- end
18
-
19
- def redirect_url_for(token)
20
- "#{redirect_url}#{token}"
21
- end
22
-
23
15
  def authorize(money, options = {})
24
16
  requires!(options, :token, :payer_id)
25
17
  request = build_sale_or_authorization_request('Authorization', money, options)
@@ -21,7 +21,7 @@ module ActiveMerchant #:nodoc:
21
21
  self.homepage_url = 'http://www.paymentexpress.com/'
22
22
  self.display_name = 'PaymentExpress'
23
23
 
24
- PAYMENT_URL = 'https://www.paymentexpress.com/pxpost.aspx'
24
+ URL = 'https://www.paymentexpress.com/pxpost.aspx'
25
25
 
26
26
  APPROVED = '1'
27
27
 
@@ -196,7 +196,7 @@ module ActiveMerchant #:nodoc:
196
196
  add_transaction_type(request, action)
197
197
 
198
198
  # Parse the XML response
199
- response = parse( ssl_post(PAYMENT_URL, request.to_s) )
199
+ response = parse( ssl_post(URL, request.to_s) )
200
200
 
201
201
  # Return a response
202
202
  PaymentExpressResponse.new(response[:success] == APPROVED, response[:response_text], response,
@@ -8,7 +8,7 @@ module ActiveMerchant #:nodoc:
8
8
  base.cattr_accessor :signature
9
9
  end
10
10
 
11
- API_VERSION = '2.0'
11
+ API_VERSION = '52.0'
12
12
 
13
13
  URLS = {
14
14
  :test => { :certificate => 'https://api.sandbox.paypal.com/2.0/',
@@ -42,6 +42,8 @@ module ActiveMerchant #:nodoc:
42
42
 
43
43
  SUCCESS_CODES = [ 'Success', 'SuccessWithWarning' ]
44
44
 
45
+ FRAUD_REVIEW_CODE = "11610"
46
+
45
47
  # The gateway must be configured with either your PayPal PEM file
46
48
  # or your PayPal API Signature. Only one is required.
47
49
  #
@@ -109,7 +111,7 @@ module ActiveMerchant #:nodoc:
109
111
 
110
112
  private
111
113
  def build_reauthorize_request(money, authorization, options)
112
- xml = Builder::XmlMarkup.new :indent => 2
114
+ xml = Builder::XmlMarkup.new
113
115
 
114
116
  xml.tag! 'DoReauthorizationReq', 'xmlns' => PAYPAL_NAMESPACE do
115
117
  xml.tag! 'DoReauthorizationRequest', 'xmlns:n2' => EBAY_NAMESPACE do
@@ -123,7 +125,7 @@ module ActiveMerchant #:nodoc:
123
125
  end
124
126
 
125
127
  def build_capture_request(money, authorization, options)
126
- xml = Builder::XmlMarkup.new :indent => 2
128
+ xml = Builder::XmlMarkup.new
127
129
 
128
130
  xml.tag! 'DoCaptureReq', 'xmlns' => PAYPAL_NAMESPACE do
129
131
  xml.tag! 'DoCaptureRequest', 'xmlns:n2' => EBAY_NAMESPACE do
@@ -139,7 +141,7 @@ module ActiveMerchant #:nodoc:
139
141
  end
140
142
 
141
143
  def build_credit_request(money, identification, options)
142
- xml = Builder::XmlMarkup.new :indent => 2
144
+ xml = Builder::XmlMarkup.new
143
145
 
144
146
  xml.tag! 'RefundTransactionReq', 'xmlns' => PAYPAL_NAMESPACE do
145
147
  xml.tag! 'RefundTransactionRequest', 'xmlns:n2' => EBAY_NAMESPACE do
@@ -155,7 +157,7 @@ module ActiveMerchant #:nodoc:
155
157
  end
156
158
 
157
159
  def build_void_request(authorization, options)
158
- xml = Builder::XmlMarkup.new :indent => 2
160
+ xml = Builder::XmlMarkup.new
159
161
 
160
162
  xml.tag! 'DoVoidReq', 'xmlns' => PAYPAL_NAMESPACE do
161
163
  xml.tag! 'DoVoidRequest', 'xmlns:n2' => EBAY_NAMESPACE do
@@ -172,7 +174,7 @@ module ActiveMerchant #:nodoc:
172
174
  default_options = args.last.is_a?(Hash) ? args.pop : {}
173
175
  recipients = args.first.is_a?(Array) ? args : [args]
174
176
 
175
- xml = Builder::XmlMarkup.new :indent => 2
177
+ xml = Builder::XmlMarkup.new
176
178
 
177
179
  xml.tag! 'MassPayReq', 'xmlns' => PAYPAL_NAMESPACE do
178
180
  xml.tag! 'MassPayRequest', 'xmlns:n2' => EBAY_NAMESPACE do
@@ -192,19 +194,41 @@ module ActiveMerchant #:nodoc:
192
194
 
193
195
  xml.target!
194
196
  end
195
-
197
+
196
198
  def parse(action, xml)
197
199
  response = {}
200
+
201
+ error_messages = []
202
+ error_codes = []
203
+
198
204
  xml = REXML::Document.new(xml)
199
205
  if root = REXML::XPath.first(xml, "//#{action}Response")
200
- root.elements.to_a.each do |node|
206
+ root.elements.each do |node|
201
207
  case node.name
202
208
  when 'Errors'
203
- response[:message] = node.elements.to_a('//LongMessage').collect{|error| error.text}.join('.')
209
+ short_message = nil
210
+ long_message = nil
211
+
212
+ node.elements.each do |child|
213
+ case child.name
214
+ when "LongMessage"
215
+ long_message = child.text unless child.text.blank?
216
+ when "ShortMessage"
217
+ short_message = child.text unless child.text.blank?
218
+ when "ErrorCode"
219
+ error_codes << child.text unless child.text.blank?
220
+ end
221
+ end
222
+
223
+ if message = long_message || short_message
224
+ error_messages << message
225
+ end
204
226
  else
205
227
  parse_element(response, node)
206
228
  end
207
229
  end
230
+ response[:message] = error_messages.uniq.join(". ") unless error_messages.empty?
231
+ response[:error_codes] = error_codes.uniq.join(",") unless error_codes.empty?
208
232
  elsif root = REXML::XPath.first(xml, "//SOAP-ENV:Fault")
209
233
  parse_element(response, root)
210
234
  response[:message] = "#{response[:faultcode]}: #{response[:faultstring]} - #{response[:detail]}"
@@ -224,19 +248,8 @@ module ActiveMerchant #:nodoc:
224
248
  end
225
249
  end
226
250
 
227
- def response_type_for(action)
228
- case action
229
- when 'Authorization', 'Purchase'
230
- 'DoDirectPaymentResponse'
231
- when 'Void'
232
- 'DoVoidResponse'
233
- when 'Capture'
234
- 'DoCaptureResponse'
235
- end
236
- end
237
-
238
251
  def build_request(body)
239
- xml = Builder::XmlMarkup.new :indent => 2
252
+ xml = Builder::XmlMarkup.new
240
253
 
241
254
  xml.instruct!
242
255
  xml.tag! 'env:Envelope', ENVELOPE_NAMESPACES do
@@ -286,11 +299,16 @@ module ActiveMerchant #:nodoc:
286
299
  build_response(successful?(response), message_from(response), response,
287
300
  :test => test?,
288
301
  :authorization => authorization_from(response),
302
+ :fraud_review => fraud_review?(response),
289
303
  :avs_result => { :code => response[:avs_code] },
290
304
  :cvv_result => response[:cvv2_code]
291
305
  )
292
306
  end
293
307
 
308
+ def fraud_review?(response)
309
+ response[:error_codes] == FRAUD_REVIEW_CODE
310
+ end
311
+
294
312
  def authorization_from(response)
295
313
  response[:transaction_id] || response[:authorization_id] # latter one is from reauthorization
296
314
  end