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 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
- 'order' => {'reference' => transaction.reference},
32
- 'cardDetails' => {purchase_token_key(token) => token},
33
- 'transaction' => {'amount' => transaction.amount.to_s, 'currency' => transaction.currency, 'reference' => transaction_id.to_s}
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/#{@merchant_id}/order/#{order_id}/transaction/#{transaction_id}", params
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/#{@merchant_id}/order/#{order_id}/transaction/#{transaction_id}", params
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
- request :post, "/merchant/#{@merchant_id}/token"
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/#{@merchant_id}/token/#{token}"
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/#{@merchant_id}/session"
61
- response.success?? response.response['session'] : raise(response.response.inspect)
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 api_url
68
- "#{host}/api/rest/version/4"
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 purchase_token_key token
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
- authorization = options.fetch(:authorization) { true }
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
- extend Forwardable
3
+ attr_reader :raw_response
4
4
 
5
- attr_reader :response
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 credit_card
15
- @credit_card ||= Tns::CreditCard.new @response['card']
9
+ def response
10
+ @response ||= JSON.parse(raw_response)
16
11
  end
17
12
 
18
13
  def success?
19
- %w[SUCCESS OPERATING].include? @result
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
@@ -1,3 +1,3 @@
1
1
  module TNSPayments
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/tns_payments.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'tns_payments/connection'
2
- require 'tns_payments/credit_card'
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(:headers => {'Accept'=>'*/*', 'Content-Type'=>'Application/json;charset=UTF-8'}, :body => {})
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\/\d{16}/).
228
- with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'Application/json;charset=UTF-8'}, :body => {})
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
@@ -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: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
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-08 00:00:00 +10:00
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/credit_card.rb
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