shipay 0.1.5
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/.byebug_history +125 -0
- data/.editorconfig +30 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/.solargraph.yml +2 -0
- data/.vscode/launch.json +16 -0
- data/CHANGELOG.md +22 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +83 -0
- data/README.md +39 -0
- data/Rakefile +12 -0
- data/bin/console +73 -0
- data/bin/setup +8 -0
- data/lib/shipay/authenticator.rb +114 -0
- data/lib/shipay/core_ext.rb +9 -0
- data/lib/shipay/errors.rb +69 -0
- data/lib/shipay/generators/install_generator.rb +42 -0
- data/lib/shipay/model.rb +69 -0
- data/lib/shipay/object.rb +139 -0
- data/lib/shipay/order_commom.rb +44 -0
- data/lib/shipay/request.rb +113 -0
- data/lib/shipay/resources/buyer_info.rb +4 -0
- data/lib/shipay/resources/item.rb +4 -0
- data/lib/shipay/resources/order.rb +10 -0
- data/lib/shipay/resources/order_bacen.rb +10 -0
- data/lib/shipay/resources/order_v.rb +39 -0
- data/lib/shipay/resources/wallet.rb +23 -0
- data/lib/shipay/resources/wallet_list.rb +11 -0
- data/lib/shipay/token_manager.rb +134 -0
- data/lib/shipay/util.rb +67 -0
- data/lib/shipay/version.rb +5 -0
- data/lib/shipay.rb +43 -0
- data/main.rb +45 -0
- metadata +120 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
module Shipay
|
2
|
+
class ShipayError < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
class ConnectionError < ShipayError
|
6
|
+
attr_reader :error
|
7
|
+
|
8
|
+
def initialize(error)
|
9
|
+
@error = error
|
10
|
+
super error.message
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class RequestError < ShipayError
|
15
|
+
end
|
16
|
+
|
17
|
+
class ResponseError < ShipayError
|
18
|
+
attr_reader :request_params, :error
|
19
|
+
|
20
|
+
def initialize(request_params, error, message=nil)
|
21
|
+
@request_params, @error = request_params, error
|
22
|
+
msg = @error.message
|
23
|
+
msg += " => " + message if message
|
24
|
+
super msg
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class NotFound < ResponseError
|
29
|
+
attr_reader :response
|
30
|
+
def initialize(response, request_params, error)
|
31
|
+
@response = response
|
32
|
+
super request_params, error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class ValidationError < ShipayError
|
37
|
+
attr_reader :response, :errors
|
38
|
+
|
39
|
+
def initialize(response)
|
40
|
+
@response = response
|
41
|
+
@errors = response['message']&.map do |message|
|
42
|
+
params = error.values_at('message', 'parameter_name', 'type', 'url')
|
43
|
+
ParamError.new(*params)
|
44
|
+
end
|
45
|
+
super @errors&.map(&:message).join(', ')
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_h
|
49
|
+
@errors.map(&:to_h)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class MissingCredentialsError < ShipayError
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
class ParamError < ShipayError
|
58
|
+
attr_reader :parameter_name, :type, :url
|
59
|
+
|
60
|
+
def initialize(message, parameter_name, type, url=nil)
|
61
|
+
@parameter_name, @type, @url = parameter_name, type, url
|
62
|
+
super message
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_h
|
66
|
+
{ parameter_name: parameter_name, type: type, message: message }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
# require 'rails/generators/base'
|
3
|
+
|
4
|
+
# module Shipay
|
5
|
+
# module Generator
|
6
|
+
# class InstallGenerator < Rails::Generators::Base
|
7
|
+
# source_root File.expand_path("../../templates", __FILE__)
|
8
|
+
|
9
|
+
# desc "Creates a Devise initializer and copy locale files to your application."
|
10
|
+
# class_option :orm, required: true
|
11
|
+
|
12
|
+
# def copy_initializer
|
13
|
+
# unless options[:orm]
|
14
|
+
# raise MissingORMError, <<-ERROR.strip_heredoc
|
15
|
+
# An ORM must be set to install Devise in your application.
|
16
|
+
# Be sure to have an ORM like Active Record or Mongoid loaded in your
|
17
|
+
# app or configure your own at `config/application.rb`.
|
18
|
+
# config.generators do |g|
|
19
|
+
# g.orm :your_orm_gem
|
20
|
+
# end
|
21
|
+
# ERROR
|
22
|
+
# end
|
23
|
+
|
24
|
+
# template "devise.rb", "config/initializers/devise.rb"
|
25
|
+
# end
|
26
|
+
|
27
|
+
# def copy_locale
|
28
|
+
# copy_file "../../../config/locales/en.yml", "config/locales/devise.en.yml"
|
29
|
+
# end
|
30
|
+
|
31
|
+
# def show_readme
|
32
|
+
# readme "README" if behavior == :invoke
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
# end
|
42
|
+
# end
|
data/lib/shipay/model.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Shipay
|
2
|
+
class Model < ShipayObject
|
3
|
+
def create
|
4
|
+
update Shipay::Request.post(self.class.url, params: to_hash).call(class_name)
|
5
|
+
self
|
6
|
+
end
|
7
|
+
|
8
|
+
def save
|
9
|
+
update Shipay::Request.put(url, params: unsaved_attributes).call(class_name)
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def url(*params)
|
14
|
+
raise RequestError.new('Invalid ID') unless primary_key.present?
|
15
|
+
self.class.url CGI.escape(primary_key.to_s), *params
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch
|
19
|
+
update self.class.find(primary_key, client_key: client_key)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def primary_key
|
24
|
+
id
|
25
|
+
end
|
26
|
+
|
27
|
+
def class_name
|
28
|
+
self.class.to_s.split('::').last
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def create(*args)
|
33
|
+
self.new(*args).create
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_by_id(id, **options)
|
37
|
+
raise RequestError.new('Invalid ID') unless id.present?
|
38
|
+
Shipay::Request.get(url(id), options).call underscored_class_name
|
39
|
+
end
|
40
|
+
alias :find :find_by_id
|
41
|
+
|
42
|
+
# def find_by(params = Hash.new, page = nil, count = nil)
|
43
|
+
# params = extract_page_count_or_params(page, count, **params)
|
44
|
+
# raise RequestError.new('Invalid page count') if params[:page] < 1 or params[:count] < 1
|
45
|
+
|
46
|
+
# Shipay::Request.get(url, params: params).call
|
47
|
+
# end
|
48
|
+
# alias :find_by_hash :find_by
|
49
|
+
|
50
|
+
# def all(*args, **params)
|
51
|
+
# params = extract_page_count_or_params(*args, **params)
|
52
|
+
# find_by params
|
53
|
+
# end
|
54
|
+
# alias :where :all
|
55
|
+
|
56
|
+
def url(*params)
|
57
|
+
["/#{ CGI.escape class_name }", *params].join '/'
|
58
|
+
end
|
59
|
+
|
60
|
+
def class_name
|
61
|
+
self.name.split('::').last.downcase
|
62
|
+
end
|
63
|
+
|
64
|
+
def underscored_class_name
|
65
|
+
self.name.split('::').last.gsub(/[a-z0-9][A-Z]/){|s| "#{s[0]}_#{s[1]}"}.downcase
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Shipay
|
2
|
+
class ShipayObject
|
3
|
+
attr_reader :attributes
|
4
|
+
|
5
|
+
RESOURCES = Dir[File.expand_path('../resources/*.rb', __FILE__)].map do |path|
|
6
|
+
File.basename(path, '.rb').to_sym
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(response = {})
|
10
|
+
# raise MissingCredentialsError.new("Missing :client_key for extra options #{options}") if options && !options[:client_key]
|
11
|
+
|
12
|
+
@attributes = Hash.new
|
13
|
+
@unsaved_attributes = Set.new
|
14
|
+
|
15
|
+
@client_key = response.dig(:client_key) || Shipay.default_client_key #|| :default
|
16
|
+
update response
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(key,value)
|
20
|
+
@attributes[key] = value
|
21
|
+
@unsaved_attributes.add key
|
22
|
+
end
|
23
|
+
|
24
|
+
def empty?
|
25
|
+
@attributes.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
self.class == other.class && id == other.id
|
30
|
+
end
|
31
|
+
|
32
|
+
def unsaved_attributes
|
33
|
+
Hash[@unsaved_attributes.map do |key|
|
34
|
+
[ key, to_hash_value(self[key], :unsaved_attributes) ]
|
35
|
+
end]
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_hash
|
39
|
+
Hash[@attributes.map do |key, value|
|
40
|
+
[ key, to_hash_value(value, :to_hash) ]
|
41
|
+
end]
|
42
|
+
end
|
43
|
+
|
44
|
+
def respond_to?(name, include_all = false)
|
45
|
+
return true if name.to_s.end_with? '='
|
46
|
+
|
47
|
+
@attributes.has_key?(name.to_s) || super
|
48
|
+
end
|
49
|
+
|
50
|
+
# def to_s
|
51
|
+
# attributes_str = ''
|
52
|
+
# (attributes.keys - ['id', 'object']).sort.each do |key|
|
53
|
+
# attributes_str += " \033[1;33m#{key}:\033[0m#{self[key].inspect}" unless self[key].nil?
|
54
|
+
# end
|
55
|
+
# "\033[1;31m#<#{self.class.name}:\033[0;32m#{id}#{attributes_str}\033[0m\033[0m\033[1;31m>\033[0;32m"
|
56
|
+
# end
|
57
|
+
# # alias :inspect :to_s
|
58
|
+
|
59
|
+
protected
|
60
|
+
def update(attributes)
|
61
|
+
removed_attributes = @attributes.keys - attributes.to_hash.keys
|
62
|
+
|
63
|
+
removed_attributes.each do |key|
|
64
|
+
@attributes.delete key
|
65
|
+
end
|
66
|
+
|
67
|
+
attributes.each do |key, value|
|
68
|
+
key = key.to_s
|
69
|
+
|
70
|
+
@attributes[key] = ShipayObject.convert(value, Util.singularize(key), @client_key)
|
71
|
+
@unsaved_attributes.delete key
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_hash_value(value, type)
|
76
|
+
case value
|
77
|
+
when ShipayObject
|
78
|
+
value.send type
|
79
|
+
when Array
|
80
|
+
value.map do |v|
|
81
|
+
to_hash_value v, type
|
82
|
+
end
|
83
|
+
else
|
84
|
+
value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def method_missing(name, *args, &block)
|
89
|
+
name = name.to_s
|
90
|
+
|
91
|
+
unless block_given?
|
92
|
+
if name.end_with?('=') && args.size == 1
|
93
|
+
attribute_name = name[0...-1]
|
94
|
+
return self[attribute_name] = args[0]
|
95
|
+
end
|
96
|
+
|
97
|
+
if args.size == 0
|
98
|
+
return self[name] || self[name.to_sym]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
if attributes.respond_to? name
|
103
|
+
return attributes.public_send name, *args, &block
|
104
|
+
end
|
105
|
+
|
106
|
+
super name, *args, &block
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
class << self
|
111
|
+
def convert(response, resource_name = nil, client_key=nil)
|
112
|
+
case response
|
113
|
+
when Array
|
114
|
+
response.map{ |i| convert i, resource_name, client_key }
|
115
|
+
when Hash
|
116
|
+
resource_class_for(resource_name).new(response.merge({client_key: client_key}))
|
117
|
+
else
|
118
|
+
response
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
protected
|
123
|
+
def resource_class_for(resource_name)
|
124
|
+
return Shipay::ShipayObject if resource_name.nil?
|
125
|
+
|
126
|
+
if RESOURCES.include? resource_name.to_sym
|
127
|
+
Object.const_get "Shipay::#{capitalize_name resource_name}"
|
128
|
+
else
|
129
|
+
Shipay::ShipayObject
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def capitalize_name(name)
|
134
|
+
name.split('_').collect(&:capitalize).join
|
135
|
+
# name.gsub(/(\A\w|\_\w)/){ |str| str.gsub('_', '').upcase }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Shipay
|
2
|
+
class OrderCommom < Model
|
3
|
+
|
4
|
+
# def self.url(*params)
|
5
|
+
# ["/#{ CGI.escape underscored_class_name }", *params].join '/'
|
6
|
+
# end
|
7
|
+
|
8
|
+
#
|
9
|
+
# Request refund to Shipay api for this order
|
10
|
+
#
|
11
|
+
# @param [Hash] params Parameters for function
|
12
|
+
# @option params [Numeric] :amount (Required) The amount that will be refunded in float format
|
13
|
+
# @return [Order] Return model order instance
|
14
|
+
# @example Refund 1.0 from order
|
15
|
+
# order_instance.refund(amount: 1.0)
|
16
|
+
def refund(params={})
|
17
|
+
raise ParamError.new("Missing ammount param", :amount, :float, url('refund')) unless params.has_key? :amount
|
18
|
+
update Shipay::Request.delete(url_delete('refund'), params: params.merge(client_key: @client_key)).call(underscored_class_name)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Defines primary key for model
|
24
|
+
#
|
25
|
+
# @return [String] Return the primary_key field value
|
26
|
+
def primary_key
|
27
|
+
order_id
|
28
|
+
end
|
29
|
+
|
30
|
+
def url_delete(*params)
|
31
|
+
raise RequestError.new('Invalid ID') unless primary_key.present?
|
32
|
+
["/order", CGI.escape(primary_key.to_s), *params].join('/')
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Request order Cancel to Shipay api
|
37
|
+
#
|
38
|
+
# @return [Order] Return model order instance
|
39
|
+
def cancel()
|
40
|
+
update Shipay::Request.delete(url_delete, client_key: @client_key).call(underscored_class_name)
|
41
|
+
self
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'multi_json'
|
4
|
+
|
5
|
+
|
6
|
+
DEFAULT_HEADERS = {
|
7
|
+
'Content-Type' => 'application/json; charset=utf8',
|
8
|
+
'Accept' => 'application/json',
|
9
|
+
'User-Agent' => "shipay-ruby/#{Shipay::VERSION}"
|
10
|
+
}
|
11
|
+
|
12
|
+
module Shipay
|
13
|
+
class Request
|
14
|
+
attr_accessor :path, :method, :parameters, :headers, :query
|
15
|
+
|
16
|
+
def initialize(path, method, options={})
|
17
|
+
@path = path
|
18
|
+
@method = method
|
19
|
+
@parameters = options[:params] || nil
|
20
|
+
@query = options[:query] || Hash.new
|
21
|
+
@headers = options[:headers] || Hash.new
|
22
|
+
@auth = options[:auth] || false
|
23
|
+
@client_key = options[:client_key] || @parameters && ( @parameters[:client_key] || @parameters["client_key"] ) || Shipay.default_client_key
|
24
|
+
end
|
25
|
+
|
26
|
+
def run
|
27
|
+
response = RestClient::Request.execute request_params
|
28
|
+
MultiJson.decode response.body
|
29
|
+
|
30
|
+
rescue RestClient::Exception => error
|
31
|
+
begin
|
32
|
+
parsed_error = MultiJson.decode error.http_body
|
33
|
+
|
34
|
+
if error.is_a? RestClient::ResourceNotFound
|
35
|
+
if parsed_error['message']
|
36
|
+
raise Shipay::NotFound.new(parsed_error, request_params, error)
|
37
|
+
else
|
38
|
+
raise Shipay::NotFound.new(nil, request_params, error)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
if parsed_error['message']
|
42
|
+
raise Shipay::ResponseError.new(request_params, error, parsed_error['message'])
|
43
|
+
else
|
44
|
+
raise Shipay::ValidationError.new parsed_error
|
45
|
+
end
|
46
|
+
end
|
47
|
+
rescue MultiJson::ParseError
|
48
|
+
raise Shipay::ResponseError.new(request_params, error)
|
49
|
+
end
|
50
|
+
rescue MultiJson::ParseError
|
51
|
+
raise Shipay::ResponseError.new(request_params, response)
|
52
|
+
rescue SocketError
|
53
|
+
raise Shipay::ConnectionError.new $!
|
54
|
+
rescue RestClient::ServerBrokeConnection
|
55
|
+
raise Shipay::ConnectionError.new $!
|
56
|
+
end
|
57
|
+
|
58
|
+
def call(ressource_name)
|
59
|
+
ShipayObject.convert run, ressource_name, @client_key
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.get(url, options={})
|
63
|
+
self.new url, 'GET', options
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.auth(url, options={})
|
67
|
+
options[:auth] = true
|
68
|
+
self.new url, 'POST', options
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.post(url, options={})
|
72
|
+
self.new url, 'POST', options
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.put(url, options={})
|
76
|
+
self.new url, 'PUT', options
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.patch(url, options={})
|
80
|
+
self.new url, 'PATCH', options
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.delete(url, options={})
|
84
|
+
self.new url, 'DELETE', options
|
85
|
+
end
|
86
|
+
|
87
|
+
def request_params
|
88
|
+
aux = {
|
89
|
+
method: method,
|
90
|
+
url: full_api_url,
|
91
|
+
}
|
92
|
+
|
93
|
+
@parameters&.except_nested!("client_key")
|
94
|
+
|
95
|
+
if !@auth && @parameters && Shipay.callback_url && Shipay::TokenManager.client_type_for(@client_key) == :e_comerce && method == 'POST'
|
96
|
+
aux.merge!({ payload: MultiJson.encode(@parameters.merge({callback_url: Shipay.callback_url}))})
|
97
|
+
elsif @parameters
|
98
|
+
aux.merge!({ payload: MultiJson.encode(@parameters)})
|
99
|
+
end
|
100
|
+
|
101
|
+
extra_headers = DEFAULT_HEADERS
|
102
|
+
extra_headers[:authorization] = "Bearer #{Shipay::TokenManager.token_for @client_key}" unless @auth
|
103
|
+
extra_headers["x-shipay-order-type"] = "e-order" if (!@auth && Shipay::TokenManager.client_type_for(@client_key) == :e_comerce)
|
104
|
+
|
105
|
+
aux.merge!({ headers: extra_headers })
|
106
|
+
aux
|
107
|
+
end
|
108
|
+
|
109
|
+
def full_api_url
|
110
|
+
Shipay.api_endpoint + path
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# {
|
2
|
+
# "order_ref": "shipaypag-001",
|
3
|
+
# "wallet": "shipay-pagador",
|
4
|
+
# "total": 0.51,
|
5
|
+
# "items": [
|
6
|
+
# {
|
7
|
+
# "item_title": "Item 1",
|
8
|
+
# "unit_price": 0.30,
|
9
|
+
# "quantity": 1
|
10
|
+
# },
|
11
|
+
# {
|
12
|
+
# "item_title": "Item 2",
|
13
|
+
# "unit_price": 0.20,
|
14
|
+
# "quantity": 1
|
15
|
+
# },
|
16
|
+
# {
|
17
|
+
# "item_title": "Item 3",
|
18
|
+
# "unit_price": 0.01,
|
19
|
+
# "quantity": 1
|
20
|
+
# }
|
21
|
+
# ],
|
22
|
+
# "buyer": {
|
23
|
+
# "name": "Shipay PDV",
|
24
|
+
# "cpf_cnpj": "121.191.870-02",
|
25
|
+
# "email": "shipay-pagador@shipay.com.br",
|
26
|
+
# "phone": "+55 11 99999-9999"
|
27
|
+
# }
|
28
|
+
# }
|
29
|
+
# path = '/order'
|
30
|
+
module Shipay
|
31
|
+
class OrderV < OrderCommom
|
32
|
+
|
33
|
+
# def self.url(*params)
|
34
|
+
# ["/#{ CGI.escape underscored_class_name }", *params].join '/'
|
35
|
+
# end
|
36
|
+
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# {
|
2
|
+
# "active": true,
|
3
|
+
# "friendly_name": "Shipay Pagador",
|
4
|
+
# "logo": null,
|
5
|
+
# "minimum_payment": 0.0,
|
6
|
+
# "pix_dict_key": null,
|
7
|
+
# "pix_psp": null,
|
8
|
+
# "wallet": "shipay-pagador",
|
9
|
+
# "wallet_setting_id": null,
|
10
|
+
# "wallet_setting_name": null
|
11
|
+
# }
|
12
|
+
# path = '/v1/wallets'
|
13
|
+
module Shipay
|
14
|
+
class Wallet < Model
|
15
|
+
def self.url(*params)
|
16
|
+
["/v1/#{ CGI.escape underscored_class_name }s", *params].join '/'
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.all()
|
20
|
+
Shipay::Request.get(url).call(class_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|