vanty-payments 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. vanty_payments-0.1.0/.github/workflows/release.yml +56 -0
  2. vanty_payments-0.1.0/.github/workflows/tests.yml +63 -0
  3. vanty_payments-0.1.0/.gitignore +33 -0
  4. vanty_payments-0.1.0/PKG-INFO +238 -0
  5. vanty_payments-0.1.0/README.md +217 -0
  6. vanty_payments-0.1.0/docs/architecture.mdx +21 -0
  7. vanty_payments-0.1.0/docs/data-model.mdx +40 -0
  8. vanty_payments-0.1.0/docs/index.mdx +16 -0
  9. vanty_payments-0.1.0/docs/parity-target.mdx +42 -0
  10. vanty_payments-0.1.0/docs/sync.mdx +17 -0
  11. vanty_payments-0.1.0/docs/webhooks.mdx +16 -0
  12. vanty_payments-0.1.0/examples/reference-api/main.py +75 -0
  13. vanty_payments-0.1.0/pyproject.toml +80 -0
  14. vanty_payments-0.1.0/src/vanty_payments/__init__.py +18 -0
  15. vanty_payments-0.1.0/src/vanty_payments/admin/__init__.py +3 -0
  16. vanty_payments-0.1.0/src/vanty_payments/admin/router.py +177 -0
  17. vanty_payments-0.1.0/src/vanty_payments/admin/schemas.py +96 -0
  18. vanty_payments-0.1.0/src/vanty_payments/admin/services.py +156 -0
  19. vanty_payments-0.1.0/src/vanty_payments/billing/__init__.py +55 -0
  20. vanty_payments-0.1.0/src/vanty_payments/billing/constants.py +54 -0
  21. vanty_payments-0.1.0/src/vanty_payments/billing/schemas.py +158 -0
  22. vanty_payments-0.1.0/src/vanty_payments/billing/services.py +497 -0
  23. vanty_payments-0.1.0/src/vanty_payments/catalog/__init__.py +4 -0
  24. vanty_payments-0.1.0/src/vanty_payments/catalog/schemas.py +35 -0
  25. vanty_payments-0.1.0/src/vanty_payments/catalog/services.py +18 -0
  26. vanty_payments-0.1.0/src/vanty_payments/checkout/__init__.py +15 -0
  27. vanty_payments-0.1.0/src/vanty_payments/checkout/schemas.py +52 -0
  28. vanty_payments-0.1.0/src/vanty_payments/checkout/services.py +114 -0
  29. vanty_payments-0.1.0/src/vanty_payments/core/__init__.py +7 -0
  30. vanty_payments-0.1.0/src/vanty_payments/core/context.py +14 -0
  31. vanty_payments-0.1.0/src/vanty_payments/core/events.py +23 -0
  32. vanty_payments-0.1.0/src/vanty_payments/core/identity.py +44 -0
  33. vanty_payments-0.1.0/src/vanty_payments/core/schemas.py +10 -0
  34. vanty_payments-0.1.0/src/vanty_payments/core/stripe_client.py +179 -0
  35. vanty_payments-0.1.0/src/vanty_payments/core/utils.py +40 -0
  36. vanty_payments-0.1.0/src/vanty_payments/customers/__init__.py +4 -0
  37. vanty_payments-0.1.0/src/vanty_payments/customers/schemas.py +32 -0
  38. vanty_payments-0.1.0/src/vanty_payments/customers/services.py +107 -0
  39. vanty_payments-0.1.0/src/vanty_payments/db/__init__.py +3 -0
  40. vanty_payments-0.1.0/src/vanty_payments/db/models.py +478 -0
  41. vanty_payments-0.1.0/src/vanty_payments/db/parity_models.py +400 -0
  42. vanty_payments-0.1.0/src/vanty_payments/db/views.py +30 -0
  43. vanty_payments-0.1.0/src/vanty_payments/fastapi/__init__.py +4 -0
  44. vanty_payments-0.1.0/src/vanty_payments/fastapi/dependencies.py +18 -0
  45. vanty_payments-0.1.0/src/vanty_payments/fastapi/router.py +473 -0
  46. vanty_payments-0.1.0/src/vanty_payments/kit.py +334 -0
  47. vanty_payments-0.1.0/src/vanty_payments/py.typed +0 -0
  48. vanty_payments-0.1.0/src/vanty_payments/settings.py +51 -0
  49. vanty_payments-0.1.0/src/vanty_payments/sync/__init__.py +4 -0
  50. vanty_payments-0.1.0/src/vanty_payments/sync/parity.py +617 -0
  51. vanty_payments-0.1.0/src/vanty_payments/sync/schemas.py +57 -0
  52. vanty_payments-0.1.0/src/vanty_payments/sync/services.py +458 -0
  53. vanty_payments-0.1.0/src/vanty_payments/webhooks/__init__.py +4 -0
  54. vanty_payments-0.1.0/src/vanty_payments/webhooks/handlers.py +145 -0
  55. vanty_payments-0.1.0/src/vanty_payments/webhooks/schemas.py +23 -0
  56. vanty_payments-0.1.0/src/vanty_payments/webhooks/services.py +111 -0
  57. vanty_payments-0.1.0/tests/conftest.py +23 -0
  58. vanty_payments-0.1.0/tests/test_admin_routes.py +200 -0
  59. vanty_payments-0.1.0/tests/test_admin_service.py +193 -0
  60. vanty_payments-0.1.0/tests/test_api_routes.py +431 -0
  61. vanty_payments-0.1.0/tests/test_billing.py +163 -0
  62. vanty_payments-0.1.0/tests/test_billing_routes.py +294 -0
  63. vanty_payments-0.1.0/tests/test_billing_service.py +646 -0
  64. vanty_payments-0.1.0/tests/test_catalog_sync.py +63 -0
  65. vanty_payments-0.1.0/tests/test_checkout.py +127 -0
  66. vanty_payments-0.1.0/tests/test_core_utils.py +69 -0
  67. vanty_payments-0.1.0/tests/test_customer_bootstrap.py +35 -0
  68. vanty_payments-0.1.0/tests/test_events.py +79 -0
  69. vanty_payments-0.1.0/tests/test_identity.py +53 -0
  70. vanty_payments-0.1.0/tests/test_parity_sync.py +205 -0
  71. vanty_payments-0.1.0/tests/test_settings.py +46 -0
  72. vanty_payments-0.1.0/tests/test_stripe_client.py +140 -0
  73. vanty_payments-0.1.0/tests/test_sync_backfill.py +42 -0
  74. vanty_payments-0.1.0/tests/test_webhook_handlers.py +244 -0
  75. vanty_payments-0.1.0/tests/test_webhook_replay.py +100 -0
  76. vanty_payments-0.1.0/tests/test_webhooks.py +85 -0
  77. vanty_payments-0.1.0/uv.lock +648 -0
@@ -0,0 +1,56 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: write
10
+ id-token: write
11
+
12
+ jobs:
13
+ build:
14
+ name: Build
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 5
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.12"
22
+ - uses: astral-sh/setup-uv@v6
23
+ - run: uv build
24
+ - uses: actions/upload-artifact@v4
25
+ with:
26
+ name: dist
27
+ path: dist/
28
+
29
+ github-release:
30
+ name: GitHub Release
31
+ needs: build
32
+ runs-on: ubuntu-latest
33
+ timeout-minutes: 5
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - uses: actions/download-artifact@v4
37
+ with:
38
+ name: dist
39
+ path: dist/
40
+ - uses: softprops/action-gh-release@v2
41
+ with:
42
+ generate_release_notes: true
43
+ files: dist/*
44
+
45
+ publish:
46
+ name: Publish to PyPI
47
+ needs: build
48
+ runs-on: ubuntu-latest
49
+ timeout-minutes: 5
50
+ environment: release
51
+ steps:
52
+ - uses: actions/download-artifact@v4
53
+ with:
54
+ name: dist
55
+ path: dist/
56
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,63 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths:
7
+ - "src/**"
8
+ - "tests/**"
9
+ - "pyproject.toml"
10
+ - "uv.lock"
11
+ - ".github/workflows/**"
12
+ pull_request:
13
+ workflow_dispatch:
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ lint:
20
+ name: Lint
21
+ runs-on: ubuntu-latest
22
+ timeout-minutes: 5
23
+ steps:
24
+ - uses: actions/checkout@v4
25
+ - uses: actions/setup-python@v5
26
+ with:
27
+ python-version: "3.12"
28
+ - uses: astral-sh/setup-uv@v6
29
+ - run: uv sync --dev
30
+ - run: uv run ruff check
31
+
32
+ test:
33
+ name: "Test: Python ${{ matrix.python-version }}"
34
+ runs-on: ubuntu-latest
35
+ timeout-minutes: 10
36
+ strategy:
37
+ matrix:
38
+ python-version: ["3.12", "3.13"]
39
+ fail-fast: false
40
+ steps:
41
+ - uses: actions/checkout@v4
42
+ - uses: actions/setup-python@v5
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+ - uses: astral-sh/setup-uv@v6
46
+ - run: uv sync --dev
47
+ - run: uv run pytest -q
48
+
49
+ build:
50
+ name: Build
51
+ runs-on: ubuntu-latest
52
+ timeout-minutes: 5
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - uses: actions/setup-python@v5
56
+ with:
57
+ python-version: "3.12"
58
+ - uses: astral-sh/setup-uv@v6
59
+ - run: uv build
60
+ - uses: actions/upload-artifact@v4
61
+ with:
62
+ name: dist
63
+ path: dist/
@@ -0,0 +1,33 @@
1
+ .DS_Store
2
+ .env
3
+ .env.*
4
+ .coverage
5
+
6
+ # Local-only runtime and tool state
7
+ .local/
8
+ .omx/
9
+ .pgdata*
10
+ .pgrun
11
+ .pgsocket
12
+
13
+ # Python
14
+ .pytest_cache/
15
+ .ruff_cache/
16
+ .venv/
17
+ __pycache__/
18
+ *.db
19
+ *.db-shm
20
+ *.db-wal
21
+
22
+ # Build artifacts
23
+ dist/
24
+ *.egg-info/
25
+ *.db-journal
26
+ *.egg-info/
27
+ *.pyc
28
+ build/
29
+ dist/
30
+
31
+ # Node / Frontend
32
+ node_modules/
33
+ tsconfig.tsbuildinfo
@@ -0,0 +1,238 @@
1
+ Metadata-Version: 2.4
2
+ Name: vanty-payments
3
+ Version: 0.1.0
4
+ Summary: Lean Stripe-first payments toolkit for FastAPI with Tortoise ORM
5
+ License-Expression: MIT
6
+ Keywords: billing,fastapi,payments,stripe,subscriptions
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Framework :: FastAPI
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Topic :: Office/Business :: Financial
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.12
16
+ Requires-Dist: fastapi>=0.135.1
17
+ Requires-Dist: pydantic-settings>=2.13.1
18
+ Requires-Dist: stripe>=13.0.1
19
+ Requires-Dist: tortoise-orm>=1.1.6
20
+ Description-Content-Type: text/markdown
21
+
22
+ # Vanty Payments
23
+
24
+ [![Tests](https://github.com/advantch/vanty-payments/actions/workflows/tests.yml/badge.svg)](https://github.com/advantch/vanty-payments/actions/workflows/tests.yml)
25
+ [![PyPI](https://img.shields.io/pypi/v/vanty-payments)](https://pypi.org/project/vanty-payments/)
26
+ [![Python](https://img.shields.io/pypi/pyversions/vanty-payments)](https://pypi.org/project/vanty-payments/)
27
+
28
+ Stripe-first payments toolkit for FastAPI with Tortoise ORM. Checkout, subscriptions, invoices, billing portal, webhooks, and full Stripe object sync in a single `pip install`.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install vanty-payments
34
+ # or
35
+ uv pip install vanty-payments
36
+ ```
37
+
38
+ ## Quick start
39
+
40
+ ```python
41
+ from contextlib import asynccontextmanager
42
+
43
+ from fastapi import FastAPI
44
+
45
+ from vanty_payments import PaymentsKitSettings, mount_payments_router
46
+
47
+ settings = PaymentsKitSettings(
48
+ database_url="sqlite://./vanty-payments.db",
49
+ stripe_test_secret_key="sk_test_example",
50
+ stripe_webhook_secret="whsec_example",
51
+ )
52
+
53
+ app = FastAPI()
54
+ kit = mount_payments_router(app, settings=settings)
55
+
56
+
57
+ @asynccontextmanager
58
+ async def lifespan(_: FastAPI):
59
+ await kit.init_orm(generate_schemas=True)
60
+ try:
61
+ yield
62
+ finally:
63
+ await kit.close_orm()
64
+
65
+
66
+ app.router.lifespan_context = lifespan
67
+ ```
68
+
69
+ Run with `uvicorn main:app --reload` and visit `/docs` for the interactive API explorer.
70
+
71
+ ## Features
72
+
73
+ - **Checkout sessions** with Stripe-hosted and embedded flows
74
+ - **Subscription management** with plan changes, cancellation, and reactivation
75
+ - **Invoice management** with PDF links and payment status tracking
76
+ - **Billing portal** sessions for customer self-service
77
+ - **Payment method** management (cards, bank accounts)
78
+ - **Webhook ingestion** with signature verification and idempotent processing
79
+ - **Manual sync** to pull Stripe state into local models on demand
80
+ - **Full Stripe object parity** covering customers, products, prices, coupons, promotion codes, discounts, charges, refunds, disputes, and more
81
+ - **Admin management** endpoints for super-admin billing operations
82
+ - **Identity integration** with optional `vanty-auth` or custom identity resolvers
83
+
84
+ ## Architecture
85
+
86
+ `PaymentsKit` is a composition root that wires all services. Access services directly:
87
+
88
+ ```python
89
+ kit = mount_payments_router(app, settings=settings)
90
+
91
+ # Direct service access
92
+ await kit.checkout_service.create_session(customer_id=cid, price_id=pid)
93
+ await kit.subscription_service.list_subscriptions(customer_id=cid)
94
+ await kit.sync_service.sync_customer(stripe_customer_id="cus_xxx")
95
+ ```
96
+
97
+ Available services on `PaymentsKit`:
98
+
99
+ | Service | Purpose |
100
+ |---|---|
101
+ | `customer_service` | Customer bootstrap and management |
102
+ | `checkout_service` | Checkout session creation |
103
+ | `subscription_service` | Subscription reads and management |
104
+ | `invoice_service` | Invoice listing and retrieval |
105
+ | `payment_method_service` | Payment method listing |
106
+ | `portal_service` | Billing portal session creation |
107
+ | `webhook_service` | Webhook signature verification and dispatch |
108
+ | `sync_service` | Manual Stripe-to-local sync for all object types |
109
+ | `admin_service` | Super-admin billing operations |
110
+
111
+ ## Configuration
112
+
113
+ All settings are read from environment variables with the `PAYMENTS_KIT_` prefix, or passed directly to `PaymentsKitSettings`.
114
+
115
+ | Setting | Default | Description |
116
+ |---|---|---|
117
+ | `database_url` | `sqlite://./vanty-payments.db` | Tortoise ORM database URL |
118
+ | `stripe_test_secret_key` | — | Stripe test mode secret key |
119
+ | `stripe_live_secret_key` | — | Stripe live mode secret key |
120
+ | `stripe_webhook_secret` | — | Webhook endpoint signing secret |
121
+ | `stripe_mode` | `test` | `test` or `live` |
122
+ | `default_currency` | `usd` | Default currency for new prices |
123
+
124
+ Set via environment: `PAYMENTS_KIT_STRIPE_TEST_SECRET_KEY=sk_test_... PAYMENTS_KIT_DATABASE_URL=postgres://...`
125
+
126
+ ## API surface
127
+
128
+ ### Public routes (`/payments`)
129
+
130
+ | Method | Path | Description |
131
+ |---|---|---|
132
+ | `POST` | `/customers/bootstrap` | Create or retrieve a Stripe customer |
133
+ | `GET` | `/catalog/products` | List available products |
134
+ | `GET` | `/catalog/prices` | List prices for a product |
135
+ | `POST` | `/checkout/sessions` | Create a checkout session |
136
+ | `GET` | `/subscriptions` | List subscriptions |
137
+ | `GET` | `/subscriptions/{id}` | Get subscription details |
138
+ | `POST` | `/subscriptions/{id}/cancel` | Cancel a subscription |
139
+ | `POST` | `/portal/sessions` | Create a billing portal session |
140
+ | `GET` | `/invoices` | List invoices |
141
+ | `GET` | `/invoices/{id}` | Get invoice details |
142
+ | `GET` | `/payment-methods` | List payment methods |
143
+ | `POST` | `/webhooks/stripe` | Stripe webhook endpoint |
144
+ | `POST` | `/sync` | Trigger manual sync |
145
+
146
+ ### Admin routes (`/admin/payments`)
147
+
148
+ Super-admin endpoints for platform-wide billing management. Mount separately:
149
+
150
+ ```python
151
+ app.include_router(kit.admin_router, prefix="/admin/payments")
152
+ ```
153
+
154
+ ## Host app identity integration
155
+
156
+ The package works standalone, but a host app can supply a request-level identity adapter through `app.state.payments_identity_resolver`:
157
+
158
+ ```python
159
+ async def resolve_identity(request: Request) -> IdentityContext:
160
+ return IdentityContext(
161
+ user_reference=request.state.user_id,
162
+ organization_reference=request.state.org_id,
163
+ )
164
+
165
+ app.state.payments_identity_resolver = resolve_identity
166
+ ```
167
+
168
+ Routes then use those references automatically when request payloads omit them.
169
+
170
+ ## Project layout
171
+
172
+ ```text
173
+ src/vanty_payments/ Package source
174
+ docs/ Documentation
175
+ examples/reference-api/ Reference FastAPI application
176
+ tests/ pytest suite (unit + integration)
177
+ ```
178
+
179
+ ## Development
180
+
181
+ ```bash
182
+ git clone https://github.com/advantch/vanty-payments.git
183
+ cd vanty-payments
184
+ uv sync --dev
185
+
186
+ # Lint
187
+ uv run ruff check
188
+
189
+ # Test
190
+ uv run pytest -q
191
+
192
+ # Run reference API
193
+ cd examples/reference-api && uv run uvicorn main:app --reload
194
+ ```
195
+
196
+ Use `uv run pytest --no-cov tests/path/to/test.py` for targeted debugging without the coverage gate.
197
+
198
+ ## Releasing
199
+
200
+ Releases are automated via GitHub Actions. To publish a new version:
201
+
202
+ 1. Update the version in `pyproject.toml`:
203
+
204
+ ```toml
205
+ version = "0.2.0"
206
+ ```
207
+
208
+ 2. Commit and tag:
209
+
210
+ ```bash
211
+ git add pyproject.toml
212
+ git commit -m "release: v0.2.0"
213
+ git tag v0.2.0
214
+ git push origin main --tags
215
+ ```
216
+
217
+ 3. The `release.yml` workflow will automatically:
218
+ - Build the package
219
+ - Create a GitHub Release with auto-generated notes
220
+ - Publish to PyPI via trusted publishing (OIDC)
221
+
222
+ ### PyPI trusted publishing setup
223
+
224
+ To enable automated publishing, configure a trusted publisher on PyPI:
225
+
226
+ 1. Go to [pypi.org/manage/account/publishing](https://pypi.org/manage/account/publishing/)
227
+ 2. Add a new pending publisher (or update an existing project):
228
+ - **PyPI project name**: `vanty-payments`
229
+ - **Owner**: `advantch`
230
+ - **Repository**: `vanty-payments`
231
+ - **Workflow name**: `release.yml`
232
+ - **Environment name**: `release`
233
+
234
+ No API tokens are needed once trusted publishing is configured.
235
+
236
+ ## License
237
+
238
+ MIT
@@ -0,0 +1,217 @@
1
+ # Vanty Payments
2
+
3
+ [![Tests](https://github.com/advantch/vanty-payments/actions/workflows/tests.yml/badge.svg)](https://github.com/advantch/vanty-payments/actions/workflows/tests.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/vanty-payments)](https://pypi.org/project/vanty-payments/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/vanty-payments)](https://pypi.org/project/vanty-payments/)
6
+
7
+ Stripe-first payments toolkit for FastAPI with Tortoise ORM. Checkout, subscriptions, invoices, billing portal, webhooks, and full Stripe object sync in a single `pip install`.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ pip install vanty-payments
13
+ # or
14
+ uv pip install vanty-payments
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```python
20
+ from contextlib import asynccontextmanager
21
+
22
+ from fastapi import FastAPI
23
+
24
+ from vanty_payments import PaymentsKitSettings, mount_payments_router
25
+
26
+ settings = PaymentsKitSettings(
27
+ database_url="sqlite://./vanty-payments.db",
28
+ stripe_test_secret_key="sk_test_example",
29
+ stripe_webhook_secret="whsec_example",
30
+ )
31
+
32
+ app = FastAPI()
33
+ kit = mount_payments_router(app, settings=settings)
34
+
35
+
36
+ @asynccontextmanager
37
+ async def lifespan(_: FastAPI):
38
+ await kit.init_orm(generate_schemas=True)
39
+ try:
40
+ yield
41
+ finally:
42
+ await kit.close_orm()
43
+
44
+
45
+ app.router.lifespan_context = lifespan
46
+ ```
47
+
48
+ Run with `uvicorn main:app --reload` and visit `/docs` for the interactive API explorer.
49
+
50
+ ## Features
51
+
52
+ - **Checkout sessions** with Stripe-hosted and embedded flows
53
+ - **Subscription management** with plan changes, cancellation, and reactivation
54
+ - **Invoice management** with PDF links and payment status tracking
55
+ - **Billing portal** sessions for customer self-service
56
+ - **Payment method** management (cards, bank accounts)
57
+ - **Webhook ingestion** with signature verification and idempotent processing
58
+ - **Manual sync** to pull Stripe state into local models on demand
59
+ - **Full Stripe object parity** covering customers, products, prices, coupons, promotion codes, discounts, charges, refunds, disputes, and more
60
+ - **Admin management** endpoints for super-admin billing operations
61
+ - **Identity integration** with optional `vanty-auth` or custom identity resolvers
62
+
63
+ ## Architecture
64
+
65
+ `PaymentsKit` is a composition root that wires all services. Access services directly:
66
+
67
+ ```python
68
+ kit = mount_payments_router(app, settings=settings)
69
+
70
+ # Direct service access
71
+ await kit.checkout_service.create_session(customer_id=cid, price_id=pid)
72
+ await kit.subscription_service.list_subscriptions(customer_id=cid)
73
+ await kit.sync_service.sync_customer(stripe_customer_id="cus_xxx")
74
+ ```
75
+
76
+ Available services on `PaymentsKit`:
77
+
78
+ | Service | Purpose |
79
+ |---|---|
80
+ | `customer_service` | Customer bootstrap and management |
81
+ | `checkout_service` | Checkout session creation |
82
+ | `subscription_service` | Subscription reads and management |
83
+ | `invoice_service` | Invoice listing and retrieval |
84
+ | `payment_method_service` | Payment method listing |
85
+ | `portal_service` | Billing portal session creation |
86
+ | `webhook_service` | Webhook signature verification and dispatch |
87
+ | `sync_service` | Manual Stripe-to-local sync for all object types |
88
+ | `admin_service` | Super-admin billing operations |
89
+
90
+ ## Configuration
91
+
92
+ All settings are read from environment variables with the `PAYMENTS_KIT_` prefix, or passed directly to `PaymentsKitSettings`.
93
+
94
+ | Setting | Default | Description |
95
+ |---|---|---|
96
+ | `database_url` | `sqlite://./vanty-payments.db` | Tortoise ORM database URL |
97
+ | `stripe_test_secret_key` | — | Stripe test mode secret key |
98
+ | `stripe_live_secret_key` | — | Stripe live mode secret key |
99
+ | `stripe_webhook_secret` | — | Webhook endpoint signing secret |
100
+ | `stripe_mode` | `test` | `test` or `live` |
101
+ | `default_currency` | `usd` | Default currency for new prices |
102
+
103
+ Set via environment: `PAYMENTS_KIT_STRIPE_TEST_SECRET_KEY=sk_test_... PAYMENTS_KIT_DATABASE_URL=postgres://...`
104
+
105
+ ## API surface
106
+
107
+ ### Public routes (`/payments`)
108
+
109
+ | Method | Path | Description |
110
+ |---|---|---|
111
+ | `POST` | `/customers/bootstrap` | Create or retrieve a Stripe customer |
112
+ | `GET` | `/catalog/products` | List available products |
113
+ | `GET` | `/catalog/prices` | List prices for a product |
114
+ | `POST` | `/checkout/sessions` | Create a checkout session |
115
+ | `GET` | `/subscriptions` | List subscriptions |
116
+ | `GET` | `/subscriptions/{id}` | Get subscription details |
117
+ | `POST` | `/subscriptions/{id}/cancel` | Cancel a subscription |
118
+ | `POST` | `/portal/sessions` | Create a billing portal session |
119
+ | `GET` | `/invoices` | List invoices |
120
+ | `GET` | `/invoices/{id}` | Get invoice details |
121
+ | `GET` | `/payment-methods` | List payment methods |
122
+ | `POST` | `/webhooks/stripe` | Stripe webhook endpoint |
123
+ | `POST` | `/sync` | Trigger manual sync |
124
+
125
+ ### Admin routes (`/admin/payments`)
126
+
127
+ Super-admin endpoints for platform-wide billing management. Mount separately:
128
+
129
+ ```python
130
+ app.include_router(kit.admin_router, prefix="/admin/payments")
131
+ ```
132
+
133
+ ## Host app identity integration
134
+
135
+ The package works standalone, but a host app can supply a request-level identity adapter through `app.state.payments_identity_resolver`:
136
+
137
+ ```python
138
+ async def resolve_identity(request: Request) -> IdentityContext:
139
+ return IdentityContext(
140
+ user_reference=request.state.user_id,
141
+ organization_reference=request.state.org_id,
142
+ )
143
+
144
+ app.state.payments_identity_resolver = resolve_identity
145
+ ```
146
+
147
+ Routes then use those references automatically when request payloads omit them.
148
+
149
+ ## Project layout
150
+
151
+ ```text
152
+ src/vanty_payments/ Package source
153
+ docs/ Documentation
154
+ examples/reference-api/ Reference FastAPI application
155
+ tests/ pytest suite (unit + integration)
156
+ ```
157
+
158
+ ## Development
159
+
160
+ ```bash
161
+ git clone https://github.com/advantch/vanty-payments.git
162
+ cd vanty-payments
163
+ uv sync --dev
164
+
165
+ # Lint
166
+ uv run ruff check
167
+
168
+ # Test
169
+ uv run pytest -q
170
+
171
+ # Run reference API
172
+ cd examples/reference-api && uv run uvicorn main:app --reload
173
+ ```
174
+
175
+ Use `uv run pytest --no-cov tests/path/to/test.py` for targeted debugging without the coverage gate.
176
+
177
+ ## Releasing
178
+
179
+ Releases are automated via GitHub Actions. To publish a new version:
180
+
181
+ 1. Update the version in `pyproject.toml`:
182
+
183
+ ```toml
184
+ version = "0.2.0"
185
+ ```
186
+
187
+ 2. Commit and tag:
188
+
189
+ ```bash
190
+ git add pyproject.toml
191
+ git commit -m "release: v0.2.0"
192
+ git tag v0.2.0
193
+ git push origin main --tags
194
+ ```
195
+
196
+ 3. The `release.yml` workflow will automatically:
197
+ - Build the package
198
+ - Create a GitHub Release with auto-generated notes
199
+ - Publish to PyPI via trusted publishing (OIDC)
200
+
201
+ ### PyPI trusted publishing setup
202
+
203
+ To enable automated publishing, configure a trusted publisher on PyPI:
204
+
205
+ 1. Go to [pypi.org/manage/account/publishing](https://pypi.org/manage/account/publishing/)
206
+ 2. Add a new pending publisher (or update an existing project):
207
+ - **PyPI project name**: `vanty-payments`
208
+ - **Owner**: `advantch`
209
+ - **Repository**: `vanty-payments`
210
+ - **Workflow name**: `release.yml`
211
+ - **Environment name**: `release`
212
+
213
+ No API tokens are needed once trusted publishing is configured.
214
+
215
+ ## License
216
+
217
+ MIT
@@ -0,0 +1,21 @@
1
+ ---
2
+ title: Architecture
3
+ description: Feature-oriented payments package layout.
4
+ ---
5
+
6
+ # Architecture
7
+
8
+ `PaymentsKit` is the composition root. It wires:
9
+
10
+ - settings
11
+ - Stripe client wrapper
12
+ - host-app identity adapter boundary
13
+ - sync service
14
+ - customer, catalog, checkout, billing, and webhook services
15
+ - FastAPI router
16
+ - Tortoise ORM lifecycle
17
+
18
+ The transport boundary lives in `fastapi/`. Persisted models live in `db/models.py`.
19
+
20
+ `StripeCheckoutSession` is treated as an app-owned workflow record, while the
21
+ other Stripe-backed models primarily act as synced local cache records.
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: Data Model
3
+ description: Persisted Stripe-backed records.
4
+ ---
5
+
6
+ # Data Model
7
+
8
+ Persisted state lives in `db/models.py`.
9
+
10
+ Primary entities:
11
+
12
+ - `StripeCustomer`
13
+ - `StripeProduct`
14
+ - `StripePrice`
15
+ - `StripePaymentMethod`
16
+ - `StripePaymentIntent`
17
+ - `StripeSubscription`
18
+ - `StripeSubscriptionItem`
19
+ - `StripeInvoice`
20
+ - `StripeInvoiceLine`
21
+ - `StripeCheckoutSession`
22
+ - `StripeWebhookEvent`
23
+ - `StripeWebhookDelivery`
24
+ - `StripeSyncRun`
25
+
26
+ Expanded parity families also include:
27
+
28
+ - account/API key models
29
+ - coupon/promotion/discount/plan/subscription schedule models
30
+ - charge/refund/dispute/balance-transaction/payout models
31
+ - card/bank-account/source models
32
+ - connect models
33
+ - tax models
34
+ - entitlements models
35
+ - identity verification models
36
+ - issuing models
37
+ - radar and sigma models
38
+ - pricing table models
39
+
40
+ Every synced Stripe-backed model stores both normalized fields and raw `stripe_data_json`.
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Vanty Payments
3
+ description: Stripe-first payments package for FastAPI with local Tortoise ORM models.
4
+ ---
5
+
6
+ # Vanty Payments
7
+
8
+ `vanty-payments` is the Stripe-first sibling package to `vanty-auth`.
9
+
10
+ It follows the same high-level shape:
11
+
12
+ - one composition root (`PaymentsKit`)
13
+ - Pydantic settings (`PaymentsKitSettings`)
14
+ - thin `fastapi/` transport layer
15
+ - centralized `db/models.py`
16
+ - local SQLite-friendly setup for development