activemerchant-payrix 0.0.1

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,92 @@
1
+ require 'test_helper'
2
+
3
+ class RemotePayrixTest < Test::Unit::TestCase
4
+ AMOUNTS = {
5
+ invalid_card: 31,
6
+ expired_card: 54,
7
+ declined: 51,
8
+ insufficient_funds: 61,
9
+ technical_failure: 96
10
+ }
11
+
12
+ def setup
13
+ @gateway = PayrixGateway.new(fixtures(:payrix))
14
+
15
+ @amount = 100_00
16
+ @credit_card = credit_card('4000100011112224')
17
+ @declined_card = credit_card('4000300011112220')
18
+
19
+ @options = {
20
+ billing_address: address,
21
+ description: 'Store Purchase',
22
+ return_url: 'https://app.black.test/payrix',
23
+ transaction_reference: SecureRandom.hex(16),
24
+ email: 'user@example.com'
25
+ }
26
+ end
27
+
28
+ def test_successful_setup_purchase
29
+ response = @gateway.setup_purchase(@amount, @options)
30
+ assert_success response
31
+ assert_equal 'Succeeded', response.message
32
+ end
33
+
34
+ def test_successful_setup_purchase_with_more_options
35
+ options = @options.merge({ ip: '127.0.0.1', phone: '021 902 123' })
36
+
37
+ response = @gateway.setup_purchase(@amount, options)
38
+ assert_success response
39
+ assert_equal 'Succeeded', response.message
40
+ end
41
+
42
+ def test_failed_setup_purchase
43
+ options = @options.merge({ transaction_reference: nil })
44
+ response = @gateway.setup_purchase(@amount, options)
45
+ assert_failure response
46
+ assert_equal 'Reference is required', response.message
47
+ end
48
+
49
+ def test_failed_setup_purchase_and_details_for_token
50
+ response =
51
+ @gateway.setup_purchase(@amount + AMOUNTS[:invalid_card], @options)
52
+ assert_success response
53
+ assert_equal 'Succeeded', response.message
54
+ assert response.params['token']
55
+
56
+ details_response = @gateway.details_for(response.params['token'])
57
+ assert_failure details_response
58
+ end
59
+
60
+ def test_successful_setup_authorize
61
+ response = @gateway.setup_authorize(@amount, @options)
62
+ assert_success response
63
+ assert_equal 'Succeeded', response.message
64
+ end
65
+
66
+ # def test_failed_setup_authorize
67
+ # response = @gateway.setup_authorize(@amount, @options)
68
+ # assert_failure response
69
+ # assert_equal 'REPLACE WITH FAILED AUTHORIZE MESSAGE', response.message
70
+ # end
71
+
72
+ # def test_successful_setup_verify
73
+ # response = @gateway.setup_verify(@options)
74
+ # assert_success response
75
+ # assert_match(/REPLACE WITH SUCCESS MESSAGE/, response.message)
76
+ # end
77
+
78
+ # def test_failed_setup_verify
79
+ # response = @gateway.setup_verify(@options)
80
+ # assert_failure response
81
+ # assert_match(/REPLACE WITH FAILED PURCHASE MESSAGE/, response.message)
82
+ # end
83
+
84
+ def test_invalid_login
85
+ gateway =
86
+ PayrixGateway.new(fixtures(:payrix).merge(login: '', password: ''))
87
+
88
+ response = gateway.setup_purchase(@amount, @options)
89
+ assert_failure response
90
+ assert_match(/The Password field is required./, response.message)
91
+ end
92
+ end
@@ -0,0 +1,404 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'bundler/setup'
4
+
5
+ require 'test/unit'
6
+ require 'mocha/test_unit'
7
+
8
+ require 'yaml'
9
+ require 'json'
10
+ require 'active_merchant'
11
+ require 'comm_stub'
12
+ require 'activemerchant/billing/gateways/payrix'
13
+
14
+ # require 'active_support/core_ext/integer/time'
15
+ # require 'active_support/core_ext/numeric/time'
16
+ # require 'active_support/core_ext/time/acts_like'
17
+
18
+ ActiveMerchant::Billing::Base.mode = :test
19
+
20
+ if ENV['DEBUG_ACTIVE_MERCHANT'] == 'true'
21
+ require 'logger'
22
+ ActiveMerchant::Billing::Gateway.logger = Logger.new(STDOUT)
23
+ ActiveMerchant::Billing::Gateway.wiredump_device = STDOUT
24
+ end
25
+
26
+ # Test gateways
27
+ class SimpleTestGateway < ActiveMerchant::Billing::Gateway
28
+ end
29
+
30
+ class SubclassGateway < SimpleTestGateway
31
+ end
32
+
33
+ module ActiveMerchant
34
+ module Assertions
35
+ ASSERTION_CLASS =
36
+ if defined?(Minitest)
37
+ MiniTest::Assertion
38
+ else
39
+ Test::Unit::AssertionFailedError
40
+ end
41
+
42
+ def assert_field(field, value)
43
+ clean_backtrace { assert_equal value, @helper.fields[field] }
44
+ end
45
+
46
+ # Allows testing of negative assertions:
47
+ #
48
+ # # Instead of
49
+ # assert !something_that_is_false
50
+ #
51
+ # # Do this
52
+ # assert_false something_that_should_be_false
53
+ #
54
+ # An optional +msg+ parameter is available to help you debug.
55
+ def assert_false(boolean, message = nil)
56
+ message = build_message message, '<?> is not false or nil.', boolean
57
+
58
+ clean_backtrace do
59
+ assert_block message do
60
+ not boolean
61
+ end
62
+ end
63
+ end
64
+
65
+ # An assertion of a successful response:
66
+ #
67
+ # # Instead of
68
+ # assert response.success?
69
+ #
70
+ # # DRY that up with
71
+ # assert_success response
72
+ #
73
+ # A message will automatically show the inspection of the response
74
+ # object if things go afoul.
75
+ def assert_success(response, message = nil)
76
+ clean_backtrace do
77
+ assert response.success?,
78
+ build_message(
79
+ nil,
80
+ "#{message + "\n" if message}Response expected to succeed: <?>",
81
+ response
82
+ )
83
+ end
84
+ end
85
+
86
+ # The negative of +assert_success+
87
+ def assert_failure(response, message = nil)
88
+ clean_backtrace do
89
+ assert !response.success?,
90
+ build_message(
91
+ nil,
92
+ "#{message + "\n" if message}Response expected to fail: <?>",
93
+ response
94
+ )
95
+ end
96
+ end
97
+
98
+ def assert_valid(model, message = nil)
99
+ errors = model.validate
100
+
101
+ clean_backtrace do
102
+ assert_equal({}, errors, (message || 'Expected to be valid'))
103
+ end
104
+
105
+ errors
106
+ end
107
+
108
+ def assert_not_valid(model)
109
+ errors = model.validate
110
+
111
+ clean_backtrace do
112
+ assert_not_equal({}, errors, 'Expected to not be valid')
113
+ end
114
+
115
+ errors
116
+ end
117
+
118
+ def assert_deprecation_warning(message = nil)
119
+ ActiveMerchant.expects(:deprecated).with(message || anything)
120
+ yield
121
+ end
122
+
123
+ def refute(value, message = nil)
124
+ assert(!value, message)
125
+ end
126
+
127
+ def silence_deprecation_warnings
128
+ ActiveMerchant.stubs(:deprecated)
129
+ yield
130
+ end
131
+
132
+ def assert_no_deprecation_warning
133
+ ActiveMerchant.expects(:deprecated).never
134
+ yield
135
+ end
136
+
137
+ def assert_scrubbed(unexpected_value, transcript)
138
+ regexp =
139
+ (
140
+ if Regexp === unexpected_value
141
+ unexpected_value
142
+ else
143
+ Regexp.new(Regexp.quote(unexpected_value.to_s))
144
+ end
145
+ )
146
+ refute_match regexp,
147
+ transcript,
148
+ 'Expected the value to be scrubbed out of the transcript'
149
+ end
150
+
151
+ private
152
+
153
+ def clean_backtrace(&block)
154
+ yield
155
+ rescue ASSERTION_CLASS => e
156
+ path = File.expand_path(__FILE__)
157
+ raise ASSERTION_CLASS,
158
+ e.message,
159
+ (
160
+ e.backtrace.reject { |line|
161
+ File.expand_path(line).match?(/#{path}/)
162
+ }
163
+ )
164
+ end
165
+ end
166
+
167
+ module Fixtures
168
+ HOME_DIR =
169
+ if RUBY_PLATFORM.match?('mswin32')
170
+ ENV['HOMEPATH']
171
+ else
172
+ ENV['HOME']
173
+ end unless defined?(HOME_DIR)
174
+ LOCAL_CREDENTIALS =
175
+ File.join(HOME_DIR.to_s, '.active_merchant/fixtures.yml') unless defined?(
176
+ LOCAL_CREDENTIALS
177
+ )
178
+ DEFAULT_CREDENTIALS =
179
+ File.join(File.dirname(__FILE__), 'fixtures.yml') unless defined?(
180
+ DEFAULT_CREDENTIALS
181
+ )
182
+
183
+ private
184
+
185
+ def default_expiration_date
186
+ @default_expiration_date ||= Date.new((Time.now.year + 1), 9, 30)
187
+ end
188
+
189
+ def formatted_expiration_date(credit_card)
190
+ credit_card.expiry_date.expiration.strftime('%Y-%m')
191
+ end
192
+
193
+ def credit_card(number = '4242424242424242', options = {})
194
+ defaults =
195
+ {
196
+ number: number,
197
+ month: default_expiration_date.month,
198
+ year: default_expiration_date.year,
199
+ first_name: 'Longbob',
200
+ last_name: 'Longsen',
201
+ verification_value: options[:verification_value] || '123',
202
+ brand: 'visa'
203
+ }.update(options)
204
+
205
+ Billing::CreditCard.new(defaults)
206
+ end
207
+
208
+ def credit_card_with_track_data(number = '4242424242424242', options = {})
209
+ exp_date = default_expiration_date.strftime('%y%m')
210
+
211
+ defaults =
212
+ {
213
+ track_data:
214
+ "%B#{number}^LONGSEN/L. ^#{exp_date}1200000000000000**123******?"
215
+ }.update(options)
216
+
217
+ Billing::CreditCard.new(defaults)
218
+ end
219
+
220
+ def network_tokenization_credit_card(
221
+ number = '4242424242424242',
222
+ options = {}
223
+ )
224
+ defaults =
225
+ {
226
+ number: number,
227
+ month: default_expiration_date.month,
228
+ year: default_expiration_date.year,
229
+ first_name: 'Longbob',
230
+ last_name: 'Longsen',
231
+ verification_value: '123',
232
+ brand: 'visa'
233
+ }.update(options)
234
+
235
+ Billing::NetworkTokenizationCreditCard.new(defaults)
236
+ end
237
+
238
+ def check(options = {})
239
+ defaults =
240
+ {
241
+ name: 'Jim Smith',
242
+ bank_name: 'Bank of Elbonia',
243
+ routing_number: '244183602',
244
+ account_number: '15378535',
245
+ account_holder_type: 'personal',
246
+ account_type: 'checking',
247
+ number: '1'
248
+ }.update(options)
249
+
250
+ Billing::Check.new(defaults)
251
+ end
252
+
253
+ def apple_pay_payment_token(options = {})
254
+ # apple_pay_json_raw should contain the JSON serialization of the object described here
255
+ # https://developer.apple.com/library/IOs//documentation/PassKit/Reference/PaymentTokenJSON/PaymentTokenJSON.htm
256
+ apple_pay_json_raw = '{"version":"EC_v1","data":"","signature":""}'
257
+ defaults =
258
+ {
259
+ payment_data: ActiveSupport::JSON.decode(apple_pay_json_raw),
260
+ payment_instrument_name: 'Visa 2424',
261
+ payment_network: 'Visa',
262
+ transaction_identifier: 'uniqueidentifier123'
263
+ }.update(options)
264
+
265
+ ActiveMerchant::Billing::ApplePayPaymentToken.new(
266
+ defaults[:payment_data],
267
+ payment_instrument_name: defaults[:payment_instrument_name],
268
+ payment_network: defaults[:payment_network],
269
+ transaction_identifier: defaults[:transaction_identifier]
270
+ )
271
+ end
272
+
273
+ def address(options = {})
274
+ {
275
+ name: 'Jim Smith',
276
+ address1: '456 My Street',
277
+ address2: 'Apt 1',
278
+ company: 'Widgets Inc',
279
+ city: 'Ottawa',
280
+ state: 'ON',
281
+ zip: 'K1C2N6',
282
+ country: 'CA',
283
+ phone: '(555)555-5555',
284
+ fax: '(555)555-6666'
285
+ }.update(options)
286
+ end
287
+
288
+ def statement_address(options = {})
289
+ {
290
+ address1: '456 My Street',
291
+ address2: 'Apt 1',
292
+ city: 'Ottawa',
293
+ state: 'ON',
294
+ zip: 'K1C2N6'
295
+ }.update(options)
296
+ end
297
+
298
+ def stored_credential(*args, **options)
299
+ id = options.delete(:id) || options.delete(:network_transaction_id)
300
+
301
+ stored_credential = {
302
+ network_transaction_id: id,
303
+ initial_transaction: false
304
+ }
305
+
306
+ stored_credential[:initial_transaction] = true if args.include?(:initial)
307
+
308
+ stored_credential[:reason_type] = 'recurring' if args.include?(:recurring)
309
+ stored_credential[:reason_type] = 'unscheduled' if args.include?(
310
+ :unscheduled
311
+ )
312
+ stored_credential[:reason_type] = 'installment' if args.include?(
313
+ :installment
314
+ )
315
+
316
+ stored_credential[:initiator] = 'cardholder' if args.include?(:cardholder)
317
+ stored_credential[:initiator] = 'merchant' if args.include?(:merchant)
318
+
319
+ stored_credential
320
+ end
321
+
322
+ def generate_unique_id
323
+ SecureRandom.hex(16)
324
+ end
325
+
326
+ def all_fixtures
327
+ @@fixtures ||= load_fixtures
328
+ end
329
+
330
+ def fixtures(key)
331
+ data =
332
+ all_fixtures[key] ||
333
+ raise(StandardError, "No fixture data was found for '#{key}'")
334
+
335
+ data.dup
336
+ end
337
+
338
+ def load_fixtures
339
+ [DEFAULT_CREDENTIALS, LOCAL_CREDENTIALS].inject(
340
+ {}
341
+ ) do |credentials, file_name|
342
+ if File.exist?(file_name)
343
+ yaml_data = YAML.safe_load(File.read(file_name), aliases: true)
344
+ credentials.merge!(symbolize_keys(yaml_data))
345
+ end
346
+ credentials
347
+ end
348
+ end
349
+
350
+ def symbolize_keys(hash)
351
+ return unless hash.is_a?(Hash)
352
+
353
+ hash.symbolize_keys!
354
+ hash.each { |_k, v| symbolize_keys(v) }
355
+ end
356
+ end
357
+ end
358
+
359
+ Test::Unit::TestCase.class_eval do
360
+ include ActiveMerchant::Billing
361
+ include ActiveMerchant::Assertions
362
+ include ActiveMerchant::Fixtures
363
+
364
+ def capture_transcript(gateway)
365
+ transcript = ''
366
+ gateway.class.wiredump_device = transcript
367
+
368
+ yield
369
+
370
+ transcript
371
+ end
372
+
373
+ def dump_transcript_and_fail(gateway, amount, credit_card, params)
374
+ transcript =
375
+ capture_transcript(gateway) do
376
+ gateway.purchase(amount, credit_card, params)
377
+ end
378
+
379
+ File.open('transcript.log', 'w') { |f| f.write(transcript) }
380
+ assert false,
381
+ 'A purchase transcript has been written to transcript.log for you to test scrubbing with.'
382
+ end
383
+ end
384
+
385
+ class MockResponse
386
+ attr_reader :code, :body, :message
387
+ attr_accessor :headers
388
+
389
+ def self.succeeded(body, message = '')
390
+ MockResponse.new(200, body, message)
391
+ end
392
+
393
+ def self.failed(body, http_status_code = 422, message = '')
394
+ MockResponse.new(http_status_code, body, message)
395
+ end
396
+
397
+ def initialize(code, body, message = '', headers = {})
398
+ @code, @body, @message, @headers = code, body, message, headers
399
+ end
400
+
401
+ def [](header)
402
+ @headers[header]
403
+ end
404
+ end
@@ -0,0 +1,158 @@
1
+ require 'test_helper'
2
+
3
+ class PayrixTest < Test::Unit::TestCase
4
+ include CommStub
5
+
6
+ def setup
7
+ @gateway =
8
+ PayrixGateway.new(
9
+ login: 'login',
10
+ password: 'password',
11
+ business_id: 1,
12
+ service: :hpp
13
+ )
14
+ @amount = 100_00
15
+
16
+ @options = {
17
+ address: address,
18
+ description: 'Store Purchase',
19
+ ip: '127.0.0.1',
20
+ return_url: 'https://example.net',
21
+ transaction_reference: '1234'
22
+ }
23
+ end
24
+
25
+ def test_failed_login
26
+ @gateway.expects(:ssl_request).returns(failed_login_response)
27
+ response = @gateway.setup_purchase(@amount, @options)
28
+
29
+ assert_failure response
30
+ assert_equal Gateway::STANDARD_ERROR_CODE[:processing_error],
31
+ response.error_code
32
+ end
33
+
34
+ def test_hpp_successful_purchase
35
+ response =
36
+ stub_comms { @gateway.setup_purchase(@amount, @options) }
37
+ .check_request do |_verb, endpoint, _data, headers|
38
+ unless endpoint =~ /login$/
39
+ assert_equal 'Bearer ACCESS_TOKEN', headers['Authorization']
40
+ end
41
+ end
42
+ .respond_with(successful_login_response, successful_hpp_response)
43
+
44
+ assert_success response
45
+
46
+ assert_equal 'TOKEN', response.token
47
+ assert_match(/sandbox\.hosted\.paymentsapi\.io/, response.redirect_url)
48
+ assert response.test?
49
+ end
50
+
51
+ def test_hpp_failed_purchase
52
+ stub_response(failed_hpp_response)
53
+
54
+ response = @gateway.setup_purchase(@amount, @options)
55
+ assert_failure response
56
+ assert_equal Gateway::STANDARD_ERROR_CODE[:processing_error],
57
+ response.error_code
58
+ end
59
+
60
+ def test_hpp_successful_authorize
61
+ response =
62
+ stub_comms { @gateway.setup_authorize(@amount, @options) }
63
+ .check_request do |_verb, endpoint, data, headers|
64
+ unless endpoint =~ /login$/
65
+ payload = JSON.parse(data)
66
+ assert_equal 'PREAUTH', payload['Transaction']['ProcessType']
67
+ end
68
+ end
69
+ .respond_with(successful_login_response, successful_hpp_response)
70
+
71
+ assert_success response
72
+
73
+ assert_equal 'TOKEN', response.token
74
+ assert_match(/sandbox\.hosted\.paymentsapi\.io/, response.redirect_url)
75
+ assert response.test?
76
+ end
77
+
78
+ def test_details_for_successful_token
79
+ stub_response(successful_details_for_token_response)
80
+
81
+ response = @gateway.details_for('TOKEN')
82
+
83
+ assert_success response
84
+
85
+ assert_equal 'TOKEN', response.token
86
+ assert response.test?
87
+ end
88
+
89
+ def test_details_for_waiting_token
90
+ stub_response(waiting_details_for_token_response)
91
+
92
+ response = @gateway.details_for('TOKEN')
93
+
94
+ assert_failure response
95
+
96
+ assert 'Token URL not yet accessed', response.message
97
+ assert_equal 'TOKEN', response.token
98
+ assert response.test?
99
+ end
100
+
101
+ def test_details_for_failed_token
102
+ stub_response(failed_details_for_token_response)
103
+
104
+ response = @gateway.details_for('TOKEN')
105
+
106
+ assert_failure response
107
+
108
+ assert response.test?
109
+ assert_equal 'TOKEN', response.token
110
+ assert_equal 'PROCESSED_REJECTED', response.error_code
111
+ assert_equal 'Invalid credit card', response.message
112
+ end
113
+
114
+ def test_scrub
115
+ assert_false @gateway.supports_scrubbing?
116
+ end
117
+
118
+ private
119
+
120
+ def successful_login_response
121
+ '{"access_token":"ACCESS_TOKEN","expires_in":3600,"token_type":"Bearer","scope":"integrapay.api.public"}'
122
+ end
123
+
124
+ def failed_login_response
125
+ '{"errorCode":"BadRequest","errorMessage":"The Password field is required.","errorDetail":"Password"}'
126
+ end
127
+
128
+ def successful_hpp_response
129
+ '{"token":"TOKEN","redirectToUrl":"https://sandbox.hosted.paymentsapi.io/ui/hpp/api/65026106-fd50-4c09-a43b-9c6bab4ab65f"}'
130
+ end
131
+
132
+ def failed_hpp_response
133
+ '{"errorCode":"BadRequest","errorMessage":"Reference is required","errorDetail":"Transaction.Reference"}'
134
+ end
135
+
136
+ def successful_details_for_token_response
137
+ '{"token":"TOKEN","type":"HPP","time":"2021-11-22T20:48:00+00:00","status":"PROCESSED_SUCCESSFUL","statusDescription":"PROCESSED_SUCCESSFUL","returnUrl":"https://app.black.test/public/client/e4xpJS48v/payment/success","redirectToUrl":"https://sandbox.hosted.paymentsapi.io/ui/hpp/api/TOKEN","template":"60357dc7-de7a-446a-a1c1-8d228eab89a0","templateName":"Basic","transaction":{"business":{"businessId":"90024","businessName":"Debtor Daddy Test"},"time":"2021-11-22T20:51:49.89+00:00","transactionId":"2272290","secondaryTransactionId":"RT732135","reference":"c76684ed583be031c58e1464819a6529","description":"Purchase","scheduleReference":null,"amount":61.87,"amountRequested":61.87,"amountRefunded":0.00,"currency":"AUD","type":"RT","typeDescription":"Realtime Payment - Website","statusCode":"S","subStatusCode":null,"statusDescription":"Settled","paymentMethod":"VISA","payer":null,"card":{"cardNumber":"411111xxxxxx1111","cardholderName":"TEST CARD","cardExpires":"2027-11-01T00:00:00","cardType":"Visa"},"bankAccount":null,"rejectionRecovery":null,"verification":null,"source":null,"recurringReference":null,"cardStorageType":null,"cardAuthorizationType":null,"cardAuthorizationReference":"TG-cd217b17-8278-4a3d-b1ab-5ff5b7118281","profile":null},"payer":null,"schedule":null,"requestHpp":{"returnUrl":"https://app.black.test/public/client/e4xpJS48v/payment/success","template":"Basic","transaction":{"processType":"COMPLETE","reference":"c76684ed583be031c58e1464819a6529","description":"Purchase","amount":61.87,"currencyCode":"USD"},"payer":{"savePayer":false,"uniqueReference":null,"groupReference":null,"familyOrBusinessName":null,"givenName":null,"email":null,"phone":"018005001","mobile":"017775001","address":null,"dateOfBirth":null,"extraInfo":null},"audit":null},"events":[{"event":"WAITING","time":"2021-11-22T20:48:00+00:00","description":null,"username":"API: ","ip":"120.136.2.157"},{"event":"VALIDATED","time":"2021-11-22T20:48:00+00:00","description":null,"username":null,"ip":""},{"event":"PROCESSED_SUCCESSFUL","time":"2021-11-22T20:52:00+00:00","description":null,"username":null,"ip":"120.136.2.157"},{"event":"EXPIRED","time":"2021-11-22T21:08:00+00:00","description":null,"username":null,"ip":null}]}'
138
+ end
139
+
140
+ def waiting_details_for_token_response
141
+ '{"token":"TOKEN","type":"HPP","time":"2021-11-21T23:24:00+00:00","status":"WAITING","statusDescription":"WAITING","returnUrl":"https://app.black.test/payrix","redirectToUrl":"https://sandbox.hosted.paymentsapi.io/ui/hpp/api/TOKEN","template":"60357dc7-de7a-446a-a1c1-8d228eab89a0","templateName":"Basic","transaction":null,"payer":null,"schedule":null,"requestHpp":{"returnUrl":"https://app.black.test/payrix","template":"Basic","transaction":{"processType":"COMPLETE","reference":"030ec6d893dabcf48bad2859a61735b5","description":"Store Purchase","amount":100.00,"currencyCode":"USD"},"payer":{"savePayer":false,"uniqueReference":null,"groupReference":null,"familyOrBusinessName":null,"givenName":null,"email":"user@example.com","phone":null,"mobile":null,"address":{"line1":"456 My Street","line2":"Apt 1","suburb":null,"state":"ON","postCode":"K1C2N6","country":"CA"},"dateOfBirth":null,"extraInfo":null},"audit":null},"events":[{"event":"WAITING","time":"2021-11-21T23:24:00+00:00","description":null,"username":"API: ","ip":"120.136.2.157"}]}'
142
+ end
143
+
144
+ def failed_details_for_token_response
145
+ '{"token":"TOKEN","type":"HPP","time":"2021-11-23T02:47:00+00:00","status":"PROCESSED_REJECTED","statusDescription":"PROCESSED_REJECTED","returnUrl":"https://app.black.test/payrix","redirectToUrl":"https://sandbox.hosted.paymentsapi.io/ui/hpp/api/TOKEN","template":"60357dc7-de7a-446a-a1c1-8d228eab89a0","templateName":"Basic","transaction":{"business":{"businessId":"90024","businessName":"Debtor Daddy Test"},"time":"2021-11-23T02:47:33.083+00:00","transactionId":"2272471","secondaryTransactionId":"RT732330","reference":"3632fa83cfcd4851137c2dec371717a8","description":"Store Purchase","scheduleReference":null,"amount":100.31,"amountRequested":100.31,"amountRefunded":0.00,"currency":"AUD","type":"RT","typeDescription":"Realtime Payment - Website","statusCode":"R","subStatusCode":"R3","statusDescription":"Rejected: Invalid Credit Card","paymentMethod":"VISA","payer":null,"card":{"cardNumber":"411111xxxxxx1111","cardholderName":"TEST CARD","cardExpires":"2027-03-01T00:00:00","cardType":"Visa"},"bankAccount":null,"rejectionRecovery":null,"verification":null,"source":null,"recurringReference":null,"cardStorageType":null,"cardAuthorizationType":null,"cardAuthorizationReference":"TG-491ea49f-ac45-43cb-a074-4305493e79c0","profile":null},"payer":null,"schedule":null,"requestHpp":{"returnUrl":"https://app.black.test/payrix","template":"Basic","transaction":{"processType":"COMPLETE","reference":"3632fa83cfcd4851137c2dec371717a8","description":"Store Purchase","amount":100.31,"currencyCode":"USD"},"payer":{"savePayer":false,"uniqueReference":null,"groupReference":null,"familyOrBusinessName":null,"givenName":null,"email":"user@example.com","phone":null,"mobile":null,"address":{"line1":"456 My Street","line2":"Apt 1","suburb":null,"state":"ON","postCode":"K1C2N6","country":"CA"},"dateOfBirth":null,"extraInfo":null},"audit":null},"events":[{"event":"WAITING","time":"2021-11-23T02:47:00+00:00","description":null,"username":"API: ","ip":"120.136.2.157"},{"event":"VALIDATED","time":"2021-11-23T02:47:00+00:00","description":null,"username":null,"ip":""},{"event":"PROCESSED_SUCCESSFUL","time":"2021-11-23T02:48:00+00:00","description":null,"username":null,"ip":"120.136.2.157"}]}'
146
+ end
147
+
148
+ def stub_comms(gateway = @gateway, method_to_stub = :ssl_request, &action)
149
+ super
150
+ end
151
+
152
+ def stub_response(response)
153
+ @gateway
154
+ .expects(:ssl_request)
155
+ .times(2)
156
+ .returns(successful_login_response, response)
157
+ end
158
+ end