@profullstack/coinpay 0.24.1 → 0.25.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.
- package/CHANGELOG.md +9 -0
- package/bin/coinpay.js +2 -1
- package/package.json +1 -1
- package/src/client.d.ts +60 -0
- package/src/client.js +83 -0
- package/src/finances-commands.js +2 -1
- package/src/finances-reports.js +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to `@profullstack/coinpay` will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.25.0] - 2026-10-21
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `createCheckoutSession({ amount, customerEmail, accountId, property, metadata, successUrl, cancelUrl, expiresInMinutes, allowedMethods })`
|
|
12
|
+
and `getCheckoutSession(id)`: one hosted checkout URL where the buyer picks any coin the business can
|
|
13
|
+
receive, or PayPal. Webhooks for the resulting payment carry `checkout_session_id`, `customer_email`,
|
|
14
|
+
`account_id`, `property` and `metadata`.
|
|
15
|
+
- `createPayment({ customerEmail, accountId, property })`, stored in the payment's metadata.
|
|
16
|
+
|
|
8
17
|
## [0.23.0] - 2026-10-21
|
|
9
18
|
|
|
10
19
|
### Added
|
package/bin/coinpay.js
CHANGED
|
@@ -712,7 +712,8 @@ ${colors.cyan}Commands:${colors.reset}
|
|
|
712
712
|
--with-documents: a ZIP with the period's tax documents, up to 8 MiB)
|
|
713
713
|
pnl Profit and loss, personal and business as separate files
|
|
714
714
|
(--scope personal|business, --months 3 (default: last 3
|
|
715
|
-
complete months) or --from/--to, --name "Holder", --format pdf|html|csv|json
|
|
715
|
+
complete months) or --from/--to, --name "Holder", --format pdf|html|csv|json,
|
|
716
|
+
--newest-first puts the latest month first)
|
|
716
717
|
payloads [list|download <id>] Raw provider responses, exactly as received
|
|
717
718
|
reports send <id> Email a report (--to a@x,b@y, --format pdf,csv, --message, --no-attach)
|
|
718
719
|
books send Email the CPA pack (--to, --period, --scope, --format,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profullstack/coinpay",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "CoinPay SDK & CLI \u2014 Accept cryptocurrency and card payments (BTC, ETH, SOL, POL, BCH, USDC) with wallet, swap and a live finances dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
package/src/client.d.ts
CHANGED
|
@@ -31,6 +31,57 @@ export interface PaymentParams {
|
|
|
31
31
|
successUrl?: string;
|
|
32
32
|
/** Where "Back to merchant" goes from an expired or abandoned checkout */
|
|
33
33
|
cancelUrl?: string;
|
|
34
|
+
/** Email of the person paying; stored in metadata and sent on webhooks */
|
|
35
|
+
customerEmail?: string;
|
|
36
|
+
/** Your site's user id or handle for the payer */
|
|
37
|
+
accountId?: string;
|
|
38
|
+
/** Your site hostname */
|
|
39
|
+
property?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Parameters for creating a hosted checkout session */
|
|
43
|
+
export interface CheckoutSessionParams {
|
|
44
|
+
/** Amount in USD */
|
|
45
|
+
amount: number;
|
|
46
|
+
/** Only `'USD'` */
|
|
47
|
+
currency?: 'USD';
|
|
48
|
+
description?: string;
|
|
49
|
+
/** Email of the person paying (required) */
|
|
50
|
+
customerEmail: string;
|
|
51
|
+
/** Your site's user id or handle for the payer (required) */
|
|
52
|
+
accountId: string;
|
|
53
|
+
/** Your site hostname (defaults to the business name) */
|
|
54
|
+
property?: string;
|
|
55
|
+
metadata?: Record<string, unknown>;
|
|
56
|
+
/** `{CHECKOUT_SESSION_ID}` and `{PAYMENT_ID}` are filled in */
|
|
57
|
+
successUrl?: string;
|
|
58
|
+
cancelUrl?: string;
|
|
59
|
+
/** 15 to 120, default 60 */
|
|
60
|
+
expiresInMinutes?: number;
|
|
61
|
+
/** Coin codes (e.g. `'USDC_POL'`), `'CRYPTO'` or `'PAYPAL'`; default all */
|
|
62
|
+
allowedMethods?: string[];
|
|
63
|
+
/** Only with a merchant session token; a business API key implies it */
|
|
64
|
+
businessId?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Response from `createCheckoutSession` */
|
|
68
|
+
export interface CheckoutSessionResponse {
|
|
69
|
+
success: boolean;
|
|
70
|
+
id: string;
|
|
71
|
+
url: string;
|
|
72
|
+
status: 'open' | 'paid' | 'expired';
|
|
73
|
+
amount: number;
|
|
74
|
+
currency: 'USD';
|
|
75
|
+
description: string | null;
|
|
76
|
+
customer_email: string;
|
|
77
|
+
account_id: string;
|
|
78
|
+
property: string;
|
|
79
|
+
metadata: Record<string, unknown>;
|
|
80
|
+
success_url: string | null;
|
|
81
|
+
cancel_url: string | null;
|
|
82
|
+
expires_at: string;
|
|
83
|
+
methods: string[];
|
|
84
|
+
[key: string]: unknown;
|
|
34
85
|
}
|
|
35
86
|
|
|
36
87
|
/** Parameters for listing payments */
|
|
@@ -200,6 +251,15 @@ export class CoinPayClient {
|
|
|
200
251
|
*/
|
|
201
252
|
createPayment(params: PaymentParams): Promise<CreatePaymentResponse>;
|
|
202
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Create a hosted checkout session; redirect the buyer to `url`. The buyer
|
|
256
|
+
* picks any coin the business can receive, or PayPal.
|
|
257
|
+
*/
|
|
258
|
+
createCheckoutSession(params: CheckoutSessionParams): Promise<CheckoutSessionResponse>;
|
|
259
|
+
|
|
260
|
+
/** Get a checkout session (`cs_...`). */
|
|
261
|
+
getCheckoutSession(sessionId: string): Promise<Record<string, unknown>>;
|
|
262
|
+
|
|
203
263
|
/**
|
|
204
264
|
* Get payment details by ID.
|
|
205
265
|
*
|
package/src/client.js
CHANGED
|
@@ -255,6 +255,9 @@ export class CoinPayClient {
|
|
|
255
255
|
metadata,
|
|
256
256
|
successUrl,
|
|
257
257
|
cancelUrl,
|
|
258
|
+
customerEmail,
|
|
259
|
+
accountId,
|
|
260
|
+
property,
|
|
258
261
|
}) {
|
|
259
262
|
// Map to API field names (snake_case)
|
|
260
263
|
return this.request('/payments/create', {
|
|
@@ -268,10 +271,90 @@ export class CoinPayClient {
|
|
|
268
271
|
metadata,
|
|
269
272
|
success_url: successUrl,
|
|
270
273
|
cancel_url: cancelUrl,
|
|
274
|
+
customer_email: customerEmail,
|
|
275
|
+
account_id: accountId,
|
|
276
|
+
property,
|
|
271
277
|
}),
|
|
272
278
|
});
|
|
273
279
|
}
|
|
274
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Create a hosted checkout session.
|
|
283
|
+
*
|
|
284
|
+
* Redirect the buyer to the returned `url`. There they choose any coin your
|
|
285
|
+
* business has a wallet for (stablecoins first) or PayPal when connected.
|
|
286
|
+
* The payment and every webhook for it carry `checkout_session_id`,
|
|
287
|
+
* `customer_email`, `account_id`, `property` and your `metadata`.
|
|
288
|
+
*
|
|
289
|
+
* @param {Object} params
|
|
290
|
+
* @param {number} params.amount - Amount in USD
|
|
291
|
+
* @param {string} params.customerEmail - Email of the person paying (required)
|
|
292
|
+
* @param {string} params.accountId - Your site's user id or handle for the payer (required)
|
|
293
|
+
* @param {string} [params.property] - Your site hostname (defaults to the business name)
|
|
294
|
+
* @param {string} [params.description]
|
|
295
|
+
* @param {Object} [params.metadata]
|
|
296
|
+
* @param {string} [params.successUrl] - `{CHECKOUT_SESSION_ID}` and `{PAYMENT_ID}` are filled in
|
|
297
|
+
* @param {string} [params.cancelUrl]
|
|
298
|
+
* @param {number} [params.expiresInMinutes=60] - 15 to 120
|
|
299
|
+
* @param {string[]} [params.allowedMethods] - coin codes, 'CRYPTO' or 'PAYPAL' (default: all)
|
|
300
|
+
* @returns {Promise<{success: boolean, id: string, url: string, status: string, expires_at: string, methods: string[]}>}
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* const { id, url } = await client.createCheckoutSession({
|
|
304
|
+
* amount: 9.99,
|
|
305
|
+
* description: 'Pro plan',
|
|
306
|
+
* customerEmail: 'buyer@example.com',
|
|
307
|
+
* accountId: 'user_123',
|
|
308
|
+
* property: 'example.com',
|
|
309
|
+
* successUrl: 'https://example.com/thanks?session={CHECKOUT_SESSION_ID}',
|
|
310
|
+
* cancelUrl: 'https://example.com/pricing',
|
|
311
|
+
* });
|
|
312
|
+
* // res.redirect(url)
|
|
313
|
+
*/
|
|
314
|
+
async createCheckoutSession({
|
|
315
|
+
amount,
|
|
316
|
+
currency = 'USD',
|
|
317
|
+
description,
|
|
318
|
+
customerEmail,
|
|
319
|
+
accountId,
|
|
320
|
+
property,
|
|
321
|
+
metadata,
|
|
322
|
+
successUrl,
|
|
323
|
+
cancelUrl,
|
|
324
|
+
expiresInMinutes,
|
|
325
|
+
allowedMethods,
|
|
326
|
+
businessId,
|
|
327
|
+
}) {
|
|
328
|
+
return this.request('/checkout/sessions', {
|
|
329
|
+
method: 'POST',
|
|
330
|
+
body: JSON.stringify({
|
|
331
|
+
amount,
|
|
332
|
+
currency,
|
|
333
|
+
description,
|
|
334
|
+
customer_email: customerEmail,
|
|
335
|
+
account_id: accountId,
|
|
336
|
+
property,
|
|
337
|
+
metadata,
|
|
338
|
+
success_url: successUrl,
|
|
339
|
+
cancel_url: cancelUrl,
|
|
340
|
+
expires_in_minutes: expiresInMinutes,
|
|
341
|
+
allowed_methods: allowedMethods,
|
|
342
|
+
business_id: businessId,
|
|
343
|
+
}),
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Get a checkout session. With your business API key the response includes
|
|
349
|
+
* the customer fields, metadata and the underlying payment ids.
|
|
350
|
+
*
|
|
351
|
+
* @param {string} sessionId - `cs_...`
|
|
352
|
+
* @returns {Promise<Object>} `{ success, session }`
|
|
353
|
+
*/
|
|
354
|
+
async getCheckoutSession(sessionId) {
|
|
355
|
+
return this.request(`/checkout/sessions/${encodeURIComponent(sessionId)}`);
|
|
356
|
+
}
|
|
357
|
+
|
|
275
358
|
/**
|
|
276
359
|
* Get payment by ID
|
|
277
360
|
*
|
package/src/finances-commands.js
CHANGED
|
@@ -816,9 +816,10 @@ export async function runFinancesCommand(subcommand, args, flags, ctx) {
|
|
|
816
816
|
const to = typeof flags.to === 'string' ? flags.to : undefined;
|
|
817
817
|
const timezone = typeof flags.timezone === 'string' ? flags.timezone : undefined;
|
|
818
818
|
const name = typeof flags.name === 'string' ? flags.name : undefined;
|
|
819
|
+
const order = flags['newest-first'] === true ? 'newest' : typeof flags.order === 'string' ? flags.order : undefined;
|
|
819
820
|
const written = [];
|
|
820
821
|
for (const scope of wanted) {
|
|
821
|
-
const file = await api.exportPnl(client, { scope, months, period, from, to, timezone, name, format });
|
|
822
|
+
const file = await api.exportPnl(client, { scope, months, period, from, to, timezone, name, format, order });
|
|
822
823
|
const output = typeof flags.output === 'string' && wanted.length === 1 ? flags.output : file.filename || `pnl-${scope}.${format}`;
|
|
823
824
|
written.push({ scope, output: writeDownload(output, Buffer.from(file.bytes), { overwrite: flags.overwrite === true }), bytes: file.bytes.length });
|
|
824
825
|
}
|
package/src/finances-reports.js
CHANGED
|
@@ -403,8 +403,8 @@ export async function exportBooks(client, { period, from, to, timezone, scope, f
|
|
|
403
403
|
* Profit and loss statement for one scope. With no period it covers the
|
|
404
404
|
* last `months` complete calendar months (server default 3).
|
|
405
405
|
*/
|
|
406
|
-
export async function exportPnl(client, { scope, months, period, from, to, timezone, name, format = 'pdf' } = {}) {
|
|
407
|
-
return client.requestBinary(`/finances/pnl${query({ scope, months, period, from, to, timezone, name, format })}`);
|
|
406
|
+
export async function exportPnl(client, { scope, months, period, from, to, timezone, name, format = 'pdf', order } = {}) {
|
|
407
|
+
return client.requestBinary(`/finances/pnl${query({ scope, months, period, from, to, timezone, name, format, order })}`);
|
|
408
408
|
}
|
|
409
409
|
|
|
410
410
|
// ── Raw provider payloads ──
|