@farm.js/stripe 0.1.0-beta.102 → 0.1.0-beta.104
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/dist/index.d.ts.map +1 -1
- package/dist/index.js +90 -19
- package/package.json +3 -3
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAKL,KAAK,eAAe,EAEpB,KAAK,6BAA6B,EAClC,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC3B,MAAM,eAAe,CAAC;AAQvB,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC/F,OAAO,EAQL,KAAK,sCAAsC,EAE3C,KAAK,wCAAwC,EAI7C,KAAK,qCAAqC,EAS1C,KAAK,eAAe,EACpB,KAAK,sBAAsB,EAK3B,KAAK,wBAAwB,EAG7B,KAAK,2BAA2B,EAEhC,KAAK,mBAAmB,EAEzB,MAAM,aAAa,CAAC;AACrB,OAAO,EAUL,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EAKzB,KAAK,wBAAwB,EAS7B,KAAK,4BAA4B,EAElC,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,8BAA8B,EAC9B,iCAAiC,EACjC,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,EAC5B,6BAA6B,EAC7B,oCAAoC,EACpC,sCAAsC,EACtC,kCAAkC,EAClC,wCAAwC,EACxC,6BAA6B,EAC7B,8BAA8B,EAC9B,yBAAyB,EACzB,qCAAqC,EACrC,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,eAAe,EACf,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,2BAA2B,EAC3B,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,2BAA2B,EAC3B,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,4BAA4B,EAC5B,sBAAsB,EACtB,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,2BAA2B,EAC3B,kBAAkB,EAClB,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,kBAAmB,SAAQ,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;CAAG;AAEnG,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;AAExE,UAAU,6BAA6B;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,qBAAqB,CAAC,KAAK,EAAE;QAC3B,OAAO,EAAE,wBAAwB,CAAC;QAClC,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,KAAK,CAAC;YAChB,OAAO,EAAE,wBAAwB,CAAC;YAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC,CAAC;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAClC,mBAAmB,CAAC,EAAE,OAAO,CAAC;QAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;KACxB,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzC,mBAAmB,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChG,kBAAkB,CAAC,CAAC,KAAK,EAAE;QACzB,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,wBAAwB,CAAC;QAClC,SAAS,EAAE,KAAK,CAAC;YACf,OAAO,EAAE,wBAAwB,CAAC;YAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB,CAAC,CAAC;QACH,iBAAiB,CAAC,EAAE,qCAAqC,CAAC;KAC3D,GAAG,OAAO,CAAC;QACV,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,cAAc,EAAE,MAAM,CAAC;QACvB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;QAClC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;QAChC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,SAAS,EAAE,2BAA2B,EAAE,CAAC;KAC1C,CAAC,CAAC;IACH,WAAW,CAAC,CAAC,KAAK,EAAE;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,kBAAkB,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,4BAA4B,CAAC;KAC3C,GAAG,OAAO,CAAC;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,sBAAsB,CAAC,CAAC,KAAK,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAAC;KACvC,GAAG,OAAO,CAAC;QACV,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,MAAM,EAAE,wCAAwC,CAAC;QACjD,KAAK,EAAE,sCAAsC,EAAE,CAAC;KACjD,CAAC,CAAC;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACzE,qBAAqB,CAAC,KAAK,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,6BAA6B,CAAC,CAAC;CAC5C;AAkDD,mFAAmF;AACnF,MAAM,MAAM,yBAAyB,GAAG,MAAM,GAAG,wBAAwB,CAAC;AAE1E,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,yBAAyB,CAAC;IACrC,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,wBAAwB,EAAE,CAAC;IACtC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,qBAAqB,CAAC;IAC5B,SAAS,CAAC,EAAE,CACV,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,6BAA6B,KACnC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAyDD,KAAK,6BAA6B,CAChC,KAAK,SAAS,MAAM,GAAG,SAAS,EAChC,QAAQ,SAAS,MAAM,IACrB,KAAK,SAAS,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE5C,KAAK,sBAAsB,CAAC,MAAM,SAAS,sBAAsB,IAAI;IACnE,QAAQ,CAAC,YAAY,EAAE,6BAA6B,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAClG,QAAQ,CAAC,UAAU,EAAE,6BAA6B,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5F,QAAQ,CAAC,kBAAkB,EAAE,6BAA6B,CACxD,MAAM,CAAC,oBAAoB,CAAC,EAC5B,0BAA0B,CAC3B,CAAC;IACF,QAAQ,CAAC,YAAY,EAAE,6BAA6B,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAClG,QAAQ,CAAC,UAAU,EAAE,6BAA6B,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5F,QAAQ,CAAC,SAAS,EAAE,6BAA6B,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACzF,QAAQ,CAAC,cAAc,EAAE,6BAA6B,CACpD,MAAM,CAAC,gBAAgB,CAAC,EACxB,sBAAsB,CACvB,CAAC;IACF,QAAQ,CAAC,mBAAmB,EAAE,6BAA6B,CACzD,MAAM,CAAC,qBAAqB,CAAC,EAC7B,2BAA2B,CAC5B,CAAC;IACF,QAAQ,CAAC,eAAe,EAAE,6BAA6B,CACrD,MAAM,CAAC,iBAAiB,CAAC,EACzB,uBAAuB,CACxB,CAAC;IACF,QAAQ,CAAC,SAAS,EAAE,6BAA6B,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACzF,QAAQ,CAAC,YAAY,EAAE,6BAA6B,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAClG,QAAQ,CAAC,WAAW,EAAE,6BAA6B,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC,CAAC;IAC/F,QAAQ,CAAC,UAAU,EAAE,6BAA6B,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAC5F,QAAQ,CAAC,WAAW,EAAE,6BAA6B,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,kBAAkB,CAAC,CAAC;CAChG,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,kBAAkB,CAAC,EAAE,SAAS,CAAC;IAC/B,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAChC,eAAe,CAAC,EAAE,SAAS,CAAC;IAC5B,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB,CAAC;AAEF,KAAK,uBAAuB,CAAC,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,GAAG;IAClE,GAAG,EAAE,IAAI,CAAC;CACX,CAAC;AAEF,KAAK,qBAAqB,GAAG,wBAAwB,GAAG;IACtD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,wBAAwB,CAAC;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,EAAE,oBAAoB,GAAG,sBAAsB,CAAC;CAC5D,CAAC;AAuOF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmHQ,CAAC;AA6hFlC,wBAAgB,MAAM,CAAC,KAAK,CAAC,MAAM,SAAS,sBAAsB,GAAG,sBAAsB,GAAG,EAAE,EAC9F,KAAK,CAAC,EAAE,MAAM,GACb,uBAAuB,CAAC,sBAAsB,CAAC,CAAC;AACnD,wBAAgB,MAAM,CAAC,KAAK,CAAC,MAAM,SAAS,sBAAsB,GAAG,EAAE,EACrE,KAAK,CAAC,EAAE,MAAM,GACb,uBAAuB,CAAC,eAAe,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Stripe from "stripe";
|
|
2
|
-
import { createIntegrationOrm, defineIntegration, integrationRoute, } from "@farm.js/core";
|
|
2
|
+
import { createIntegrationOrm, declareSchemaTables, defineIntegration, integrationRoute, } from "@farm.js/core";
|
|
3
3
|
import { integrationConfig, normalizeWebhookConfig, resolveAppPath, toAbsoluteUrl, withSearchParams, } from "@farm.js/integration-utils";
|
|
4
4
|
import { createStripeClientApi, } from "./client.js";
|
|
5
5
|
import { ormStorageAdapter, } from "./storage.js";
|
|
@@ -1746,18 +1746,19 @@ function getBillingMeter(billing, key) {
|
|
|
1746
1746
|
const meter = billing?.meters?.[key];
|
|
1747
1747
|
return meter ?? null;
|
|
1748
1748
|
}
|
|
1749
|
-
function hasConfiguredStorageRuntimeClient(
|
|
1750
|
-
const storage =
|
|
1749
|
+
function hasConfiguredStorageRuntimeClient(config) {
|
|
1750
|
+
const storage = config.storage;
|
|
1751
1751
|
return (!!storage &&
|
|
1752
1752
|
typeof storage === "object" &&
|
|
1753
1753
|
"client" in storage &&
|
|
1754
1754
|
storage.client != null);
|
|
1755
1755
|
}
|
|
1756
|
-
async function resolveConfiguredStorageRuntimeClient(
|
|
1757
|
-
|
|
1756
|
+
async function resolveConfiguredStorageRuntimeClient(config) {
|
|
1757
|
+
// The guard is what establishes the shape, so narrowing happens after it.
|
|
1758
|
+
if (!hasConfiguredStorageRuntimeClient(config)) {
|
|
1758
1759
|
return undefined;
|
|
1759
1760
|
}
|
|
1760
|
-
const storage =
|
|
1761
|
+
const storage = config.storage;
|
|
1761
1762
|
const client = storage?.client;
|
|
1762
1763
|
return typeof client === "function"
|
|
1763
1764
|
? await client()
|
|
@@ -1771,7 +1772,7 @@ function createBillingHookTools(context, stripe, schema) {
|
|
|
1771
1772
|
stripe,
|
|
1772
1773
|
storage: {
|
|
1773
1774
|
getClient() {
|
|
1774
|
-
clientPromise ??= resolveConfiguredStorageRuntimeClient(context);
|
|
1775
|
+
clientPromise ??= resolveConfiguredStorageRuntimeClient(context.config);
|
|
1775
1776
|
return clientPromise;
|
|
1776
1777
|
},
|
|
1777
1778
|
getOrm() {
|
|
@@ -1785,7 +1786,7 @@ function createBillingHookTools(context, stripe, schema) {
|
|
|
1785
1786
|
};
|
|
1786
1787
|
}
|
|
1787
1788
|
function resolveConfiguredBillingStorage(context, tools) {
|
|
1788
|
-
if (!hasConfiguredStorageRuntimeClient(context)) {
|
|
1789
|
+
if (!hasConfiguredStorageRuntimeClient(context.config)) {
|
|
1789
1790
|
return undefined;
|
|
1790
1791
|
}
|
|
1791
1792
|
return ormStorageAdapter({
|
|
@@ -2013,6 +2014,23 @@ function createBillingSnapshotFromSubscriptionChange(owner, result, billing, pro
|
|
|
2013
2014
|
},
|
|
2014
2015
|
};
|
|
2015
2016
|
}
|
|
2017
|
+
/**
|
|
2018
|
+
* Decide whether a checkout session belongs to the authenticated owner.
|
|
2019
|
+
*
|
|
2020
|
+
* Session ids travel through success-url query strings, browser history, and
|
|
2021
|
+
* referrers, so holding one is not proof of ownership. Checkout stamps
|
|
2022
|
+
* `ownerId`/`ownerKind` into session metadata, which is the authoritative
|
|
2023
|
+
* binding; the owner's stored customer id is accepted as a fallback for
|
|
2024
|
+
* sessions created before that metadata existed.
|
|
2025
|
+
*/
|
|
2026
|
+
function sessionBelongsToOwner(session, owner, ownerCustomerId) {
|
|
2027
|
+
const sessionOwnerId = session.metadata?.ownerId;
|
|
2028
|
+
const sessionOwnerKind = session.metadata?.ownerKind;
|
|
2029
|
+
if (sessionOwnerId) {
|
|
2030
|
+
return sessionOwnerId === owner.id && (!sessionOwnerKind || sessionOwnerKind === owner.kind);
|
|
2031
|
+
}
|
|
2032
|
+
return Boolean(ownerCustomerId) && session.customerId === ownerCustomerId;
|
|
2033
|
+
}
|
|
2016
2034
|
async function resolveBillingSnapshotForSession(session, products, billing, persistence, context) {
|
|
2017
2035
|
if (!billing) {
|
|
2018
2036
|
return null;
|
|
@@ -2023,12 +2041,31 @@ async function resolveBillingSnapshotForSession(session, products, billing, pers
|
|
|
2023
2041
|
const getByCustomerId = requireBillingMethod(persistence.getBillingAccountByStripeCustomerId, "getBillingAccountByStripeCustomerId");
|
|
2024
2042
|
existingSnapshot = await getByCustomerId(session.customerId);
|
|
2025
2043
|
if (!owner) {
|
|
2044
|
+
// No signed-in caller (the webhook path): the session's customer is the
|
|
2045
|
+
// only binding available.
|
|
2026
2046
|
owner = existingSnapshot?.owner ?? null;
|
|
2027
2047
|
}
|
|
2028
2048
|
}
|
|
2029
2049
|
if (!owner) {
|
|
2030
2050
|
return null;
|
|
2031
2051
|
}
|
|
2052
|
+
// A signed-in caller must not be able to bind someone else's checkout to
|
|
2053
|
+
// themselves by presenting its session id. Checkout stamps ownerId into the
|
|
2054
|
+
// session metadata, and an already-persisted snapshot names the customer's
|
|
2055
|
+
// real owner; either disagreeing with the caller means this session is not
|
|
2056
|
+
// theirs.
|
|
2057
|
+
const sessionOwnerId = session.metadata?.ownerId;
|
|
2058
|
+
const sessionOwnerKind = session.metadata?.ownerKind;
|
|
2059
|
+
const boundOwner = existingSnapshot?.owner;
|
|
2060
|
+
const mismatchesCaller = (sessionOwnerId !== undefined &&
|
|
2061
|
+
(sessionOwnerId !== owner.id ||
|
|
2062
|
+
(sessionOwnerKind !== undefined && sessionOwnerKind !== owner.kind))) ||
|
|
2063
|
+
(boundOwner !== undefined &&
|
|
2064
|
+
boundOwner !== null &&
|
|
2065
|
+
(boundOwner.id !== owner.id || boundOwner.kind !== owner.kind));
|
|
2066
|
+
if (mismatchesCaller) {
|
|
2067
|
+
return null;
|
|
2068
|
+
}
|
|
2032
2069
|
return createBillingSnapshot(owner, session, billing, products, existingSnapshot?.planId ?? "free", existingSnapshot);
|
|
2033
2070
|
}
|
|
2034
2071
|
async function persistBillingSnapshot(snapshot, billing, persistence, previousSnapshot = null) {
|
|
@@ -2226,7 +2263,7 @@ export function stripe(input = {}) {
|
|
|
2226
2263
|
}
|
|
2227
2264
|
},
|
|
2228
2265
|
}));
|
|
2229
|
-
|
|
2266
|
+
const integration = defineIntegration({
|
|
2230
2267
|
category: "payment",
|
|
2231
2268
|
type: "stripe",
|
|
2232
2269
|
instance: {
|
|
@@ -3310,21 +3347,47 @@ export function stripe(input = {}) {
|
|
|
3310
3347
|
async handler(request, context) {
|
|
3311
3348
|
const body = await readJsonObject(request);
|
|
3312
3349
|
try {
|
|
3313
|
-
|
|
3350
|
+
const requestedCustomerId = typeof body.customerId === "string" ? body.customerId : undefined;
|
|
3351
|
+
const requestedSessionId = typeof body.sessionId === "string" ? body.sessionId : undefined;
|
|
3352
|
+
let customerId;
|
|
3314
3353
|
const billingTools = input.billing
|
|
3315
3354
|
? createBillingHookTools(context, stripeSdk, integrationSchema)
|
|
3316
3355
|
: undefined;
|
|
3317
3356
|
const persistence = resolveBillingPersistence(input.billing, context, stripeSdk, integrationSchema, billingTools);
|
|
3318
|
-
if (
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3357
|
+
if (input.billing) {
|
|
3358
|
+
// A portal session exposes invoices, payment methods, and
|
|
3359
|
+
// cancellation, so the signed-in owner is the only identity we
|
|
3360
|
+
// trust here. A customerId or sessionId from the request is
|
|
3361
|
+
// treated as a claim to verify, never as the identity itself.
|
|
3323
3362
|
const owner = await resolveBillingOwner(input.billing, context, persistence.tools);
|
|
3324
|
-
if (owner) {
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3363
|
+
if (!owner) {
|
|
3364
|
+
return Response.json({ error: "Stripe portal requires an authenticated billing owner." }, { status: 401 });
|
|
3365
|
+
}
|
|
3366
|
+
const getBillingAccount = requireBillingMethod(persistence.getBillingAccount, "getBillingAccount");
|
|
3367
|
+
const snapshot = await getBillingAccount(owner);
|
|
3368
|
+
customerId = snapshot?.stripeCustomerId ?? undefined;
|
|
3369
|
+
if (requestedCustomerId && requestedCustomerId !== customerId) {
|
|
3370
|
+
return Response.json({ error: "Stripe portal customerId does not belong to the billing owner." }, { status: 403 });
|
|
3371
|
+
}
|
|
3372
|
+
if (requestedSessionId) {
|
|
3373
|
+
const session = await instance.retrieveCheckoutSession(requestedSessionId);
|
|
3374
|
+
// Checkout stamps the owner into session metadata, which lets a
|
|
3375
|
+
// just-completed checkout open the portal before its snapshot
|
|
3376
|
+
// has been persisted without trusting a bare session id.
|
|
3377
|
+
if (!sessionBelongsToOwner(session, owner, customerId)) {
|
|
3378
|
+
return Response.json({ error: "Stripe portal sessionId does not belong to the billing owner." }, { status: 403 });
|
|
3379
|
+
}
|
|
3380
|
+
customerId = customerId ?? session.customerId ?? undefined;
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
else {
|
|
3384
|
+
// Without billing there is no owner to authenticate against, so
|
|
3385
|
+
// the caller supplies the customer directly. This path is for
|
|
3386
|
+
// server-side callers that already did their own authorization.
|
|
3387
|
+
customerId = requestedCustomerId;
|
|
3388
|
+
if (!customerId && requestedSessionId) {
|
|
3389
|
+
const session = await instance.retrieveCheckoutSession(requestedSessionId);
|
|
3390
|
+
customerId = session.customerId ?? undefined;
|
|
3328
3391
|
}
|
|
3329
3392
|
}
|
|
3330
3393
|
if (!customerId) {
|
|
@@ -3402,4 +3465,12 @@ export function stripe(input = {}) {
|
|
|
3402
3465
|
...webhookRoutes,
|
|
3403
3466
|
],
|
|
3404
3467
|
});
|
|
3468
|
+
// Declared so `farm stripe migrate` can create the billing tables, and
|
|
3469
|
+
// `farm generate --orm` can include them in schema artifacts. The connection
|
|
3470
|
+
// lives in the app's `storage.client`, not in this integration's options.
|
|
3471
|
+
return declareSchemaTables(integration, {
|
|
3472
|
+
name: "stripe",
|
|
3473
|
+
schema: integrationSchema,
|
|
3474
|
+
resolveClient: (config) => resolveConfiguredStorageRuntimeClient(config),
|
|
3475
|
+
});
|
|
3405
3476
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farm.js/stripe",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.104",
|
|
4
4
|
"description": "Stripe billing integration for Farm.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"stripe": "^20.4.1",
|
|
37
|
-
"@farm.js/core": "0.1.0-beta.
|
|
38
|
-
"@farm.js/integration-utils": "0.1.0-beta.
|
|
37
|
+
"@farm.js/core": "0.1.0-beta.104",
|
|
38
|
+
"@farm.js/integration-utils": "0.1.0-beta.104"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc",
|