@paykit-sdk/stripe 1.1.9 → 1.1.92

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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { schema, validateRequiredKeys, AbstractPayKitProvider, NotImplementedError, createCustomerSchema, ValidationError, createSubscriptionSchema, InvalidTypeError, updateSubscriptionSchema, retrieveSubscriptionSchema, createPaymentSchema, updatePaymentSchema, retrievePaymentSchema, deletePaymentSchema, capturePaymentSchema, createRefundSchema, headersExtractor, WebhookError, paykitEvent$InboundSchema, billingModeSchema, invoiceStatusSchema, omitInternalMetadata } from '@paykit-sdk/core';
1
+ import { schema, validateRequiredKeys, AbstractPayKitProvider, createCheckoutSchema, ValidationError, stringifyMetadataValues, InvalidTypeError, updateCheckoutSchema, ResourceNotFoundError, createCustomerSchema, createSubscriptionSchema, updateSubscriptionSchema, retrieveSubscriptionSchema, createPaymentSchema, PAYKIT_METADATA_KEY, updatePaymentSchema, retrievePaymentSchema, tryCatchAsync, deletePaymentSchema, capturePaymentSchema, createRefundSchema, WebhookError, paykitEvent$InboundSchema, billingModeSchema, omitInternalMetadata, invoiceStatusSchema } from '@paykit-sdk/core';
2
2
  import Stripe from 'stripe';
3
3
 
4
4
  var __defProp = Object.defineProperty;
@@ -4046,13 +4046,16 @@ var coerce = {
4046
4046
  date: (arg) => ZodDate.create({ ...arg, coerce: true })
4047
4047
  };
4048
4048
  var NEVER = INVALID;
4049
- var paykitCheckout$InboundSchema = (checkout) => {
4049
+ var paykitCheckout$InboundSchema = (checkout, lineItems) => {
4050
4050
  return {
4051
4051
  id: checkout.id,
4052
4052
  customer: typeof checkout.customer === "string" ? checkout.customer : checkout.customer?.id ?? "",
4053
4053
  session_type: checkout.mode === "subscription" ? "recurring" : "one_time",
4054
4054
  payment_url: checkout.url,
4055
- products: checkout.line_items.data.map((item) => ({ id: item.price.id, quantity: item.quantity })),
4055
+ products: lineItems.map((item) => ({
4056
+ id: item.id,
4057
+ quantity: item.quantity
4058
+ })),
4056
4059
  currency: checkout.currency,
4057
4060
  amount: checkout.amount_total,
4058
4061
  subscription: null,
@@ -4071,10 +4074,13 @@ var paykitCustomer$InboundSchema = (customer) => {
4071
4074
  var paykitSubscription$InboundSchema = (subscription) => {
4072
4075
  const status = (() => {
4073
4076
  if (["active", "trialing"].includes(subscription.status)) return "active";
4074
- if (["incomplete_expired", "incomplete", "past_due"].includes(subscription.status)) return "past_due";
4077
+ if (["incomplete_expired", "incomplete", "past_due"].includes(subscription.status)) {
4078
+ return "past_due";
4079
+ }
4075
4080
  if (["canceled"].includes(subscription.status)) return "canceled";
4076
4081
  if (["expired"].includes(subscription.status)) return "expired";
4077
- throw new Error(`Unknown status: ${subscription.status}`);
4082
+ console.log(`Unknown subscription status: ${subscription.status}`);
4083
+ return "pending";
4078
4084
  })();
4079
4085
  const metadata = omitInternalMetadata(subscription.metadata ?? {});
4080
4086
  return {
@@ -4094,7 +4100,8 @@ var paykitSubscription$InboundSchema = (subscription) => {
4094
4100
  var paykitInvoice$InboundSchema = (invoice) => {
4095
4101
  const status = (() => {
4096
4102
  if (invoice.status == "paid") return "paid";
4097
- if (["draft", "open", "uncollectible", "void"].includes(invoice.status)) return "open";
4103
+ if (["draft", "open", "uncollectible", "void"].includes(invoice.status))
4104
+ return "open";
4098
4105
  throw new Error(`Unknown status: ${invoice.status}`);
4099
4106
  })();
4100
4107
  const customerId = (() => {
@@ -4108,7 +4115,10 @@ var paykitInvoice$InboundSchema = (invoice) => {
4108
4115
  customer: customerId,
4109
4116
  billing_mode: invoice.billingMode,
4110
4117
  amount_paid: invoice.amount_paid,
4111
- line_items: invoice.lines.data.map((line) => ({ id: line.id, quantity: line.quantity })),
4118
+ line_items: invoice.lines.data.map((line) => ({
4119
+ id: line.id,
4120
+ quantity: line.quantity
4121
+ })),
4112
4122
  subscription_id: invoice.parent?.subscription_details?.subscription?.toString() ?? null,
4113
4123
  status,
4114
4124
  paid_at: new Date(invoice.created * 1e3).toISOString(),
@@ -4142,6 +4152,7 @@ var stripeToPaykitStatus = (status) => {
4142
4152
  }
4143
4153
  };
4144
4154
  var paykitPayment$InboundSchema = (intent) => {
4155
+ const itemId = JSON.parse(intent.metadata?.[PAYKIT_METADATA_KEY] ?? "{}").itemId;
4145
4156
  return {
4146
4157
  id: intent.id,
4147
4158
  amount: intent.amount,
@@ -4149,7 +4160,7 @@ var paykitPayment$InboundSchema = (intent) => {
4149
4160
  customer: intent.customer ?? "",
4150
4161
  status: stripeToPaykitStatus(intent.status),
4151
4162
  metadata: omitInternalMetadata(intent.metadata ?? {}),
4152
- product_id: intent.metadata?.product_id
4163
+ item_id: itemId
4153
4164
  };
4154
4165
  };
4155
4166
  var paykitRefund$InboundSchema = (refund) => {
@@ -4161,6 +4172,22 @@ var paykitRefund$InboundSchema = (refund) => {
4161
4172
  metadata: omitInternalMetadata(refund.metadata ?? {})
4162
4173
  };
4163
4174
  };
4175
+ var paykitRefundReason$OutboundSchema = (reason) => {
4176
+ if (!reason) return void 0;
4177
+ const normalized = reason.toLowerCase().trim();
4178
+ if (/duplicate|duplicated|double.*charge|charged.*twice/i.test(normalized)) {
4179
+ return "duplicate";
4180
+ }
4181
+ if (/fraud|fraudulent|unauthorized|scam|stolen.*card|not.*authorized/i.test(normalized)) {
4182
+ return "fraudulent";
4183
+ }
4184
+ if (/customer.*request|requested.*customer|customer.*want|cancel|refund.*request|changed.*mind/i.test(
4185
+ normalized
4186
+ )) {
4187
+ return "requested_by_customer";
4188
+ }
4189
+ return "requested_by_customer";
4190
+ };
4164
4191
 
4165
4192
  // src/stripe-provider.ts
4166
4193
  var stripeOptionsSchema = schema()(
@@ -4171,26 +4198,53 @@ var stripeOptionsSchema = schema()(
4171
4198
  );
4172
4199
  var providerName = "stripe";
4173
4200
  var StripeProvider = class extends AbstractPayKitProvider {
4174
- constructor(config) {
4175
- super(stripeOptionsSchema, config, providerName);
4201
+ constructor(opts) {
4202
+ super(stripeOptionsSchema, opts, providerName);
4176
4203
  this.providerName = providerName;
4177
4204
  /**
4178
4205
  * Checkout management
4179
4206
  */
4180
4207
  this.createCheckout = async (params) => {
4181
- const metadata = Object.fromEntries(Object.entries(params.metadata ?? {}).map(([key, value]) => [key, JSON.stringify(value)]));
4208
+ const { error, data } = createCheckoutSchema.safeParse(params);
4209
+ if (error) {
4210
+ throw ValidationError.fromZodError(error, this.providerName, "createCheckout");
4211
+ }
4212
+ const checkoutMetadata = stringifyMetadataValues(data.metadata ?? {});
4182
4213
  const checkoutOptions = {
4183
- ...typeof params.customer === "string" && { customer: params.customer },
4184
- ...typeof params.customer === "object" && { customer: params.customer.email },
4185
- mode: params.session_type === "one_time" ? "payment" : "subscription",
4186
- line_items: [{ price: params.item_id, quantity: params.quantity }],
4187
- ...params.session_type == "one_time" && { metadata },
4188
- ...params.session_type == "recurring" && { subscription_data: { metadata } },
4189
- ...params.provider_metadata
4214
+ ...data.provider_metadata,
4215
+ mode: data.session_type === "one_time" ? "payment" : "subscription",
4216
+ line_items: [{ price: data.item_id, quantity: data.quantity }],
4217
+ success_url: data.success_url,
4218
+ cancel_url: data.cancel_url
4190
4219
  };
4220
+ if (params.session_type == "recurring") {
4221
+ checkoutOptions.subscription_data = { metadata: checkoutMetadata };
4222
+ } else if (params.session_type == "one_time") {
4223
+ checkoutOptions.metadata = checkoutMetadata;
4224
+ checkoutOptions.payment_intent_data = {
4225
+ setup_future_usage: "off_session"
4226
+ };
4227
+ }
4228
+ if (typeof params.customer === "string") {
4229
+ checkoutOptions.customer = params.customer;
4230
+ } else if (typeof params.customer === "object" && "email" in params.customer) {
4231
+ checkoutOptions.customer_email = params.customer.email;
4232
+ } else {
4233
+ throw new InvalidTypeError(
4234
+ "customer",
4235
+ "string (customer ID) or object (customer) with email",
4236
+ "object",
4237
+ {
4238
+ provider: this.providerName,
4239
+ method: "createCheckout"
4240
+ }
4241
+ );
4242
+ }
4191
4243
  if (params.billing) {
4192
4244
  checkoutOptions.shipping_address_collection = {
4193
- allowed_countries: [params.billing.address.country]
4245
+ allowed_countries: [
4246
+ params.billing.address.country
4247
+ ]
4194
4248
  };
4195
4249
  checkoutOptions.shipping_options = [
4196
4250
  {
@@ -4203,18 +4257,48 @@ var StripeProvider = class extends AbstractPayKitProvider {
4203
4257
  ];
4204
4258
  }
4205
4259
  const checkout = await this.stripe.checkout.sessions.create(checkoutOptions);
4206
- return paykitCheckout$InboundSchema(checkout);
4260
+ return paykitCheckout$InboundSchema(checkout, [
4261
+ { id: params.item_id, quantity: params.quantity }
4262
+ ]);
4207
4263
  };
4208
4264
  this.retrieveCheckout = async (id) => {
4209
- const checkout = await this.stripe.checkout.sessions.retrieve(id);
4210
- return paykitCheckout$InboundSchema(checkout);
4265
+ const checkout = await this.stripe.checkout.sessions.retrieve(id, {
4266
+ expand: ["line_items"]
4267
+ });
4268
+ return paykitCheckout$InboundSchema(
4269
+ checkout,
4270
+ checkout.line_items?.data.map((item) => ({
4271
+ id: item.price?.id ?? "",
4272
+ quantity: item.quantity ?? 0
4273
+ })) ?? []
4274
+ );
4211
4275
  };
4212
4276
  this.updateCheckout = async (id, params) => {
4213
- const checkout = await this.stripe.checkout.sessions.update(id, params);
4214
- return paykitCheckout$InboundSchema(checkout);
4277
+ const { error, data } = updateCheckoutSchema.safeParse(params);
4278
+ if (error) {
4279
+ throw ValidationError.fromZodError(error, this.providerName, "updateCheckout");
4280
+ }
4281
+ const originalCheckout = await this.stripe.checkout.sessions.retrieve(id, {
4282
+ expand: ["line_items"]
4283
+ });
4284
+ if (!originalCheckout) {
4285
+ throw new ResourceNotFoundError("checkout", id, this.providerName);
4286
+ }
4287
+ const updatedCheckout = await this.stripe.checkout.sessions.update(id, {
4288
+ ...data,
4289
+ metadata: stringifyMetadataValues(data.metadata ?? {})
4290
+ });
4291
+ return paykitCheckout$InboundSchema(
4292
+ updatedCheckout,
4293
+ updatedCheckout.line_items?.data.map((item) => ({
4294
+ id: item.price?.id ?? "",
4295
+ quantity: item.quantity ?? 0
4296
+ })) ?? []
4297
+ );
4215
4298
  };
4216
4299
  this.deleteCheckout = async (id) => {
4217
- throw new NotImplementedError("deleteCheckout", "stripe", { futureSupport: false });
4300
+ await this.stripe.checkout.sessions.expire(id);
4301
+ return null;
4218
4302
  };
4219
4303
  /**
4220
4304
  * Customer management
@@ -4230,7 +4314,11 @@ var StripeProvider = class extends AbstractPayKitProvider {
4230
4314
  };
4231
4315
  this.updateCustomer = async (id, params) => {
4232
4316
  const { provider_metadata, ...rest } = params;
4233
- const customer = await this.stripe.customers.update(id, { ...rest, ...provider_metadata });
4317
+ const customer = await this.stripe.customers.update(id, {
4318
+ ...provider_metadata,
4319
+ ...rest,
4320
+ metadata: stringifyMetadataValues(rest.metadata ?? {})
4321
+ });
4234
4322
  return paykitCustomer$InboundSchema(customer);
4235
4323
  };
4236
4324
  this.deleteCustomer = async (id) => {
@@ -4256,11 +4344,20 @@ var StripeProvider = class extends AbstractPayKitProvider {
4256
4344
  method: "createSubscription"
4257
4345
  });
4258
4346
  }
4347
+ if (this.opts.debug) {
4348
+ console.info(
4349
+ "Creating subscription with default payment method, this can be overridden by passing `default_payment_method` in the provider_metadata e.g pm_xxx"
4350
+ );
4351
+ }
4352
+ const defaultPaymentMethod = data.provider_metadata?.default_payment_method;
4259
4353
  const subscription = await this.stripe.subscriptions.create({
4354
+ ...data.provider_metadata,
4355
+ ...defaultPaymentMethod && { default_payment_method: defaultPaymentMethod },
4260
4356
  customer: data.customer,
4261
4357
  items: [{ price: data.item_id }],
4262
- metadata: Object.fromEntries(Object.entries(data.metadata ?? {}).map(([key, value]) => [key, JSON.stringify(value)])),
4263
- ...data.provider_metadata
4358
+ metadata: stringifyMetadataValues(data.metadata ?? {}),
4359
+ payment_behavior: "default_incomplete"
4360
+ // customer's default payment method will be used if available
4264
4361
  });
4265
4362
  return paykitSubscription$InboundSchema(subscription);
4266
4363
  };
@@ -4273,19 +4370,19 @@ var StripeProvider = class extends AbstractPayKitProvider {
4273
4370
  if (error) {
4274
4371
  throw ValidationError.fromZodError(error, this.providerName, "updateSubscription");
4275
4372
  }
4276
- const subscription = await this.stripe.subscriptions.retrieve(id);
4277
- const metadata = Object.fromEntries(
4278
- Object.entries({ ...subscription.metadata ?? {}, ...data.metadata ?? {} }).map(([key, value]) => [key, JSON.stringify(value)])
4279
- );
4280
4373
  const updatedSubscription = await this.stripe.subscriptions.update(id, {
4281
- metadata
4374
+ metadata: stringifyMetadataValues(data.metadata ?? {})
4282
4375
  });
4283
4376
  return paykitSubscription$InboundSchema(updatedSubscription);
4284
4377
  };
4285
4378
  this.retrieveSubscription = async (id) => {
4286
4379
  const { error, data } = retrieveSubscriptionSchema.safeParse({ id });
4287
4380
  if (error) {
4288
- throw ValidationError.fromZodError(error, this.providerName, "retrieveSubscription");
4381
+ throw ValidationError.fromZodError(
4382
+ error,
4383
+ this.providerName,
4384
+ "retrieveSubscription"
4385
+ );
4289
4386
  }
4290
4387
  const subscription = await this.stripe.subscriptions.retrieve(data.id);
4291
4388
  return paykitSubscription$InboundSchema(subscription);
@@ -4303,20 +4400,56 @@ var StripeProvider = class extends AbstractPayKitProvider {
4303
4400
  */
4304
4401
  this.createPayment = async (params) => {
4305
4402
  const { error, data } = createPaymentSchema.safeParse(params);
4306
- if (error) throw new ValidationError(error.message.split("\n").join(" "), { provider: this.providerName, method: "createPayment" });
4307
- const { provider_metadata, customer, ...rest } = data;
4403
+ if (error)
4404
+ throw new ValidationError(error.message.split("\n").join(" "), {
4405
+ provider: this.providerName,
4406
+ method: "createPayment"
4407
+ });
4408
+ const { provider_metadata, customer, capture_method, ...rest } = data;
4308
4409
  if (typeof customer === "object") {
4309
4410
  throw new InvalidTypeError("customer", "string (customer ID)", "object", {
4310
4411
  provider: this.providerName,
4311
4412
  method: "createPayment"
4312
4413
  });
4313
4414
  }
4314
- const metadata = Object.fromEntries(
4315
- Object.entries({ ...rest.metadata ?? {}, ...provider_metadata?.metadata ?? {}, product_id: params.product_id ?? null }).map(
4316
- ([key, value]) => [key, JSON.stringify(value)]
4317
- )
4415
+ const paymentMetadata = stringifyMetadataValues({
4416
+ ...rest.metadata,
4417
+ ...provider_metadata?.metadata ?? {},
4418
+ [PAYKIT_METADATA_KEY]: JSON.stringify({ itemId: data.item_id ?? null })
4419
+ });
4420
+ const customerWithDefaultPaymentMethod = await this.stripe.customers.retrieve(
4421
+ customer,
4422
+ { expand: ["invoice_settings.default_payment_method"] }
4318
4423
  );
4319
- const paymentIntentOptions = { ...provider_metadata, ...rest, metadata, customer };
4424
+ if ("deleted" in customerWithDefaultPaymentMethod) {
4425
+ throw new ValidationError("Customer has been deleted", {
4426
+ provider: this.providerName,
4427
+ method: "createPayment"
4428
+ });
4429
+ }
4430
+ let defaultPaymentMethod = customerWithDefaultPaymentMethod.invoice_settings?.default_payment_method;
4431
+ if (!defaultPaymentMethod) {
4432
+ const paymentMethods = await this.stripe.paymentMethods.list({ customer });
4433
+ if (paymentMethods.data.length === 0) {
4434
+ throw new ValidationError(
4435
+ `Customer ${customer} has no payment methods. Add a payment method for the customer before creating a payment intent`,
4436
+ { provider: this.providerName, method: "createPayment" }
4437
+ );
4438
+ }
4439
+ defaultPaymentMethod = paymentMethods.data[0].id;
4440
+ }
4441
+ const paymentIntentOptions = {
4442
+ currency: rest.currency,
4443
+ amount: rest.amount,
4444
+ metadata: paymentMetadata,
4445
+ customer,
4446
+ capture_method,
4447
+ confirm: true,
4448
+ // automatically confirms the payment
4449
+ payment_method: defaultPaymentMethod,
4450
+ off_session: true
4451
+ // uses customer's default payment method, avoids 3Ds/authentication
4452
+ };
4320
4453
  if (data.billing) {
4321
4454
  paymentIntentOptions.shipping = {
4322
4455
  name: data.billing.address.name,
@@ -4340,21 +4473,38 @@ var StripeProvider = class extends AbstractPayKitProvider {
4340
4473
  throw ValidationError.fromZodError(error, this.providerName, "updatePayment");
4341
4474
  }
4342
4475
  const { provider_metadata, customer, ...rest } = data;
4343
- if (typeof customer === "object") {
4344
- throw new InvalidTypeError("customer", "string (customer ID)", "object", {
4345
- provider: this.providerName,
4346
- method: "updatePayment"
4347
- });
4476
+ const payment = await this.stripe.paymentIntents.retrieve(id);
4477
+ const paymentOptions = {
4478
+ ...provider_metadata,
4479
+ metadata: stringifyMetadataValues({
4480
+ ...rest.metadata,
4481
+ ...provider_metadata?.metadata ?? {}
4482
+ })
4483
+ };
4484
+ if (["requires_payment_method", "requires_confirmation", "requires_action"].includes(
4485
+ payment.status
4486
+ )) {
4487
+ paymentOptions.amount = rest.amount;
4488
+ paymentOptions.currency = rest.currency;
4348
4489
  }
4349
- const payment = await this.stripe.paymentIntents.update(id, { ...rest, ...provider_metadata, customer });
4350
- return paykitPayment$InboundSchema(payment);
4490
+ if (typeof customer === "string") {
4491
+ paymentOptions.customer = customer;
4492
+ } else if (typeof customer == "object" && "email" in customer) {
4493
+ paymentOptions.receipt_email = customer.email;
4494
+ }
4495
+ const updatedPayment = await this.stripe.paymentIntents.update(id, paymentOptions);
4496
+ return paykitPayment$InboundSchema(updatedPayment);
4351
4497
  };
4352
4498
  this.retrievePayment = async (id) => {
4353
4499
  const { error, data } = retrievePaymentSchema.safeParse({ id });
4354
4500
  if (error) {
4355
4501
  throw ValidationError.fromZodError(error, this.providerName, "retrievePayment");
4356
4502
  }
4357
- const payment = await this.stripe.paymentIntents.retrieve(data.id);
4503
+ const [payment, paymentError] = await tryCatchAsync(
4504
+ this.stripe.paymentIntents.retrieve(data.id)
4505
+ );
4506
+ if (!payment || paymentError?.code === "resource_missing")
4507
+ return null;
4358
4508
  return paykitPayment$InboundSchema(payment);
4359
4509
  };
4360
4510
  this.deletePayment = async (id) => {
@@ -4367,13 +4517,17 @@ var StripeProvider = class extends AbstractPayKitProvider {
4367
4517
  };
4368
4518
  this.capturePayment = async (id, params) => {
4369
4519
  const { error, data } = capturePaymentSchema.safeParse(params);
4370
- if (error) throw new ValidationError(error.message, { provider: this.providerName, method: "capturePayment" });
4371
- const payment = await this.stripe.paymentIntents.capture(id, { amount_to_capture: data.amount });
4520
+ if (error) {
4521
+ throw ValidationError.fromZodError(error, this.providerName, "capturePayment");
4522
+ }
4523
+ const payment = await this.stripe.paymentIntents.capture(id, {
4524
+ amount_to_capture: data.amount
4525
+ });
4372
4526
  return paykitPayment$InboundSchema(payment);
4373
4527
  };
4374
4528
  this.cancelPayment = async (id) => {
4375
- const payment = await this.stripe.paymentIntents.cancel(id);
4376
- return paykitPayment$InboundSchema(payment);
4529
+ const canceledPayment = await this.stripe.paymentIntents.cancel(id);
4530
+ return paykitPayment$InboundSchema(canceledPayment);
4377
4531
  };
4378
4532
  /**
4379
4533
  * Refund management
@@ -4383,8 +4537,19 @@ var StripeProvider = class extends AbstractPayKitProvider {
4383
4537
  if (error) {
4384
4538
  throw ValidationError.fromZodError(error, this.providerName, "createRefund");
4385
4539
  }
4386
- const { provider_metadata, ...rest } = params;
4387
- const refund = await this.stripe.refunds.create({ ...rest, reason: rest.reason, ...provider_metadata });
4540
+ const { provider_metadata, ...rest } = data;
4541
+ const stripeRefundOptions = {
4542
+ ...provider_metadata,
4543
+ reason: paykitRefundReason$OutboundSchema(rest.reason),
4544
+ amount: rest.amount,
4545
+ metadata: stringifyMetadataValues(rest.metadata ?? {})
4546
+ };
4547
+ if (data.payment_id.startsWith("pi_")) {
4548
+ stripeRefundOptions.payment_intent = data.payment_id;
4549
+ } else {
4550
+ stripeRefundOptions.charge = data.payment_id;
4551
+ }
4552
+ const refund = await this.stripe.refunds.create(stripeRefundOptions);
4388
4553
  return paykitRefund$InboundSchema(refund);
4389
4554
  };
4390
4555
  /**
@@ -4392,9 +4557,17 @@ var StripeProvider = class extends AbstractPayKitProvider {
4392
4557
  */
4393
4558
  this.handleWebhook = async (params) => {
4394
4559
  const { body, headers, webhookSecret } = params;
4395
- const stripeHeaders = headersExtractor(headers, ["x-stripe-signature"]);
4396
- const signature = stripeHeaders[0].value;
4397
- const event = this.stripe.webhooks.constructEvent(body, signature, webhookSecret);
4560
+ const stripeSignature = headers.get("stripe-signature");
4561
+ if (!stripeSignature) {
4562
+ throw new WebhookError("Missing Stripe signature", {
4563
+ provider: this.providerName
4564
+ });
4565
+ }
4566
+ const event = this.stripe.webhooks.constructEvent(
4567
+ body,
4568
+ stripeSignature,
4569
+ webhookSecret
4570
+ );
4398
4571
  const stripePaymentIntentUpdateEventsWithHandlers = [
4399
4572
  "payment_intent.processing",
4400
4573
  "payment_intent.requires_action",
@@ -4429,20 +4602,29 @@ var StripeProvider = class extends AbstractPayKitProvider {
4429
4602
  paid_at: new Date(event2.created * 1e3).toISOString(),
4430
4603
  amount_paid: data.amount_total ?? 0,
4431
4604
  currency: data.currency ?? "",
4432
- metadata: Object.fromEntries(Object.entries(data.metadata ?? {}).map(([key, value]) => [key, JSON.stringify(value)])),
4605
+ metadata: omitInternalMetadata(data.metadata ?? {}),
4433
4606
  customer: typeof data.customer === "string" ? data.customer : data.customer?.id ?? "",
4434
4607
  billing_mode: billingModeSchema.parse("one_time"),
4435
4608
  subscription_id: null,
4436
4609
  custom_fields: customFields ?? null,
4437
- line_items: data.line_items?.data.map((item) => ({ id: item.price.id, quantity: item.quantity })) ?? []
4610
+ line_items: data.line_items?.data.map((item) => ({
4611
+ id: item.price.id,
4612
+ quantity: item.quantity
4613
+ })) ?? []
4614
+ };
4615
+ const invoice = {
4616
+ type: "invoice.generated",
4617
+ created: event2.created,
4618
+ id: event2.id,
4619
+ data: invoiceData
4438
4620
  };
4439
- const invoice = { type: "invoice.generated", created: event2.created, id: event2.id, data: invoiceData };
4440
4621
  return [paykitEvent$InboundSchema(invoice)];
4441
4622
  },
4442
4623
  "invoice.paid": async (event2) => {
4443
4624
  const data = event2.data.object;
4444
4625
  const relevantBillingReasons = ["subscription_create", "subscription_cycle"];
4445
- if (data.status !== "paid" && !relevantBillingReasons.includes(data.billing_reason)) return null;
4626
+ if (data.status !== "paid" && !relevantBillingReasons.includes(data.billing_reason))
4627
+ return null;
4446
4628
  const invoice = {
4447
4629
  type: "invoice.generated",
4448
4630
  created: event2.created,
@@ -4456,16 +4638,31 @@ var StripeProvider = class extends AbstractPayKitProvider {
4456
4638
  */
4457
4639
  "customer.created": async (event2) => {
4458
4640
  const data = event2.data.object;
4459
- const customer = { type: "customer.created", created: event2.created, id: event2.id, data: paykitCustomer$InboundSchema(data) };
4641
+ const customer = {
4642
+ type: "customer.created",
4643
+ created: event2.created,
4644
+ id: event2.id,
4645
+ data: paykitCustomer$InboundSchema(data)
4646
+ };
4460
4647
  return [paykitEvent$InboundSchema(customer)];
4461
4648
  },
4462
4649
  "customer.updated": async (event2) => {
4463
4650
  const data = event2.data.object;
4464
- const customer = { type: "customer.updated", created: event2.created, id: event2.id, data: paykitCustomer$InboundSchema(data) };
4651
+ const customer = {
4652
+ type: "customer.updated",
4653
+ created: event2.created,
4654
+ id: event2.id,
4655
+ data: paykitCustomer$InboundSchema(data)
4656
+ };
4465
4657
  return [paykitEvent$InboundSchema(customer)];
4466
4658
  },
4467
4659
  "customer.deleted": async (event2) => {
4468
- const customer = { type: "customer.deleted", created: event2.created, id: event2.id, data: null };
4660
+ const customer = {
4661
+ type: "customer.deleted",
4662
+ created: event2.created,
4663
+ id: event2.id,
4664
+ data: null
4665
+ };
4469
4666
  return [paykitEvent$InboundSchema(customer)];
4470
4667
  },
4471
4668
  /**
@@ -4474,46 +4671,104 @@ var StripeProvider = class extends AbstractPayKitProvider {
4474
4671
  "customer.subscription.created": async (event2) => {
4475
4672
  const data = event2.data.object;
4476
4673
  const subscription = paykitSubscription$InboundSchema(data);
4477
- return [paykitEvent$InboundSchema({ type: "subscription.created", created: event2.created, id: event2.id, data: subscription })];
4674
+ return [
4675
+ paykitEvent$InboundSchema({
4676
+ type: "subscription.created",
4677
+ created: event2.created,
4678
+ id: event2.id,
4679
+ data: subscription
4680
+ })
4681
+ ];
4478
4682
  },
4479
4683
  "customer.subscription.updated": async (event2) => {
4480
4684
  const data = event2.data.object;
4481
4685
  const subscription = paykitSubscription$InboundSchema(data);
4482
- return [paykitEvent$InboundSchema({ type: "subscription.updated", created: event2.created, id: event2.id, data: subscription })];
4686
+ return [
4687
+ paykitEvent$InboundSchema({
4688
+ type: "subscription.updated",
4689
+ created: event2.created,
4690
+ id: event2.id,
4691
+ data: subscription
4692
+ })
4693
+ ];
4483
4694
  },
4484
4695
  "customer.subscription.deleted": async (event2) => {
4485
4696
  const subscription = null;
4486
- return [paykitEvent$InboundSchema({ type: "subscription.canceled", created: event2.created, id: event2.id, data: subscription })];
4697
+ return [
4698
+ paykitEvent$InboundSchema({
4699
+ type: "subscription.canceled",
4700
+ created: event2.created,
4701
+ id: event2.id,
4702
+ data: subscription
4703
+ })
4704
+ ];
4487
4705
  },
4488
4706
  "payment_intent.created": async (event2) => {
4489
4707
  const data = event2.data.object;
4490
4708
  const payment = paykitPayment$InboundSchema(data);
4491
- return [paykitEvent$InboundSchema({ type: "payment.created", created: event2.created, id: event2.id, data: payment })];
4709
+ return [
4710
+ paykitEvent$InboundSchema({
4711
+ type: "payment.created",
4712
+ created: event2.created,
4713
+ id: event2.id,
4714
+ data: payment
4715
+ })
4716
+ ];
4492
4717
  },
4493
- ...stripePaymentIntentUpdateEventsWithHandlers.map(() => async (event2) => {
4494
- const data = event2.data.object;
4495
- const payment = paykitPayment$InboundSchema(data);
4496
- return [paykitEvent$InboundSchema({ type: "payment.updated", created: event2.created, id: event2.id, data: payment })];
4497
- }),
4718
+ ...stripePaymentIntentUpdateEventsWithHandlers.map(
4719
+ () => async (event2) => {
4720
+ const data = event2.data.object;
4721
+ const payment = paykitPayment$InboundSchema(data);
4722
+ return [
4723
+ paykitEvent$InboundSchema({
4724
+ type: "payment.updated",
4725
+ created: event2.created,
4726
+ id: event2.id,
4727
+ data: payment
4728
+ })
4729
+ ];
4730
+ }
4731
+ ),
4498
4732
  "payment_intent.canceled": async (event2) => {
4499
4733
  const data = event2.data.object;
4500
4734
  const payment = paykitPayment$InboundSchema(data);
4501
- return [paykitEvent$InboundSchema({ type: "payment.canceled", created: event2.created, id: event2.id, data: payment })];
4735
+ return [
4736
+ paykitEvent$InboundSchema({
4737
+ type: "payment.canceled",
4738
+ created: event2.created,
4739
+ id: event2.id,
4740
+ data: payment
4741
+ })
4742
+ ];
4502
4743
  },
4503
4744
  "refund.created": async (event2) => {
4504
4745
  const data = event2.data.object;
4505
4746
  const refund = paykitRefund$InboundSchema(data);
4506
- return [paykitEvent$InboundSchema({ type: "refund.created", created: event2.created, id: event2.id, data: refund })];
4747
+ return [
4748
+ paykitEvent$InboundSchema({
4749
+ type: "refund.created",
4750
+ created: event2.created,
4751
+ id: event2.id,
4752
+ data: refund
4753
+ })
4754
+ ];
4507
4755
  }
4508
4756
  };
4509
4757
  const handler = webhookHandlers[event.type];
4510
- if (!handler) throw new WebhookError(`Unhandled event type: ${event.type}`, { provider: this.providerName });
4758
+ if (!handler)
4759
+ throw new WebhookError(`Unhandled event type: ${event.type}`, {
4760
+ provider: this.providerName
4761
+ });
4511
4762
  const result = await handler(event);
4512
- if (!result) throw new WebhookError(`Unhandled event type: ${event.type}`, { provider: this.providerName });
4763
+ if (!result)
4764
+ throw new WebhookError(`Unhandled event type: ${event.type}`, {
4765
+ provider: this.providerName
4766
+ });
4513
4767
  return result;
4514
4768
  };
4515
- const { debug, apiKey, ...rest } = config;
4769
+ const { debug = true, apiKey, ...rest } = opts;
4516
4770
  this.stripe = new Stripe(apiKey, rest);
4771
+ this.opts = opts;
4517
4772
  }
4518
4773
  };
4519
4774
 
@@ -4522,9 +4777,17 @@ var createStripe = (config) => {
4522
4777
  return new StripeProvider(config);
4523
4778
  };
4524
4779
  var stripe = () => {
4525
- const envVars = validateRequiredKeys(["STRIPE_API_KEY"], process.env, "Missing required environment variables: {keys}");
4780
+ const envVars = validateRequiredKeys(
4781
+ ["STRIPE_API_KEY"],
4782
+ process.env,
4783
+ "Missing required environment variables: {keys}"
4784
+ );
4526
4785
  const isSandbox = process.env.NODE_ENV === "development";
4527
- return createStripe({ apiKey: envVars.STRIPE_API_KEY, debug: isSandbox, apiVersion: "2025-07-30.basil" });
4786
+ return createStripe({
4787
+ apiKey: envVars.STRIPE_API_KEY,
4788
+ debug: isSandbox,
4789
+ apiVersion: "2025-07-30.basil"
4790
+ });
4528
4791
  };
4529
4792
 
4530
4793
  export { createStripe, stripe };
@@ -6,7 +6,8 @@ interface StripeOptions extends PaykitProviderOptions<Stripe.StripeConfig> {
6
6
  }
7
7
  declare class StripeProvider extends AbstractPayKitProvider implements PayKitProvider {
8
8
  private stripe;
9
- constructor(config: StripeOptions);
9
+ private opts;
10
+ constructor(opts: StripeOptions);
10
11
  readonly providerName = "stripe";
11
12
  /**
12
13
  * Checkout management