@fantastic.dev/better-stripe 0.13.0 → 0.14.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 (77) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +30 -1
  3. package/dist/client/connect/disputes.d.ts +20 -0
  4. package/dist/client/connect/disputes.d.ts.map +1 -1
  5. package/dist/client/connect/disputes.js +55 -0
  6. package/dist/client/connect/disputes.js.map +1 -1
  7. package/dist/client/costRecovery-invoices.d.ts +10 -4
  8. package/dist/client/costRecovery-invoices.d.ts.map +1 -1
  9. package/dist/client/costRecovery-invoices.js +4 -0
  10. package/dist/client/costRecovery-invoices.js.map +1 -1
  11. package/dist/client/costRecovery.d.ts +18 -2
  12. package/dist/client/costRecovery.d.ts.map +1 -1
  13. package/dist/client/costRecovery.js +4 -0
  14. package/dist/client/costRecovery.js.map +1 -1
  15. package/dist/client/errors.d.ts +1 -1
  16. package/dist/client/errors.d.ts.map +1 -1
  17. package/dist/client/errors.js.map +1 -1
  18. package/dist/client/index.d.ts +5 -14
  19. package/dist/client/index.d.ts.map +1 -1
  20. package/dist/client/index.js +3 -7
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/component/_generated/component.d.ts +59 -0
  23. package/dist/component/_generated/component.d.ts.map +1 -1
  24. package/dist/component/costRecovery/claims.d.ts +12 -0
  25. package/dist/component/costRecovery/claims.d.ts.map +1 -1
  26. package/dist/component/costRecovery/imports.d.ts +53 -0
  27. package/dist/component/costRecovery/imports.d.ts.map +1 -0
  28. package/dist/component/costRecovery/imports.js +67 -0
  29. package/dist/component/costRecovery/imports.js.map +1 -0
  30. package/dist/component/costRecovery/mutations.d.ts +47 -0
  31. package/dist/component/costRecovery/mutations.d.ts.map +1 -1
  32. package/dist/component/costRecovery/mutations.js +7 -1
  33. package/dist/component/costRecovery/mutations.js.map +1 -1
  34. package/dist/component/costRecovery/queries.d.ts +12 -0
  35. package/dist/component/costRecovery/queries.d.ts.map +1 -1
  36. package/dist/component/costRecovery/schema.d.ts +72 -2
  37. package/dist/component/costRecovery/schema.d.ts.map +1 -1
  38. package/dist/component/costRecovery/schema.js +13 -0
  39. package/dist/component/costRecovery/schema.js.map +1 -1
  40. package/dist/component/schema.d.ts +19 -1
  41. package/dist/react/workflows/EvidenceUpload.d.ts +18 -0
  42. package/dist/react/workflows/EvidenceUpload.d.ts.map +1 -0
  43. package/dist/react/workflows/EvidenceUpload.js +35 -0
  44. package/dist/react/workflows/EvidenceUpload.js.map +1 -0
  45. package/dist/react/workflows/Onboarding.d.ts +3 -3
  46. package/dist/react/workflows/Onboarding.d.ts.map +1 -1
  47. package/dist/react/workflows/Onboarding.js +8 -6
  48. package/dist/react/workflows/Onboarding.js.map +1 -1
  49. package/dist/react/workflows/index.d.ts +2 -0
  50. package/dist/react/workflows/index.d.ts.map +1 -1
  51. package/dist/react/workflows/index.js +1 -0
  52. package/dist/react/workflows/index.js.map +1 -1
  53. package/dist/react/workflows/useWorkflowAction.d.ts +1 -1
  54. package/dist/react/workflows/useWorkflowAction.d.ts.map +1 -1
  55. package/dist/react/workflows/useWorkflowAction.js +6 -2
  56. package/dist/react/workflows/useWorkflowAction.js.map +1 -1
  57. package/docs/react-workflows.md +42 -0
  58. package/package.json +1 -1
  59. package/src/client/connect/dispute-upload.test.ts +208 -0
  60. package/src/client/connect/disputes.ts +103 -0
  61. package/src/client/costRecovery-import.test.ts +174 -0
  62. package/src/client/costRecovery-invoices.test.ts +69 -0
  63. package/src/client/costRecovery-invoices.ts +32 -0
  64. package/src/client/costRecovery.ts +16 -0
  65. package/src/client/errors.ts +1 -0
  66. package/src/client/index.ts +14 -13
  67. package/src/component/_generated/api.ts +2 -0
  68. package/src/component/_generated/component.ts +65 -0
  69. package/src/component/costRecovery/imports.ts +74 -0
  70. package/src/component/costRecovery/mutations.ts +8 -0
  71. package/src/component/costRecovery/schema.ts +13 -0
  72. package/src/react/workflows/EvidenceUpload.test.tsx +56 -0
  73. package/src/react/workflows/EvidenceUpload.tsx +71 -0
  74. package/src/react/workflows/Onboarding.test.tsx +73 -0
  75. package/src/react/workflows/Onboarding.tsx +8 -5
  76. package/src/react/workflows/index.ts +3 -0
  77. package/src/react/workflows/useWorkflowAction.ts +6 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/workflows/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/workflows/index.ts"],"names":[],"mappings":"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"}
@@ -40,4 +40,5 @@ export { Pagination, useCursorPagination } from "./Pagination.js";
40
40
  export { PlanPricingEditor } from "./PlanPricingEditor.js";
41
41
  export { AffiliateRateEditor } from "./AffiliateRateEditor.js";
42
42
  export { AffiliatePayoutEditor } from "./AffiliatePayoutEditor.js";
43
+ export { EvidenceUpload } from "./EvidenceUpload.js";
43
44
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/workflows/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/react/workflows/index.ts"],"names":[],"mappings":"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"}
@@ -7,5 +7,5 @@ export type WorkflowActionState<T, Args extends unknown[]> = {
7
7
  reset: () => void;
8
8
  };
9
9
  /** Shared async action lifecycle. Scope identifies the authenticated account/resource, not authorization. */
10
- export declare function useWorkflowAction<T, Args extends unknown[]>(action: (...args: Args) => Promise<T>, scope?: string): WorkflowActionState<T, Args>;
10
+ export declare function useWorkflowAction<T, Args extends unknown[]>(action: (...args: Args) => Promise<T>, scope?: string, onSuccess?: (result: T) => void): WorkflowActionState<T, Args>;
11
11
  //# sourceMappingURL=useWorkflowAction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useWorkflowAction.d.ts","sourceRoot":"","sources":["../../../src/react/workflows/useWorkflowAction.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,CAAC,CAAC,EAAE,IAAI,SAAS,OAAO,EAAE,IAAI;IAC3D,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IACtB,gFAAgF;IAChF,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AACF,6GAA6G;AAC7G,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,OAAO,EAAE,EACzD,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACrC,KAAK,GAAE,MAAkB,GACxB,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CA4D9B"}
1
+ {"version":3,"file":"useWorkflowAction.d.ts","sourceRoot":"","sources":["../../../src/react/workflows/useWorkflowAction.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,CAAC,CAAC,EAAE,IAAI,SAAS,OAAO,EAAE,IAAI;IAC3D,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC;IACtB,gFAAgF;IAChF,GAAG,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AACF,6GAA6G;AAC7G,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,SAAS,OAAO,EAAE,EACzD,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACrC,KAAK,GAAE,MAAkB,EACzB,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,GAC9B,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CAgE9B"}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { useCallback, useEffect, useRef, useState } from "react";
3
3
  /** Shared async action lifecycle. Scope identifies the authenticated account/resource, not authorization. */
4
- export function useWorkflowAction(action, scope = "default") {
4
+ export function useWorkflowAction(action, scope = "default", onSuccess) {
5
5
  const initial = {
6
6
  scope,
7
7
  isPending: false,
@@ -12,11 +12,13 @@ export function useWorkflowAction(action, scope = "default") {
12
12
  if (state.scope !== scope)
13
13
  setState(initial);
14
14
  const callback = useRef(action);
15
+ const success = useRef(onSuccess);
15
16
  const lifecycle = useRef({ version: 0, mounted: false });
16
17
  const lock = useRef(null);
17
18
  useEffect(() => {
18
19
  callback.current = action;
19
- }, [action]);
20
+ success.current = onSuccess;
21
+ }, [action, onSuccess]);
20
22
  useEffect(() => {
21
23
  const version = ++lifecycle.current.version;
22
24
  lifecycle.current.mounted = true;
@@ -41,10 +43,12 @@ export function useWorkflowAction(action, scope = "default") {
41
43
  lock.current = version;
42
44
  setState({ scope, isPending: true, error: null, result: undefined });
43
45
  const current = () => lifecycle.current.mounted && lifecycle.current.version === version;
46
+ const complete = success.current;
44
47
  try {
45
48
  const result = await callback.current(...args);
46
49
  if (!current())
47
50
  return undefined;
51
+ complete?.(result);
48
52
  setState({ scope, isPending: false, error: null, result });
49
53
  return result;
50
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useWorkflowAction.js","sourceRoot":"","sources":["../../../src/react/workflows/useWorkflowAction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useWorkflowAction.js","sourceRoot":"","sources":["../../../src/react/workflows/useWorkflowAction.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AACb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AASjE,6GAA6G;AAC7G,MAAM,UAAU,iBAAiB,CAC/B,MAAqC,EACrC,KAAK,GAAW,SAAS,EACzB,SAA+B;IAE/B,MAAM,OAAO,GAAG;QACd,KAAK;QACL,SAAS,EAAE,KAAK;QAChB,KAAK,EAAE,IAAqB;QAC5B,MAAM,EAAE,SAA0B;KACnC,CAAC;IACF,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,KAAK,CAAC,KAAK,KAAK,KAAK;QAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACzD,MAAM,IAAI,GAAG,MAAM,CAAgB,IAAI,CAAC,CAAC;IACzC,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,OAAO,GAAG,MAAM,CAAC;QAC1B,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAC9B,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACxB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,OAAO,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;QAC5C,SAAS,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,OAAO,GAAG,EAAE;YACV,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAC1C,SAAS,CAAC,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;gBAClC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACtB,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO;QAClC,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACxE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,MAAM,GAAG,GAAG,WAAW,CACrB,KAAK,EAAE,GAAG,IAAU,EAAE,EAAE;QACtB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC;QAC5C,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;QAC1C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACrE,MAAM,OAAO,GAAG,GAAG,EAAE,CACnB,SAAS,CAAC,OAAO,CAAC,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC;QACrE,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO,EAAE;gBAAE,OAAO,SAAS,CAAC;YACjC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;YACnB,QAAQ,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;YAC3D,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO,EAAE;gBACX,QAAQ,CAAC;oBACP,KAAK;oBACL,SAAS,EAAE,KAAK;oBAChB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;oBAC7D,MAAM,EAAE,SAAS;iBAClB,CAAC,CAAC;YACL,OAAO,SAAS,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO;gBAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpD,CAAC;IACH,CAAC,EACD,CAAC,KAAK,CAAC,CACR,CAAC;IACF,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC"}
@@ -489,3 +489,45 @@ original method and types; it does not retry an unpaid invoice or automatically
489
489
  fall back to a card. The example demonstrates durable preparation and pending
490
490
  operation records in `storeBalanceFunding.ts` with a separate preview client.
491
491
  See the [README balance-funding workflow](../README.md#optional-balance-funded-subscriptions).
492
+
493
+ ## Dispute evidence uploads and onboarding navigation
494
+
495
+ `EvidenceUpload` is an unstyled control with render props. Its `scopeKey` must
496
+ include the authenticated scope and selected dispute. Bind `onUpload(file)` to
497
+ an authenticated server callback, convert the file to bytes there, and call
498
+ `betterStripe.uploadDisputeEvidence(ctx, { stripeDisputeId, actor, field, file })`.
499
+ The example seller disputes page demonstrates a communication-file attachment.
500
+ The example uses demo personas, so production applications must replace its
501
+ persona authorization with a session-derived actor and dispute ownership check.
502
+ Never accept an actor, connected request account, or attachment file ID from the
503
+ browser as authorization.
504
+
505
+ The server API accepts nonempty PDF, JPEG or PNG bytes up to 5,000,000 bytes. MIME
506
+ type and file signature must match. Stripe performs full document validation and
507
+ may reject corrupt documents or apply additional dispute/network limits. See
508
+ [Stripe's file upload guide](https://docs.stripe.com/file-upload) and
509
+ [evidence troubleshooting](https://support.stripe.com/questions/evidence-submission-troubleshooting-faq).
510
+ Authorization runs before uploading and again before binding. The API uploads
511
+ with `purpose: "dispute_evidence"`, binds only the returned ID to the chosen
512
+ file evidence field, and explicitly sends `submit: false`. Uploading never sends
513
+ evidence to the bank. Continue using `EvidenceForm.stage()` for prose drafts and
514
+ `EvidenceForm.submit()` for explicit final submission.
515
+
516
+ `DISPUTE_UPLOAD_FAILED` carries structured provider error details. An attachment
517
+ failure reports `DISPUTE_UPDATE_FAILED`; the uploaded file can remain at Stripe
518
+ without a draft attachment. Keep the local file and prose draft so the user can
519
+ retry. Do not mark an upload as attached until the entire callback succeeds.
520
+ Convex action payload limits can be lower than Stripe's file limit. For larger
521
+ files, authorize and load a private storage reference on the server, then pass
522
+ its bytes to the package. The example byte-action transport is for small files.
523
+
524
+ `useWorkflowAction(action, scopeKey, onSuccess)` invokes `onSuccess` only after
525
+ checking that the response still belongs to the mounted scope. `useOnboarding`
526
+ uses this lifecycle for both create and continue navigation, including its
527
+ `window.location.assign` fallback. An old response cannot navigate after unmount
528
+ or scope replacement. Current requests preserve shared pending locks and errors.
529
+ These APIs ship in the release containing the dispute-upload and stale-navigation
530
+ implementation PR. Version 0.13.0 does not contain them. Consumers must upgrade
531
+ to that release before removing their navigation guard or using the upload API.
532
+ Production storage, session authorization, styling, translations and extended
533
+ hosted onboarding verification remain application responsibilities.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fantastic.dev/better-stripe",
3
- "version": "0.13.0",
3
+ "version": "0.14.0",
4
4
  "description": "A Convex component for Stripe V2 Accounts API integration.",
5
5
  "keywords": [
6
6
  "stripe",
@@ -0,0 +1,208 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+
3
+ import type { Component, RunCtx } from "../helpers.js";
4
+ import { updateDispute, uploadDisputeEvidence } from "./disputes.js";
5
+
6
+ function makeStripe() {
7
+ return {
8
+ disputes: {
9
+ update: vi.fn().mockResolvedValue({}),
10
+ close: vi.fn().mockResolvedValue({}),
11
+ },
12
+ };
13
+ }
14
+ const asStripe = (s: ReturnType<typeof makeStripe>) =>
15
+ s as unknown as Parameters<typeof updateDispute>[0];
16
+
17
+ const TO_REF = Symbol.for("toReferencePath");
18
+
19
+ /**
20
+ * Component proxy exposing the two connect query refs the dispute-action
21
+ * authorization resolves: the dispute (by its Stripe id) and the payment that
22
+ * dispute is linked to (by PaymentIntent id).
23
+ */
24
+ function makeAuthComponent(): Component {
25
+ const ref = (path: string) => ({ [TO_REF]: `betterStripe/${path}` });
26
+ return {
27
+ connect: {
28
+ queries: {
29
+ getDisputeByStripeId: ref("connect/queries/getDisputeByStripeId"),
30
+ getPaymentByStripeId: ref("connect/queries/getPaymentByStripeId"),
31
+ },
32
+ },
33
+ } as unknown as Component;
34
+ }
35
+
36
+ /**
37
+ * A ctx whose runQuery dispatches by the query args: a `stripeDisputeId` lookup
38
+ * resolves the dispute row; a `stripePaymentIntentId` lookup resolves the
39
+ * payment row. Either may be null to exercise the fail-closed paths.
40
+ */
41
+ function makeAuthCtx(disputeRow?: unknown, paymentRow?: unknown) {
42
+ const runQuery = vi.fn().mockImplementation((_ref, args) => {
43
+ if (args && "stripeDisputeId" in args)
44
+ return Promise.resolve(disputeRow ?? null);
45
+ if (args && "stripePaymentIntentId" in args)
46
+ return Promise.resolve(paymentRow ?? null);
47
+ return Promise.resolve(null);
48
+ });
49
+ return { runQuery } as unknown as RunCtx & {
50
+ runQuery: ReturnType<typeof vi.fn>;
51
+ };
52
+ }
53
+
54
+ describe("uploadDisputeEvidence", () => {
55
+ const file = {
56
+ data: new TextEncoder().encode("%PDF-1.7\nfixture"),
57
+ name: "evidence.pdf",
58
+ type: "application/pdf" as const,
59
+ };
60
+ const opts = {
61
+ stripeDisputeId: "dp_1",
62
+ actor: { type: "seller" as const, accountId: "acct_owner" },
63
+ field: "customer_communication" as const,
64
+ file,
65
+ };
66
+ function setup(owner = "acct_owner") {
67
+ const stripe = {
68
+ ...makeStripe(),
69
+ files: { create: vi.fn().mockResolvedValue({ id: "file_uploaded" }) },
70
+ };
71
+ const ctx = makeAuthCtx(
72
+ { stripePaymentIntentId: "pi_1" },
73
+ { destinationAccountId: owner },
74
+ );
75
+ return { stripe, ctx };
76
+ }
77
+ it("uploads bytes and binds only the returned file ID as draft", async () => {
78
+ const { stripe, ctx } = setup();
79
+ const result = await uploadDisputeEvidence(
80
+ asStripe(stripe),
81
+ makeAuthComponent(),
82
+ ctx,
83
+ opts,
84
+ );
85
+ expect(stripe.files.create).toHaveBeenCalledWith(
86
+ { purpose: "dispute_evidence", file },
87
+ undefined,
88
+ );
89
+ expect(stripe.disputes.update).toHaveBeenCalledWith(
90
+ "dp_1",
91
+ { evidence: { customer_communication: "file_uploaded" }, submit: false },
92
+ undefined,
93
+ );
94
+ expect(result).toEqual({
95
+ stripeFileId: "file_uploaded",
96
+ stripeDisputeId: "dp_1",
97
+ });
98
+ });
99
+ it("denies another seller before uploading", async () => {
100
+ const { stripe, ctx } = setup("acct_other");
101
+ await expect(
102
+ uploadDisputeEvidence(asStripe(stripe), makeAuthComponent(), ctx, opts),
103
+ ).rejects.toThrow(/not authorized/);
104
+ expect(stripe.files.create).not.toHaveBeenCalled();
105
+ expect(stripe.disputes.update).not.toHaveBeenCalled();
106
+ });
107
+ it.each([
108
+ { ...file, type: "text/plain" },
109
+ { ...file, data: new Uint8Array(0) },
110
+ { ...file, data: new Uint8Array(5_000_001) },
111
+ { ...file, data: new TextEncoder().encode("not a PDF") },
112
+ ])("rejects invalid files before provider calls", async (file) => {
113
+ const { stripe, ctx } = setup();
114
+ await expect(
115
+ uploadDisputeEvidence(asStripe(stripe), makeAuthComponent(), ctx, {
116
+ ...opts,
117
+ file: file as typeof opts.file,
118
+ }),
119
+ ).rejects.toThrow(/Invalid dispute evidence/);
120
+ expect(stripe.files.create).not.toHaveBeenCalled();
121
+ });
122
+ it("does not attach after an upload failure and preserves provider errors", async () => {
123
+ const { stripe, ctx } = setup();
124
+ stripe.files.create.mockRejectedValue({
125
+ type: "StripeInvalidRequestError",
126
+ code: "file_invalid",
127
+ message: "Corrupt PDF",
128
+ });
129
+ await expect(
130
+ uploadDisputeEvidence(asStripe(stripe), makeAuthComponent(), ctx, opts),
131
+ ).rejects.toMatchObject({
132
+ data: {
133
+ code: "DISPUTE_UPLOAD_FAILED",
134
+ stripeError: { code: "file_invalid" },
135
+ },
136
+ });
137
+ expect(stripe.disputes.update).not.toHaveBeenCalled();
138
+ });
139
+ it("surfaces draft attachment failure without submitting", async () => {
140
+ const { stripe, ctx } = setup();
141
+ stripe.disputes.update.mockRejectedValue(new Error("unavailable"));
142
+ await expect(
143
+ uploadDisputeEvidence(asStripe(stripe), makeAuthComponent(), ctx, opts),
144
+ ).rejects.toMatchObject({ data: { code: "DISPUTE_UPDATE_FAILED" } });
145
+ expect(stripe.disputes.update.mock.calls[0][1].submit).toBe(false);
146
+ });
147
+ });
148
+
149
+ it.each([
150
+ {
151
+ type: "image/png" as const,
152
+ data: new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]),
153
+ },
154
+ { type: "image/jpeg" as const, data: new Uint8Array([255, 216, 255]) },
155
+ ])(
156
+ "uploads supported image signatures to the owning request account",
157
+ async (file) => {
158
+ const stripe = {
159
+ ...makeStripe(),
160
+ files: { create: vi.fn().mockResolvedValue({ id: "file_image" }) },
161
+ };
162
+ await uploadDisputeEvidence(
163
+ asStripe(stripe),
164
+ makeAuthComponent(),
165
+ {} as RunCtx,
166
+ {
167
+ actor: { type: "admin" },
168
+ stripeDisputeId: "dp_1",
169
+ stripeAccountId: "acct_direct",
170
+ field: "receipt",
171
+ file: { ...file, name: "proof" },
172
+ },
173
+ );
174
+ expect(stripe.files.create.mock.calls[0][1]).toEqual({
175
+ stripeAccount: "acct_direct",
176
+ });
177
+ expect(stripe.disputes.update.mock.calls[0][2]).toEqual({
178
+ stripeAccount: "acct_direct",
179
+ });
180
+ },
181
+ );
182
+
183
+ it("rejects a malformed seller actor before any provider call", async () => {
184
+ const stripe = {
185
+ ...makeStripe(),
186
+ files: { create: vi.fn().mockResolvedValue({ id: "file_1" }) },
187
+ };
188
+ await expect(
189
+ uploadDisputeEvidence(
190
+ asStripe(stripe),
191
+ makeAuthComponent(),
192
+ makeAuthCtx({ stripePaymentIntentId: "pi_1" }, {}),
193
+ {
194
+ actor: { type: "seller" } as Parameters<
195
+ typeof uploadDisputeEvidence
196
+ >[3]["actor"],
197
+ stripeDisputeId: "dp_1",
198
+ field: "receipt",
199
+ file: {
200
+ data: new TextEncoder().encode("%PDF-1.7"),
201
+ name: "a.pdf",
202
+ type: "application/pdf",
203
+ },
204
+ },
205
+ ),
206
+ ).rejects.toThrow(/authenticated actor/);
207
+ expect(stripe.files.create).not.toHaveBeenCalled();
208
+ });
@@ -148,6 +148,109 @@ export async function updateDispute(
148
148
  }
149
149
  }
150
150
 
151
+ /** File fields supported by Stripe dispute evidence. */
152
+ export type DisputeEvidenceFileField =
153
+ | "cancellation_policy"
154
+ | "customer_communication"
155
+ | "customer_signature"
156
+ | "duplicate_charge_documentation"
157
+ | "receipt"
158
+ | "refund_policy"
159
+ | "service_documentation"
160
+ | "shipping_documentation"
161
+ | "uncategorized_file";
162
+ export type DisputeEvidenceUploadOptions = {
163
+ stripeDisputeId: string;
164
+ /** Derive this on the server from the authenticated session. */
165
+ actor: RefundActor;
166
+ field: DisputeEvidenceFileField;
167
+ file: {
168
+ data: Uint8Array;
169
+ name: string;
170
+ type: "application/pdf" | "image/jpeg" | "image/png";
171
+ };
172
+ /** Request account owning the charge, distinct from the seller actor. */
173
+ stripeAccountId?: string;
174
+ };
175
+
176
+ /** Upload and attach to one authorized dispute as a draft. Never submits. */
177
+ export async function uploadDisputeEvidence(
178
+ stripe: Stripe,
179
+ component: Component,
180
+ ctx: RunCtx,
181
+ opts: DisputeEvidenceUploadOptions,
182
+ ): Promise<{ stripeFileId: string; stripeDisputeId: string }> {
183
+ if (
184
+ !opts.actor ||
185
+ !["admin", "seller"].includes(opts.actor.type) ||
186
+ (opts.actor.type === "seller" &&
187
+ (typeof opts.actor.accountId !== "string" ||
188
+ !opts.actor.accountId.trim()))
189
+ )
190
+ throwStripeError(
191
+ "DISPUTE_UNAUTHORIZED",
192
+ "Dispute upload requires an authenticated actor",
193
+ );
194
+ await assertDisputeAuthorized(component, ctx, opts);
195
+ const fields: DisputeEvidenceFileField[] = [
196
+ "cancellation_policy",
197
+ "customer_communication",
198
+ "customer_signature",
199
+ "duplicate_charge_documentation",
200
+ "receipt",
201
+ "refund_policy",
202
+ "service_documentation",
203
+ "shipping_documentation",
204
+ "uncategorized_file",
205
+ ];
206
+ const { data, name, type } = opts.file;
207
+ const signature =
208
+ type === "application/pdf"
209
+ ? [37, 80, 68, 70, 45]
210
+ : type === "image/jpeg"
211
+ ? [255, 216, 255]
212
+ : type === "image/png"
213
+ ? [137, 80, 78, 71, 13, 10, 26, 10]
214
+ : [];
215
+ if (
216
+ !fields.includes(opts.field) ||
217
+ !(data instanceof Uint8Array) ||
218
+ !data.byteLength ||
219
+ data.byteLength > 5_000_000 ||
220
+ !name.trim() ||
221
+ !signature.length ||
222
+ !signature.every((byte, i) => data[i] === byte)
223
+ )
224
+ throwStripeError(
225
+ "INVALID_CONFIGURATION",
226
+ "Invalid dispute evidence: use a nonempty PDF, JPEG or PNG up to 5 MB with a matching MIME type and filename",
227
+ );
228
+ let stripeFileId: string;
229
+ try {
230
+ const file = await stripe.files.create(
231
+ { purpose: "dispute_evidence", file: { data, name, type } },
232
+ opts.stripeAccountId
233
+ ? { stripeAccount: opts.stripeAccountId }
234
+ : undefined,
235
+ );
236
+ stripeFileId = file.id;
237
+ } catch (err) {
238
+ throwStripeError(
239
+ "DISPUTE_UPLOAD_FAILED",
240
+ "Failed to upload dispute evidence",
241
+ err,
242
+ );
243
+ }
244
+ await updateDispute(stripe, component, ctx, {
245
+ stripeDisputeId: opts.stripeDisputeId,
246
+ actor: opts.actor,
247
+ stripeAccountId: opts.stripeAccountId,
248
+ evidence: { [opts.field]: stripeFileId },
249
+ submit: false,
250
+ });
251
+ return { stripeFileId, stripeDisputeId: opts.stripeDisputeId };
252
+ }
253
+
151
254
  /**
152
255
  * Accept a dispute (concede the chargeback). Irreversible.
153
256
  *
@@ -0,0 +1,174 @@
1
+ import { componentsGeneric, type FunctionReference } from "convex/server";
2
+ import { expect, it } from "vitest";
3
+ import schema from "../component/schema.js";
4
+ import { initConvexTest } from "./setup.test.js";
5
+ import { BetterStripe } from "./index.js";
6
+ import type { Component, RunCtx } from "./helpers.js";
7
+ const modules = import.meta.glob("../component/**/*.{ts,js,tsx,jsx}");
8
+ const scope = { accountId: "acct_owner", scopeKey: "store", currency: "usd" };
9
+ const observation = {
10
+ ...scope,
11
+ claimKey: "cost:ch_original",
12
+ sourceChargeId: "ch_original",
13
+ sourceGross: 10000,
14
+ sourceProcessingFee: 320,
15
+ amountDue: 320,
16
+ revision: 0,
17
+ };
18
+ async function setup() {
19
+ const t = initConvexTest();
20
+ t.registerComponent("betterStripe", schema, modules);
21
+ const ctx = {
22
+ runQuery: (
23
+ ref: FunctionReference<"query">,
24
+ args: Record<string, unknown>,
25
+ ) => t.query(ref, args),
26
+ runMutation: (
27
+ ref: FunctionReference<"mutation">,
28
+ args: Record<string, unknown>,
29
+ ) => t.mutation(ref, args),
30
+ } as unknown as RunCtx;
31
+ return {
32
+ ctx,
33
+ recovery: new BetterStripe(
34
+ componentsGeneric().betterStripe as unknown as Component,
35
+ {},
36
+ ).costRecovery,
37
+ };
38
+ }
39
+ it("imports verified opening collections once and preserves the snapshot across newer observations", async () => {
40
+ const { ctx, recovery } = await setup();
41
+ const input = {
42
+ ...observation,
43
+ operationKey: "cutover:legacy-row",
44
+ collectedAmount: 200,
45
+ };
46
+ const first = await recovery.importClaim(ctx, input);
47
+ expect(first).toMatchObject({
48
+ amountDue: 320,
49
+ collectedAmount: 200,
50
+ outstanding: 120,
51
+ reservedAmount: 0,
52
+ });
53
+ expect(await recovery.balance(ctx, scope)).toMatchObject({
54
+ amountDue: 320,
55
+ collectedAmount: 200,
56
+ outstanding: 120,
57
+ });
58
+ await recovery.recordClaim(ctx, {
59
+ ...observation,
60
+ amountDue: 100,
61
+ revision: 1,
62
+ });
63
+ const replay = await recovery.importClaim(ctx, input);
64
+ expect(replay).toMatchObject({
65
+ _id: first._id,
66
+ amountDue: 100,
67
+ revision: 1,
68
+ collectedAmount: 200,
69
+ outstanding: -100,
70
+ });
71
+ expect(await recovery.balance(ctx, scope)).toMatchObject({
72
+ amountDue: 100,
73
+ collectedAmount: 200,
74
+ outstanding: -100,
75
+ });
76
+ await expect(
77
+ recovery.importClaim(ctx, { ...input, collectedAmount: 201 }),
78
+ ).rejects.toThrow(/snapshot/i);
79
+ await expect(
80
+ recovery.importClaim(ctx, { ...input, accountId: "acct_other" }),
81
+ ).rejects.toThrow(/identity/i);
82
+ });
83
+ it("preserves signed credit collections and currency isolation without Stripe credentials", async () => {
84
+ const { ctx, recovery } = await setup();
85
+ await recovery.importClaim(ctx, {
86
+ ...observation,
87
+ amountDue: -500,
88
+ collectedAmount: -200,
89
+ operationKey: "credit-import",
90
+ });
91
+ await recovery.importClaim(ctx, {
92
+ ...observation,
93
+ claimKey: "cost:eur",
94
+ currency: "eur",
95
+ collectedAmount: 300,
96
+ operationKey: "eur-import",
97
+ });
98
+ expect(await recovery.balance(ctx, scope)).toMatchObject({
99
+ amountDue: -500,
100
+ collectedAmount: -200,
101
+ outstanding: -300,
102
+ });
103
+ expect(
104
+ await recovery.balance(ctx, { ...scope, currency: "eur" }),
105
+ ).toMatchObject({ amountDue: 320, collectedAmount: 300, outstanding: 20 });
106
+ });
107
+ it("refuses to overwrite live claims or import into a pending external recovery boundary", async () => {
108
+ const { ctx, recovery } = await setup();
109
+ await recovery.recordClaim(ctx, observation);
110
+ await expect(
111
+ recovery.importClaim(ctx, {
112
+ ...observation,
113
+ operationKey: "late-import",
114
+ collectedAmount: 200,
115
+ }),
116
+ ).rejects.toThrow(/existing/i);
117
+ await recovery.reserve(ctx, {
118
+ ...scope,
119
+ groupKey: "pending",
120
+ operationKey: "pending:1",
121
+ sourceKind: "invoice",
122
+ sourceId: "in_1",
123
+ maxDebit: 10000,
124
+ maxCredit: 10000,
125
+ });
126
+ await expect(
127
+ recovery.importClaim(ctx, {
128
+ ...observation,
129
+ claimKey: "other",
130
+ operationKey: "new-import",
131
+ collectedAmount: 10,
132
+ }),
133
+ ).rejects.toThrow(/pending/i);
134
+ await expect(
135
+ recovery.importClaim(ctx, {
136
+ ...observation,
137
+ claimKey: "invalid",
138
+ operationKey: "",
139
+ collectedAmount: 0.5,
140
+ }),
141
+ ).rejects.toThrow();
142
+ });
143
+ it("reserves only the uncollected remainder and keeps the opening import idempotent after collection", async () => {
144
+ const { ctx, recovery } = await setup();
145
+ const input = {
146
+ ...observation,
147
+ operationKey: "opening",
148
+ collectedAmount: 200,
149
+ };
150
+ await recovery.importClaim(ctx, input);
151
+ const group = {
152
+ ...scope,
153
+ groupKey: "funding",
154
+ operationKey: "funding:1",
155
+ sourceKind: "settlement" as const,
156
+ sourceId: "ch_funding",
157
+ sourceGross: 10000,
158
+ sourceProcessingFee: 320,
159
+ maxDebit: 10000,
160
+ maxCredit: 10000,
161
+ };
162
+ expect((await recovery.reserve(ctx, group)).group.amount).toBe(120);
163
+ await recovery.seal(ctx, { groupKey: "funding" });
164
+ await recovery.finish(ctx, { groupKey: "funding", outcome: "collect" });
165
+ await recovery.importClaim(ctx, input);
166
+ expect(await recovery.balance(ctx, scope)).toMatchObject({
167
+ amountDue: 320,
168
+ collectedAmount: 320,
169
+ outstanding: 0,
170
+ });
171
+ await expect(
172
+ recovery.importClaim(ctx, { ...input, claimKey: "other" }),
173
+ ).rejects.toThrow(/identity/i);
174
+ });