1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125import type { NextFunction, Response } from 'express'
import express from 'express'
import type { Config } from 'payload/config'
import type { PayloadRequest } from 'payload/types'
import { extendWebpackConfig } from './extendWebpackConfig'
import { getFields } from './fields/getFields'
import { createNewInStripe } from './hooks/createNewInStripe'
import { deleteFromStripe } from './hooks/deleteFromStripe'
import { syncExistingWithStripe } from './hooks/syncExistingWithStripe'
import { stripeREST } from './routes/rest'
import { stripeWebhooks } from './routes/webhooks'
import type { SanitizedStripeConfig, StripeConfig } from './types'
export const stripePlugin =
(incomingStripeConfig: StripeConfig) =>
(config: Config): Config => {
const { collections } = config
// set config defaults here
const stripeConfig: SanitizedStripeConfig = {
...incomingStripeConfig,
// TODO: in the next major version, default this to `false`
rest: incomingStripeConfig?.rest ?? true,
sync: incomingStripeConfig?.sync || [],
}
// NOTE: env variables are never passed to the client, but we need to know if `stripeSecretKey` is a test key
// unfortunately we must set the 'isTestKey' property on the config instead of using the following code:
// const isTestKey = stripeConfig.stripeSecretKey?.startsWith('sk_test_');
return {
...config,
admin: {
...config.admin,
webpack: extendWebpackConfig(config),
},
endpoints: [
...(config?.endpoints || []),
{
path: '/stripe/webhooks',
method: 'post',
root: true,
handler: [
express.raw({ type: 'application/json' }),
(req, res, next) => {
stripeWebhooks({
req,
res,
next,
config,
stripeConfig,
})
},
],
},
...(incomingStripeConfig?.rest
? [
{
path: '/stripe/rest',
method: 'post',
handler: (req: PayloadRequest, res: Response, next: NextFunction) => {
stripeREST({
req,
res,
next,
stripeConfig,
})
},
},
]
: []),
],
collections: collections?.map(collection => {
const { hooks: existingHooks } = collection
const syncConfig = stripeConfig.sync?.find(sync => sync.collection === collection.slug)
if (syncConfig) {
const fields = getFields({
collection,
stripeConfig,
syncConfig,
})
return {
...collection,
hooks: {
...collection.hooks,
beforeValidate: [
...(existingHooks?.beforeValidate || []),
async args =>
createNewInStripe({
...args,
collection,
stripeConfig,
}),
],
beforeChange: [
...(existingHooks?.beforeChange || []),
async args =>
syncExistingWithStripe({
...args,
collection,
stripeConfig,
}),
],
afterDelete: [
...(existingHooks?.afterDelete || []),
async args =>
deleteFromStripe({
...args,
collection,
stripeConfig,
}),
],
},
fields,
}
}
return collection
}),
}
}