@flink-app/stripe-plugin 0.12.1-alpha.4 → 0.12.1-alpha.44
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/.flink/generatedHandlers.ts +1 -1
- package/.flink/generatedJobs.ts +1 -1
- package/.flink/generatedRepos.ts +1 -1
- package/.flink/schemas/schemas.ts +1 -1
- package/.flink/start.ts +2 -1
- package/dist/.flink/generatedHandlers.js +1 -1
- package/dist/.flink/generatedJobs.js +1 -1
- package/dist/.flink/generatedRepos.js +1 -1
- package/dist/.flink/schemas/schemas.js +1 -1
- package/dist/.flink/start.d.ts +2 -0
- package/dist/.flink/start.js +2 -1
- package/package.json +4 -4
- package/readme.md +365 -26
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import { autoRegisteredHandlers, HttpMethod } from "@flink-app/flink";
|
|
3
3
|
import * as HandlebarsTemplateHandler_0 from "../src/handlers/HandlebarsTemplateHandler";
|
|
4
4
|
|
package/.flink/generatedJobs.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import { autoRegisteredJobs } from "@flink-app/flink";
|
|
3
3
|
export const jobs = [];
|
|
4
4
|
autoRegisteredJobs.push(...jobs);
|
package/.flink/generatedRepos.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import { autoRegisteredRepos } from "@flink-app/flink";
|
|
3
3
|
export const repos = [];
|
|
4
4
|
autoRegisteredRepos.push(...repos);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
package/.flink/start.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
// Generated
|
|
1
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
2
2
|
import "./generatedHandlers";
|
|
3
3
|
import "./generatedRepos";
|
|
4
4
|
import "./generatedJobs";
|
|
5
5
|
import "../src/index";
|
|
6
|
+
export default {}; // Export an empty object to make it a module
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handlers = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
5
5
|
var flink_1 = require("@flink-app/flink");
|
|
6
6
|
exports.handlers = [];
|
|
7
7
|
flink_1.autoRegisteredHandlers.push.apply(flink_1.autoRegisteredHandlers, exports.handlers);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.jobs = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
5
5
|
var flink_1 = require("@flink-app/flink");
|
|
6
6
|
exports.jobs = [];
|
|
7
7
|
flink_1.autoRegisteredJobs.push.apply(flink_1.autoRegisteredJobs, exports.jobs);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.repos = void 0;
|
|
4
|
-
// Generated
|
|
4
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
5
5
|
var flink_1 = require("@flink-app/flink");
|
|
6
6
|
exports.repos = [];
|
|
7
7
|
flink_1.autoRegisteredRepos.push.apply(flink_1.autoRegisteredRepos, exports.repos);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Generated
|
|
2
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
package/dist/.flink/start.d.ts
CHANGED
package/dist/.flink/start.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
// Generated
|
|
3
|
+
// Generated Sun Nov 23 2025 14:20:59 GMT+0100 (Central European Standard Time)
|
|
4
4
|
require("./generatedHandlers");
|
|
5
5
|
require("./generatedRepos");
|
|
6
6
|
require("./generatedJobs");
|
|
7
7
|
require("../src/index");
|
|
8
|
+
exports.default = {}; // Export an empty object to make it a module
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flink-app/stripe-plugin",
|
|
3
|
-
"version": "0.12.1-alpha.
|
|
3
|
+
"version": "0.12.1-alpha.44",
|
|
4
4
|
"description": "Flink plugin to work with stripe payments",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\"",
|
|
7
7
|
"build": "flink build",
|
|
8
|
-
"
|
|
8
|
+
"prepare": "npm run build",
|
|
9
9
|
"watch": "nodemon --exec \"flink build\""
|
|
10
10
|
},
|
|
11
11
|
"author": "johan@frost.se",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"stripe": "^8.186.1"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@flink-app/flink": "^0.12.1-alpha.
|
|
27
|
+
"@flink-app/flink": "^0.12.1-alpha.44",
|
|
28
28
|
"@types/bcrypt": "^5.0.0",
|
|
29
29
|
"@types/express": "4.17.11",
|
|
30
30
|
"@types/express-fileupload": "^1.1.7",
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"ts-node": "^9.1.1",
|
|
34
34
|
"typescript": "5.4.5"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "4243e3b3cd6d4e1ca001a61baa8436bf2bbe4113"
|
|
37
37
|
}
|
package/readme.md
CHANGED
|
@@ -1,51 +1,390 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @flink-app/stripe-plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A comprehensive Flink plugin for integrating Stripe payment processing, including customer management, payment intents, card setup, and Stripe Connect functionality. The plugin provides both API methods and hosted UI pages for payment flows.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- Customer creation and management
|
|
8
|
+
- Payment intent creation and confirmation
|
|
9
|
+
- Card setup with hosted UI
|
|
10
|
+
- Payment capture for authorized payments
|
|
11
|
+
- Stripe Connect integration
|
|
12
|
+
- Pre-built, customizable payment UI templates
|
|
13
|
+
- JWT-based secure token system
|
|
14
|
+
- MongoDB-backed session management
|
|
15
|
+
- Webhook callback support
|
|
16
|
+
- Full TypeScript support
|
|
8
17
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
Install plugin to your flink app project:
|
|
18
|
+
## Installation
|
|
12
19
|
|
|
13
|
-
```
|
|
14
|
-
npm
|
|
20
|
+
```bash
|
|
21
|
+
npm install @flink-app/stripe-plugin
|
|
15
22
|
```
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
## Usage
|
|
18
25
|
|
|
19
|
-
|
|
20
|
-
import { managementApiPlugin } from "@flink-app/management-api-plugin";
|
|
26
|
+
### Basic Setup
|
|
21
27
|
|
|
28
|
+
```typescript
|
|
29
|
+
import { FlinkApp } from "@flink-app/flink";
|
|
30
|
+
import { stripePlugin } from "@flink-app/stripe-plugin";
|
|
22
31
|
|
|
23
32
|
function start() {
|
|
24
33
|
new FlinkApp<AppContext>({
|
|
25
34
|
name: "My app",
|
|
26
35
|
plugins: [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
36
|
+
stripePlugin({
|
|
37
|
+
stripeSecreteKey: process.env.STRIPE_SECRET_KEY!,
|
|
38
|
+
stripePublishableKey: process.env.STRIPE_PUBLISHABLE_KEY!,
|
|
39
|
+
JTW_TOKEN: process.env.JWT_SECRET!,
|
|
40
|
+
baseUrl: "/stripe", // optional, defaults to /stripe
|
|
41
|
+
redirectUrl: "https://yourapp.com/success", // Where to redirect after successful operations
|
|
42
|
+
logo: "https://yourapp.com/logo.png", // Optional logo for payment pages
|
|
43
|
+
stripeConnectClientID: process.env.STRIPE_CONNECT_CLIENT_ID, // For Stripe Connect
|
|
44
|
+
paymentCallback: (paymentIntentId, status) => {
|
|
45
|
+
// Handle successful payments
|
|
46
|
+
console.log(`Payment ${paymentIntentId} status: ${status}`);
|
|
47
|
+
},
|
|
48
|
+
stripeConnectCallback: (userId, stripeAccountId) => {
|
|
49
|
+
// Handle Stripe Connect account linking
|
|
50
|
+
console.log(`User ${userId} connected to Stripe account ${stripeAccountId}`);
|
|
51
|
+
},
|
|
52
|
+
phrases: {
|
|
53
|
+
setupDescription: "Add your payment card",
|
|
54
|
+
setupButtonText: "Save Card",
|
|
55
|
+
setupDoneMessage: "Your card has been saved successfully",
|
|
56
|
+
paymentSelectCardPayButtonText: "Pay",
|
|
57
|
+
paymentSelectCardChangeCardButtonText: "Change Card",
|
|
58
|
+
paymentEnterCardPayButtonText: "Pay",
|
|
59
|
+
connectDoneMessage: "Your account has been connected to Stripe",
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
33
62
|
],
|
|
34
63
|
}).start();
|
|
35
64
|
}
|
|
36
65
|
```
|
|
37
66
|
|
|
38
|
-
|
|
67
|
+
### Add Plugin Context to Your Application
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { stripePluginContext } from "@flink-app/stripe-plugin";
|
|
71
|
+
|
|
72
|
+
export interface AppContext extends FlinkContext<stripePluginContext> {
|
|
73
|
+
repos: {
|
|
74
|
+
// your repos
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Configuration Options
|
|
80
|
+
|
|
81
|
+
- `stripeSecreteKey` (required): Your Stripe secret API key
|
|
82
|
+
- `stripePublishableKey` (required): Your Stripe publishable API key
|
|
83
|
+
- `JTW_TOKEN` (required): Secret for JWT token generation
|
|
84
|
+
- `baseUrl` (optional): Base URL for plugin routes (defaults to `/stripe`)
|
|
85
|
+
- `redirectUrl` (optional): URL to redirect users after successful operations
|
|
86
|
+
- `logo` (optional): Logo URL to display on payment pages
|
|
87
|
+
- `stripeConnectClientID` (optional): Client ID for Stripe Connect integration
|
|
88
|
+
- `paymentCallback` (optional): Function called when payment succeeds
|
|
89
|
+
- `stripeConnectCallback` (optional): Function called when Stripe Connect linking succeeds
|
|
90
|
+
- `phrases` (optional): Customize UI text for different languages
|
|
91
|
+
- `templates` (optional): Override default Handlebars templates for payment pages
|
|
92
|
+
|
|
93
|
+
## API Usage
|
|
94
|
+
|
|
95
|
+
### Customer Management
|
|
96
|
+
|
|
97
|
+
#### Create Customer
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
const customerId = await ctx.plugins.stripePlugin.stripeAPI.customer.create({
|
|
101
|
+
email: "customer@example.com",
|
|
102
|
+
name: "John Doe",
|
|
103
|
+
metadata: {
|
|
104
|
+
userId: "user123",
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### Check if Customer Has Payment Method
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const hasCard = await ctx.plugins.stripePlugin.stripeAPI.customer.hasPaymentMethod({
|
|
113
|
+
stripeCustomerId: "cus_xxxxx",
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Setup Card Registration
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const { token, redirectUrl } = await ctx.plugins.stripePlugin.stripeAPI.customer.setupCard({
|
|
121
|
+
stripeCustomerId: "cus_xxxxx",
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Redirect user to redirectUrl to complete card setup
|
|
125
|
+
// Example: https://yourapp.com/stripe/customer/setup-card/JWT_TOKEN
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Connect to Stripe Connect
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
const connectUrl = await ctx.plugins.stripePlugin.stripeAPI.customer.connectToStripeConnect({
|
|
132
|
+
userId: "user123",
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// Redirect user to connectUrl to link their Stripe Connect account
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Payment Processing
|
|
139
|
+
|
|
140
|
+
#### Create Payment Intent
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
const payment = await ctx.plugins.stripePlugin.stripeAPI.payment.create({
|
|
144
|
+
amount: 5000, // Amount in cents ($50.00)
|
|
145
|
+
currency: "usd",
|
|
146
|
+
customer: "cus_xxxxx",
|
|
147
|
+
description: "Order #12345",
|
|
148
|
+
capture_method: "automatic", // or "manual" for authorization only
|
|
149
|
+
metadata: {
|
|
150
|
+
orderId: "order_12345",
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// payment.token - JWT token for payment confirmation
|
|
155
|
+
// payment.paymentUrl - URL to redirect user for payment
|
|
156
|
+
// payment.paymentIntentId - Stripe payment intent ID
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### Confirm Payment
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const result = await ctx.plugins.stripePlugin.stripeAPI.payment.confirm({
|
|
163
|
+
paymentIntentId: "pi_xxxxx",
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// result.confirmed - true if payment was confirmed
|
|
167
|
+
// result.captured - true if payment was captured (only for automatic capture)
|
|
168
|
+
// result.token - JWT token if additional action needed
|
|
169
|
+
// result.redirectUrl - URL to redirect user if additional action needed
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
#### Create and Confirm Payment (Combined)
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
const result = await ctx.plugins.stripePlugin.stripeAPI.payment.createAndConfirm({
|
|
176
|
+
amount: 5000,
|
|
177
|
+
currency: "usd",
|
|
178
|
+
customer: "cus_xxxxx",
|
|
179
|
+
description: "Order #12345",
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
#### Capture Authorized Payment
|
|
184
|
+
|
|
185
|
+
For payments created with `capture_method: "manual"`:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
const captured = await ctx.plugins.stripePlugin.stripeAPI.payment.capture({
|
|
189
|
+
paymentIntentId: "pi_xxxxx",
|
|
190
|
+
amount: 5000, // Optional: partial capture amount
|
|
191
|
+
});
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Hosted Payment Flow
|
|
195
|
+
|
|
196
|
+
The plugin provides pre-built, secure payment pages:
|
|
197
|
+
|
|
198
|
+
### Card Setup Flow
|
|
199
|
+
|
|
200
|
+
1. Generate setup URL:
|
|
201
|
+
```typescript
|
|
202
|
+
const { redirectUrl } = await ctx.plugins.stripePlugin.stripeAPI.customer.setupCard({
|
|
203
|
+
stripeCustomerId: "cus_xxxxx",
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
2. Redirect user to `redirectUrl`
|
|
208
|
+
3. User enters card details on hosted page
|
|
209
|
+
4. User is redirected to your `redirectUrl` upon completion
|
|
210
|
+
|
|
211
|
+
### Payment Flow
|
|
212
|
+
|
|
213
|
+
1. Create payment intent:
|
|
214
|
+
```typescript
|
|
215
|
+
const { paymentUrl } = await ctx.plugins.stripePlugin.stripeAPI.payment.create({
|
|
216
|
+
amount: 5000,
|
|
217
|
+
currency: "usd",
|
|
218
|
+
customer: "cus_xxxxx",
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
2. Redirect user to `paymentUrl`
|
|
223
|
+
3. Plugin automatically detects if customer has saved cards
|
|
224
|
+
4. Shows appropriate UI (select saved card or enter new card)
|
|
225
|
+
5. Processes payment and redirects to your `redirectUrl`
|
|
226
|
+
|
|
227
|
+
## API Routes
|
|
228
|
+
|
|
229
|
+
The plugin automatically registers these routes:
|
|
230
|
+
|
|
231
|
+
- `GET /stripe/customer/setup-card/:token` - Card setup page
|
|
232
|
+
- `GET /stripe/customer/setup-card-done` - Success page after card setup
|
|
233
|
+
- `GET /stripe/payment/confirm/:token` - Payment confirmation flow entry
|
|
234
|
+
- `GET /stripe/payment/select-card/:token` - Select from saved cards
|
|
235
|
+
- `GET /stripe/payment/enter-card/:token` - Enter new card details
|
|
236
|
+
- `GET /stripe/error` - Error page
|
|
237
|
+
- `POST /stripe/callback/:event` - Webhook for payment status updates
|
|
238
|
+
- `GET /stripe/connect` - Stripe Connect OAuth callback
|
|
239
|
+
|
|
240
|
+
## Webhooks
|
|
241
|
+
|
|
242
|
+
Configure Stripe webhooks to point to:
|
|
243
|
+
```
|
|
244
|
+
POST https://yourapp.com/stripe/callback/charge.succeeded
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The `paymentCallback` function will be invoked when payments succeed:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
paymentCallback: async (paymentIntentId, status) => {
|
|
251
|
+
// Update order status in database
|
|
252
|
+
await ctx.repos.orderRepo.updateByPaymentId(paymentIntentId, {
|
|
253
|
+
status: status === "succeeded" ? "paid" : "authorized",
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Stripe Connect Integration
|
|
259
|
+
|
|
260
|
+
Enable users to receive payments through Stripe Connect:
|
|
261
|
+
|
|
262
|
+
1. Configure `stripeConnectClientID` in plugin options
|
|
263
|
+
2. Generate connect URL:
|
|
264
|
+
```typescript
|
|
265
|
+
const url = await ctx.plugins.stripePlugin.stripeAPI.customer.connectToStripeConnect({
|
|
266
|
+
userId: "user123",
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
3. Redirect user to `url`
|
|
270
|
+
4. User completes Stripe Connect onboarding
|
|
271
|
+
5. `stripeConnectCallback` is invoked with their Stripe account ID
|
|
272
|
+
|
|
273
|
+
## Customization
|
|
274
|
+
|
|
275
|
+
### Custom Templates
|
|
276
|
+
|
|
277
|
+
Override default payment page templates:
|
|
278
|
+
|
|
279
|
+
```typescript
|
|
280
|
+
stripePlugin({
|
|
281
|
+
// ... other options
|
|
282
|
+
templates: {
|
|
283
|
+
master: customMasterTemplate,
|
|
284
|
+
style: customStyleTemplate,
|
|
285
|
+
setupCard: customSetupCardTemplate,
|
|
286
|
+
setupDone: customSetupDoneTemplate,
|
|
287
|
+
error: customErrorTemplate,
|
|
288
|
+
paySelectCard: customPaySelectCardTemplate,
|
|
289
|
+
payEnterCard: customPayEnterCardTemplate,
|
|
290
|
+
connectDone: customConnectDoneTemplate,
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Templates use Handlebars syntax.
|
|
296
|
+
|
|
297
|
+
### Custom Phrases
|
|
298
|
+
|
|
299
|
+
Customize text for different languages or branding:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
phrases: {
|
|
303
|
+
setupDescription: "Lägg till ditt kort",
|
|
304
|
+
setupButtonText: "Spara",
|
|
305
|
+
setupDoneMessage: "Kortet har sparats",
|
|
306
|
+
paymentSelectCardPayButtonText: "Betala",
|
|
307
|
+
paymentSelectCardChangeCardButtonText: "Byt kort",
|
|
308
|
+
paymentEnterCardPayButtonText: "Betala",
|
|
309
|
+
connectDoneMessage: "Kontot har kopplats",
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Database Requirements
|
|
314
|
+
|
|
315
|
+
This plugin requires MongoDB to be configured for Stripe Connect session management. The plugin automatically creates a `ConnectSessionRepo` repository.
|
|
316
|
+
|
|
317
|
+
## Security Notes
|
|
318
|
+
|
|
319
|
+
- Never expose your `stripeSecreteKey` in client-side code
|
|
320
|
+
- Store all secrets in environment variables
|
|
321
|
+
- Use the JWT token system for secure payment URLs
|
|
322
|
+
- Validate webhook signatures in production (enhance `paymentCallback` with signature verification)
|
|
323
|
+
- Use HTTPS in production for all payment flows
|
|
324
|
+
|
|
325
|
+
## Testing
|
|
39
326
|
|
|
40
|
-
|
|
327
|
+
Use Stripe test mode credentials during development:
|
|
328
|
+
- Test secret key: `sk_test_...`
|
|
329
|
+
- Test publishable key: `pk_test_...`
|
|
330
|
+
- Use Stripe's test card numbers
|
|
41
331
|
|
|
42
|
-
|
|
332
|
+
## Error Handling
|
|
43
333
|
|
|
44
|
-
|
|
334
|
+
All API methods throw errors that should be caught and handled:
|
|
45
335
|
|
|
336
|
+
```typescript
|
|
337
|
+
try {
|
|
338
|
+
const payment = await ctx.plugins.stripePlugin.stripeAPI.payment.create({
|
|
339
|
+
amount: 5000,
|
|
340
|
+
currency: "usd",
|
|
341
|
+
customer: "cus_xxxxx",
|
|
342
|
+
});
|
|
343
|
+
} catch (error) {
|
|
344
|
+
console.error("Payment creation failed:", error);
|
|
345
|
+
// Handle error appropriately
|
|
346
|
+
}
|
|
46
347
|
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
348
|
+
|
|
349
|
+
## TypeScript Support
|
|
350
|
+
|
|
351
|
+
The plugin includes comprehensive TypeScript definitions for all options, methods, and responses.
|
|
352
|
+
|
|
353
|
+
## Complete Example
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
// Create customer
|
|
357
|
+
const customerId = await ctx.plugins.stripePlugin.stripeAPI.customer.create({
|
|
358
|
+
email: user.email,
|
|
359
|
+
name: user.name,
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
// Setup their card
|
|
363
|
+
const { redirectUrl: setupUrl } = await ctx.plugins.stripePlugin.stripeAPI.customer.setupCard({
|
|
364
|
+
stripeCustomerId: customerId,
|
|
365
|
+
});
|
|
366
|
+
// Redirect user to setupUrl
|
|
367
|
+
|
|
368
|
+
// Later, create a payment
|
|
369
|
+
const hasCard = await ctx.plugins.stripePlugin.stripeAPI.customer.hasPaymentMethod({
|
|
370
|
+
stripeCustomerId: customerId,
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
if (hasCard) {
|
|
374
|
+
const result = await ctx.plugins.stripePlugin.stripeAPI.payment.createAndConfirm({
|
|
375
|
+
amount: 5000,
|
|
376
|
+
currency: "usd",
|
|
377
|
+
customer: customerId,
|
|
378
|
+
description: "Premium subscription",
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
if (result.confirmed && result.captured) {
|
|
382
|
+
// Payment successful
|
|
383
|
+
await activatePremiumSubscription(user.id);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
51
386
|
```
|
|
387
|
+
|
|
388
|
+
## License
|
|
389
|
+
|
|
390
|
+
MIT
|