@odla-ai/chapter 0.39.2 → 0.40.1
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 +8 -0
- package/dist/{chunk-BIYWPPH6.js → chunk-E5OXQ3DC.js} +5 -1
- package/dist/chunk-E5OXQ3DC.js.map +1 -0
- package/dist/{copy-context-Dbu9Bbq1.d.ts → copy-context-B14OOiYq.d.ts} +2 -0
- package/dist/index.cjs +36 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +36 -6
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +2 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -1
- package/dist/ui/member/index.d.ts +6 -2
- package/dist/ui/member/index.js +1 -1
- package/dist/worker/index.cjs +84 -23
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +7 -0
- package/dist/worker/index.d.ts +7 -0
- package/dist/worker/index.js +84 -23
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
- package/runbooks/greenfield.md +19 -8
- package/dist/chunk-BIYWPPH6.js.map +0 -1
package/dist/worker/index.d.cts
CHANGED
|
@@ -273,6 +273,8 @@ interface ChapterPrices {
|
|
|
273
273
|
interface ChapterPolicy {
|
|
274
274
|
disclaimerText?: string;
|
|
275
275
|
refundPolicyText?: string;
|
|
276
|
+
/** Plain-language merchant identity shown immediately before payment consent. */
|
|
277
|
+
merchantDisclosureText?: string;
|
|
276
278
|
trustCopy?: string;
|
|
277
279
|
commitmentText?: string;
|
|
278
280
|
normsText?: string;
|
|
@@ -714,6 +716,9 @@ interface ChapterEnv {
|
|
|
714
716
|
* reads fail closed when it is absent or stale. */
|
|
715
717
|
ODLA_APP_INCARNATION?: string;
|
|
716
718
|
ODLA_ENV: string;
|
|
719
|
+
/** Immutable developer-runtime identity. Omitted by legacy deployments whose
|
|
720
|
+
* runtime and data environment are the same. */
|
|
721
|
+
ODLA_RUNTIME?: string;
|
|
717
722
|
ODLA_API_KEY: string;
|
|
718
723
|
SEND_EMAIL?: {
|
|
719
724
|
send(payload: EmailPayload): Promise<{
|
|
@@ -874,6 +879,8 @@ interface SignupControlApplication {
|
|
|
874
879
|
interface SignupControlPolicy {
|
|
875
880
|
disclaimerText: string;
|
|
876
881
|
refundPolicyText: string;
|
|
882
|
+
/** Plain-language merchant identity displayed before payment consent. */
|
|
883
|
+
merchantDisclosureText?: string;
|
|
877
884
|
trustCopy?: string;
|
|
878
885
|
commitmentText?: string;
|
|
879
886
|
normsText?: string;
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -273,6 +273,8 @@ interface ChapterPrices {
|
|
|
273
273
|
interface ChapterPolicy {
|
|
274
274
|
disclaimerText?: string;
|
|
275
275
|
refundPolicyText?: string;
|
|
276
|
+
/** Plain-language merchant identity shown immediately before payment consent. */
|
|
277
|
+
merchantDisclosureText?: string;
|
|
276
278
|
trustCopy?: string;
|
|
277
279
|
commitmentText?: string;
|
|
278
280
|
normsText?: string;
|
|
@@ -714,6 +716,9 @@ interface ChapterEnv {
|
|
|
714
716
|
* reads fail closed when it is absent or stale. */
|
|
715
717
|
ODLA_APP_INCARNATION?: string;
|
|
716
718
|
ODLA_ENV: string;
|
|
719
|
+
/** Immutable developer-runtime identity. Omitted by legacy deployments whose
|
|
720
|
+
* runtime and data environment are the same. */
|
|
721
|
+
ODLA_RUNTIME?: string;
|
|
717
722
|
ODLA_API_KEY: string;
|
|
718
723
|
SEND_EMAIL?: {
|
|
719
724
|
send(payload: EmailPayload): Promise<{
|
|
@@ -874,6 +879,8 @@ interface SignupControlApplication {
|
|
|
874
879
|
interface SignupControlPolicy {
|
|
875
880
|
disclaimerText: string;
|
|
876
881
|
refundPolicyText: string;
|
|
882
|
+
/** Plain-language merchant identity displayed before payment consent. */
|
|
883
|
+
merchantDisclosureText?: string;
|
|
877
884
|
trustCopy?: string;
|
|
878
885
|
commitmentText?: string;
|
|
879
886
|
normsText?: string;
|
package/dist/worker/index.js
CHANGED
|
@@ -317,6 +317,7 @@ function joinConfig(group, paymentsReady, tiers = [], conditions = {}) {
|
|
|
317
317
|
conditions,
|
|
318
318
|
disclaimerText: group.disclaimerText ?? "",
|
|
319
319
|
refundPolicyText: group.refundPolicyText ?? "",
|
|
320
|
+
merchantDisclosureText: group.merchantDisclosureText ?? "",
|
|
320
321
|
trustCopy: group.trustCopy ?? "",
|
|
321
322
|
commitmentText: group.commitmentText ?? "",
|
|
322
323
|
normsText: group.normsText ?? "",
|
|
@@ -2325,7 +2326,14 @@ function policyOf(value, errors) {
|
|
|
2325
2326
|
errors.push("document.policy must be an object");
|
|
2326
2327
|
return void 0;
|
|
2327
2328
|
}
|
|
2328
|
-
const allowed2 = /* @__PURE__ */ new Set([
|
|
2329
|
+
const allowed2 = /* @__PURE__ */ new Set([
|
|
2330
|
+
"disclaimerText",
|
|
2331
|
+
"refundPolicyText",
|
|
2332
|
+
"merchantDisclosureText",
|
|
2333
|
+
"trustCopy",
|
|
2334
|
+
"commitmentText",
|
|
2335
|
+
"normsText"
|
|
2336
|
+
]);
|
|
2329
2337
|
unknownKeys(input, allowed2, "document.policy", errors);
|
|
2330
2338
|
const result = {};
|
|
2331
2339
|
for (const key of allowed2) {
|
|
@@ -3354,12 +3362,16 @@ function findApplicationRef(obj) {
|
|
|
3354
3362
|
const applicationId = candidates.map(pick).find(Boolean);
|
|
3355
3363
|
const appId = candidates.map((metadata) => typeof metadata.odlaAppId === "string" ? metadata.odlaAppId : void 0).find(Boolean);
|
|
3356
3364
|
const environment = candidates.map((metadata) => typeof metadata.odlaEnvironment === "string" ? metadata.odlaEnvironment : void 0).find(Boolean);
|
|
3365
|
+
const dataEnvironment = candidates.map((metadata) => typeof metadata.odlaDataEnvironment === "string" ? metadata.odlaDataEnvironment : void 0).find(Boolean);
|
|
3366
|
+
const runtime = candidates.map((metadata) => typeof metadata.odlaRuntime === "string" ? metadata.odlaRuntime : void 0).find(Boolean);
|
|
3357
3367
|
const customerId = typeof obj.customer === "string" ? obj.customer : void 0;
|
|
3358
3368
|
return {
|
|
3359
3369
|
...applicationId ? { applicationId } : {},
|
|
3360
3370
|
...customerId ? { customerId } : {},
|
|
3361
3371
|
...appId ? { appId } : {},
|
|
3362
|
-
...environment ? { environment } : {}
|
|
3372
|
+
...environment ? { environment } : {},
|
|
3373
|
+
...dataEnvironment ? { dataEnvironment } : {},
|
|
3374
|
+
...runtime ? { runtime } : {}
|
|
3363
3375
|
};
|
|
3364
3376
|
}
|
|
3365
3377
|
function findGiftRef(obj) {
|
|
@@ -3369,17 +3381,31 @@ function findGiftRef(obj) {
|
|
|
3369
3381
|
const subscription = obj.subscription_details ?? parent?.subscription_details;
|
|
3370
3382
|
const giftIntentId = pick(metaOf(obj)) ?? pick(metaOf(subscription));
|
|
3371
3383
|
const subscriptionId = typeof obj.subscription === "string" ? obj.subscription : typeof subscription?.subscription === "string" ? String(subscription.subscription) : void 0;
|
|
3372
|
-
|
|
3384
|
+
const candidates = [metaOf(obj), metaOf(subscription)];
|
|
3385
|
+
const pickIdentity = (name) => candidates.map((metadata) => typeof metadata[name] === "string" ? String(metadata[name]) : void 0).find(Boolean);
|
|
3386
|
+
const appId = pickIdentity("odlaAppId");
|
|
3387
|
+
const environment = pickIdentity("odlaEnvironment");
|
|
3388
|
+
const dataEnvironment = pickIdentity("odlaDataEnvironment");
|
|
3389
|
+
const runtime = pickIdentity("odlaRuntime");
|
|
3390
|
+
return {
|
|
3391
|
+
...giftIntentId ? { giftIntentId } : {},
|
|
3392
|
+
providerObjectId: subscriptionId ?? String(obj.id ?? ""),
|
|
3393
|
+
...appId ? { appId } : {},
|
|
3394
|
+
...environment ? { environment } : {},
|
|
3395
|
+
...dataEnvironment ? { dataEnvironment } : {},
|
|
3396
|
+
...runtime ? { runtime } : {}
|
|
3397
|
+
};
|
|
3373
3398
|
}
|
|
3374
3399
|
function normalizeWebhookEvent(event) {
|
|
3375
3400
|
const obj = event.data?.object ?? {};
|
|
3376
3401
|
const gift = findGiftRef(obj);
|
|
3377
3402
|
if (gift.giftIntentId) {
|
|
3403
|
+
const { giftIntentId, providerObjectId, ...identity } = gift;
|
|
3378
3404
|
if (event.type === "payment_intent.succeeded" || event.type === "invoice.paid" && obj.billing_reason === "subscription_create") {
|
|
3379
|
-
return { kind: "gift_paid", giftIntentId
|
|
3405
|
+
return { kind: "gift_paid", giftIntentId, providerObjectId, ...identity };
|
|
3380
3406
|
}
|
|
3381
|
-
if (event.type === "charge.refunded") return { kind: "gift_revoked", giftIntentId
|
|
3382
|
-
if (event.type === "customer.subscription.deleted") return { kind: "gift_revoked", giftIntentId
|
|
3407
|
+
if (event.type === "charge.refunded") return { kind: "gift_revoked", giftIntentId, ...identity, reason: "refunded" };
|
|
3408
|
+
if (event.type === "customer.subscription.deleted") return { kind: "gift_revoked", giftIntentId, ...identity, reason: "canceled" };
|
|
3383
3409
|
return { kind: "ignored", type: event.type };
|
|
3384
3410
|
}
|
|
3385
3411
|
const ref = findApplicationRef(obj);
|
|
@@ -3456,7 +3482,9 @@ function createStripeProvider(config) {
|
|
|
3456
3482
|
groupId: input.groupId,
|
|
3457
3483
|
email: input.email,
|
|
3458
3484
|
odlaAppId: input.appId,
|
|
3459
|
-
odlaEnvironment: input.environment
|
|
3485
|
+
odlaEnvironment: input.environment,
|
|
3486
|
+
odlaDataEnvironment: input.environment,
|
|
3487
|
+
...input.runtime ? { odlaRuntime: input.runtime } : {}
|
|
3460
3488
|
};
|
|
3461
3489
|
let customerId = input.existingCustomerId;
|
|
3462
3490
|
if (!customerId) {
|
|
@@ -3744,12 +3772,16 @@ var clientSecret = (value) => {
|
|
|
3744
3772
|
const nested = confirmation?.client_secret ?? intent?.client_secret;
|
|
3745
3773
|
return typeof nested === "string" && nested ? nested : null;
|
|
3746
3774
|
};
|
|
3747
|
-
async function startGiftProviderCheckout(secretKey, intent, email, existingCustomerId) {
|
|
3775
|
+
async function startGiftProviderCheckout(secretKey, intent, email, existingCustomerId, runtime) {
|
|
3748
3776
|
const offer = intent.offerSnapshot;
|
|
3749
3777
|
const metadata = {
|
|
3750
3778
|
giftIntentId: intent.id,
|
|
3751
3779
|
chapterId: intent.chapterId,
|
|
3752
3780
|
environment: intent.environment,
|
|
3781
|
+
odlaAppId: intent.chapterId,
|
|
3782
|
+
odlaEnvironment: intent.environment,
|
|
3783
|
+
odlaDataEnvironment: intent.environment,
|
|
3784
|
+
...runtime ? { odlaRuntime: runtime } : {},
|
|
3753
3785
|
offerId: intent.offerId
|
|
3754
3786
|
};
|
|
3755
3787
|
let customerId = existingCustomerId;
|
|
@@ -3799,6 +3831,7 @@ async function startGiftIntent(db, input) {
|
|
|
3799
3831
|
id: input.id,
|
|
3800
3832
|
chapterId: input.chapterId,
|
|
3801
3833
|
environment: input.environment,
|
|
3834
|
+
...input.runtime ? { runtime: input.runtime } : {},
|
|
3802
3835
|
purchaserType: input.purchaserType,
|
|
3803
3836
|
purchaserEmailNormalized: input.purchaserEmailNormalized,
|
|
3804
3837
|
...input.purchaserApplicationId ? { purchaserApplicationId: input.purchaserApplicationId } : {},
|
|
@@ -3818,7 +3851,7 @@ async function startGiftIntent(db, input) {
|
|
|
3818
3851
|
stored = write.duplicate ? first2((await db.query({ giftPurchaseIntents: { $: { where: { id: input.id }, limit: 1 } } })).giftPurchaseIntents) : attrs;
|
|
3819
3852
|
if (!write.duplicate) giftCode = prepared.code;
|
|
3820
3853
|
}
|
|
3821
|
-
if (!stored || stored.chapterId !== input.chapterId || stored.environment !== input.environment || stored.offerId !== input.offer.id || stored.purchaserEmailNormalized !== input.purchaserEmailNormalized) {
|
|
3854
|
+
if (!stored || stored.chapterId !== input.chapterId || stored.environment !== input.environment || stored.runtime !== input.runtime || stored.offerId !== input.offer.id || stored.purchaserEmailNormalized !== input.purchaserEmailNormalized) {
|
|
3822
3855
|
throw new Error("gift purchase intent does not match this checkout");
|
|
3823
3856
|
}
|
|
3824
3857
|
if (stored.status === "paid") throw new Error("gift purchase is already paid");
|
|
@@ -3826,7 +3859,8 @@ async function startGiftIntent(db, input) {
|
|
|
3826
3859
|
input.stripeSecret,
|
|
3827
3860
|
stored,
|
|
3828
3861
|
input.purchaserEmail,
|
|
3829
|
-
typeof stored.providerCustomerId === "string" ? stored.providerCustomerId : input.existingCustomerId
|
|
3862
|
+
typeof stored.providerCustomerId === "string" ? stored.providerCustomerId : input.existingCustomerId,
|
|
3863
|
+
input.runtime
|
|
3830
3864
|
);
|
|
3831
3865
|
await db.transact([{ t: "update", ns: "giftPurchaseIntents", id: input.id, attrs: {
|
|
3832
3866
|
status: "checkout_ready",
|
|
@@ -3845,18 +3879,29 @@ async function startGiftIntent(db, input) {
|
|
|
3845
3879
|
};
|
|
3846
3880
|
}
|
|
3847
3881
|
|
|
3882
|
+
// src/stripe-runtime.ts
|
|
3883
|
+
function stripeWebhookSecretName(runtime) {
|
|
3884
|
+
if (!runtime) return "stripe_webhook_secret";
|
|
3885
|
+
if (!/^[a-z0-9]{2,12}$/.test(runtime) || runtime === "prod" || runtime === "production") {
|
|
3886
|
+
throw new Error("ODLA_RUNTIME is invalid");
|
|
3887
|
+
}
|
|
3888
|
+
return `stripe_webhook_secret__${runtime}`;
|
|
3889
|
+
}
|
|
3890
|
+
|
|
3891
|
+
// src/payments-route-support.ts
|
|
3892
|
+
var paymentErrorCode = (error) => error && typeof error === "object" && typeof error.code === "string" ? error.code : "unknown";
|
|
3893
|
+
function paymentLineItems(group) {
|
|
3894
|
+
const standard = Number(group.standardPriceCents ?? 0);
|
|
3895
|
+
const discount = Number(group.foundingDiscountCents ?? 0);
|
|
3896
|
+
return { standardCents: standard, discountCents: discount, dueTodayCents: standard - discount };
|
|
3897
|
+
}
|
|
3898
|
+
|
|
3848
3899
|
// src/worker-routes-payments.ts
|
|
3849
|
-
var codeOf = (err) => err && typeof err === "object" && typeof err.code === "string" ? err.code : "unknown";
|
|
3850
3900
|
async function firstRow2(db, ns, q) {
|
|
3851
3901
|
const res = await db.query({ [ns]: { $: q } });
|
|
3852
3902
|
const rows4 = res[ns];
|
|
3853
3903
|
return Array.isArray(rows4) ? rows4[0] : void 0;
|
|
3854
3904
|
}
|
|
3855
|
-
function lineItems(group) {
|
|
3856
|
-
const standard = Number(group.standardPriceCents ?? 0);
|
|
3857
|
-
const discount = Number(group.foundingDiscountCents ?? 0);
|
|
3858
|
-
return { standardCents: standard, discountCents: discount, dueTodayCents: standard - discount };
|
|
3859
|
-
}
|
|
3860
3905
|
async function findApplication(db, event) {
|
|
3861
3906
|
if ("applicationId" in event && event.applicationId) {
|
|
3862
3907
|
return firstRow2(db, "applications", { where: { id: event.applicationId }, limit: 1 });
|
|
@@ -3947,6 +3992,7 @@ async function startSubscription(req, env, ctx) {
|
|
|
3947
3992
|
chapterId: ctx.chapter.id,
|
|
3948
3993
|
environment: env.ODLA_ENV,
|
|
3949
3994
|
offer,
|
|
3995
|
+
...env.ODLA_RUNTIME ? { runtime: env.ODLA_RUNTIME } : {},
|
|
3950
3996
|
purchaserType: "application",
|
|
3951
3997
|
purchaserEmail: String(app.email ?? ""),
|
|
3952
3998
|
purchaserEmailNormalized: normalizeChapterEmail(String(app.email ?? "")),
|
|
@@ -3979,6 +4025,7 @@ async function startSubscription(req, env, ctx) {
|
|
|
3979
4025
|
result = await provider.createSubscription({
|
|
3980
4026
|
appId: env.ODLA_APP_ID,
|
|
3981
4027
|
environment: env.ODLA_ENV,
|
|
4028
|
+
...env.ODLA_RUNTIME ? { runtime: env.ODLA_RUNTIME } : {},
|
|
3982
4029
|
applicationId,
|
|
3983
4030
|
groupId: String(group.id),
|
|
3984
4031
|
email: String(app.email ?? ""),
|
|
@@ -3987,29 +4034,35 @@ async function startSubscription(req, env, ctx) {
|
|
|
3987
4034
|
existingCustomerId: typeof app.stripeCustomerId === "string" ? app.stripeCustomerId : void 0
|
|
3988
4035
|
});
|
|
3989
4036
|
} catch (err) {
|
|
3990
|
-
return json({ error: "payment setup failed", code:
|
|
4037
|
+
return json({ error: "payment setup failed", code: paymentErrorCode(err) }, 502);
|
|
3991
4038
|
}
|
|
3992
4039
|
await db.transact([
|
|
3993
4040
|
{
|
|
3994
4041
|
t: "update",
|
|
3995
4042
|
ns: "applications",
|
|
3996
4043
|
id: applicationId,
|
|
3997
|
-
attrs: {
|
|
4044
|
+
attrs: {
|
|
4045
|
+
stripeCustomerId: result.customerId,
|
|
4046
|
+
stripeSubscriptionId: result.subscriptionId,
|
|
4047
|
+
...env.ODLA_RUNTIME ? { stripeRuntime: env.ODLA_RUNTIME } : {},
|
|
4048
|
+
refundPolicyAckAt: Date.now()
|
|
4049
|
+
}
|
|
3998
4050
|
}
|
|
3999
4051
|
]);
|
|
4000
|
-
return json({ clientSecret: result.clientSecret, publishableKey: group.stripePublishableKey ?? null, lineItems:
|
|
4052
|
+
return json({ clientSecret: result.clientSecret, publishableKey: group.stripePublishableKey ?? null, lineItems: paymentLineItems(group) });
|
|
4001
4053
|
}
|
|
4002
4054
|
async function ingestWebhook(req, env, ctx) {
|
|
4003
4055
|
const db = ctx.makeDb(env);
|
|
4004
|
-
const webhookSecret = await getVaultSecret(db,
|
|
4056
|
+
const webhookSecret = await getVaultSecret(db, stripeWebhookSecretName(env.ODLA_RUNTIME));
|
|
4005
4057
|
if (!webhookSecret) return json({ error: "webhook not configured" }, 503);
|
|
4006
4058
|
const rawBody = await req.text();
|
|
4007
4059
|
const ingest = await createStripeProvider({ webhookSecret }).ingestWebhook(rawBody, req.headers.get("stripe-signature") ?? "");
|
|
4008
4060
|
if (!ingest.ok) return json({ error: "invalid signature" }, 400);
|
|
4009
4061
|
const { eventId, event } = ingest;
|
|
4010
4062
|
if (event.kind === "ignored") return json({ ok: true, ignored: event.type });
|
|
4011
|
-
const identifiedEnvironment = event.appId !== void 0 || event.environment !== void 0;
|
|
4012
|
-
|
|
4063
|
+
const identifiedEnvironment = event.appId !== void 0 || event.environment !== void 0 || event.dataEnvironment !== void 0 || event.runtime !== void 0;
|
|
4064
|
+
const eventDataEnvironment = event.dataEnvironment ?? event.environment;
|
|
4065
|
+
if (env.ODLA_APP_ID && identifiedEnvironment && (event.appId !== env.ODLA_APP_ID || eventDataEnvironment !== env.ODLA_ENV || event.runtime !== void 0 && event.runtime !== env.ODLA_RUNTIME)) {
|
|
4013
4066
|
return json({ ok: true, matched: false });
|
|
4014
4067
|
}
|
|
4015
4068
|
if (event.kind === "gift_paid" || event.kind === "gift_revoked") {
|
|
@@ -4017,6 +4070,9 @@ async function ingestWebhook(req, env, ctx) {
|
|
|
4017
4070
|
if (!intent || intent.chapterId !== ctx.chapter.id || intent.environment !== env.ODLA_ENV) {
|
|
4018
4071
|
return json({ ok: true, matched: false });
|
|
4019
4072
|
}
|
|
4073
|
+
if (event.runtime === void 0 && typeof intent.runtime === "string" && intent.runtime !== env.ODLA_RUNTIME) {
|
|
4074
|
+
return json({ ok: true, matched: false });
|
|
4075
|
+
}
|
|
4020
4076
|
if (event.kind === "gift_paid") {
|
|
4021
4077
|
if (intent.providerObjectId !== event.providerObjectId) return json({ ok: true, matched: false });
|
|
4022
4078
|
if (intent.status === "refunded" || intent.status === "canceled") return json({ ok: true, matched: false });
|
|
@@ -4040,6 +4096,9 @@ async function ingestWebhook(req, env, ctx) {
|
|
|
4040
4096
|
}
|
|
4041
4097
|
const app = await findApplication(db, event);
|
|
4042
4098
|
if (!app) return json({ ok: true, matched: false });
|
|
4099
|
+
if (event.runtime === void 0 && typeof app.stripeRuntime === "string" && app.stripeRuntime !== env.ODLA_RUNTIME) {
|
|
4100
|
+
return json({ ok: true, matched: false });
|
|
4101
|
+
}
|
|
4043
4102
|
const patch = webhookPatch(event, String(app.status ?? ""));
|
|
4044
4103
|
let next = app;
|
|
4045
4104
|
if (Object.keys(patch).length) {
|
|
@@ -4111,7 +4170,8 @@ var handleGifts = async (req, url, env, ctx) => {
|
|
|
4111
4170
|
return json({
|
|
4112
4171
|
offers: publicGiftOffers(control3?.document.giftOffers, Date.now()),
|
|
4113
4172
|
claims: buyerGiftClaims(rows2(found.giftClaims).sort((a, b) => Number(b.createdAt) - Number(a.createdAt)), Date.now()),
|
|
4114
|
-
refundPolicyText: typeof group?.refundPolicyText === "string" ? group.refundPolicyText : ""
|
|
4173
|
+
refundPolicyText: typeof group?.refundPolicyText === "string" ? group.refundPolicyText : "",
|
|
4174
|
+
merchantDisclosureText: typeof group?.merchantDisclosureText === "string" ? group.merchantDisclosureText : ""
|
|
4115
4175
|
});
|
|
4116
4176
|
}
|
|
4117
4177
|
if (req.method === "POST" && url.pathname === "/api/gifts/checkout") {
|
|
@@ -4142,6 +4202,7 @@ var handleGifts = async (req, url, env, ctx) => {
|
|
|
4142
4202
|
offer,
|
|
4143
4203
|
purchaserType: "member",
|
|
4144
4204
|
purchaserEmail: user.email,
|
|
4205
|
+
...env.ODLA_RUNTIME ? { runtime: env.ODLA_RUNTIME } : {},
|
|
4145
4206
|
purchaserEmailNormalized: emailNormalized,
|
|
4146
4207
|
purchaserUserId: user.userId,
|
|
4147
4208
|
...typeof app?.stripeCustomerId === "string" ? { existingCustomerId: app.stripeCustomerId } : {},
|