@paykit-sdk/xendit 1.0.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 +177 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +4824 -0
- package/dist/index.mjs +4820 -0
- package/dist/schema.d.mts +192 -0
- package/dist/schema.d.ts +192 -0
- package/dist/schema.js +8 -0
- package/dist/schema.mjs +6 -0
- package/dist/utils/mapper.d.mts +34 -0
- package/dist/utils/mapper.d.ts +34 -0
- package/dist/utils/mapper.js +169 -0
- package/dist/utils/mapper.mjs +162 -0
- package/dist/xendit-provider.d.mts +50 -0
- package/dist/xendit-provider.d.ts +50 -0
- package/dist/xendit-provider.js +4806 -0
- package/dist/xendit-provider.mjs +4804 -0
- package/package.json +46 -0
package/README.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# @paykit-sdk/xendit
|
|
2
|
+
|
|
3
|
+
Xendit provider for PayKit.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @paykit-sdk/xendit
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @paykit-sdk/xendit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createEndpointHandlers, PayKit } from '@paykit-sdk/core';
|
|
17
|
+
import { xendit } from '@paykit-sdk/xendit';
|
|
18
|
+
|
|
19
|
+
export const paykit = new PayKit(xendit());
|
|
20
|
+
export const endpoints = createEndpointHandlers(paykit);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or with direct config:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { PayKit } from '@paykit-sdk/core';
|
|
27
|
+
import { createXendit } from '@paykit-sdk/xendit';
|
|
28
|
+
|
|
29
|
+
export const paykit = new PayKit(
|
|
30
|
+
createXendit({
|
|
31
|
+
secretKey: 'xnd_development_...',
|
|
32
|
+
isSandbox: true,
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Environment Variables
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
XENDIT_SECRET_KEY=xnd_development_...
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`isSandbox` is inferred from `NODE_ENV` — set `NODE_ENV=production` for live mode. Whether requests actually hit test or live data is determined by whether `XENDIT_SECRET_KEY` is a `xnd_development_` or `xnd_production_` key, not by `isSandbox` itself.
|
|
44
|
+
|
|
45
|
+
## Next.js API Route
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// app/api/paykit/[...endpoint]/route.ts
|
|
49
|
+
import { endpoints } from '@/lib/paykit';
|
|
50
|
+
import { EndpointPath } from '@paykit-sdk/core';
|
|
51
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
52
|
+
|
|
53
|
+
export async function POST(
|
|
54
|
+
request: NextRequest,
|
|
55
|
+
{ params }: { params: Promise<{ endpoint: string[] }> },
|
|
56
|
+
) {
|
|
57
|
+
const { endpoint: endpointArray } = await params;
|
|
58
|
+
const endpoint = ('/' + endpointArray.join('/')) as EndpointPath;
|
|
59
|
+
const handler = endpoints[endpoint];
|
|
60
|
+
|
|
61
|
+
if (!handler) {
|
|
62
|
+
return NextResponse.json(
|
|
63
|
+
{ message: 'Not found' },
|
|
64
|
+
{ status: 404 },
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const { args } = await request.json();
|
|
69
|
+
const result = await handler(...args);
|
|
70
|
+
return NextResponse.json({ result });
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Webhooks
|
|
75
|
+
|
|
76
|
+
Xendit verifies webhooks with a **Callback Verification Token** you copy from your Xendit dashboard — it's a plain string comparison via the `x-callback-token` header, not an HMAC signature.
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
// app/api/paykit/webhooks/route.ts
|
|
80
|
+
import { paykit } from '@/lib/paykit';
|
|
81
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
82
|
+
|
|
83
|
+
export async function POST(request: NextRequest) {
|
|
84
|
+
const body = await request.text();
|
|
85
|
+
|
|
86
|
+
const webhook = paykit.webhooks
|
|
87
|
+
.setup({ webhookSecret: process.env.XENDIT_CALLBACK_TOKEN! })
|
|
88
|
+
.on('payment.succeeded', async event => {
|
|
89
|
+
/* invoice status PAID/SETTLED, or a succeeded recurring cycle */
|
|
90
|
+
})
|
|
91
|
+
.on('payment.failed', async event => {
|
|
92
|
+
/* invoice status EXPIRED, or a failed recurring cycle */
|
|
93
|
+
})
|
|
94
|
+
.on('subscription.updated', async event => {
|
|
95
|
+
/* recurring.plan.activated */
|
|
96
|
+
})
|
|
97
|
+
.on('subscription.canceled', async event => {
|
|
98
|
+
/* recurring.plan.inactivated */
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
await webhook.handle({
|
|
102
|
+
body,
|
|
103
|
+
headersAsObject: Object.fromEntries(request.headers),
|
|
104
|
+
fullUrl: request.url,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return NextResponse.json({ received: true });
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Checkout
|
|
112
|
+
|
|
113
|
+
Xendit checkouts are built on hosted Invoices and require an email customer and amount/currency in `provider_metadata`:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const checkout = await paykit.checkouts.create({
|
|
117
|
+
customer: { email: 'user@example.com' },
|
|
118
|
+
item_id: 'plan_pro',
|
|
119
|
+
session_type: 'one_time',
|
|
120
|
+
quantity: 1,
|
|
121
|
+
success_url: 'https://example.com/success',
|
|
122
|
+
cancel_url: 'https://example.com/cancel',
|
|
123
|
+
provider_metadata: {
|
|
124
|
+
amount: '400',
|
|
125
|
+
currency: 'IDR',
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Redirect user to checkout.payment_url
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Subscriptions
|
|
133
|
+
|
|
134
|
+
Xendit's Recurring Plans API has no separate reusable plan template — each plan already carries its own amount/currency/schedule, and requires a pre-created Xendit customer id plus at least one saved payment token:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const subscription = await paykit.subscriptions.create({
|
|
138
|
+
customer: { id: 'cust_xendit_id' },
|
|
139
|
+
item_id: 'My Newspaper Subscription',
|
|
140
|
+
quantity: 1,
|
|
141
|
+
billing_interval: 'month',
|
|
142
|
+
amount: 50000,
|
|
143
|
+
currency: 'IDR',
|
|
144
|
+
metadata: null,
|
|
145
|
+
provider_metadata: {
|
|
146
|
+
payment_tokens: [{ payment_token_id: 'pt-...', rank: 1 }],
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Refunds
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const refund = await paykit.refunds.create({
|
|
155
|
+
payment_id: 'invoice_id_from_the_original_checkout',
|
|
156
|
+
amount: 400,
|
|
157
|
+
reason: 'requested_by_customer',
|
|
158
|
+
metadata: null,
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Unsupported
|
|
163
|
+
|
|
164
|
+
Xendit has no delete-customer API and no manual payment-capture API — `deleteCustomer` and `capturePayment` throw `ProviderNotSupportedError`. Use `cancelPayment` to expire a pending invoice instead.
|
|
165
|
+
|
|
166
|
+
## Documentation
|
|
167
|
+
|
|
168
|
+
Full docs at [docs.usepaykit.com/providers/xendit](https://docs.usepaykit.com/providers/xendit).
|
|
169
|
+
|
|
170
|
+
## Support
|
|
171
|
+
|
|
172
|
+
- [Xendit Documentation](https://docs.xendit.co)
|
|
173
|
+
- [PayKit Issues](https://github.com/usepaykit/paykit-sdk/issues)
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
ISC
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { XenditOptions, XenditProvider } from './xendit-provider.mjs';
|
|
2
|
+
import '@paykit-sdk/core';
|
|
3
|
+
import './schema.mjs';
|
|
4
|
+
|
|
5
|
+
declare const createXendit: (config: XenditOptions) => XenditProvider;
|
|
6
|
+
declare const xendit: () => XenditProvider;
|
|
7
|
+
|
|
8
|
+
export { XenditOptions, XenditProvider, createXendit, xendit };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { XenditOptions, XenditProvider } from './xendit-provider.js';
|
|
2
|
+
import '@paykit-sdk/core';
|
|
3
|
+
import './schema.js';
|
|
4
|
+
|
|
5
|
+
declare const createXendit: (config: XenditOptions) => XenditProvider;
|
|
6
|
+
declare const xendit: () => XenditProvider;
|
|
7
|
+
|
|
8
|
+
export { XenditOptions, XenditProvider, createXendit, xendit };
|