straight-server-kit 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 371f0f2803fd90c9dcc9f1e81a3c0d6e3a760c01
4
- data.tar.gz: 0c5fe9a5d52bca199d784acce675b55d222ff3ef
3
+ metadata.gz: 42c92cfbb55d2a9c63a48f6ba070178f21094291
4
+ data.tar.gz: 8d73b5ceb43e1744ecdf96b38beed1c328030539
5
5
  SHA512:
6
- metadata.gz: c88f6c14842cb15fbd44d8efe1ff5a764fd3e39110979b24c23a7afb3b4704fba92b249777f6397fa407a1ad42faca002689fdce3f471b0e0b05d910abbfc08e
7
- data.tar.gz: 34726dbfcb75815f75fea12ac78625ec95f671e3104da9edc99c2369d1e9582c01e9993a2b5bf7d9d21cb49ed7ca8ec2236a84bfcc8852fbe912b935c12ee828
6
+ metadata.gz: e35f434ba01efb2bafc93b3db053adb7b61b231c20fc6d6394ce0c3e9065eda6ea8355476e323b3ba53020da75aaf949e92ced25edf120ef6f5c94067817eb4e
7
+ data.tar.gz: ded69fc391c0babfad8a711b2bb66c89cca2aca360e38aa4ddfb81f44dbed056cdabc86ba51ce144f4d753c382c9482f84b6e8db28fa0a0995e37755bde2e884
data/README.md CHANGED
@@ -21,27 +21,28 @@ Or install it yourself as:
21
21
  ## Usage
22
22
 
23
23
  ```ruby
24
- client = StraightServerKit::Client.new(url: 'http://gear.loc')
25
- client = StraightServerKit::Client.new
24
+ client = StraightServerKit::Client.new(gateway_id: 'gateway_id', secret: 'secret', url: 'http://gear.loc')
26
25
  ```
27
26
 
28
- ### Order resource
27
+ ## Order resource
29
28
 
29
+ client = StraightServerKit::Client.new(gateway_id: 1, secret: 'secret')
30
30
  client.orders #=> StraightServerKit::OrderResource
31
31
 
32
- Actions supported:
32
+ Actions supported:
33
33
 
34
- * `client.orders.create(order, gateway_id: 'gateway_id')`
35
- * `client.orders.find(gateway_id: 'gateway_id', id: 'id')`
34
+ * `client.orders.create(order)`
35
+ * `client.orders.find(id: 'id')`
36
+ * `client.orders.cancel(id: 'id')`
36
37
 
37
- ### Order signing
38
+ ### Order creation
38
39
 
39
40
  order = StraightServerKit::Order.new(amount: 0.01, callback_data: '123', keychain_id: 1)
40
- order.sign_with 'gateway_secret'
41
+ client.orders.create(order)
41
42
 
42
43
  ### Callback validation
43
44
 
44
- if StraightServerKit.valid_callback?(params, 'gateway_secret')
45
+ if StraightServerKit.valid_callback?(signature: headers['X-Signature'], request_uri: @env['REQUEST_URI'], secret: gateway_secret)
45
46
  # params can be trusted
46
47
  end
47
48
 
@@ -1,6 +1,7 @@
1
1
  require 'straight-server-kit/version'
2
2
  require 'resource_kit'
3
3
  require 'kartograph'
4
+ require 'openssl'
4
5
 
5
6
  module StraightServerKit
6
7
  autoload :Client, File.expand_path('../straight-server-kit/client', __FILE__)
@@ -13,17 +14,20 @@ module StraightServerKit
13
14
  # Resources
14
15
  autoload :OrderResource, File.expand_path('../straight-server-kit/resources/order_resource', __FILE__)
15
16
 
16
- def self.valid_callback?(params, secret)
17
- return false unless params[:signature] && params[:order_id]
18
- sign(content: params[:order_id], secret: secret) == params[:signature]
17
+ # @param [String] signature X-Signature header
18
+ # @param [String] request_uri /full/callback_path/with?order&callback_data
19
+ # @param [String] secret gateway secret
20
+ def self.valid_callback?(signature:, request_uri:, secret:)
21
+ signature == self.signature(nonce: nil, body: nil, method: 'GET', request_uri: request_uri, secret: secret)
19
22
  end
20
23
 
21
- def self.sign(content:, secret:, level: 1)
22
- return unless secret
23
- result = content.to_s
24
- level.times do
25
- result = OpenSSL::HMAC.hexdigest('sha256', secret.to_s, result)
26
- end
27
- result
24
+ def self.valid_signature?(signature:, **args)
25
+ signature == self.signature(**args)
26
+ end
27
+
28
+ def self.signature(nonce:, body:, method:, request_uri:, secret:)
29
+ sha512 = OpenSSL::Digest::SHA512.new
30
+ request = "#{method.to_s.upcase}#{request_uri}#{sha512.digest("#{nonce}#{body}")}"
31
+ Base64.strict_encode64 OpenSSL::HMAC.digest(sha512, secret.to_s, request)
28
32
  end
29
33
  end
@@ -5,11 +5,13 @@ module StraightServerKit
5
5
 
6
6
  DEFAULT_API_URL = 'http://localhost:9000'.freeze
7
7
 
8
- attr_reader :url, :resources
8
+ attr_reader :url, :resources, :gateway_id, :secret
9
9
 
10
- def initialize(url: DEFAULT_API_URL)
11
- @url = url
12
- @resources = {}
10
+ def initialize(gateway_id:, secret:, url: DEFAULT_API_URL)
11
+ @gateway_id = gateway_id
12
+ @secret = secret
13
+ @url = url
14
+ @resources = {}
13
15
  end
14
16
 
15
17
  def pay_url(order)
@@ -17,14 +19,15 @@ module StraightServerKit
17
19
  end
18
20
 
19
21
  def connection
20
- Faraday.new(connection_options) { |req|
21
- req.adapter :net_http
22
- }
22
+ Faraday.new(connection_options) do |faraday|
23
+ faraday.use SigningMiddleware, @secret
24
+ faraday.adapter :net_http
25
+ end
23
26
  end
24
27
 
25
28
  def method_missing(name, *args, &block)
26
- if self.class.resources.keys.include?(name)
27
- resources[name] ||= self.class.resources[name].new(connection: connection)
29
+ if self.class.resources.has_key?(name)
30
+ resources[name] ||= self.class.resources[name].for_gateway(@gateway_id).new(connection: connection)
28
31
  else
29
32
  super
30
33
  end
@@ -39,10 +42,33 @@ module StraightServerKit
39
42
  private def connection_options
40
43
  {
41
44
  url: url,
45
+ ssl: {
46
+ ca_path: ENV['SSL_CERT_DIR'] || '/etc/ssl/certs',
47
+ },
42
48
  headers: {
43
49
  content_type: 'application/json',
44
50
  }
45
51
  }
46
52
  end
53
+
54
+ class SigningMiddleware < Faraday::Middleware
55
+
56
+ def initialize(app, secret)
57
+ @app = app
58
+ @secret = secret
59
+ end
60
+
61
+ def call(env)
62
+ env[:request_headers]['X-Nonce'] = nonce = (Time.now.to_f * 1e12).to_i.to_s
63
+ env[:request_headers]['X-Signature'] = StraightServerKit.signature(
64
+ nonce: nonce,
65
+ body: env[:body],
66
+ method: env[:method],
67
+ request_uri: URI(env[:url]).request_uri,
68
+ secret: @secret,
69
+ )
70
+ @app.call(env)
71
+ end
72
+ end
47
73
  end
48
74
  end
@@ -9,14 +9,9 @@ module StraightServerKit
9
9
  attribute :keychain_id, Integer
10
10
  attribute :last_keychain_id, Integer
11
11
  attribute :payment_id, String
12
- attribute :signature, String
13
12
  attribute :status, Integer
14
13
  attribute :tid, String
15
14
 
16
- def sign_with(secret)
17
- self.signature = StraightServerKit.sign(content: keychain_id.to_s, secret: secret)
18
- end
19
-
20
15
  def pay_path
21
16
  "/pay/#{payment_id}" if payment_id
22
17
  end
@@ -30,7 +25,6 @@ module StraightServerKit
30
25
  property :amount
31
26
  property :callback_data
32
27
  property :keychain_id
33
- property :signature
34
28
  end
35
29
  scoped :created, :found do
36
30
  property :address
@@ -5,27 +5,43 @@ module StraightServerKit
5
5
  raise ApiError.new(status: response.status, message: response.body)
6
6
  end
7
7
 
8
- resources do
9
- action :create do
10
- verb :post
11
- path '/gateways/:gateway_id/orders'
12
- body do |order|
13
- Order::Mapping.representation_for(:create, order)
14
- end
15
- handler 200 do |response|
16
- Order::Mapping.extract_single(response.body, :created)
17
- end
18
- handler &API_ERROR_HANDLER
19
- end
8
+ def self.for_gateway(gateway_id)
9
+ name = "OrderResource_#{gateway_id.to_s.to_sym.object_id}"
10
+ return StraightServerKit.const_get(name) if StraightServerKit.const_defined?(name)
11
+ klass = Class.new self do
12
+ resources do
13
+ action :create do
14
+ verb :post
15
+ path "/gateways/#{gateway_id}/orders"
16
+ body do |order|
17
+ Order::Mapping.representation_for(:create, order)
18
+ end
19
+ handler 200 do |response|
20
+ Order::Mapping.extract_single(response.body, :created)
21
+ end
22
+ handler &API_ERROR_HANDLER
23
+ end
24
+
25
+ action :find do
26
+ verb :get
27
+ path "/gateways/#{gateway_id}/orders/:id"
28
+ handler 200 do |response|
29
+ Order::Mapping.extract_single(response.body, :found)
30
+ end
31
+ handler &API_ERROR_HANDLER
32
+ end
20
33
 
21
- action :find do
22
- verb :get
23
- path '/gateways/:gateway_id/orders/:id'
24
- handler 200 do |response|
25
- Order::Mapping.extract_single(response.body, :found)
34
+ action :cancel do
35
+ verb :post
36
+ path "/gateways/#{gateway_id}/orders/:id/cancel"
37
+ handler 200 do
38
+ true
39
+ end
40
+ handler &API_ERROR_HANDLER
41
+ end
26
42
  end
27
- handler &API_ERROR_HANDLER
28
43
  end
44
+ StraightServerKit.const_set name, klass
29
45
  end
30
46
  end
31
47
  end
@@ -1,3 +1,3 @@
1
1
  module StraightServerKit
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -10,10 +10,17 @@ namespace :doc do
10
10
  next
11
11
  end
12
12
 
13
- puts "## #{klass.name.demodulize.underscore.humanize}"
13
+ if klass == StraightServerKit::OrderResource
14
+ klass = klass.for_gateway(1)
15
+ klass_name = 'StraightServerKit::OrderResource'
16
+ else
17
+ klass_name = klass.name
18
+ end
19
+
20
+ puts "## #{klass_name.demodulize.underscore.humanize}"
14
21
  puts
15
- puts " client = StraightServerKit::Client.new"
16
- puts " client.#{key} #=> #{klass.name}"
22
+ puts " client = StraightServerKit::Client.new(gateway_id: 1, secret: 'secret')"
23
+ puts " client.#{key} #=> #{klass_name}"
17
24
  puts
18
25
  puts "Actions supported: "
19
26
  puts
@@ -22,7 +29,7 @@ namespace :doc do
22
29
  params = []
23
30
 
24
31
  if action.body && action.body.arity > 0
25
- params << klass.name.demodulize.underscore.downcase.gsub('_resource', '')
32
+ params << klass_name.demodulize.underscore.downcase.gsub('_resource', '')
26
33
  end
27
34
 
28
35
  if action_options.any?
@@ -0,0 +1,42 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders/9eff7da15d0fb91ac5bd690fb2a5f7b465aa7fdfbe747028dd1579c8a9b36dba/cancel
6
+ body:
7
+ encoding: UTF-8
8
+ string: ''
9
+ headers:
10
+ Content-Type:
11
+ - application/json
12
+ User-Agent:
13
+ - Faraday v0.9.1
14
+ X-Nonce:
15
+ - '1435134015939447357440'
16
+ X-Signature:
17
+ - 7AMxBVTiH9e2GF0mWnIwHai8Pg+d5W3wlNc+GOmiIAZ4EazaWSo3T9Kzi1389Zfy8BjVP0Iy/h/WBO7GwcMaDQ==
18
+ Content-Length:
19
+ - '0'
20
+ Accept-Encoding:
21
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
22
+ Accept:
23
+ - "*/*"
24
+ response:
25
+ status:
26
+ code: 200
27
+ message: OK
28
+ headers:
29
+ Server:
30
+ - nginx/1.9.1
31
+ Date:
32
+ - Wed, 24 Jun 2015 08:20:16 GMT
33
+ Content-Length:
34
+ - '0'
35
+ Connection:
36
+ - keep-alive
37
+ body:
38
+ encoding: UTF-8
39
+ string: ''
40
+ http_version:
41
+ recorded_at: Wed, 24 Jun 2015 08:20:16 GMT
42
+ recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: get
5
- uri: http://gear.loc/gateways/c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb/orders/15
5
+ uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders/5
6
6
  body:
7
7
  encoding: US-ASCII
8
8
  string: ''
@@ -11,6 +11,10 @@ http_interactions:
11
11
  - application/json
12
12
  User-Agent:
13
13
  - Faraday v0.9.1
14
+ X-Nonce:
15
+ - '1435134015332155129856'
16
+ X-Signature:
17
+ - ayhOtW3Si64mB5FMtnK4o6NTPqFIq/FeIQYbiv7s15b6EwSs+1GdqZoKDkaAFLbNyPcxHfyUcnQa7qSc/IMGlw==
14
18
  Accept-Encoding:
15
19
  - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
20
  Accept:
@@ -23,14 +27,14 @@ http_interactions:
23
27
  Server:
24
28
  - nginx/1.9.1
25
29
  Date:
26
- - Wed, 10 Jun 2015 13:13:44 GMT
30
+ - Wed, 24 Jun 2015 08:20:15 GMT
27
31
  Content-Length:
28
- - '238'
32
+ - '264'
29
33
  Connection:
30
34
  - keep-alive
31
35
  body:
32
36
  encoding: UTF-8
33
- string: '{"status":5,"amount":4382,"address":"1EvNEJtVFuoGdGRMSKsDALxaZy5q66B2qq","tid":null,"id":15,"payment_id":"5d010bd6d45ec67ccd8d3c63dfdf038bd6310f89ed2b657d42b1831e551bc2fe","amount_in_btc":"0.00004382","keychain_id":1,"last_keychain_id":1}'
37
+ string: '{"status":0,"amount":398740,"address":"1Q8gGSuqyQk2rZeLKiPJz2nrSieTn3VrTy","tid":null,"id":5,"payment_id":"9eff7da15d0fb91ac5bd690fb2a5f7b465aa7fdfbe747028dd1579c8a9b36dba","amount_in_btc":"0.0039874","amount_paid_in_btc":"0.","keychain_id":1,"last_keychain_id":1}'
34
38
  http_version:
35
- recorded_at: Wed, 10 Jun 2015 13:13:44 GMT
39
+ recorded_at: Wed, 24 Jun 2015 08:20:15 GMT
36
40
  recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: get
5
- uri: http://gear.loc/gateways/c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb/orders/5d010bd6d45ec67ccd8d3c63dfdf038bd6310f89ed2b657d42b1831e551bc2fe
5
+ uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders/9eff7da15d0fb91ac5bd690fb2a5f7b465aa7fdfbe747028dd1579c8a9b36dba
6
6
  body:
7
7
  encoding: US-ASCII
8
8
  string: ''
@@ -11,6 +11,10 @@ http_interactions:
11
11
  - application/json
12
12
  User-Agent:
13
13
  - Faraday v0.9.1
14
+ X-Nonce:
15
+ - '1435134015612564013056'
16
+ X-Signature:
17
+ - yhP5sDe/d+QDzsEEmLhpHgxXhQb/o1hjlTqI59oQZ2V/Yf3slCjXIkbtmk/SShPXJ8W2b2bR3tzl4nNYZ1oNDw==
14
18
  Accept-Encoding:
15
19
  - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
20
  Accept:
@@ -23,14 +27,14 @@ http_interactions:
23
27
  Server:
24
28
  - nginx/1.9.1
25
29
  Date:
26
- - Wed, 10 Jun 2015 13:13:44 GMT
30
+ - Wed, 24 Jun 2015 08:20:15 GMT
27
31
  Content-Length:
28
- - '238'
32
+ - '264'
29
33
  Connection:
30
34
  - keep-alive
31
35
  body:
32
36
  encoding: UTF-8
33
- string: '{"status":5,"amount":4382,"address":"1EvNEJtVFuoGdGRMSKsDALxaZy5q66B2qq","tid":null,"id":15,"payment_id":"5d010bd6d45ec67ccd8d3c63dfdf038bd6310f89ed2b657d42b1831e551bc2fe","amount_in_btc":"0.00004382","keychain_id":1,"last_keychain_id":1}'
37
+ string: '{"status":0,"amount":398740,"address":"1Q8gGSuqyQk2rZeLKiPJz2nrSieTn3VrTy","tid":null,"id":5,"payment_id":"9eff7da15d0fb91ac5bd690fb2a5f7b465aa7fdfbe747028dd1579c8a9b36dba","amount_in_btc":"0.0039874","amount_paid_in_btc":"0.","keychain_id":1,"last_keychain_id":1}'
34
38
  http_version:
35
- recorded_at: Wed, 10 Jun 2015 13:13:44 GMT
39
+ recorded_at: Wed, 24 Jun 2015 08:20:15 GMT
36
40
  recorded_with: VCR 2.9.3
@@ -2,7 +2,7 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: get
5
- uri: http://gear.loc/gateways/c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb/orders/meah
5
+ uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders/meah
6
6
  body:
7
7
  encoding: US-ASCII
8
8
  string: ''
@@ -11,6 +11,10 @@ http_interactions:
11
11
  - application/json
12
12
  User-Agent:
13
13
  - Faraday v0.9.1
14
+ X-Nonce:
15
+ - '1435134015890302697472'
16
+ X-Signature:
17
+ - b42hKPlUp5/+IjnqBVX+BOGQ1Kbl6QlqJkqUCwZYyx7LuFMxg9TrxcnizXJckoZBdX9LEySgJ1BWxCYFU4pOhw==
14
18
  Accept-Encoding:
15
19
  - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
20
  Accept:
@@ -23,15 +27,15 @@ http_interactions:
23
27
  Server:
24
28
  - nginx/1.9.1
25
29
  Date:
26
- - Wed, 10 Jun 2015 13:37:14 GMT
30
+ - Wed, 24 Jun 2015 08:20:15 GMT
27
31
  Content-Length:
28
32
  - '100'
29
33
  Connection:
30
34
  - keep-alive
31
35
  body:
32
36
  encoding: UTF-8
33
- string: GET /gateways/c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb/orders/meah
37
+ string: GET /gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders/meah
34
38
  Not found
35
39
  http_version:
36
- recorded_at: Wed, 10 Jun 2015 13:37:14 GMT
40
+ recorded_at: Wed, 24 Jun 2015 08:20:15 GMT
37
41
  recorded_with: VCR 2.9.3
@@ -2,15 +2,19 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: http://gear.loc/gateways/c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb/orders
5
+ uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders
6
6
  body:
7
7
  encoding: UTF-8
8
- string: '{"amount":"0.1E-1","callback_data":"123","keychain_id":1,"signature":"1d295e79be14197cea096afbcd898267aebaa93d6e6973227132ff35d5f64147"}'
8
+ string: '{"amount":"0.1E1","callback_data":"123","keychain_id":1}'
9
9
  headers:
10
10
  Content-Type:
11
11
  - application/json
12
12
  User-Agent:
13
13
  - Faraday v0.9.1
14
+ X-Nonce:
15
+ - '1435134015216702717952'
16
+ X-Signature:
17
+ - 5R+Xy+1GCQckZDiqThmqDbSOQJhkMT7DTDZaw+m4IsC4YafSNbb1il9Hv/rvgXZtY9Rj06l3iCzJUB62PIZJNA==
14
18
  Accept-Encoding:
15
19
  - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
20
  Accept:
@@ -23,14 +27,14 @@ http_interactions:
23
27
  Server:
24
28
  - nginx/1.9.1
25
29
  Date:
26
- - Wed, 10 Jun 2015 11:54:27 GMT
30
+ - Wed, 24 Jun 2015 08:20:15 GMT
27
31
  Content-Length:
28
- - '238'
32
+ - '264'
29
33
  Connection:
30
34
  - keep-alive
31
35
  body:
32
36
  encoding: UTF-8
33
- string: '{"status":0,"amount":4382,"address":"1EvNEJtVFuoGdGRMSKsDALxaZy5q66B2qq","tid":null,"id":15,"payment_id":"5d010bd6d45ec67ccd8d3c63dfdf038bd6310f89ed2b657d42b1831e551bc2fe","amount_in_btc":"0.00004382","keychain_id":1,"last_keychain_id":1}'
37
+ string: '{"status":0,"amount":398740,"address":"1Q8gGSuqyQk2rZeLKiPJz2nrSieTn3VrTy","tid":null,"id":5,"payment_id":"9eff7da15d0fb91ac5bd690fb2a5f7b465aa7fdfbe747028dd1579c8a9b36dba","amount_in_btc":"0.0039874","amount_paid_in_btc":"0.","keychain_id":1,"last_keychain_id":1}'
34
38
  http_version:
35
- recorded_at: Wed, 10 Jun 2015 11:54:27 GMT
39
+ recorded_at: Wed, 24 Jun 2015 08:20:15 GMT
36
40
  recorded_with: VCR 2.9.3
@@ -2,15 +2,19 @@
2
2
  http_interactions:
3
3
  - request:
4
4
  method: post
5
- uri: http://gear.loc/gateways/c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb/orders
5
+ uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders
6
6
  body:
7
7
  encoding: UTF-8
8
- string: '{"amount":"0.1E-1","callback_data":"123","keychain_id":1,"signature":null}'
8
+ string: '{"amount":null,"callback_data":"123","keychain_id":1}'
9
9
  headers:
10
10
  Content-Type:
11
11
  - application/json
12
12
  User-Agent:
13
13
  - Faraday v0.9.1
14
+ X-Nonce:
15
+ - '1435134015292253143040'
16
+ X-Signature:
17
+ - 38R+VK1z2/HZzusiR0L9850nvIACu5grh3HpNiExW+2BJ3toe33r4YilV4X2jGN1RCWWv6h/rQZlu2FgEuoG4Q==
14
18
  Accept-Encoding:
15
19
  - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
16
20
  Accept:
@@ -23,14 +27,14 @@ http_interactions:
23
27
  Server:
24
28
  - nginx/1.9.1
25
29
  Date:
26
- - Wed, 10 Jun 2015 13:01:45 GMT
30
+ - Wed, 24 Jun 2015 08:20:15 GMT
27
31
  Content-Length:
28
- - '26'
32
+ - '61'
29
33
  Connection:
30
34
  - keep-alive
31
35
  body:
32
36
  encoding: UTF-8
33
- string: 'Invalid signature for id: '
37
+ string: 'Invalid order: amount cannot be nil and should be more than 0'
34
38
  http_version:
35
- recorded_at: Wed, 10 Jun 2015 13:01:45 GMT
39
+ recorded_at: Wed, 24 Jun 2015 08:20:15 GMT
36
40
  recorded_with: VCR 2.9.3
@@ -1,17 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe StraightServerKit::Client do
4
- subject(:client) { StraightServerKit::Client.new }
4
+
5
+ let(:default_params) { {gateway_id: 1, secret: '0'} }
6
+ subject(:client) { described_class.new(**default_params) }
7
+
8
+ it "must be initialized with gateway_id and secret" do
9
+ expect { StraightServerKit::Client.new }.to raise_error ArgumentError
10
+ expect { StraightServerKit::Client.new(gateway_id: 1) }.to raise_error ArgumentError
11
+ expect(subject.gateway_id).to eq 1
12
+ expect(subject.secret).to eq '0'
13
+ end
5
14
 
6
15
  it "can be initializes with an url" do
7
- @client = StraightServerKit::Client.new(url: 'http://gear.loc')
16
+ @client = StraightServerKit::Client.new(url: 'http://gear.loc', **default_params)
8
17
  expect(@client.url).to eq 'http://gear.loc'
9
18
  end
10
19
 
11
20
  it "constructs pay url" do
12
21
  @order = StraightServerKit::Order.new(payment_id: 'abc')
13
- expect(described_class.new.pay_url(@order)).to eq 'http://localhost:9000/pay/abc'
14
- expect(described_class.new(url: 'https://gear.loc').pay_url(@order)).to eq 'https://gear.loc/pay/abc'
22
+ expect(subject.pay_url(@order)).to eq 'http://localhost:9000/pay/abc'
23
+ expect(described_class.new(url: 'https://gear.loc', **default_params).pay_url(@order)).to eq 'https://gear.loc/pay/abc'
15
24
  end
16
25
 
17
26
  it "does respond to valid resources" do
@@ -2,73 +2,84 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe StraightServerKit::OrderResource do
4
4
  include_context 'resources'
5
- subject(:resource) { described_class.new(connection: connection) }
5
+
6
+ it "builds subclass for each gateway" do
7
+ resources = 3.times.map do |i|
8
+ resource = StraightServerKit::Client.new(gateway_id: i, secret: nil).orders
9
+ expect(resource.class.name).to eq "StraightServerKit::OrderResource_#{i.to_s.to_sym.object_id}"
10
+ resource
11
+ end
12
+ resources2 = 3.times.map do |i|
13
+ StraightServerKit::Client.new(gateway_id: i, secret: nil).orders
14
+ end
15
+ expect(resources.map(&:class)).to eq resources2.map(&:class)
16
+ end
6
17
 
7
18
  describe '#create' do
8
19
  it 'creates order' do
9
- @order = StraightServerKit::Order.new(amount: 0.01, callback_data: '123', keychain_id: 1)
10
- @order.sign_with gateway_secret
20
+ @order = StraightServerKit::Order.new(amount: 1, callback_data: '123', keychain_id: 1)
11
21
 
12
- expect(@order.amount).to eq 0.01
22
+ expect(@order.amount).to eq 1
13
23
  expect(@order.amount).to be_kind_of BigDecimal
14
24
  expect(@order.callback_data).to eq '123'
15
25
  expect(@order.keychain_id).to eq 1
16
- expect(@order.signature).to eq '1d295e79be14197cea096afbcd898267aebaa93d6e6973227132ff35d5f64147'
17
26
 
18
27
  VCR.use_cassette 'orders_create' do
19
- @created_order = client.orders.create(@order, gateway_id: gateway_id)
28
+ @created_order = client.orders.create(@order)
20
29
  end
21
30
 
22
- expect(@created_order.address).to eq '1EvNEJtVFuoGdGRMSKsDALxaZy5q66B2qq'
23
- expect(@created_order.amount).to eq 4382
31
+ expect(@created_order.address.to_s).not_to be_empty
32
+ expect(@created_order.amount > 0).to eq true
24
33
  expect(@created_order.amount).to be_kind_of BigDecimal
25
- expect(@created_order.amount_in_btc).to eq 0.00004382
34
+ expect(@created_order.amount_in_btc > 0).to eq true
26
35
  expect(@created_order.amount_in_btc).to be_kind_of BigDecimal
27
- expect(@created_order.id).to eq 15
28
- expect(@created_order.keychain_id).to eq 1
29
- expect(@created_order.last_keychain_id).to eq 1
30
- expect(@created_order.payment_id).to eq '5d010bd6d45ec67ccd8d3c63dfdf038bd6310f89ed2b657d42b1831e551bc2fe'
36
+ expect(@created_order.id > 0).to eq true
37
+ expect(@created_order.keychain_id > 0).to eq true
38
+ expect(@created_order.last_keychain_id > 0).to eq true
39
+ expect(@created_order.payment_id.to_s).not_to be_empty
31
40
  expect(@created_order.status).to eq 0
32
41
  expect(@created_order.tid).to eq nil
33
42
 
34
43
  # orders.create never sets these fields
35
44
  expect(@created_order.callback_data).to eq nil
36
- expect(@created_order.signature).to eq nil
45
+
46
+ $order_id = @created_order.id
47
+ $payment_id = @created_order.payment_id
37
48
  end
38
49
 
39
50
  it 'raises ApiError' do
40
- @order = StraightServerKit::Order.new(amount: 0.01, callback_data: '123', keychain_id: 1)
41
- VCR.use_cassette 'orders_create_unsigned' do
51
+ @order = StraightServerKit::Order.new(callback_data: '123', keychain_id: 1)
52
+ VCR.use_cassette 'orders_create_invalid' do
42
53
  begin
43
- client.orders.create(@order, gateway_id: gateway_id)
54
+ client.orders.create(@order)
44
55
  rescue => @error
45
56
  end
46
57
  end
47
58
  expect(@error).to be_instance_of StraightServerKit::ApiError
48
59
  expect(@error.status).to eq 409
49
- expect(@error.message).to start_with "Invalid signature"
60
+ expect(@error.message).to eq "Invalid order: amount cannot be nil and should be more than 0"
50
61
  end
51
62
  end
52
63
 
53
64
  describe '#find' do
54
65
  it 'finds existing order by id' do
55
66
  VCR.use_cassette 'find_order_by_id' do
56
- @order = client.orders.find(id: 15, gateway_id: gateway_id)
67
+ @order = client.orders.find(id: $order_id)
57
68
  end
58
- expect(@order.id).to eq 15
69
+ expect(@order.id).to eq $order_id
59
70
  end
60
71
 
61
72
  it 'finds existing order by payment_id' do
62
73
  VCR.use_cassette 'find_order_by_payment_id' do
63
- @order = client.orders.find(id: '5d010bd6d45ec67ccd8d3c63dfdf038bd6310f89ed2b657d42b1831e551bc2fe', gateway_id: gateway_id)
74
+ @order = client.orders.find(id: $payment_id)
64
75
  end
65
- expect(@order.id).to eq 15
76
+ expect(@order.id).to eq $order_id
66
77
  end
67
78
 
68
79
  it 'raises ApiError when not found' do
69
80
  VCR.use_cassette 'find_order_fails' do
70
81
  begin
71
- @order = client.orders.find(id: 'meah', gateway_id: gateway_id)
82
+ @order = client.orders.find(id: 'meah')
72
83
  rescue => @error
73
84
  end
74
85
  end
@@ -77,4 +88,13 @@ RSpec.describe StraightServerKit::OrderResource do
77
88
  expect(@error.message).to end_with "Not found"
78
89
  end
79
90
  end
91
+
92
+ describe '#cancel' do
93
+ it "cancels new order" do
94
+ VCR.use_cassette 'cancel_new_order' do
95
+ @result = client.orders.cancel(id: $payment_id)
96
+ end
97
+ expect(@result).to eq true
98
+ end
99
+ end
80
100
  end
@@ -1,12 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe StraightServerKit do
4
- it "validates callback signature" do
5
- secret = 'secret'
6
- signature = described_class.sign(content: 1, secret: secret)
7
- expect(described_class.valid_callback?({}, secret)).to eq false
8
- expect(described_class.valid_callback?({signature: 'asdf'}, secret)).to eq false
9
- expect(described_class.valid_callback?({order_id: 1}, secret)).to eq false
10
- expect(described_class.valid_callback?({order_id: 1, signature: signature}, secret)).to eq true
4
+ it "validates signature" do
5
+ secret = 'secret'
6
+ request_uri = '/callback/path?order_id=1&callback_data=test'
7
+ signature = described_class.signature(nonce: nil, body: nil, method: 'GET', request_uri: request_uri, secret: secret)
8
+ expect(described_class.valid_callback?(signature: nil, request_uri: request_uri, secret: nil)).to eq false
9
+ expect(described_class.valid_callback?(signature: nil, request_uri: request_uri, secret: secret)).to eq false
10
+ expect(described_class.valid_callback?(signature: signature, request_uri: request_uri, secret: nil)).to eq false
11
+ expect(described_class.valid_callback?(signature: signature, request_uri: request_uri, secret: secret)).to eq true
12
+ expect(described_class.valid_signature?(signature: signature, request_uri: request_uri, secret: secret, nonce: nil, body: nil, method: 'GET')).to eq true
11
13
  end
12
14
  end
@@ -1,6 +1,5 @@
1
1
  shared_context 'resources' do
2
- let(:client) { StraightServerKit::Client.new(url: 'http://gear.loc') }
3
- let(:connection) { client.connection }
4
- let(:gateway_id) { 'c2809c9fd3465529d2946fb8299450b4f46b24fc40f0e3a641e7e19cd75a3adb' }
5
- let(:gateway_secret) { 'w4b1lc5qs3n0vx9q8q76yxparfcmto1dqlr6vo5hh7mfvaoz64epa4e7qhvmv4vg' }
2
+ let(:gateway_id) { 'a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5' }
3
+ let(:gateway_secret) { 'qx1r05e9i38q3g0lnknwaiwjeaufquw4wsmtra2nj5jqyl9m2jlx27jhclmm2mzp' }
4
+ let(:client) { StraightServerKit::Client.new(url: 'http://gear.loc', gateway_id: gateway_id, secret: gateway_secret) }
6
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: straight-server-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Pavlenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-11 00:00:00.000000000 Z
11
+ date: 2015-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -159,11 +159,12 @@ files:
159
159
  - lib/straight-server-kit/resources/order_resource.rb
160
160
  - lib/straight-server-kit/version.rb
161
161
  - lib/tasks/resource_doc.rake
162
+ - spec/fixtures/vcr/cancel_new_order.yml
162
163
  - spec/fixtures/vcr/find_order_by_id.yml
163
164
  - spec/fixtures/vcr/find_order_by_payment_id.yml
164
165
  - spec/fixtures/vcr/find_order_fails.yml
165
166
  - spec/fixtures/vcr/orders_create.yml
166
- - spec/fixtures/vcr/orders_create_unsigned.yml
167
+ - spec/fixtures/vcr/orders_create_invalid.yml
167
168
  - spec/lib/straight-server-kit/client_spec.rb
168
169
  - spec/lib/straight-server-kit/models/base_model_spec.rb
169
170
  - spec/lib/straight-server-kit/models/order_spec.rb
@@ -192,16 +193,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
193
  version: '0'
193
194
  requirements: []
194
195
  rubyforge_project:
195
- rubygems_version: 2.4.6
196
+ rubygems_version: 2.4.8
196
197
  signing_key:
197
198
  specification_version: 4
198
199
  summary: Straight Server Kit is the official Ruby library for Straight Server's API
199
200
  test_files:
201
+ - spec/fixtures/vcr/cancel_new_order.yml
200
202
  - spec/fixtures/vcr/find_order_by_id.yml
201
203
  - spec/fixtures/vcr/find_order_by_payment_id.yml
202
204
  - spec/fixtures/vcr/find_order_fails.yml
203
205
  - spec/fixtures/vcr/orders_create.yml
204
- - spec/fixtures/vcr/orders_create_unsigned.yml
206
+ - spec/fixtures/vcr/orders_create_invalid.yml
205
207
  - spec/lib/straight-server-kit/client_spec.rb
206
208
  - spec/lib/straight-server-kit/models/base_model_spec.rb
207
209
  - spec/lib/straight-server-kit/models/order_spec.rb