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

feat: Subscriptions with Stripe function #2

Merged
merged 37 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
c3bf5c8
feat: subscriptions with stripe initial
loks0n Jul 11, 2023
0198883
chore: add prettierrc
loks0n Jul 11, 2023
b2cf965
chore: add prettier
loks0n Jul 11, 2023
cf1b202
Merge branch 'main' of https://github.com/appwrite/templates-for-node…
loks0n Jul 11, 2023
5fe47c5
feat: migrate to esm
loks0n Jul 12, 2023
f92ff3a
fix: esm migration
loks0n Jul 17, 2023
de28d65
docs: update readme
loks0n Jul 18, 2023
457a42c
chore: add semis, remove pjson extras
loks0n Jul 19, 2023
e237cd2
chore: use classes over function pattern
loks0n Jul 19, 2023
a34fee9
chore: new structure
loks0n Jul 20, 2023
29aef16
chore: prettier script
loks0n Jul 20, 2023
55ca0ac
Merge branch 'main' of https://github.com/appwrite/templates into fea…
loks0n Jul 25, 2023
33c582a
docs: update to new template
loks0n Jul 25, 2023
d540ce2
chore: new utils, env.d.ts
loks0n Jul 31, 2023
8349908
feat: use appwrite_function_project_id
loks0n Aug 9, 2023
04329cc
fix: more robust setup
loks0n Aug 9, 2023
1d25136
Migrate stripe sub to labels
Meldiron Sep 6, 2023
7ce17d8
URLs to be optional
Meldiron Sep 6, 2023
9c1bead
Fix required env vars
Meldiron Sep 6, 2023
be69393
Add basic HTML file
Meldiron Sep 6, 2023
15e8331
add file utils
Meldiron Sep 6, 2023
2c070ae
Implement frontend
Meldiron Sep 6, 2023
3d07d95
Introduce context var
Meldiron Sep 6, 2023
b6ca9d5
Fix redirect URL
Meldiron Sep 6, 2023
2c88880
Remove dev changes
Meldiron Sep 6, 2023
b2e8e07
Fix redirect JS
Meldiron Sep 6, 2023
32fa082
Improve logging
Meldiron Sep 6, 2023
241d6c9
Allow dynamic direrect URLs
Meldiron Sep 6, 2023
548c202
Improve UX
Meldiron Sep 6, 2023
764ee04
Apply suggestions from code review
Meldiron Sep 8, 2023
1f552e4
Add payment with stripe template for Node
Meldiron Sep 8, 2023
cd9a783
Fix HTML page for payments
Meldiron Sep 8, 2023
f1e34a5
Finish payment HTML
Meldiron Sep 8, 2023
1c06e24
Fix alpine bug
Meldiron Sep 8, 2023
07467fd
Fix layout and missing orders
Meldiron Sep 8, 2023
e81b9be
Improve UX
Meldiron Sep 8, 2023
06edae0
Apply suggestions from code review
Meldiron Sep 9, 2023
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
130 changes: 130 additions & 0 deletions node/subscriptions-with-stripe/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
6 changes: 6 additions & 0 deletions node/subscriptions-with-stripe/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": true
}
112 changes: 112 additions & 0 deletions node/subscriptions-with-stripe/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# 💳 Node.js Stripe Subscriptions Function

Integrates Stripe subscriptions into your Appwrite project. Collect card payment with the `/subscribe` endpoint and check the status of a user subscription using the `Subscriptions` collection.
Meldiron marked this conversation as resolved.
Show resolved Hide resolved
Meldiron marked this conversation as resolved.
Show resolved Hide resolved

## 🧰 Usage

### `POST /subscribe`

This endpoint initiates a Stripe checkout session for a subscription. The user ID is fetched from the headers of the request. If the user ID is not found or a Stripe checkout session could not be created, the request will be redirected to a cancel URL.

**Parameters**

| Name | Description | Location | Type | Sample Value |
| ------------------ | ---------------------- | -------- | ------ | ------------ |
| x-appwrite-user-id | User ID from Appwrite. | Header | String | 642...7cd |
| Content-Type | The content type of the request body | Header | `application/json` | N/A |
| successUrl | The URL to redirect to after a successful payment. | Body | String | https://example.com/success |
| failureUrl | The URL to redirect to after a cancelled payment attempt. | Body | String | https://example.com/failure |

**Response**

Sample `303` Response:

The response is a redirect to the Stripe checkout session URL or to the cancel URL if an error occurs

```text
Location: https://checkout.stripe.com/pay/cs_test_...#fidkdWxOYHwnP
```

```text
Location: https://mywebapp.com/cancel
```

### `POST /webhook`

This endpoint is a webhook that handles two types of events from Stripe: `customer.subscription.created` and `customer.subscription.deleted`. It validates the incoming request using the Stripe's validateWebhook method. If the validation fails, a `401` response is sent.

**Parameters**

| Name | Description | Location | Type | Sample Value |
| ---- | ---------------------------- | -------- | ------ | --------------------------------------------------------------------- |
| None | Webhook payload from Stripe. | Body | Object | [See Stripe documentation](https://stripe.com/docs/api/events/object) |

**Response**

Sample `200` Response:

In case of `customer.subscription.created` event, it gives user `subscriber` label.
In case of `customer.subscription.deleted` event, it takes `subscriber` label away from user.

```json
{ "success": true }
```

Sample `401` Response:

```json
{ "success": false }
```

## ⚙️ Configuration

| Setting | Value |
| ----------------- | --------------- |
| Runtime | Node (18.0) |
| Entrypoint | `src/main.js` |
| Build Commands | `npm install` |
| Permissions | `any` |
| Timeout (Seconds) | 15 |

Meldiron marked this conversation as resolved.
Show resolved Hide resolved
> If using a demo web app to subscribe, make sure to add your function domain as a web platform to your Appwrite project. Doing this fixes CORS errors and allows proper functionality.

## 🔒 Environment Variables

### APPWRITE_API_KEY

Your Appwrite project's API key.

| Question | Answer |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Required | Yes |
| Sample Value | `083d341ee48...` |
| Documentation | [Appwrite: Create an API key](https://appwrite.io/docs/keys#:~:text=To%20create%20a%20new%20API,scope%20to%20grant%20your%20application.) |

### APPWRITE_ENDPOINT

The endpoint where your Appwrite server is located. If not provided, it defaults to the Appwrite Cloud server: `https://cloud.appwrite.io/v1`.

| Question | Answer |
| ------------ | ------------------------------ |
| Required | No |
| Sample Value | `https://cloud.appwrite.io/v1` |

### STRIPE_SECRET_KEY

Secret for sending requests to the Stripe API.

| Question | Answer |
| ------------- | ------------------------------------------------ |
| Required | Yes |
| Sample Value | `sk_test_51J...` |
| Documentation | [Stripe: API Keys](https://stripe.com/docs/keys) |

### STRIPE_WEBHOOK_SECRET

Secret used to validate the Stripe Webhook signature.

| Question | Answer |
| ------------- | ---------------------------------------------------- |
| Required | Yes |
| Sample Value | `whsec_...` |
| Documentation | [Stripe: Webhooks](https://stripe.com/docs/webhooks) |
13 changes: 13 additions & 0 deletions node/subscriptions-with-stripe/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
declare global {
namespace NodeJS {
interface ProcessEnv {
APPWRITE_ENDPOINT?: string;
APPWRITE_FUNCTION_PROJECT_ID: string;
APPWRITE_API_KEY: string;
STRIPE_SECRET_KEY: string;
STRIPE_WEBHOOK_SECRET: string;
}
}
}

export {};
Loading