Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Updates for beta branch #1676

Merged
merged 19 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
node_modules
lib
testProjects
examples/**
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Changelog

## 11.10.0 - 2023-02-09
* [#1679](https://github.com/stripe/stripe-node/pull/1679) Enable library to work in worker environments without extra configuration.

## 11.10.0-beta.1 - 2023-02-02
* [#1671](https://github.com/stripe/stripe-node/pull/1671) API Updates for beta branch
* Updated stable APIs to the latest version
Expand All @@ -16,6 +19,9 @@
* Remove support for `id` on `QuoteCreateParams.lines[].starts_at.line_ends_at`
* Add support for new values `customer.subscription.paused`, `customer.subscription.resumed`, `financial_connections.account.refreshed_inferred_balances`, `financial_connections.account.refreshed_ownership`, `financial_connections.account.refreshed_transactions`, and `financial_connections.session.updated` on enums `WebhookEndpointCreateParams.enabled_events[]` and `WebhookEndpointUpdateParams.enabled_events[]`

## 11.9.1 - 2023-02-03
* [#1672](https://github.com/stripe/stripe-node/pull/1672) Update main entrypoint on package.json

## 11.9.0 - 2023-02-02
* [#1669](https://github.com/stripe/stripe-node/pull/1669) API Updates
* Add support for `resume` method on resource `Subscription`
Expand Down
2 changes: 1 addition & 1 deletion OPENAPI_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v223
v224
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ Stripe can optionally sign the webhook events it sends to your endpoint, allowin

Please note that you must pass the _raw_ request body, exactly as received from Stripe, to the `constructEvent()` function; this will not work with a parsed (i.e., JSON) request body.

You can find an example of how to use this with [Express](https://expressjs.com/) in the [`examples/webhook-signing`](examples/webhook-signing) folder, but here's what it looks like:
You can find an example of how to use this with various JavaScript frameworks in [`examples/webhook-signing`](examples/webhook-signing) folder, but here's what it looks like:

```js
const event = stripe.webhooks.constructEvent(
Expand Down
2 changes: 1 addition & 1 deletion examples/webhook-signing/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Stripe keys
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_WEBHOOK_SECRET=whsec_0000000000000000000000000000000000000000000000000000000000000000
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ module.exports = {
env: {
node: true,
},
parserOptions: {
warnOnUnsupportedTypeScriptVersion: false,
},
root: true,
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint', 'prettier'],
Expand Down
3 changes: 3 additions & 0 deletions examples/webhook-signing/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
*/tsconfig.json
**/.eslintrc.js
**/package-lock.json
.env
express-ts.js
39 changes: 26 additions & 13 deletions examples/webhook-signing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@

Verify the events that Stripe sends to your webhook endpoints. Additional details in the Stripe [docs](https://stripe.com/docs/webhooks/signatures).

You can find a Node.js TypeScript server example in [stripe-samples](https://github.com/stripe-samples/accept-a-payment/tree/main/custom-payment-flow/server/node-typescript).
Available examples:
- [`express`](./express) - Express 4
- [`koa`](./koa) - Koa 2

### Requirements

You’ll need the following:

- [Node.js](http://nodejs.org) >=10.0.0
- [Node.js](http://nodejs.org) >=14.0.0
- Stripe account to accept payments ([sign up](https://dashboard.stripe.com/register) for free).
- [Stripe CLI](https://github.com/stripe/stripe-cli) or [ngrok](https://ngrok.com/) to tunnel requests to your local server.

### Setup

In this directory (`cd examples/webhook-signing/`), copy the environment variables file:

cp .env.example .env

Update `.env` with your own [Stripe API keys](https://dashboard.stripe.com/account/apikeys).

### Install and run

In the sample directory (`cd examples/webhook-signing/express`).

Install dependencies:

npm install

Update `.env` with your own [Stripe API keys](https://dashboard.stripe.com/account/apikeys).

Next, follow [these installation steps](https://github.com/stripe/stripe-cli#installation) to install the Stripe CLI which we'll use for webhook forwarding.

After the installation has finished, authenticate the CLI with your Stripe account:
Expand All @@ -42,13 +40,28 @@ The Stripe CLI will let you know that webhook forwarding is ready and output you

Copy the webhook signing secret (`whsec_xxx`) to your `.env` file.

In a separate terminal window, start the local server:
In a separate terminal window, start the local sample server:

npm run vanilla # Runs the vanilla JavaScript example.
npm run typescript # Compiles and runs the TypeScript example.
`./main.ts`

In another separate terminal window, trigger an event, for example:

stripe trigger payment_intent.succeeded

You should now see some webhook event details being logged to your Node.js console.

## Developing

To add a new example:
1. Create a new subfolder using the server library name
2. Copy `package.json` from one of the existing samples. Remove extra dependencies.
3. Create a `main.ts` file with sample server code and run `chmod +x main.ts` so it's directly executable.
4. The `main.ts` has to follow some rules:
1. Written in typescript using `import .. from ..` import syntax.
2. Must have `#!/usr/bin/env -S npm run-script run` header to be directly runable.
3. Must print `Webhook endpoint available at <url>` when the server is started.
4. Must return `{"received":true}` and 200 status code for `charge.succeeded` event.
5. Test your example
1. `cd examples/webhook-signing/test`
2. `./main.ts ../<your test directory>`
3. Add a test to `/tests/Integration.spec.ts`
12 changes: 9 additions & 3 deletions ...ing/typescript-node-express/express-ts.ts → examples/webhook-signing/express/main.ts
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env -S npm run-script run

import Stripe from 'stripe';
import express from 'express';
import env from 'dotenv';
import {AddressInfo} from 'net';

env.config();

Expand Down Expand Up @@ -65,6 +68,9 @@ app.post(
}
);

app.listen(3000, (): void => {
console.log('Example app listening on port 3000!');
});
const server = app.listen();
console.log(
`Webhook endpoint available at http://localhost:${
(<AddressInfo>server.address()).port
}/webhook`
);
26 changes: 26 additions & 0 deletions examples/webhook-signing/express/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "webhook-signing-example-express",
"version": "1.0.0",
"description": "Express webhook parsing sample",
"repository": {},
"main": "./main.ts",
"scripts": {
"run": "ts-node-transpile-only ./main.ts",
"prepare": "../prepare.sh"
},
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^8.2.0",
"express": "^4.17.1",
"koa": "^2.14.1",
"stripe": "^11.9.1"
},
"devDependencies": {
"eslint": "^8.33.0",
"@types/koa": "^2.13.5",
"@types/koa-bodyparser": "^4.3.10",
"@types/node": "^13.1.4",
"typescript": "^4.8.3"
}
}
71 changes: 71 additions & 0 deletions examples/webhook-signing/koa/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env -S npm run-script run

import Stripe from 'stripe';
import Koa from 'koa';
import bodyParser from 'koa-bodyparser';
import env from 'dotenv';
import {AddressInfo} from 'net';

const app = new Koa();

env.config();
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY, {
apiVersion: '2022-11-15',
});

const handleWebhook = async (ctx: Koa.ParameterizedContext, next: Koa.Next) => {
const sig = ctx.request.headers['stripe-signature'];
let event;

try {
event = stripe.webhooks.constructEvent(
ctx.request.rawBody,
sig,
webhookSecret
);
} catch (err) {
// On error, log and return the error message
console.log(`❌ Error message: ${err.message}`);
ctx.response.status = 400;
ctx.body = `Webhook Error: ${err.message}`;
return await next();
}

// Successfully constructed event
console.log('✅ Success:', event.id);

// Cast event data to Stripe object
if (event.type === 'payment_intent.succeeded') {
const stripeObject = event.data.object;
console.log(`💰 PaymentIntent status: ${stripeObject.status}`);
} else if (event.type === 'charge.succeeded') {
const charge = event.data.object;
console.log(`💵 Charge id: ${charge.id}`);
} else {
console.warn(`🤷‍♀️ Unhandled event type: ${event.type}`);
}

// Return a response to acknowledge receipt of the event
ctx.response.body = JSON.stringify({received: true});
ctx.response.set('Content-Type', 'application/json');
return await next();
};

app.use(bodyParser({enableTypes: ['json']}));
app.use(async (ctx, next) => {
if (ctx.request.path === '/webhook') {
return handleWebhook(ctx, next);
}
const name = ctx.request.body?.['name'] ?? 'world';
ctx.body = `hello ${name}, you hit ${ctx.request.path}`;
});

const server = app.listen();

console.log(
`Webhook endpoint available at http://localhost:${
(<AddressInfo>server.address()).port
}/webhook`
);
26 changes: 26 additions & 0 deletions examples/webhook-signing/koa/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "webhook-signing-example-koa",
"version": "1.0.0",
"description": "",
"main": "./main.ts",
"scripts": {
"run": "ts-node-transpile-only ./main.ts",
"prepare": "../prepare.sh"
},
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^8.2.0",
"koa": "^2.14.1",
"stripe": "^11.9.1",
"koa-bodyparser": "^4.3.0"
},
"devDependencies": {
"eslint": "^8.33.0",
"@types/node": "^13.1.4",
"@types/koa": "^2.13.5",
"@types/koa-bodyparser": "^4.3.10",
"typescript": "^4.8.3",
"ts-node": "^10.9.1"
}
}
10 changes: 0 additions & 10 deletions examples/webhook-signing/node-express/.eslintrc.js

This file was deleted.

41 changes: 0 additions & 41 deletions examples/webhook-signing/node-express/express.js

This file was deleted.

Loading