defra_ruby_mocks 5.1.0 → 5.1.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.
- checksums.yaml +4 -4
- data/app/controllers/concerns/defra_ruby_mocks/can_use_aws_s3.rb +51 -0
- data/app/controllers/defra_ruby_mocks/govpay_controller.rb +12 -14
- data/app/controllers/defra_ruby_mocks/govpay_test_helpers_controller.rb +10 -8
- data/app/jobs/base_send_webhook_job.rb +4 -2
- data/app/services/defra_ruby_mocks/aws_bucket_service.rb +6 -6
- data/app/services/defra_ruby_mocks/govpay_create_payment_service.rb +3 -10
- data/app/services/defra_ruby_mocks/govpay_get_payment_service.rb +3 -6
- data/app/services/defra_ruby_mocks/govpay_refund_details_service.rb +4 -26
- data/app/services/defra_ruby_mocks/govpay_request_refund_service.rb +4 -17
- data/lib/defra_ruby_mocks/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a54f9624d84a56d58fb86ff1a7556d5d7c88db8cd4c93106c260e1b14008c38
|
4
|
+
data.tar.gz: 020561b363c345fa55dc26a27b9cc5bbe4306a5c5743ef824d095463b8e80e12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 60761ea8c403d69d31ef96d890d37b90013b26e0dc0cd271ef7b5a3efb933225d3fb75178dc3aae3f8715088e1fe2e26344118668bed43cee9f44b901c0071e9
|
7
|
+
data.tar.gz: d6c620d9805c12b864727a0f6d7b52356a18925858f8ef11c6e44889764f317d52379146c3fc25adede7e06c8c04e814fd8990b03d57816f4604bf70db7d9490
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module DefraRubyMocks
|
6
|
+
module CanUseAwsS3
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
DEFAULT_LAST_REFUND_REQUEST_TIME = 1.day.ago.freeze
|
11
|
+
|
12
|
+
included do
|
13
|
+
|
14
|
+
def s3_bucket_name
|
15
|
+
@s3_bucket_name ||= ENV.fetch("AWS_DEFRA_RUBY_MOCKS_BUCKET", nil)
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_response_status(response_status_filename:, status:)
|
19
|
+
Rails.logger.info "[DefraRubyMocks] [AwsS3] Setting #{response_status_filename} status to \"#{status}\""
|
20
|
+
|
21
|
+
AwsBucketService.write(s3_bucket_name, response_status_filename, status)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check whether a non-default status value has been requested
|
25
|
+
def response_status(response_status_filename:, default_status:)
|
26
|
+
status = AwsBucketService.read(s3_bucket_name, response_status_filename)
|
27
|
+
Rails.logger.warn "[DefraRubyMocks] [AwsS3] read #{response_status_filename}: \"#{status}\""
|
28
|
+
|
29
|
+
status || default_status
|
30
|
+
rescue StandardError => e
|
31
|
+
# This is expected behaviour when the status default override file is not present.
|
32
|
+
Rails.logger.warn "[DefraRubyMocks] [AwsS3] failed to read #{response_status_filename}: #{e}"
|
33
|
+
|
34
|
+
default_status
|
35
|
+
end
|
36
|
+
|
37
|
+
# let the refund details service know how long since the refund was requested
|
38
|
+
def write_refund_requested_timestamp(timestamp_file_name:)
|
39
|
+
Rails.logger.warn "[DefraRubyMocks] [AwsS3] storing timestamp_file_name timestamp"
|
40
|
+
AwsBucketService.write(s3_bucket_name, timestamp_file_name, Time.zone.now.to_s)
|
41
|
+
end
|
42
|
+
|
43
|
+
def refund_request_timestamp(timestamp_file_name:)
|
44
|
+
timestamp = AwsBucketService.read(s3_bucket_name, timestamp_file_name)
|
45
|
+
timestamp ? Time.parse(timestamp) : DEFAULT_LAST_REFUND_REQUEST_TIME
|
46
|
+
rescue StandardError
|
47
|
+
DEFAULT_LAST_REFUND_REQUEST_TIME
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -3,6 +3,8 @@
|
|
3
3
|
module DefraRubyMocks
|
4
4
|
class GovpayController < ::DefraRubyMocks::ApplicationController
|
5
5
|
|
6
|
+
include CanUseAwsS3
|
7
|
+
|
6
8
|
skip_before_action :verify_authenticity_token
|
7
9
|
|
8
10
|
def create_payment
|
@@ -14,7 +16,7 @@ module DefraRubyMocks
|
|
14
16
|
amount: params[:amount], description: params[:description]
|
15
17
|
)
|
16
18
|
rescue StandardError => e
|
17
|
-
Rails.logger.error("
|
19
|
+
Rails.logger.error("[DefraRubyMocks] [create_payment] error: #{e}")
|
18
20
|
head 500
|
19
21
|
end
|
20
22
|
|
@@ -23,12 +25,12 @@ module DefraRubyMocks
|
|
23
25
|
# straight to the application callback route.
|
24
26
|
def next_url
|
25
27
|
response_url = retrieve_return_url
|
26
|
-
Rails.logger.warn "Govpay
|
28
|
+
Rails.logger.warn "[DefraRubyMocks] [Govpay] calling response URL #{response_url}"
|
27
29
|
redirect_to response_url, allow_other_host: true
|
28
30
|
rescue RestClient::ExceptionWithResponse => e
|
29
|
-
Rails.logger.warn "Govpay
|
31
|
+
Rails.logger.warn "[DefraRubyMocks] [Govpay] RestClient received response: #{e}"
|
30
32
|
rescue StandardError => e
|
31
|
-
Rails.logger.error("Govpay
|
33
|
+
Rails.logger.error("[DefraRubyMocks] [Govpay] Error sending request to govpay: #{e}")
|
32
34
|
Airbrake.notify(e, message: "Error on govpay request")
|
33
35
|
end
|
34
36
|
|
@@ -36,7 +38,7 @@ module DefraRubyMocks
|
|
36
38
|
valid_payment_id
|
37
39
|
render json: GovpayGetPaymentService.new.run(payment_id: params[:payment_id])
|
38
40
|
rescue StandardError => e
|
39
|
-
Rails.logger.error("
|
41
|
+
Rails.logger.error("[DefraRubyMocks] [payment_details] error: #{e}")
|
40
42
|
head 422
|
41
43
|
end
|
42
44
|
|
@@ -46,36 +48,32 @@ module DefraRubyMocks
|
|
46
48
|
amount: params[:amount],
|
47
49
|
refund_amount_available: params[:refund_amount_available])
|
48
50
|
rescue StandardError => e
|
49
|
-
Rails.logger.error("
|
51
|
+
Rails.logger.error("[DefraRubyMocks] [create_refund] error: #{e}")
|
50
52
|
head 500
|
51
53
|
end
|
52
54
|
|
53
55
|
def refund_details
|
54
56
|
render json: GovpayRefundDetailsService.new.run(payment_id: params[:payment_id], refund_id: params[:refund_id])
|
55
57
|
rescue StandardError => e
|
56
|
-
Rails.logger.error("
|
58
|
+
Rails.logger.error("[DefraRubyMocks] [refund_details] error: #{e}")
|
57
59
|
head 500
|
58
60
|
end
|
59
61
|
|
60
62
|
private
|
61
63
|
|
62
|
-
def s3_bucket_name
|
63
|
-
@s3_bucket_name = ENV.fetch("AWS_DEFRA_RUBY_MOCKS_BUCKET", nil)
|
64
|
-
end
|
65
|
-
|
66
64
|
def return_url_file_name
|
67
|
-
@return_url_file_name
|
65
|
+
@return_url_file_name ||= "return_url_file"
|
68
66
|
end
|
69
67
|
|
70
68
|
# We need to persist the return_url between the initial payment creation request and the execution of next_url.
|
71
69
|
# We can't use tmp for multi-server environments so we load the temp file to AWS S3.
|
72
70
|
def store_return_url(return_url)
|
73
|
-
Rails.logger.warn "
|
71
|
+
Rails.logger.warn "[DefraRubyMocks] [store_return_url] #{return_url}"
|
74
72
|
AwsBucketService.write(s3_bucket_name, return_url_file_name, return_url)
|
75
73
|
end
|
76
74
|
|
77
75
|
def retrieve_return_url
|
78
|
-
AwsBucketService.read(s3_bucket_name, return_url_file_name)
|
76
|
+
@retrieve_return_url ||= AwsBucketService.read(s3_bucket_name, return_url_file_name)
|
79
77
|
end
|
80
78
|
|
81
79
|
def valid_create_params
|
@@ -5,29 +5,29 @@ module DefraRubyMocks
|
|
5
5
|
|
6
6
|
skip_before_action :verify_authenticity_token
|
7
7
|
|
8
|
+
include CanUseAwsS3
|
9
|
+
|
8
10
|
# These are helpers for the automated acceptance tests.
|
9
11
|
|
10
12
|
# The mock will use the value passed in to populate the status field on all future payments.
|
11
13
|
def set_test_payment_response_status
|
12
|
-
|
13
|
-
|
14
|
-
AwsBucketService.write(s3_bucket_name, "test_payment_response_status", params[:status])
|
14
|
+
set_response_status(response_status_filename: "test_payment_response_status", status: params[:status])
|
15
15
|
|
16
16
|
head 200
|
17
17
|
end
|
18
18
|
|
19
19
|
# The mock will use the value passed in to populate the status field on all future refunds.
|
20
20
|
def set_test_refund_response_status
|
21
|
-
|
22
|
-
|
23
|
-
AwsBucketService.write(s3_bucket_name, "test_refund_response_status", params[:status])
|
21
|
+
set_response_status(response_status_filename: "test_refund_response_status", status: params[:status])
|
24
22
|
|
25
23
|
head 200
|
26
24
|
end
|
27
25
|
|
28
26
|
# This schedules a job to send a mock payment webhook.
|
29
27
|
def send_payment_webhook
|
30
|
-
Rails.logger.warn "
|
28
|
+
Rails.logger.warn "[DefraRubyMocks] [send_payment_webhook] " \
|
29
|
+
"params: #{params[:govpay_id]}, status #{params[:payment_status]}"
|
30
|
+
|
31
31
|
%w[govpay_id payment_status callback_url signing_secret].each do |p|
|
32
32
|
raise StandardError, "Missing parameter: '#{p}'" unless params[p].present?
|
33
33
|
end
|
@@ -44,7 +44,9 @@ module DefraRubyMocks
|
|
44
44
|
|
45
45
|
# This schedules a job to send a mock refund webhook.
|
46
46
|
def send_refund_webhook
|
47
|
-
Rails.logger.warn "
|
47
|
+
Rails.logger.warn "[DefraRubyMocks] [send_refund webhook] " \
|
48
|
+
"params: #{params[:govpay_id]}, status #{params[:refund_status]}"
|
49
|
+
|
48
50
|
%w[govpay_id refund_status callback_url signing_secret].each do |p|
|
49
51
|
raise StandardError, "Missing parameter: '#{p}'" unless params[p].present?
|
50
52
|
end
|
@@ -3,7 +3,8 @@
|
|
3
3
|
class BaseSendWebhookJob < ApplicationJob
|
4
4
|
def perform(govpay_id:, status:, callback_url:, signing_secret:)
|
5
5
|
body = webhook_body(govpay_id:, status:)
|
6
|
-
Rails.logger.warn "
|
6
|
+
Rails.logger.warn "[DefraRubyMocks] [BaseSendWebhookJob] sending #{webhook_type} webhook " \
|
7
|
+
"for #{govpay_id}, status \"#{status}\" to #{callback_url}"
|
7
8
|
RestClient::Request.execute(
|
8
9
|
method: :get,
|
9
10
|
url: callback_url,
|
@@ -11,7 +12,8 @@ class BaseSendWebhookJob < ApplicationJob
|
|
11
12
|
headers: { "Pay-Signature": webhook_signature(body, signing_secret) }
|
12
13
|
)
|
13
14
|
rescue StandardError => e
|
14
|
-
Rails.logger.error "
|
15
|
+
Rails.logger.error "[DefraRubyMocks] [BaseSendWebhookJob] error sending " \
|
16
|
+
"#{webhook_type} webhook to #{callback_url}: #{e}"
|
15
17
|
end
|
16
18
|
|
17
19
|
private
|
@@ -17,14 +17,14 @@ module DefraRubyMocks
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.remove(bucket_name, file_name)
|
20
|
-
Rails.logger.debug "
|
20
|
+
Rails.logger.debug "[DefraRubyMocks] [AwsBucketService] removing #{file_name} on S3"
|
21
21
|
new.remove(bucket_name, file_name)
|
22
22
|
end
|
23
23
|
|
24
24
|
def write(bucket_name, file_name, content)
|
25
25
|
@bucket_name = bucket_name
|
26
26
|
@file_name = file_name
|
27
|
-
Rails.logger.debug "
|
27
|
+
Rails.logger.debug "[DefraRubyMocks] [AwsBucketService] writing #{file_name} to S3"
|
28
28
|
|
29
29
|
write_temp_file(content)
|
30
30
|
|
@@ -36,14 +36,14 @@ module DefraRubyMocks
|
|
36
36
|
def read(bucket_name, file_name)
|
37
37
|
@bucket_name = bucket_name
|
38
38
|
@file_name = file_name
|
39
|
-
Rails.logger.debug "
|
39
|
+
Rails.logger.debug "[DefraRubyMocks] [AwsBucketService] reading #{file_name} from S3"
|
40
40
|
|
41
41
|
s3.get_object(bucket: bucket_name, key: file_name).body.read
|
42
42
|
end
|
43
43
|
|
44
44
|
def remove(bucket_name, file_name)
|
45
45
|
@bucket_name = bucket_name
|
46
|
-
Rails.logger.debug "
|
46
|
+
Rails.logger.debug "[DefraRubyMocks] [AwsBucketService] removing #{file_name} from S3"
|
47
47
|
|
48
48
|
bucket.delete(file_name)
|
49
49
|
end
|
@@ -65,12 +65,12 @@ module DefraRubyMocks
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def write_temp_file(content)
|
68
|
-
Rails.logger.debug "
|
68
|
+
Rails.logger.debug "[DefraRubyMocks] [AwsBucketService] creating temp file for \"#{content}\""
|
69
69
|
File.write(temp_filepath, content)
|
70
70
|
end
|
71
71
|
|
72
72
|
def load_temp_file_to_s3
|
73
|
-
Rails.logger.debug "
|
73
|
+
Rails.logger.debug "[DefraRubyMocks] [AwsBucketService] loading temp file to S3 bucket #{bucket_name}"
|
74
74
|
|
75
75
|
result = nil
|
76
76
|
|
@@ -5,6 +5,8 @@ require "securerandom"
|
|
5
5
|
module DefraRubyMocks
|
6
6
|
class GovpayCreatePaymentService < BaseService
|
7
7
|
|
8
|
+
include CanUseAwsS3
|
9
|
+
|
8
10
|
def run(amount:, description:)
|
9
11
|
success_response.merge(
|
10
12
|
{
|
@@ -21,17 +23,8 @@ module DefraRubyMocks
|
|
21
23
|
|
22
24
|
private
|
23
25
|
|
24
|
-
def s3_bucket_name
|
25
|
-
@s3_bucket_name = ENV.fetch("AWS_DEFRA_RUBY_MOCKS_BUCKET", nil)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Check if a non-default status value has been requested
|
29
26
|
def test_payment_response_status
|
30
|
-
|
31
|
-
rescue StandardError => e
|
32
|
-
# This is expected behaviour when the payment status default override file is not present.
|
33
|
-
Rails.logger.warn ":::::: mocks failed to read test_payment_response_status: #{e}"
|
34
|
-
"created"
|
27
|
+
response_status(response_status_filename: "test_payment_response_status", default_status: "created")
|
35
28
|
end
|
36
29
|
|
37
30
|
def base_url
|
@@ -5,6 +5,8 @@ require "securerandom"
|
|
5
5
|
module DefraRubyMocks
|
6
6
|
class GovpayGetPaymentService < BaseService
|
7
7
|
|
8
|
+
include CanUseAwsS3
|
9
|
+
|
8
10
|
def run(payment_id:, amount: Random.rand(100..1_000), created_at: Time.current)
|
9
11
|
# This currently supports only success results:
|
10
12
|
response_success.merge(
|
@@ -19,13 +21,8 @@ module DefraRubyMocks
|
|
19
21
|
|
20
22
|
private
|
21
23
|
|
22
|
-
# Check if a non-default status value has been requested
|
23
24
|
def test_payment_response_status
|
24
|
-
|
25
|
-
rescue StandardError => e
|
26
|
-
# This is expected behaviour when the payment status default override file is not present.
|
27
|
-
Rails.logger.warn ":::::: mocks failed to read test_payment_response_status: #{e}"
|
28
|
-
"success"
|
25
|
+
response_status(response_status_filename: "test_payment_response_status", default_status: "success")
|
29
26
|
end
|
30
27
|
|
31
28
|
# rubocop:disable Metrics/MethodLength
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module DefraRubyMocks
|
4
4
|
class GovpayRefundDetailsService < BaseService
|
5
5
|
|
6
|
-
|
6
|
+
include CanUseAwsS3
|
7
7
|
|
8
8
|
def run(payment_id:, refund_id:) # rubocop:disable Lint/UnusedMethodArgument
|
9
9
|
{
|
@@ -21,48 +21,26 @@ module DefraRubyMocks
|
|
21
21
|
|
22
22
|
# Check if a non-default status value has been requested
|
23
23
|
def test_refund_response_status
|
24
|
-
|
25
|
-
rescue StandardError => e
|
26
|
-
# This is expected behaviour when the refund status default override file is not present.
|
27
|
-
Rails.logger.warn ":::::: mocks failed to read test_refund_response_status: #{e}"
|
28
|
-
"submitted"
|
24
|
+
response_status(response_status_filename: "test_refund_response_status", default_status: "submitted")
|
29
25
|
end
|
30
26
|
|
31
27
|
# "submitted" (or other, if default override is in place) for up to GOVPAY_REFUND_SUBMITTED_SUCCESS_LAG
|
32
28
|
# seconds after the last refund request, then "success"
|
33
29
|
def status
|
34
|
-
last_refund_time = refund_request_timestamp
|
30
|
+
last_refund_time = refund_request_timestamp(timestamp_file_name:)
|
35
31
|
submitted_success_lag = ENV.fetch("GOVPAY_REFUND_SUBMITTED_SUCCESS_LAG", 0).to_i
|
36
32
|
cutoff_time = (last_refund_time + submitted_success_lag.seconds).to_time
|
37
33
|
return "success" if submitted_success_lag.zero?
|
38
34
|
|
39
35
|
Time.zone.now < cutoff_time ? test_refund_response_status : "success"
|
40
36
|
rescue Errno::ENOENT
|
41
|
-
|
37
|
+
write_refund_requested_timestamp(timestamp_file_name:)
|
42
38
|
|
43
39
|
"success"
|
44
40
|
end
|
45
41
|
|
46
|
-
def write_timestamp_file
|
47
|
-
timestamp = Time.zone.now
|
48
|
-
Rails.logger.warn ":::::: writing timestamp file: #{timestamp}"
|
49
|
-
AwsBucketService.write(s3_bucket_name, timestamp_file_name, timestamp)
|
50
|
-
end
|
51
|
-
|
52
|
-
def s3_bucket_name
|
53
|
-
@s3_bucket_name = ENV.fetch("AWS_DEFRA_RUBY_MOCKS_BUCKET", nil)
|
54
|
-
end
|
55
|
-
|
56
42
|
def timestamp_file_name
|
57
43
|
@govpay_request_refund_service_last_run_time = "govpay_request_refund_service_last_run_time"
|
58
44
|
end
|
59
|
-
|
60
|
-
def refund_request_timestamp
|
61
|
-
timestamp = AwsBucketService.read(s3_bucket_name, timestamp_file_name)
|
62
|
-
timestamp ? Time.parse(timestamp) : DEFAULT_LAST_REFUND_REQUEST_TIME
|
63
|
-
rescue StandardError
|
64
|
-
DEFAULT_LAST_REFUND_REQUEST_TIME
|
65
|
-
end
|
66
|
-
|
67
45
|
end
|
68
46
|
end
|
@@ -3,8 +3,10 @@
|
|
3
3
|
module DefraRubyMocks
|
4
4
|
class GovpayRequestRefundService < BaseService
|
5
5
|
|
6
|
+
include CanUseAwsS3
|
7
|
+
|
6
8
|
def run(payment_id:, amount:, refund_amount_available:) # rubocop:disable Lint/UnusedMethodArgument
|
7
|
-
|
9
|
+
write_refund_requested_timestamp(timestamp_file_name:)
|
8
10
|
|
9
11
|
{
|
10
12
|
amount: amount,
|
@@ -16,23 +18,8 @@ module DefraRubyMocks
|
|
16
18
|
|
17
19
|
private
|
18
20
|
|
19
|
-
# Check if a non-default status value has been requested
|
20
21
|
def test_refund_response_status
|
21
|
-
|
22
|
-
rescue StandardError => e
|
23
|
-
# This is expected behaviour when the refund status default override file is not present.
|
24
|
-
Rails.logger.warn ":::::: mocks failed to read test_refund_response_status: #{e}"
|
25
|
-
"submitted"
|
26
|
-
end
|
27
|
-
|
28
|
-
# let the refund details service know how long since the refund was requested
|
29
|
-
def write_timestamp
|
30
|
-
Rails.logger.warn ":::::: storing refund request timestamp"
|
31
|
-
AwsBucketService.write(s3_bucket_name, timestamp_file_name, Time.zone.now.to_s)
|
32
|
-
end
|
33
|
-
|
34
|
-
def s3_bucket_name
|
35
|
-
@s3_bucket_name = ENV.fetch("AWS_DEFRA_RUBY_MOCKS_BUCKET", nil)
|
22
|
+
response_status(response_status_filename: "test_refund_response_status", default_status: "submitted")
|
36
23
|
end
|
37
24
|
|
38
25
|
def timestamp_file_name
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: defra_ruby_mocks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.1.
|
4
|
+
version: 5.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Defra
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-05-
|
11
|
+
date: 2025-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- LICENSE
|
92
92
|
- README.md
|
93
93
|
- Rakefile
|
94
|
+
- app/controllers/concerns/defra_ruby_mocks/can_use_aws_s3.rb
|
94
95
|
- app/controllers/defra_ruby_mocks/application_controller.rb
|
95
96
|
- app/controllers/defra_ruby_mocks/company_controller.rb
|
96
97
|
- app/controllers/defra_ruby_mocks/govpay_controller.rb
|