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 +4 -4
- data/README.md +10 -9
- data/lib/straight-server-kit.rb +14 -10
- data/lib/straight-server-kit/client.rb +35 -9
- data/lib/straight-server-kit/models/order.rb +0 -6
- data/lib/straight-server-kit/resources/order_resource.rb +34 -18
- data/lib/straight-server-kit/version.rb +1 -1
- data/lib/tasks/resource_doc.rake +11 -4
- data/spec/fixtures/vcr/cancel_new_order.yml +42 -0
- data/spec/fixtures/vcr/find_order_by_id.yml +9 -5
- data/spec/fixtures/vcr/find_order_by_payment_id.yml +9 -5
- data/spec/fixtures/vcr/find_order_fails.yml +8 -4
- data/spec/fixtures/vcr/orders_create.yml +10 -6
- data/spec/fixtures/vcr/{orders_create_unsigned.yml → orders_create_invalid.yml} +10 -6
- data/spec/lib/straight-server-kit/client_spec.rb +13 -4
- data/spec/lib/straight-server-kit/resources/order_resource_spec.rb +43 -23
- data/spec/lib/straight-server-kit_spec.rb +9 -7
- data/spec/support/resource_context.rb +3 -4
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42c92cfbb55d2a9c63a48f6ba070178f21094291
|
4
|
+
data.tar.gz: 8d73b5ceb43e1744ecdf96b38beed1c328030539
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
35
|
-
* `client.orders.find(
|
34
|
+
* `client.orders.create(order)`
|
35
|
+
* `client.orders.find(id: 'id')`
|
36
|
+
* `client.orders.cancel(id: 'id')`
|
36
37
|
|
37
|
-
### Order
|
38
|
+
### Order creation
|
38
39
|
|
39
40
|
order = StraightServerKit::Order.new(amount: 0.01, callback_data: '123', keychain_id: 1)
|
40
|
-
order
|
41
|
+
client.orders.create(order)
|
41
42
|
|
42
43
|
### Callback validation
|
43
44
|
|
44
|
-
if StraightServerKit.valid_callback?(
|
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
|
|
data/lib/straight-server-kit.rb
CHANGED
@@ -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
|
-
|
17
|
-
|
18
|
-
|
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.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
@
|
12
|
-
@
|
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)
|
21
|
-
|
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.
|
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
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
data/lib/tasks/resource_doc.rake
CHANGED
@@ -10,10 +10,17 @@ namespace :doc do
|
|
10
10
|
next
|
11
11
|
end
|
12
12
|
|
13
|
-
|
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} #=> #{
|
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 <<
|
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/
|
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,
|
30
|
+
- Wed, 24 Jun 2015 08:20:15 GMT
|
27
31
|
Content-Length:
|
28
|
-
- '
|
32
|
+
- '264'
|
29
33
|
Connection:
|
30
34
|
- keep-alive
|
31
35
|
body:
|
32
36
|
encoding: UTF-8
|
33
|
-
string: '{"status":
|
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,
|
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/
|
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,
|
30
|
+
- Wed, 24 Jun 2015 08:20:15 GMT
|
27
31
|
Content-Length:
|
28
|
-
- '
|
32
|
+
- '264'
|
29
33
|
Connection:
|
30
34
|
- keep-alive
|
31
35
|
body:
|
32
36
|
encoding: UTF-8
|
33
|
-
string: '{"status":
|
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,
|
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/
|
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,
|
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/
|
37
|
+
string: GET /gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders/meah
|
34
38
|
Not found
|
35
39
|
http_version:
|
36
|
-
recorded_at: Wed,
|
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/
|
5
|
+
uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"amount":"0.
|
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,
|
30
|
+
- Wed, 24 Jun 2015 08:20:15 GMT
|
27
31
|
Content-Length:
|
28
|
-
- '
|
32
|
+
- '264'
|
29
33
|
Connection:
|
30
34
|
- keep-alive
|
31
35
|
body:
|
32
36
|
encoding: UTF-8
|
33
|
-
string: '{"status":0,"amount":
|
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,
|
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/
|
5
|
+
uri: http://gear.loc/gateways/a55c73f90728ea2750c0d92151e14f960a4cee1e3bca0cf2da8312573a98a8c5/orders
|
6
6
|
body:
|
7
7
|
encoding: UTF-8
|
8
|
-
string: '{"amount":
|
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,
|
30
|
+
- Wed, 24 Jun 2015 08:20:15 GMT
|
27
31
|
Content-Length:
|
28
|
-
- '
|
32
|
+
- '61'
|
29
33
|
Connection:
|
30
34
|
- keep-alive
|
31
35
|
body:
|
32
36
|
encoding: UTF-8
|
33
|
-
string: 'Invalid
|
37
|
+
string: 'Invalid order: amount cannot be nil and should be more than 0'
|
34
38
|
http_version:
|
35
|
-
recorded_at: Wed,
|
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
|
-
|
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(
|
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
|
-
|
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:
|
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
|
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
|
28
|
+
@created_order = client.orders.create(@order)
|
20
29
|
end
|
21
30
|
|
22
|
-
expect(@created_order.address).
|
23
|
-
expect(@created_order.amount).to eq
|
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
|
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
|
28
|
-
expect(@created_order.keychain_id).to eq
|
29
|
-
expect(@created_order.last_keychain_id).to eq
|
30
|
-
expect(@created_order.payment_id).
|
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
|
-
|
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(
|
41
|
-
VCR.use_cassette '
|
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
|
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
|
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:
|
67
|
+
@order = client.orders.find(id: $order_id)
|
57
68
|
end
|
58
|
-
expect(@order.id).to eq
|
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:
|
74
|
+
@order = client.orders.find(id: $payment_id)
|
64
75
|
end
|
65
|
-
expect(@order.id).to eq
|
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'
|
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
|
5
|
-
secret
|
6
|
-
|
7
|
-
|
8
|
-
expect(described_class.valid_callback?(
|
9
|
-
expect(described_class.valid_callback?(
|
10
|
-
expect(described_class.valid_callback?(
|
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(:
|
3
|
-
let(:
|
4
|
-
let(:
|
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.
|
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-
|
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/
|
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.
|
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/
|
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
|