straight-server-kit 0.1.0 → 0.2.0

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