@plumbus/payments-stripe 0.2.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +60 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/catalog.d.ts +14 -0
  5. package/dist/catalog.d.ts.map +1 -0
  6. package/dist/catalog.js +286 -0
  7. package/dist/catalog.js.map +1 -0
  8. package/dist/charges.d.ts +64 -0
  9. package/dist/charges.d.ts.map +1 -0
  10. package/dist/charges.js +339 -0
  11. package/dist/charges.js.map +1 -0
  12. package/dist/config-rules.d.ts +7 -0
  13. package/dist/config-rules.d.ts.map +1 -0
  14. package/dist/config-rules.js +87 -0
  15. package/dist/config-rules.js.map +1 -0
  16. package/dist/diagnose.d.ts +17 -0
  17. package/dist/diagnose.d.ts.map +1 -0
  18. package/dist/diagnose.js +237 -0
  19. package/dist/diagnose.js.map +1 -0
  20. package/dist/errors.d.ts +4 -0
  21. package/dist/errors.d.ts.map +1 -0
  22. package/dist/errors.js +45 -0
  23. package/dist/errors.js.map +1 -0
  24. package/dist/events.d.ts +38 -0
  25. package/dist/events.d.ts.map +1 -0
  26. package/dist/events.js +167 -0
  27. package/dist/events.js.map +1 -0
  28. package/dist/index.d.ts +7 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +10 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/mapping.d.ts +328 -0
  33. package/dist/mapping.d.ts.map +1 -0
  34. package/dist/mapping.js +437 -0
  35. package/dist/mapping.js.map +1 -0
  36. package/dist/provider.d.ts +33 -0
  37. package/dist/provider.d.ts.map +1 -0
  38. package/dist/provider.js +634 -0
  39. package/dist/provider.js.map +1 -0
  40. package/dist/resolve.d.ts +10 -0
  41. package/dist/resolve.d.ts.map +1 -0
  42. package/dist/resolve.js +171 -0
  43. package/dist/resolve.js.map +1 -0
  44. package/dist/secrets.d.ts +7 -0
  45. package/dist/secrets.d.ts.map +1 -0
  46. package/dist/secrets.js +33 -0
  47. package/dist/secrets.js.map +1 -0
  48. package/dist/testing/index.d.ts +54 -0
  49. package/dist/testing/index.d.ts.map +1 -0
  50. package/dist/testing/index.js +119 -0
  51. package/dist/testing/index.js.map +1 -0
  52. package/instructions/README.md +14 -0
  53. package/instructions/configure-stripe.md +69 -0
  54. package/instructions/framework.md +62 -0
  55. package/instructions/testing.md +41 -0
  56. package/instructions/webhooks.md +44 -0
  57. package/package.json +66 -0
@@ -0,0 +1,339 @@
1
+ // ── Charges on Stripe ──
2
+ // Where money moves (ChargeRouting → Stripe parameters), payment pages
3
+ // (Checkout Sessions), invoices, saved payment methods charged off-session,
4
+ // holds, and finding the charge a PaymentIntent belongs to.
5
+ //
6
+ // Flows:
7
+ // • direct — on the seller's account (Stripe-Account header), with an application fee
8
+ // • destination — on the platform, `transfer_data.destination` = the seller, with an
9
+ // application fee; `on_behalf_of` makes the seller the merchant of record
10
+ // • platform — on the platform, no seller; `transfer_group` ties later transfers
11
+ import { ErrorCode, PlumbusError } from '@plumbus/core';
12
+ import Stripe from 'stripe';
13
+ import { idOf, mapIntent, mapInvoiceCharge, mapSession, } from './mapping.js';
14
+ // Checkout accepts expires_at 30 minutes to 24 hours after Stripe creates the
15
+ // session; keep a minute inside both ends for request time and clock skew.
16
+ const CHECKOUT_MIN_SECONDS = 31 * 60;
17
+ const CHECKOUT_MAX_SECONDS = 24 * 3600 - 60;
18
+ export const PRODUCT_NAME_MAX = 250;
19
+ /** Marks PaymentIntents that are charges themselves (a saved method charged off-session). */
20
+ export const COLLECTION_METADATA_KEY = 'plumbus_collection';
21
+ export const SESSION_EXPAND = [
22
+ 'payment_intent.latest_charge',
23
+ 'payment_intent.payment_method',
24
+ ];
25
+ /** Cut to `max` UTF-16 units without splitting a surrogate pair (Stripe rejects half emoji). */
26
+ export function clip(text, max) {
27
+ const cut = text.slice(0, max);
28
+ return /[\uD800-\uDBFF]$/.test(cut) ? cut.slice(0, -1) : cut;
29
+ }
30
+ export function checkoutExpiry(requested) {
31
+ const now = Math.floor(Date.now() / 1000);
32
+ const wanted = Math.floor(requested.getTime() / 1000);
33
+ return Math.min(Math.max(wanted, now + CHECKOUT_MIN_SECONDS), now + CHECKOUT_MAX_SECONDS);
34
+ }
35
+ /** Request options for an object on a seller's account, or on the platform (null). */
36
+ export function onAccount(accountId) {
37
+ return accountId ? { stripeAccount: accountId } : {};
38
+ }
39
+ /** The account a charge's objects live on: the seller's for direct charges, else the platform. */
40
+ export function chargeAccount(routing) {
41
+ return routing.flow === 'direct' ? routing.sellerAccountId : null;
42
+ }
43
+ function requireSeller(routing) {
44
+ if (!routing.sellerAccountId) {
45
+ throw new PlumbusError(ErrorCode.Validation, `A ${routing.flow} charge needs a seller account`, {
46
+ reason: 'stripe_seller_account_missing',
47
+ });
48
+ }
49
+ return routing.sellerAccountId;
50
+ }
51
+ /** Fee and payee fields shared by PaymentIntents, Checkout's payment_intent_data, and invoices. */
52
+ export function moneyRouting(routing, platformFeeAmount) {
53
+ const fee = platformFeeAmount > 0 ? { application_fee_amount: platformFeeAmount } : {};
54
+ if (routing.flow === 'direct')
55
+ return fee;
56
+ if (routing.flow === 'destination') {
57
+ const seller = requireSeller(routing);
58
+ return {
59
+ ...fee,
60
+ transfer_data: { destination: seller },
61
+ ...(routing.onBehalfOf ? { on_behalf_of: seller } : {}),
62
+ };
63
+ }
64
+ return routing.transferGroup ? { transfer_group: routing.transferGroup } : {};
65
+ }
66
+ /** Checkout page options, for payment and subscription pages. */
67
+ export function checkoutOptionParams(options, mode, hasCustomer) {
68
+ return {
69
+ ...(options.allowPromotionCodes ? { allow_promotion_codes: true } : {}),
70
+ ...(options.automaticTax
71
+ ? {
72
+ automatic_tax: { enabled: true },
73
+ // Tax needs an address; take the one entered on the page for known customers.
74
+ ...(hasCustomer ? { customer_update: { address: 'auto' } } : {}),
75
+ }
76
+ : {}),
77
+ ...(options.billingAddress ? { billing_address_collection: options.billingAddress } : {}),
78
+ ...(options.phone ? { phone_number_collection: { enabled: true } } : {}),
79
+ ...(options.shippingCountries?.length
80
+ ? {
81
+ shipping_address_collection: {
82
+ allowed_countries: options.shippingCountries,
83
+ },
84
+ }
85
+ : {}),
86
+ ...(options.locale
87
+ ? { locale: options.locale }
88
+ : {}),
89
+ ...(mode === 'payment' && options.submitType ? { submit_type: options.submitType } : {}),
90
+ };
91
+ }
92
+ export function lineItemsFor(currency, items) {
93
+ return items.map((item) => ({
94
+ quantity: item.quantity,
95
+ price_data: {
96
+ currency,
97
+ unit_amount: item.unitAmount,
98
+ product_data: {
99
+ name: clip(item.name, PRODUCT_NAME_MAX),
100
+ ...(item.description ? { description: item.description } : {}),
101
+ },
102
+ },
103
+ }));
104
+ }
105
+ /** A price whose amount the client chooses (Checkout takes it only as a saved Price). */
106
+ export async function customAmountPrice(stripe, input, options) {
107
+ const { minimum, maximum, preset } = input.customAmount;
108
+ return stripe.prices.create({
109
+ currency: input.currency,
110
+ custom_unit_amount: {
111
+ enabled: true,
112
+ ...(minimum !== undefined ? { minimum } : {}),
113
+ ...(maximum !== undefined ? { maximum } : {}),
114
+ ...(preset !== undefined ? { preset } : {}),
115
+ },
116
+ product_data: { name: clip(input.name, PRODUCT_NAME_MAX) },
117
+ }, options);
118
+ }
119
+ export async function createCheckoutCharge(stripe, input) {
120
+ const account = chargeAccount(input);
121
+ const onIt = onAccount(account);
122
+ const lineItems = input.customAmount
123
+ ? [
124
+ {
125
+ quantity: 1,
126
+ price: (await customAmountPrice(stripe, {
127
+ currency: input.currency,
128
+ name: input.items[0]?.name ?? input.description,
129
+ customAmount: input.customAmount,
130
+ }, { ...onIt, idempotencyKey: `${input.idempotencyKey}:price` })).id,
131
+ },
132
+ ]
133
+ : lineItemsFor(input.currency, input.items);
134
+ const hasCustomer = Boolean(input.clientId);
135
+ const session = await stripe.checkout.sessions.create({
136
+ mode: 'payment',
137
+ ui_mode: input.ui === 'embedded' ? 'embedded_page' : 'hosted_page',
138
+ line_items: lineItems,
139
+ ...(input.clientId ? { customer: input.clientId } : {}),
140
+ ...(input.clientEmail && !input.clientId ? { customer_email: input.clientEmail } : {}),
141
+ // A method kept for later needs a customer to belong to.
142
+ ...(input.saveMethod && !input.clientId ? { customer_creation: 'always' } : {}),
143
+ client_reference_id: input.reference,
144
+ metadata: input.metadata,
145
+ payment_intent_data: {
146
+ ...moneyRouting(input, input.platformFeeAmount),
147
+ description: input.description,
148
+ metadata: { ...input.metadata, [COLLECTION_METADATA_KEY]: 'checkout' },
149
+ ...(input.capture === 'manual' ? { capture_method: 'manual' } : {}),
150
+ ...(input.saveMethod ? { setup_future_usage: 'off_session' } : {}),
151
+ ...(input.options.statementDescriptorSuffix
152
+ ? { statement_descriptor_suffix: input.options.statementDescriptorSuffix }
153
+ : {}),
154
+ },
155
+ ...(input.ui === 'embedded'
156
+ ? { return_url: input.returnUrl }
157
+ : { success_url: input.successUrl, cancel_url: input.cancelUrl }),
158
+ expires_at: checkoutExpiry(input.expiresAt),
159
+ ...checkoutOptionParams(input.options, 'payment', hasCustomer),
160
+ }, { ...onIt, idempotencyKey: input.idempotencyKey });
161
+ return mapSession(session);
162
+ }
163
+ async function retrieveInvoice(stripe, invoiceId, options) {
164
+ return (await stripe.invoices.retrieve(invoiceId, { expand: ['payments'] }, options));
165
+ }
166
+ /**
167
+ * Email an invoice for a charge. An earlier attempt that crashed part-way may
168
+ * have left the invoice behind (found by the charge id in its metadata); it is
169
+ * finished instead of made twice.
170
+ */
171
+ export async function createInvoiceCharge(stripe, input) {
172
+ const onIt = onAccount(chargeAccount(input));
173
+ const earlier = (await stripe.invoices.list({ customer: input.clientId, limit: 20 }, onIt)).data.find((invoice) => invoice.metadata?.plumbus_charge_id === input.reference && invoice.status !== 'void');
174
+ const { transfer_group: _group, ...money } = moneyRouting(input, input.platformFeeAmount);
175
+ let invoice = earlier ??
176
+ (await stripe.invoices.create({
177
+ customer: input.clientId,
178
+ currency: input.currency,
179
+ collection_method: 'send_invoice',
180
+ days_until_due: input.dueInDays,
181
+ description: input.description,
182
+ pending_invoice_items_behavior: 'exclude',
183
+ auto_advance: false,
184
+ metadata: input.metadata,
185
+ ...money,
186
+ ...(input.automaticTax ? { automatic_tax: { enabled: true } } : {}),
187
+ }, { ...onIt, idempotencyKey: `${input.idempotencyKey}:invoice` }));
188
+ if (invoice.status === 'draft') {
189
+ if ((invoice.lines?.data.length ?? 0) === 0) {
190
+ for (const [index, item] of input.items.entries()) {
191
+ await stripe.invoiceItems.create({
192
+ customer: input.clientId,
193
+ invoice: invoice.id,
194
+ currency: input.currency,
195
+ description: item.description ? `${item.name} — ${item.description}` : item.name,
196
+ quantity: item.quantity,
197
+ unit_amount_decimal: Stripe.Decimal.from(item.unitAmount),
198
+ metadata: { plumbus_charge_id: input.reference },
199
+ }, { ...onIt, idempotencyKey: `${input.idempotencyKey}:item:${index}` });
200
+ }
201
+ }
202
+ invoice = await stripe.invoices.finalizeInvoice(invoice.id, { auto_advance: false }, onIt);
203
+ }
204
+ if (invoice.status === 'open' && !earlier) {
205
+ await stripe.invoices.sendInvoice(invoice.id, {}, { ...onIt, idempotencyKey: `${input.idempotencyKey}:send` });
206
+ }
207
+ return mapInvoiceCharge(await retrieveInvoice(stripe, invoice.id, onIt));
208
+ }
209
+ /** The PaymentIntent a declined off-session payment left behind, from Stripe's error. */
210
+ function intentFromError(err) {
211
+ if (!(err instanceof Stripe.errors.StripeError))
212
+ return null;
213
+ const raw = err.raw;
214
+ return raw?.payment_intent ?? null;
215
+ }
216
+ /**
217
+ * Charge a saved method without the client. A decline or a bank that wants the
218
+ * client present is an outcome (failed / requires_action), not an error.
219
+ */
220
+ export async function chargeSavedMethod(stripe, input) {
221
+ try {
222
+ const intent = await stripe.paymentIntents.create({
223
+ amount: input.amount,
224
+ currency: input.currency,
225
+ customer: input.clientId,
226
+ payment_method: input.methodId,
227
+ off_session: true,
228
+ confirm: true,
229
+ description: input.description,
230
+ metadata: { ...input.metadata, [COLLECTION_METADATA_KEY]: 'saved_method' },
231
+ ...(input.capture === 'manual' ? { capture_method: 'manual' } : {}),
232
+ ...moneyRouting(input, input.platformFeeAmount),
233
+ ...(input.statementDescriptorSuffix
234
+ ? { statement_descriptor_suffix: input.statementDescriptorSuffix }
235
+ : {}),
236
+ expand: ['latest_charge'],
237
+ }, { ...onAccount(chargeAccount(input)), idempotencyKey: input.idempotencyKey });
238
+ return mapIntent(intent);
239
+ }
240
+ catch (err) {
241
+ const intent = intentFromError(err);
242
+ if (intent)
243
+ return mapIntent(intent);
244
+ throw err;
245
+ }
246
+ }
247
+ async function retrieveIntent(stripe, paymentId, options) {
248
+ return (await stripe.paymentIntents.retrieve(paymentId, { expand: ['latest_charge', 'payment_method'] }, options));
249
+ }
250
+ /**
251
+ * The charge a PaymentIntent belongs to, in the shape its collection reports:
252
+ * the PaymentIntent itself (saved methods), its Checkout Session (payment pages
253
+ * and links), or its invoice (invoices sent as charges). Null = not ours.
254
+ */
255
+ export async function chargeForPayment(stripe, paymentId, accountId) {
256
+ const onIt = onAccount(accountId);
257
+ const intent = await retrieveIntent(stripe, paymentId, onIt);
258
+ if (intent.metadata?.[COLLECTION_METADATA_KEY] === 'saved_method')
259
+ return mapIntent(intent);
260
+ const [session] = (await stripe.checkout.sessions.list({
261
+ payment_intent: paymentId,
262
+ limit: 1,
263
+ expand: SESSION_EXPAND.map((path) => `data.${path}`),
264
+ }, onIt)).data;
265
+ if (session)
266
+ return mapSession(session);
267
+ const [invoicePayment] = (await stripe.invoicePayments.list({ payment: { type: 'payment_intent', payment_intent: paymentId }, limit: 1 }, onIt)).data;
268
+ const invoiceId = idOf(invoicePayment?.invoice);
269
+ if (!invoiceId)
270
+ return null;
271
+ const invoice = await retrieveInvoice(stripe, invoiceId, onIt);
272
+ if (!invoice.metadata?.plumbus_charge_id)
273
+ return null;
274
+ const latest = intent.latest_charge;
275
+ return {
276
+ ...mapInvoiceCharge(invoice),
277
+ paymentId,
278
+ amountRefunded: latest && typeof latest === 'object'
279
+ ? (latest.amount_refunded ?? 0)
280
+ : null,
281
+ };
282
+ }
283
+ export async function captureCharge(stripe, input) {
284
+ const intent = await stripe.paymentIntents.capture(input.paymentId, {
285
+ ...(input.amount !== undefined ? { amount_to_capture: input.amount } : {}),
286
+ ...(input.platformFeeAmount !== undefined && input.routing.flow !== 'platform'
287
+ ? { application_fee_amount: input.platformFeeAmount }
288
+ : {}),
289
+ expand: ['latest_charge'],
290
+ }, { ...onAccount(chargeAccount(input.routing)), idempotencyKey: input.idempotencyKey });
291
+ return mapIntent(intent);
292
+ }
293
+ const CANCELABLE_INTENT = new Set([
294
+ 'requires_payment_method',
295
+ 'requires_confirmation',
296
+ 'requires_action',
297
+ 'requires_capture',
298
+ 'processing',
299
+ ]);
300
+ async function releaseIntent(stripe, paymentId, options) {
301
+ const intent = await retrieveIntent(stripe, paymentId, options);
302
+ if (!CANCELABLE_INTENT.has(intent.status))
303
+ return intent;
304
+ return (await stripe.paymentIntents.cancel(paymentId, { expand: ['latest_charge'] }, options));
305
+ }
306
+ /** Stop a charge: expire its payment page, void its invoice, or release its hold. */
307
+ export async function cancelCharge(stripe, input) {
308
+ const onIt = onAccount(chargeAccount(input.routing));
309
+ if (input.collection === 'invoice') {
310
+ const invoice = await retrieveInvoice(stripe, input.chargeId, onIt);
311
+ if (invoice.status === 'draft') {
312
+ await stripe.invoices.del(input.chargeId, onIt);
313
+ return { ...mapInvoiceCharge(invoice), status: 'canceled', url: null };
314
+ }
315
+ if (invoice.status === 'open') {
316
+ await stripe.invoices.voidInvoice(input.chargeId, {}, onIt);
317
+ return mapInvoiceCharge(await retrieveInvoice(stripe, input.chargeId, onIt));
318
+ }
319
+ return mapInvoiceCharge(invoice);
320
+ }
321
+ // A payment page: the charge's own, or one opened for a saved method that needed the client.
322
+ if (input.chargeId.startsWith('cs_')) {
323
+ let session = (await stripe.checkout.sessions.retrieve(input.chargeId, { expand: [...SESSION_EXPAND] }, onIt));
324
+ if (session.status === 'open') {
325
+ session = (await stripe.checkout.sessions.expire(input.chargeId, { expand: [...SESSION_EXPAND] }, onIt));
326
+ }
327
+ else if (idOf(session.payment_intent) && input.collection !== 'saved_method') {
328
+ // A completed page with a hold: release it.
329
+ await releaseIntent(stripe, idOf(session.payment_intent), onIt);
330
+ session = (await stripe.checkout.sessions.retrieve(input.chargeId, { expand: [...SESSION_EXPAND] }, onIt));
331
+ }
332
+ if (input.collection !== 'saved_method' || !input.paymentId)
333
+ return mapSession(session);
334
+ }
335
+ // A saved method charged off-session: the PaymentIntent is the charge.
336
+ const paymentId = input.paymentId ?? input.chargeId;
337
+ return mapIntent(await releaseIntent(stripe, paymentId, onIt));
338
+ }
339
+ //# sourceMappingURL=charges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"charges.js","sourceRoot":"","sources":["../src/charges.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { MerchantDashboard, NormalizedPaymentsConfig, PaymentsFinding, Responsibility } from '@plumbus/payments';
2
+ export declare function stripeDefaultResponsibilities(dashboard: MerchantDashboard): {
3
+ fees: Responsibility;
4
+ losses: Responsibility;
5
+ };
6
+ export declare function validateStripeConfig(config: NormalizedPaymentsConfig): PaymentsFinding[];
7
+ //# sourceMappingURL=config-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-rules.d.ts","sourceRoot":"","sources":["../src/config-rules.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,iBAAiB,EACjB,wBAAwB,EACxB,eAAe,EACf,cAAc,EACf,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,6BAA6B,CAAC,SAAS,EAAE,iBAAiB,GAAG;IAC3E,IAAI,EAAE,cAAc,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB,CAKA;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,wBAAwB,GAAG,eAAe,EAAE,CAiFxF"}
@@ -0,0 +1,87 @@
1
+ // ── Stripe Connect rules for the payments config ──
2
+ // Encodes what Stripe's Accounts v2 API accepts (hard errors) and what Stripe
3
+ // recommends (warnings/info). Sources: Stripe "Configure the behavior of
4
+ // connected accounts", "Recommended Connect integrations", and the v2 account
5
+ // create error codes. Recommended pairs: full dashboard with direct charges;
6
+ // Express or no dashboard with destination charges and platform liability.
7
+ export function stripeDefaultResponsibilities(dashboard) {
8
+ // Express requires your platform to carry both; full and none default to Stripe.
9
+ return dashboard === 'express'
10
+ ? { fees: 'platform', losses: 'platform' }
11
+ : { fees: 'provider', losses: 'provider' };
12
+ }
13
+ export function validateStripeConfig(config) {
14
+ const findings = [];
15
+ for (const [name, option] of Object.entries(config.dashboards)) {
16
+ const path = `dashboards.${name}`;
17
+ if (name === 'express' && (option.fees !== 'platform' || option.losses !== 'platform')) {
18
+ findings.push({
19
+ level: 'error',
20
+ code: 'stripe_express_needs_platform_liability',
21
+ path,
22
+ message: 'Stripe requires Express-dashboard sellers to have your platform pay fees and cover losses (fees: "platform", losses: "platform")',
23
+ });
24
+ }
25
+ if (option.losses === 'platform' && option.fees !== 'platform') {
26
+ findings.push({
27
+ level: 'error',
28
+ code: 'stripe_platform_losses_need_platform_fees',
29
+ path,
30
+ message: 'Stripe requires fees: "platform" whenever losses: "platform"',
31
+ });
32
+ }
33
+ if (option.losses === 'platform') {
34
+ findings.push({
35
+ level: 'warning',
36
+ code: 'stripe_platform_covers_losses',
37
+ path: `${path}.losses`,
38
+ message: 'Your platform covers negative balances for these sellers; Stripe may hold a reserve on your balance and expects you to manage seller risk',
39
+ });
40
+ }
41
+ if (name === 'none' && option.losses === 'platform') {
42
+ findings.push({
43
+ level: 'warning',
44
+ code: 'stripe_platform_collects_requirements',
45
+ path,
46
+ message: 'With no dashboard and platform-covered losses, your platform is responsible for collecting seller identity requirements (Stripe onboarding pages can still do the collecting)',
47
+ });
48
+ }
49
+ const chargeType = config.chargeType[name] ?? 'direct';
50
+ if (chargeType === 'destination' &&
51
+ (option.fees !== 'platform' || option.losses !== 'platform')) {
52
+ // With no dashboard, platform losses also make the platform collect identity requirements.
53
+ findings.push({
54
+ level: name === 'none' ? 'info' : 'warning',
55
+ code: 'stripe_destination_recommends_platform_liability',
56
+ path,
57
+ message: name === 'none'
58
+ ? 'Stripe recommends fees: "platform" and losses: "platform" for sellers paid by destination charges; with no dashboard that also makes your platform collect their identity requirements, so keeping Stripe-covered losses is a reasonable choice'
59
+ : 'Stripe recommends fees: "platform" and losses: "platform" for sellers paid by destination charges (your platform is the merchant of record and pays the Stripe fees either way)',
60
+ });
61
+ }
62
+ if (name !== 'full' && chargeType === 'direct') {
63
+ findings.push({
64
+ level: 'warning',
65
+ code: 'stripe_direct_charges_on_limited_dashboard',
66
+ path: `chargeType.${name}`,
67
+ message: `Stripe recommends destination charges for ${name}-dashboard sellers: with direct charges their customers see the seller as the merchant, and the seller handles refunds and disputes with limited tools`,
68
+ });
69
+ findings.push({
70
+ level: 'info',
71
+ code: 'stripe_radar_rules',
72
+ path,
73
+ message: `Sellers on the ${name} dashboard cannot set their own Radar fraud rules, and your platform rules do not apply to their direct charges; set rules per seller with "View Dashboard as this account"`,
74
+ });
75
+ }
76
+ if (name === 'full' && chargeType === 'destination') {
77
+ findings.push({
78
+ level: 'info',
79
+ code: 'stripe_destination_on_full_dashboard',
80
+ path: `chargeType.${name}`,
81
+ message: 'Stripe recommends direct charges for full-dashboard sellers, who run their own Stripe account; with destination charges your platform is the merchant of record for their sales',
82
+ });
83
+ }
84
+ }
85
+ return findings;
86
+ }
87
+ //# sourceMappingURL=config-rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-rules.js","sourceRoot":"","sources":["../src/config-rules.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CatalogInput, PaymentsFinding, WebhookSetupResult } from '@plumbus/payments';
2
+ import Stripe from 'stripe';
3
+ export declare const STRIPE_API_VERSION: "2026-08-26.dahlia";
4
+ export declare const STRIPE_DESTINATION_NAMES: {
5
+ readonly snapshot: "plumbus-payments-sellers";
6
+ readonly thin: "plumbus-payments-accounts";
7
+ };
8
+ export declare function diagnoseStripe(input: {
9
+ client: () => Promise<Stripe>;
10
+ secretKey: () => Promise<string>;
11
+ webhookSecrets: () => Promise<readonly string[]>;
12
+ webhookUrl: string | undefined;
13
+ catalog: CatalogInput | undefined;
14
+ }): Promise<PaymentsFinding[]>;
15
+ export declare function setupStripeDestinations(stripe: Stripe, url: string): Promise<WebhookSetupResult>;
16
+ export declare function messageOf(err: unknown): string;
17
+ //# sourceMappingURL=diagnose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../src/diagnose.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,MAAM,MAAM,QAAQ,CAAC;AAK5B,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AAErD,eAAO,MAAM,wBAAwB;;;CAG3B,CAAC;AAwCX,wBAAsB,cAAc,CAAC,KAAK,EAAE;IAC1C,MAAM,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,cAAc,EAAE,MAAM,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IACjD,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;CACnC,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA4J7B;AAED,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,kBAAkB,CAAC,CAoD7B;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAE9C"}