@86d-app/payments 0.0.3

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.
package/AGENTS.md ADDED
@@ -0,0 +1,47 @@
1
+ # payments module
2
+
3
+ Provider-agnostic payment processing module. Tracks payment intents, saved payment methods, and refunds locally. Delegates actual payment processing to a configurable `PaymentProvider` (e.g. Stripe).
4
+
5
+ ## Architecture
6
+
7
+ - `schema.ts` — `paymentIntent`, `paymentMethod`, `refund` entities
8
+ - `service.ts` — `PaymentController`, `PaymentProvider`, `PaymentIntent`, `PaymentMethod`, `Refund` types
9
+ - `service-impl.ts` — `createPaymentController(data, provider?)` factory
10
+ - `endpoints/store/` — customer-facing endpoints (create/confirm/cancel intent, manage payment methods)
11
+ - `endpoints/admin/` — admin endpoints (list, get, refund)
12
+
13
+ ## PaymentProvider Interface
14
+
15
+ Users plug in a provider by implementing `PaymentProvider`:
16
+ - `createIntent(params)` — returns `{ providerIntentId, status, providerMetadata? }`
17
+ - `confirmIntent(providerIntentId)` — returns updated status
18
+ - `cancelIntent(providerIntentId)` — returns cancelled status
19
+ - `createRefund(params)` — returns `{ providerRefundId, status, providerMetadata? }`
20
+
21
+ The module works without a provider (offline mode) — intents are stored with `pending` status and transitions are handled locally.
22
+
23
+ ## Store Endpoints
24
+
25
+ | Method | Path | Description |
26
+ |--------|------|-------------|
27
+ | POST | `/payments/intents` | Create payment intent |
28
+ | GET | `/payments/intents/:id` | Get intent by ID |
29
+ | POST | `/payments/intents/:id/confirm` | Confirm payment |
30
+ | POST | `/payments/intents/:id/cancel` | Cancel payment |
31
+ | GET | `/payments/methods` | List customer's payment methods |
32
+ | DELETE | `/payments/methods/:id` | Delete a payment method |
33
+
34
+ ## Admin Endpoints
35
+
36
+ | Method | Path | Description |
37
+ |--------|------|-------------|
38
+ | GET | `/admin/payments` | List all intents (filter: customerId, status, orderId) |
39
+ | GET | `/admin/payments/:id` | Get intent detail |
40
+ | POST | `/admin/payments/:id/refund` | Create refund |
41
+ | GET | `/admin/payments/:id/refunds` | List refunds for intent |
42
+
43
+ ## Tests (34 tests)
44
+
45
+ Run: `bun test` from this directory.
46
+
47
+ Covers: createIntent, getIntent, confirmIntent, cancelIntent, listIntents, savePaymentMethod, getPaymentMethod, listPaymentMethods, deletePaymentMethod, createRefund, getRefund, listRefunds — all with and without provider.
package/README.md ADDED
@@ -0,0 +1,261 @@
1
+ <p align="center">
2
+ <a href="https://86d.app">
3
+ <img src="https://86d.app/logo" height="96" alt="86d" />
4
+ </a>
5
+ </p>
6
+
7
+ <p align="center">
8
+ Dynamic Commerce
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://vercel.com/changelog"><strong>npm</strong></a> ·
13
+ <a href="https://x.com/86d_app"><strong>X</strong></a> ·
14
+ <a href="https://vercel.com/templates"><strong>LinkedIn</strong></a>
15
+ </p>
16
+ <br/>
17
+
18
+ > [!WARNING]
19
+ > This project is under active development and is not ready for production use. Please proceed with caution. Use at your own risk.
20
+
21
+ # @86d-app/payments
22
+
23
+ Provider-agnostic payment processing for the 86d commerce platform. Tracks payment intents, saved payment methods, and refunds locally. Delegates actual processing to a configurable `PaymentProvider` (Stripe, Square, PayPal, etc.).
24
+
25
+ ![version](https://img.shields.io/badge/version-0.0.1-blue) ![license](https://img.shields.io/badge/license-MIT-green)
26
+
27
+ ## Installation
28
+
29
+ ```sh
30
+ npm install @86d-app/payments
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ ```ts
36
+ import payments from "@86d-app/payments";
37
+ import { createModuleClient } from "@86d-app/core";
38
+
39
+ // Without a provider (offline/test mode)
40
+ const client = createModuleClient([payments()]);
41
+
42
+ // With a Stripe provider
43
+ import { StripePaymentProvider } from "@86d-app/stripe";
44
+ const provider = new StripePaymentProvider("sk_live_...");
45
+ const client = createModuleClient([payments({ provider, currency: "USD" })]);
46
+ ```
47
+
48
+ ## Configuration
49
+
50
+ | Option | Type | Default | Description |
51
+ |---|---|---|---|
52
+ | `currency` | `string` | `"USD"` | Default currency for payment intents |
53
+ | `provider` | `PaymentProvider` | `undefined` | Payment processor implementation |
54
+
55
+ ## PaymentProvider Interface
56
+
57
+ Implement this interface to connect any payment processor:
58
+
59
+ ```ts
60
+ interface PaymentProvider {
61
+ createIntent(params: {
62
+ amount: number; // in smallest currency unit (e.g. cents)
63
+ currency: string;
64
+ metadata?: Record<string, unknown>;
65
+ }): Promise<ProviderIntentResult>;
66
+
67
+ confirmIntent(providerIntentId: string): Promise<ProviderIntentResult>;
68
+
69
+ cancelIntent(providerIntentId: string): Promise<ProviderIntentResult>;
70
+
71
+ createRefund(params: {
72
+ providerIntentId: string;
73
+ amount?: number; // partial refund; omit for full refund
74
+ reason?: string;
75
+ }): Promise<ProviderRefundResult>;
76
+ }
77
+ ```
78
+
79
+ **Offline mode:** If no provider is configured, intents are stored locally with `pending` status and status transitions are handled in-memory. Useful for testing and development.
80
+
81
+ ## Store Endpoints
82
+
83
+ | Method | Path | Description |
84
+ |---|---|---|
85
+ | `POST` | `/payments/intents` | Create a payment intent |
86
+ | `GET` | `/payments/intents/:id` | Get intent by ID |
87
+ | `POST` | `/payments/intents/:id/confirm` | Confirm payment |
88
+ | `POST` | `/payments/intents/:id/cancel` | Cancel payment |
89
+ | `GET` | `/payments/methods` | List customer's saved payment methods |
90
+ | `DELETE` | `/payments/methods/:id` | Delete a payment method |
91
+
92
+ ## Admin Endpoints
93
+
94
+ | Method | Path | Description |
95
+ |---|---|---|
96
+ | `GET` | `/admin/payments` | List all intents (filter: `customerId`, `status`, `orderId`) |
97
+ | `GET` | `/admin/payments/:id` | Get intent detail |
98
+ | `POST` | `/admin/payments/:id/refund` | Issue a refund |
99
+ | `GET` | `/admin/payments/:id/refunds` | List refunds for an intent |
100
+
101
+ ## Controller API
102
+
103
+ ```ts
104
+ // ── Payment intents ─────────────────────────────────────────────────────────
105
+
106
+ controller.createIntent(params: {
107
+ amount: number; // in smallest currency unit (e.g. cents)
108
+ currency?: string; // default: module currency option
109
+ customerId?: string;
110
+ email?: string;
111
+ orderId?: string;
112
+ checkoutSessionId?: string;
113
+ metadata?: Record<string, unknown>;
114
+ }): Promise<PaymentIntent>
115
+
116
+ controller.getIntent(id: string): Promise<PaymentIntent | null>
117
+
118
+ controller.confirmIntent(id: string): Promise<PaymentIntent | null>
119
+
120
+ controller.cancelIntent(id: string): Promise<PaymentIntent | null>
121
+
122
+ controller.listIntents(params?: {
123
+ customerId?: string;
124
+ status?: PaymentIntentStatus;
125
+ orderId?: string;
126
+ take?: number;
127
+ skip?: number;
128
+ }): Promise<PaymentIntent[]>
129
+
130
+ // ── Payment methods ─────────────────────────────────────────────────────────
131
+
132
+ // Saves a payment method; if isDefault=true, clears all other defaults
133
+ controller.savePaymentMethod(params: {
134
+ customerId: string;
135
+ providerMethodId: string; // e.g. Stripe's pm_xxx
136
+ type?: string; // "card" | "bank_transfer" | "wallet"
137
+ last4?: string;
138
+ brand?: string; // "visa" | "mastercard" | etc.
139
+ expiryMonth?: number;
140
+ expiryYear?: number;
141
+ isDefault?: boolean;
142
+ }): Promise<PaymentMethod>
143
+
144
+ controller.getPaymentMethod(id: string): Promise<PaymentMethod | null>
145
+
146
+ controller.listPaymentMethods(customerId: string): Promise<PaymentMethod[]>
147
+
148
+ controller.deletePaymentMethod(id: string): Promise<boolean>
149
+
150
+ // ── Refunds ─────────────────────────────────────────────────────────────────
151
+
152
+ // Throws if payment intent not found; marks intent status as "refunded"
153
+ controller.createRefund(params: {
154
+ intentId: string;
155
+ amount?: number; // omit for full refund
156
+ reason?: string;
157
+ }): Promise<Refund>
158
+
159
+ controller.getRefund(id: string): Promise<Refund | null>
160
+
161
+ controller.listRefunds(intentId: string): Promise<Refund[]>
162
+ ```
163
+
164
+ ## Example: Checkout Payment Flow
165
+
166
+ ```ts
167
+ // 1. Customer initiates checkout — create intent
168
+ const intent = await controller.createIntent({
169
+ amount: 4999, // $49.99
170
+ currency: "USD",
171
+ customerId: "cust_123",
172
+ orderId: "ord_456",
173
+ });
174
+ // intent.status === "pending"
175
+ // With Stripe: intent.providerMetadata.clientSecret → send to frontend
176
+
177
+ // 2. Customer completes payment on frontend → call confirm
178
+ const confirmed = await controller.confirmIntent(intent.id);
179
+ // confirmed.status === "succeeded"
180
+
181
+ // 3. Customer requests refund
182
+ const refund = await controller.createRefund({
183
+ intentId: intent.id,
184
+ reason: "customer request",
185
+ });
186
+ // refund.status === "succeeded"
187
+ // intent.status is now "refunded"
188
+
189
+ // 4. Save a payment method for future use
190
+ const method = await controller.savePaymentMethod({
191
+ customerId: "cust_123",
192
+ providerMethodId: "pm_stripe_xxx",
193
+ type: "card",
194
+ last4: "4242",
195
+ brand: "visa",
196
+ isDefault: true,
197
+ });
198
+ ```
199
+
200
+ ## Payment Intent Statuses
201
+
202
+ | Status | Description |
203
+ |---|---|
204
+ | `pending` | Intent created, payment not yet initiated |
205
+ | `processing` | Payment is being processed |
206
+ | `succeeded` | Payment completed successfully |
207
+ | `failed` | Payment failed |
208
+ | `cancelled` | Intent was cancelled |
209
+ | `refunded` | Payment has been refunded |
210
+
211
+ ## Types
212
+
213
+ ```ts
214
+ type PaymentIntentStatus =
215
+ | "pending" | "processing" | "succeeded"
216
+ | "failed" | "cancelled" | "refunded";
217
+
218
+ type RefundStatus = "pending" | "succeeded" | "failed";
219
+
220
+ interface PaymentIntent {
221
+ id: string;
222
+ providerIntentId?: string; // e.g. Stripe's pi_xxx
223
+ customerId?: string;
224
+ email?: string;
225
+ amount: number;
226
+ currency: string;
227
+ status: PaymentIntentStatus;
228
+ paymentMethodId?: string;
229
+ orderId?: string;
230
+ checkoutSessionId?: string;
231
+ metadata: Record<string, unknown>;
232
+ providerMetadata: Record<string, unknown>;
233
+ createdAt: Date;
234
+ updatedAt: Date;
235
+ }
236
+
237
+ interface PaymentMethod {
238
+ id: string;
239
+ customerId: string;
240
+ providerMethodId: string;
241
+ type: string;
242
+ last4?: string;
243
+ brand?: string;
244
+ expiryMonth?: number;
245
+ expiryYear?: number;
246
+ isDefault: boolean;
247
+ createdAt: Date;
248
+ updatedAt: Date;
249
+ }
250
+
251
+ interface Refund {
252
+ id: string;
253
+ paymentIntentId: string;
254
+ providerRefundId: string;
255
+ amount: number;
256
+ reason?: string;
257
+ status: RefundStatus;
258
+ createdAt: Date;
259
+ updatedAt: Date;
260
+ }
261
+ ```
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@86d-app/payments",
3
+ "version": "0.0.3",
4
+ "description": "Payment processing abstraction for 86d commerce platform",
5
+ "keywords": [
6
+ "commerce",
7
+ "payments",
8
+ "payment-intents",
9
+ "refunds",
10
+ "86d"
11
+ ],
12
+ "license": "MIT",
13
+ "author": "86d <chat@86d.app>",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/86d-app/86d.git",
17
+ "directory": "modules/payments"
18
+ },
19
+ "homepage": "https://github.com/86d-app/86d/tree/main/modules/payments",
20
+ "type": "module",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./src/index.ts",
24
+ "import": "./src/index.ts",
25
+ "default": "./src/index.ts"
26
+ },
27
+ "./admin-components": "./src/admin/components",
28
+ "./*": "./src/*"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "check": "biome check src",
33
+ "check:fix": "biome check --write src",
34
+ "clean": "git clean -xdf .cache .turbo dist node_modules",
35
+ "dev": "tsc",
36
+ "test": "vitest run",
37
+ "test:watch": "vitest watch",
38
+ "typecheck": "tsc --noEmit --emitDeclarationOnly false"
39
+ },
40
+ "dependencies": {
41
+ "@86d-app/core": "workspace:*"
42
+ },
43
+ "devDependencies": {
44
+ "@biomejs/biome": "catalog:",
45
+ "@types/react": "catalog:react",
46
+ "typescript": "catalog:",
47
+ "vitest": "catalog:vite"
48
+ }
49
+ }