# 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 TypeORM module for Ts.ED:

npm install --save @tsed/stripe
npm install --save stripe
1
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
  }
}
1
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

# 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) {
  
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 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()
  stripe: Stripe;
  
  @Post("/callback")
  successPaymentHook(
    @WebhookEvent() event: Stripe.Event,
    @Context() ctx: Context
  ) {
    ctx.logger.info({name: 'Webhook success', event});
   
    return {received: true}
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 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})
  });
})
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

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.SuperTest<SuperTest.Test>;
  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
    });
  });
});
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

# Author

    # Maintainers

      Last Updated: 1/25/2021, 12:25:46 PM

      Other topics