flashpi 0.1.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/CHANGELOG.md +25 -0
- data/LICENSE +21 -0
- data/README.en.md +379 -0
- data/README.md +383 -0
- data/lib/flashpi/api_response.rb +33 -0
- data/lib/flashpi/client.rb +112 -0
- data/lib/flashpi/errors.rb +116 -0
- data/lib/flashpi/internal/engine.rb +355 -0
- data/lib/flashpi/internal/json_text.rb +108 -0
- data/lib/flashpi/internal/multipart.rb +141 -0
- data/lib/flashpi/internal/problems.rb +111 -0
- data/lib/flashpi/internal/request.rb +231 -0
- data/lib/flashpi/internal/resource.rb +125 -0
- data/lib/flashpi/internal/secret.rb +41 -0
- data/lib/flashpi/internal/settings.rb +88 -0
- data/lib/flashpi/internal/transport.rb +432 -0
- data/lib/flashpi/internal/validate.rb +122 -0
- data/lib/flashpi/page.rb +82 -0
- data/lib/flashpi/resources/documents.rb +136 -0
- data/lib/flashpi/resources/events.rb +36 -0
- data/lib/flashpi/resources/issuer_onboardings.rb +47 -0
- data/lib/flashpi/resources/issuers.rb +179 -0
- data/lib/flashpi/resources/webhook_endpoints.rb +110 -0
- data/lib/flashpi/version.rb +6 -0
- data/lib/flashpi/webhooks.rb +223 -0
- data/lib/flashpi.rb +42 -0
- data/sig/flashpi/internal.rbs +376 -0
- data/sig/flashpi/resources.rbs +712 -0
- data/sig/flashpi/sdk_types.rbs +114 -0
- data/sig/flashpi/types.rbs +2495 -0
- data/sig/flashpi.rbs +187 -0
- data/sig/manifest.yaml +8 -0
- metadata +80 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flashpi
|
|
4
|
+
module Resources
|
|
5
|
+
# Issues one document type. The answer is the document: `processing` right away (202), or,
|
|
6
|
+
# with `options: { waitForAuthorization: true }`, its outcome once the SRI decides (200),
|
|
7
|
+
# unless the wait ends first (202 with `processing` or `pending_sri`; follow it with webhooks
|
|
8
|
+
# or `documents.get`).
|
|
9
|
+
class DocumentIssuer < Internal::Resource
|
|
10
|
+
# Seconds the API waits for the SRI in sync mode when `waitTimeoutSeconds` is not sent.
|
|
11
|
+
DEFAULT_WAIT_SECONDS = 15
|
|
12
|
+
# Time on top of the sync wait for Flashpi to build, sign and answer.
|
|
13
|
+
SYNC_MARGIN_SECONDS = 15
|
|
14
|
+
|
|
15
|
+
response_methods :create
|
|
16
|
+
|
|
17
|
+
# The shortest per-attempt timeout for issuing `body`, in seconds.
|
|
18
|
+
#
|
|
19
|
+
# In sync mode (`options.waitForAuthorization`) the API holds the request for up to
|
|
20
|
+
# `waitTimeoutSeconds` (15 by default) while the SRI decides, so each attempt waits at least
|
|
21
|
+
# that plus 15 seconds. Otherwise 0: the client's timeout applies.
|
|
22
|
+
#
|
|
23
|
+
# @return [Float]
|
|
24
|
+
def self.sync_timeout_floor(body)
|
|
25
|
+
settings = member(body, :options)
|
|
26
|
+
return 0.0 unless member(settings, :waitForAuthorization) == true
|
|
27
|
+
|
|
28
|
+
wait = member(settings, :waitTimeoutSeconds)
|
|
29
|
+
wait = DEFAULT_WAIT_SECONDS unless wait.is_a?(Integer) || (wait.is_a?(Float) && wait.finite?)
|
|
30
|
+
(wait + SYNC_MARGIN_SECONDS).to_f
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# @api private
|
|
34
|
+
def self.member(value, name)
|
|
35
|
+
return nil unless value.is_a?(Hash)
|
|
36
|
+
|
|
37
|
+
value.key?(name) ? value[name] : value[name.to_s]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Issues the document. Retries reuse the same Idempotency-Key, and when a retry finds the
|
|
41
|
+
# document already created by an earlier attempt, its current state is returned instead of
|
|
42
|
+
# an error.
|
|
43
|
+
#
|
|
44
|
+
# @param body [Hash] the document, with the API's camelCase keys
|
|
45
|
+
# @return [Hash{Symbol => Object}] the document
|
|
46
|
+
def create(body, **options)
|
|
47
|
+
floor = DocumentIssuer.sync_timeout_floor(body)
|
|
48
|
+
send_request(operation(:post, self.class::PATH, body:, options:, min_timeout: floor, recover_document: true))
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Invoices (facturas).
|
|
53
|
+
class Invoices < DocumentIssuer
|
|
54
|
+
PATH = "/v1/invoices"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Credit notes (notas de crédito).
|
|
58
|
+
class CreditNotes < DocumentIssuer
|
|
59
|
+
PATH = "/v1/credit-notes"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Debit notes (notas de débito).
|
|
63
|
+
class DebitNotes < DocumentIssuer
|
|
64
|
+
PATH = "/v1/debit-notes"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Purchase settlements (liquidaciones de compra).
|
|
68
|
+
class PurchaseSettlements < DocumentIssuer
|
|
69
|
+
PATH = "/v1/purchase-settlements"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Waybills (guías de remisión).
|
|
73
|
+
class Waybills < DocumentIssuer
|
|
74
|
+
PATH = "/v1/waybills"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Withholding receipts (comprobantes de retención).
|
|
78
|
+
class Withholdings < DocumentIssuer
|
|
79
|
+
PATH = "/v1/withholdings"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Every issued document, of any type: search, XML, RIDE (PDF) and email.
|
|
83
|
+
class Documents < Internal::Resource
|
|
84
|
+
XML_ACCEPT = "application/xml, application/problem+json"
|
|
85
|
+
PDF_ACCEPT = "application/pdf, application/problem+json"
|
|
86
|
+
XML_KINDS = %w[authorized signed unsigned].freeze
|
|
87
|
+
|
|
88
|
+
response_methods :list, :get, :xml, :pdf, :send_email
|
|
89
|
+
|
|
90
|
+
# Lists documents, newest first, with optional filters.
|
|
91
|
+
#
|
|
92
|
+
# @param params [Hash, nil] filters with the API's names (`status`, `issueDateFrom`, ...)
|
|
93
|
+
# @return [Flashpi::Page]
|
|
94
|
+
def list(params = nil, **options)
|
|
95
|
+
paginate(operation(:get, "/v1/documents", query: params, options:))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Retrieves a document with its tax status, SRI messages, RIDE and email state.
|
|
99
|
+
#
|
|
100
|
+
# @return [Hash{Symbol => Object}]
|
|
101
|
+
def get(document_id, **options)
|
|
102
|
+
send_request(operation(:get, "/v1/documents/{}", document_id, options:))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# The document's XML: the authorized one once the SRI authorizes it, otherwise the signed or
|
|
106
|
+
# unsigned one (see `kind`).
|
|
107
|
+
#
|
|
108
|
+
# @return [Hash{Symbol => Object}] `{ xml: String, kind: "authorized" | "signed" | "unsigned" | nil }`
|
|
109
|
+
def xml(document_id, **options)
|
|
110
|
+
result = send_call(
|
|
111
|
+
operation(:get, "/v1/documents/{}/xml", document_id, accept: XML_ACCEPT, response_type: :text, options:)
|
|
112
|
+
)
|
|
113
|
+
kind = result.headers["flashpi-xml-kind"]
|
|
114
|
+
_ = { xml: result.data, kind: XML_KINDS.include?(kind) ? kind : nil }
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# The RIDE (the printable PDF) of an authorized document, as a binary String. Raises a
|
|
118
|
+
# ConflictError with code `ride_not_available` while it is still being generated.
|
|
119
|
+
#
|
|
120
|
+
# @return [String]
|
|
121
|
+
def pdf(document_id, **options)
|
|
122
|
+
send_request(
|
|
123
|
+
operation(:get, "/v1/documents/{}/pdf", document_id, accept: PDF_ACCEPT, response_type: :bytes, options:)
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Emails the authorized document (RIDE and XML) again to the address of its request. The new
|
|
128
|
+
# delivery shows in `email.deliveries`; daily limits apply (RateLimitError).
|
|
129
|
+
#
|
|
130
|
+
# @return [Hash{Symbol => Object}] the document
|
|
131
|
+
def send_email(document_id, **options)
|
|
132
|
+
send_request(operation(:post, "/v1/documents/{}/email", document_id, body: {}, options:))
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flashpi
|
|
4
|
+
module Resources
|
|
5
|
+
# Events: what happened to documents, certificates and email sending, newest first.
|
|
6
|
+
class Events < Internal::Resource
|
|
7
|
+
response_methods :list, :get
|
|
8
|
+
|
|
9
|
+
# Lists events, optionally by type, issuer, document or certificate.
|
|
10
|
+
#
|
|
11
|
+
# @return [Flashpi::Page]
|
|
12
|
+
def list(params = nil, **options)
|
|
13
|
+
paginate(operation(:get, "/v1/events", query: params, options:))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Retrieves an event: the same object its webhook delivered.
|
|
17
|
+
#
|
|
18
|
+
# @return [Hash{Symbol => Object}] the event
|
|
19
|
+
def get(event_id, **options)
|
|
20
|
+
send_request(operation(:get, "/v1/events/{}", event_id, options:))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# The API's own status. It needs no API key.
|
|
25
|
+
class Status < Internal::Resource
|
|
26
|
+
response_methods :get
|
|
27
|
+
|
|
28
|
+
# Whether Flashpi is operational.
|
|
29
|
+
#
|
|
30
|
+
# @return [Hash{Symbol => Object}]
|
|
31
|
+
def get(**options)
|
|
32
|
+
send_request(operation(:get, "/v1/status", options:))
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flashpi
|
|
4
|
+
module Resources
|
|
5
|
+
# Creates an issuer from its .p12: upload the certificate, wait while the onboarding is
|
|
6
|
+
# `verifying` until it is `ready` (Flashpi reads the holder, RUC and SRI data) or `rejected`,
|
|
7
|
+
# review the prefill, then complete it.
|
|
8
|
+
#
|
|
9
|
+
# Needs an account-scoped API key with read_write access.
|
|
10
|
+
class IssuerOnboardings < Internal::Resource
|
|
11
|
+
response_methods :create, :get, :complete
|
|
12
|
+
|
|
13
|
+
# Starts an onboarding with a .p12 and its password. It starts `verifying`.
|
|
14
|
+
#
|
|
15
|
+
# @param upload [Hash] `{ file: String or IO, password: String, filename: String }`
|
|
16
|
+
# @return [Hash{Symbol => Object}] the onboarding
|
|
17
|
+
def create(upload, **options)
|
|
18
|
+
form = Internal::Multipart.certificate(upload)
|
|
19
|
+
send_request(operation(:post, "/v1/issuer-onboardings", multipart: form, options:))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Retrieves an onboarding, to follow it while it is `verifying`.
|
|
23
|
+
#
|
|
24
|
+
# @return [Hash{Symbol => Object}] the onboarding
|
|
25
|
+
def get(onboarding_id, **options)
|
|
26
|
+
send_request(operation(:get, "/v1/issuer-onboardings/{}", onboarding_id, options:))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Completes a `ready` onboarding.
|
|
30
|
+
#
|
|
31
|
+
# - For a new RUC, `body` is the issuer to create (as in `issuers.create`): `legalName`,
|
|
32
|
+
# `headOfficeAddress` and `taxProfile` are required. Build it from `onboarding[:prefill]`;
|
|
33
|
+
# the API does not apply the prefill by itself.
|
|
34
|
+
# - When `onboarding[:existingIssuer]` is set, `body` can be left out (`{}` is sent): the
|
|
35
|
+
# certificate is added to that issuer for both modes (a renewal) and the issuer is left as
|
|
36
|
+
# it is.
|
|
37
|
+
# - Send `ruc` when `onboarding[:rucNeedsConfirmation]` is true.
|
|
38
|
+
#
|
|
39
|
+
# @return [Hash{Symbol => Object}] the completed onboarding, with its issuer
|
|
40
|
+
def complete(onboarding_id, body = nil, **options)
|
|
41
|
+
send_request(
|
|
42
|
+
operation(:post, "/v1/issuer-onboardings/{}/complete", onboarding_id, body: body.nil? ? {} : body, options:)
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flashpi
|
|
4
|
+
module Resources
|
|
5
|
+
# Emission points (the second 3-digit series code) of an establishment.
|
|
6
|
+
class EmissionPoints < Internal::Resource
|
|
7
|
+
PATH = "/v1/issuers/{}/establishments/{}/emission-points"
|
|
8
|
+
ITEM = "/v1/issuers/{}/establishments/{}/emission-points/{}"
|
|
9
|
+
|
|
10
|
+
response_methods :create, :list, :get, :delete
|
|
11
|
+
|
|
12
|
+
# @return [Hash{Symbol => Object}] the emission point
|
|
13
|
+
def create(issuer_id, establishment_id, body, **options)
|
|
14
|
+
send_request(operation(:post, PATH, issuer_id, establishment_id, body:, options:))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Lists the emission points of an establishment, by code.
|
|
18
|
+
#
|
|
19
|
+
# @return [Flashpi::Page]
|
|
20
|
+
def list(issuer_id, establishment_id, params = nil, **options)
|
|
21
|
+
paginate(operation(:get, PATH, issuer_id, establishment_id, query: params, options:))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# @return [Hash{Symbol => Object}] the emission point
|
|
25
|
+
def get(issuer_id, establishment_id, emission_point_id, **options)
|
|
26
|
+
send_request(operation(:get, ITEM, issuer_id, establishment_id, emission_point_id, options:))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Deletes an emission point that has no documents.
|
|
30
|
+
#
|
|
31
|
+
# @return [nil]
|
|
32
|
+
def delete(issuer_id, establishment_id, emission_point_id, **options)
|
|
33
|
+
send_request(
|
|
34
|
+
operation(:delete, ITEM, issuer_id, establishment_id, emission_point_id, response_type: :none, options:)
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Establishments (the 3-digit series codes such as `001`) of an issuer.
|
|
40
|
+
class Establishments < Internal::Resource
|
|
41
|
+
PATH = "/v1/issuers/{}/establishments"
|
|
42
|
+
ITEM = "/v1/issuers/{}/establishments/{}"
|
|
43
|
+
|
|
44
|
+
response_methods :create, :list, :get, :update, :delete
|
|
45
|
+
|
|
46
|
+
# @return [EmissionPoints] the emission points of an establishment
|
|
47
|
+
attr_reader :emission_points
|
|
48
|
+
|
|
49
|
+
def initialize(engine)
|
|
50
|
+
super
|
|
51
|
+
@emission_points = EmissionPoints.new(engine)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [Hash{Symbol => Object}] the establishment
|
|
55
|
+
def create(issuer_id, body, **options)
|
|
56
|
+
send_request(operation(:post, PATH, issuer_id, body:, options:))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Lists the establishments of an issuer, by code.
|
|
60
|
+
#
|
|
61
|
+
# @return [Flashpi::Page]
|
|
62
|
+
def list(issuer_id, params = nil, **options)
|
|
63
|
+
paginate(operation(:get, PATH, issuer_id, query: params, options:))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [Hash{Symbol => Object}] the establishment
|
|
67
|
+
def get(issuer_id, establishment_id, **options)
|
|
68
|
+
send_request(operation(:get, ITEM, issuer_id, establishment_id, options:))
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Updates an establishment (only the fields sent).
|
|
72
|
+
#
|
|
73
|
+
# @return [Hash{Symbol => Object}] the establishment
|
|
74
|
+
def update(issuer_id, establishment_id, body, **options)
|
|
75
|
+
send_request(operation(:patch, ITEM, issuer_id, establishment_id, body:, options:))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Deletes an establishment that has no documents, with its emission points.
|
|
79
|
+
#
|
|
80
|
+
# @return [nil]
|
|
81
|
+
def delete(issuer_id, establishment_id, **options)
|
|
82
|
+
send_request(operation(:delete, ITEM, issuer_id, establishment_id, response_type: :none, options:))
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# The .p12 certificates (firmas electrónicas) of an issuer.
|
|
87
|
+
class Certificates < Internal::Resource
|
|
88
|
+
PATH = "/v1/issuers/{}/certificates"
|
|
89
|
+
ITEM = "/v1/issuers/{}/certificates/{}"
|
|
90
|
+
|
|
91
|
+
response_methods :upload, :list, :get
|
|
92
|
+
|
|
93
|
+
# Uploads a .p12 for the issuer, for the mode of the API key only (test or live). To renew
|
|
94
|
+
# the certificate of both modes, start an `issuer_onboardings.create` with it instead.
|
|
95
|
+
#
|
|
96
|
+
# Flashpi checks it in the background: the certificate starts `processing`, then becomes
|
|
97
|
+
# `accepted` (event `certificate.verified`, or `certificate.pending` while its revocation
|
|
98
|
+
# status cannot be checked) or `rejected` (no event: follow it with `get` and read
|
|
99
|
+
# `rejection`).
|
|
100
|
+
#
|
|
101
|
+
# @param upload [Hash] `{ file: String or IO, password: String, filename: String }`
|
|
102
|
+
# @return [Hash{Symbol => Object}] the certificate
|
|
103
|
+
def upload(issuer_id, upload, **options)
|
|
104
|
+
form = Internal::Multipart.certificate(upload)
|
|
105
|
+
send_request(operation(:post, PATH, issuer_id, multipart: form, options:))
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Lists the certificates of an issuer, newest first.
|
|
109
|
+
#
|
|
110
|
+
# @return [Flashpi::Page]
|
|
111
|
+
def list(issuer_id, params = nil, **options)
|
|
112
|
+
paginate(operation(:get, PATH, issuer_id, query: params, options:))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @return [Hash{Symbol => Object}] the certificate
|
|
116
|
+
def get(issuer_id, certificate_id, **options)
|
|
117
|
+
send_request(operation(:get, ITEM, issuer_id, certificate_id, options:))
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# The issuers (RUCs) of the account, with their establishments, emission points and .p12
|
|
122
|
+
# certificates. Needs an account-scoped API key with read_write access, also to read.
|
|
123
|
+
class Issuers < Internal::Resource
|
|
124
|
+
PATH = "/v1/issuers"
|
|
125
|
+
ITEM = "/v1/issuers/{}"
|
|
126
|
+
|
|
127
|
+
response_methods :create, :list, :get, :update, :delete
|
|
128
|
+
|
|
129
|
+
# @return [Establishments] establishments of an issuer, with their emission points
|
|
130
|
+
attr_reader :establishments
|
|
131
|
+
# @return [Certificates] the .p12 certificates of an issuer
|
|
132
|
+
attr_reader :certificates
|
|
133
|
+
|
|
134
|
+
def initialize(engine)
|
|
135
|
+
super
|
|
136
|
+
@establishments = Establishments.new(engine)
|
|
137
|
+
@certificates = Certificates.new(engine)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Creates an issuer. To start from its .p12 instead, see `issuer_onboardings`.
|
|
141
|
+
#
|
|
142
|
+
# @return [Hash{Symbol => Object}] the issuer
|
|
143
|
+
def create(body, **options)
|
|
144
|
+
send_request(operation(:post, PATH, body:, options:))
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Lists the issuers, newest first.
|
|
148
|
+
#
|
|
149
|
+
# @return [Flashpi::Page]
|
|
150
|
+
def list(params = nil, **options)
|
|
151
|
+
paginate(operation(:get, PATH, query: params, options:))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Retrieves an issuer.
|
|
155
|
+
#
|
|
156
|
+
# @return [Hash{Symbol => Object}] the issuer
|
|
157
|
+
def get(issuer_id, **options)
|
|
158
|
+
send_request(operation(:get, ITEM, issuer_id, options:))
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# Updates an issuer's name, tax profile, branding or defaults (only the fields sent).
|
|
162
|
+
#
|
|
163
|
+
# @return [Hash{Symbol => Object}] the issuer
|
|
164
|
+
def update(issuer_id, body, **options)
|
|
165
|
+
send_request(operation(:patch, ITEM, issuer_id, body:, options:))
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Deletes an issuer that has no documents and no certificates, with its establishments,
|
|
169
|
+
# emission points and issuer-scoped API keys. Otherwise 409 `resource_in_use`: certificates
|
|
170
|
+
# cannot be deleted, so an issuer that ever had a .p12 (one from `issuer_onboardings` too)
|
|
171
|
+
# stays.
|
|
172
|
+
#
|
|
173
|
+
# @return [nil]
|
|
174
|
+
def delete(issuer_id, **options)
|
|
175
|
+
send_request(operation(:delete, ITEM, issuer_id, response_type: :none, options:))
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Flashpi
|
|
4
|
+
module Resources
|
|
5
|
+
# Deliveries of events to one endpoint.
|
|
6
|
+
class WebhookDeliveries < Internal::Resource
|
|
7
|
+
PATH = "/v1/webhook-endpoints/{}/deliveries"
|
|
8
|
+
ITEM = "/v1/webhook-endpoints/{}/deliveries/{}"
|
|
9
|
+
|
|
10
|
+
response_methods :list, :get, :replay
|
|
11
|
+
|
|
12
|
+
# Lists deliveries, newest first, optionally by status, event type or event.
|
|
13
|
+
#
|
|
14
|
+
# @return [Flashpi::Page]
|
|
15
|
+
def list(endpoint_id, params = nil, **options)
|
|
16
|
+
paginate(operation(:get, PATH, endpoint_id, query: params, options:))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Retrieves a delivery with its attempts.
|
|
20
|
+
#
|
|
21
|
+
# @return [Hash{Symbol => Object}] the delivery
|
|
22
|
+
def get(endpoint_id, delivery_id, **options)
|
|
23
|
+
send_request(operation(:get, ITEM, endpoint_id, delivery_id, options:))
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Sends the delivery's event again, with the same `webhook-id`.
|
|
27
|
+
#
|
|
28
|
+
# @return [Hash{Symbol => Object}] the delivery
|
|
29
|
+
def replay(endpoint_id, delivery_id, **options)
|
|
30
|
+
send_request(operation(:post, "#{ITEM}/replay", endpoint_id, delivery_id, options:))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The URLs Flashpi sends events to. Needs an account-scoped API key with read_write access.
|
|
35
|
+
# To check the signature of a webhook you receive, use {Flashpi::Webhooks} instead.
|
|
36
|
+
class WebhookEndpoints < Internal::Resource
|
|
37
|
+
PATH = "/v1/webhook-endpoints"
|
|
38
|
+
ITEM = "/v1/webhook-endpoints/{}"
|
|
39
|
+
|
|
40
|
+
response_methods :create, :list, :get, :update, :delete, :get_secret, :rotate_secret, :verify
|
|
41
|
+
|
|
42
|
+
# @return [WebhookDeliveries] the deliveries of an endpoint: attempts, answers and replays
|
|
43
|
+
attr_reader :deliveries
|
|
44
|
+
|
|
45
|
+
def initialize(engine)
|
|
46
|
+
super
|
|
47
|
+
@deliveries = WebhookDeliveries.new(engine)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Creates an endpoint. It stays `pending_verification` until it answers the activation
|
|
51
|
+
# challenge; read its secret with {#get_secret} first, then call {#verify} if needed.
|
|
52
|
+
#
|
|
53
|
+
# @return [Hash{Symbol => Object}] the endpoint
|
|
54
|
+
def create(body, **options)
|
|
55
|
+
send_request(operation(:post, PATH, body:, options:))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Lists the endpoints, newest first.
|
|
59
|
+
#
|
|
60
|
+
# @return [Flashpi::Page]
|
|
61
|
+
def list(params = nil, **options)
|
|
62
|
+
paginate(operation(:get, PATH, query: params, options:))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Retrieves an endpoint.
|
|
66
|
+
#
|
|
67
|
+
# @return [Hash{Symbol => Object}] the endpoint
|
|
68
|
+
def get(endpoint_id, **options)
|
|
69
|
+
send_request(operation(:get, ITEM, endpoint_id, options:))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Updates the URL, events, payload mode, description or `disabled` (only the fields sent).
|
|
73
|
+
#
|
|
74
|
+
# @return [Hash{Symbol => Object}] the endpoint
|
|
75
|
+
def update(endpoint_id, body, **options)
|
|
76
|
+
send_request(operation(:patch, ITEM, endpoint_id, body:, options:))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Deletes an endpoint.
|
|
80
|
+
#
|
|
81
|
+
# @return [nil]
|
|
82
|
+
def delete(endpoint_id, **options)
|
|
83
|
+
send_request(operation(:delete, ITEM, endpoint_id, response_type: :none, options:))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# The signing secret (`whsec_...`) and, during a rotation, when the previous one expires.
|
|
87
|
+
#
|
|
88
|
+
# @return [Hash{Symbol => Object}]
|
|
89
|
+
def get_secret(endpoint_id, **options)
|
|
90
|
+
send_request(operation(:get, "#{ITEM}/secret", endpoint_id, options:))
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Replaces the signing secret. The previous one keeps signing for
|
|
94
|
+
# `previousSecretExpiresInHours` (24 by default, 0 to drop it at once). Read the new secret
|
|
95
|
+
# with {#get_secret}.
|
|
96
|
+
#
|
|
97
|
+
# @return [Hash{Symbol => Object}] the endpoint
|
|
98
|
+
def rotate_secret(endpoint_id, body = nil, **options)
|
|
99
|
+
send_request(operation(:post, "#{ITEM}/rotate-secret", endpoint_id, body:, options:))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Sends the activation challenge (`webhook_endpoint.verification`) to the endpoint again.
|
|
103
|
+
#
|
|
104
|
+
# @return [Hash{Symbol => Object}] the endpoint
|
|
105
|
+
def verify(endpoint_id, **options)
|
|
106
|
+
send_request(operation(:post, "#{ITEM}/verify", endpoint_id, options:))
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|