pagaris 1.0.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 +7 -0
- data/.gitignore +42 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +55 -0
- data/LICENSE +21 -0
- data/README.md +128 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/pagaris.rb +12 -0
- data/lib/pagaris/client.rb +116 -0
- data/lib/pagaris/errors.rb +6 -0
- data/lib/pagaris/errors/http_base_error.rb +15 -0
- data/lib/pagaris/errors/not_found_error.rb +5 -0
- data/lib/pagaris/errors/server_error.rb +5 -0
- data/lib/pagaris/errors/unauthorized_error.rb +7 -0
- data/lib/pagaris/errors/unexpected_response_error.rb +5 -0
- data/lib/pagaris/errors/unprocessable_entity_error.rb +7 -0
- data/lib/pagaris/order.rb +84 -0
- data/lib/pagaris/signature.rb +72 -0
- data/lib/pagaris/version.rb +3 -0
- data/pagaris.gemspec +39 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c15d79c8e9c30a30734d5c2198847c5fb4a0b091080347f8c3ce63d053bdf333
|
4
|
+
data.tar.gz: 648d0b4ffe8a439d9ef4aaeedfb3cd12d04080ab9ddca996390950eeedd141ac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e42c2b812331921dcffa178c879693e2f4fef65d5391cf3d434fc89310366fbd8c962f5c35dfbdd64f67d0cf3d2e60e492a15b1dabddf0a6d42770cd125a27d4
|
7
|
+
data.tar.gz: af473b870512465600d368516a2e1632692f6c35bb3ad8c29038f87aabcedf35bc046ffab0fc96a4e810cb322b71f581449ecdbba6fc7758352b5d0fb728a22f
|
data/.gitignore
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# General
|
2
|
+
.DS_Store
|
3
|
+
.AppleDouble
|
4
|
+
.LSOverride
|
5
|
+
|
6
|
+
# Icon must end with two \r
|
7
|
+
Icon
|
8
|
+
|
9
|
+
|
10
|
+
# Thumbnails
|
11
|
+
._*
|
12
|
+
|
13
|
+
# Files that might appear in the root of a volume
|
14
|
+
.DocumentRevisions-V100
|
15
|
+
.fseventsd
|
16
|
+
.Spotlight-V100
|
17
|
+
.TemporaryItems
|
18
|
+
.Trashes
|
19
|
+
.VolumeIcon.icns
|
20
|
+
.com.apple.timemachine.donotpresent
|
21
|
+
|
22
|
+
# Directories potentially created on remote AFP share
|
23
|
+
.AppleDB
|
24
|
+
.AppleDesktop
|
25
|
+
Network Trash Folder
|
26
|
+
Temporary Items
|
27
|
+
.apdisk
|
28
|
+
|
29
|
+
/.bundle/
|
30
|
+
/.yardoc
|
31
|
+
/_yardoc/
|
32
|
+
/coverage/
|
33
|
+
/doc/
|
34
|
+
/pkg/
|
35
|
+
/spec/reports/
|
36
|
+
/tmp/
|
37
|
+
|
38
|
+
|
39
|
+
.ruby-version
|
40
|
+
.ruby-gemset
|
41
|
+
|
42
|
+
.env
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pagaris (1.0.0)
|
5
|
+
httparty (~> 0.17.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
addressable (2.7.0)
|
11
|
+
public_suffix (>= 2.0.2, < 5.0)
|
12
|
+
ansi (1.5.0)
|
13
|
+
builder (3.2.3)
|
14
|
+
crack (0.4.3)
|
15
|
+
safe_yaml (~> 1.0.0)
|
16
|
+
dotenv (2.7.5)
|
17
|
+
hashdiff (1.0.1)
|
18
|
+
httparty (0.17.1)
|
19
|
+
mime-types (~> 3.0)
|
20
|
+
multi_xml (>= 0.5.2)
|
21
|
+
mime-types (3.3)
|
22
|
+
mime-types-data (~> 3.2015)
|
23
|
+
mime-types-data (3.2019.0904)
|
24
|
+
minitest (5.12.1)
|
25
|
+
minitest-reporters (1.3.8)
|
26
|
+
ansi
|
27
|
+
builder
|
28
|
+
minitest (>= 5.0)
|
29
|
+
ruby-progressbar
|
30
|
+
multi_xml (0.6.0)
|
31
|
+
public_suffix (4.0.4)
|
32
|
+
rake (13.0.1)
|
33
|
+
ruby-progressbar (1.10.1)
|
34
|
+
safe_yaml (1.0.5)
|
35
|
+
vcr (5.1.0)
|
36
|
+
webmock (3.8.3)
|
37
|
+
addressable (>= 2.3.6)
|
38
|
+
crack (>= 0.3.2)
|
39
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
40
|
+
|
41
|
+
PLATFORMS
|
42
|
+
ruby
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
bundler (~> 2.0)
|
46
|
+
dotenv (~> 2.7.5)
|
47
|
+
minitest (~> 5.0)
|
48
|
+
minitest-reporters (~> 1.3.8)
|
49
|
+
pagaris!
|
50
|
+
rake (~> 13.0)
|
51
|
+
vcr (~> 5.1.0)
|
52
|
+
webmock (~> 3.8.3)
|
53
|
+
|
54
|
+
BUNDLED WITH
|
55
|
+
2.0.2
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2019 Pagaris Fintech SAPI de CV
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# Installation
|
2
|
+
|
3
|
+
Add this line to your application's Gemfile:
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
gem 'pagaris'
|
7
|
+
```
|
8
|
+
|
9
|
+
And then execute:
|
10
|
+
|
11
|
+
$ bundle
|
12
|
+
|
13
|
+
Or install it yourself as:
|
14
|
+
|
15
|
+
$ gem install pagaris
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
#### Configuration
|
20
|
+
|
21
|
+
> Warning: Never store your credentials in plaintext. We recommend using environment variables.
|
22
|
+
|
23
|
+
> Note: The private key you use in `Pagaris#private_key=` determines the current environment for all calls (i.e. sandbox or production calls).
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
# Only if it's not already required for you (e.g. Rails)
|
27
|
+
require 'pagaris'
|
28
|
+
|
29
|
+
Pagaris.application_id = ENV['PAGARIS_APPLICATION_ID']
|
30
|
+
Pagaris.private_key = ENV['PAGARIS_PRIVATE_KEY']
|
31
|
+
```
|
32
|
+
|
33
|
+
#### Creating an Order
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# First way: `Pagaris::Order::create`
|
37
|
+
begin
|
38
|
+
order = Pagaris::Order.create(
|
39
|
+
amount: 4_999.99,
|
40
|
+
metadata: { internal_id: 192 }, # Optional
|
41
|
+
products: [{ sku: '123', quantity: 3 }], # Optional
|
42
|
+
redirect_url: 'https://some.url/for/redirect' # Optional, overrides app
|
43
|
+
)
|
44
|
+
|
45
|
+
order.id # => 'a0248c87-2f0f-4e4e-a913-893d54046321'
|
46
|
+
order.amount # => 4999.99
|
47
|
+
order.fee # => 100 (for example)
|
48
|
+
order.payout_amount # => 4899.99
|
49
|
+
order.status # => 'created'
|
50
|
+
order.metadata # => { internal_id: 192 }
|
51
|
+
order.products # => [{ sku: '123', quantity: 3 }]
|
52
|
+
order.created_at # => 2020-05-04 16:03:51 -0500 (Time)
|
53
|
+
order.updated_at # => 2020-05-04 16:03:51 -0500 (Time)
|
54
|
+
order.url # => 'https://pagaris.com/some_url_to_redirect_your_buyer_to'
|
55
|
+
rescue Exception => e
|
56
|
+
# See the 'Exceptions' section
|
57
|
+
end
|
58
|
+
|
59
|
+
# Second way: Calling `Order#create` after initializing it
|
60
|
+
order = Order.new(amount: 4_999.99)
|
61
|
+
order.redirect_url = 'http://something.com'
|
62
|
+
begin
|
63
|
+
order.create
|
64
|
+
rescue Exception => e
|
65
|
+
# See the 'Exceptions' section
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
#### Getting an Order
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
order = Order.get('caff2436-b41c-41f5-b7e9-7259d158c95a') # => <Pagaris::Order>
|
73
|
+
|
74
|
+
orders.id # => 'a0248c87-2f0f-4e4e-a913-893d54046321'
|
75
|
+
```
|
76
|
+
|
77
|
+
#### Getting all Orders
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
orders = Order.all # => [<Pagaris::Order>, <Pagaris::Order>, ...]
|
81
|
+
|
82
|
+
orders.first&.id # => 'a0248c87-2f0f-4e4e-a913-893d54046321'
|
83
|
+
```
|
84
|
+
|
85
|
+
#### Confirming an Order
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
order = Order.get('caff2436-b41c-41f5-b7e9-7259d158c95a')
|
89
|
+
order.status # => 'approved'
|
90
|
+
order.confirm
|
91
|
+
order.status # => 'confirmed'
|
92
|
+
```
|
93
|
+
|
94
|
+
#### Cancelling an Order
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
order = Order.get('dcf647cb-39f2-4ef2-a07f-555a1d5be7e3')
|
98
|
+
order.status # => 'approved'
|
99
|
+
order.cancel
|
100
|
+
order.status # => 'cancelled'
|
101
|
+
```
|
102
|
+
|
103
|
+
#### Exceptions
|
104
|
+
|
105
|
+
Any of the previous operations can raise one of the following exceptions. You can call `#response` on them to inspect what caused the error
|
106
|
+
|
107
|
+
- `Pagaris::Errors::UnauthorizedError` - Credentials were not configured correctly or the request is impossible (e.g. trying to confirm an Order which can't be confirmed)
|
108
|
+
- `Pagaris::Errors::NotFoundError` - When fetching or trying to update an Order with an incorrect `id` (note the environment in which they were created)
|
109
|
+
- `Pagaris::Errors::UnprocessableEntityError` - When the parameters are invalid (e.g. creating an Order without an amount, or with an amount less than the minimum amount or greater than the maximum amount).
|
110
|
+
- `Pagaris::Errors::UnexpectedResponseError`
|
111
|
+
- `Pagaris::Errors::ServerError`
|
112
|
+
|
113
|
+
###### Example of handling exceptions
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
begin
|
117
|
+
order = Order.create(amount: 100)
|
118
|
+
rescue Pagaris::Errors::UnprocessableEntityError => e
|
119
|
+
e.response # => HTTParty::Response
|
120
|
+
e.response&.body # => {"error":{"status":422,"detail":"Some detail"}}
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
## Development
|
125
|
+
|
126
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
127
|
+
|
128
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "pagaris"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/lib/pagaris.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Pagaris
|
5
|
+
##
|
6
|
+
# In charge of the HTTP calls to the API
|
7
|
+
##
|
8
|
+
class Client
|
9
|
+
DOMAIN = ENV.fetch('PAGARIS_DOMAIN', 'https://pagaris.com')
|
10
|
+
API_PREFIX = '/api/v1/'
|
11
|
+
BASE_URL = DOMAIN + API_PREFIX
|
12
|
+
|
13
|
+
##
|
14
|
+
# Makes a GET HTTP request to the given `path`
|
15
|
+
#
|
16
|
+
# @param path [String] path that goes after the base url
|
17
|
+
#
|
18
|
+
# @raise [Error::HttpBaseError] Any of the subclasses of `HttpBaseError`,
|
19
|
+
# depending on the response status code
|
20
|
+
#
|
21
|
+
# @return [Hash] Response body as a Hash with symbolized names
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# Client.get('orders') # => { orders: [{ id: '1234', amount: 1234.56}] }
|
25
|
+
# Client.get('orders/1234') # => { id: '1234', amount: 1234.56 }
|
26
|
+
##
|
27
|
+
def self.get(path)
|
28
|
+
response = HTTParty.get(BASE_URL + path, request_options(path, 'GET'))
|
29
|
+
throw_error(response) unless [200, 201].include?(response.code)
|
30
|
+
JSON.parse(response.body, symbolize_names: true)
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Makes a POST HTTP request to the given `path`, with the given `body`
|
35
|
+
#
|
36
|
+
# @param path [String] path that goes after the base url
|
37
|
+
# @param body [Hash] Body to send on the request. Will be converted to JSON
|
38
|
+
# directly in this class.
|
39
|
+
#
|
40
|
+
# @raise [Error::HttpBaseError] Any of the subclasses of `HttpBaseError`,
|
41
|
+
# depending on the response status code
|
42
|
+
#
|
43
|
+
# @return [Hash] Response body as a Hash with symbolized names
|
44
|
+
#
|
45
|
+
# @example
|
46
|
+
# Client.post('orders', { amount: 5432.10 })
|
47
|
+
# # => { id: '4321', amount: 5432.10 }
|
48
|
+
##
|
49
|
+
def self.post(path, body = nil)
|
50
|
+
response = HTTParty.post(
|
51
|
+
BASE_URL + path,
|
52
|
+
request_options(path, 'POST', body)
|
53
|
+
)
|
54
|
+
throw_error(response) unless [200, 201].include?(response.code)
|
55
|
+
JSON.parse(response.body, symbolize_names: true)
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Makes a PUT HTTP request to the given `path`, with the given `body`
|
60
|
+
#
|
61
|
+
# @param path [String] path that goes after the base url
|
62
|
+
# @param body [Hash] Body to send on the request. Will be converted to JSON
|
63
|
+
# directly in this class.
|
64
|
+
#
|
65
|
+
# @raise [Error::HttpBaseError] Any of the subclasses of `HttpBaseError`,
|
66
|
+
# depending on the response status code
|
67
|
+
#
|
68
|
+
# @return [Hash] Response body as a Hash with symbolized names
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# Client.put('orders/1234/confirm')
|
72
|
+
# # => { id: '1234', amount: 5432.10 }
|
73
|
+
##
|
74
|
+
def self.put(path, body = nil)
|
75
|
+
response = HTTParty.put(
|
76
|
+
BASE_URL + path,
|
77
|
+
request_options(path, 'PUT', body)
|
78
|
+
)
|
79
|
+
throw_error(response) unless [200, 201].include?(response.code)
|
80
|
+
JSON.parse(response.body, symbolize_names: true)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def self.request_options(path, method, body = nil)
|
85
|
+
body = body.to_json if body
|
86
|
+
path = API_PREFIX + path
|
87
|
+
signature = Signature.new(path: path, body: body, method: method)
|
88
|
+
|
89
|
+
{
|
90
|
+
headers: {
|
91
|
+
'content-type' => 'application/json',
|
92
|
+
'accept' => 'application/json',
|
93
|
+
'authorization' => signature.header_value
|
94
|
+
},
|
95
|
+
body: body
|
96
|
+
}.compact
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.throw_error(response)
|
100
|
+
if (500..599).include?(response.code)
|
101
|
+
raise Errors::ServerError.new(response: response)
|
102
|
+
end
|
103
|
+
|
104
|
+
case response.code
|
105
|
+
when 401 # Unauthorized
|
106
|
+
raise Errors::UnauthorizedError.new(response: response)
|
107
|
+
when 404 # Resource not found
|
108
|
+
raise Errors::NotFoundError.new(response: response)
|
109
|
+
when 422
|
110
|
+
raise Errors::UnprocessableEntityError.new(response: response)
|
111
|
+
else
|
112
|
+
raise Errors::UnexpectedResponseError.new(response: response)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require "pagaris/errors/http_base_error"
|
2
|
+
require "pagaris/errors/not_found_error"
|
3
|
+
require "pagaris/errors/server_error"
|
4
|
+
require "pagaris/errors/unauthorized_error"
|
5
|
+
require "pagaris/errors/unexpected_response_error"
|
6
|
+
require "pagaris/errors/unprocessable_entity_error"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Pagaris::Errors
|
2
|
+
class HTTPBaseError < StandardError
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
@default_message = 'An unexpected error occurred when making a request'
|
6
|
+
class << self
|
7
|
+
attr_accessor :default_message
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(message = self.class.default_message, response = nil)
|
11
|
+
@response = response
|
12
|
+
super message
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Pagaris
|
2
|
+
##
|
3
|
+
# @see https://pagaris.com/docs#ordenes
|
4
|
+
##
|
5
|
+
class Order
|
6
|
+
READABLE_ATTRS = %i(id fee payout_amount status created_at updated_at url)
|
7
|
+
WRITABLE_ATTRS = %i(amount metadata products redirect_url)
|
8
|
+
ALL_ATTRS = READABLE_ATTRS + WRITABLE_ATTRS
|
9
|
+
|
10
|
+
attr_reader(*READABLE_ATTRS)
|
11
|
+
attr_accessor(*WRITABLE_ATTRS)
|
12
|
+
|
13
|
+
def initialize(amount:, metadata: nil, products: nil, redirect_url: nil)
|
14
|
+
@amount = amount
|
15
|
+
@metadata = metadata
|
16
|
+
@products = products
|
17
|
+
@redirect_url = redirect_url
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
if defined?(@id)
|
22
|
+
raise 'Cannot call `#create` on an `Order` which already has an `id`'
|
23
|
+
end
|
24
|
+
|
25
|
+
ord_attrs = WRITABLE_ATTRS.map { |a| [a, instance_variable_get("@#{a}")] }
|
26
|
+
body = { order: Hash[ord_attrs] }
|
27
|
+
response_order = Client.post('orders', body)[:order]
|
28
|
+
update_from_response(response_order)
|
29
|
+
end
|
30
|
+
|
31
|
+
def confirm
|
32
|
+
if !defined?(@id)
|
33
|
+
raise 'Cannot call `#confirm` on a non-persisted `Order`. Maybe you '\
|
34
|
+
'have not called `#create` yet?'
|
35
|
+
end
|
36
|
+
|
37
|
+
response_order = Client.put("orders/#{@id}/confirm")[:order]
|
38
|
+
update_from_response(response_order)
|
39
|
+
end
|
40
|
+
|
41
|
+
def cancel
|
42
|
+
if !defined?(@id)
|
43
|
+
raise 'Cannot call `#cancel` on a non-persisted `Order`. Maybe you '\
|
44
|
+
'have not called `#create` yet?'
|
45
|
+
end
|
46
|
+
|
47
|
+
response_order = Client.put("orders/#{@id}/cancel")[:order]
|
48
|
+
update_from_response(response_order)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.create(amount:, metadata: nil, products: nil, redirect_url: nil)
|
52
|
+
order = self.new(amount: amount, metadata: metadata, products: products,
|
53
|
+
redirect_url: redirect_url)
|
54
|
+
order.create
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.all
|
58
|
+
Client.get('orders')[:orders].map do |order|
|
59
|
+
self.new(amount: order[:amount]).send(:update_from_response, order)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.get(id)
|
64
|
+
order = Client.get("orders/#{id}")[:order]
|
65
|
+
self.new(amount: order[:amount]).send(:update_from_response, order)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def update_from_response(response_order)
|
70
|
+
ALL_ATTRS.each do |attr|
|
71
|
+
instance_variable_set("@#{attr}", response_order[attr])
|
72
|
+
end
|
73
|
+
|
74
|
+
@amount = @amount.to_f if @amount
|
75
|
+
@fee = @fee.to_f if @fee
|
76
|
+
@payout_amount = @payout_amount.to_f if @payout_amount
|
77
|
+
|
78
|
+
@created_at = Time.new(@created_at) if @created_at
|
79
|
+
@updated_at = Time.new(@updated_at) if @updated_at
|
80
|
+
|
81
|
+
self
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Pagaris
|
4
|
+
##
|
5
|
+
# Signatures (SHA256 HMACs) are used inside the `Authorization` header of API
|
6
|
+
# calls. This class extracts the signature building process.
|
7
|
+
##
|
8
|
+
class Signature
|
9
|
+
HEADER_REGEXP = /\A(Pagaris\s)?(.+):(.+):(.+)\z/
|
10
|
+
|
11
|
+
attr_reader :value
|
12
|
+
|
13
|
+
##
|
14
|
+
# Constructs a signature that should be included in the Authorization header
|
15
|
+
# of requests made by `Client` to the API.
|
16
|
+
#
|
17
|
+
# @param path [String] The path on your app where this webhook was received.
|
18
|
+
# It must match the path of the URL that you set in your Pagaris
|
19
|
+
# @param timestamp [Integer, String] Defaults to current time. Seconds since
|
20
|
+
# the Unix epoch
|
21
|
+
# @param body [String, NilClass] `nil` by default. Raw body string.
|
22
|
+
# @param method [String] `'POST'` by default, but could be changed (e.g.
|
23
|
+
# `'GET'`)
|
24
|
+
##
|
25
|
+
def initialize(path:, timestamp: Time.now.to_i, body: nil, method: 'POST')
|
26
|
+
@timestamp = timestamp
|
27
|
+
data = "#{@timestamp}-#{method}-#{path}-#{body}"
|
28
|
+
@value = OpenSSL::HMAC.hexdigest('SHA256', Pagaris.private_key, data)
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Constructs the value of an `Authorization` HTTP header, from its
|
33
|
+
# calculated value when initializing, as well as the timestamp that was
|
34
|
+
# used to calculate it.
|
35
|
+
##
|
36
|
+
def header_value
|
37
|
+
"Pagaris #{Pagaris.application_id}:#{@timestamp}:#{@value}"
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Checks if a given `Authorization` header's value contains a valid
|
42
|
+
# signature, by comparing it to an expected signature that would be
|
43
|
+
# generated with the configured `Pagaris.private_key`. Useful for verifying
|
44
|
+
# a signature of a received webhook.
|
45
|
+
#
|
46
|
+
# @param header_value [String] The value of the `Authorization` header. It
|
47
|
+
# may include the `Pagaris ` prefix as the Authentication type or not.
|
48
|
+
# @param path [String] The path on your app where this webhook was received.
|
49
|
+
# It must match the path of the URL that you set in your Pagaris
|
50
|
+
# Application (e.g. if you use a trailing slash on your Application, you
|
51
|
+
# should include it here too).
|
52
|
+
# @param body [String, NilClass] Raw body string.
|
53
|
+
# @param method [String] `'POST'` by default, but could be changed (e.g.
|
54
|
+
# `'GET'`)
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# Signature.valid?(
|
58
|
+
# header_value: request.authorization, # e.g. 'Pagaris a:b:c'
|
59
|
+
# path: request.fullpath, # e.g. '/path/for/receiving/webhooks'
|
60
|
+
# body: request.raw_post # e.g. '{"order": {"amount": "9876.54"}}'
|
61
|
+
# ) # => true or false
|
62
|
+
##
|
63
|
+
def self.valid?(header_value:, path:, body:, method: 'POST')
|
64
|
+
timestamp, signature = header_value&.match(HEADER_REGEXP)&.captures
|
65
|
+
&.[](2..3)
|
66
|
+
|
67
|
+
expected_signature = self.new(timestamp: timestamp, path: path,
|
68
|
+
body: body, method: method)
|
69
|
+
expected_signature.value == signature
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/pagaris.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "pagaris/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "pagaris"
|
7
|
+
spec.version = Pagaris::VERSION
|
8
|
+
spec.authors = ["Pagaris"]
|
9
|
+
spec.email = ["info@pagaris.com"]
|
10
|
+
|
11
|
+
spec.summary = 'Ruby library for the Pagaris API'
|
12
|
+
spec.description = 'Ruby library for the Pagaris Orders API and webhooks handling'
|
13
|
+
spec.homepage = "https://github.com/pagaris/pagaris-ruby"
|
14
|
+
|
15
|
+
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/pagaris/pagaris-ruby"
|
19
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
31
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
32
|
+
spec.add_development_dependency "minitest", "~> 5.0"
|
33
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.3.8"
|
34
|
+
spec.add_development_dependency "dotenv", "~> 2.7.5"
|
35
|
+
spec.add_development_dependency "vcr", "~> 5.1.0"
|
36
|
+
spec.add_development_dependency "webmock", "~> 3.8.3"
|
37
|
+
|
38
|
+
spec.add_dependency "httparty", "~> 0.17.1"
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pagaris
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pagaris
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest-reporters
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.8
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.3.8
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dotenv
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.7.5
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.7.5
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: vcr
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 5.1.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 5.1.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webmock
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.8.3
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.8.3
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: httparty
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.17.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.17.1
|
125
|
+
description: Ruby library for the Pagaris Orders API and webhooks handling
|
126
|
+
email:
|
127
|
+
- info@pagaris.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".travis.yml"
|
134
|
+
- Gemfile
|
135
|
+
- Gemfile.lock
|
136
|
+
- LICENSE
|
137
|
+
- README.md
|
138
|
+
- Rakefile
|
139
|
+
- bin/console
|
140
|
+
- bin/setup
|
141
|
+
- lib/pagaris.rb
|
142
|
+
- lib/pagaris/client.rb
|
143
|
+
- lib/pagaris/errors.rb
|
144
|
+
- lib/pagaris/errors/http_base_error.rb
|
145
|
+
- lib/pagaris/errors/not_found_error.rb
|
146
|
+
- lib/pagaris/errors/server_error.rb
|
147
|
+
- lib/pagaris/errors/unauthorized_error.rb
|
148
|
+
- lib/pagaris/errors/unexpected_response_error.rb
|
149
|
+
- lib/pagaris/errors/unprocessable_entity_error.rb
|
150
|
+
- lib/pagaris/order.rb
|
151
|
+
- lib/pagaris/signature.rb
|
152
|
+
- lib/pagaris/version.rb
|
153
|
+
- pagaris.gemspec
|
154
|
+
homepage: https://github.com/pagaris/pagaris-ruby
|
155
|
+
licenses: []
|
156
|
+
metadata:
|
157
|
+
homepage_uri: https://github.com/pagaris/pagaris-ruby
|
158
|
+
source_code_uri: https://github.com/pagaris/pagaris-ruby
|
159
|
+
post_install_message:
|
160
|
+
rdoc_options: []
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
requirements: []
|
174
|
+
rubygems_version: 3.0.3
|
175
|
+
signing_key:
|
176
|
+
specification_version: 4
|
177
|
+
summary: Ruby library for the Pagaris API
|
178
|
+
test_files: []
|