Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/supabase/stripe-sync-engine
Sync your Stripe account to you Postgres database.
https://github.com/supabase/stripe-sync-engine
fastify postgres postgresql stripe stripe-api stripe-payments stripe-subscriptions typescript
Last synced: about 6 hours ago
JSON representation
Sync your Stripe account to you Postgres database.
- Host: GitHub
- URL: https://github.com/supabase/stripe-sync-engine
- Owner: supabase
- License: apache-2.0
- Created: 2021-04-29T13:12:48.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2024-09-18T16:16:47.000Z (5 months ago)
- Last Synced: 2024-10-29T13:28:32.044Z (3 months ago)
- Topics: fastify, postgres, postgresql, stripe, stripe-api, stripe-payments, stripe-subscriptions, typescript
- Language: TypeScript
- Homepage: https://supabase.com
- Size: 1.65 MB
- Stars: 496
- Watchers: 36
- Forks: 49
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Stripe Sync Engine
Continuously synchronizes a Stripe account to a Postgres database.
![Sync Stripe with Postgres](./docs/stripe-sync-engine.jpg)
## Motivation
Sometimes you want to analyze your billing data using SQL. Even more importantly, you want to join your billing data to your product/business data.
This server synchronizes your Stripe account to a Postgres database. It can be a new database, or an existing Postgres database.
## How it works
![How it works](./docs/sync-engine-how.png)
- Creates a new schema `stripe` in a Postgres database, with tables & columns matching Stripe.
- Exposes a `/webhooks` endpoint that listens to any Stripe webhooks.
- Inserts/updates/deletes changes into the tables whenever there is a change to Stripe.**Not implemented**
- This will not do an initial load of existing Stripe data. You should use CSV loads for this. We might implement this in the future.
- We are progressively working through webhooks.## Webhook Progress
- [ ] `balance.available`
- [x] `charge.captured` π’
- [x] `charge.expired` π’
- [x] `charge.failed` π’
- [x] `charge.pending` π’
- [x] `charge.refunded` π’
- [x] `charge.succeeded` π’
- [x] `charge.updated` π’
- [x] `charge.dispute.closed` π’
- [x] `charge.dispute.created` π’
- [x] `charge.dispute.funds_reinstated` π’
- [x] `charge.dispute.funds_withdrawn` π’
- [x] `charge.dispute.updated` π’
- [ ] `checkout.session.async_payment_failed`
- [ ] `checkout.session.async_payment_succeeded`
- [ ] `checkout.session.completed`
- [x] `credit_note.created` π’
- [x] `credit_note.updated` π’
- [x] `credit_note.voided` π’
- [x] `customer.created` π’
- [x] `customer.deleted` π’
- [ ] `customer.source.created`
- [ ] `customer.source.updated`
- [x] `customer.subscription.created` π’
- [x] `customer.subscription.deleted` π’
- [x] `customer.subscription.paused` π’
- [x] `customer.subscription.pending_update_applied` π’
- [x] `customer.subscription.pending_update_expired` π’
- [x] `customer.subscription.resumed` π’
- [x] `customer.subscription.trial_will_end` π’
- [x] `customer.subscription.updated` π’
- [x] `customer.tax_id.created` π’
- [x] `customer.tax_id.deleted` π’
- [x] `customer.tax_id.updated` π’
- [x] `customer.updated` π’
- [x] `invoice.created` π’
- [x] `invoice.deleted` π’
- [x] `invoice.finalized` π’
- [x] `invoice.finalization_failed` π’
- [x] `invoice.marked_uncollectible` π’
- [x] `invoice.paid` π’
- [x] `invoice.payment_action_required` π’
- [x] `invoice.payment_failed` π’
- [x] `invoice.payment_succeeded` π’
- [x] `invoice.sent` π’
- [x] `invoice.upcoming` π’
- [x] `invoice.updated` π’
- [x] `invoice.voided` π’
- [ ] `issuing_authorization.request`
- [ ] `issuing_card.created`
- [ ] `issuing_cardholder.created`
- [x] `payment_intent.amount_capturable_updated` π’
- [x] `payment_intent.canceled` π’
- [x] `payment_intent.created` π’
- [x] `payment_intent.partially_refunded` π’
- [x] `payment_intent.payment_failed` π’
- [x] `payment_intent.processing` π’
- [x] `payment_intent.requires_action` π’
- [x] `payment_intent.succeeded` π’
- [x] `payment_method.attached` π’
- [x] `payment_method.automatically_updated` π’
- [x] `payment_method.detached` π’
- [x] `payment_method.updated` π’
- [x] `plan.created` π’
- [x] `plan.deleted` π’
- [x] `plan.updated` π’
- [x] `price.created` π’
- [x] `price.deleted` π’
- [x] `price.updated` π’
- [x] `product.created` π’
- [x] `product.deleted` π’
- [x] `product.updated` π’
- [x] `setup_intent.canceled` π’
- [x] `setup_intent.created` π’
- [x] `setup_intent.requires_action` π’
- [x] `setup_intent.setup_failed` π’
- [x] `setup_intent.succeeded` π’
- [x] `subscription_schedule.aborted` π’
- [x] `subscription_schedule.canceled` π’
- [x] `subscription_schedule.completed` π’
- [x] `subscription_schedule.created` π’
- [x] `subscription_schedule.expiring` π’
- [x] `subscription_schedule.released` π’
- [x] `subscription_schedule.updated` π’## Usage
- Update your Stripe account with all valid webhooks and get the webhook secret
- `mv .env.sample .env` and then rename all the variables
- Make sure the database URL has search_path `stripe`. eg: `DATABASE_URL=postgres://postgres:postgres@hostname:5432/postgres?sslmode=disable&search_path=stripe`
- Deploy the [docker image](https://hub.docker.com/r/supabase/stripe-sync-engine) to your favourite hosting service and expose port `8080`
- eg: `docker run -e PORT=8080 --env-file .env supabase/stripe-sync-engine`
- This will automatically run any migrations on your database
- Point your Stripe webooks to your deployed app.## Backfill from Stripe
```
POST /sync
body: {
"object": "product",
"created": {
"gte": 1643872333
}
}
```- `object` **all** | **charge** | **customer** | **dispute** | **invoice** | **payment_method** | **payment_intent** | **plan** | **price** | **product** | **setup_intent** | **subscription**
- `created` is Stripe.RangeQueryParam. It supports **gt**, **gte**, **lt**, **lte**#### Alternative routes to sync `daily/weekly/monthly` data
```
POST /sync/daily---
POST /sync/daily
body: {
"object": "product"
}
```### Syncing single entity
To backfill/update a single entity, you can use
```
POST /sync/single/cus_12345
```The entity type is recognized automatically, based on the prefix.
## Future ideas
- Expose an "initialize" endpoint that will fetch data from Stripe and do an initial load (or perhaps `POST` a CSV to an endpoint).
## Development
**Set up**
- Create a Postgres database on [supabase.com](https://supabase.com) (or another Postgres provider)
- Update Stripe with all valid webhooks and get the webhook secret
- `mv .env.sample .env` and then rename all the variables**Develop**
- `npm run dev` to start the local server
- `npm run test` to run tests**Building Docker**
```bash
docker build -t stripe-sync-engine .
docker run -p 8080:8080 stripe-sync-engine
```**Release**
Handled by GitHub actions whenever their is a commit to the `main` branch with `fix` or `feat` in the description.
## License
Apache 2.0
## Sponsors
Supabase is building the features of Firebase using enterprise-grade, open source products. We support existing communities wherever possible, and if the products donβt exist we build them and open source them ourselves.
[![New Sponsor](https://user-images.githubusercontent.com/10214025/90518111-e74bbb00-e198-11ea-8f88-c9e3c1aa4b5b.png)](https://github.com/sponsors/supabase)