tns_payments 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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