rail0-sdk 1.7.2 → 1.8.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 +4 -4
- data/README.md +64 -20
- data/lib/rail0/resources/accounts.rb +30 -4
- data/lib/rail0/resources/auth.rb +1 -1
- data/lib/rail0/resources/payments.rb +42 -14
- data/lib/rail0/resources/query.rb +1 -1
- data/lib/rail0/resources/webhooks.rb +12 -0
- data/lib/rail0/types.rb +47 -18
- data/lib/rail0/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eaaadaf08346573c426e649979548088c8cbbb1a2b037e63026c5512fa44feb8
|
|
4
|
+
data.tar.gz: b4eea2d0cd8cb675f2d31e5fbddee08f62fd3421f2cb969db246fc8e4d4338fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9433218dbe34e8d9a6cf7c200aca99d15695940fc099e5347b85e14c9612dbef6d824c303b3cd52e81e00787c25a0c2459cc40aa5e62bd0adb4555294f984816
|
|
7
|
+
data.tar.gz: 5e185810e4e78e7282ceda6760e5c2ee2857bf7c5469806fbb48fdc92fed12592fd8367aa1707bdafc76a52d4d7e65251d3dce36222174434bce9c53125398ff
|
data/README.md
CHANGED
|
@@ -471,6 +471,11 @@ client.payments.create(params, idempotency_key: nil) # or keyword fields
|
|
|
471
471
|
client.payments.get(id)
|
|
472
472
|
client.payments.update(id, description: "Order #42") # → the payment, same shape as get
|
|
473
473
|
client.payments.update(id, description: nil) # nil (or "") clears it
|
|
474
|
+
# The payee's own fields (the payer gets 403 not_the_payee): an internal note never shown
|
|
475
|
+
# to the payer, and the payment's identifier in the merchant's system. Only what you pass
|
|
476
|
+
# is sent.
|
|
477
|
+
client.payments.update(id, merchant_note: "refund agreed by email")
|
|
478
|
+
client.payments.update(id, reference: "ORD-1042", reference_origin: "commercelayer")
|
|
474
479
|
# The description is the only editable field: off-chain, so any status, settled included.
|
|
475
480
|
# Payer or payee only (a non-participant gets 404); over 255 characters is a 422.
|
|
476
481
|
client.payments.list(status: "authorized", disputed: false, chain_id: 84532, sort: "-created_at")
|
|
@@ -644,6 +649,7 @@ client.webhooks.enable(id)
|
|
|
644
649
|
client.webhooks.disable(id)
|
|
645
650
|
client.webhooks.rotate_secret(id) # returns a fresh shared_secret
|
|
646
651
|
client.webhooks.reset_circuit(id)
|
|
652
|
+
client.webhooks.test(id) # signed webhooks.test event now → { delivered:, response_code:, … }; not logged
|
|
647
653
|
# status is "delivered" or "failed" only; payment_id takes a UUID or a rail0_id.
|
|
648
654
|
client.webhooks.event_callbacks(id, status: "failed", response_code: "500")
|
|
649
655
|
client.webhooks.redeliver(id, callback_id) # 202 { status: "queued" } — replay one delivery
|
|
@@ -740,11 +746,13 @@ client.accounts.get(account_id)
|
|
|
740
746
|
client.accounts.update(account_id, email: "ops@merchant.example")
|
|
741
747
|
client.accounts.update(account_id, name: "Merchant Ltd", email: "ops@merchant.example")
|
|
742
748
|
client.accounts.update(account_id, priority_tip: false) # minimum tip on the account's own transactions
|
|
749
|
+
# Payment windows of NEW payments: seconds, or :default (sent as null) for the gateway default.
|
|
750
|
+
client.accounts.update(account_id, authorization_ttl: 2 * 86_400, refund_ttl: :default)
|
|
743
751
|
```
|
|
744
752
|
|
|
745
753
|
`email` is in the response because the holder is this endpoint's only possible caller.
|
|
746
754
|
|
|
747
|
-
`update` needs at least one of `name`/`email`/`priority_tip
|
|
755
|
+
`update` needs at least one of `name`/`email`/`priority_tip`/a payment window (it raises `ArgumentError`
|
|
748
756
|
before sending an empty PATCH, which the gateway would answer with 400). Name and email are
|
|
749
757
|
unique across accounts, so a value another account holds answers **409**. It is a write on
|
|
750
758
|
the account, so a deactivated wallet (403 `wallet_deactivated`) or account (403
|
|
@@ -755,6 +763,15 @@ exposed here.
|
|
|
755
763
|
capture, void, release, refund): `true`, the default, tips the network's suggested priority
|
|
756
764
|
fee; `false` uses the chain's minimum tip (0 on most chains, 25 gwei on Polygon PoS/Amoy) —
|
|
757
765
|
cheaper, slower to confirm under load. The buyer's dispute/close-dispute never read it.
|
|
766
|
+
|
|
767
|
+
**Payment windows** — `authorization_ttl` (how long an authorization can be captured) and
|
|
768
|
+
`refund_ttl` (how long a payment can be refunded or disputed), in seconds — are the deadlines
|
|
769
|
+
the account's **new** payments are created with: its own value, or the gateway default. The
|
|
770
|
+
profile's `payment_windows` says which, and the bounds; outside them, or with the refund
|
|
771
|
+
window less than `min_refund_window` (one day) past the authorization, the gateway answers
|
|
772
|
+
**422** `invalid_payment_windows`. A payment's deadlines are signed into it, so a change moves
|
|
773
|
+
only the payments created afterwards.
|
|
774
|
+
|
|
758
775
|
The account's wallets are a collection under the same path (`client.wallets`), and
|
|
759
776
|
buyer-facing discovery is `client.payment_methods`.
|
|
760
777
|
|
|
@@ -1082,25 +1099,52 @@ uses them everywhere, table-aligned hashes because some literals are tables, and
|
|
|
1082
1099
|
(`retry_on_429`, `eip712`, `secp256k1`) that each spell themselves their own way. A linter
|
|
1083
1100
|
that argues with the codebase teaches people to ignore it.
|
|
1084
1101
|
|
|
1085
|
-
##
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1102
|
+
## Releasing
|
|
1103
|
+
|
|
1104
|
+
A release is an approved pull request: merging it is what publishes.
|
|
1105
|
+
|
|
1106
|
+
1. `bin/release-prepare`, on an up-to-date, clean `main`. It computes the version from the titles of the pull requests merged since the last tag
|
|
1107
|
+
(Conventional Commits): a breaking change — `!` after the type, as in `feat(api)!:`, or a
|
|
1108
|
+
`BREAKING CHANGE:` footer — makes it a major, any `feat` a minor, anything else a patch,
|
|
1109
|
+
and it refuses when nothing merged. `bin/release-prepare minor` (or `patch`, `major`,
|
|
1110
|
+
`X.Y.Z`) sets it by hand instead. The release PR says which pull requests decided it.
|
|
1111
|
+
It then bumps `Rail0::VERSION` and `Gemfile.lock`, writes the release
|
|
1112
|
+
notes from the pull requests merged since the last tag, and opens
|
|
1113
|
+
`chore(release): vX.Y.Z`. `--dry-run` prints all of it and writes nothing.
|
|
1114
|
+
|
|
1115
|
+
**Or on a feature branch**, to release a change in the same review: run it on a clean
|
|
1116
|
+
branch that is pushed, contains `origin/main` and has an open pull request into `main`.
|
|
1117
|
+
The bump is committed and pushed on that branch (`chore(release): vX.Y.Z`), the pull
|
|
1118
|
+
request's own title counts toward the version and gets a line in the notes, and the
|
|
1119
|
+
notes go into its description between `<!-- release:start -->` markers — the text above
|
|
1120
|
+
them is kept. Re-run it after new commits or a merge of `main`: it refreshes the version
|
|
1121
|
+
and the notes instead of bumping twice. One approval then covers the change and its
|
|
1122
|
+
release.
|
|
1123
|
+
2. Review the pull request (edit the notes in its body if needed), approve and merge it.
|
|
1124
|
+
The approval must come from a reviewer **other than the pull request's author**, on its
|
|
1125
|
+
final commit: release.yml checks it before publishing anything and stops otherwise —
|
|
1126
|
+
an admin merge that bypassed the review, a direct push to `main` or a resume of an
|
|
1127
|
+
unapproved release publishes nothing.
|
|
1128
|
+
3. `.github/workflows/release.yml` runs on that push to `main`: CI again on the release
|
|
1129
|
+
commit, `gem push` through RubyGems **Trusted Publishing**, then the tag `vX.Y.Z` and
|
|
1130
|
+
the GitHub release (notes from the pull request), then a Slack message.
|
|
1131
|
+
|
|
1132
|
+
A merge that does not change the version releases nothing. If a run stops halfway, Actions
|
|
1133
|
+
→ release → Run workflow (on `main`) resumes it: what is already on RubyGems.org or already
|
|
1134
|
+
tagged is skipped. `rake release` is disabled (it would tag and push from a laptop), and no
|
|
1135
|
+
API key exists anywhere: RubyGems.org trusts only `release.yml` in this repo.
|
|
1136
|
+
|
|
1137
|
+
One-time settings (repository admins):
|
|
1138
|
+
|
|
1139
|
+
- environment `release` (Settings → Environments), deployment limited to `main`;
|
|
1140
|
+
- on rubygems.org, rail0-sdk's trusted publisher (repository `commercelayer/rail0-ruby`,
|
|
1141
|
+
workflow `release.yml`) bound to environment `release` — only once the new
|
|
1142
|
+
`release.yml` is on `main`;
|
|
1143
|
+
- a tag ruleset on `v*`: block updates and deletions, restrict creation to GitHub Actions
|
|
1144
|
+
and admins;
|
|
1145
|
+
- branch protection on `main`: required `ci` check (`spec`), "Include administrators";
|
|
1146
|
+
- the Slack channel: `release.yml` posts through the `PIPELINE_SLACK_CHANNEL_WEBHOOK_URL`
|
|
1147
|
+
secret, named in one place (the `announce` job).
|
|
1104
1148
|
|
|
1105
1149
|
## License
|
|
1106
1150
|
|
|
@@ -30,12 +30,16 @@ module Rail0
|
|
|
30
30
|
|
|
31
31
|
# The account's own profile.
|
|
32
32
|
# @param account_id [String] The account UUID — must be the one this JWT belongs to.
|
|
33
|
-
# @return [Hash] `id`, `name`, `email`, `priority_tip`, `
|
|
33
|
+
# @return [Hash] `id`, `name`, `email`, `priority_tip`, `authorization_ttl`, `refund_ttl`,
|
|
34
|
+
# `payment_windows`, `created_at`, `updated_at`.
|
|
34
35
|
# `email` is part of the response because only the account's owner, or an operator,
|
|
35
36
|
# can read it. `priority_tip` is the fee setting of the account's OWN transactions
|
|
36
37
|
# (authorize, capture, void, release, refund): true, the default, tips the network's
|
|
37
38
|
# suggested priority fee; false uses the chain's minimum tip — 0 on most chains,
|
|
38
39
|
# 25 gwei on Polygon PoS/Amoy. The buyer's dispute/close_dispute never read it.
|
|
40
|
+
# `authorization_ttl` / `refund_ttl` are the payment windows the account's NEW
|
|
41
|
+
# payments are created with, in seconds — its own or the gateway default;
|
|
42
|
+
# `payment_windows` says which, and the bounds a new value must fit.
|
|
39
43
|
def get(account_id)
|
|
40
44
|
http.get("/accounts/#{segment(account_id)}")
|
|
41
45
|
end
|
|
@@ -48,6 +52,10 @@ module Rail0
|
|
|
48
52
|
# are UNIQUE across accounts, so a value another account already holds answers 409.
|
|
49
53
|
# `priority_tip: false` is a value, not an absence: it is sent as false and switches
|
|
50
54
|
# the account's own transactions to the chain's minimum tip; nil leaves it alone.
|
|
55
|
+
# The payment windows take a number of seconds, or `:default` to put one back on the
|
|
56
|
+
# gateway default (sent as null); nil leaves it alone. Outside the bounds in
|
|
57
|
+
# `payment_windows`, or closer than its `min_refund_window`, the gateway answers 422
|
|
58
|
+
# invalid_payment_windows. A change moves only the payments created afterwards.
|
|
51
59
|
#
|
|
52
60
|
# This is a write on the account itself, so a deactivated wallet (403
|
|
53
61
|
# wallet_deactivated) or a deactivated account (403 account_deactivated) cannot
|
|
@@ -60,17 +68,35 @@ module Rail0
|
|
|
60
68
|
# @param priority_tip [Boolean, nil] Tip the network's suggested priority fee on the
|
|
61
69
|
# account's own transactions (true, the gateway default) or the chain's minimum tip
|
|
62
70
|
# (false). Owner or admin.
|
|
71
|
+
# @param authorization_ttl [Integer, :default, nil] Authorization (capture) window of
|
|
72
|
+
# new payments, in seconds, or :default. Owner or admin.
|
|
73
|
+
# @param refund_ttl [Integer, :default, nil] Refund and dispute window of new
|
|
74
|
+
# payments, in seconds, or :default. Owner or admin.
|
|
63
75
|
# @return [Hash] the updated profile, same shape as {get}.
|
|
64
|
-
# @raise [ArgumentError] when
|
|
65
|
-
|
|
76
|
+
# @raise [ArgumentError] when no field is given, or a window is neither an Integer
|
|
77
|
+
# nor :default.
|
|
78
|
+
def update(account_id, name: nil, email: nil, priority_tip: nil, authorization_ttl: nil, refund_ttl: nil)
|
|
66
79
|
body = {}
|
|
67
80
|
body[:name] = name unless name.nil?
|
|
68
81
|
body[:email] = email unless email.nil?
|
|
69
82
|
body[:priority_tip] = priority_tip unless priority_tip.nil?
|
|
70
|
-
|
|
83
|
+
{ authorization_ttl: authorization_ttl, refund_ttl: refund_ttl }.each do |key, value|
|
|
84
|
+
body[key] = window(key, value) unless value.nil?
|
|
85
|
+
end
|
|
86
|
+
raise ArgumentError, "at least one of name, email, priority_tip or a payment window is required" if body.empty?
|
|
71
87
|
|
|
72
88
|
http.patch("/accounts/#{segment(account_id)}", body)
|
|
73
89
|
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
# A payment window as the gateway takes it: whole seconds, or null for the default.
|
|
94
|
+
def window(key, value)
|
|
95
|
+
return if value == :default
|
|
96
|
+
return value if value.is_a?(Integer)
|
|
97
|
+
|
|
98
|
+
raise ArgumentError, "#{key} must be an Integer number of seconds or :default"
|
|
99
|
+
end
|
|
74
100
|
end
|
|
75
101
|
end
|
|
76
102
|
end
|
data/lib/rail0/resources/auth.rb
CHANGED
|
@@ -58,7 +58,7 @@ module Rail0
|
|
|
58
58
|
#
|
|
59
59
|
# +admin+ is true only for an account holding the operator (administrators)
|
|
60
60
|
# grant: the gateway adds the field on an admin's session alone, and it is
|
|
61
|
-
#
|
|
61
|
+
# normalized here to a boolean so a standard login reads false rather than nil.
|
|
62
62
|
# Visibility only — every gated route re-checks the grant per request.
|
|
63
63
|
def verify(message:, signature:)
|
|
64
64
|
session = http.post("/auth", { message: message, signature: signature })
|
|
@@ -13,6 +13,11 @@ module Rail0
|
|
|
13
13
|
# step (e.g. MetaMask) skip the local signer and report the hash via
|
|
14
14
|
# {submit_by_hash} instead.
|
|
15
15
|
class Payments
|
|
16
|
+
# The default of {update}'s keywords: "not passed", told apart from an explicit +nil+
|
|
17
|
+
# (which is sent, as JSON null, and clears the field).
|
|
18
|
+
UNSET = Object.new.freeze
|
|
19
|
+
private_constant :UNSET
|
|
20
|
+
|
|
16
21
|
include Query
|
|
17
22
|
|
|
18
23
|
# Operations accepted by the prepare/submit endpoints.
|
|
@@ -62,6 +67,10 @@ module Rail0
|
|
|
62
67
|
# `last_error_code`, false = none.
|
|
63
68
|
# @param expiring_within [Integer, nil] scope "all" only: `authorized` payments whose
|
|
64
69
|
# `authorization_expiry` falls within this many SECONDS from now (1..90 days).
|
|
70
|
+
# @param reference [String, nil] Only payments with this reference — the payment's
|
|
71
|
+
# identifier in the merchant's own system (exact match).
|
|
72
|
+
# @param reference_origin [String, nil] Only payments whose reference comes from this
|
|
73
|
+
# system (case-insensitive).
|
|
65
74
|
# @param sort [String, nil] Comma-separated sort fields; prefix with - for desc.
|
|
66
75
|
# @param page [Integer, nil] Page number (1-based; 1..1,000,000, 400 outside).
|
|
67
76
|
# @param per_page [Integer, nil] Items per page (max 100).
|
|
@@ -74,9 +83,11 @@ module Rail0
|
|
|
74
83
|
def list(status: nil, mode: nil, payer: nil, payee: nil, token: nil, rail0_id: nil,
|
|
75
84
|
chain_id: nil, disputed: nil, operation: nil, min_amount: nil, max_amount: nil,
|
|
76
85
|
created_from: nil, created_to: nil, scope: nil, account_id: nil, has_error: nil,
|
|
77
|
-
expiring_within: nil,
|
|
86
|
+
expiring_within: nil, reference: nil, reference_origin: nil, sort: nil, page: nil,
|
|
87
|
+
per_page: nil)
|
|
78
88
|
query = build_query(status: status, mode: mode, payer: payer, payee: payee, token: token,
|
|
79
|
-
rail0_id: rail0_id,
|
|
89
|
+
rail0_id: rail0_id, reference: reference, reference_origin: reference_origin,
|
|
90
|
+
chain_id: chain_id, disputed: disputed,
|
|
80
91
|
operation: operation,
|
|
81
92
|
min_amount: min_amount, max_amount: max_amount,
|
|
82
93
|
created_from: created_from, created_to: created_to,
|
|
@@ -97,7 +108,10 @@ module Rail0
|
|
|
97
108
|
# create(chain_id: 84532, mode: "authorize", amount: "100.00", token: "0x…", payer: "0x…", payee: "0x…")
|
|
98
109
|
# create({ chain_id: 84532, ... }, idempotency_key: "order-42")
|
|
99
110
|
#
|
|
100
|
-
# @param params [Hash, nil] chain_id, mode, amount, token, payer, payee, description (opt),
|
|
111
|
+
# @param params [Hash, nil] chain_id, mode, amount, token, payer, payee, description (opt),
|
|
112
|
+
# metadata (opt), reference (opt — the payment's identifier in the merchant's own
|
|
113
|
+
# system, max 128 characters, not unique, an idempotency term), reference_origin (opt
|
|
114
|
+
# — which system: a lowercase slug, e.g. "commercelayer"; needs a reference).
|
|
101
115
|
# @param idempotency_key [String, nil] Optional Idempotency-Key header value.
|
|
102
116
|
# @param fields [Hash] Field keywords, used when +params+ is omitted.
|
|
103
117
|
# @return [Hash]
|
|
@@ -116,22 +130,36 @@ module Rail0
|
|
|
116
130
|
http.get("/payments/#{segment(id)}")
|
|
117
131
|
end
|
|
118
132
|
|
|
119
|
-
# Set or clear a payment's
|
|
133
|
+
# Set or clear a payment's off-chain fields (PATCH /payments/{id}).
|
|
134
|
+
#
|
|
135
|
+
# Off-chain metadata, so it can change at any status, settled payments included. Only
|
|
136
|
+
# a participant (the payer or the payee) may call it — a non-participant gets the same
|
|
137
|
+
# 404 as an unknown id, and a deactivated caller wallet a 403 `wallet_deactivated`.
|
|
138
|
+
#
|
|
139
|
+
# Only the keywords you PASS are sent, and at least one is required (ArgumentError
|
|
140
|
+
# first, rather than the gateway's 400). +nil+ or +""+ clears a field.
|
|
120
141
|
#
|
|
121
|
-
#
|
|
122
|
-
#
|
|
123
|
-
# payer
|
|
124
|
-
#
|
|
142
|
+
# - +description:+ either party, max 255 characters (422 over).
|
|
143
|
+
# - +merchant_note:+ the PAYEE's internal note, max 2000 characters — never shown to
|
|
144
|
+
# the payer, not in webhooks.
|
|
145
|
+
# - +reference:+ / +reference_origin:+ the payment's identifier in the merchant's own
|
|
146
|
+
# system and which system; the payee corrects them, and clearing the reference
|
|
147
|
+
# clears its origin.
|
|
125
148
|
#
|
|
126
|
-
#
|
|
127
|
-
# which clears it (as does +""+). Over 255 characters is a 422.
|
|
128
|
-
# (rail0-gateway#373)
|
|
149
|
+
# The last three are the payee's: the payer gets 403 `not_the_payee`.
|
|
129
150
|
#
|
|
130
151
|
# @param id [String] Payment UUID or rail0_id.
|
|
131
|
-
# @param description [String, nil] The new description; +nil+ or +""+ clears it.
|
|
132
152
|
# @return [Hash] The updated payment, the same shape {get} returns.
|
|
133
|
-
|
|
134
|
-
|
|
153
|
+
# @raise [ArgumentError] when no field is given.
|
|
154
|
+
def update(id, description: UNSET, merchant_note: UNSET, reference: UNSET, reference_origin: UNSET)
|
|
155
|
+
body = { description: description, merchant_note: merchant_note, reference: reference,
|
|
156
|
+
reference_origin: reference_origin }.reject { |_, v| v.equal?(UNSET) }
|
|
157
|
+
if body.empty?
|
|
158
|
+
raise ArgumentError,
|
|
159
|
+
"at least one of description, merchant_note, reference or reference_origin is required"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
http.patch("/payments/#{segment(id)}", body)
|
|
135
163
|
end
|
|
136
164
|
|
|
137
165
|
# List on-chain transactions for a payment.
|
|
@@ -11,7 +11,7 @@ module Rail0
|
|
|
11
11
|
# segment the same way ({#segment}).
|
|
12
12
|
module Query
|
|
13
13
|
# Segments that would not stay put once interpolated: "." and ".." are dot
|
|
14
|
-
# segments that a URL
|
|
14
|
+
# segments that a URL normalizer (a proxy, a CDN, the server's router) may
|
|
15
15
|
# resolve away, and an empty one collapses the path onto its parent.
|
|
16
16
|
UNSAFE_SEGMENTS = ["", ".", ".."].freeze
|
|
17
17
|
private_constant :UNSAFE_SEGMENTS
|
|
@@ -127,6 +127,18 @@ module Rail0
|
|
|
127
127
|
http.put("/webhooks/#{segment(id)}/reset_circuit")
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
# Send a test event to the webhook's callback now and report what it did
|
|
131
|
+
# (POST /webhooks/{id}/test). The event has topic "webhooks.test", +test: true+ and
|
|
132
|
+
# no payment, and is signed and delivered like a real one. Synchronous, one attempt,
|
|
133
|
+
# not logged in {event_callbacks} and not counted by the circuit breaker; it works on
|
|
134
|
+
# a disabled webhook. A refusal by the endpoint is a result, not an error.
|
|
135
|
+
# @param id [String] Webhook UUID.
|
|
136
|
+
# @return [Hash] +delivered+, +response_code+, +response_message+, +error_reason+,
|
|
137
|
+
# +duration_ms+.
|
|
138
|
+
def test(id)
|
|
139
|
+
http.post("/webhooks/#{segment(id)}/test", {})
|
|
140
|
+
end
|
|
141
|
+
|
|
130
142
|
# List delivery attempts for a webhook.
|
|
131
143
|
# @param id [String] Webhook UUID.
|
|
132
144
|
# @param status [String, nil] Filter by delivery status: "delivered" or "failed" only
|
data/lib/rail0/types.rb
CHANGED
|
@@ -265,6 +265,9 @@ module Rail0
|
|
|
265
265
|
:last_error_code, # Decoded reason of the last failed on-chain attempt; null once the payment makes forward progress. Non-null means the latest attempt failed.
|
|
266
266
|
:last_error_message, # Human-readable form of last_error_code.
|
|
267
267
|
:description,
|
|
268
|
+
:reference, # This payment's identifier in the merchant's own system; set at create, correctable by the payee.
|
|
269
|
+
:reference_origin, # The system the reference comes from, a lowercase slug (e.g. commercelayer).
|
|
270
|
+
:merchant_note, # The payee's internal note (PATCH /payments/{id}). Present only when the session is the payment's PAYEE, and on the operator's Full view; absent for the payer.
|
|
268
271
|
:metadata,
|
|
269
272
|
:signed_at, # When the payer signature was stored (null while unsigned).
|
|
270
273
|
:created_at, # String
|
|
@@ -291,6 +294,16 @@ module Rail0
|
|
|
291
294
|
keyword_init: true
|
|
292
295
|
)
|
|
293
296
|
|
|
297
|
+
# What the callback did with a test event (POST /webhooks/{id}/test).
|
|
298
|
+
WebhookTestResult = Struct.new(
|
|
299
|
+
:delivered, # Boolean — The endpoint answered 2xx.
|
|
300
|
+
:response_code, # The HTTP status it answered; null when no response came (see error_reason).
|
|
301
|
+
:response_message, # Up to 1000 printable characters of its response body.
|
|
302
|
+
:error_reason, # Why no response came: a refused address, a TLS or connection error, the deadline.
|
|
303
|
+
:duration_ms, # Integer — How long the attempt took.
|
|
304
|
+
keyword_init: true
|
|
305
|
+
)
|
|
306
|
+
|
|
294
307
|
Transaction = Struct.new(
|
|
295
308
|
:id, # String
|
|
296
309
|
:payment_id, # String
|
|
@@ -336,32 +349,48 @@ module Rail0
|
|
|
336
349
|
)
|
|
337
350
|
|
|
338
351
|
# The account's own profile as the holder reads it (GET) and as a PATCH returns it — id, name,
|
|
339
|
-
# email, priority_tip, timestamps. Deliberately no admin/role field: the operator
|
|
340
|
-
# separate table, so a standard account's profile carries no trace of that axis. An
|
|
341
|
-
# any account gets the whole record plus `admin` instead, which is a different shape
|
|
342
|
-
# one.
|
|
352
|
+
# email, priority_tip, payment windows, timestamps. Deliberately no admin/role field: the operator
|
|
353
|
+
# grant lives in a separate table, so a standard account's profile carries no trace of that axis. An
|
|
354
|
+
# ADMIN reading any account gets the whole record plus `admin` instead, which is a different shape
|
|
355
|
+
# and not this one.
|
|
343
356
|
Account = Struct.new(
|
|
344
|
-
:id,
|
|
345
|
-
:name,
|
|
357
|
+
:id, # String
|
|
358
|
+
:name, # String
|
|
346
359
|
:email,
|
|
347
|
-
:priority_tip,
|
|
348
|
-
:
|
|
349
|
-
:
|
|
360
|
+
:priority_tip, # Boolean — Whether the merchant's own transactions tip the network's suggested priority fee (true, the default) or the chain's minimum tip (false: 0 on most chains, 25 gwei on Polygon PoS/Amoy). The buyer's dispute/close_dispute never read it.
|
|
361
|
+
:authorization_ttl, # Integer — Seconds an authorization of the account's new payments stays capturable after the payment is created: the account's own value, or the gateway default (AUTHORIZATION_TTL).
|
|
362
|
+
:refund_ttl, # Integer — Seconds the account's new payments stay refundable, and open to a dispute, after they are created: the account's own value, or the gateway default (REFUND_TTL).
|
|
363
|
+
:payment_windows, # PaymentWindows
|
|
364
|
+
:created_at, # String
|
|
365
|
+
:updated_at, # String
|
|
366
|
+
keyword_init: true
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
# How the account's windows are set and what a new value must meet: per window, whether it is the
|
|
370
|
+
# account's own (custom) or the default, the default, and the bounds. The refund window has no floor
|
|
371
|
+
# of its own: the pair must keep refund_ttl - authorization_ttl >= min_refund_window.
|
|
372
|
+
PaymentWindows = Struct.new(
|
|
373
|
+
:authorization_ttl, # Hash
|
|
374
|
+
:refund_ttl, # Hash
|
|
375
|
+
:min_refund_window, # Integer
|
|
350
376
|
keyword_init: true
|
|
351
377
|
)
|
|
352
378
|
|
|
353
379
|
# The whole account record, as an operator reads it (Full entity: GET /accounts, and GET/PATCH
|
|
354
380
|
# /accounts/{account_id} for an admin session): every column plus `admin` and the derived `status`.
|
|
355
381
|
AccountFull = Struct.new(
|
|
356
|
-
:id,
|
|
357
|
-
:name,
|
|
358
|
-
:email,
|
|
359
|
-
:active,
|
|
360
|
-
:priority_tip,
|
|
361
|
-
:
|
|
362
|
-
:
|
|
363
|
-
:
|
|
364
|
-
:
|
|
382
|
+
:id, # String
|
|
383
|
+
:name, # String
|
|
384
|
+
:email, # String — Stored lowercase.
|
|
385
|
+
:active, # Boolean — The operator's switch. false = deactivated.
|
|
386
|
+
:priority_tip, # Boolean — The merchant's fee setting (see Account.priority_tip).
|
|
387
|
+
:authorization_ttl, # Integer — Seconds an authorization of the account's new payments stays capturable after the payment is created: the account's own value, or the gateway default (AUTHORIZATION_TTL).
|
|
388
|
+
:refund_ttl, # Integer — Seconds the account's new payments stay refundable, and open to a dispute, after they are created: the account's own value, or the gateway default (REFUND_TTL).
|
|
389
|
+
:payment_windows, # PaymentWindows
|
|
390
|
+
:created_at, # String
|
|
391
|
+
:updated_at, # String
|
|
392
|
+
:admin, # Boolean — Whether the account holds the operator grant (a row in administrators).
|
|
393
|
+
:status, # String — One-word reading of active: active, or deactivated (switched off by an operator).
|
|
365
394
|
keyword_init: true
|
|
366
395
|
)
|
|
367
396
|
|
data/lib/rail0/version.rb
CHANGED
|
@@ -5,5 +5,5 @@ module Rail0
|
|
|
5
5
|
# consumed by path from a sibling checkout, where the number bought nothing: no registry
|
|
6
6
|
# ever served a 1.x, no tag was ever cut, and the one consumer resolves the working tree.
|
|
7
7
|
# Publishing from 1.2.0 would have implied two releases nobody can install.
|
|
8
|
-
VERSION = "1.
|
|
8
|
+
VERSION = "1.8.1"
|
|
9
9
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rail0-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.8.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Commerce Layer
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: logger
|