@secureprocessing/node 0.2.0 → 0.2.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.
- package/README.md +26 -12
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +15 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,21 +4,24 @@ Card payments for Belize. Zero dependencies; runs on Node 20+, Deno, Bun and Clo
|
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install @secureprocessing/node@0.2.1
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
The same version is served from our own domain, byte for byte — npm publishes the very file at this
|
|
12
|
+
URL, so either one records the same hash in your lockfile:
|
|
8
13
|
|
|
9
14
|
```bash
|
|
10
|
-
npm install https://secureprocessing.app/sdk/secureprocessing-node-0.2.
|
|
15
|
+
npm install https://secureprocessing.app/sdk/secureprocessing-node-0.2.1.tgz
|
|
11
16
|
```
|
|
12
17
|
|
|
13
|
-
It installs as `@secureprocessing/node
|
|
14
|
-
works unchanged
|
|
15
|
-
on the npm registry, `npm install @secureprocessing/node@0.2.0` gives you these same bytes;
|
|
16
|
-
[the docs](https://docs.secureprocessing.app/sdk) say which of the two to use today.
|
|
18
|
+
It installs as `@secureprocessing/node` either way, so every `import ... from "@secureprocessing/node"`
|
|
19
|
+
below works unchanged. `pnpm add` takes the same name or URL.
|
|
17
20
|
|
|
18
21
|
Deno, including Supabase Edge Functions:
|
|
19
22
|
|
|
20
23
|
```ts
|
|
21
|
-
import { SecureProcessing } from "https://secureprocessing.app/sdk/0.2.
|
|
24
|
+
import { SecureProcessing } from "https://secureprocessing.app/sdk/0.2.1/index.js";
|
|
22
25
|
|
|
23
26
|
// Deno 2 imports only from its built-in allow-list unless told otherwise:
|
|
24
27
|
// deno run --allow-net --allow-env --allow-import=secureprocessing.app your-script.ts
|
|
@@ -153,6 +156,13 @@ try {
|
|
|
153
156
|
(on the bank's page, or in 3-D Secure). Nothing was changed, the message says when to try again,
|
|
154
157
|
and `err.isPaymentInProgress` is `true`. The client never retries it — it is minutes, not a backoff.
|
|
155
158
|
|
|
159
|
+
`400 refund_not_yet_possible` (`err.isRefundNotYetPossible`) is a partial refund on a payment the
|
|
160
|
+
bank has not settled yet. The bank definitely refused and nothing was refunded. It is **the one
|
|
161
|
+
error to retry under a NEW idempotency key**, once the payment has settled — usually by the next
|
|
162
|
+
business day: the original key stays bound to this answer for 24 hours and would only replay it.
|
|
163
|
+
Calling the method again WITHOUT `idempotencyKey` already sends a fresh key, so that is all the
|
|
164
|
+
retry needs. If nothing has been refunded yet, a full refund can be made now.
|
|
165
|
+
|
|
156
166
|
🔴 `500 outcome_unknown` (`err.isOutcomeUnknown`) means the request reached the bank and the result
|
|
157
167
|
could not be confirmed: **the money may have moved.** Never repeat it under a new idempotency key —
|
|
158
168
|
that is a second charge or refund. Retrying under the same key (`err.idempotencyKey`, which the
|
|
@@ -231,11 +241,15 @@ whatever today's is.
|
|
|
231
241
|
|
|
232
242
|
Keys beginning `sk_test_` never move real money. Test cards:
|
|
233
243
|
|
|
234
|
-
| Number | Result |
|
|
235
|
-
|
|
236
|
-
| `
|
|
237
|
-
| `
|
|
238
|
-
| `
|
|
244
|
+
| Number | Expiry | Result |
|
|
245
|
+
|---|---|---|
|
|
246
|
+
| `5555555555555599` | 12/34 | Succeeds |
|
|
247
|
+
| `4111111111111111` | 12/26 | Succeeds |
|
|
248
|
+
| `5168494895055780` | 12/26 | Declined |
|
|
249
|
+
|
|
250
|
+
CVC `123` for all of them. These are the bank's sandbox cards as they stood when this version was
|
|
251
|
+
released, and two of them expire 12/26; the current list is always at
|
|
252
|
+
<https://docs.secureprocessing.app/test-cards>.
|
|
239
253
|
|
|
240
254
|
## Options
|
|
241
255
|
|
package/dist/errors.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export declare class SecureProcessingError extends Error {
|
|
|
33
33
|
* 🔴 To retry a failed POST, pass THIS back: `{ idempotencyKey: err.idempotencyKey }`. Calling the
|
|
34
34
|
* method again without it sends a new key, and a new key is a new request to the API: if the
|
|
35
35
|
* first one did reach the bank, that is a second charge or refund.
|
|
36
|
+
*
|
|
37
|
+
* The one exception is `isRefundNotYetPossible`: the bank definitely refused and nothing moved,
|
|
38
|
+
* so the retry after settlement takes a NEW key — this one stays bound to the refusal for 24 hours
|
|
39
|
+
* and replays it. Calling the method again WITHOUT `idempotencyKey` already sends a fresh key.
|
|
36
40
|
*/
|
|
37
41
|
readonly idempotencyKey: string | undefined;
|
|
38
42
|
/**
|
|
@@ -70,6 +74,15 @@ export declare class SecureProcessingError extends Error {
|
|
|
70
74
|
* The client never retries it: a loop here would only poll the bank on the customer's behalf.
|
|
71
75
|
*/
|
|
72
76
|
get isPaymentInProgress(): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* `400 refund_not_yet_possible`: a partial refund on a payment the bank has not settled yet. The
|
|
79
|
+
* bank refunds only settled payments and cannot reverse part of one. Nothing was refunded. Retry
|
|
80
|
+
* once it has settled — usually by the next business day — with a NEW idempotency key: this
|
|
81
|
+
* answer is stored against the old one for 24 hours and replayed. Calling the method again
|
|
82
|
+
* WITHOUT `idempotencyKey` already sends a fresh key. A new key is safe for this error only. If
|
|
83
|
+
* nothing has been refunded yet, a full refund can be made now.
|
|
84
|
+
*/
|
|
85
|
+
get isRefundNotYetPossible(): boolean;
|
|
73
86
|
/**
|
|
74
87
|
* 🔴 `500 outcome_unknown`: the request asked the bank to move money — a charge, a capture, a
|
|
75
88
|
* refund — and the API could not confirm what happened. The money MAY HAVE MOVED.
|
package/dist/errors.js
CHANGED
|
@@ -21,6 +21,10 @@ export class SecureProcessingError extends Error {
|
|
|
21
21
|
* 🔴 To retry a failed POST, pass THIS back: `{ idempotencyKey: err.idempotencyKey }`. Calling the
|
|
22
22
|
* method again without it sends a new key, and a new key is a new request to the API: if the
|
|
23
23
|
* first one did reach the bank, that is a second charge or refund.
|
|
24
|
+
*
|
|
25
|
+
* The one exception is `isRefundNotYetPossible`: the bank definitely refused and nothing moved,
|
|
26
|
+
* so the retry after settlement takes a NEW key — this one stays bound to the refusal for 24 hours
|
|
27
|
+
* and replays it. Calling the method again WITHOUT `idempotencyKey` already sends a fresh key.
|
|
24
28
|
*/
|
|
25
29
|
idempotencyKey;
|
|
26
30
|
/**
|
|
@@ -80,6 +84,17 @@ export class SecureProcessingError extends Error {
|
|
|
80
84
|
get isPaymentInProgress() {
|
|
81
85
|
return this.code === "payment_in_progress";
|
|
82
86
|
}
|
|
87
|
+
/**
|
|
88
|
+
* `400 refund_not_yet_possible`: a partial refund on a payment the bank has not settled yet. The
|
|
89
|
+
* bank refunds only settled payments and cannot reverse part of one. Nothing was refunded. Retry
|
|
90
|
+
* once it has settled — usually by the next business day — with a NEW idempotency key: this
|
|
91
|
+
* answer is stored against the old one for 24 hours and replayed. Calling the method again
|
|
92
|
+
* WITHOUT `idempotencyKey` already sends a fresh key. A new key is safe for this error only. If
|
|
93
|
+
* nothing has been refunded yet, a full refund can be made now.
|
|
94
|
+
*/
|
|
95
|
+
get isRefundNotYetPossible() {
|
|
96
|
+
return this.code === "refund_not_yet_possible";
|
|
97
|
+
}
|
|
83
98
|
/**
|
|
84
99
|
* 🔴 `500 outcome_unknown`: the request asked the bank to move money — a charge, a capture, a
|
|
85
100
|
* refund — and the API could not confirm what happened. The money MAY HAVE MOVED.
|
package/dist/index.d.ts
CHANGED
|
@@ -76,6 +76,9 @@ export declare class SecureProcessing {
|
|
|
76
76
|
* against what is refundable — and wait for `refund.succeeded` or `refund.failed`. A thrown
|
|
77
77
|
* error with `isOutcomeUnknown` means the same without a refund object to hold: list the
|
|
78
78
|
* payment's refunds to see it, and never retry under a new idempotency key.
|
|
79
|
+
*
|
|
80
|
+
* A partial refund on a payment the bank has not settled yet throws with
|
|
81
|
+
* `isRefundNotYetPossible`. That one is retried after settlement under a NEW key.
|
|
79
82
|
*/
|
|
80
83
|
create: (params: CreateRefundParams, options?: RequestOptions) => Promise<ApiResponse<Refund>>;
|
|
81
84
|
retrieve: (id: string) => Promise<ApiResponse<Refund>>;
|
|
@@ -237,6 +240,9 @@ export declare class SecureProcessing {
|
|
|
237
240
|
* 🔴 `amount_paid` does NOT change — the payment happened, and the refund is its own record, so
|
|
238
241
|
* the excess is netted against anything already refunded. Calling this twice returns an error
|
|
239
242
|
* rather than refunding twice. Returns the refund, not the invoice.
|
|
243
|
+
*
|
|
244
|
+
* If the overpaying payment has not been settled by the bank yet, this throws with
|
|
245
|
+
* `isRefundNotYetPossible`. That one is retried after settlement under a NEW key.
|
|
240
246
|
*/
|
|
241
247
|
refundOverpayment: (id: string, options?: RequestOptions) => Promise<ApiResponse<Refund>>;
|
|
242
248
|
/**
|
package/dist/index.js
CHANGED
|
@@ -73,6 +73,9 @@ export class SecureProcessing {
|
|
|
73
73
|
* against what is refundable — and wait for `refund.succeeded` or `refund.failed`. A thrown
|
|
74
74
|
* error with `isOutcomeUnknown` means the same without a refund object to hold: list the
|
|
75
75
|
* payment's refunds to see it, and never retry under a new idempotency key.
|
|
76
|
+
*
|
|
77
|
+
* A partial refund on a payment the bank has not settled yet throws with
|
|
78
|
+
* `isRefundNotYetPossible`. That one is retried after settlement under a NEW key.
|
|
76
79
|
*/
|
|
77
80
|
create: (params, options) => this.http.post("/v1/refunds", params, options),
|
|
78
81
|
retrieve: (id) => this.http.get(`/v1/refunds/${encodeURIComponent(id)}`),
|
|
@@ -209,6 +212,9 @@ export class SecureProcessing {
|
|
|
209
212
|
* 🔴 `amount_paid` does NOT change — the payment happened, and the refund is its own record, so
|
|
210
213
|
* the excess is netted against anything already refunded. Calling this twice returns an error
|
|
211
214
|
* rather than refunding twice. Returns the refund, not the invoice.
|
|
215
|
+
*
|
|
216
|
+
* If the overpaying payment has not been settled by the bank yet, this throws with
|
|
217
|
+
* `isRefundNotYetPossible`. That one is retried after settlement under a NEW key.
|
|
212
218
|
*/
|
|
213
219
|
refundOverpayment: (id, options) => this.http.post(`/v1/invoices/${encodeURIComponent(id)}/refund_overpayment`, {}, options),
|
|
214
220
|
/**
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED