|
| 1 | +# Sample using Next.js, TypeScript, and react-stripe-js 🔒💸 |
| 2 | + |
| 3 | +- Demo: https://nextjs-typescript-react-stripe-js.now.sh/ |
| 4 | +- CodeSandbox: https://codesandbox.io/s/github/stripe-samples/nextjs-typescript-react-stripe-js |
| 5 | +- Tutorial: https://dev.to/thorwebdev/type-safe-payments-with-next-js-typescript-and-stripe-4jo7 |
| 6 | + |
| 7 | +This is a full-stack TypeScript example using: |
| 8 | + |
| 9 | +- Frontend: |
| 10 | + - Next.js and [SWR](https://github.com/zeit/swr) |
| 11 | + - [react-stripe-js](https://github.com/stripe/react-stripe-js) for [Checkout](https://stripe.com/checkout) and [Elements](https://stripe.com/elements) |
| 12 | +- Backend |
| 13 | + - Next.js [API routes](https://nextjs.org/docs/api-routes/introduction) |
| 14 | + - [stripe-node with TypeScript](https://github.com/stripe/stripe-node#usage-with-typescript) |
| 15 | + |
| 16 | +### Included functionality |
| 17 | + |
| 18 | +- Making `.env` variables available to next: [next.config.js](next.config.js) |
| 19 | + - **Note**: When deploying with Now you need to [add your secrets](https://zeit.co/docs/v2/serverless-functions/env-and-secrets) and specify a [now.json](/now.json) file. |
| 20 | +- Implementation of a Layout component that loads and sets up Stripe.js and Elements for usage with SSR via `loadStripe` helper: [components/Layout.tsx](components/Layout.tsx). |
| 21 | +- Stripe Checkout |
| 22 | + - Custom Amount Donation with redirect to Stripe Checkout: |
| 23 | + - Frontend: [pages/donate-with-checkout.tsx](pages/donate-with-checkout.tsx) |
| 24 | + - Backend: [pages/api/checkout_sessions/](pages/api/checkout_sessions/) |
| 25 | + - Checkout payment result page that uses [SWR](https://github.com/zeit/swr) hooks to fetch the CheckoutSession status from the API route: [pages/result.tsx](pages/result.tsx). |
| 26 | +- Stripe Elements |
| 27 | + - Custom Amount Donation with Stripe Elements & PaymentIntents (no redirect): |
| 28 | + - Frontend: [pages/donate-with-elements.tsx](pages/donate-with-checkout.tsx) |
| 29 | + - Backend: [pages/api/payment_intents/](pages/api/payment_intents/) |
| 30 | +- Webhook handling for [post-payment events](https://stripe.com/docs/payments/accept-a-payment#web-fulfillment) |
| 31 | + - By default Next.js API routes are same-origin only. To allow Stripe webhook event requests to reach our API route, we need to add `micro-cors` and [verify the webhook signature](https://stripe.com/docs/webhooks/signatures) of the event. All of this happens in [pages/api/webhooks/index.ts](pages/api/webhooks/index.ts). |
| 32 | +- Helpers |
| 33 | + - [utils/api-helpers.ts](utils/api-helpers.ts) |
| 34 | + - helpers for GET and POST requests. |
| 35 | + - [utils/stripe-helpers.ts](utils/stripe-helpers.ts) |
| 36 | + - Format amount strings properly using `Intl.NumberFormat`. |
| 37 | + - Format amount for usage with Stripe, including zero decimal currency detection. |
| 38 | + |
| 39 | +## How to use |
| 40 | + |
| 41 | +### Using `create-next-app` |
| 42 | + |
| 43 | +Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: |
| 44 | + |
| 45 | +```bash |
| 46 | +npm init next-app --example with-stripe-typescript with-stripe-typescript-app |
| 47 | +# or |
| 48 | +yarn create next-app --example with-stripe-typescript with-stripe-typescript-app |
| 49 | +``` |
| 50 | + |
| 51 | +### Download manually |
| 52 | + |
| 53 | +Download the example: |
| 54 | + |
| 55 | +```bash |
| 56 | +curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-stripe-typescript |
| 57 | +cd with-stripe-typescript |
| 58 | +``` |
| 59 | + |
| 60 | +### Required configuration |
| 61 | + |
| 62 | +Copy the `.env.example` file into a file named `.env` in the root directory of this project: |
| 63 | + |
| 64 | +```bash |
| 65 | +cp .env.example .env |
| 66 | +``` |
| 67 | + |
| 68 | +You will need a Stripe account ([register](https://dashboard.stripe.com/register)) to run this sample. Go to the Stripe [developer dashboard](https://stripe.com/docs/development#api-keys) to find your API keys and replace them in the `.env` file. |
| 69 | + |
| 70 | +```bash |
| 71 | +STRIPE_PUBLISHABLE_KEY=<replace-with-your-publishable-key> |
| 72 | +STRIPE_SECRET_KEY=<replace-with-your-secret-key> |
| 73 | +``` |
| 74 | + |
| 75 | +Now install the dependencies and start the development server. |
| 76 | + |
| 77 | +```bash |
| 78 | +npm install |
| 79 | +npm run dev |
| 80 | +# or |
| 81 | +yarn |
| 82 | +yarn dev |
| 83 | +``` |
| 84 | + |
| 85 | +### Forward webhooks to your local dev server |
| 86 | + |
| 87 | +First [install the CLI](https://stripe.com/docs/stripe-cli) and [link your Stripe account](https://stripe.com/docs/stripe-cli#link-account). |
| 88 | + |
| 89 | +Next, start the webhook forwarding: |
| 90 | + |
| 91 | +```bash |
| 92 | +stripe listen --forward-to localhost:3000/api/webhooks |
| 93 | +``` |
| 94 | + |
| 95 | +The CLI will print a webhook secret key to the console. Set `STRIPE_WEBHOOK_SECRET` to this value in your `.env` file. |
| 96 | + |
| 97 | +### Deploy |
| 98 | + |
| 99 | +Deploy it to the cloud with [ZEIT Now](https://zeit.co/new?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). |
| 100 | + |
| 101 | +**Note**: You must add your Stripe secrets using the ZEIT Now CLI ([Download here](https://zeit.co/download)): |
| 102 | + |
| 103 | +```bash |
| 104 | +now secrets add stripe_publishable_key pk_*** |
| 105 | +now secrets add stripe_secret_key sk_*** |
| 106 | +now secrets add stripe_webhook_secret whsec_*** |
| 107 | +``` |
| 108 | + |
| 109 | +After deploying, copy the deployment URL with the webhook path (`https://your-url.now.sh/api/webhooks`) and create a live webhook endpoint [in your Stripe dashboard](https://stripe.com/docs/webhooks/setup#configure-webhook-settings). |
| 110 | + |
| 111 | +**Note**: Your live webhook will have a different secret. To update it in your deployed application you will need to first remove the existing secret and then add the new secret: |
| 112 | + |
| 113 | +```bash |
| 114 | +now secrets rm stripe_webhook_secret |
| 115 | +now secrets add stripe_webhook_secret whsec_*** |
| 116 | +``` |
| 117 | + |
| 118 | +As the secrets are set as env vars in the project at deploy time, we will need to redeploy our app after we made changes to the secrets. |
| 119 | + |
| 120 | +### Author |
| 121 | + |
| 122 | +- [@thorsten-stripe](https://twitter.com/thorwebdev) |
0 commit comments