# Stripe
This tutorial shows you how you can use Stripe package with Ts.ED.
The Stripe Node library provides convenient access to the Stripe API from applications written in server-side JavaScript.
For collecting customer and payment information in the browser, use Stripe.js (opens new window).
# Features
Currently, @tsed/stripe
(opens new window) allows you to:
- Configure Stripe,
- Create webhooks,
- Use Stripe API.
# Installation
To begin, install the Stripe module for Ts.ED:
npm install --save @tsed/stripe
npm install --save stripe
2
Then import @tsed/stripe
in your Server:
import {Configuration, PlatformApplication} from "@tsed/common";
import "@tsed/stripe";
import {Stripe} from "stripe";
@Configuration({
stripe: {
apiKey: process.env.STRIPE_SECRET_KEY,
webhooks: {
secret: process.env.STRIPE_WEBHOOK_SECRET
},
// Stripe options
apiVersion: "2019-08-08",
httpProxy: new ProxyAgent(process.env.http_proxy)
}
})
export class Server {
@Inject()
stripe: Stripe;
$afterInit() {
// do something with stripe
// this.stripe.customers
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
TIP
See Stripe options for more details: https://www.npmjs.com/package/stripe
STRIPE_SECRET_KEY
can be retrieved on the Stripe Dashboard here: https://dashboard.stripe.com/test/apikeys
And the STRIPE_WEBHOOK_SECRET
can be retrieved by using the stripe listen
or stripe forward
:
stripe listen
> Ready! You are using Stripe API Version [2020-08-27]. Your webhook signing secret is whsec_*****************************
2
3
::: note
You have to install the stripe-cli
to run stripe listen
. See https://stripe.com/docs/stripe-cli.
:::
# Inject Stripe
import {Injectable} from "@tsed/di";
@Injectable()
class MyStripeService {
@Inject()
stripe: Stripe;
$onInit() {
// do something with stripe
this.stripe.on("request", this.onRequest.bind(this));
}
protected onRequest(request: any) {}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# Webhook signing
Stripe can optionally sign the webhook events it sends to your endpoint, allowing you to validate that they were not sent by a third-party. You can read more about it here (opens new window).
To register a Stripe webhook with Ts.ED, just use the
WebhookEvent
decorator. It'll call for you the stripe.webhooks.constructEvent
with the right parameters:
import {RawBodyParams, HeaderParams, Controller, Context} from "@tsed/common";
import {Stripe} from "stripe";
@Controller("/webhooks")
export class StripWebhookCtrl {
@Inject()
protected stripe: Stripe;
@Post("/callback")
successPaymentHook(@WebhookEvent() event: Stripe.Event, @Context() ctx: Context) {
ctx.logger.info({name: "Webhook success", event});
return {received: true};
}
// with custom webhook options
@Post("/callback2")
successPaymentHook(@WebhookEvent({secret: "....."}) event: Stripe.Event, @Context() ctx: Context) {
ctx.logger.info({name: "Webhook success", event});
return {received: true};
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Testing webhook
You can use stripe.webhooks.generateTestHeaderString to mock webhook events that come from Stripe:
import {Stripe} from "stripe";
import {PlatformTest} from "@tsed/common";
import {StripWebhookCtrl} from "./StripWebhookCtrl";
describe("StripWebhookCtrl", () => {
beforeEach(() =>
PlatformTest.create({
stripe: {
apiKey: "fake_api_key",
webhooks: {
secret: "whsec_test_secret"
},
// Stripe options
apiVersion: "2019-08-08"
}
})
);
afterEach(PlatformTest.reset);
it("should call event", async () => {
const stripe = PlatformTest.get<Stripe>(Stripe);
const payload = {
id: "evt_test_webhook",
object: "event"
};
const payloadString = JSON.stringify(payload, null, 2);
const header = stripe.webhooks.generateTestHeaderString({
payload: payloadString,
secret: "whsec_test_secret"
});
const event = stripe.webhooks.constructEvent(payloadString, header, secret);
const ctx = PlatformTest.createRequestContext();
const ctrl = await PlatformTest.invoke<StripWebhookCtrl>(StripWebhookCtrl);
const result = ctrl.successPaymentHook(event, ctx);
expect(result).toEqual({received: true});
});
});
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
With SuperTest:
import {PlatformTest} from "@tsed/common";
import {PlatformExpress} from "@tsed/platform-express";
import {PlatformTestUtils} from "@tsed/platform-test-utils";
import {expect} from "chai";
import {Stripe} from "stripe";
import SuperTest from "supertest";
import {StripeWebhooksCtrl} from "./StripWebhookCtrl";
import {rootDir, Server} from "../Server";
const utils = PlatformTestUtils.create({
rootDir,
platform: PlatformExpress,
server: Server,
logger: {
level: "info"
}
});
describe("Stripe", () => {
let request: SuperTest.Agent;
beforeEach(
utils.bootstrap({
mount: {
"/rest": [StripWebhookCtrl]
}
})
);
beforeEach(() => {
request = SuperTest.agent(PlatformTest.callback());
});
afterEach(() => PlatformTest.reset());
it("should call the webhook", async () => {
const stripe = PlatformTest.get<Stripe>(Stripe);
const payload = {
id: "evt_test_webhook",
object: "event"
};
const payloadString = JSON.stringify(payload, null, 2);
const signature = stripe.webhooks.generateTestHeaderString({
payload: payloadString,
secret: "whsec_test_secret"
});
const response = await request.post("/rest/webhooks/callback").send(payloadString).set("stripe-signature", signature).expect(200);
expect(response.body).to.deep.eq({
event: payload,
received: true
});
});
});
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
# Known issue
If you have the followings message, it means you have an issue with your STRIPE_WEBHOOK_SECRET.
Error message: No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe?
Please double-check your configuration!
# Author
# Maintainers
Other topics
- Session & cookies
- Passport.js
- Keycloak
- Prisma
- TypeORM
- MikroORM
- Mongoose
- GraphQL
- GraphQL WS
- Apollo
- TypeGraphQL
- GraphQL Nexus
- Socket.io
- Swagger
- AJV
- Multer
- Serve static files
- Templating
- Serverless HTTP
- Seq
- OIDC
- Stripe
- Agenda
- Terminus
- Serverless
- Server-sent events
- IORedis
- Vike
- Jest
- Vitest
- Controllers
- Providers
- Model
- JsonMapper
- Middlewares
- Pipes
- Interceptors
- Authentication
- Hooks
- Exceptions
- Throw HTTP Exceptions
- Cache
- Command
- Response Filter
- Injection scopes
- Custom providers
- Lazy-loading provider
- Custom endpoint decorator
- Testing
- Customize 404