defra_ruby_mocks 1.0.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +90 -2
- data/Rakefile +0 -2
- data/app/controllers/defra_ruby_mocks/company_controller.rb +1 -1
- data/app/controllers/defra_ruby_mocks/worldpay_controller.rb +51 -0
- data/app/services/defra_ruby_mocks/worldpay_payment_service.rb +47 -0
- data/app/services/defra_ruby_mocks/worldpay_refund_service.rb +37 -0
- data/app/services/defra_ruby_mocks/worldpay_request_handler_service.rb +40 -0
- data/app/services/defra_ruby_mocks/worldpay_resource_service.rb +55 -0
- data/app/services/defra_ruby_mocks/worldpay_response_service.rb +92 -0
- data/app/views/defra_ruby_mocks/worldpay/payment_request.xml.erb +4 -0
- data/app/views/defra_ruby_mocks/worldpay/refund_request.xml.erb +4 -0
- data/app/views/defra_ruby_mocks/worldpay/stuck.html.erb +37 -0
- data/config/routes.rb +11 -0
- data/lib/defra_ruby_mocks/configuration.rb +2 -0
- data/lib/defra_ruby_mocks/engine.rb +3 -0
- data/lib/defra_ruby_mocks/invalid_config_error.rb +9 -0
- data/lib/defra_ruby_mocks/missing_resource_error.rb +9 -0
- data/lib/defra_ruby_mocks/unrecognised_worldpay_request_error.rb +5 -0
- data/lib/defra_ruby_mocks/version.rb +1 -1
- data/spec/dummy/log/development.log +180 -0
- data/spec/dummy/log/test.log +679 -99
- data/spec/examples.txt +83 -30
- data/spec/fixtures/payment_request_invalid.xml +6 -0
- data/spec/fixtures/payment_request_valid.xml +30 -0
- data/spec/fixtures/refund_request_invalid.xml +6 -0
- data/spec/fixtures/refund_request_valid.xml +11 -0
- data/spec/fixtures/unrecognised_request.xml +6 -0
- data/spec/requests/company_spec.rb +3 -3
- data/spec/requests/worldpay_spec.rb +142 -0
- data/spec/services/worldpay_payment_service_spec.rb +95 -0
- data/spec/services/worldpay_refund_service_spec.rb +68 -0
- data/spec/services/worldpay_request_handler_service_spec.rb +79 -0
- data/spec/services/worldpay_resource_service_spec.rb +112 -0
- data/spec/services/worldpay_response_service_spec.rb +156 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/support/helpers/configuration.rb +1 -0
- data/spec/support/helpers/helpers.rb +13 -0
- data/spec/support/helpers/waste_carriers_engine.rb +10 -0
- data/spec/support/helpers/xml_matchers.rb +19 -0
- metadata +75 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 37b80527c008c3d05100caffb316ae36fd75050a7d5612db07a180f163e3e17a
|
4
|
+
data.tar.gz: 622dc9a174d7e0af97046b33a12164b37deec2d3574afebd42932b7c7b699171
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab9dec997252c0e656cb39c4364e9d2f28e28bfd707309178a3d0e17d3d3289241720cc4c78a1f542edef1545a5d30e43573aea389e6fc69ee33237e47414c95
|
7
|
+
data.tar.gz: e3f3707826e51e569703a04aaaaeb4593f99db011331ffd73018909c8548f702cf317ccefe0f30308047b3734107b4ce292c8ef740fb362e9647834b3eb79e4c
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Defra Ruby Mocks
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.com/DEFRA/defra-ruby-mocks.svg?branch=master)](https://travis-ci.com/DEFRA/defra-ruby-mocks)
|
4
|
-
[![Maintainability](https://
|
5
|
-
[![
|
4
|
+
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=DEFRA_defra-ruby-mocks&metric=sqale_rating)](https://sonarcloud.io/dashboard?id=DEFRA_defra-ruby-mocks)
|
5
|
+
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=DEFRA_defra-ruby-mocks&metric=coverage)](https://sonarcloud.io/dashboard?id=DEFRA_defra-ruby-mocks)
|
6
6
|
[![security](https://hakiri.io/github/DEFRA/defra-ruby-mocks/master.svg)](https://hakiri.io/github/DEFRA/defra-ruby-mocks/master)
|
7
7
|
[![Licence](https://img.shields.io/badge/Licence-OGLv3-blue.svg)](http://www.nationalarchives.gov.uk/doc/open-government-licence/version/3)
|
8
8
|
|
@@ -104,6 +104,94 @@ The list of possible statuses was taken from
|
|
104
104
|
- [Companies House API](https://developer.companieshouse.gov.uk/api/docs/company/company_number/companyProfile-resource.html)
|
105
105
|
- [Companies House API enumerations](https://github.com/companieshouse/api-enumerations/blob/master/constants.yml)
|
106
106
|
|
107
|
+
### Worldpay
|
108
|
+
|
109
|
+
When mounted into an app you can simulate interacting with the Worldpay hosted pages service.
|
110
|
+
|
111
|
+
#### Payments
|
112
|
+
|
113
|
+
Making a payment with Worldpay essentially comes in 2 stages
|
114
|
+
|
115
|
+
1. The app sends an XML request to Worldpay asking it to prepare for a new payment. Worldpay responds with a reference and a URL to redirect the user to
|
116
|
+
2. The app redirects the user to the URL and adds to it query params that tell Worldpay where to redirect the user to when the payment is complete
|
117
|
+
|
118
|
+
For more details check out [Making a payment with WorldPay](https://github.com/DEFRA/ruby-services-team/blob/master/services/wcr/payment_with_worldpay.md)
|
119
|
+
|
120
|
+
This Worldpay mock replicates those 2 interactions with the following urls
|
121
|
+
|
122
|
+
- `../worldpay/payments-service`
|
123
|
+
- `../worldpay/dispatcher`
|
124
|
+
|
125
|
+
##### Refused payments
|
126
|
+
|
127
|
+
The engine has the ability to also mock Worldpay refusing a payment. To have the mock refuse payment just ensure the registration's company name includes the word `reject` (case doesn't matter).
|
128
|
+
|
129
|
+
If it does the engine will redirect back to the failure url instead of the success url provided, plus set the payment status to `REFUSED`.
|
130
|
+
|
131
|
+
This allows us to test how the application handles both successful and unsucessful Worldpay payments.
|
132
|
+
|
133
|
+
##### Stuck payments
|
134
|
+
|
135
|
+
The engine has the ability to also mock Worldpay not redirecting back to the service. This is the equivalent of a registration getting 'stuck at Worldpay'. To have the mock not respond just ensure the registration's company name includes the word `stuck` (case doesn't matter).
|
136
|
+
|
137
|
+
If it does the engine will not redirect back to the service, but instead render a 'You're stuck!' page.
|
138
|
+
|
139
|
+
This allows us to test how the application handles Worldpay not returning after we redirect a user to them.
|
140
|
+
|
141
|
+
#### Refunds
|
142
|
+
|
143
|
+
Requesting a refund from Worldpay is a single step process.
|
144
|
+
|
145
|
+
1. The app sends an XML request to Worldpay with details of the order to be refunded and the amount. Worldpay returns an XML response confirming the request has been received
|
146
|
+
|
147
|
+
Like payments, refund requests are also sent to the same url `../worldpay/payments-service`. The mock handles determining what request is being made and returns the appropriate response.
|
148
|
+
|
149
|
+
#### Configuration
|
150
|
+
|
151
|
+
In order to use the Worldpay mock you'll need to provide additional configuration details
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
# config/initializers/defra_ruby_mocks.rb
|
155
|
+
require "defra_ruby_mocks"
|
156
|
+
|
157
|
+
DefraRubyMocks.configure do |config|
|
158
|
+
config.enable = true
|
159
|
+
config.delay = 1000
|
160
|
+
|
161
|
+
config.worldpay_admin_code = "admincode1"
|
162
|
+
config.worldpay_mac_secret = "macsecret1"
|
163
|
+
config.worldpay_merchant_code = "merchantcode1"
|
164
|
+
config.worldpay_domain = "http://localhost:3000/mocks"
|
165
|
+
end
|
166
|
+
```
|
167
|
+
|
168
|
+
It's important that the admin code, mac secret and merchant code are the same as used by the apps calling the Worldpay mock. These values are used when generating the responses and are validated by the apps so it's important they match.
|
169
|
+
|
170
|
+
The domain is used when generating the URL we tell the app to redirect users to. As this is just an engine and not a standalone service, we need to tell it what domain it is running from. For example, if the engine is mounted into the app like this
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
mount DefraRubyMocks::Engine => "/mocks"
|
174
|
+
```
|
175
|
+
|
176
|
+
And the app is running at `http://localhost:3000`, this engine can then use that information to tell the app to redirect users to `http://localhost:3000/mocks/worldpay/dispatcher` as part of the `payments-service` response.
|
177
|
+
|
178
|
+
#### Only for Waste Carriers
|
179
|
+
|
180
|
+
At this time there is only one digital service built using Ruby on Rails that uses Worldpay; the [Waste Carriers Registration service](https://github.com/DEFRA/ruby-services-team/tree/master/services/wcr). So the Worldpay mock has been written with the assumption it will only be mounted into one of the Waste Carriers apps.
|
181
|
+
|
182
|
+
A critical aspect of this is the expectation that the following classes will be loaded and available when the engine is mounted and the app is running
|
183
|
+
|
184
|
+
- `WasteCarriersEngine::TransientRegistration`
|
185
|
+
- `WasteCarriersEngine::Registration`
|
186
|
+
|
187
|
+
We need these classes so we can use them to query the database for the registration the payment is being made against. We only get the registration reference in the request made to `/worldpay/dispatcher`, not the order code. As the response needs to include the order code we need access to these ActiveRecord models to locate the last order added.
|
188
|
+
|
189
|
+
In the live Worldpay service this information (along with the amount to be paid) is saved after the initial request to `/payments-service`. The mock however isn't persisting anything to reduce complexity. So instead it needs to be able to query the database for the information it needs via ActiveRecord.
|
190
|
+
|
191
|
+
#### Payment pages are not mocked
|
192
|
+
|
193
|
+
The actual Worldpay service presents payment pages that display a form where users are able to enter their credit card details and confirm the payment is correct. This mock does **not** replicate the UI of Worldpay, only the API. Bear this in mind when building any automated acceptance tests.
|
194
|
+
|
107
195
|
## Installation
|
108
196
|
|
109
197
|
You don't need to do this if you're just mounting the engine without making any changes.
|
data/Rakefile
CHANGED
@@ -25,7 +25,6 @@ Bundler::GemHelper.install_tasks
|
|
25
25
|
# This is wrapped to prevent an error when rake is called in environments where
|
26
26
|
# rspec may not be available, e.g. production. As such we don't need to handle
|
27
27
|
# the error.
|
28
|
-
# rubocop:disable Lint/HandleExceptions
|
29
28
|
begin
|
30
29
|
require "rspec/core/rake_task"
|
31
30
|
|
@@ -35,4 +34,3 @@ begin
|
|
35
34
|
rescue LoadError
|
36
35
|
# no rspec available
|
37
36
|
end
|
38
|
-
# rubocop:enable Lint/HandleExceptions
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefraRubyMocks
|
4
|
+
class WorldpayController < ::DefraRubyMocks::ApplicationController
|
5
|
+
|
6
|
+
before_action :set_default_response_format
|
7
|
+
|
8
|
+
def payments_service
|
9
|
+
@values = WorldpayRequestHandlerService.run(convert_request_body_to_xml)
|
10
|
+
|
11
|
+
render_payment_response if @values[:request_type] == :payment
|
12
|
+
render_refund_response if @values[:request_type] == :refund
|
13
|
+
rescue StandardError
|
14
|
+
head 500
|
15
|
+
end
|
16
|
+
|
17
|
+
def dispatcher
|
18
|
+
@response = WorldpayResponseService.run(
|
19
|
+
success_url: params[:successURL],
|
20
|
+
failure_url: params[:failureURL]
|
21
|
+
)
|
22
|
+
|
23
|
+
if @response.status == :STUCK
|
24
|
+
render formats: :html, action: "stuck", layout: false
|
25
|
+
else
|
26
|
+
redirect_to @response.url
|
27
|
+
end
|
28
|
+
rescue StandardError
|
29
|
+
head 500
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def set_default_response_format
|
35
|
+
request.format = :xml
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_request_body_to_xml
|
39
|
+
Nokogiri::XML(request.body.read)
|
40
|
+
end
|
41
|
+
|
42
|
+
def render_payment_response
|
43
|
+
render "defra_ruby_mocks/worldpay/payment_request"
|
44
|
+
end
|
45
|
+
|
46
|
+
def render_refund_response
|
47
|
+
render "defra_ruby_mocks/worldpay/refund_request"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefraRubyMocks
|
4
|
+
class WorldpayPaymentService < BaseService
|
5
|
+
def run(merchant_code:, xml:)
|
6
|
+
check_config
|
7
|
+
|
8
|
+
@merchant_code = merchant_code
|
9
|
+
@order_code = extract_order_code(xml)
|
10
|
+
|
11
|
+
{
|
12
|
+
merchant_code: @merchant_code,
|
13
|
+
order_code: @order_code,
|
14
|
+
id: generate_id,
|
15
|
+
url: generate_url
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def check_config
|
22
|
+
domain = DefraRubyMocks.configuration.worldpay_domain
|
23
|
+
|
24
|
+
raise InvalidConfigError, :worldpay_domain if domain.blank?
|
25
|
+
end
|
26
|
+
|
27
|
+
def extract_order_code(xml)
|
28
|
+
order = xml.at_xpath("//order")
|
29
|
+
order.attribute("orderCode").text
|
30
|
+
end
|
31
|
+
|
32
|
+
def generate_id
|
33
|
+
# Worldpay seems to generate 10 digit numbers for all its ID's. So we
|
34
|
+
# replicate that here with this.
|
35
|
+
# https://stackoverflow.com/a/31043825
|
36
|
+
rand(1e9...1e10).to_i.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def generate_url
|
40
|
+
"#{base_url}?OrderKey=#{@merchant_code}%5E#{@order_code}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def base_url
|
44
|
+
File.join(DefraRubyMocks.configuration.worldpay_domain, "/worldpay/dispatcher")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefraRubyMocks
|
4
|
+
class WorldpayRefundService < BaseService
|
5
|
+
def run(merchant_code:, xml:)
|
6
|
+
{
|
7
|
+
merchant_code: merchant_code,
|
8
|
+
order_code: extract_order_code(xml),
|
9
|
+
refund_value: extract_refund_value(xml),
|
10
|
+
currency_code: extract_currency_code(xml),
|
11
|
+
exponent: extract_exponent(xml)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def extract_order_code(xml)
|
18
|
+
order_modification = xml.at_xpath("//orderModification")
|
19
|
+
order_modification.attribute("orderCode").text
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract_refund_value(xml)
|
23
|
+
amount = xml.at_xpath("//amount")
|
24
|
+
amount.attribute("value").text
|
25
|
+
end
|
26
|
+
|
27
|
+
def extract_currency_code(xml)
|
28
|
+
amount = xml.at_xpath("//amount")
|
29
|
+
amount.attribute("currencyCode").text
|
30
|
+
end
|
31
|
+
|
32
|
+
def extract_exponent(xml)
|
33
|
+
amount = xml.at_xpath("//amount")
|
34
|
+
amount.attribute("exponent").text
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefraRubyMocks
|
4
|
+
class WorldpayRequestHandlerService < BaseService
|
5
|
+
def run(xml)
|
6
|
+
arguments = {
|
7
|
+
merchant_code: extract_merchant_code(xml),
|
8
|
+
xml: xml
|
9
|
+
}
|
10
|
+
|
11
|
+
generate_response(arguments)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def extract_merchant_code(xml)
|
17
|
+
payment_service = xml.at_xpath("//paymentService")
|
18
|
+
payment_service.attribute("merchantCode").text
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_response(arguments)
|
22
|
+
return WorldpayPaymentService.run(arguments).merge(request_type: :payment) if payment_request?(arguments[:xml])
|
23
|
+
return WorldpayRefundService.run(arguments).merge(request_type: :refund) if refund_request?(arguments[:xml])
|
24
|
+
|
25
|
+
raise UnrecognisedWorldpayRequestError
|
26
|
+
end
|
27
|
+
|
28
|
+
def payment_request?(xml)
|
29
|
+
submit = xml.at_xpath("//submit")
|
30
|
+
|
31
|
+
!submit.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def refund_request?(xml)
|
35
|
+
modify = xml.at_xpath("//modify")
|
36
|
+
|
37
|
+
!modify.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefraRubyMocks
|
4
|
+
class WorldpayResourceService < BaseService
|
5
|
+
|
6
|
+
def run(reference:)
|
7
|
+
@reference = reference
|
8
|
+
|
9
|
+
raise(MissingResourceError, @reference) if resource.nil?
|
10
|
+
|
11
|
+
WorldpayResource.new(resource, order, company_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
WorldpayResource = Struct.new(:resource, :order, :company_name)
|
17
|
+
|
18
|
+
def resource
|
19
|
+
@_resource ||= locate_transient_registration || locate_completed_registration
|
20
|
+
end
|
21
|
+
|
22
|
+
def locate_transient_registration
|
23
|
+
"WasteCarriersEngine::TransientRegistration"
|
24
|
+
.constantize
|
25
|
+
.where(token: @reference)
|
26
|
+
.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def locate_completed_registration
|
30
|
+
"WasteCarriersEngine::Registration"
|
31
|
+
.constantize
|
32
|
+
.where(reg_uuid: @reference)
|
33
|
+
.first
|
34
|
+
end
|
35
|
+
|
36
|
+
def locate_original_registration(reg_identifier)
|
37
|
+
"WasteCarriersEngine::Registration"
|
38
|
+
.constantize
|
39
|
+
.where(reg_identifier: reg_identifier)
|
40
|
+
.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def order
|
44
|
+
@_order ||= resource.finance_details&.orders&.order_by(dateCreated: :desc)&.first
|
45
|
+
end
|
46
|
+
|
47
|
+
def company_name
|
48
|
+
if resource.class.to_s == "WasteCarriersEngine::OrderCopyCardsRegistration"
|
49
|
+
locate_original_registration(resource.reg_identifier).company_name.downcase
|
50
|
+
else
|
51
|
+
resource.company_name.downcase
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefraRubyMocks
|
4
|
+
class WorldpayResponseService < BaseService
|
5
|
+
|
6
|
+
def run(success_url:, failure_url:)
|
7
|
+
parse_reference(success_url)
|
8
|
+
@resource = WorldpayResourceService.run(reference: @reference)
|
9
|
+
|
10
|
+
generate_response(success_url, failure_url)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
WorldpayResponse = Struct.new(:supplied_url, :separator, :order_key, :mac, :value, :status, :reference) do
|
16
|
+
def url
|
17
|
+
[supplied_url, separator, params].join
|
18
|
+
end
|
19
|
+
|
20
|
+
def params
|
21
|
+
[
|
22
|
+
"orderKey=#{order_key}",
|
23
|
+
"paymentStatus=#{status}",
|
24
|
+
"paymentAmount=#{value}",
|
25
|
+
"paymentCurrency=GBP",
|
26
|
+
"mac=#{mac}",
|
27
|
+
"source=WP"
|
28
|
+
].join("&")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_reference(url)
|
33
|
+
path = URI.parse(url).path
|
34
|
+
parts = path.split("/")
|
35
|
+
|
36
|
+
if parts[1].downcase == "your-registration"
|
37
|
+
# ["", "your-registration", "xP2zj9nqWYI0SAsMtGZn6w", "worldpay", "success", "1577812071", "NEWREG"]
|
38
|
+
@reference = parts[-5]
|
39
|
+
@url_format = :old
|
40
|
+
else
|
41
|
+
# ["", "fo", "jq6sTt2RQguAu4ZyKFfRg9zm", "worldpay", "success"]
|
42
|
+
@reference = parts[-3]
|
43
|
+
@url_format = :new
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def order_key
|
48
|
+
[
|
49
|
+
DefraRubyMocks.configuration.worldpay_admin_code,
|
50
|
+
DefraRubyMocks.configuration.worldpay_merchant_code,
|
51
|
+
@resource.order.order_code
|
52
|
+
].join("^")
|
53
|
+
end
|
54
|
+
|
55
|
+
def order_value
|
56
|
+
@resource.order.total_amount.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
def payment_status
|
60
|
+
return :REFUSED if @resource.company_name.include?("reject")
|
61
|
+
return :STUCK if @resource.company_name.include?("stuck")
|
62
|
+
|
63
|
+
:AUTHORISED
|
64
|
+
end
|
65
|
+
|
66
|
+
def generate_mac(status)
|
67
|
+
data = [
|
68
|
+
order_key,
|
69
|
+
order_value,
|
70
|
+
"GBP",
|
71
|
+
status,
|
72
|
+
DefraRubyMocks.configuration.worldpay_mac_secret
|
73
|
+
]
|
74
|
+
|
75
|
+
Digest::MD5.hexdigest(data.join).to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate_response(success_url, failure_url)
|
79
|
+
status = payment_status
|
80
|
+
|
81
|
+
WorldpayResponse.new(
|
82
|
+
status == :AUTHORISED ? success_url : failure_url,
|
83
|
+
@url_format == :new ? "?" : "&",
|
84
|
+
order_key,
|
85
|
+
generate_mac(status),
|
86
|
+
order_value,
|
87
|
+
status,
|
88
|
+
@reference
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|