@mixrpay/merchant-sdk 0.1.0 → 0.2.0
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/README.md +186 -88
- package/dist/index.js +498 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +496 -3
- package/dist/index.mjs.map +1 -1
- package/dist/middleware/express.js +259 -1
- package/dist/middleware/express.js.map +1 -1
- package/dist/middleware/express.mjs +258 -1
- package/dist/middleware/express.mjs.map +1 -1
- package/dist/middleware/fastify.js +1 -1
- package/dist/middleware/fastify.js.map +1 -1
- package/dist/middleware/fastify.mjs +1 -1
- package/dist/middleware/fastify.mjs.map +1 -1
- package/dist/middleware/nextjs.js +238 -1
- package/dist/middleware/nextjs.js.map +1 -1
- package/dist/middleware/nextjs.mjs +237 -1
- package/dist/middleware/nextjs.mjs.map +1 -1
- package/package.json +4 -1
- package/dist/index.d.mts +0 -291
- package/dist/index.d.ts +0 -291
- package/dist/middleware/express.d.mts +0 -57
- package/dist/middleware/express.d.ts +0 -57
- package/dist/middleware/fastify.d.mts +0 -56
- package/dist/middleware/fastify.d.ts +0 -56
- package/dist/middleware/nextjs.d.mts +0 -78
- package/dist/middleware/nextjs.d.ts +0 -78
- package/dist/types-BJNy6Hhb.d.mts +0 -166
- package/dist/types-BJNy6Hhb.d.ts +0 -166
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mixrpay/merchant-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Accept payments from AI agents and web apps with one middleware. Supports session-based payments (Agent SDK, Widget) and x402 protocol.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -14,10 +14,14 @@ pnpm add @mixrpay/merchant-sdk
|
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
17
|
-
### 1. Set
|
|
17
|
+
### 1. Set Environment Variables
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
#
|
|
20
|
+
# .env
|
|
21
|
+
MIXRPAY_PUBLIC_KEY=pk_live_... # Your merchant public key
|
|
22
|
+
MIXRPAY_SECRET_KEY=sk_live_... # Your merchant secret key
|
|
23
|
+
|
|
24
|
+
# Optional: for x402 protocol support
|
|
21
25
|
MIXRPAY_MERCHANT_ADDRESS=0xYourWalletAddress
|
|
22
26
|
```
|
|
23
27
|
|
|
@@ -27,118 +31,166 @@ MIXRPAY_MERCHANT_ADDRESS=0xYourWalletAddress
|
|
|
27
31
|
|
|
28
32
|
```typescript
|
|
29
33
|
import express from 'express';
|
|
30
|
-
import {
|
|
34
|
+
import { mixrpay } from '@mixrpay/merchant-sdk/express';
|
|
31
35
|
|
|
32
36
|
const app = express();
|
|
33
37
|
|
|
34
|
-
//
|
|
35
|
-
app.post('/api/
|
|
36
|
-
//
|
|
37
|
-
const { payer,
|
|
38
|
+
// Accepts payments from Widget, Agent SDK, and x402 agents
|
|
39
|
+
app.post('/api/generate', mixrpay({ priceUsd: 0.05 }), (req, res) => {
|
|
40
|
+
// Payment verified! Access via req.mixrPayment
|
|
41
|
+
const { payer, amountUsd, method } = req.mixrPayment!;
|
|
38
42
|
|
|
39
|
-
console.log(`Payment
|
|
43
|
+
console.log(`Payment: $${amountUsd} via ${method} from ${payer}`);
|
|
40
44
|
|
|
41
|
-
const result =
|
|
45
|
+
const result = processRequest(req.body);
|
|
42
46
|
res.json(result);
|
|
43
47
|
});
|
|
44
48
|
|
|
45
49
|
// Dynamic pricing based on request
|
|
46
|
-
app.post('/api/
|
|
47
|
-
getPrice: (
|
|
50
|
+
app.post('/api/ai', mixrpay({
|
|
51
|
+
getPrice: (req) => req.body?.premium ? 0.10 : 0.05
|
|
48
52
|
}), handler);
|
|
49
53
|
```
|
|
50
54
|
|
|
51
55
|
#### Next.js (App Router)
|
|
52
56
|
|
|
53
57
|
```typescript
|
|
54
|
-
// app/api/
|
|
55
|
-
import {
|
|
58
|
+
// app/api/generate/route.ts
|
|
59
|
+
import { withMixrPay, MixrPayment } from '@mixrpay/merchant-sdk/nextjs';
|
|
56
60
|
import { NextRequest, NextResponse } from 'next/server';
|
|
57
61
|
|
|
58
|
-
async function handler(req: NextRequest, payment:
|
|
59
|
-
// payment contains: { payer,
|
|
60
|
-
console.log(`Paid by ${payment.payer}: $${payment.
|
|
62
|
+
async function handler(req: NextRequest, payment: MixrPayment) {
|
|
63
|
+
// payment contains: { payer, amountUsd, method, sessionId?, chargeId?, txHash? }
|
|
64
|
+
console.log(`Paid by ${payment.payer}: $${payment.amountUsd} via ${payment.method}`);
|
|
61
65
|
|
|
62
66
|
return NextResponse.json({ result: 'success' });
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
export const POST =
|
|
69
|
+
export const POST = withMixrPay({ priceUsd: 0.05 }, handler);
|
|
66
70
|
```
|
|
67
71
|
|
|
68
72
|
#### Fastify
|
|
69
73
|
|
|
70
74
|
```typescript
|
|
71
75
|
import Fastify from 'fastify';
|
|
72
|
-
import {
|
|
76
|
+
import { mixrpayPlugin, mixrpay } from '@mixrpay/merchant-sdk/fastify';
|
|
73
77
|
|
|
74
78
|
const app = Fastify();
|
|
75
79
|
|
|
76
80
|
// Register plugin with defaults
|
|
77
|
-
app.register(
|
|
78
|
-
|
|
81
|
+
app.register(mixrpayPlugin, {
|
|
82
|
+
publicKey: process.env.MIXRPAY_PUBLIC_KEY,
|
|
83
|
+
secretKey: process.env.MIXRPAY_SECRET_KEY,
|
|
79
84
|
});
|
|
80
85
|
|
|
81
86
|
// Use on routes
|
|
82
|
-
app.post('/api/
|
|
83
|
-
preHandler:
|
|
87
|
+
app.post('/api/generate', {
|
|
88
|
+
preHandler: mixrpay({ priceUsd: 0.05 })
|
|
84
89
|
}, async (req, reply) => {
|
|
85
|
-
return { result: 'success', payer: req.
|
|
90
|
+
return { result: 'success', payer: req.mixrPayment?.payer };
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Accepted Payment Methods
|
|
95
|
+
|
|
96
|
+
The middleware automatically handles **three payment methods**:
|
|
97
|
+
|
|
98
|
+
| Header | Source | Description |
|
|
99
|
+
|--------|--------|-------------|
|
|
100
|
+
| `X-Mixr-Session` | Agent SDK | Session-based payment (recommended for MixrPay clients) |
|
|
101
|
+
| `X-Mixr-Payment` | Widget | Widget payment proof JWT |
|
|
102
|
+
| `X-PAYMENT` | x402 | External agent payment via x402 protocol |
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
app.post('/api/generate', mixrpay({ priceUsd: 0.05 }), (req, res) => {
|
|
106
|
+
const { method } = req.mixrPayment!;
|
|
107
|
+
|
|
108
|
+
switch (method) {
|
|
109
|
+
case 'session':
|
|
110
|
+
console.log('Payment from Agent SDK');
|
|
111
|
+
break;
|
|
112
|
+
case 'widget':
|
|
113
|
+
console.log('Payment from Widget user');
|
|
114
|
+
break;
|
|
115
|
+
case 'x402':
|
|
116
|
+
console.log('Payment from external x402 agent');
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
res.json({ result: 'success' });
|
|
86
121
|
});
|
|
87
122
|
```
|
|
88
123
|
|
|
89
124
|
## How It Works
|
|
90
125
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
126
|
+
### Session-Based Flow (Agent SDK / Widget)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
Agent/User Your API MixrPay
|
|
130
|
+
│ │ │
|
|
131
|
+
│ 1. Request with │ │
|
|
132
|
+
│ X-Mixr-Session header │ │
|
|
133
|
+
├───────────────────────────▶│ │
|
|
134
|
+
│ │ 2. Validate session │
|
|
135
|
+
│ ├──────────────────────────▶│
|
|
136
|
+
│ │◀──────────────────────────┤
|
|
137
|
+
│ 3. Response │ │
|
|
138
|
+
│◀───────────────────────────┤ │
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### x402 Flow (External Agents)
|
|
97
142
|
|
|
98
143
|
```
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
144
|
+
Agent Your API Facilitator
|
|
145
|
+
│ │ │
|
|
146
|
+
│ 1. Request (no payment) │ │
|
|
147
|
+
├───────────────────────────▶│ │
|
|
148
|
+
│◀── 402 Payment Required ───┤ │
|
|
149
|
+
│ │ │
|
|
150
|
+
│ 2. Request with │ │
|
|
151
|
+
│ X-PAYMENT header │ │
|
|
152
|
+
├───────────────────────────▶│ │
|
|
153
|
+
│ │ 3. Verify & settle │
|
|
154
|
+
│ ├──────────────────────────▶│
|
|
155
|
+
│ │◀──────────────────────────┤
|
|
156
|
+
│ 4. Response │ │
|
|
157
|
+
│◀───────────────────────────┤ │
|
|
109
158
|
```
|
|
110
159
|
|
|
111
160
|
## Configuration Options
|
|
112
161
|
|
|
113
|
-
###
|
|
162
|
+
### MixrPayOptions
|
|
114
163
|
|
|
115
164
|
```typescript
|
|
116
|
-
interface
|
|
165
|
+
interface MixrPayOptions {
|
|
117
166
|
/** Price in USD (e.g., 0.05 for 5 cents) */
|
|
118
|
-
|
|
167
|
+
priceUsd?: number;
|
|
168
|
+
|
|
169
|
+
/** Dynamic pricing function */
|
|
170
|
+
getPrice?: (req: Request) => number | Promise<number>;
|
|
119
171
|
|
|
120
|
-
/** Your
|
|
121
|
-
|
|
172
|
+
/** Your public key (defaults to MIXRPAY_PUBLIC_KEY env var) */
|
|
173
|
+
publicKey?: string;
|
|
122
174
|
|
|
123
|
-
/**
|
|
124
|
-
|
|
175
|
+
/** Your secret key (defaults to MIXRPAY_SECRET_KEY env var) */
|
|
176
|
+
secretKey?: string;
|
|
125
177
|
|
|
126
|
-
/**
|
|
178
|
+
/** Wallet address for x402 (defaults to MIXRPAY_MERCHANT_ADDRESS env var) */
|
|
179
|
+
merchantAddress?: string;
|
|
180
|
+
|
|
181
|
+
/** x402 facilitator URL (default: https://x402.org/facilitator) */
|
|
127
182
|
facilitator?: string;
|
|
128
183
|
|
|
129
184
|
/** Description shown to payer */
|
|
130
185
|
description?: string;
|
|
131
186
|
|
|
132
|
-
/** Dynamic pricing function */
|
|
133
|
-
getPrice?: (context: PriceContext) => number | Promise<number>;
|
|
134
|
-
|
|
135
187
|
/** Callback after successful payment */
|
|
136
|
-
onPayment?: (payment:
|
|
188
|
+
onPayment?: (payment: MixrPayment) => void | Promise<void>;
|
|
137
189
|
|
|
138
190
|
/** Skip payment for certain requests */
|
|
139
|
-
skip?: (
|
|
191
|
+
skip?: (req: Request) => boolean | Promise<boolean>;
|
|
140
192
|
|
|
141
|
-
/** Test mode -
|
|
193
|
+
/** Test mode - accepts test payments */
|
|
142
194
|
testMode?: boolean;
|
|
143
195
|
}
|
|
144
196
|
```
|
|
@@ -146,21 +198,30 @@ interface X402Options {
|
|
|
146
198
|
### Payment Result
|
|
147
199
|
|
|
148
200
|
```typescript
|
|
149
|
-
interface
|
|
201
|
+
interface MixrPayment {
|
|
150
202
|
/** Whether payment is valid */
|
|
151
203
|
valid: boolean;
|
|
152
204
|
|
|
205
|
+
/** Payment method used */
|
|
206
|
+
method: 'session' | 'widget' | 'x402';
|
|
207
|
+
|
|
153
208
|
/** Payer's wallet address */
|
|
154
|
-
payer
|
|
209
|
+
payer: string;
|
|
155
210
|
|
|
156
211
|
/** Amount paid in USD */
|
|
157
|
-
|
|
212
|
+
amountUsd: number;
|
|
213
|
+
|
|
214
|
+
/** Session ID (for session-based payments) */
|
|
215
|
+
sessionId?: string;
|
|
158
216
|
|
|
159
|
-
/**
|
|
217
|
+
/** Charge record ID */
|
|
218
|
+
chargeId?: string;
|
|
219
|
+
|
|
220
|
+
/** Settlement transaction hash (for x402) */
|
|
160
221
|
txHash?: string;
|
|
161
222
|
|
|
162
|
-
/** When payment was
|
|
163
|
-
|
|
223
|
+
/** When payment was made */
|
|
224
|
+
timestamp: Date;
|
|
164
225
|
|
|
165
226
|
/** Error message if invalid */
|
|
166
227
|
error?: string;
|
|
@@ -172,9 +233,9 @@ interface X402PaymentResult {
|
|
|
172
233
|
### Dynamic Pricing
|
|
173
234
|
|
|
174
235
|
```typescript
|
|
175
|
-
app.post('/api/ai',
|
|
176
|
-
getPrice: async (
|
|
177
|
-
const { model, tokens } =
|
|
236
|
+
app.post('/api/ai', mixrpay({
|
|
237
|
+
getPrice: async (req) => {
|
|
238
|
+
const { model, tokens } = req.body;
|
|
178
239
|
|
|
179
240
|
// Price based on model and usage
|
|
180
241
|
const rates = { 'gpt-4': 0.03, 'gpt-3.5': 0.002 };
|
|
@@ -188,11 +249,12 @@ app.post('/api/ai', x402({
|
|
|
188
249
|
### Skip Payment for Certain Requests
|
|
189
250
|
|
|
190
251
|
```typescript
|
|
191
|
-
app.post('/api/query',
|
|
192
|
-
|
|
193
|
-
skip: (
|
|
252
|
+
app.post('/api/query', mixrpay({
|
|
253
|
+
priceUsd: 0.05,
|
|
254
|
+
skip: async (req) => {
|
|
194
255
|
// Free for authenticated premium users
|
|
195
|
-
|
|
256
|
+
const user = await getUser(req.headers.authorization);
|
|
257
|
+
return user?.isPremium || false;
|
|
196
258
|
}
|
|
197
259
|
}), handler);
|
|
198
260
|
```
|
|
@@ -200,52 +262,52 @@ app.post('/api/query', x402({
|
|
|
200
262
|
### Payment Callbacks
|
|
201
263
|
|
|
202
264
|
```typescript
|
|
203
|
-
app.post('/api/query',
|
|
204
|
-
|
|
265
|
+
app.post('/api/query', mixrpay({
|
|
266
|
+
priceUsd: 0.05,
|
|
205
267
|
onPayment: async (payment) => {
|
|
206
268
|
// Log to your analytics
|
|
207
269
|
await analytics.track('payment_received', {
|
|
208
270
|
payer: payment.payer,
|
|
209
|
-
amount: payment.
|
|
210
|
-
|
|
271
|
+
amount: payment.amountUsd,
|
|
272
|
+
method: payment.method,
|
|
211
273
|
});
|
|
212
274
|
|
|
213
275
|
// Store in database
|
|
214
276
|
await db.payments.create({
|
|
215
277
|
data: {
|
|
216
278
|
payer: payment.payer,
|
|
217
|
-
amount: payment.
|
|
218
|
-
|
|
279
|
+
amount: payment.amountUsd,
|
|
280
|
+
chargeId: payment.chargeId,
|
|
219
281
|
}
|
|
220
282
|
});
|
|
221
283
|
}
|
|
222
284
|
}), handler);
|
|
223
285
|
```
|
|
224
286
|
|
|
225
|
-
###
|
|
287
|
+
### Manual Verification
|
|
226
288
|
|
|
227
289
|
```typescript
|
|
228
|
-
import {
|
|
290
|
+
import { verifyMixrPayment } from '@mixrpay/merchant-sdk';
|
|
229
291
|
|
|
230
292
|
// Manual verification without middleware
|
|
231
|
-
const result = await
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
293
|
+
const result = await verifyMixrPayment(req.headers, {
|
|
294
|
+
publicKey: process.env.MIXRPAY_PUBLIC_KEY,
|
|
295
|
+
secretKey: process.env.MIXRPAY_SECRET_KEY,
|
|
296
|
+
expectedAmount: 0.05,
|
|
235
297
|
});
|
|
236
298
|
|
|
237
299
|
if (result.valid) {
|
|
238
|
-
console.log(`Valid payment from ${result.payer}`);
|
|
300
|
+
console.log(`Valid payment from ${result.payer} via ${result.method}`);
|
|
239
301
|
}
|
|
240
302
|
```
|
|
241
303
|
|
|
242
304
|
## Testing
|
|
243
305
|
|
|
244
|
-
Enable test mode to
|
|
306
|
+
Enable test mode to accept test payments during development:
|
|
245
307
|
|
|
246
308
|
```typescript
|
|
247
|
-
app.post('/api/query',
|
|
248
|
-
|
|
309
|
+
app.post('/api/query', mixrpay({
|
|
310
|
+
priceUsd: 0.05,
|
|
249
311
|
testMode: process.env.NODE_ENV !== 'production',
|
|
250
312
|
}), handler);
|
|
251
313
|
```
|
|
@@ -254,7 +316,9 @@ app.post('/api/query', x402({
|
|
|
254
316
|
|
|
255
317
|
| Variable | Description | Required |
|
|
256
318
|
|----------|-------------|----------|
|
|
257
|
-
| `
|
|
319
|
+
| `MIXRPAY_PUBLIC_KEY` | Your merchant public key (pk_...) | Yes |
|
|
320
|
+
| `MIXRPAY_SECRET_KEY` | Your merchant secret key | Yes |
|
|
321
|
+
| `MIXRPAY_MERCHANT_ADDRESS` | Wallet address for x402 payments | For x402 |
|
|
258
322
|
|
|
259
323
|
## Supported Chains
|
|
260
324
|
|
|
@@ -268,14 +332,20 @@ app.post('/api/query', x402({
|
|
|
268
332
|
The middleware returns appropriate HTTP status codes:
|
|
269
333
|
|
|
270
334
|
- `402 Payment Required` - No payment or invalid payment
|
|
335
|
+
- `403 Forbidden` - Session limit exceeded or revoked
|
|
271
336
|
- `500 Internal Server Error` - Configuration issues
|
|
272
337
|
|
|
273
338
|
Error responses include details:
|
|
274
339
|
|
|
275
340
|
```json
|
|
276
341
|
{
|
|
277
|
-
"error": "
|
|
278
|
-
"
|
|
342
|
+
"error": "payment_required",
|
|
343
|
+
"message": "No valid payment provided",
|
|
344
|
+
"paymentInfo": {
|
|
345
|
+
"priceUsd": 0.05,
|
|
346
|
+
"recipient": "0x...",
|
|
347
|
+
"acceptedMethods": ["X-Mixr-Session", "X-Mixr-Payment", "X-PAYMENT"]
|
|
348
|
+
}
|
|
279
349
|
}
|
|
280
350
|
```
|
|
281
351
|
|
|
@@ -284,10 +354,38 @@ Error responses include details:
|
|
|
284
354
|
Full TypeScript support with type definitions included.
|
|
285
355
|
|
|
286
356
|
```typescript
|
|
287
|
-
import type {
|
|
357
|
+
import type { MixrPayOptions, MixrPayment } from '@mixrpay/merchant-sdk';
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
### Widget Custom Elements (React/JSX)
|
|
361
|
+
|
|
362
|
+
If you're using the MixrPay widget with TypeScript and React, import the type declarations:
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
// In your app's entry file or a .d.ts file
|
|
366
|
+
import '@mixrpay/merchant-sdk/widget-elements';
|
|
367
|
+
|
|
368
|
+
// Now these work without TypeScript errors:
|
|
369
|
+
<mixr-balance data-theme="dark" />
|
|
370
|
+
<mixr-wallet />
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## Migration from x402-Only
|
|
374
|
+
|
|
375
|
+
If you were using the old x402-only middleware:
|
|
376
|
+
|
|
377
|
+
```typescript
|
|
378
|
+
// Before (x402 only)
|
|
379
|
+
import { x402 } from '@mixrpay/merchant-sdk/express';
|
|
380
|
+
app.post('/api/query', x402({ price: 0.05 }), handler);
|
|
381
|
+
|
|
382
|
+
// After (unified - backwards compatible)
|
|
383
|
+
import { mixrpay } from '@mixrpay/merchant-sdk/express';
|
|
384
|
+
app.post('/api/query', mixrpay({ priceUsd: 0.05 }), handler);
|
|
288
385
|
```
|
|
289
386
|
|
|
387
|
+
The new `mixrpay` middleware is backwards compatible—it still accepts x402 payments via `X-PAYMENT` header, but now also accepts session-based payments.
|
|
388
|
+
|
|
290
389
|
## License
|
|
291
390
|
|
|
292
391
|
MIT
|
|
293
|
-
|