@happyvertical/accounting 0.90.0 → 0.92.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/README.md +150 -2
- package/dist/chunks/{OAuthClient-Bv-lzpx8.js → OAuthClient-DgRaQp_Y.js} +2 -2
- package/dist/chunks/{OAuthClient-Bv-lzpx8.js.map → OAuthClient-DgRaQp_Y.js.map} +1 -1
- package/dist/chunks/errors-Dvn2QzOB.js +49 -0
- package/dist/chunks/errors-Dvn2QzOB.js.map +1 -0
- package/dist/chunks/{quickbooks-BF3GrJBw.js → quickbooks-DujZt_Gx.js} +3 -2
- package/dist/chunks/{quickbooks-BF3GrJBw.js.map → quickbooks-DujZt_Gx.js.map} +1 -1
- package/dist/chunks/{stripe-e3yn8cEJ.js → stripe-DvSZ3fGk.js} +453 -34
- package/dist/chunks/stripe-DvSZ3fGk.js.map +1 -0
- package/dist/errors.d.ts +24 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/providers/stripe/index.d.ts +10 -1
- package/dist/providers/stripe/index.d.ts.map +1 -1
- package/dist/types.d.ts +257 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/chunks/stripe-e3yn8cEJ.js.map +0 -1
package/README.md
CHANGED
|
@@ -37,11 +37,159 @@ complete billing address before creating the invoice so Stripe can calculate
|
|
|
37
37
|
tax from that customer tax location. Read the invoice back to persist Stripe's
|
|
38
38
|
calculated `taxAmount`; callers do not supply local tax tables or rates.
|
|
39
39
|
|
|
40
|
+
Invoice lines carry more than an amount:
|
|
41
|
+
|
|
42
|
+
- `periodStart` / `periodEnd` (set both) become the Stripe invoice item's
|
|
43
|
+
service `period`, so the invoice PDF, portal, and revenue reports show the
|
|
44
|
+
billed window. `periodEnd` is exclusive, like Stripe's own subscription
|
|
45
|
+
periods, and must not be before `periodStart`.
|
|
46
|
+
- `discount` is the line's total discount in major units. Stripe receives it
|
|
47
|
+
as an amount-off coupon on the invoice item (one reusable coupon per
|
|
48
|
+
currency and amount, id `hv_amount_off_<currency>_<stripe amount>`), so the
|
|
49
|
+
discount shows on the invoice and Stripe Tax taxes the discounted amount.
|
|
50
|
+
|
|
51
|
+
`collectionMethod: 'charge_automatically'` bills the customer's default
|
|
52
|
+
payment method instead of emailing a payable invoice (the default,
|
|
53
|
+
`send_invoice`). `invoices.send()` then finalizes the invoice with automatic
|
|
54
|
+
collection on: Stripe charges the card on its own collection schedule (not
|
|
55
|
+
necessarily at once, so activate service on `invoice.paid` rather than on
|
|
56
|
+
`send()`), retries failures under your Stripe retry settings, and reports the
|
|
57
|
+
result as `invoice.paid` or `invoice.payment_failed`. Automatically charged invoices carry no due date.
|
|
58
|
+
`invoices.markUncollectible()` writes an open invoice off, and invoice reads
|
|
59
|
+
report that state as `status: 'uncollectible'`.
|
|
60
|
+
|
|
61
|
+
## Stripe customers
|
|
62
|
+
|
|
63
|
+
Pass a stable `idempotencyKey` when a retry might create the customer again
|
|
64
|
+
(for example a worker that crashed before storing the returned id). A retry
|
|
65
|
+
with the same key returns the first customer: Stripe replays the create
|
|
66
|
+
inside its idempotency window, and after it the adapter finds the customer by
|
|
67
|
+
the `local_id` metadata it writes on every customer (the oldest one wins if
|
|
68
|
+
earlier retries left duplicates). Reuse the key only for the same customer
|
|
69
|
+
contents.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const { externalId } = await stripe.customers.sync({
|
|
73
|
+
id: account.id,
|
|
74
|
+
name: account.name,
|
|
75
|
+
billingAddress: account.address,
|
|
76
|
+
idempotencyKey: `billing-account:${account.id}`,
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
40
80
|
## Stripe Checkout and webhooks
|
|
41
81
|
|
|
42
82
|
`billing.createCheckoutSession` accepts `idempotencyKey`; reuse it when
|
|
43
|
-
retrying the same Checkout Session creation.
|
|
44
|
-
|
|
83
|
+
retrying the same Checkout Session creation.
|
|
84
|
+
|
|
85
|
+
Price ad-hoc Checkout lines with `priceData.unitAmountMinor`, integer ISO 4217
|
|
86
|
+
minor units that the adapter converts to Stripe's unit (ISK and UGX are
|
|
87
|
+
two-decimal at Stripe). `priceData.unitAmount` is still accepted and passed
|
|
88
|
+
through unconverted in Stripe's unit. Set `automaticTax: true` to charge tax
|
|
89
|
+
with Stripe Tax; Stripe needs the buyer's location, so collect it with
|
|
90
|
+
`billingAddressCollection` or, for an existing customer, save it with
|
|
91
|
+
`customerUpdate: { address: 'auto' }`. Ad-hoc prices default to
|
|
92
|
+
`taxBehavior: 'exclusive'` when tax is on.
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const session = await stripe.billing.createCheckoutSession({
|
|
96
|
+
mode: 'payment',
|
|
97
|
+
customerExternalId: 'cus_123',
|
|
98
|
+
lineItems: [
|
|
99
|
+
{
|
|
100
|
+
priceData: { currency: 'CAD', unitAmountMinor: 5000, productName: 'Credit' },
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
automaticTax: true,
|
|
104
|
+
customerUpdate: { address: 'auto' },
|
|
105
|
+
setupFutureUsage: 'off_session', // also keep the card for top-ups
|
|
106
|
+
successUrl,
|
|
107
|
+
cancelUrl,
|
|
108
|
+
idempotencyKey: `credit-purchase:${cartId}`,
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Card on file
|
|
113
|
+
|
|
114
|
+
A `setup` mode session saves a payment method without charging. It takes no
|
|
115
|
+
line items and needs `currency` (or `paymentMethodTypes`). After it completes,
|
|
116
|
+
read the saved method and make it the customer's default so automatically
|
|
117
|
+
charged invoices and off-session charges can use it:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
const setup = await stripe.billing.createCheckoutSession({
|
|
121
|
+
mode: 'setup',
|
|
122
|
+
customerExternalId: 'cus_123',
|
|
123
|
+
currency: 'CAD',
|
|
124
|
+
billingAddressCollection: 'required',
|
|
125
|
+
customerUpdate: { address: 'auto', name: 'auto' },
|
|
126
|
+
successUrl,
|
|
127
|
+
cancelUrl,
|
|
128
|
+
idempotencyKey: `card-setup:${accountId}:${attempt}`,
|
|
129
|
+
});
|
|
130
|
+
// On checkout.session.completed:
|
|
131
|
+
// Both methods are optional on StripeBillingOperations; StripeProvider has them.
|
|
132
|
+
const done = await stripe.billing.retrieveCheckoutSession?.(setup.externalId);
|
|
133
|
+
if (done?.status === 'complete' && done.paymentMethodExternalId) {
|
|
134
|
+
await stripe.billing.setDefaultPaymentMethod?.(
|
|
135
|
+
'cus_123',
|
|
136
|
+
done.paymentMethodExternalId,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Off-session charges
|
|
142
|
+
|
|
143
|
+
`payments.chargeSavedPaymentMethod()` charges a saved payment method without
|
|
144
|
+
the customer present, for example an automatic prepaid-credit top-up. It is
|
|
145
|
+
provider-neutral and optional on `PaymentOperations`: a provider that cannot
|
|
146
|
+
pull funds from a stored method (such as a push-payment BTC rail) does not
|
|
147
|
+
implement it, so check for it before calling. Amounts are integer minor units
|
|
148
|
+
(`amountMinor`), and `idempotencyKey` is required.
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const charge = await stripe.payments.chargeSavedPaymentMethod?.({
|
|
152
|
+
customerExternalId: 'cus_123', // default payment method unless one is given
|
|
153
|
+
amountMinor: 2500,
|
|
154
|
+
currency: 'USD',
|
|
155
|
+
idempotencyKey: `topup:${policyId}:${sequence}`,
|
|
156
|
+
metadata: { policy: policyId },
|
|
157
|
+
});
|
|
158
|
+
switch (charge?.status) {
|
|
159
|
+
case 'succeeded': // funds secured: grant the credit
|
|
160
|
+
case 'processing': // wait for the payment webhook
|
|
161
|
+
case 'requires_action': // issuer wants authentication; re-save the card on-session
|
|
162
|
+
case 'failed': // declined or no payment method; see failureCode
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
A decline (`failureCode: 'card_declined'`) or an authentication requirement
|
|
167
|
+
(`requires_action`, `failureCode: 'authentication_required'`) is returned, not
|
|
168
|
+
thrown. Results never include Stripe's client secret, so a `requires_action`
|
|
169
|
+
attempt is not completed later: when the customer is next present, collect
|
|
170
|
+
authentication with a `setup` mode Checkout session and
|
|
171
|
+
`setDefaultPaymentMethod`, then charge again with a new idempotency key (the
|
|
172
|
+
old key returns the original, unauthenticated attempt). Other Stripe API
|
|
173
|
+
errors throw a `StripeApiError` carrying `status`, `type`, and `code`;
|
|
174
|
+
invalid input and a reused-key refusal throw a plain `Error` before any
|
|
175
|
+
provider request. Every retry with the same key returns the original
|
|
176
|
+
charge: Stripe replays it inside its idempotency window, and after it the
|
|
177
|
+
adapter finds the PaymentIntent by its `hv_charge_key` metadata. Scope keys
|
|
178
|
+
to the payer and use a new key for a new attempt: a key reused for a
|
|
179
|
+
different amount, currency, customer, or explicit payment method is refused
|
|
180
|
+
(Stripe `idempotency_error`, or an adapter error after the window), never
|
|
181
|
+
charged. Pass `paymentMethodExternalId` to keep retries identical when the
|
|
182
|
+
customer's default card may change in between. Payment webhooks (`payment_intent.*`) carry a normalized `WebhookEvent.payment`
|
|
183
|
+
summary with the status, minor-unit amount, and `chargeKey`.
|
|
184
|
+
|
|
185
|
+
Minor-unit amounts (`amountMinor`, `unitAmountMinor`, and the `*Minor` read
|
|
186
|
+
fields) use ISO 4217 exponents from an explicit table, not the runtime's
|
|
187
|
+
`Intl` display digits, which differ for some currencies (for example RSD,
|
|
188
|
+
IQD, and MGA). Derive minor units the same way before calling.
|
|
189
|
+
|
|
190
|
+
## Stripe webhooks
|
|
191
|
+
|
|
192
|
+
After `webhooks.verify` succeeds, the parsed Stripe webhook exposes its provider event as `WebhookEvent.id`.
|
|
45
193
|
Persist that identifier in a durable inbox before applying side effects; the
|
|
46
194
|
in-process parser alone cannot deduplicate deliveries across restarts or
|
|
47
195
|
replicas.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as __toCommonJS, i as __require, n as __esmMin, r as __exportAll, t as __commonJSMin } from "./quickbooks-
|
|
1
|
+
import { a as __toCommonJS, i as __require, n as __esmMin, r as __exportAll, t as __commonJSMin } from "./quickbooks-DujZt_Gx.js";
|
|
2
2
|
//#region ../../node_modules/.pnpm/atob@2.1.2/node_modules/atob/browser-atob.js
|
|
3
3
|
var require_browser_atob = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
4
4
|
(function(w) {
|
|
@@ -18261,4 +18261,4 @@ var require_OAuthClient = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
18261
18261
|
//#endregion
|
|
18262
18262
|
export default require_OAuthClient();
|
|
18263
18263
|
|
|
18264
|
-
//# sourceMappingURL=OAuthClient-
|
|
18264
|
+
//# sourceMappingURL=OAuthClient-DgRaQp_Y.js.map
|