@timbro/payments 0.1.0-next.1 → 0.1.0-next.2
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.
- package/README.md +94 -5
- package/dist/generated/openapi.d.ts +6034 -2784
- package/dist/generated/openapi.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/payments-client.d.ts +24 -2
- package/dist/payments-client.d.ts.map +1 -1
- package/dist/payments-client.js +28 -5
- package/dist/payments-client.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# `@timbro/payments`
|
|
2
2
|
|
|
3
|
-
Node 24 ESM SDK for merchant Payments
|
|
3
|
+
Node 24 ESM SDK for merchant Payments, their payment-linked fiscal documents, and the merchant
|
|
4
|
+
business that onboards them.
|
|
5
|
+
|
|
6
|
+
`apiKey` takes either merchant key. A secret key (`sk_test_…` or `sk_live_…`) creates and reads
|
|
7
|
+
Payments; an administrator key, which the owner creates and names in the Workspace business
|
|
8
|
+
settings, also administers the business and its Merchant Accounts. Keys are additive: creating another one,
|
|
9
|
+
of either kind, never retires the keys you already use.
|
|
4
10
|
|
|
5
11
|
Each Payment create request supplies one immutable `source` coordinate and one tagged `sale` snapshot. `source.id` and `source.version` remain stable across credential rotation and retries; `idempotencyKey` remains the HTTP command retry key.
|
|
6
12
|
|
|
@@ -13,7 +19,7 @@ Use `amount_only` when the adapter has only a payable amount. This variant canno
|
|
|
13
19
|
```ts
|
|
14
20
|
import { createTimbroPayments } from "@timbro/payments";
|
|
15
21
|
|
|
16
|
-
const timbro = createTimbroPayments({
|
|
22
|
+
const timbro = createTimbroPayments({ apiKey: process.env.TIMBRO_PAYMENTS_SECRET_KEY });
|
|
17
23
|
const payment = await timbro.payments.create({
|
|
18
24
|
idempotencyKey: "create-order-123",
|
|
19
25
|
source: { id: "odoo:pos.order:123", version: "7" },
|
|
@@ -166,13 +172,96 @@ CardNet Ztrans full refunds are implemented for test mode with deterministic rec
|
|
|
166
172
|
|
|
167
173
|
Before collecting the rest of a merchant's onboarding details, verify its RNC
|
|
168
174
|
against the current DGII directory snapshot. The operation is read-only and
|
|
169
|
-
returns the canonical taxpayer name for the form to use.
|
|
170
|
-
|
|
171
|
-
authentication are separate onboarding work:
|
|
175
|
+
returns the canonical taxpayer name for the form to use. Either merchant key
|
|
176
|
+
calls it:
|
|
172
177
|
|
|
173
178
|
```ts
|
|
174
179
|
const verification = await timbro.merchantOnboarding.verifyRnc({ rnc: "101000155" });
|
|
175
180
|
// verification.legalName is the Directory's registered name.
|
|
176
181
|
```
|
|
177
182
|
|
|
183
|
+
## Onboard the merchant business
|
|
184
|
+
|
|
185
|
+
The business belongs to the key's tenant, so no call names it. Claiming the business and handing
|
|
186
|
+
over the certificate file stay with the person who holds them; everything else is one resource.
|
|
187
|
+
Read it, act on the first requirement your integration owns, and read it again:
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
const admin = createTimbroPayments({ apiKey: process.env.TIMBRO_ADMIN_KEY });
|
|
191
|
+
|
|
192
|
+
let business = await admin.merchantBusiness.retrieve();
|
|
193
|
+
business = await admin.merchantBusiness.update({
|
|
194
|
+
capabilities: { electronicInvoicing: { requested: true } },
|
|
195
|
+
fiscalDetails: {
|
|
196
|
+
commercialName: "Café Duarte",
|
|
197
|
+
address: "Calle El Conde 101",
|
|
198
|
+
location: { municipalityCode: "320100" },
|
|
199
|
+
phone: "+18095550142",
|
|
200
|
+
defaultIncomeType: "01",
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
business = await admin.merchantBusiness.importSigningCertificate({
|
|
204
|
+
certificateP12Base64: p12.toString("base64"),
|
|
205
|
+
password: certificatePassword,
|
|
206
|
+
});
|
|
207
|
+
// Timbro sends the TesteCF document itself; poll until DGII answers.
|
|
208
|
+
business = await admin.merchantBusiness.retrieve();
|
|
209
|
+
if (business.capabilities.electronicInvoicing.status === "active") {
|
|
210
|
+
const { credential, fiscalOrigin } = await admin.merchantBusiness.issueSandboxCredential({
|
|
211
|
+
idempotencyKey: "sandbox-credential-1",
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Each entry of `business.requirements` names its `owner`: `merchant` entries are yours to resolve,
|
|
217
|
+
and `field` points into the representation when a field answers it. `dgii` and `timbro` entries
|
|
218
|
+
wait, `provider` entries wait on the acquirer, and `operator` entries need Timbro support. `update` replaces each member it carries, and
|
|
219
|
+
an `expectedRevision` refuses a stale write with `merchant_business_revision_conflict`.
|
|
220
|
+
Electronic invoicing onboards against DGII's TesteCF environment only. The certificate import is
|
|
221
|
+
the one call that carries the PKCS#12 archive; send it only from a machine that already holds the
|
|
222
|
+
file, and do not resend it once `fiscalSetup.signingCertificate.sha256` matches.
|
|
223
|
+
`retryTestFiscalDocument()` sends a new TesteCF document only when none is processing or
|
|
224
|
+
accepted. `issueSandboxCredential` returns the ERP credential once and retires the one issued
|
|
225
|
+
before it; the same `idempotencyKey` replays it.
|
|
226
|
+
|
|
227
|
+
## Every published operation
|
|
228
|
+
|
|
229
|
+
`timbro.client` is the typed low-level client for every operation in the published document,
|
|
230
|
+
with the same key and transport. Requests, responses, and Problem bodies are typed from the
|
|
231
|
+
generated `paths`, `components`, and `operations`, which the package also exports:
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
import { createTimbroPayments, type components } from "@timbro/payments";
|
|
235
|
+
|
|
236
|
+
const { data, error, response } = await timbro.client.POST("/v1/api_keys/rotate", {
|
|
237
|
+
params: { header: { "idempotency-key": "rotate-2026-09" } },
|
|
238
|
+
});
|
|
239
|
+
if (error !== undefined) {
|
|
240
|
+
console.error(response.status, error.code);
|
|
241
|
+
}
|
|
242
|
+
type Requirement = components["schemas"]["MerchantBusinessRequirement"];
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The facade covers every published merchant operation except `rotateApiKey`,
|
|
246
|
+
`createPreCreationJourneyRequest`, and `chooseFiscalDocument`, which the client reaches directly.
|
|
247
|
+
|
|
248
|
+
## From a terminal
|
|
249
|
+
|
|
250
|
+
The published document is served at `https://api.timbro.dev/openapi.json`, so a
|
|
251
|
+
generic OpenAPI client needs nothing from Timbro. With [Restish](https://rest.sh), register the
|
|
252
|
+
API once and pass a test administrator key on each call, from an environment variable rather than
|
|
253
|
+
your shell history:
|
|
254
|
+
|
|
255
|
+
```sh
|
|
256
|
+
restish api configure timbro https://api.timbro.dev
|
|
257
|
+
restish timbro retrieve-merchant-business -H "Authorization: Bearer $TIMBRO_ADMIN_KEY"
|
|
258
|
+
restish timbro update-merchant-business -H "Authorization: Bearer $TIMBRO_ADMIN_KEY" \
|
|
259
|
+
'capabilities.electronicInvoicing.requested: true'
|
|
260
|
+
jq -n --arg p12 "$(base64 -w0 certificate.p12)" --arg password "$CERTIFICATE_PASSWORD" \
|
|
261
|
+
'{certificateP12Base64: $p12, password: $password}' |
|
|
262
|
+
restish timbro import-merchant-business-signing-certificate -H "Authorization: Bearer $TIMBRO_ADMIN_KEY"
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Restish names each command after the operation ID in kebab case. Timbro ships no CLI of its own.
|
|
266
|
+
|
|
178
267
|
`@timbro/payments` serves payment consumers. `@timbro/sdk` is the consumer-neutral fiscal SDK for ERPs, POS systems, payment systems, and other direct fiscal integrations. Neither package depends on or re-exports the other.
|