tns_payments 0.0.4 → 0.0.5
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.
- data/CHANGELOG.md +6 -0
- data/lib/tns_payments/connection.rb +19 -32
- data/lib/tns_payments/request.rb +33 -0
- data/lib/tns_payments/response.rb +15 -11
- data/lib/tns_payments/version.rb +1 -1
- data/lib/tns_payments.rb +3 -1
- data/test/unit/conntection_test.rb +38 -21
- data/test/unit/response_test.rb +25 -0
- metadata +5 -5
- data/lib/tns_payments/credit_card.rb +0 -8
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.0.5 / 2012-03-29
|
4
|
+
|
5
|
+
* Tokenize credit card.
|
6
|
+
* Request gets it's own class.
|
7
|
+
* Raise SessionTokenException when `session_token` request is invalid.
|
8
|
+
|
3
9
|
## 0.0.4 / 2012-03-08
|
4
10
|
|
5
11
|
* Check credit card token length as well as starting digit.
|
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'base64'
|
2
|
-
require 'json'
|
3
|
-
require 'rest-client'
|
4
2
|
|
5
3
|
module TNSPayments
|
6
4
|
class Connection
|
7
5
|
CREDIT_CARD_TOKEN_FORMAT = /^9\d{15}/
|
8
6
|
|
9
7
|
attr_accessor :host
|
8
|
+
attr_reader :api_key, :merchant_id
|
10
9
|
attr_writer :session_token
|
11
10
|
|
12
11
|
def available?
|
@@ -28,12 +27,12 @@ module TNSPayments
|
|
28
27
|
transaction_id = transaction.transaction_id
|
29
28
|
params = {
|
30
29
|
'apiOperation' => 'PAY',
|
31
|
-
'
|
32
|
-
'
|
33
|
-
'transaction' => {'amount'
|
30
|
+
'cardDetails' => card_details(token),
|
31
|
+
'order' => {'reference' => transaction.reference},
|
32
|
+
'transaction' => {'amount' => transaction.amount.to_s, 'currency' => transaction.currency, 'reference' => transaction_id.to_s}
|
34
33
|
}
|
35
34
|
|
36
|
-
request :put, "/merchant/#{
|
35
|
+
request :put, "/merchant/#{merchant_id}/order/#{order_id}/transaction/#{transaction_id}", params
|
37
36
|
end
|
38
37
|
|
39
38
|
def refund transaction
|
@@ -44,52 +43,40 @@ module TNSPayments
|
|
44
43
|
'transaction' => {'amount' => transaction.amount.to_s, 'currency' => transaction.currency, 'reference' => transaction_id.to_s}
|
45
44
|
}
|
46
45
|
|
47
|
-
request :put, "/merchant/#{
|
46
|
+
request :put, "/merchant/#{merchant_id}/order/#{order_id}/transaction/#{transaction_id}", params
|
48
47
|
end
|
49
48
|
|
50
|
-
def create_credit_card_token
|
51
|
-
|
49
|
+
def create_credit_card_token token
|
50
|
+
params = {
|
51
|
+
'cardDetails' => card_details(token)
|
52
|
+
}
|
53
|
+
|
54
|
+
request :post, "/merchant/#{merchant_id}/token", params
|
52
55
|
end
|
53
56
|
|
54
57
|
def delete_credit_card_token token
|
55
|
-
request :delete, "/merchant/#{
|
58
|
+
request :delete, "/merchant/#{merchant_id}/token/#{token}"
|
56
59
|
end
|
57
60
|
|
58
61
|
def session_token
|
59
62
|
@session_token ||= begin
|
60
|
-
response = request :post, "/merchant/#{
|
61
|
-
response.
|
63
|
+
response = request :post, "/merchant/#{merchant_id}/session"
|
64
|
+
response.response.fetch('session') { raise(SessionTokenException.new, response.message) }
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
65
68
|
private
|
66
69
|
|
67
|
-
def
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
def encode_credentials
|
72
|
-
credentials = ['', @api_key].join(':')
|
73
|
-
'Basic ' << Base64.encode64(credentials)
|
70
|
+
def card_details token
|
71
|
+
{token_key(token) => token}
|
74
72
|
end
|
75
73
|
|
76
|
-
def
|
74
|
+
def token_key token
|
77
75
|
token =~ CREDIT_CARD_TOKEN_FORMAT ? 'cardToken' : 'session'
|
78
76
|
end
|
79
77
|
|
80
78
|
def request method, path, options = {}
|
81
|
-
|
82
|
-
url = api_url << path
|
83
|
-
auth_headers = {:Authorization => encode_credentials}
|
84
|
-
headers = {:content_type => 'Application/json;charset=UTF-8', :accept => '*/*'}
|
85
|
-
headers.merge! auth_headers if authorization
|
86
|
-
|
87
|
-
args = [headers]
|
88
|
-
args.unshift(options.to_json) unless [:delete, :get, :head].include? method
|
89
|
-
|
90
|
-
Response.new JSON.parse(RestClient.send(method, url, *args))
|
91
|
-
rescue RestClient::Exception => e
|
92
|
-
Response.new 'result' => e.message.upcase, 'response' => e.response
|
79
|
+
Request.new(self, method, path, options).perform
|
93
80
|
end
|
94
81
|
end
|
95
82
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
module TNSPayments
|
5
|
+
class Request
|
6
|
+
attr_accessor :connection, :method, :path, :options
|
7
|
+
|
8
|
+
def initialize connection, method, path, options = {}
|
9
|
+
self.connection, self.method, self.path, self.options = connection, method, path, options
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform
|
13
|
+
authorization = options.fetch(:authorization) { true }
|
14
|
+
url = "#{connection.host}/api/rest/version/4#{path}"
|
15
|
+
auth_headers = {:Authorization => encode_credentials}
|
16
|
+
headers = {:content_type => 'Application/json;charset=UTF-8', :accept => '*/*'}
|
17
|
+
headers.merge! auth_headers if authorization
|
18
|
+
|
19
|
+
args = [headers]
|
20
|
+
args.unshift(options.to_json) unless [:delete, :get, :head].include? method
|
21
|
+
|
22
|
+
Response.new RestClient.send(method, url, *args)
|
23
|
+
rescue RestClient::Exception => e
|
24
|
+
Response.new({:result => e.message.upcase, :response => JSON.parse(e.response || '{}')}.to_json)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def encode_credentials
|
30
|
+
'Basic ' + Base64.encode64(":#{connection.api_key}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,22 +1,26 @@
|
|
1
1
|
module TNSPayments
|
2
2
|
class Response
|
3
|
-
|
3
|
+
attr_reader :raw_response
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
def_delegators :credit_card, :card_type
|
8
|
-
|
9
|
-
def initialize body
|
10
|
-
@response = body
|
11
|
-
@result = @response['result'] || @response['status']
|
5
|
+
def initialize response
|
6
|
+
@raw_response = response
|
12
7
|
end
|
13
8
|
|
14
|
-
def
|
15
|
-
@
|
9
|
+
def response
|
10
|
+
@response ||= JSON.parse(raw_response)
|
16
11
|
end
|
17
12
|
|
18
13
|
def success?
|
19
|
-
%w[SUCCESS OPERATING].include?
|
14
|
+
%w[SUCCESS OPERATING].include? response['result'] || response['status']
|
15
|
+
end
|
16
|
+
|
17
|
+
def message
|
18
|
+
result = response['response'].fetch('result') { 'SUCCESS' }
|
19
|
+
if result == 'ERROR'
|
20
|
+
response['response']['error']['explanation']
|
21
|
+
else
|
22
|
+
'Successful request'
|
23
|
+
end
|
20
24
|
end
|
21
25
|
end
|
22
26
|
end
|
data/lib/tns_payments/version.rb
CHANGED
data/lib/tns_payments.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'tns_payments/connection'
|
2
|
-
require 'tns_payments/
|
2
|
+
require 'tns_payments/request'
|
3
3
|
require 'tns_payments/response'
|
4
4
|
require 'tns_payments/version'
|
5
5
|
|
6
6
|
module TNSPayments
|
7
|
+
class SessionTokenException < Exception; end
|
8
|
+
|
7
9
|
def self.new options = {}
|
8
10
|
Connection.new options
|
9
11
|
end
|
@@ -64,29 +64,29 @@ class TNSPayments::ConnectionTest < MiniTest::Unit::TestCase
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def test_create_credit_card_token_successfully_stores_creditcard
|
67
|
-
stub_successful_create_credit_card_token_request
|
68
|
-
assert @gateway.create_credit_card_token.success?
|
67
|
+
stub_successful_create_credit_card_token_request 'SESSIONTOKEN'
|
68
|
+
assert @gateway.create_credit_card_token('SESSIONTOKEN').success?
|
69
69
|
end
|
70
70
|
|
71
71
|
def test_create_credit_card_token_returns_valid_card_token_when_successful
|
72
|
-
stub_successful_create_credit_card_token_request
|
73
|
-
token = @gateway.create_credit_card_token.response['cardToken']
|
72
|
+
stub_successful_create_credit_card_token_request 'SESSIONTOKEN'
|
73
|
+
token = @gateway.create_credit_card_token('SESSIONTOKEN').response['cardToken']
|
74
74
|
assert_equal 16, token.size
|
75
75
|
assert_match Connection::CREDIT_CARD_TOKEN_FORMAT, token
|
76
76
|
end
|
77
77
|
|
78
78
|
def test_create_credit_card_token_unsuccessfully_attempts_to_store_credit_card
|
79
|
-
stub_unsuccessful_create_credit_card_token_request
|
80
|
-
refute @gateway.create_credit_card_token.success?
|
79
|
+
stub_unsuccessful_create_credit_card_token_request 'SESSIONTOKEN'
|
80
|
+
refute @gateway.create_credit_card_token('SESSIONTOKEN').success?
|
81
81
|
end
|
82
82
|
|
83
83
|
def test_delete_credit_card_token_successfully_deletes_a_stored_credit_card_token
|
84
|
-
stub_successful_delete_credit_card_token_request
|
84
|
+
stub_successful_delete_credit_card_token_request '9123456781234567'
|
85
85
|
assert @gateway.delete_credit_card_token('9123456781234567').success?
|
86
86
|
end
|
87
87
|
|
88
88
|
def test_delete_credit_card_token_unsuccessfully_attempts_to_delete_a_stored_credit_card
|
89
|
-
stub_unsuccessful_delete_credit_card_token_request
|
89
|
+
stub_unsuccessful_delete_credit_card_token_request '9123456781234567'
|
90
90
|
refute @gateway.delete_credit_card_token('9123456781234567').success?
|
91
91
|
end
|
92
92
|
|
@@ -95,6 +95,13 @@ class TNSPayments::ConnectionTest < MiniTest::Unit::TestCase
|
|
95
95
|
assert_equal 'SESSIONTOKEN', @gateway.session_token
|
96
96
|
end
|
97
97
|
|
98
|
+
def test_unsuccessful_session_token_request_raises_an_exception
|
99
|
+
stub_session_token_request.to_return(:status => 400, :body => '{}')
|
100
|
+
assert_raises SessionTokenException do
|
101
|
+
@gateway.session_token
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
98
105
|
private
|
99
106
|
|
100
107
|
def stub_availability_request
|
@@ -137,23 +144,23 @@ private
|
|
137
144
|
to_return(:status => 200, :body => '{"result":"FAILURE"}', :headers => {})
|
138
145
|
end
|
139
146
|
|
140
|
-
def stub_successful_create_credit_card_token_request
|
141
|
-
stub_create_credit_card_token_request.
|
147
|
+
def stub_successful_create_credit_card_token_request token
|
148
|
+
stub_create_credit_card_token_request(token).
|
142
149
|
to_return(:status => 200, :body => %{{"result":"SUCCESS", "response":{"gatewayCode":"BASIC_VERIFICATION_SUCCESSFUL"}, "card":{"number":"xxxxxxxxxxxxxxxx", "scheme":"MASTERCARD", "expiry":{"month":"5", "year":"13"}}, "cardToken":"9102370788509763"}}, :headers => {})
|
143
150
|
end
|
144
151
|
|
145
|
-
def stub_unsuccessful_create_credit_card_token_request
|
146
|
-
stub_create_credit_card_token_request.
|
152
|
+
def stub_unsuccessful_create_credit_card_token_request token
|
153
|
+
stub_create_credit_card_token_request(token).
|
147
154
|
to_return(:status => 200, :body => '{"result":"FAILURE"}', :headers => {})
|
148
155
|
end
|
149
156
|
|
150
|
-
def stub_successful_delete_credit_card_token_request
|
151
|
-
stub_delete_credit_card_token_request.
|
157
|
+
def stub_successful_delete_credit_card_token_request token
|
158
|
+
stub_delete_credit_card_token_request(token).
|
152
159
|
to_return(:status => 200, :body => '{"result":"SUCCESS"}', :headers => {})
|
153
160
|
end
|
154
161
|
|
155
|
-
def stub_unsuccessful_delete_credit_card_token_request
|
156
|
-
stub_delete_credit_card_token_request.
|
162
|
+
def stub_unsuccessful_delete_credit_card_token_request token
|
163
|
+
stub_delete_credit_card_token_request(token).
|
157
164
|
to_return(:status => 200, :body => '{"result":"FAILURE"}', :headers => {})
|
158
165
|
end
|
159
166
|
|
@@ -218,14 +225,24 @@ private
|
|
218
225
|
}
|
219
226
|
end
|
220
227
|
|
221
|
-
def stub_create_credit_card_token_request
|
228
|
+
def stub_create_credit_card_token_request token
|
222
229
|
stub_request(:post, /https:\/\/:#{@api_key}@secure\.ap\.tnspayments\.com\/api\/rest\/version\/4\/merchant\/#{@merchant_id}\/token/).
|
223
|
-
with
|
230
|
+
with :body => JSON.generate({
|
231
|
+
'cardDetails' => {'session' => token}
|
232
|
+
}),
|
233
|
+
:headers => {
|
234
|
+
'Accept' => '*/*',
|
235
|
+
'Content-Type' => 'Application/json;charset=UTF-8'
|
236
|
+
}
|
224
237
|
end
|
225
238
|
|
226
|
-
def stub_delete_credit_card_token_request
|
227
|
-
stub_request(:delete, /https:\/\/:#{@api_key}@secure\.ap\.tnspayments\.com\/api\/rest\/version\/4\/merchant\/#{@merchant_id}\/token
|
228
|
-
with
|
239
|
+
def stub_delete_credit_card_token_request token
|
240
|
+
stub_request(:delete, /https:\/\/:#{@api_key}@secure\.ap\.tnspayments\.com\/api\/rest\/version\/4\/merchant\/#{@merchant_id}\/token\/#{token}/).
|
241
|
+
with :body => {},
|
242
|
+
:headers => {
|
243
|
+
'Accept' => '*/*',
|
244
|
+
'Content-Type' => 'Application/json;charset=UTF-8'
|
245
|
+
}
|
229
246
|
end
|
230
247
|
|
231
248
|
def mock_transaction
|
data/test/unit/response_test.rb
CHANGED
@@ -1,4 +1,29 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TNSPayments::ResponseTest < MiniTest::Unit::TestCase
|
4
|
+
def test_success_when_operating
|
5
|
+
assert Response.new({:result => 'OPERATING'}.to_json).success?
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_success_when_success
|
9
|
+
assert Response.new({:result => 'SUCCESS'}.to_json).success?
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_success_when_not_successful
|
13
|
+
refute Response.new({:result => '404 RESOURCE NOT FOUND'}.to_json).success?
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_message_when_error_request
|
17
|
+
response = "{\"result\":\"401 UNAUTHORIZED\",\"response\":{\"error\":{\"cause\":\"INVALID_REQUEST\",\"explanation\":\"Invalid credentials.\"},\"result\":\"ERROR\"}}"
|
18
|
+
assert_equal 'Invalid credentials.', Response.new(response).message
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_message_when_success_request
|
22
|
+
assert_equal 'Successful request', Response.new({:result => 'SUCCESS', :response => {}}.to_json).message
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_raw_response_is_the_json
|
26
|
+
response = "{\"result\":\"401 UNAUTHORIZED\",\"response\":{\"error\":{\"cause\":\"INVALID_REQUEST\",\"explanation\":\"Invalid credentials.\"},\"result\":\"ERROR\"}}"
|
27
|
+
assert_equal response, Response.new(response).raw_response
|
28
|
+
end
|
4
29
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tns_payments
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tim Cooper
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-03-
|
18
|
+
date: 2012-03-29 00:00:00 +10:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -104,7 +104,7 @@ files:
|
|
104
104
|
- Rakefile
|
105
105
|
- lib/tns_payments.rb
|
106
106
|
- lib/tns_payments/connection.rb
|
107
|
-
- lib/tns_payments/
|
107
|
+
- lib/tns_payments/request.rb
|
108
108
|
- lib/tns_payments/response.rb
|
109
109
|
- lib/tns_payments/version.rb
|
110
110
|
- test/helper.rb
|
@@ -1,8 +0,0 @@
|
|
1
|
-
module TNSPayments
|
2
|
-
class CreditCard
|
3
|
-
FORM_RESPONSE_MAPPING = {:gatewayCardExpiryDateYear => :year, :gatewayCardExpiryDateMonth => :month, :gatewayCardNumber => :number, :gatewayCardSecurityCode => :verification_value}.freeze
|
4
|
-
|
5
|
-
def initialize args = {}
|
6
|
-
end
|
7
|
-
end
|
8
|
-
end
|