Initial @trigger.dev/stripe integration, with support for triggers and tasks (#231)
* Initial Stripe integration, with support for triggers and tasks * Adding stripe integration to the catalog
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@trigger.dev/stripe": minor
|
||||
"@trigger.dev/sdk": patch
|
||||
---
|
||||
|
||||
Initial Stripe integration
|
||||
@@ -64,6 +64,7 @@ export function ConnectToIntegrationSheet({
|
||||
to={docsIntegrationPath(integration.identifier)}
|
||||
variant="secondary/small"
|
||||
LeadingIcon="docs"
|
||||
target="_blank"
|
||||
>
|
||||
View docs
|
||||
</LinkButton>
|
||||
|
||||
@@ -28,7 +28,7 @@ export function HelpInstall({ packageName }: { packageName: string }) {
|
||||
<ClientTabsContent value={"pnpm"}>
|
||||
<ClipboardField
|
||||
variant="secondary/medium"
|
||||
value={`pnpm install ${packageName}`}
|
||||
value={`pnpm add ${packageName}`}
|
||||
className="mb-4"
|
||||
/>
|
||||
</ClientTabsContent>
|
||||
|
||||
@@ -45,6 +45,7 @@ export function IntegrationWithMissingFieldSheet({
|
||||
to={docsIntegrationPath(integration.identifier)}
|
||||
variant="secondary/small"
|
||||
LeadingIcon="docs"
|
||||
target="_blank"
|
||||
>
|
||||
View docs
|
||||
</LinkButton>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ActionArgs } from "@remix-run/server-runtime";
|
||||
|
||||
/*
|
||||
To use this route, use the stripe CLI to forward events to this route:
|
||||
|
||||
stripe listen --forward-to localhost:3030/api/internal/stripe_webhooks
|
||||
*/
|
||||
export async function action({ request }: ActionArgs) {
|
||||
const body: any = await request.json();
|
||||
|
||||
const response = await fetch("https://jsonhero.io/api/create.json", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
title: body.type,
|
||||
content: body,
|
||||
readOnly: true,
|
||||
}),
|
||||
});
|
||||
|
||||
const json: any = await response.json();
|
||||
|
||||
console.log({ [body.type]: json.location });
|
||||
|
||||
return json;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { openai } from "./integrations/openai";
|
||||
import { plain } from "./integrations/plain";
|
||||
import { resend } from "./integrations/resend";
|
||||
import { slack } from "./integrations/slack";
|
||||
import { stripe } from "./integrations/stripe";
|
||||
import { supabaseManagement, supabase } from "./integrations/supabase";
|
||||
import { typeform } from "./integrations/typeform";
|
||||
import type { Integration } from "./types";
|
||||
@@ -28,14 +29,13 @@ export class IntegrationCatalog {
|
||||
}
|
||||
|
||||
export const integrationCatalog = new IntegrationCatalog({
|
||||
//todo support airtable
|
||||
// airtable,
|
||||
github,
|
||||
openai,
|
||||
plain,
|
||||
resend,
|
||||
slack,
|
||||
typeform,
|
||||
stripe,
|
||||
supabaseManagement,
|
||||
supabase,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import type { Integration } from "../types";
|
||||
|
||||
export const stripe: Integration = {
|
||||
identifier: "stripe",
|
||||
name: "Stripe",
|
||||
packageName: "@trigger.dev/stripe",
|
||||
authenticationMethods: {
|
||||
apikey: {
|
||||
type: "apikey",
|
||||
help: {
|
||||
samples: [
|
||||
{
|
||||
title: "Creating the integration",
|
||||
code: `
|
||||
import { Stripe } from "@trigger.dev/stripe";
|
||||
|
||||
export const stripe = new Stripe({
|
||||
id: "__SLUG__",
|
||||
apiKey: process.env.PLAIN_API_KEY!,
|
||||
});
|
||||
`,
|
||||
},
|
||||
{
|
||||
title: "Using the integration",
|
||||
code: `
|
||||
client.defineJob({
|
||||
id: "stripe-playground",
|
||||
name: "Stripe Playground",
|
||||
version: "0.1.1",
|
||||
integrations: {
|
||||
stripe,
|
||||
},
|
||||
trigger: eventTrigger({
|
||||
name: "stripe.playground",
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.stripe.createCharge("charge-customer", {
|
||||
amount: 100,
|
||||
currency: "usd",
|
||||
source: payload.source,
|
||||
customer: payload.customerId,
|
||||
});
|
||||
},
|
||||
});
|
||||
`,
|
||||
highlight: [
|
||||
[5, 7],
|
||||
[12, 17],
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Using Stripe triggers",
|
||||
code: `
|
||||
client.defineJob({
|
||||
id: "stripe-on-subscription-created",
|
||||
name: "Stripe On Subscription Created",
|
||||
version: "0.1.0",
|
||||
trigger: stripe.onCustomerSubscriptionCreated({
|
||||
filter: {
|
||||
currency: ["usd"],
|
||||
},
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info("Subscription created in USD!");
|
||||
},
|
||||
});
|
||||
`,
|
||||
highlight: [[5, 9]],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -343,7 +343,7 @@ export function runCompletedPath(runPath: string) {
|
||||
|
||||
// Docs
|
||||
export function docsRoot() {
|
||||
return "https://docs.trigger.dev";
|
||||
return "https://trigger.dev/docs";
|
||||
}
|
||||
|
||||
export function docsPath(path: string) {
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
"react-query": "^3.39.3",
|
||||
"typescript": "5.0.4",
|
||||
"zod": "3.21.4",
|
||||
"@trigger.dev/supabase": "workspace:*"
|
||||
"@trigger.dev/supabase": "workspace:*",
|
||||
"@trigger.dev/stripe": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trigger.dev/cli": "workspace:*",
|
||||
|
||||
@@ -14,5 +14,6 @@ import "@/jobs/typeform";
|
||||
import "@/jobs/edgeCases";
|
||||
import "@/jobs/hooks";
|
||||
import "@/jobs/supabase";
|
||||
import "@/jobs/stripe";
|
||||
|
||||
export const { POST, dynamic } = createAppRoute(client);
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
import { Stripe } from "@trigger.dev/stripe";
|
||||
import { client } from "@/trigger";
|
||||
import { eventTrigger } from "@trigger.dev/sdk";
|
||||
import { z } from "zod";
|
||||
|
||||
const stripe = new Stripe({
|
||||
id: "stripe",
|
||||
apiKey: process.env.STRIPE_API_KEY!,
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-example-1",
|
||||
name: "Stripe Example 1",
|
||||
version: "0.1.0",
|
||||
trigger: eventTrigger({
|
||||
name: "stripe.example",
|
||||
schema: z.object({
|
||||
customerId: z.string(),
|
||||
source: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
stripe,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.stripe.createCharge("create-charge", {
|
||||
amount: 100,
|
||||
currency: "usd",
|
||||
source: payload.source,
|
||||
customer: payload.customerId,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-example-1",
|
||||
name: "Stripe Example 1",
|
||||
version: "0.1.0",
|
||||
trigger: eventTrigger({
|
||||
name: "stripe.example",
|
||||
schema: z.object({
|
||||
customerId: z.string(),
|
||||
source: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
stripe,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.stripe.createCharge("create-charge", {
|
||||
amount: 100,
|
||||
currency: "usd",
|
||||
source: payload.source,
|
||||
customer: payload.customerId,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-create-customer",
|
||||
name: "Stripe Create Customer",
|
||||
version: "0.1.0",
|
||||
trigger: eventTrigger({
|
||||
name: "stripe.new.customer",
|
||||
schema: z.object({
|
||||
email: z.string(),
|
||||
name: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
stripe,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.stripe.createCustomer("create-customer", {
|
||||
email: payload.email,
|
||||
name: payload.name,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-update-customer",
|
||||
name: "Stripe Update Customer",
|
||||
version: "0.1.0",
|
||||
trigger: eventTrigger({
|
||||
name: "stripe.update.customer",
|
||||
schema: z.object({
|
||||
customerId: z.string(),
|
||||
name: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
stripe,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.stripe.updateCustomer("update-customer", {
|
||||
id: payload.customerId,
|
||||
name: payload.name,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-retrieve-subscription",
|
||||
name: "Stripe Retrieve Subscription",
|
||||
version: "0.1.0",
|
||||
trigger: eventTrigger({
|
||||
name: "stripe.retrieve.subscription",
|
||||
schema: z.object({
|
||||
id: z.string(),
|
||||
}),
|
||||
}),
|
||||
integrations: {
|
||||
stripe,
|
||||
},
|
||||
run: async (payload, io, ctx) => {
|
||||
const subscription = await io.stripe.retrieveSubscription("get", {
|
||||
id: payload.id,
|
||||
expand: ["customer"],
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-on-price-created",
|
||||
name: "Stripe On Price Created",
|
||||
version: "0.1.0",
|
||||
trigger: stripe.onPriceCreated(),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info("ctx", { ctx });
|
||||
},
|
||||
});
|
||||
|
||||
client.defineJob({
|
||||
id: "stripe-on-subscription-created",
|
||||
name: "Stripe On Subscription Created",
|
||||
version: "0.1.0",
|
||||
trigger: stripe.onCustomerSubscriptionCreated({
|
||||
filter: {
|
||||
currency: ["usd"],
|
||||
},
|
||||
}),
|
||||
run: async (payload, io, ctx) => {
|
||||
await io.logger.info("ctx", { ctx });
|
||||
},
|
||||
});
|
||||
@@ -18,8 +18,6 @@
|
||||
"@/*": ["./src/*"],
|
||||
"@trigger.dev/sdk": ["../../packages/trigger-sdk/src/index"],
|
||||
"@trigger.dev/sdk/*": ["../../packages/trigger-sdk/src/*"],
|
||||
"@trigger.dev/react": ["../../packages/react/src/index"],
|
||||
"@trigger.dev/react/*": ["../../packages/react/src/*"],
|
||||
"@trigger.dev/nextjs": ["../../packages/nextjs/src/index"],
|
||||
"@trigger.dev/nextjs/*": ["../../packages/nextjs/src/*"],
|
||||
"@trigger.dev/internal": ["../../packages/internal/src/index"],
|
||||
@@ -43,7 +41,9 @@
|
||||
"@trigger.dev/plain": ["../../integrations/plain/src/index"],
|
||||
"@trigger.dev/plain/*": ["../../integrations/plain/src/*"],
|
||||
"@trigger.dev/supabase": ["../../integrations/supabase/src/index"],
|
||||
"@trigger.dev/supabase/*": ["../../integrations/supabase/src/*"]
|
||||
"@trigger.dev/supabase/*": ["../../integrations/supabase/src/*"],
|
||||
"@trigger.dev/stripe": ["../../integrations/stripe/src/index"],
|
||||
"@trigger.dev/stripe/*": ["../../integrations/stripe/src/*"]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
# @trigger.dev/stripe
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@trigger.dev/stripe",
|
||||
"version": "0.0.1",
|
||||
"description": "Trigger.dev integration for stripe",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"dist/index.js",
|
||||
"dist/index.d.ts",
|
||||
"dist/index.js.map"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@types/node": "16.x",
|
||||
"rimraf": "^3.0.2",
|
||||
"stripe-event-types": "^2.4.0",
|
||||
"tsup": "7.1.x",
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"build": "npm run clean && npm run build:tsup",
|
||||
"build:tsup": "tsup",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@trigger.dev/integration-kit": "workspace:^2.0.0-next.5",
|
||||
"@trigger.dev/sdk": "workspace:^2.0.0-next.19",
|
||||
"stripe": "^12.14.0",
|
||||
"zod": "3.21.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.8.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,347 @@
|
||||
import type { EventSpecification } from "@trigger.dev/sdk";
|
||||
import {
|
||||
cancelledSubscriptionExample,
|
||||
checkoutSessionExample,
|
||||
customerSubscriptionExample,
|
||||
pausedSubscriptionExample,
|
||||
updatedSubscriptionExample,
|
||||
} from "./examples";
|
||||
import {
|
||||
OnCheckoutSession,
|
||||
OnCustomerSubscription,
|
||||
OnPriceEvent,
|
||||
OnProductEvent,
|
||||
} from "./types";
|
||||
|
||||
export const onPriceCreated: EventSpecification<OnPriceEvent> = {
|
||||
name: "price.created",
|
||||
title: "On Price Created",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [
|
||||
{
|
||||
id: "recurring",
|
||||
name: "Recurring Price",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "price_1NYV6vI0XSgju2urKsSmI53v",
|
||||
object: "price",
|
||||
active: true,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690467853,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLBTh0QPxDXkIU",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 1500,
|
||||
unit_amount_decimal: "1500",
|
||||
},
|
||||
},
|
||||
],
|
||||
parsePayload: (payload) => payload as OnPriceEvent,
|
||||
runProperties: (payload) => [{ label: "Price ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onPriceUpdated: EventSpecification<OnPriceEvent> = {
|
||||
name: "price.updated",
|
||||
title: "On Price Updated",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [
|
||||
{
|
||||
id: "recurring",
|
||||
name: "Recurring Price",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "price_1NYVmXI0XSgju2urA56rnf3e",
|
||||
object: "price",
|
||||
active: true,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690470433,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {
|
||||
foo: "bar",
|
||||
},
|
||||
nickname: null,
|
||||
product: "prod_OLCAdNbcBTwgEn",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 1500,
|
||||
unit_amount_decimal: "1500",
|
||||
},
|
||||
},
|
||||
],
|
||||
parsePayload: (payload) => payload as OnPriceEvent,
|
||||
runProperties: (payload) => [{ label: "Price ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onPriceDeleted: EventSpecification<OnPriceEvent> = {
|
||||
name: "price.deleted",
|
||||
title: "On Price Deleted",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [
|
||||
{
|
||||
id: "recurring",
|
||||
name: "Recurring Price",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "plan_OLCbCoAUbHPcHT",
|
||||
object: "price",
|
||||
active: false,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690472058,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLCbckE3tpR34b",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 2000,
|
||||
unit_amount_decimal: "2000",
|
||||
},
|
||||
},
|
||||
],
|
||||
parsePayload: (payload) => payload as OnPriceEvent,
|
||||
runProperties: (payload) => [{ label: "Price ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onProductCreated: EventSpecification<OnProductEvent> = {
|
||||
name: "product.created",
|
||||
title: "On Product Created",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [
|
||||
{
|
||||
id: "mock_product",
|
||||
name: "Mock Product",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "prod_OLBTh0QPxDXkIU",
|
||||
object: "product",
|
||||
active: true,
|
||||
attributes: [],
|
||||
created: 1690467853,
|
||||
default_price: null,
|
||||
description: "(created by Stripe CLI)",
|
||||
images: [],
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
name: "myproduct",
|
||||
package_dimensions: null,
|
||||
shippable: null,
|
||||
statement_descriptor: null,
|
||||
tax_code: null,
|
||||
type: "service",
|
||||
unit_label: null,
|
||||
updated: 1690467853,
|
||||
url: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
parsePayload: (payload) => payload as OnProductEvent,
|
||||
runProperties: (payload) => [{ label: "Product ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onProductUpdated: EventSpecification<OnProductEvent> = {
|
||||
name: "product.updated",
|
||||
title: "On Product Updated",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [
|
||||
{
|
||||
id: "mock_product",
|
||||
name: "Mock Product",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "prod_OLBTh0QPxDXkIU",
|
||||
object: "product",
|
||||
active: true,
|
||||
attributes: [],
|
||||
created: 1690467853,
|
||||
default_price: null,
|
||||
description: "(created by Stripe CLI)",
|
||||
images: [],
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
name: "myproduct",
|
||||
package_dimensions: null,
|
||||
shippable: null,
|
||||
statement_descriptor: null,
|
||||
tax_code: null,
|
||||
type: "service",
|
||||
unit_label: null,
|
||||
updated: 1690467853,
|
||||
url: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
parsePayload: (payload) => payload as OnProductEvent,
|
||||
runProperties: (payload) => [{ label: "Product ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onProductDeleted: EventSpecification<OnProductEvent> = {
|
||||
name: "product.deleted",
|
||||
title: "On Product Deleted",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [
|
||||
{
|
||||
id: "mock_product",
|
||||
name: "Mock Product",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "prod_OLBTh0QPxDXkIU",
|
||||
object: "product",
|
||||
active: true,
|
||||
attributes: [],
|
||||
created: 1690467853,
|
||||
default_price: null,
|
||||
description: "(created by Stripe CLI)",
|
||||
images: [],
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
name: "myproduct",
|
||||
package_dimensions: null,
|
||||
shippable: null,
|
||||
statement_descriptor: null,
|
||||
tax_code: null,
|
||||
type: "service",
|
||||
unit_label: null,
|
||||
updated: 1690467853,
|
||||
url: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
parsePayload: (payload) => payload as OnProductEvent,
|
||||
runProperties: (payload) => [{ label: "Product ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onCheckoutSessionCompleted: EventSpecification<OnCheckoutSession> =
|
||||
{
|
||||
name: "checkout.session.completed",
|
||||
title: "On Checkout Session Completed",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [checkoutSessionExample],
|
||||
parsePayload: (payload) => payload as OnCheckoutSession,
|
||||
runProperties: (payload) => [{ label: "Session ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onCheckoutSessionExpired: EventSpecification<OnCheckoutSession> = {
|
||||
name: "checkout.session.expired",
|
||||
title: "On Checkout Session Expired",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [checkoutSessionExample],
|
||||
parsePayload: (payload) => payload as OnCheckoutSession,
|
||||
runProperties: (payload) => [{ label: "Session ID", text: payload.id }],
|
||||
};
|
||||
|
||||
export const onCustomerSubscriptionCreated: EventSpecification<OnCustomerSubscription> =
|
||||
{
|
||||
name: "customer.subscription.created",
|
||||
title: "On Customer Subscription Created",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [customerSubscriptionExample],
|
||||
parsePayload: (payload) => payload as OnCustomerSubscription,
|
||||
runProperties: (payload) => [
|
||||
{ label: "Subscription ID", text: payload.id },
|
||||
{ label: "Status", text: payload.status },
|
||||
],
|
||||
};
|
||||
|
||||
export const onCustomerSubscriptionPaused: EventSpecification<OnCustomerSubscription> =
|
||||
{
|
||||
name: "customer.subscription.paused",
|
||||
title: "On Customer Subscription Paused",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [pausedSubscriptionExample],
|
||||
parsePayload: (payload) => payload as OnCustomerSubscription,
|
||||
runProperties: (payload) => [
|
||||
{ label: "Subscription ID", text: payload.id },
|
||||
{ label: "Status", text: payload.status },
|
||||
],
|
||||
};
|
||||
|
||||
export const onCustomerSubscriptionResumed: EventSpecification<OnCustomerSubscription> =
|
||||
{
|
||||
name: "customer.subscription.resumed",
|
||||
title: "On Customer Subscription Resumed",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [customerSubscriptionExample],
|
||||
parsePayload: (payload) => payload as OnCustomerSubscription,
|
||||
runProperties: (payload) => [
|
||||
{ label: "Subscription ID", text: payload.id },
|
||||
{ label: "Status", text: payload.status },
|
||||
],
|
||||
};
|
||||
|
||||
export const onCustomerSubscriptionDeleted: EventSpecification<OnCustomerSubscription> =
|
||||
{
|
||||
name: "customer.subscription.deleted",
|
||||
title: "On Customer Subscription Deleted",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [cancelledSubscriptionExample],
|
||||
parsePayload: (payload) => payload as OnCustomerSubscription,
|
||||
runProperties: (payload) => [
|
||||
{ label: "Subscription ID", text: payload.id },
|
||||
{ label: "Status", text: payload.status },
|
||||
],
|
||||
};
|
||||
|
||||
export const onCustomerSubscriptionUpdated: EventSpecification<OnCustomerSubscription> =
|
||||
{
|
||||
name: "customer.subscription.updated",
|
||||
title: "On Customer Subscription Deleted",
|
||||
source: "stripe.com",
|
||||
icon: "stripe",
|
||||
examples: [updatedSubscriptionExample],
|
||||
parsePayload: (payload) => payload as OnCustomerSubscription,
|
||||
runProperties: (payload) => [
|
||||
{ label: "Subscription ID", text: payload.id },
|
||||
{ label: "Status", text: payload.status },
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,700 @@
|
||||
export const checkoutSessionExample = {
|
||||
id: "test_session",
|
||||
name: "Mock Checkout Session",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "cs_test_a1LFuyKHsmzBxr6SvxfFu184ISK2sNebnb60DloYuCenBcJtfGttTydm4n",
|
||||
object: "checkout.session",
|
||||
after_expiration: null,
|
||||
allow_promotion_codes: null,
|
||||
amount_subtotal: 3000,
|
||||
amount_total: 3000,
|
||||
automatic_tax: {
|
||||
enabled: false,
|
||||
status: null,
|
||||
},
|
||||
billing_address_collection: null,
|
||||
cancel_url: "https://httpbin.org/post",
|
||||
client_reference_id: null,
|
||||
consent: null,
|
||||
consent_collection: null,
|
||||
created: 1690472483,
|
||||
currency: "usd",
|
||||
currency_conversion: null,
|
||||
custom_fields: [],
|
||||
custom_text: {
|
||||
shipping_address: null,
|
||||
submit: null,
|
||||
},
|
||||
customer: null,
|
||||
customer_creation: "if_required",
|
||||
customer_details: {
|
||||
address: {
|
||||
city: "South San Francisco",
|
||||
country: "US",
|
||||
line1: "354 Oyster Point Blvd",
|
||||
line2: null,
|
||||
postal_code: "94080",
|
||||
state: "CA",
|
||||
},
|
||||
email: "stripe@example.com",
|
||||
name: "Jenny Rosen",
|
||||
phone: null,
|
||||
tax_exempt: "none",
|
||||
tax_ids: [],
|
||||
},
|
||||
customer_email: null,
|
||||
expires_at: 1690558883,
|
||||
invoice: null,
|
||||
invoice_creation: {
|
||||
enabled: false,
|
||||
invoice_data: {
|
||||
account_tax_ids: null,
|
||||
custom_fields: null,
|
||||
description: null,
|
||||
footer: null,
|
||||
metadata: {},
|
||||
rendering_options: null,
|
||||
},
|
||||
},
|
||||
livemode: false,
|
||||
locale: null,
|
||||
metadata: {},
|
||||
mode: "payment",
|
||||
payment_intent: "pi_3NYWJcI0XSgju2ur1bZTeRhR",
|
||||
payment_link: null,
|
||||
payment_method_collection: "always",
|
||||
payment_method_options: {},
|
||||
payment_method_types: ["card"],
|
||||
payment_status: "paid",
|
||||
phone_number_collection: {
|
||||
enabled: false,
|
||||
},
|
||||
recovered_from: null,
|
||||
setup_intent: null,
|
||||
shipping_address_collection: null,
|
||||
shipping_cost: null,
|
||||
shipping_details: null,
|
||||
shipping_options: [],
|
||||
status: "complete",
|
||||
submit_type: null,
|
||||
subscription: null,
|
||||
success_url: "https://httpbin.org/post",
|
||||
total_details: {
|
||||
amount_discount: 0,
|
||||
amount_shipping: 0,
|
||||
amount_tax: 0,
|
||||
},
|
||||
url: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const customerSubscriptionExample = {
|
||||
id: "test_subscription",
|
||||
name: "Mock Subscription",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "sub_1NYWgUI0XSgju2urmVcglalG",
|
||||
object: "subscription",
|
||||
application: null,
|
||||
application_fee_percent: null,
|
||||
automatic_tax: {
|
||||
enabled: false,
|
||||
},
|
||||
billing_cycle_anchor: 1690473902,
|
||||
billing_thresholds: null,
|
||||
cancel_at: null,
|
||||
cancel_at_period_end: false,
|
||||
canceled_at: null,
|
||||
cancellation_details: {
|
||||
comment: null,
|
||||
feedback: null,
|
||||
reason: null,
|
||||
},
|
||||
collection_method: "charge_automatically",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
current_period_end: 1693152302,
|
||||
current_period_start: 1690473902,
|
||||
customer: "cus_OLD6IR3D8CJasG",
|
||||
days_until_due: null,
|
||||
default_payment_method: null,
|
||||
default_source: null,
|
||||
default_tax_rates: [],
|
||||
description: null,
|
||||
discount: null,
|
||||
ended_at: null,
|
||||
items: {
|
||||
object: "list",
|
||||
data: [
|
||||
{
|
||||
id: "si_OLD6qgIKdp0wZO",
|
||||
object: "subscription_item",
|
||||
billing_thresholds: null,
|
||||
created: 1690473903,
|
||||
metadata: {},
|
||||
plan: {
|
||||
id: "price_1NYWgUI0XSgju2ur3rwJGw1n",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLD6aEjleFDUfA",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
price: {
|
||||
id: "price_1NYWgUI0XSgju2ur3rwJGw1n",
|
||||
object: "price",
|
||||
active: true,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLD6aEjleFDUfA",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 1500,
|
||||
unit_amount_decimal: "1500",
|
||||
},
|
||||
quantity: 1,
|
||||
subscription: "sub_1NYWgUI0XSgju2urmVcglalG",
|
||||
tax_rates: [],
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
total_count: 1,
|
||||
url: "/v1/subscription_items?subscription=sub_1NYWgUI0XSgju2urmVcglalG",
|
||||
},
|
||||
latest_invoice: "in_1NYWgUI0XSgju2urV5ZTEyIn",
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
next_pending_invoice_item_invoice: null,
|
||||
on_behalf_of: null,
|
||||
pause_collection: null,
|
||||
payment_settings: {
|
||||
payment_method_options: null,
|
||||
payment_method_types: null,
|
||||
save_default_payment_method: "off",
|
||||
},
|
||||
pending_invoice_item_interval: null,
|
||||
pending_setup_intent: null,
|
||||
pending_update: null,
|
||||
plan: {
|
||||
id: "price_1NYWgUI0XSgju2ur3rwJGw1n",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLD6aEjleFDUfA",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
quantity: 1,
|
||||
schedule: null,
|
||||
start_date: 1690473902,
|
||||
status: "active",
|
||||
test_clock: null,
|
||||
transfer_data: null,
|
||||
trial_end: null,
|
||||
trial_settings: {
|
||||
end_behavior: {
|
||||
missing_payment_method: "create_invoice",
|
||||
},
|
||||
},
|
||||
trial_start: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const pausedSubscriptionExample = {
|
||||
id: "test_subscription",
|
||||
name: "Mock Subscription",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "sub_1NYWgUI0XSgju2urmVcglalG",
|
||||
object: "subscription",
|
||||
application: null,
|
||||
application_fee_percent: null,
|
||||
automatic_tax: {
|
||||
enabled: false,
|
||||
},
|
||||
billing_cycle_anchor: 1690473902,
|
||||
billing_thresholds: null,
|
||||
cancel_at: null,
|
||||
cancel_at_period_end: false,
|
||||
canceled_at: null,
|
||||
cancellation_details: {
|
||||
comment: null,
|
||||
feedback: null,
|
||||
reason: null,
|
||||
},
|
||||
collection_method: "charge_automatically",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
current_period_end: 1693152302,
|
||||
current_period_start: 1690473902,
|
||||
customer: "cus_OLD6IR3D8CJasG",
|
||||
days_until_due: null,
|
||||
default_payment_method: null,
|
||||
default_source: null,
|
||||
default_tax_rates: [],
|
||||
description: null,
|
||||
discount: null,
|
||||
ended_at: null,
|
||||
items: {
|
||||
object: "list",
|
||||
data: [
|
||||
{
|
||||
id: "si_OLD6qgIKdp0wZO",
|
||||
object: "subscription_item",
|
||||
billing_thresholds: null,
|
||||
created: 1690473903,
|
||||
metadata: {},
|
||||
plan: {
|
||||
id: "price_1NYWgUI0XSgju2ur3rwJGw1n",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLD6aEjleFDUfA",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
price: {
|
||||
id: "price_1NYWgUI0XSgju2ur3rwJGw1n",
|
||||
object: "price",
|
||||
active: true,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLD6aEjleFDUfA",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 1500,
|
||||
unit_amount_decimal: "1500",
|
||||
},
|
||||
quantity: 1,
|
||||
subscription: "sub_1NYWgUI0XSgju2urmVcglalG",
|
||||
tax_rates: [],
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
total_count: 1,
|
||||
url: "/v1/subscription_items?subscription=sub_1NYWgUI0XSgju2urmVcglalG",
|
||||
},
|
||||
latest_invoice: "in_1NYWgUI0XSgju2urV5ZTEyIn",
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
next_pending_invoice_item_invoice: null,
|
||||
on_behalf_of: null,
|
||||
pause_collection: null,
|
||||
payment_settings: {
|
||||
payment_method_options: null,
|
||||
payment_method_types: null,
|
||||
save_default_payment_method: "off",
|
||||
},
|
||||
pending_invoice_item_interval: null,
|
||||
pending_setup_intent: null,
|
||||
pending_update: null,
|
||||
plan: {
|
||||
id: "price_1NYWgUI0XSgju2ur3rwJGw1n",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690473902,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLD6aEjleFDUfA",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
quantity: 1,
|
||||
schedule: null,
|
||||
start_date: 1690473902,
|
||||
status: "paused",
|
||||
test_clock: null,
|
||||
transfer_data: null,
|
||||
trial_end: null,
|
||||
trial_settings: {
|
||||
end_behavior: {
|
||||
missing_payment_method: "create_invoice",
|
||||
},
|
||||
},
|
||||
trial_start: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const cancelledSubscriptionExample = {
|
||||
id: "test_subscription",
|
||||
name: "Cancelled Subscription",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "sub_1NYWmqI0XSgju2urM6J7U81g",
|
||||
object: "subscription",
|
||||
application: null,
|
||||
application_fee_percent: null,
|
||||
automatic_tax: {
|
||||
enabled: false,
|
||||
},
|
||||
billing_cycle_anchor: 1690474295,
|
||||
billing_thresholds: null,
|
||||
cancel_at: null,
|
||||
cancel_at_period_end: false,
|
||||
canceled_at: 1690474298,
|
||||
cancellation_details: {
|
||||
comment: null,
|
||||
feedback: null,
|
||||
reason: "cancellation_requested",
|
||||
},
|
||||
collection_method: "charge_automatically",
|
||||
created: 1690474295,
|
||||
currency: "usd",
|
||||
current_period_end: 1693152695,
|
||||
current_period_start: 1690474295,
|
||||
customer: "cus_OLDDzu7ZE2wLZB",
|
||||
days_until_due: null,
|
||||
default_payment_method: null,
|
||||
default_source: null,
|
||||
default_tax_rates: [],
|
||||
description: null,
|
||||
discount: null,
|
||||
ended_at: 1690474298,
|
||||
items: {
|
||||
object: "list",
|
||||
data: [
|
||||
{
|
||||
id: "si_OLDDWvHquPJrro",
|
||||
object: "subscription_item",
|
||||
billing_thresholds: null,
|
||||
created: 1690474296,
|
||||
metadata: {},
|
||||
plan: {
|
||||
id: "price_1NYWmpI0XSgju2ur8YboK1MK",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690474295,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLDDFHiTTQUoPT",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
price: {
|
||||
id: "price_1NYWmpI0XSgju2ur8YboK1MK",
|
||||
object: "price",
|
||||
active: true,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690474295,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLDDFHiTTQUoPT",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 1500,
|
||||
unit_amount_decimal: "1500",
|
||||
},
|
||||
quantity: 1,
|
||||
subscription: "sub_1NYWmqI0XSgju2urM6J7U81g",
|
||||
tax_rates: [],
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
total_count: 1,
|
||||
url: "/v1/subscription_items?subscription=sub_1NYWmqI0XSgju2urM6J7U81g",
|
||||
},
|
||||
latest_invoice: "in_1NYWmqI0XSgju2ur1YkCeiE3",
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
next_pending_invoice_item_invoice: null,
|
||||
on_behalf_of: null,
|
||||
pause_collection: null,
|
||||
payment_settings: {
|
||||
payment_method_options: null,
|
||||
payment_method_types: null,
|
||||
save_default_payment_method: "off",
|
||||
},
|
||||
pending_invoice_item_interval: null,
|
||||
pending_setup_intent: null,
|
||||
pending_update: null,
|
||||
plan: {
|
||||
id: "price_1NYWmpI0XSgju2ur8YboK1MK",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690474295,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLDDFHiTTQUoPT",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
quantity: 1,
|
||||
schedule: null,
|
||||
start_date: 1690474295,
|
||||
status: "canceled",
|
||||
test_clock: null,
|
||||
transfer_data: null,
|
||||
trial_end: null,
|
||||
trial_settings: {
|
||||
end_behavior: {
|
||||
missing_payment_method: "create_invoice",
|
||||
},
|
||||
},
|
||||
trial_start: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const updatedSubscriptionExample = {
|
||||
id: "test_subscription",
|
||||
name: "Updated Subscription",
|
||||
icon: "stripe",
|
||||
payload: {
|
||||
id: "sub_1NYWr9I0XSgju2urREzIjypw",
|
||||
object: "subscription",
|
||||
application: null,
|
||||
application_fee_percent: null,
|
||||
automatic_tax: {
|
||||
enabled: false,
|
||||
},
|
||||
billing_cycle_anchor: 1690474563,
|
||||
billing_thresholds: null,
|
||||
cancel_at: null,
|
||||
cancel_at_period_end: false,
|
||||
canceled_at: null,
|
||||
cancellation_details: {
|
||||
comment: null,
|
||||
feedback: null,
|
||||
reason: null,
|
||||
},
|
||||
collection_method: "charge_automatically",
|
||||
created: 1690474563,
|
||||
currency: "usd",
|
||||
current_period_end: 1693152963,
|
||||
current_period_start: 1690474563,
|
||||
customer: "cus_OLDHaOoGMJKpbQ",
|
||||
days_until_due: null,
|
||||
default_payment_method: null,
|
||||
default_source: null,
|
||||
default_tax_rates: [],
|
||||
description: null,
|
||||
discount: null,
|
||||
ended_at: null,
|
||||
items: {
|
||||
object: "list",
|
||||
data: [
|
||||
{
|
||||
id: "si_OLDHbwqQpcI7wJ",
|
||||
object: "subscription_item",
|
||||
billing_thresholds: null,
|
||||
created: 1690474564,
|
||||
metadata: {},
|
||||
plan: {
|
||||
id: "price_1NYWr9I0XSgju2urK88vlVrN",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690474563,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLDHCaYW7Sp4Xg",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
price: {
|
||||
id: "price_1NYWr9I0XSgju2urK88vlVrN",
|
||||
object: "price",
|
||||
active: true,
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690474563,
|
||||
currency: "usd",
|
||||
custom_unit_amount: null,
|
||||
livemode: false,
|
||||
lookup_key: null,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLDHCaYW7Sp4Xg",
|
||||
recurring: {
|
||||
aggregate_usage: null,
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
tax_behavior: "unspecified",
|
||||
tiers_mode: null,
|
||||
transform_quantity: null,
|
||||
type: "recurring",
|
||||
unit_amount: 1500,
|
||||
unit_amount_decimal: "1500",
|
||||
},
|
||||
quantity: 1,
|
||||
subscription: "sub_1NYWr9I0XSgju2urREzIjypw",
|
||||
tax_rates: [],
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
total_count: 1,
|
||||
url: "/v1/subscription_items?subscription=sub_1NYWr9I0XSgju2urREzIjypw",
|
||||
},
|
||||
latest_invoice: "in_1NYWr9I0XSgju2uro3uB0RuT",
|
||||
livemode: false,
|
||||
metadata: {
|
||||
foo: "bar",
|
||||
},
|
||||
next_pending_invoice_item_invoice: null,
|
||||
on_behalf_of: null,
|
||||
pause_collection: null,
|
||||
payment_settings: {
|
||||
payment_method_options: null,
|
||||
payment_method_types: null,
|
||||
save_default_payment_method: "off",
|
||||
},
|
||||
pending_invoice_item_interval: null,
|
||||
pending_setup_intent: null,
|
||||
pending_update: null,
|
||||
plan: {
|
||||
id: "price_1NYWr9I0XSgju2urK88vlVrN",
|
||||
object: "plan",
|
||||
active: true,
|
||||
aggregate_usage: null,
|
||||
amount: 1500,
|
||||
amount_decimal: "1500",
|
||||
billing_scheme: "per_unit",
|
||||
created: 1690474563,
|
||||
currency: "usd",
|
||||
interval: "month",
|
||||
interval_count: 1,
|
||||
livemode: false,
|
||||
metadata: {},
|
||||
nickname: null,
|
||||
product: "prod_OLDHCaYW7Sp4Xg",
|
||||
tiers_mode: null,
|
||||
transform_usage: null,
|
||||
trial_period_days: null,
|
||||
usage_type: "licensed",
|
||||
},
|
||||
quantity: 1,
|
||||
schedule: null,
|
||||
start_date: 1690474563,
|
||||
status: "active",
|
||||
test_clock: null,
|
||||
transfer_data: null,
|
||||
trial_end: null,
|
||||
trial_settings: {
|
||||
end_behavior: {
|
||||
missing_payment_method: "create_invoice",
|
||||
},
|
||||
},
|
||||
trial_start: null,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,384 @@
|
||||
import { Stripe as StripeClient } from "stripe";
|
||||
import {
|
||||
EventFilter,
|
||||
ExternalSource,
|
||||
ExternalSourceTrigger,
|
||||
type HandlerEvent,
|
||||
type IntegrationClient,
|
||||
type Logger,
|
||||
type TriggerIntegration,
|
||||
} from "@trigger.dev/sdk";
|
||||
import type {
|
||||
StripeSDK,
|
||||
StripeIntegrationOptions,
|
||||
WebhookEvents,
|
||||
} from "./types";
|
||||
|
||||
import * as tasks from "./tasks";
|
||||
import z from "zod";
|
||||
import * as events from "./events";
|
||||
|
||||
export * from "./types";
|
||||
|
||||
type StripeIntegrationClient = IntegrationClient<StripeSDK, typeof tasks>;
|
||||
type StripeIntegration = TriggerIntegration<StripeIntegrationClient>;
|
||||
|
||||
export class Stripe implements StripeIntegration {
|
||||
client: StripeIntegrationClient;
|
||||
|
||||
constructor(private options: StripeIntegrationOptions) {
|
||||
this.client = {
|
||||
tasks,
|
||||
usesLocalAuth: true,
|
||||
client: new StripeClient(options.apiKey, {
|
||||
apiVersion: "2022-11-15",
|
||||
typescript: true,
|
||||
timeout: 10000,
|
||||
maxNetworkRetries: 0,
|
||||
stripeAccount: options.stripeAccount,
|
||||
appInfo: {
|
||||
name: "Trigger.dev Stripe Integration",
|
||||
version: "0.1.0",
|
||||
url: "https://trigger.dev",
|
||||
},
|
||||
}),
|
||||
auth: {
|
||||
apiKey: options.apiKey,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this.options.id;
|
||||
}
|
||||
|
||||
get metadata() {
|
||||
return { id: "stripe", name: "Stripe" };
|
||||
}
|
||||
|
||||
get source() {
|
||||
return createWebhookEventSource(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a price is created.
|
||||
*/
|
||||
onPriceCreated(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onPriceCreated,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a price is updated.
|
||||
*/
|
||||
onPriceUpdated(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onPriceUpdated,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a price is deleted.
|
||||
*/
|
||||
onPriceDeleted(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onPriceDeleted,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a product is created.
|
||||
*/
|
||||
onProductCreated(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onProductCreated,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a product is updated.
|
||||
*/
|
||||
onProductUpdated(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onProductUpdated,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a product is deleted.
|
||||
*/
|
||||
onProductDeleted(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onProductDeleted,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs when a Checkout Session has been successfully completed.
|
||||
*/
|
||||
onCheckoutSessionCompleted(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCheckoutSessionCompleted,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs when a Checkout Session is expired.
|
||||
*/
|
||||
onCheckoutSessionExpired(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCheckoutSessionExpired,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a customer is signed up for a new plan.
|
||||
*/
|
||||
onCustomerSubscriptionCreated(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCustomerSubscriptionCreated,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a customer's subscription is paused. Only applies when subscriptions enter `status=paused`, not when [payment collection](https://stripe.com/docs/billing/subscriptions/pause) is paused.
|
||||
*/
|
||||
onCustomerSubscriptionPaused(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCustomerSubscriptionPaused,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a customer's subscription is no longer paused. Only applies when a `status=paused` subscription is [resumed](https://stripe.com/docs/api/subscriptions/resume), not when [payment collection](https://stripe.com/docs/billing/subscriptions/pause) is resumed.
|
||||
*/
|
||||
onCustomerSubscriptionResumed(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCustomerSubscriptionResumed,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a subscription changes (e.g., switching from one plan to another, or changing the status from trial to active).
|
||||
*/
|
||||
onCustomerSubscriptionUpdated(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCustomerSubscriptionUpdated,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Occurs whenever a customer's subscription ends.
|
||||
*/
|
||||
onCustomerSubscriptionDeleted(params?: TriggerParams) {
|
||||
return createTrigger(
|
||||
this.source,
|
||||
events.onCustomerSubscriptionDeleted,
|
||||
params ?? { connect: false }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export type TriggerParams = {
|
||||
connect?: boolean;
|
||||
filter?: EventFilter;
|
||||
};
|
||||
|
||||
type StripeEvents = (typeof events)[keyof typeof events];
|
||||
|
||||
type CreateTriggersResult<TEventSpecification extends StripeEvents> =
|
||||
ExternalSourceTrigger<
|
||||
TEventSpecification,
|
||||
ReturnType<typeof createWebhookEventSource>
|
||||
>;
|
||||
|
||||
function createTrigger<TEventSpecification extends StripeEvents>(
|
||||
source: ReturnType<typeof createWebhookEventSource>,
|
||||
event: TEventSpecification,
|
||||
params: TriggerParams
|
||||
): CreateTriggersResult<TEventSpecification> {
|
||||
return new ExternalSourceTrigger({
|
||||
event,
|
||||
params,
|
||||
source,
|
||||
});
|
||||
}
|
||||
|
||||
const WebhookDataSchema = z.object({
|
||||
id: z.string(),
|
||||
object: z.literal("webhook_endpoint"),
|
||||
api_version: z.string().nullable(),
|
||||
application: z.string().nullable(),
|
||||
created: z.number(),
|
||||
description: z.string().nullable(),
|
||||
enabled_events: z.array(z.string()),
|
||||
livemode: z.boolean(),
|
||||
metadata: z.record(z.string()),
|
||||
status: z.enum(["enabled", "disabled"]),
|
||||
url: z.string(),
|
||||
});
|
||||
|
||||
function createWebhookEventSource(
|
||||
integration: StripeIntegration
|
||||
): ExternalSource<StripeIntegration, { connect?: boolean }, "HTTP"> {
|
||||
return new ExternalSource("HTTP", {
|
||||
id: "stripe.webhook",
|
||||
schema: z.object({ connect: z.boolean().optional() }),
|
||||
version: "0.1.0",
|
||||
integration,
|
||||
key: (params) => `stripe.webhook${params.connect ? ".connect" : ""}`,
|
||||
handler: webhookHandler,
|
||||
register: async (event, io, ctx) => {
|
||||
const { params, source: httpSource, events, missingEvents } = event;
|
||||
|
||||
const webhookData = WebhookDataSchema.safeParse(httpSource.data);
|
||||
|
||||
const allEvents = Array.from(new Set([...events, ...missingEvents]));
|
||||
|
||||
if (httpSource.active && webhookData.success) {
|
||||
if (missingEvents.length === 0) return;
|
||||
|
||||
const updatedWebhook = await io.integration.updateWebhook(
|
||||
"update-webhook",
|
||||
{
|
||||
id: webhookData.data.id,
|
||||
url: httpSource.url,
|
||||
enabled_events: allEvents as unknown as WebhookEvents[],
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
data: WebhookDataSchema.parse(updatedWebhook),
|
||||
registeredEvents: allEvents,
|
||||
};
|
||||
}
|
||||
|
||||
const listResponse = await io.integration.listWebhooks("list-webhooks", {
|
||||
limit: 100,
|
||||
});
|
||||
|
||||
const existingWebhook = listResponse.data.find(
|
||||
(w) => w.url === httpSource.url
|
||||
);
|
||||
|
||||
if (existingWebhook) {
|
||||
const updatedWebhook = await io.integration.updateWebhook(
|
||||
"update-found-webhook",
|
||||
{
|
||||
id: existingWebhook.id,
|
||||
url: httpSource.url,
|
||||
enabled_events: allEvents as unknown as WebhookEvents[],
|
||||
disabled: false,
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
data: WebhookDataSchema.parse(updatedWebhook),
|
||||
registeredEvents: allEvents,
|
||||
};
|
||||
}
|
||||
|
||||
const webhook = await io.integration.createWebhook("create-webhook", {
|
||||
url: httpSource.url,
|
||||
enabled_events: allEvents as unknown as WebhookEvents[],
|
||||
connect: params.connect,
|
||||
});
|
||||
|
||||
return {
|
||||
data: WebhookDataSchema.parse(webhook),
|
||||
secret: webhook.secret,
|
||||
registeredEvents: allEvents,
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function webhookHandler(event: HandlerEvent<"HTTP">, logger: Logger) {
|
||||
logger.debug("[@trigger.dev/stripe] Handling webhook payload");
|
||||
|
||||
const { rawEvent: request, source } = event;
|
||||
|
||||
if (!request.body) {
|
||||
logger.debug("[@trigger.dev/stripe] No body found");
|
||||
|
||||
return { events: [] };
|
||||
}
|
||||
|
||||
const rawBody = await request.text();
|
||||
|
||||
const signature = request.headers.get("stripe-signature");
|
||||
|
||||
if (signature) {
|
||||
const stripeClient = new StripeClient("", { apiVersion: "2022-11-15" });
|
||||
|
||||
try {
|
||||
const event = stripeClient.webhooks.constructEvent(
|
||||
rawBody,
|
||||
signature,
|
||||
source.secret
|
||||
);
|
||||
|
||||
return {
|
||||
events: [
|
||||
{
|
||||
id: event.id,
|
||||
payload: event.data.object,
|
||||
source: "stripe.com",
|
||||
name: event.type,
|
||||
timestamp: new Date(event.created * 1000),
|
||||
context: {
|
||||
apiVersion: event.api_version,
|
||||
livemode: event.livemode,
|
||||
request: event.request,
|
||||
previousAttributes: event.data.previous_attributes,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
logger.error(
|
||||
"[@trigger.dev/stripe] Error while validating webhook signature",
|
||||
{
|
||||
error: { name: error.name, message: error.message },
|
||||
}
|
||||
);
|
||||
} else {
|
||||
logger.error(
|
||||
"[@trigger.dev/stripe] Unknown Error while validating webhook signature"
|
||||
);
|
||||
}
|
||||
|
||||
return { events: [] };
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
events: [],
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
import type {
|
||||
StripeSDK,
|
||||
CreateChargeParams,
|
||||
CreateChargeResponse,
|
||||
CreateCustomerResponse,
|
||||
CreateCustomerParams,
|
||||
UpdateCustomerParams,
|
||||
UpdateCustomerResponse,
|
||||
RetrieveSubscriptionParams,
|
||||
RetrieveSubscriptionResponse,
|
||||
CreateCheckoutSessionParams,
|
||||
CreateCheckoutSessionResponse,
|
||||
CreateWebhookParams,
|
||||
CreateWebhookResponse,
|
||||
UpdateWebhookParams,
|
||||
UpdateWebhookResponse,
|
||||
ListWebhooksResponse,
|
||||
ListWebhooksParams,
|
||||
} from "./types";
|
||||
import { AuthenticatedTask } from "@trigger.dev/sdk";
|
||||
import { Stripe } from "stripe";
|
||||
import { omit } from "./utils";
|
||||
|
||||
export const createCharge: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
CreateChargeParams,
|
||||
CreateChargeResponse
|
||||
> = {
|
||||
onError: (error) => {
|
||||
if (error instanceof Stripe.errors.StripeError) {
|
||||
console.log("Stripe error", error);
|
||||
}
|
||||
|
||||
throw error;
|
||||
},
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.charges.create(params, {
|
||||
idempotencyKey: task.idempotencyKey,
|
||||
stripeAccount: params.stripeAccount,
|
||||
});
|
||||
|
||||
task.outputProperties = [
|
||||
{
|
||||
label: "Charge ID",
|
||||
text: response.id,
|
||||
},
|
||||
...(response.lastResponse.requestId
|
||||
? [
|
||||
{
|
||||
label: "Request ID",
|
||||
text: response.lastResponse.requestId,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Create Charge",
|
||||
params,
|
||||
icon: "stripe",
|
||||
properties: [
|
||||
{
|
||||
label: "Amount",
|
||||
text: `${params.amount}`,
|
||||
},
|
||||
...(params.currency
|
||||
? [
|
||||
{
|
||||
label: "Currency",
|
||||
text: params.currency,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(params.stripeAccount
|
||||
? [
|
||||
{
|
||||
label: "Stripe Account",
|
||||
text: params.stripeAccount,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const createCustomer: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
CreateCustomerParams,
|
||||
CreateCustomerResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.customers.create(params, {
|
||||
idempotencyKey: task.idempotencyKey,
|
||||
stripeAccount: params.stripeAccount,
|
||||
});
|
||||
|
||||
task.outputProperties = [
|
||||
{
|
||||
label: "Customer ID",
|
||||
text: response.id,
|
||||
},
|
||||
...(response.lastResponse.requestId
|
||||
? [
|
||||
{
|
||||
label: "Request ID",
|
||||
text: response.lastResponse.requestId,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Create Customer",
|
||||
params,
|
||||
icon: "stripe",
|
||||
properties: [
|
||||
...(params.stripeAccount
|
||||
? [
|
||||
{
|
||||
label: "Stripe Account",
|
||||
text: params.stripeAccount,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const updateCustomer: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
UpdateCustomerParams,
|
||||
UpdateCustomerResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.customers.update(
|
||||
params.id,
|
||||
omit(params, "id"),
|
||||
{
|
||||
idempotencyKey: task.idempotencyKey,
|
||||
stripeAccount: params.stripeAccount,
|
||||
}
|
||||
);
|
||||
|
||||
task.outputProperties = [
|
||||
...(response.lastResponse.requestId
|
||||
? [
|
||||
{
|
||||
label: "Request ID",
|
||||
text: response.lastResponse.requestId,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Update Customer",
|
||||
params,
|
||||
icon: "stripe",
|
||||
properties: [
|
||||
{
|
||||
label: "Customer ID",
|
||||
text: params.id,
|
||||
},
|
||||
...(params.stripeAccount
|
||||
? [
|
||||
{
|
||||
label: "Stripe Account",
|
||||
text: params.stripeAccount,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const retrieveSubscription: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
RetrieveSubscriptionParams,
|
||||
RetrieveSubscriptionResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.subscriptions.retrieve(
|
||||
params.id,
|
||||
omit(params, "id"),
|
||||
{
|
||||
stripeAccount: params.stripeAccount,
|
||||
}
|
||||
);
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Retrieve Subscription",
|
||||
params,
|
||||
icon: "stripe",
|
||||
properties: [
|
||||
{
|
||||
label: "Subscription ID",
|
||||
text: params.id,
|
||||
},
|
||||
...(params.stripeAccount
|
||||
? [
|
||||
{
|
||||
label: "Stripe Account",
|
||||
text: params.stripeAccount,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const createCheckoutSession: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
CreateCheckoutSessionParams,
|
||||
CreateCheckoutSessionResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.checkout.sessions.create(params, {
|
||||
idempotencyKey: task.idempotencyKey,
|
||||
stripeAccount: params.stripeAccount,
|
||||
});
|
||||
|
||||
task.outputProperties = [
|
||||
{
|
||||
label: "Session ID",
|
||||
text: response.id,
|
||||
},
|
||||
...(response.lastResponse.requestId
|
||||
? [
|
||||
{
|
||||
label: "Request ID",
|
||||
text: response.lastResponse.requestId,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Create Checkout Session",
|
||||
params,
|
||||
icon: "stripe",
|
||||
properties: [
|
||||
...(params.stripeAccount
|
||||
? [
|
||||
{
|
||||
label: "Stripe Account",
|
||||
text: params.stripeAccount,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const createWebhook: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
CreateWebhookParams,
|
||||
CreateWebhookResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.webhookEndpoints.create(params, {
|
||||
idempotencyKey: task.idempotencyKey,
|
||||
});
|
||||
|
||||
task.outputProperties = [
|
||||
{
|
||||
label: "Webhook ID",
|
||||
text: response.id,
|
||||
},
|
||||
...(response.lastResponse.requestId
|
||||
? [
|
||||
{
|
||||
label: "Request ID",
|
||||
text: response.lastResponse.requestId,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Create Webhook",
|
||||
params,
|
||||
icon: "stripe",
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const updateWebhook: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
UpdateWebhookParams,
|
||||
UpdateWebhookResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.webhookEndpoints.update(
|
||||
params.id,
|
||||
omit(params, "id"),
|
||||
{
|
||||
idempotencyKey: task.idempotencyKey,
|
||||
}
|
||||
);
|
||||
|
||||
task.outputProperties = [
|
||||
...(response.lastResponse.requestId
|
||||
? [
|
||||
{
|
||||
label: "Request ID",
|
||||
text: response.lastResponse.requestId,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "Update Webhook",
|
||||
params,
|
||||
icon: "stripe",
|
||||
properties: [
|
||||
{
|
||||
label: "Webhook ID",
|
||||
text: params.id,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const listWebhooks: AuthenticatedTask<
|
||||
StripeSDK,
|
||||
ListWebhooksParams,
|
||||
ListWebhooksResponse
|
||||
> = {
|
||||
run: async (params, client, task) => {
|
||||
const response = await client.webhookEndpoints.list(params);
|
||||
|
||||
return response;
|
||||
},
|
||||
init: (params) => {
|
||||
return {
|
||||
name: "List Webhooks",
|
||||
params,
|
||||
icon: "stripe",
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
/// <reference types="stripe-event-types" />
|
||||
import { Stripe } from "stripe";
|
||||
import { Prettify } from "@trigger.dev/integration-kit";
|
||||
|
||||
export type StripeSDK = Stripe;
|
||||
|
||||
export type StripeIntegrationOptions = {
|
||||
id: string;
|
||||
apiKey: string;
|
||||
|
||||
/**
|
||||
* An account id on whose behalf you wish to make every request.
|
||||
*/
|
||||
stripeAccount?: string;
|
||||
};
|
||||
|
||||
type WithStripeConnectOptions<T> = T & {
|
||||
stripeAccount?: string;
|
||||
};
|
||||
|
||||
export type CreateChargeParams = Prettify<
|
||||
WithStripeConnectOptions<Stripe.ChargeCreateParams>
|
||||
>;
|
||||
export type CreateChargeResponse = Prettify<Stripe.Response<Stripe.Charge>>;
|
||||
|
||||
export type CreateCustomerParams = Prettify<
|
||||
WithStripeConnectOptions<Stripe.CustomerCreateParams>
|
||||
>;
|
||||
|
||||
export type CreateCustomerResponse = Prettify<Stripe.Response<Stripe.Customer>>;
|
||||
|
||||
export type UpdateCustomerParams = Prettify<
|
||||
WithStripeConnectOptions<Stripe.CustomerUpdateParams & { id: string }>
|
||||
>;
|
||||
|
||||
export type UpdateCustomerResponse = Prettify<Stripe.Response<Stripe.Customer>>;
|
||||
|
||||
export type RetrieveSubscriptionParams = Prettify<
|
||||
WithStripeConnectOptions<Stripe.SubscriptionRetrieveParams & { id: string }>
|
||||
>;
|
||||
|
||||
export type RetrieveSubscriptionResponse = Prettify<
|
||||
Stripe.Response<Stripe.Subscription>
|
||||
>;
|
||||
|
||||
export type CreateCheckoutSessionParams = Prettify<
|
||||
WithStripeConnectOptions<Stripe.Checkout.SessionCreateParams>
|
||||
>;
|
||||
|
||||
export type CreateCheckoutSessionResponse = Prettify<
|
||||
Stripe.Response<Stripe.Checkout.Session>
|
||||
>;
|
||||
|
||||
export type CreateWebhookParams = Prettify<Stripe.WebhookEndpointCreateParams>;
|
||||
|
||||
export type CreateWebhookResponse = Prettify<Stripe.WebhookEndpoint>;
|
||||
|
||||
export type UpdateWebhookParams = Prettify<
|
||||
Stripe.WebhookEndpointUpdateParams & { id: string }
|
||||
>;
|
||||
|
||||
export type UpdateWebhookResponse = Prettify<Stripe.WebhookEndpoint>;
|
||||
|
||||
export type WebhookEvents = Exclude<
|
||||
Stripe.WebhookEndpointUpdateParams.EnabledEvent,
|
||||
"*"
|
||||
>;
|
||||
|
||||
export type ListWebhooksParams = Prettify<Stripe.WebhookEndpointListParams>;
|
||||
|
||||
export type ListWebhooksResponse = Prettify<
|
||||
Stripe.Response<Stripe.ApiList<Stripe.WebhookEndpoint>>
|
||||
>;
|
||||
|
||||
type ExtractWebhookPayload<T extends Stripe.DiscriminatedEvent> = Prettify<
|
||||
T["data"]["object"]
|
||||
>;
|
||||
|
||||
export type OnPriceEvent =
|
||||
ExtractWebhookPayload<Stripe.DiscriminatedEvent.PriceEvent>;
|
||||
|
||||
export type OnProductEvent =
|
||||
ExtractWebhookPayload<Stripe.DiscriminatedEvent.ProductEvent>;
|
||||
|
||||
export type OnCheckoutSession =
|
||||
ExtractWebhookPayload<Stripe.DiscriminatedEvent.CheckoutSessionEvent>;
|
||||
|
||||
export type OnCustomerSubscription =
|
||||
ExtractWebhookPayload<Stripe.DiscriminatedEvent.CustomerSubscriptionEvent>;
|
||||
@@ -0,0 +1,5 @@
|
||||
export function omit<T, K extends keyof T>(obj: T, ...keys: K[]): Omit<T, K> {
|
||||
const result = { ...obj };
|
||||
keys.forEach((key) => delete result[key]);
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"composite": false,
|
||||
"declaration": false,
|
||||
"declarationMap": false,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"inlineSources": false,
|
||||
"isolatedModules": true,
|
||||
"moduleResolution": "node16",
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"preserveWatchOutput": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"sourceMap": true,
|
||||
"resolveJsonModule": true,
|
||||
"lib": [
|
||||
"es2019"
|
||||
],
|
||||
"module": "commonjs",
|
||||
"target": "es2021"
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts",
|
||||
"tsup.config.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
import { defineConfig } from "tsup";
|
||||
|
||||
export default defineConfig([
|
||||
{
|
||||
name: "main",
|
||||
entry: ["./src/index.ts"],
|
||||
outDir: "./dist",
|
||||
platform: "node",
|
||||
format: ["cjs"],
|
||||
legacyOutput: true,
|
||||
sourcemap: true,
|
||||
clean: true,
|
||||
bundle: true,
|
||||
splitting: false,
|
||||
dts: true,
|
||||
treeshake: {
|
||||
preset: "smallest",
|
||||
},
|
||||
esbuildPlugins: [],
|
||||
external: ["http", "https", "util", "events", "tty", "os", "timers"],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -2,35 +2,29 @@
|
||||
|
||||
import { EventFilter } from "./schemas";
|
||||
|
||||
// This function should take two EventFilters and return a new EventFilter that is the result of merging the two.
|
||||
export function deepMergeFilters(
|
||||
filter: EventFilter,
|
||||
other: EventFilter
|
||||
): EventFilter {
|
||||
const result: EventFilter = { ...filter };
|
||||
// This function should take any number of EventFilters and return a new EventFilter that is the result of merging of them.
|
||||
export function deepMergeFilters(...filters: EventFilter[]): EventFilter {
|
||||
const result: EventFilter = {};
|
||||
|
||||
for (const key in other) {
|
||||
if (other.hasOwnProperty(key)) {
|
||||
const otherValue = other[key];
|
||||
|
||||
if (
|
||||
typeof otherValue === "object" &&
|
||||
!Array.isArray(otherValue) &&
|
||||
otherValue !== null
|
||||
) {
|
||||
for (const filter of filters) {
|
||||
for (const key in filter) {
|
||||
if (filter.hasOwnProperty(key)) {
|
||||
const filterValue = filter[key];
|
||||
const existingValue = result[key];
|
||||
|
||||
if (
|
||||
filterValue &&
|
||||
existingValue &&
|
||||
typeof existingValue === "object" &&
|
||||
typeof filterValue === "object" &&
|
||||
!Array.isArray(filterValue)
|
||||
!Array.isArray(existingValue) &&
|
||||
!Array.isArray(filterValue) &&
|
||||
existingValue !== null &&
|
||||
filterValue !== null
|
||||
) {
|
||||
result[key] = deepMergeFilters(filterValue, otherValue);
|
||||
result[key] = deepMergeFilters(existingValue, filterValue);
|
||||
} else {
|
||||
result[key] = { ...other[key] };
|
||||
result[key] = filterValue;
|
||||
}
|
||||
} else {
|
||||
result[key] = other[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,24 +591,32 @@ export class IO {
|
||||
}
|
||||
|
||||
if (onError) {
|
||||
const onErrorResult = onError(error, task, this);
|
||||
try {
|
||||
const onErrorResult = onError(error, task, this);
|
||||
|
||||
if (onErrorResult) {
|
||||
if (onErrorResult instanceof Error) {
|
||||
error = onErrorResult;
|
||||
} else {
|
||||
const parsedError = ErrorWithStackSchema.safeParse(
|
||||
onErrorResult.error
|
||||
);
|
||||
if (onErrorResult) {
|
||||
if (onErrorResult instanceof Error) {
|
||||
error = onErrorResult;
|
||||
} else {
|
||||
const parsedError = ErrorWithStackSchema.safeParse(
|
||||
onErrorResult.error
|
||||
);
|
||||
|
||||
throw new RetryWithTaskError(
|
||||
parsedError.success
|
||||
? parsedError.data
|
||||
: { message: "Unknown error" },
|
||||
task,
|
||||
onErrorResult.retryAt
|
||||
);
|
||||
throw new RetryWithTaskError(
|
||||
parsedError.success
|
||||
? parsedError.data
|
||||
: { message: "Unknown error" },
|
||||
task,
|
||||
onErrorResult.retryAt
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (innerError) {
|
||||
if (isTriggerError(innerError)) {
|
||||
throw innerError;
|
||||
}
|
||||
|
||||
error = innerError;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -211,7 +211,7 @@ export class ExternalSource<
|
||||
export type ExternalSourceParams<
|
||||
TExternalSource extends ExternalSource<any, any, any>
|
||||
> = TExternalSource extends ExternalSource<any, infer TParams, any>
|
||||
? TParams
|
||||
? TParams & { filter?: EventFilter }
|
||||
: never;
|
||||
|
||||
export type ExternalSourceTriggerOptions<
|
||||
@@ -247,7 +247,8 @@ export class ExternalSourceTrigger<
|
||||
event: this.event.name,
|
||||
payload: deepMergeFilters(
|
||||
this.options.source.filter(this.options.params),
|
||||
this.event.filter ?? {}
|
||||
this.event.filter ?? {},
|
||||
this.options.params.filter ?? {}
|
||||
),
|
||||
source: this.event.source,
|
||||
},
|
||||
|
||||
Generated
+40
@@ -415,6 +415,7 @@ importers:
|
||||
'@trigger.dev/resend': workspace:*
|
||||
'@trigger.dev/sdk': workspace:*
|
||||
'@trigger.dev/slack': workspace:*
|
||||
'@trigger.dev/stripe': workspace:*
|
||||
'@trigger.dev/supabase': workspace:*
|
||||
'@trigger.dev/typeform': workspace:*
|
||||
'@types/node': 18.15.13
|
||||
@@ -441,6 +442,7 @@ importers:
|
||||
'@trigger.dev/resend': link:../../integrations/resend
|
||||
'@trigger.dev/sdk': link:../../packages/trigger-sdk
|
||||
'@trigger.dev/slack': link:../../integrations/slack
|
||||
'@trigger.dev/stripe': link:../../integrations/stripe
|
||||
'@trigger.dev/supabase': link:../../integrations/supabase
|
||||
'@trigger.dev/typeform': link:../../integrations/typeform
|
||||
'@types/node': 18.15.13
|
||||
@@ -570,6 +572,29 @@ importers:
|
||||
rimraf: 3.0.2
|
||||
tsup: 6.6.3
|
||||
|
||||
integrations/stripe:
|
||||
specifiers:
|
||||
'@trigger.dev/integration-kit': workspace:^2.0.0-next.5
|
||||
'@trigger.dev/sdk': workspace:^2.0.0-next.19
|
||||
'@types/node': 16.x
|
||||
rimraf: ^3.0.2
|
||||
stripe: ^12.14.0
|
||||
stripe-event-types: ^2.4.0
|
||||
tsup: 7.1.x
|
||||
typescript: 4.9.4
|
||||
zod: 3.21.4
|
||||
dependencies:
|
||||
'@trigger.dev/integration-kit': link:../../packages/integration-kit
|
||||
'@trigger.dev/sdk': link:../../packages/trigger-sdk
|
||||
stripe: 12.14.0
|
||||
zod: 3.21.4
|
||||
devDependencies:
|
||||
'@types/node': 16.18.11
|
||||
rimraf: 3.0.2
|
||||
stripe-event-types: 2.4.0_stripe@12.14.0
|
||||
tsup: 7.1.0_typescript@4.9.4
|
||||
typescript: 4.9.4
|
||||
|
||||
integrations/supabase:
|
||||
specifiers:
|
||||
'@supabase/supabase-js': ^2.26.0
|
||||
@@ -22804,6 +22829,21 @@ packages:
|
||||
acorn: 8.10.0
|
||||
dev: true
|
||||
|
||||
/stripe-event-types/2.4.0_stripe@12.14.0:
|
||||
resolution: {integrity: sha512-5ORZMW/WKjc31nsGMCUECOS+xVjtHhAFJJ8833ft3471hIjQrMbLMPBEb5AcJM8mKRRULpKmCVMDU0lLYrxERQ==}
|
||||
peerDependencies:
|
||||
stripe: '>=10.0.0'
|
||||
dependencies:
|
||||
stripe: 12.14.0
|
||||
dev: true
|
||||
|
||||
/stripe/12.14.0:
|
||||
resolution: {integrity: sha512-WrDlYH1p5jliY7uzSU5nLDY7OCIeRe6FkC0hhScpTGwMthP/Muk38WXGeggjDHKeXAGCs43jUheZ7Ud/NEAJdg==}
|
||||
engines: {node: '>=12.*'}
|
||||
dependencies:
|
||||
'@types/node': 20.4.2
|
||||
qs: 6.11.0
|
||||
|
||||
/striptags/2.2.1:
|
||||
resolution: {integrity: sha512-vZTvmFP0IYu/zn8MXV6PrLb6VKbd9WGSEnlm4D5RNXS/+zYYlHrSfJgoBw1w56D6RJCr515er3BittRGQqihLA==}
|
||||
dev: false
|
||||
|
||||
Reference in New Issue
Block a user