datatrans 4.0.1 → 5.1.0
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/.github/workflows/ci.yml +8 -2
- data/CHANGELOG.md +17 -0
- data/README.markdown +121 -3
- data/lib/datatrans/config.rb +19 -2
- data/lib/datatrans/json/transaction/authorize.rb +48 -0
- data/lib/datatrans/json/transaction/response.rb +22 -0
- data/lib/datatrans/json/transaction/status.rb +44 -0
- data/lib/datatrans/json/transaction.rb +32 -0
- data/lib/datatrans/version.rb +1 -1
- data/lib/datatrans/xml/transaction/request.rb +4 -2
- data/lib/datatrans.rb +1 -0
- data/spec/config_spec.rb +7 -1
- data/spec/json/authorize_spec.rb +79 -0
- data/spec/json/status_spec.rb +75 -0
- data/spec/json/transaction_spec.rb +10 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/xml/request_spec.rb +3 -1
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6749673b2125a6a645cef06bd13d1a9d3f6f58276bd9e6abe18c287e0b821637
|
4
|
+
data.tar.gz: 26912c6b041d37f4af6872b5bfb138e0b9b90545058335c1f58407aa874125b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f4ab534d4b3b8a684c42489c300fa6c7da8b442a4ec8faf168408712b8eb8318950dcfa25685f755826bb7270cf93adbdda7bc7a05778d8c4be4913437db439
|
7
|
+
data.tar.gz: d595075292ae69128eaf4f56f9c99eff69a736c91300fd2ced3baa2f4b918a5a15aa6b52ecfd0987a23e6ebf508c88239ba9075482b1dc6988540632c0f172bb
|
data/.github/workflows/ci.yml
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
---
|
2
2
|
name: CI
|
3
|
-
on: [push, pull_request]
|
3
|
+
on: [ push, pull_request ]
|
4
4
|
jobs:
|
5
5
|
tests:
|
6
6
|
runs-on: ubuntu-latest
|
7
7
|
strategy:
|
8
8
|
fail-fast: false
|
9
9
|
matrix:
|
10
|
-
ruby: [ '2.6', '2.7', '3.0', '3.1' ]
|
10
|
+
ruby: [ '2.6', '2.7', '3.0', '3.1', '3.2' ]
|
11
11
|
rails: [ '5-2', '6-0', '6-1', '7-0' ]
|
12
12
|
exclude:
|
13
13
|
- ruby: 2.6 # Rails 7 requires 2.7 minimum
|
@@ -20,6 +20,12 @@ jobs:
|
|
20
20
|
rails: 6-0
|
21
21
|
- ruby: 3.1
|
22
22
|
rails: 6-1
|
23
|
+
- ruby: 3.2 # Ruby 3.2 only works on the latest Rails 7 version
|
24
|
+
rails: 5-2
|
25
|
+
- ruby: 3.2
|
26
|
+
rails: 6-0
|
27
|
+
- ruby: 3.2
|
28
|
+
rails: 6-1
|
23
29
|
|
24
30
|
steps:
|
25
31
|
- uses: actions/checkout@v2
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,23 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|
5
5
|
|
6
6
|
## [Unreleased]
|
7
7
|
|
8
|
+
## 5.1.0 - 2023-07-06
|
9
|
+
|
10
|
+
### Added
|
11
|
+
|
12
|
+
* Test against Ruby 3.2 (@andyundso [#43](https://github.com/simplificator/datatrans/pull/43))
|
13
|
+
* Add support for Datatrans JSON API (@TatianaPan [#45](https://github.com/simplificator/datatrans/pull/45)). Check Readme for details on how to use it.
|
14
|
+
|
15
|
+
XML API is [deprecated](https://mailchi.mp/datatrans/basic-authdynamic-sign_reminder) by Datatrans and will not be supported by them after June 3rd, 2024. Consider to moving to a [new JSON API](https://api-reference.datatrans.ch/).
|
16
|
+
|
17
|
+
## 5.0.0 - 2022-09-21
|
18
|
+
|
19
|
+
### Changed
|
20
|
+
|
21
|
+
* [BREAKING CHANGE] Authenticate requests with HTTP Basic Auth (@crackofdusk [#41](https://github.com/simplificator/datatrans/pull/41))
|
22
|
+
|
23
|
+
Datatrans requires [HTTP Basic Auth for XML API calls](https://api-reference.datatrans.ch/xml/#authentication-tls) since 2022-09-14 ([announcement](https://mailchi.mp/datatrans/basic-authsign2_1-email_en))
|
24
|
+
|
8
25
|
## 4.0.1 - 2022-03-18
|
9
26
|
### Fixed
|
10
27
|
* Check for successful transaction depends on `status` and not on `response_message` that can be diferent for different payment methods (@schmijos [#8](https://github.com/simplificator/datatrans/pull/8) and @TatianaPan [#39](https://github.com/simplificator/datatrans/pull/39))
|
data/README.markdown
CHANGED
@@ -8,9 +8,11 @@ Configuration
|
|
8
8
|
|
9
9
|
Build your Datatrans Configuration like so:
|
10
10
|
|
11
|
+
```ruby
|
11
12
|
datatrans = Datatrans::Config.new(
|
12
13
|
:merchant_id => '1234567',
|
13
14
|
:sign_key => 'ab739fd5b7c2a1...',
|
15
|
+
:password => 'server to server request password',
|
14
16
|
:environment => :production,
|
15
17
|
:proxy => {
|
16
18
|
:http_proxyaddr => "proxy.com",
|
@@ -19,7 +21,7 @@ Build your Datatrans Configuration like so:
|
|
19
21
|
:http_proxpass => "xxx",
|
20
22
|
}
|
21
23
|
)
|
22
|
-
|
24
|
+
```
|
23
25
|
|
24
26
|
If you don't want to use signed requests (disabled in datatrans web console), you can set `config.sign_key` to `false`.
|
25
27
|
The configuration is then used as parameter to all the constructors and helpers, see examples below.
|
@@ -32,6 +34,7 @@ Web Authorization
|
|
32
34
|
If you want to process a credit card the first time a web authorization is
|
33
35
|
necessary. Add the following code to a controller action that shows the form.
|
34
36
|
You need to pass at least `amount`, `currency` and `refno` (order number).
|
37
|
+
```ruby
|
35
38
|
@transaction = datatrans.web_transaction(
|
36
39
|
:amount => 1000, # in cents!
|
37
40
|
:currency => 'CHF',
|
@@ -39,9 +42,11 @@ You need to pass at least `amount`, `currency` and `refno` (order number).
|
|
39
42
|
:uppCustomerEmail => 'customer@email.com',
|
40
43
|
# feel free to add more upp infos here ...
|
41
44
|
)
|
45
|
+
```
|
42
46
|
|
43
47
|
In your View your show the credit card form with a convenient helper:
|
44
48
|
|
49
|
+
```ruby
|
45
50
|
= form_tag Datatrans.web_authorize_url do
|
46
51
|
|
47
52
|
= text_field_tag :paymentmethod, 'ECA'
|
@@ -57,6 +62,7 @@ In your View your show the credit card form with a convenient helper:
|
|
57
62
|
= datatrans_notification_request_hidden_fields(datatrans, @transaction)
|
58
63
|
|
59
64
|
= submit_tag "send"
|
65
|
+
```
|
60
66
|
|
61
67
|
In this example we use just ECA (Mastercard) as paymentmethod. Feel free to
|
62
68
|
provide an appropriate select field to offer more payment methods. Don't forget
|
@@ -65,7 +71,7 @@ to the same value.
|
|
65
71
|
|
66
72
|
After you submit the request to Datatrans they redirect back to your application.
|
67
73
|
Now you can process the transaction like this:
|
68
|
-
|
74
|
+
```ruby
|
69
75
|
begin
|
70
76
|
transaction = datatrans.web_transaction(params)
|
71
77
|
|
@@ -85,16 +91,124 @@ Now you can process the transaction like this:
|
|
85
91
|
rescue Datatrans::InvalidSignatureError => exception
|
86
92
|
# the signature was wrong, the request may have been compromised...
|
87
93
|
end
|
94
|
+
```
|
95
|
+
|
96
|
+
JSON Transactions
|
97
|
+
=================
|
98
|
+
|
99
|
+
More information about Datatrans JSON API can be found [here](https://api-reference.datatrans.ch/). Our gem uses endpoints from `/v1/transactions` section.
|
100
|
+
|
101
|
+
We implemented support for [Redirect mode](https://docs.datatrans.ch/docs/redirect-lightbox) (since Lightbox mode may not work correctly on mobile, whereas Redirect works well on all devises).
|
102
|
+
|
103
|
+
Authorize
|
104
|
+
---------
|
105
|
+
|
106
|
+
Authorize JSON transaction:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
transaction = datatrans.json_transaction(
|
110
|
+
refno: 'ABCDEF',
|
111
|
+
amount: 1000, # in cents!
|
112
|
+
currency: "CHF",
|
113
|
+
payment_methods: ["ECA", "VIS"],
|
114
|
+
success_url: <your_application_return_url>,
|
115
|
+
cancel_url: <your_application_return_url>,
|
116
|
+
error_url: <your_application_return_url>
|
117
|
+
)
|
118
|
+
|
119
|
+
# call to init endpoint to initialize a transaction
|
120
|
+
# returns true or false depending if response was successful or not
|
121
|
+
init = transaction.authorize
|
122
|
+
|
123
|
+
# successful authorization call returns in response a transaction id
|
124
|
+
if init
|
125
|
+
transaction_id = transaction.response.params["transactionId"]
|
126
|
+
end
|
127
|
+
```
|
128
|
+
|
129
|
+
Start a transaction
|
130
|
+
-------------------
|
131
|
+
|
132
|
+
Once you have a transaction id, you can start a transaction. Users of your application will be redirected to the datatrans payment pages: `https://pay.sandbox.datatrans.com/v1/start/{{transactionId}}`.
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
path = datatrans.json_transaction(transaction_id: transaction_id).transaction_path
|
136
|
+
|
137
|
+
redirect_to path
|
138
|
+
# or if you redirect after AJAX request:
|
139
|
+
render js: "window.location='#{path}'"
|
140
|
+
```
|
141
|
+
|
142
|
+
You do not have to [settle a transaction](https://api-reference.datatrans.ch/#tag/v1transactions/operation/settle) by yourself: we set `"autoSettle": true` by default when authorizing a transaction, which means the transaction will be settled automatically.
|
143
|
+
|
144
|
+
Transaction status
|
145
|
+
------------------
|
146
|
+
|
147
|
+
You can check the trasaction [status](https://api-reference.datatrans.ch/#tag/v1transactions/operation/status), see its history and retrieve the card information.
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
transaction = datatrans.json_transaction(transaction_id: transaction_id)
|
151
|
+
|
152
|
+
# status method returns true or false depending if response was successfull
|
153
|
+
if transaction.status
|
154
|
+
data = transaction.response.params
|
155
|
+
# this will return following hash (may vary dependong on your payment method):
|
156
|
+
{
|
157
|
+
"transactionId"=>"230223022302230223",
|
158
|
+
"merchantId"=>"1100000000",
|
159
|
+
"type"=>"payment",
|
160
|
+
"status"=>"settled",
|
161
|
+
"currency"=>"CHF",
|
162
|
+
"refno"=>"123456abc",
|
163
|
+
"paymentMethod"=>"VIS",
|
164
|
+
"detail"=>
|
165
|
+
{"authorize"=>{"amount"=>1000, "acquirerAuthorizationCode"=>"100000"}, "settle"=>{"amount"=>1000}},
|
166
|
+
"language"=>"en",
|
167
|
+
"card"=>
|
168
|
+
{"masked"=>"400000xxxxxx0018",
|
169
|
+
"expiryMonth"=>"06",
|
170
|
+
"expiryYear"=>"25",
|
171
|
+
"info"=>
|
172
|
+
{"brand"=>"VISA",
|
173
|
+
"type"=>"debit",
|
174
|
+
"usage"=>"consumer",
|
175
|
+
"country"=>"SE",
|
176
|
+
"issuer"=>"SVENSKA HANDELSBANKEN AB"},
|
177
|
+
"3D"=>{"authenticationResponse"=>"Y"}},
|
178
|
+
"history"=>
|
179
|
+
[{"action"=>"init",
|
180
|
+
"amount"=>1000,
|
181
|
+
"source"=>"api",
|
182
|
+
"date"=>"2023-06-06T08:37:23Z",
|
183
|
+
"success"=>true,
|
184
|
+
"ip"=>"8.8.8.8"},
|
185
|
+
{"action"=>"authorize",
|
186
|
+
"autoSettle"=>true,
|
187
|
+
"amount"=>1000,
|
188
|
+
"source"=>"redirect",
|
189
|
+
"date"=>"2023-06-06T08:37:42Z",
|
190
|
+
"success"=>true,
|
191
|
+
"ip"=>"8.8.8.8"}]
|
192
|
+
}
|
193
|
+
else
|
194
|
+
transaction.response.error_code
|
195
|
+
transaction.response.error_message
|
196
|
+
end
|
197
|
+
```
|
198
|
+
|
88
199
|
|
89
200
|
XML Transactions
|
90
201
|
================
|
91
202
|
|
203
|
+
XML API is [deprecated](https://mailchi.mp/datatrans/basic-authdynamic-sign_reminder) by Datatrans. After June 3rd, 2024 all merchants will have to use JSON API.
|
204
|
+
|
92
205
|
If you have already a credit card alias or an authorized transaction you can
|
93
206
|
use the convenient XML methods to process payments.
|
94
207
|
|
95
208
|
Authorize
|
96
209
|
---------
|
97
210
|
|
211
|
+
```ruby
|
98
212
|
transaction = datatrans.xml_transaction(
|
99
213
|
:refno => 'ABCDEF',
|
100
214
|
:amount => 1000, # in cents!
|
@@ -110,6 +224,7 @@ Authorize
|
|
110
224
|
else
|
111
225
|
# transaction.error_code, transaction.error_message, transaction.error_detail
|
112
226
|
end
|
227
|
+
```
|
113
228
|
|
114
229
|
|
115
230
|
Capture
|
@@ -117,6 +232,7 @@ Capture
|
|
117
232
|
|
118
233
|
To capture an authorized transaction you use the following code:
|
119
234
|
|
235
|
+
```ruby
|
120
236
|
transaction = datatrans.xml_transaction(
|
121
237
|
:refno => 'ABCDEF',
|
122
238
|
:amount => 1000, # in cents!
|
@@ -129,13 +245,14 @@ To capture an authorized transaction you use the following code:
|
|
129
245
|
else
|
130
246
|
# transaction.error_code, transaction.error_message, transaction.error_detail
|
131
247
|
end
|
132
|
-
|
248
|
+
```
|
133
249
|
|
134
250
|
Void
|
135
251
|
----
|
136
252
|
|
137
253
|
To make an authorized transaction invalid use void.
|
138
254
|
|
255
|
+
```ruby
|
139
256
|
transaction = datatrans.xml_transaction(
|
140
257
|
:refno => 'ABCDEF',
|
141
258
|
:amount => 1000, # in cents!
|
@@ -148,6 +265,7 @@ To make an authorized transaction invalid use void.
|
|
148
265
|
else
|
149
266
|
# transaction.error_code, transaction.error_message, transaction.error_detail
|
150
267
|
end
|
268
|
+
```
|
151
269
|
|
152
270
|
Todo
|
153
271
|
====
|
data/lib/datatrans/config.rb
CHANGED
@@ -11,10 +11,11 @@ module Datatrans
|
|
11
11
|
}
|
12
12
|
DOMAIN = 'datatrans.com'
|
13
13
|
|
14
|
-
attr_reader :environment, :merchant_id, :sign_key, :proxy
|
14
|
+
attr_reader :environment, :merchant_id, :sign_key, :password, :proxy
|
15
15
|
|
16
16
|
# Configure with following options
|
17
17
|
# * :merchant_id (required)
|
18
|
+
# * :password (required)
|
18
19
|
# * :sign_key (defaults to false)
|
19
20
|
# * :environment (defaults to :development, available environments are defined in ENVIRONMENTS)
|
20
21
|
# * :proxy (a hash containing :http_proxyaddr, :http_proxyport, :http_proxyuser, :http_proxypass)
|
@@ -22,6 +23,8 @@ module Datatrans
|
|
22
23
|
@merchant_id = options[:merchant_id]
|
23
24
|
raise ArgumentError.new(":merchant_id is required") unless self.merchant_id
|
24
25
|
self.environment = options[:environment] || DEFAULT_ENVIRONMENT
|
26
|
+
@password = options[:password]
|
27
|
+
raise ArgumentError.new(":password is required") unless self.password
|
25
28
|
@sign_key = options[:sign_key] || DEFAULT_SIGN_KEY
|
26
29
|
@proxy = options[:proxy] || {}
|
27
30
|
end
|
@@ -36,7 +39,7 @@ module Datatrans
|
|
36
39
|
end
|
37
40
|
|
38
41
|
# Access a url, is automatically scoped to environment
|
39
|
-
def url(what)
|
42
|
+
def url(what, options = {})
|
40
43
|
case what
|
41
44
|
when :web_authorize_url
|
42
45
|
subdomain = SUBDOMAINS[:payment_page]
|
@@ -50,6 +53,16 @@ module Datatrans
|
|
50
53
|
when :xml_status_url
|
51
54
|
subdomain = SUBDOMAINS[:server_to_server_api]
|
52
55
|
path = '/upp/jsp/XML_status.jsp'
|
56
|
+
when :init_transaction
|
57
|
+
subdomain = SUBDOMAINS[:server_to_server_api]
|
58
|
+
path = "/v1/transactions"
|
59
|
+
when :start_json_transaction
|
60
|
+
subdomain = SUBDOMAINS[:payment_page]
|
61
|
+
path = "/v1/start/#{options[:transaction_id]}"
|
62
|
+
when :json_status_url
|
63
|
+
# https://api.sandbox.datatrans.com/v1/transactions/{transactionId}
|
64
|
+
subdomain = SUBDOMAINS[:server_to_server_api]
|
65
|
+
path = "/v1/transactions/#{options[:transaction_id]}"
|
53
66
|
else
|
54
67
|
raise "Unknown wanted action '#{what}'."
|
55
68
|
end
|
@@ -64,5 +77,9 @@ module Datatrans
|
|
64
77
|
def xml_transaction(*args)
|
65
78
|
XML::Transaction.new(self, *args)
|
66
79
|
end
|
80
|
+
|
81
|
+
def json_transaction(*args)
|
82
|
+
JSON::Transaction.new(self, *args)
|
83
|
+
end
|
67
84
|
end
|
68
85
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'datatrans/json/transaction/response'
|
3
|
+
|
4
|
+
class Datatrans::JSON::Transaction
|
5
|
+
class Authorize
|
6
|
+
# class to initialize a new transaction https://api-reference.datatrans.ch/#tag/v1transactions/operation/init
|
7
|
+
attr_accessor :params, :datatrans
|
8
|
+
|
9
|
+
def initialize(datatrans, params)
|
10
|
+
@datatrans = datatrans
|
11
|
+
@params = params
|
12
|
+
end
|
13
|
+
|
14
|
+
def post(url, options = {})
|
15
|
+
options = options
|
16
|
+
.merge(self.datatrans.proxy)
|
17
|
+
.merge(:basic_auth => { :username => self.datatrans.merchant_id, :password => self.datatrans.password })
|
18
|
+
HTTParty.post(url, **options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def process
|
22
|
+
post(self.datatrans.url(:init_transaction),
|
23
|
+
:headers => { 'Content-Type' => 'application/json' },
|
24
|
+
:body => request_body.to_json).parsed_response
|
25
|
+
end
|
26
|
+
|
27
|
+
def request_body
|
28
|
+
{
|
29
|
+
"currency": params[:currency],
|
30
|
+
"refno": params[:refno],
|
31
|
+
"amount": params[:amount],
|
32
|
+
"autoSettle": true,
|
33
|
+
"paymentMethods": params[:payment_methods],
|
34
|
+
"redirect": {
|
35
|
+
"successUrl": params[:success_url],
|
36
|
+
"cancelUrl": params[:cancel_url],
|
37
|
+
"errorUrl": params[:error_url]
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class AuthorizeResponse < Response
|
44
|
+
def successful?
|
45
|
+
params["error"].blank? && params["transactionId"].present?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Datatrans::JSON::Transaction
|
2
|
+
class Response
|
3
|
+
attr_accessor :params, :datatrans
|
4
|
+
|
5
|
+
def initialize(datatrans, params)
|
6
|
+
@datatrans = datatrans
|
7
|
+
@params = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def successful?
|
11
|
+
raise 'overwrite in subclass!'
|
12
|
+
end
|
13
|
+
|
14
|
+
def error_code
|
15
|
+
params["error"]["code"] rescue nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def error_message
|
19
|
+
params["error"]["message"] rescue nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'datatrans/json/transaction/response'
|
3
|
+
|
4
|
+
class Datatrans::JSON::Transaction
|
5
|
+
class Status
|
6
|
+
# class to check a transaction status and get a transaction info: https://api-reference.datatrans.ch/#tag/v1transactions/operation/status
|
7
|
+
attr_accessor :params, :datatrans
|
8
|
+
|
9
|
+
def initialize(datatrans, params)
|
10
|
+
@datatrans = datatrans
|
11
|
+
@params = params
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(url, options = {})
|
15
|
+
options = options
|
16
|
+
.merge(self.datatrans.proxy)
|
17
|
+
.merge(:basic_auth => { :username => self.datatrans.merchant_id, :password => self.datatrans.password })
|
18
|
+
HTTParty.get(url, **options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def process
|
22
|
+
get(self.datatrans.url(:json_status_url, transaction_id: params[:transaction_id]),
|
23
|
+
:headers => { 'Content-Type' => 'application/json' }).parsed_response
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class StatusResponse < Response
|
28
|
+
def successful?
|
29
|
+
params["error"].blank? && ["settled", "transmitted"].include?(response_code)
|
30
|
+
end
|
31
|
+
|
32
|
+
def response_code
|
33
|
+
params["status"] rescue nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def reference_number
|
37
|
+
params["refno"] rescue nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def amount
|
41
|
+
params["detail"]["settle"]["amount"] rescue nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_support/core_ext/hash'
|
2
|
+
|
3
|
+
module Datatrans::JSON
|
4
|
+
class Transaction
|
5
|
+
attr_accessor :request
|
6
|
+
attr_reader :response, :params, :datatrans
|
7
|
+
|
8
|
+
def initialize(datatrans, params)
|
9
|
+
@datatrans = datatrans
|
10
|
+
@params = params
|
11
|
+
end
|
12
|
+
|
13
|
+
def authorize
|
14
|
+
self.request = Authorize.new(self.datatrans, params)
|
15
|
+
@response = AuthorizeResponse.new(self.datatrans, request.process)
|
16
|
+
@response.successful?
|
17
|
+
end
|
18
|
+
|
19
|
+
def status
|
20
|
+
self.request = Status.new(self.datatrans, params)
|
21
|
+
@response = StatusResponse.new(self.datatrans, request.process)
|
22
|
+
@response.successful?
|
23
|
+
end
|
24
|
+
|
25
|
+
def transaction_path
|
26
|
+
self.datatrans.url(:start_json_transaction, transaction_id: params[:transaction_id])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require 'datatrans/json/transaction/authorize'
|
32
|
+
require 'datatrans/json/transaction/status'
|
data/lib/datatrans/version.rb
CHANGED
@@ -7,7 +7,9 @@ class Datatrans::XML::Transaction
|
|
7
7
|
attr_accessor :params, :datatrans
|
8
8
|
|
9
9
|
def post(url, options = {})
|
10
|
-
options = options
|
10
|
+
options = options
|
11
|
+
.merge(self.datatrans.proxy)
|
12
|
+
.merge(:basic_auth => { :username => self.datatrans.merchant_id, :password => self.datatrans.password })
|
11
13
|
HTTParty.post(url, **options)
|
12
14
|
end
|
13
15
|
|
@@ -39,4 +41,4 @@ class Datatrans::XML::Transaction
|
|
39
41
|
xml.target!
|
40
42
|
end
|
41
43
|
end
|
42
|
-
end
|
44
|
+
end
|
data/lib/datatrans.rb
CHANGED
data/spec/config_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Datatrans::Config do
|
4
4
|
describe "Instance Methods" do
|
5
5
|
before do
|
6
|
-
@datatrans = Datatrans::Config.new(:merchant_id => "xxx")
|
6
|
+
@datatrans = Datatrans::Config.new(:merchant_id => "xxx", :password => "yyy")
|
7
7
|
end
|
8
8
|
|
9
9
|
describe "web_transaction" do
|
@@ -17,5 +17,11 @@ describe Datatrans::Config do
|
|
17
17
|
expect(@datatrans.xml_transaction({}).class).to eq(Datatrans::XML::Transaction)
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
describe "json_transaction" do
|
22
|
+
it "builds a new json transaction object" do
|
23
|
+
expect(@datatrans.json_transaction({}).class).to eq(Datatrans::JSON::Transaction)
|
24
|
+
end
|
25
|
+
end
|
20
26
|
end
|
21
27
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Datatrans::JSON::Transaction::Authorize do
|
4
|
+
before do
|
5
|
+
@successful_response = {
|
6
|
+
"transactionId" => "230223022302230223"
|
7
|
+
}
|
8
|
+
|
9
|
+
@failed_response = {
|
10
|
+
"error" => {
|
11
|
+
"code" => "INVALID_PROPERTY",
|
12
|
+
"message" => "init.refno must not be null"
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
@valid_params = {
|
17
|
+
currency: "CHF",
|
18
|
+
refno: "B4B4B4B4B",
|
19
|
+
amount: 1337,
|
20
|
+
payment_methods: ["ECA", "VIS"],
|
21
|
+
success_url: "https://pay.sandbox.datatrans.com/upp/merchant/successPage.jsp",
|
22
|
+
cancel_url: "https://pay.sandbox.datatrans.com/upp/merchant/cancelPage.jsp",
|
23
|
+
error_url: "https://pay.sandbox.datatrans.com/upp/merchant/errorPage.jsp"
|
24
|
+
}
|
25
|
+
|
26
|
+
@invalid_params = {
|
27
|
+
currency: "CHF",
|
28
|
+
refno: nil,
|
29
|
+
amount: 1337,
|
30
|
+
payment_methods: ["ECA", "VIS"],
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
context "successful response" do
|
35
|
+
before do
|
36
|
+
allow_any_instance_of(Datatrans::JSON::Transaction::Authorize).to receive(:process).and_return(@successful_response)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "generates correct request_body" do
|
40
|
+
expected = {
|
41
|
+
"currency": "CHF",
|
42
|
+
"refno": "B4B4B4B4B",
|
43
|
+
"amount": 1337,
|
44
|
+
"autoSettle": true,
|
45
|
+
"paymentMethods": ["ECA", "VIS"],
|
46
|
+
"redirect": {
|
47
|
+
"successUrl": "https://pay.sandbox.datatrans.com/upp/merchant/successPage.jsp",
|
48
|
+
"cancelUrl": "https://pay.sandbox.datatrans.com/upp/merchant/cancelPage.jsp",
|
49
|
+
"errorUrl": "https://pay.sandbox.datatrans.com/upp/merchant/errorPage.jsp"
|
50
|
+
}
|
51
|
+
}
|
52
|
+
request = Datatrans::JSON::Transaction::Authorize.new(@datatrans, @valid_params)
|
53
|
+
|
54
|
+
expect(request.request_body).to eq(expected)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "#process handles a valid datatrans authorize response" do
|
58
|
+
@transaction = Datatrans::JSON::Transaction.new(@datatrans, @valid_params)
|
59
|
+
expect(@transaction.authorize).to be true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "failed response" do
|
64
|
+
before do
|
65
|
+
allow_any_instance_of(Datatrans::JSON::Transaction::Authorize).to receive(:process).and_return(@failed_response)
|
66
|
+
@transaction = Datatrans::JSON::Transaction.new(@datatrans, @invalid_params)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "#process handles a failed datatrans authorize response" do
|
70
|
+
expect(@transaction.authorize).to be false
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns error details" do
|
74
|
+
@transaction.authorize
|
75
|
+
expect(@transaction.response.error_code).to eq "INVALID_PROPERTY"
|
76
|
+
expect(@transaction.response.error_message).to eq "init.refno must not be null"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Datatrans::JSON::Transaction::Status do
|
4
|
+
before do
|
5
|
+
@successful_response = {
|
6
|
+
"transactionId" => "230223022302230223",
|
7
|
+
"merchantId" => "1100000000",
|
8
|
+
"type" => "payment",
|
9
|
+
"status" => "settled",
|
10
|
+
"currency" => "CHF",
|
11
|
+
"refno" => "B4B4B4B4B",
|
12
|
+
"paymentMethod" => "VIS",
|
13
|
+
"detail" => {
|
14
|
+
"authorize" => {}
|
15
|
+
},
|
16
|
+
"card" => {
|
17
|
+
"masked" => "424242xxxxxx4242",
|
18
|
+
"expiryMonth" => "06",
|
19
|
+
"expiryYear" => "25",
|
20
|
+
"info" => {}
|
21
|
+
},
|
22
|
+
"history" => [
|
23
|
+
{
|
24
|
+
"action" => "authorize",
|
25
|
+
"amount" => 1000,
|
26
|
+
"source" => "api",
|
27
|
+
"date" => "2023-02-08T14:25:24Z",
|
28
|
+
"success" => true,
|
29
|
+
"ip" => "8.8.8.8"
|
30
|
+
}
|
31
|
+
]
|
32
|
+
}
|
33
|
+
|
34
|
+
@failed_response = {
|
35
|
+
"error" => {
|
36
|
+
"code" => "INVALID_PROPERTY",
|
37
|
+
"message" => "status transactionId length must be 18 digits"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
@valid_params = {
|
42
|
+
transaction_id: '230223022302230223',
|
43
|
+
}
|
44
|
+
|
45
|
+
@invalid_params = {
|
46
|
+
transaction_id: '0208020802080208', # wrong number of digits in ID
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
context "successful response" do
|
51
|
+
before do
|
52
|
+
allow_any_instance_of(Datatrans::JSON::Transaction::Status).to receive(:process).and_return(@successful_response)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "#process handles a valid datatrans status response" do
|
56
|
+
transaction = Datatrans::JSON::Transaction.new(@datatrans, @valid_params)
|
57
|
+
expect(transaction.status).to be true
|
58
|
+
expect(transaction.response.params["refno"]).to eq "B4B4B4B4B"
|
59
|
+
expect(transaction.response.params["paymentMethod"]).to eq "VIS"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "failed response" do
|
64
|
+
before do
|
65
|
+
allow_any_instance_of(Datatrans::JSON::Transaction::Status).to receive(:process).and_return(@failed_response)
|
66
|
+
@transaction = Datatrans::JSON::Transaction.new(@datatrans, @invalid_params)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "handles a failed datatrans status response" do
|
70
|
+
expect(@transaction.status).to be false
|
71
|
+
expect(@transaction.response.error_code).to eq "INVALID_PROPERTY"
|
72
|
+
expect(@transaction.response.error_message).to eq "status transactionId length must be 18 digits"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Datatrans::JSON::Transaction do
|
4
|
+
it "returns correct trasaction_path" do
|
5
|
+
params = {transaction_id: "230223022302230223"}
|
6
|
+
transaction = Datatrans::JSON::Transaction.new(@datatrans, params)
|
7
|
+
|
8
|
+
expect(transaction.transaction_path).to eq "https://pay.sandbox.datatrans.com/v1/start/230223022302230223"
|
9
|
+
end
|
10
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -15,6 +15,7 @@ RSpec.configure do |config|
|
|
15
15
|
@datatrans = Datatrans::Config.new(
|
16
16
|
:merchant_id => '1100000000',
|
17
17
|
:sign_key => 'd777c17ba2010282c2d2350a68b441ca07a799d294bfaa630b7c8442207c0b69703cc55775b0ca5a4e455b818a9bb10a43669c0c20ce31f4a43f10e0cabb9525',
|
18
|
+
:password => 'basic_auth_password',
|
18
19
|
:environment => :development
|
19
20
|
)
|
20
21
|
end
|
data/spec/xml/request_spec.rb
CHANGED
@@ -7,6 +7,7 @@ describe Datatrans::XML::Transaction::Request do
|
|
7
7
|
@datatrans = Datatrans::Config.new(
|
8
8
|
:merchant_id => '1100000000',
|
9
9
|
:sign_key => 'd777c17ba2010282c2d2350a68b441ca07a799d294bfaa630b7c8442207c0b69703cc55775b0ca5a4e455b818a9bb10a43669c0c20ce31f4a43f10e0cabb9525',
|
10
|
+
:password => 'basic_auth_password',
|
10
11
|
:key => "value",
|
11
12
|
:proxy => {
|
12
13
|
:http_proxyaddr => "proxy.com",
|
@@ -21,6 +22,7 @@ describe Datatrans::XML::Transaction::Request do
|
|
21
22
|
it "forward those options to HTTParty" do
|
22
23
|
request = Datatrans::XML::Transaction::Request.new(@datatrans, {})
|
23
24
|
expect(HTTParty).to receive(:post).with('lirum',
|
25
|
+
:basic_auth => {:password => 'basic_auth_password', :username => '1100000000'},
|
24
26
|
:params => {:foo => :bar},
|
25
27
|
:http_proxpass => 'xxx',
|
26
28
|
:http_proxyuser => 'hans',
|
@@ -33,7 +35,7 @@ describe Datatrans::XML::Transaction::Request do
|
|
33
35
|
describe "not configured" do
|
34
36
|
it "should not add any proxy settings" do
|
35
37
|
request = Datatrans::XML::Transaction::Request.new(@datatrans, {})
|
36
|
-
expect(HTTParty).to receive(:post).with('lirum', :params => {:foo => :bar})
|
38
|
+
expect(HTTParty).to receive(:post).with('lirum', :basic_auth => {:password => 'basic_auth_password', :username => '1100000000'}, :params => {:foo => :bar})
|
37
39
|
request.post('lirum', :params => {:foo => :bar})
|
38
40
|
end
|
39
41
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: datatrans
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 5.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Miesel
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date:
|
14
|
+
date: 2023-07-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: httparty
|
@@ -165,6 +165,10 @@ files:
|
|
165
165
|
- lib/datatrans.rb
|
166
166
|
- lib/datatrans/common.rb
|
167
167
|
- lib/datatrans/config.rb
|
168
|
+
- lib/datatrans/json/transaction.rb
|
169
|
+
- lib/datatrans/json/transaction/authorize.rb
|
170
|
+
- lib/datatrans/json/transaction/response.rb
|
171
|
+
- lib/datatrans/json/transaction/status.rb
|
168
172
|
- lib/datatrans/version.rb
|
169
173
|
- lib/datatrans/web/transaction.rb
|
170
174
|
- lib/datatrans/web/transaction/authorize.rb
|
@@ -178,6 +182,9 @@ files:
|
|
178
182
|
- lib/datatrans/xml/transaction/void.rb
|
179
183
|
- spec/common_spec.rb
|
180
184
|
- spec/config_spec.rb
|
185
|
+
- spec/json/authorize_spec.rb
|
186
|
+
- spec/json/status_spec.rb
|
187
|
+
- spec/json/transaction_spec.rb
|
181
188
|
- spec/spec_helper.rb
|
182
189
|
- spec/web/authorize_spec.rb
|
183
190
|
- spec/xml/authorize_spec.rb
|