sicoob_api 0.0.1
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/README.md +10 -0
- data/lib/sicoob_api/client.rb +106 -0
- data/lib/sicoob_api/payment.rb +87 -0
- data/lib/sicoob_api/payment_error.rb +25 -0
- data/lib/sicoob_api/version.rb +5 -0
- data/lib/sicoob_api.rb +17 -0
- metadata +106 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 4d201618226be8e7c5495ff1dba58de27b32c04a1cb32f23fb0f2aa8fc152f53
|
4
|
+
data.tar.gz: e6e2c854ff1ec1f2b9cf3a80a0324c71279638dfd251fd4f21742ea3c0320c68
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5ef3778e556f6cd251d7d0dc30a2a4e5f9475b707f264de5d79cd7ac95803fef44bcb72b8d1205d6a630ca8073a5a63a37e2fc33d0a0139cdc8acf15c88cdc9d
|
7
|
+
data.tar.gz: ef8e4e299689e1e30d156b5d87d9cd1bb8440fe90cb0124fa9c8762b9ca33f9c2fee3ef2f8087808717d7c4eb39e7dc632e7a18274a029cd4e3fdec3d1afab39
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
module SicoobApi
|
2
|
+
class Client < Ac::Base
|
3
|
+
BASE_URL = "https://api.sicoob.com.br/pix/api/v2"
|
4
|
+
# SAVE_RESPONSES = true
|
5
|
+
MAX_RETIES = 2
|
6
|
+
|
7
|
+
attr_accessor :client_id, :chave_pix, :crt, :key, :token, :token_expires_at, :scopes
|
8
|
+
|
9
|
+
def initialize(client_id:, chave_pix:, crt:, key:, token: nil, token_expires_at: nil, scopes: "cob.write cob.read cobv.write cobv.read lotecobv.write lotecobv.read pix.write pix.read webhook.read webhook.write payloadlocation.write payloadlocation.read")
|
10
|
+
@client_id = client_id
|
11
|
+
@chave_pix = chave_pix
|
12
|
+
@crt = crt
|
13
|
+
@key = key
|
14
|
+
@token = token
|
15
|
+
@token_expires_at = token_expires_at
|
16
|
+
@scopes = scopes
|
17
|
+
access_token
|
18
|
+
end
|
19
|
+
|
20
|
+
def access_token
|
21
|
+
if token.nil? || token_expires_at.nil? || token_expires_at < Time.now
|
22
|
+
response = Typhoeus.post("https://auth.sicoob.com.br/auth/realms/cooperado/protocol/openid-connect/token",
|
23
|
+
body: {
|
24
|
+
client_id: client_id,
|
25
|
+
scope: scopes,
|
26
|
+
grant_type: "client_credentials"
|
27
|
+
},
|
28
|
+
sslcert: crt,
|
29
|
+
sslkey: key) { |response| validate_response(response, "access_token") }
|
30
|
+
raise "Erro ao obter token: #{response.body}" unless response.success?
|
31
|
+
@token = response.json["access_token"]
|
32
|
+
@token_expires_at = Time.now + response.json["expires_in"]
|
33
|
+
end
|
34
|
+
token
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_payment amount:, payer_tax_id: nil, payer_name: nil, expiration: 3600, solicitacao_pagador: nil, info_adicionais: []
|
38
|
+
body = {
|
39
|
+
calendario: {
|
40
|
+
expiracao: expiration
|
41
|
+
},
|
42
|
+
valor: {
|
43
|
+
original: format("%.2f", amount),
|
44
|
+
modalidadeAlteracao: 0
|
45
|
+
},
|
46
|
+
chave: chave_pix
|
47
|
+
}
|
48
|
+
body[:devedor] = devedor(payer_tax_id, payer_name) if payer_tax_id && payer_name
|
49
|
+
body[:solicitacaoPagador] = solicitacao_pagador if solicitacao_pagador
|
50
|
+
body[:infoAdicionais] = info_adicionais if info_adicionais.any?
|
51
|
+
response = post("cob", sslcert: crt, sslkey: key, body: JSON.dump(body), headers: {"content-type": "application/json"}) { |response| validate_response(response, "txid") }
|
52
|
+
SicoobApi::Payment.new(response.json, self)
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_payment txid
|
56
|
+
response = get("cob/#{txid}", sslcert: crt, sslkey: key) { |response| validate_response(response, "txid") }
|
57
|
+
SicoobApi::Payment.new(response.json, self)
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_payment(payment_id, body)
|
61
|
+
response = patch("cob/#{payment_id}", headers: {"content-type": "application/json"}, sslcert: @crt, sslkey: @key, body: JSON.dump(body)) { |response| validate_response(response, "txid") }
|
62
|
+
SicoobApi::Payment.new(response.json, self)
|
63
|
+
end
|
64
|
+
|
65
|
+
def refund_payment(end_to_end_id, amount, refund_nature, description)
|
66
|
+
id = SecureRandom.hex(10)
|
67
|
+
body = {
|
68
|
+
valor: format("%.2f", amount),
|
69
|
+
natureza: refund_nature,
|
70
|
+
descricao: description
|
71
|
+
}
|
72
|
+
response = put("pix/#{end_to_end_id}/devolucao/#{id}", headers: {"content-type": "application/json"}, sslcert: @crt, sslkey: @key, body: JSON.dump(body)) { |response| validate_response(response, "id") }
|
73
|
+
response.json
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_refund(end_to_end_id, id)
|
77
|
+
response = get("pix/#{end_to_end_id}/devolucao/#{id}", headers: {"content-type": "application/json"}, sslcert: @crt, sslkey: @key) { |response| validate_response(response, "id") }
|
78
|
+
response.json
|
79
|
+
end
|
80
|
+
|
81
|
+
def update_webhook url
|
82
|
+
put("webhook/#{chave_pix}", sslcert: crt, sslkey: key, body: JSON.dump({webhookUrl: url})) { |response| validate_response(response, "") }
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_webhook
|
86
|
+
get("webhook/#{chave_pix}", sslcert: crt, sslkey: key) { |response| validate_response(response, "webhookUrl") }
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def devedor(payer_tax_id, payer_name)
|
92
|
+
return {} if payer_tax_id.nil? || payer_name.nil?
|
93
|
+
formatted_tax_id = payer_tax_id.gsub(/\D/, "")
|
94
|
+
document_type = (formatted_tax_id.length == 11) ? "cpf" : "cnpj"
|
95
|
+
{
|
96
|
+
document_type => formatted_tax_id,
|
97
|
+
"nome" => payer_name
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def validate_response(response, required_response_key)
|
102
|
+
puts response.json unless response.success?
|
103
|
+
![500, 429].include?(response.code) || response.json.dig(*required_response_key)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module SicoobApi
|
2
|
+
class Payment
|
3
|
+
attr_reader :response, :txid, :end_to_end_id, :devolucoes, :copia_e_cola, :status, :solicitacao, :info_adicionais, :valor_original, :valor_pago, :criacao, :expiracao, :pago_em, :devedor_nome, :devedor_tax_id, :internal_error
|
4
|
+
def initialize(response, client)
|
5
|
+
@client = client
|
6
|
+
@response = response
|
7
|
+
@txid = response.dig("txid")
|
8
|
+
@end_to_end_id = response.dig("pix", 0, "endToEndId")
|
9
|
+
@devolucoes = response.dig("pix", 0, "devolucoes")
|
10
|
+
@copia_e_cola = response.dig("brcode") || response.dig("qrCode")
|
11
|
+
@status = response.dig("status")
|
12
|
+
@solicitacao = response.dig("solicitacaoPagador")
|
13
|
+
@info_adicionais = response.dig("infoAdicionais")
|
14
|
+
@valor_original = response.dig("valor", "original")
|
15
|
+
@valor_pago = response.dig("pix", 0, "valor")
|
16
|
+
@criacao = creation_date
|
17
|
+
@expiracao = expiration_date
|
18
|
+
@pago_em = paid_date
|
19
|
+
@devedor_nome = response.dig("devedor", "nome")
|
20
|
+
@devedor_tax_id = response.dig("devedor", "cpf") || response.dig("devedor", "cnpj")
|
21
|
+
@internal_error = PaymentError.new(response).internal_error
|
22
|
+
end
|
23
|
+
|
24
|
+
def paid? external_value = nil
|
25
|
+
external_value = @valor_original if external_value.nil?
|
26
|
+
@status == "CONCLUIDA" && @valor_original.to_d == @valor_pago.to_d && external_value.to_d == @valor_pago.to_d
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid?
|
30
|
+
@status == "ATIVA" && @expiracao > Time.now
|
31
|
+
end
|
32
|
+
|
33
|
+
def retrieve
|
34
|
+
@client.get_payment(@txid)
|
35
|
+
end
|
36
|
+
|
37
|
+
def reload!
|
38
|
+
new_payment = retrieve
|
39
|
+
instance_variables.each do |variable|
|
40
|
+
instance_variable_set(variable, new_payment.instance_variable_get(variable))
|
41
|
+
end
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def update(body)
|
46
|
+
@client.update_payment(@txid, body)
|
47
|
+
end
|
48
|
+
|
49
|
+
def invalidate!
|
50
|
+
update({status: "REMOVIDA_PELO_USUARIO_RECEBEDOR"})
|
51
|
+
reload!
|
52
|
+
end
|
53
|
+
|
54
|
+
def refund(amount: nil, refund_nature: nil, description: nil)
|
55
|
+
amount ||= @valor_pago
|
56
|
+
refund_nature ||= "ORIGINAL"
|
57
|
+
@client.refund_payment(@end_to_end_id, amount, refund_nature, description)
|
58
|
+
end
|
59
|
+
|
60
|
+
def qr_code(module_size: 4)
|
61
|
+
return false unless @copia_e_cola
|
62
|
+
qr = RQRCode::QRCode.new(@copia_e_cola, size: 10, level: :l)
|
63
|
+
qr.as_svg(module_size: module_size)
|
64
|
+
end
|
65
|
+
|
66
|
+
def puts_qrcode
|
67
|
+
puts RQRCode::QRCode.new(@copia_e_cola).to_s(dark: "██", light: " ")
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def creation_date
|
73
|
+
return nil unless @response.dig("calendario", "criacao")
|
74
|
+
Time.new(@response.dig("calendario", "criacao"))
|
75
|
+
end
|
76
|
+
|
77
|
+
def expiration_date
|
78
|
+
return nil unless @response.dig("calendario", "criacao")
|
79
|
+
Time.new(@response.dig("calendario", "criacao")) + @response.dig("calendario", "expiracao")
|
80
|
+
end
|
81
|
+
|
82
|
+
def paid_date
|
83
|
+
return nil unless @response.dig("pix", 0, "horario")
|
84
|
+
Time.new(@response.dig("pix", 0, "horario"))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module SicoobApi
|
2
|
+
class PaymentError
|
3
|
+
STATUS_ERROR = [400, 403, 404, 503]
|
4
|
+
attr_accessor :json_response
|
5
|
+
def initialize json_response
|
6
|
+
@json_response = json_response
|
7
|
+
end
|
8
|
+
|
9
|
+
def internal_error
|
10
|
+
return nil unless json_response["violacoes"] || STATUS_ERROR.include?(json_response["status"])
|
11
|
+
failed_message_error || rejected_message_error || "Pagamento recusado."
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def rejected_message_error
|
17
|
+
"#{json_response["title"]} => #{json_response["detail"]}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def failed_message_error
|
21
|
+
return false unless json_response["violacoes"]
|
22
|
+
"#{json_response["violacoes"][0]["razao"]} => #{json_response["violacoes"][0]["propriedade"]}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/sicoob_api.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ac"
|
4
|
+
require "bigdecimal/util"
|
5
|
+
require "securerandom"
|
6
|
+
require "rqrcode"
|
7
|
+
|
8
|
+
require_relative "sicoob_api/version"
|
9
|
+
require_relative "sicoob_api/client"
|
10
|
+
require_relative "sicoob_api/payment"
|
11
|
+
require_relative "sicoob_api/payment_error"
|
12
|
+
|
13
|
+
module SicoobApi
|
14
|
+
Typhoeus::Config.timeout = 10
|
15
|
+
|
16
|
+
class Error < StandardError; end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sicoob_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- hamilton
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ac
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rqrcode
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bigdecimal
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: securerandom
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: ''
|
70
|
+
email: hamilton@todasessascoisas.com.br
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- README.md
|
76
|
+
- lib/sicoob_api.rb
|
77
|
+
- lib/sicoob_api/client.rb
|
78
|
+
- lib/sicoob_api/payment.rb
|
79
|
+
- lib/sicoob_api/payment_error.rb
|
80
|
+
- lib/sicoob_api/version.rb
|
81
|
+
homepage: https://github.com/todasessascoisas/sicoob_api
|
82
|
+
licenses: []
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '2.5'
|
93
|
+
- - "<"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '4'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubygems_version: 3.5.10
|
103
|
+
signing_key:
|
104
|
+
specification_version: 4
|
105
|
+
summary: ''
|
106
|
+
test_files: []
|