@lacspace/khalti 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/LICENSE +51 -0
- package/README.md +107 -0
- package/dist/index.cjs +57 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +105 -0
- package/dist/index.d.ts +105 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Lacspace Free Licence
|
|
2
|
+
Version 1.0, August 2026
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 Lacspace
|
|
5
|
+
|
|
6
|
+
PREAMBLE
|
|
7
|
+
|
|
8
|
+
This software is published by Lacspace under the Lacspace Free Licence โ a free,
|
|
9
|
+
permissive licence that lets you use this software for any purpose, including in
|
|
10
|
+
commercial products and services, at no cost. It grants the same freedoms as
|
|
11
|
+
common permissive open-source licences; the only condition is that this notice
|
|
12
|
+
travels with the software. The canonical, always-current text of this licence is
|
|
13
|
+
maintained at https://lacspace.com/licenses/lacspace-free-1.0
|
|
14
|
+
|
|
15
|
+
GRANT OF RIGHTS
|
|
16
|
+
|
|
17
|
+
Permission is hereby granted, free of charge, to any person or organisation
|
|
18
|
+
obtaining a copy of this software and its associated documentation and data files
|
|
19
|
+
(the "Software"), to deal in the Software without restriction, including without
|
|
20
|
+
limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
21
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
|
22
|
+
Software is furnished to do so, subject to the conditions below. These rights are
|
|
23
|
+
granted for any purpose, personal or commercial, and are perpetual, worldwide,
|
|
24
|
+
non-exclusive, and royalty-free.
|
|
25
|
+
|
|
26
|
+
CONDITIONS
|
|
27
|
+
|
|
28
|
+
The above copyright notice, this permission notice, and the name of this licence
|
|
29
|
+
("Lacspace Free Licence") shall be included in all copies or substantial portions
|
|
30
|
+
of the Software.
|
|
31
|
+
|
|
32
|
+
TRADEMARKS
|
|
33
|
+
|
|
34
|
+
This licence does not grant permission to use the trade names, trademarks, service
|
|
35
|
+
marks, logos, or product names of Lacspace, except as required to reproduce the
|
|
36
|
+
notice above or to describe the origin of the Software in a truthful manner.
|
|
37
|
+
|
|
38
|
+
DISCLAIMER OF WARRANTY AND LIMITATION OF LIABILITY
|
|
39
|
+
|
|
40
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
41
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
42
|
+
FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
43
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN
|
|
44
|
+
AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
|
|
45
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
The Lacspace Free Licence is a source-available, permissive licence and is not (as
|
|
50
|
+
of this version) an OSI-approved licence. In substance it grants the same freedoms
|
|
51
|
+
as the MIT Licence. Learn more at https://lacspace.com/licenses
|
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# @lacspace/khalti
|
|
4
|
+
|
|
5
|
+
**Khalti KPG-2 (ePayment API v2, Nepal) โ initiate payments, look up status, typed errors and `Key` auth over `fetch`.**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@lacspace/khalti)
|
|
8
|
+
[](https://packagephobia.com/result?p=@lacspace/khalti)
|
|
9
|
+
[](https://bundlephobia.com/package/@lacspace/khalti)
|
|
10
|
+
[](https://www.npmjs.com/package/@lacspace/khalti)
|
|
11
|
+
[](https://github.com/lacspace/npm-packages/blob/main/LICENSE)
|
|
12
|
+
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
> A tiny, fully-typed client for **Khalti**'s KPG-2 (ePayment API v2) โ Nepal's leading digital wallet. Two calls: `initiate()` to start a payment and get a redirect URL, and `lookup()` to verify the real status by `pidx`. Amounts in **paisa**, `Authorization: Key` auth, and Khalti's error bodies surfaced as a typed `KhaltiError`. Zero dependencies, isomorphic, injectable `fetch`.
|
|
16
|
+
|
|
17
|
+
- ๐ **`initiate()`** โ create a payment, get back `pidx` + `payment_url` to redirect to
|
|
18
|
+
- ๐ **`lookup()`** โ the source of truth: verify status by `pidx` after the customer returns
|
|
19
|
+
- ๐งจ **Typed errors** โ non-2xx responses throw `KhaltiError` with `status` + parsed `detail`
|
|
20
|
+
- ๐ Server-side `Authorization: Key <secretKey>` ยท amounts in paisa (integer)
|
|
21
|
+
- โก Isomorphic โ Node 20+, edge runtimes & browsers via global `fetch` (injectable) ยท ๐ฆ ESM + CJS ยท zero deps
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install @lacspace/khalti # or pnpm add / yarn add / bun add
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Initiate a payment
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { initiate } from "@lacspace/khalti";
|
|
33
|
+
|
|
34
|
+
const { payment_url, pidx } = await initiate(
|
|
35
|
+
{
|
|
36
|
+
return_url: "https://myshop.np/khalti/return",
|
|
37
|
+
website_url: "https://myshop.np",
|
|
38
|
+
amount: 1000, // NPR 10, in paisa
|
|
39
|
+
purchase_order_id: "order-42",
|
|
40
|
+
purchase_order_name: "Test order",
|
|
41
|
+
customer_info: { name: "Ram", email: "ram@example.com", phone: "9800000000" },
|
|
42
|
+
},
|
|
43
|
+
{ secretKey: process.env.KHALTI_SECRET!, env: "test" },
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// redirect the customer to payment_url; keep pidx to verify later.
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Verify with lookup (never trust the callback alone)
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { lookup } from "@lacspace/khalti";
|
|
53
|
+
|
|
54
|
+
const r = await lookup(pidx, { secretKey: process.env.KHALTI_SECRET!, env: "test" });
|
|
55
|
+
if (r.status === "Completed") {
|
|
56
|
+
fulfilOrder(r.transaction_id);
|
|
57
|
+
}
|
|
58
|
+
// status: "Completed" | "Pending" | "Initiated" | "Refunded" | "Expired" | "User canceled" | "Partially Refunded"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Handle errors
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { initiate, KhaltiError } from "@lacspace/khalti";
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
await initiate(payload, { secretKey });
|
|
68
|
+
} catch (e) {
|
|
69
|
+
if (e instanceof KhaltiError) {
|
|
70
|
+
console.error(e.status, e.detail); // e.g. 400, "Amount should be greater than Rs. 1."
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## API
|
|
76
|
+
|
|
77
|
+
| Export | Description |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `initiate(payload, { secretKey, env?, fetch? })` | POST `/epayment/initiate/` โ `{ pidx, payment_url, expires_at, expires_in }` |
|
|
80
|
+
| `lookup(pidx, { secretKey, env?, fetch? })` | POST `/epayment/lookup/` โ `{ pidx, total_amount, status, transaction_id, fee, refunded }` |
|
|
81
|
+
| `KhaltiError` | thrown on non-2xx โ `status` + parsed `detail` |
|
|
82
|
+
| `KhaltiStatus` | union of Khalti payment statuses |
|
|
83
|
+
| `KHALTI_BASE_URLS` | `{ test, prod }` base-URL map |
|
|
84
|
+
|
|
85
|
+
`env` is `"test"` (default, `a.khalti.com`) or `"prod"` (`khalti.com`). All amounts are in **paisa** (NPR 10 โ `1000`).
|
|
86
|
+
|
|
87
|
+
## Licensing
|
|
88
|
+
|
|
89
|
+
This package is **free** under the **[Lacspace Free Licence](https://lacspace.com/licenses/lacspace-free-1.0)** โ permissive freedoms. Use it in personal and commercial projects at no cost; just keep the notice.
|
|
90
|
+
|
|
91
|
+
Not every Lacspace package is free. We also offer **Commercial** (paid), **Client-specific**, and **Private** (proprietary) packages under separate terms. See the full **[Lacspace Licence Centre](https://lacspace.com/licenses)**.
|
|
92
|
+
|
|
93
|
+
<!-- LACSPACE-DEV-PLATFORM -->
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## The Lacspace Developer Platform
|
|
98
|
+
|
|
99
|
+
`@lacspace/khalti` is part of **63+ zero-dependency, isomorphic TypeScript packages**. Explore the ecosystem:
|
|
100
|
+
|
|
101
|
+
- ๐๏ธ **All packages** โ https://developer.lacspace.com/packages
|
|
102
|
+
- ๐งญ **Developer handbook** โ https://developer.lacspace.com/handbook
|
|
103
|
+
- ๐งช **Live playground** โ https://developer.lacspace.com/playground
|
|
104
|
+
- ๐ฅ๏ธ **Finished app templates** โ https://templates.lacspace.com
|
|
105
|
+
- ๐ **Scaffold a full app** โ `npm create lacspace-app@latest`
|
|
106
|
+
|
|
107
|
+
Free under the **[Lacspace Free Licence](https://lacspace.com/licenses/lacspace-free-1.0)** โ a permissive, free-to-use licence.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
var KHALTI_BASE_URLS = {
|
|
5
|
+
test: "https://a.khalti.com/api/v2",
|
|
6
|
+
prod: "https://khalti.com/api/v2"
|
|
7
|
+
};
|
|
8
|
+
var KhaltiError = class _KhaltiError extends Error {
|
|
9
|
+
constructor(message, status, detail) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "KhaltiError";
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.detail = detail;
|
|
14
|
+
Object.setPrototypeOf(this, _KhaltiError.prototype);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
async function post(path, body, opts) {
|
|
18
|
+
const base = KHALTI_BASE_URLS[opts.env ?? "test"];
|
|
19
|
+
const doFetch = opts.fetch ?? globalThis.fetch;
|
|
20
|
+
if (!doFetch) throw new Error("@lacspace/khalti: global fetch is unavailable; pass opts.fetch.");
|
|
21
|
+
const res = await doFetch(`${base}${path}`, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: {
|
|
24
|
+
Authorization: `Key ${opts.secretKey}`,
|
|
25
|
+
"Content-Type": "application/json"
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify(body)
|
|
28
|
+
});
|
|
29
|
+
let parsed = void 0;
|
|
30
|
+
const text = await res.text();
|
|
31
|
+
if (text) {
|
|
32
|
+
try {
|
|
33
|
+
parsed = JSON.parse(text);
|
|
34
|
+
} catch {
|
|
35
|
+
parsed = text;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
const detail = parsed && typeof parsed === "object" && "detail" in parsed ? parsed.detail : parsed;
|
|
40
|
+
const message = typeof detail === "string" ? detail : `Khalti request failed with status ${res.status}`;
|
|
41
|
+
throw new KhaltiError(message, res.status, detail);
|
|
42
|
+
}
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
async function initiate(payload, opts) {
|
|
46
|
+
return post("/epayment/initiate/", payload, opts);
|
|
47
|
+
}
|
|
48
|
+
async function lookup(pidx, opts) {
|
|
49
|
+
return post("/epayment/lookup/", { pidx }, opts);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
exports.KHALTI_BASE_URLS = KHALTI_BASE_URLS;
|
|
53
|
+
exports.KhaltiError = KhaltiError;
|
|
54
|
+
exports.initiate = initiate;
|
|
55
|
+
exports.lookup = lookup;
|
|
56
|
+
//# sourceMappingURL=index.cjs.map
|
|
57
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;AA0BO,IAAM,gBAAA,GAA8C;AAAA,EACzD,IAAA,EAAM,6BAAA;AAAA,EACN,IAAA,EAAM;AACR;AAqEO,IAAM,WAAA,GAAN,MAAM,YAAA,SAAoB,KAAA,CAAM;AAAA,EAMrC,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,MAAA,EAAiB;AAC5D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAEd,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,YAAA,CAAY,SAAS,CAAA;AAAA,EACnD;AACF;AAMA,eAAe,IAAA,CAAQ,IAAA,EAAc,IAAA,EAAe,IAAA,EAAoC;AACtF,EAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,IAAA,CAAK,GAAA,IAAO,MAAM,CAAA;AAChD,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,IAAS,UAAA,CAAW,KAAA;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,iEAAiE,CAAA;AAE/F,EAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,GAAG,IAAI,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,IAC1C,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,aAAA,EAAe,CAAA,IAAA,EAAO,IAAA,CAAK,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,GAC1B,CAAA;AAED,EAAA,IAAI,MAAA,GAAkB,MAAA;AACtB,EAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AACN,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,IAAA,MAAM,MAAA,GACJ,UAAU,OAAO,MAAA,KAAW,YAAY,QAAA,IAAa,MAAA,GAChD,OAAmC,MAAA,GACpC,MAAA;AACN,IAAA,MAAM,UACJ,OAAO,MAAA,KAAW,WAAW,MAAA,GAAS,CAAA,kCAAA,EAAqC,IAAI,MAAM,CAAA,CAAA;AACvF,IAAA,MAAM,IAAI,WAAA,CAAY,OAAA,EAAS,GAAA,CAAI,QAAQ,MAAM,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,MAAA;AACT;AAsBA,eAAsB,QAAA,CACpB,SACA,IAAA,EAC2B;AAC3B,EAAA,OAAO,IAAA,CAAuB,qBAAA,EAAuB,OAAA,EAAS,IAAI,CAAA;AACpE;AAUA,eAAsB,MAAA,CAAO,MAAc,IAAA,EAAiD;AAC1F,EAAA,OAAO,IAAA,CAAqB,mBAAA,EAAqB,EAAE,IAAA,IAAQ,IAAI,CAAA;AACjE","file":"index.cjs","sourcesContent":["/**\n * @lacspace/khalti\n *\n * Khalti KPG-2 (ePayment API v2, Nepal) โ a tiny, typed client for the two calls\n * every integration needs:\n *\n * 1. **initiate** โ create a payment and get back a `payment_url` to redirect\n * the customer to, plus a `pidx` to track it.\n * 2. **lookup** โ the source of truth: check a payment's real status by\n * `pidx` after the customer returns (never trust the callback alone).\n *\n * Amounts are always in **paisa** (integer): NPR 10 โ `1000`. Authentication is\n * a server-side `Authorization: Key <secretKey>` header. Non-2xx responses throw\n * a {@link KhaltiError} carrying Khalti's parsed `detail`.\n *\n * Isomorphic: Node 20+, edge runtimes and browsers via global `fetch`\n * (injectable). Zero dependencies.\n */\n\n/* ------------------------------------------------------------------ *\n * Endpoints & types\n * ------------------------------------------------------------------ */\n\nexport type KhaltiEnv = \"test\" | \"prod\";\n\n/** Khalti API base URLs. */\nexport const KHALTI_BASE_URLS: Record<KhaltiEnv, string> = {\n test: \"https://a.khalti.com/api/v2\",\n prod: \"https://khalti.com/api/v2\",\n};\n\n/** Possible values of a Khalti payment `status`. */\nexport type KhaltiStatus =\n | \"Completed\"\n | \"Pending\"\n | \"Initiated\"\n | \"Refunded\"\n | \"Expired\"\n | \"User canceled\"\n | \"Partially Refunded\";\n\nexport interface KhaltiCustomerInfo {\n name?: string;\n email?: string;\n phone?: string;\n}\n\nexport interface KhaltiAmountBreakdown {\n label: string;\n /** In paisa. */\n amount: number;\n}\n\nexport interface InitiatePayload {\n /** Where Khalti redirects the customer after payment. */\n return_url: string;\n /** Your site's base URL. */\n website_url: string;\n /** Total payable amount in **paisa** (integer). */\n amount: number;\n /** Your unique order id. */\n purchase_order_id: string;\n /** Human-readable order name. */\n purchase_order_name: string;\n customer_info?: KhaltiCustomerInfo;\n amount_breakdown?: KhaltiAmountBreakdown[];\n product_details?: unknown[];\n}\n\nexport interface InitiateResponse {\n pidx: string;\n payment_url: string;\n expires_at: string;\n expires_in: number;\n}\n\nexport interface LookupResponse {\n pidx: string;\n /** In paisa. */\n total_amount: number;\n status: KhaltiStatus | string;\n transaction_id: string | null;\n /** In paisa. */\n fee: number;\n refunded: boolean;\n}\n\nexport interface KhaltiClientOpts {\n secretKey: string;\n env?: KhaltiEnv;\n fetch?: typeof fetch;\n}\n\n/* ------------------------------------------------------------------ *\n * Errors\n * ------------------------------------------------------------------ */\n\n/** Thrown on any non-2xx Khalti response, carrying the parsed error body. */\nexport class KhaltiError extends Error {\n /** HTTP status code. */\n readonly status: number;\n /** Khalti's `detail` field (or the raw error payload). */\n readonly detail: unknown;\n\n constructor(message: string, status: number, detail: unknown) {\n super(message);\n this.name = \"KhaltiError\";\n this.status = status;\n this.detail = detail;\n // Restore prototype chain for instanceof across transpile targets.\n Object.setPrototypeOf(this, KhaltiError.prototype);\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Internal request helper\n * ------------------------------------------------------------------ */\n\nasync function post<T>(path: string, body: unknown, opts: KhaltiClientOpts): Promise<T> {\n const base = KHALTI_BASE_URLS[opts.env ?? \"test\"];\n const doFetch = opts.fetch ?? globalThis.fetch;\n if (!doFetch) throw new Error(\"@lacspace/khalti: global fetch is unavailable; pass opts.fetch.\");\n\n const res = await doFetch(`${base}${path}`, {\n method: \"POST\",\n headers: {\n Authorization: `Key ${opts.secretKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n let parsed: unknown = undefined;\n const text = await res.text();\n if (text) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n const detail =\n parsed && typeof parsed === \"object\" && \"detail\" in (parsed as Record<string, unknown>)\n ? (parsed as Record<string, unknown>).detail\n : parsed;\n const message =\n typeof detail === \"string\" ? detail : `Khalti request failed with status ${res.status}`;\n throw new KhaltiError(message, res.status, detail);\n }\n\n return parsed as T;\n}\n\n/* ------------------------------------------------------------------ *\n * Public API\n * ------------------------------------------------------------------ */\n\n/**\n * Initiate a Khalti payment. POSTs to `/epayment/initiate/` and returns the\n * `pidx` and `payment_url` to redirect the customer to.\n *\n * @example\n * const { payment_url, pidx } = await initiate(\n * {\n * return_url: \"https://myshop.np/khalti/return\",\n * website_url: \"https://myshop.np\",\n * amount: 1000, // NPR 10, in paisa\n * purchase_order_id: \"order-42\",\n * purchase_order_name: \"Test order\",\n * },\n * { secretKey: process.env.KHALTI_SECRET!, env: \"test\" },\n * );\n */\nexport async function initiate(\n payload: InitiatePayload,\n opts: KhaltiClientOpts,\n): Promise<InitiateResponse> {\n return post<InitiateResponse>(\"/epayment/initiate/\", payload, opts);\n}\n\n/**\n * Look up a payment's real status by `pidx` โ the authoritative check to run\n * after the customer returns. POSTs `{ pidx }` to `/epayment/lookup/`.\n *\n * @example\n * const r = await lookup(pidx, { secretKey, env: \"test\" });\n * if (r.status === \"Completed\") fulfilOrder();\n */\nexport async function lookup(pidx: string, opts: KhaltiClientOpts): Promise<LookupResponse> {\n return post<LookupResponse>(\"/epayment/lookup/\", { pidx }, opts);\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lacspace/khalti
|
|
3
|
+
*
|
|
4
|
+
* Khalti KPG-2 (ePayment API v2, Nepal) โ a tiny, typed client for the two calls
|
|
5
|
+
* every integration needs:
|
|
6
|
+
*
|
|
7
|
+
* 1. **initiate** โ create a payment and get back a `payment_url` to redirect
|
|
8
|
+
* the customer to, plus a `pidx` to track it.
|
|
9
|
+
* 2. **lookup** โ the source of truth: check a payment's real status by
|
|
10
|
+
* `pidx` after the customer returns (never trust the callback alone).
|
|
11
|
+
*
|
|
12
|
+
* Amounts are always in **paisa** (integer): NPR 10 โ `1000`. Authentication is
|
|
13
|
+
* a server-side `Authorization: Key <secretKey>` header. Non-2xx responses throw
|
|
14
|
+
* a {@link KhaltiError} carrying Khalti's parsed `detail`.
|
|
15
|
+
*
|
|
16
|
+
* Isomorphic: Node 20+, edge runtimes and browsers via global `fetch`
|
|
17
|
+
* (injectable). Zero dependencies.
|
|
18
|
+
*/
|
|
19
|
+
type KhaltiEnv = "test" | "prod";
|
|
20
|
+
/** Khalti API base URLs. */
|
|
21
|
+
declare const KHALTI_BASE_URLS: Record<KhaltiEnv, string>;
|
|
22
|
+
/** Possible values of a Khalti payment `status`. */
|
|
23
|
+
type KhaltiStatus = "Completed" | "Pending" | "Initiated" | "Refunded" | "Expired" | "User canceled" | "Partially Refunded";
|
|
24
|
+
interface KhaltiCustomerInfo {
|
|
25
|
+
name?: string;
|
|
26
|
+
email?: string;
|
|
27
|
+
phone?: string;
|
|
28
|
+
}
|
|
29
|
+
interface KhaltiAmountBreakdown {
|
|
30
|
+
label: string;
|
|
31
|
+
/** In paisa. */
|
|
32
|
+
amount: number;
|
|
33
|
+
}
|
|
34
|
+
interface InitiatePayload {
|
|
35
|
+
/** Where Khalti redirects the customer after payment. */
|
|
36
|
+
return_url: string;
|
|
37
|
+
/** Your site's base URL. */
|
|
38
|
+
website_url: string;
|
|
39
|
+
/** Total payable amount in **paisa** (integer). */
|
|
40
|
+
amount: number;
|
|
41
|
+
/** Your unique order id. */
|
|
42
|
+
purchase_order_id: string;
|
|
43
|
+
/** Human-readable order name. */
|
|
44
|
+
purchase_order_name: string;
|
|
45
|
+
customer_info?: KhaltiCustomerInfo;
|
|
46
|
+
amount_breakdown?: KhaltiAmountBreakdown[];
|
|
47
|
+
product_details?: unknown[];
|
|
48
|
+
}
|
|
49
|
+
interface InitiateResponse {
|
|
50
|
+
pidx: string;
|
|
51
|
+
payment_url: string;
|
|
52
|
+
expires_at: string;
|
|
53
|
+
expires_in: number;
|
|
54
|
+
}
|
|
55
|
+
interface LookupResponse {
|
|
56
|
+
pidx: string;
|
|
57
|
+
/** In paisa. */
|
|
58
|
+
total_amount: number;
|
|
59
|
+
status: KhaltiStatus | string;
|
|
60
|
+
transaction_id: string | null;
|
|
61
|
+
/** In paisa. */
|
|
62
|
+
fee: number;
|
|
63
|
+
refunded: boolean;
|
|
64
|
+
}
|
|
65
|
+
interface KhaltiClientOpts {
|
|
66
|
+
secretKey: string;
|
|
67
|
+
env?: KhaltiEnv;
|
|
68
|
+
fetch?: typeof fetch;
|
|
69
|
+
}
|
|
70
|
+
/** Thrown on any non-2xx Khalti response, carrying the parsed error body. */
|
|
71
|
+
declare class KhaltiError extends Error {
|
|
72
|
+
/** HTTP status code. */
|
|
73
|
+
readonly status: number;
|
|
74
|
+
/** Khalti's `detail` field (or the raw error payload). */
|
|
75
|
+
readonly detail: unknown;
|
|
76
|
+
constructor(message: string, status: number, detail: unknown);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Initiate a Khalti payment. POSTs to `/epayment/initiate/` and returns the
|
|
80
|
+
* `pidx` and `payment_url` to redirect the customer to.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const { payment_url, pidx } = await initiate(
|
|
84
|
+
* {
|
|
85
|
+
* return_url: "https://myshop.np/khalti/return",
|
|
86
|
+
* website_url: "https://myshop.np",
|
|
87
|
+
* amount: 1000, // NPR 10, in paisa
|
|
88
|
+
* purchase_order_id: "order-42",
|
|
89
|
+
* purchase_order_name: "Test order",
|
|
90
|
+
* },
|
|
91
|
+
* { secretKey: process.env.KHALTI_SECRET!, env: "test" },
|
|
92
|
+
* );
|
|
93
|
+
*/
|
|
94
|
+
declare function initiate(payload: InitiatePayload, opts: KhaltiClientOpts): Promise<InitiateResponse>;
|
|
95
|
+
/**
|
|
96
|
+
* Look up a payment's real status by `pidx` โ the authoritative check to run
|
|
97
|
+
* after the customer returns. POSTs `{ pidx }` to `/epayment/lookup/`.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const r = await lookup(pidx, { secretKey, env: "test" });
|
|
101
|
+
* if (r.status === "Completed") fulfilOrder();
|
|
102
|
+
*/
|
|
103
|
+
declare function lookup(pidx: string, opts: KhaltiClientOpts): Promise<LookupResponse>;
|
|
104
|
+
|
|
105
|
+
export { type InitiatePayload, type InitiateResponse, KHALTI_BASE_URLS, type KhaltiAmountBreakdown, type KhaltiClientOpts, type KhaltiCustomerInfo, type KhaltiEnv, KhaltiError, type KhaltiStatus, type LookupResponse, initiate, lookup };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @lacspace/khalti
|
|
3
|
+
*
|
|
4
|
+
* Khalti KPG-2 (ePayment API v2, Nepal) โ a tiny, typed client for the two calls
|
|
5
|
+
* every integration needs:
|
|
6
|
+
*
|
|
7
|
+
* 1. **initiate** โ create a payment and get back a `payment_url` to redirect
|
|
8
|
+
* the customer to, plus a `pidx` to track it.
|
|
9
|
+
* 2. **lookup** โ the source of truth: check a payment's real status by
|
|
10
|
+
* `pidx` after the customer returns (never trust the callback alone).
|
|
11
|
+
*
|
|
12
|
+
* Amounts are always in **paisa** (integer): NPR 10 โ `1000`. Authentication is
|
|
13
|
+
* a server-side `Authorization: Key <secretKey>` header. Non-2xx responses throw
|
|
14
|
+
* a {@link KhaltiError} carrying Khalti's parsed `detail`.
|
|
15
|
+
*
|
|
16
|
+
* Isomorphic: Node 20+, edge runtimes and browsers via global `fetch`
|
|
17
|
+
* (injectable). Zero dependencies.
|
|
18
|
+
*/
|
|
19
|
+
type KhaltiEnv = "test" | "prod";
|
|
20
|
+
/** Khalti API base URLs. */
|
|
21
|
+
declare const KHALTI_BASE_URLS: Record<KhaltiEnv, string>;
|
|
22
|
+
/** Possible values of a Khalti payment `status`. */
|
|
23
|
+
type KhaltiStatus = "Completed" | "Pending" | "Initiated" | "Refunded" | "Expired" | "User canceled" | "Partially Refunded";
|
|
24
|
+
interface KhaltiCustomerInfo {
|
|
25
|
+
name?: string;
|
|
26
|
+
email?: string;
|
|
27
|
+
phone?: string;
|
|
28
|
+
}
|
|
29
|
+
interface KhaltiAmountBreakdown {
|
|
30
|
+
label: string;
|
|
31
|
+
/** In paisa. */
|
|
32
|
+
amount: number;
|
|
33
|
+
}
|
|
34
|
+
interface InitiatePayload {
|
|
35
|
+
/** Where Khalti redirects the customer after payment. */
|
|
36
|
+
return_url: string;
|
|
37
|
+
/** Your site's base URL. */
|
|
38
|
+
website_url: string;
|
|
39
|
+
/** Total payable amount in **paisa** (integer). */
|
|
40
|
+
amount: number;
|
|
41
|
+
/** Your unique order id. */
|
|
42
|
+
purchase_order_id: string;
|
|
43
|
+
/** Human-readable order name. */
|
|
44
|
+
purchase_order_name: string;
|
|
45
|
+
customer_info?: KhaltiCustomerInfo;
|
|
46
|
+
amount_breakdown?: KhaltiAmountBreakdown[];
|
|
47
|
+
product_details?: unknown[];
|
|
48
|
+
}
|
|
49
|
+
interface InitiateResponse {
|
|
50
|
+
pidx: string;
|
|
51
|
+
payment_url: string;
|
|
52
|
+
expires_at: string;
|
|
53
|
+
expires_in: number;
|
|
54
|
+
}
|
|
55
|
+
interface LookupResponse {
|
|
56
|
+
pidx: string;
|
|
57
|
+
/** In paisa. */
|
|
58
|
+
total_amount: number;
|
|
59
|
+
status: KhaltiStatus | string;
|
|
60
|
+
transaction_id: string | null;
|
|
61
|
+
/** In paisa. */
|
|
62
|
+
fee: number;
|
|
63
|
+
refunded: boolean;
|
|
64
|
+
}
|
|
65
|
+
interface KhaltiClientOpts {
|
|
66
|
+
secretKey: string;
|
|
67
|
+
env?: KhaltiEnv;
|
|
68
|
+
fetch?: typeof fetch;
|
|
69
|
+
}
|
|
70
|
+
/** Thrown on any non-2xx Khalti response, carrying the parsed error body. */
|
|
71
|
+
declare class KhaltiError extends Error {
|
|
72
|
+
/** HTTP status code. */
|
|
73
|
+
readonly status: number;
|
|
74
|
+
/** Khalti's `detail` field (or the raw error payload). */
|
|
75
|
+
readonly detail: unknown;
|
|
76
|
+
constructor(message: string, status: number, detail: unknown);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Initiate a Khalti payment. POSTs to `/epayment/initiate/` and returns the
|
|
80
|
+
* `pidx` and `payment_url` to redirect the customer to.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* const { payment_url, pidx } = await initiate(
|
|
84
|
+
* {
|
|
85
|
+
* return_url: "https://myshop.np/khalti/return",
|
|
86
|
+
* website_url: "https://myshop.np",
|
|
87
|
+
* amount: 1000, // NPR 10, in paisa
|
|
88
|
+
* purchase_order_id: "order-42",
|
|
89
|
+
* purchase_order_name: "Test order",
|
|
90
|
+
* },
|
|
91
|
+
* { secretKey: process.env.KHALTI_SECRET!, env: "test" },
|
|
92
|
+
* );
|
|
93
|
+
*/
|
|
94
|
+
declare function initiate(payload: InitiatePayload, opts: KhaltiClientOpts): Promise<InitiateResponse>;
|
|
95
|
+
/**
|
|
96
|
+
* Look up a payment's real status by `pidx` โ the authoritative check to run
|
|
97
|
+
* after the customer returns. POSTs `{ pidx }` to `/epayment/lookup/`.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const r = await lookup(pidx, { secretKey, env: "test" });
|
|
101
|
+
* if (r.status === "Completed") fulfilOrder();
|
|
102
|
+
*/
|
|
103
|
+
declare function lookup(pidx: string, opts: KhaltiClientOpts): Promise<LookupResponse>;
|
|
104
|
+
|
|
105
|
+
export { type InitiatePayload, type InitiateResponse, KHALTI_BASE_URLS, type KhaltiAmountBreakdown, type KhaltiClientOpts, type KhaltiCustomerInfo, type KhaltiEnv, KhaltiError, type KhaltiStatus, type LookupResponse, initiate, lookup };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var KHALTI_BASE_URLS = {
|
|
3
|
+
test: "https://a.khalti.com/api/v2",
|
|
4
|
+
prod: "https://khalti.com/api/v2"
|
|
5
|
+
};
|
|
6
|
+
var KhaltiError = class _KhaltiError extends Error {
|
|
7
|
+
constructor(message, status, detail) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "KhaltiError";
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.detail = detail;
|
|
12
|
+
Object.setPrototypeOf(this, _KhaltiError.prototype);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
async function post(path, body, opts) {
|
|
16
|
+
const base = KHALTI_BASE_URLS[opts.env ?? "test"];
|
|
17
|
+
const doFetch = opts.fetch ?? globalThis.fetch;
|
|
18
|
+
if (!doFetch) throw new Error("@lacspace/khalti: global fetch is unavailable; pass opts.fetch.");
|
|
19
|
+
const res = await doFetch(`${base}${path}`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Key ${opts.secretKey}`,
|
|
23
|
+
"Content-Type": "application/json"
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify(body)
|
|
26
|
+
});
|
|
27
|
+
let parsed = void 0;
|
|
28
|
+
const text = await res.text();
|
|
29
|
+
if (text) {
|
|
30
|
+
try {
|
|
31
|
+
parsed = JSON.parse(text);
|
|
32
|
+
} catch {
|
|
33
|
+
parsed = text;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (!res.ok) {
|
|
37
|
+
const detail = parsed && typeof parsed === "object" && "detail" in parsed ? parsed.detail : parsed;
|
|
38
|
+
const message = typeof detail === "string" ? detail : `Khalti request failed with status ${res.status}`;
|
|
39
|
+
throw new KhaltiError(message, res.status, detail);
|
|
40
|
+
}
|
|
41
|
+
return parsed;
|
|
42
|
+
}
|
|
43
|
+
async function initiate(payload, opts) {
|
|
44
|
+
return post("/epayment/initiate/", payload, opts);
|
|
45
|
+
}
|
|
46
|
+
async function lookup(pidx, opts) {
|
|
47
|
+
return post("/epayment/lookup/", { pidx }, opts);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { KHALTI_BASE_URLS, KhaltiError, initiate, lookup };
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";AA0BO,IAAM,gBAAA,GAA8C;AAAA,EACzD,IAAA,EAAM,6BAAA;AAAA,EACN,IAAA,EAAM;AACR;AAqEO,IAAM,WAAA,GAAN,MAAM,YAAA,SAAoB,KAAA,CAAM;AAAA,EAMrC,WAAA,CAAY,OAAA,EAAiB,MAAA,EAAgB,MAAA,EAAiB;AAC5D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAEd,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,YAAA,CAAY,SAAS,CAAA;AAAA,EACnD;AACF;AAMA,eAAe,IAAA,CAAQ,IAAA,EAAc,IAAA,EAAe,IAAA,EAAoC;AACtF,EAAA,MAAM,IAAA,GAAO,gBAAA,CAAiB,IAAA,CAAK,GAAA,IAAO,MAAM,CAAA;AAChD,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,IAAS,UAAA,CAAW,KAAA;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,iEAAiE,CAAA;AAE/F,EAAA,MAAM,MAAM,MAAM,OAAA,CAAQ,GAAG,IAAI,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI;AAAA,IAC1C,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,aAAA,EAAe,CAAA,IAAA,EAAO,IAAA,CAAK,SAAS,CAAA,CAAA;AAAA,MACpC,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,GAC1B,CAAA;AAED,EAAA,IAAI,MAAA,GAAkB,MAAA;AACtB,EAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IAC1B,CAAA,CAAA,MAAQ;AACN,MAAA,MAAA,GAAS,IAAA;AAAA,IACX;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,IAAA,MAAM,MAAA,GACJ,UAAU,OAAO,MAAA,KAAW,YAAY,QAAA,IAAa,MAAA,GAChD,OAAmC,MAAA,GACpC,MAAA;AACN,IAAA,MAAM,UACJ,OAAO,MAAA,KAAW,WAAW,MAAA,GAAS,CAAA,kCAAA,EAAqC,IAAI,MAAM,CAAA,CAAA;AACvF,IAAA,MAAM,IAAI,WAAA,CAAY,OAAA,EAAS,GAAA,CAAI,QAAQ,MAAM,CAAA;AAAA,EACnD;AAEA,EAAA,OAAO,MAAA;AACT;AAsBA,eAAsB,QAAA,CACpB,SACA,IAAA,EAC2B;AAC3B,EAAA,OAAO,IAAA,CAAuB,qBAAA,EAAuB,OAAA,EAAS,IAAI,CAAA;AACpE;AAUA,eAAsB,MAAA,CAAO,MAAc,IAAA,EAAiD;AAC1F,EAAA,OAAO,IAAA,CAAqB,mBAAA,EAAqB,EAAE,IAAA,IAAQ,IAAI,CAAA;AACjE","file":"index.js","sourcesContent":["/**\n * @lacspace/khalti\n *\n * Khalti KPG-2 (ePayment API v2, Nepal) โ a tiny, typed client for the two calls\n * every integration needs:\n *\n * 1. **initiate** โ create a payment and get back a `payment_url` to redirect\n * the customer to, plus a `pidx` to track it.\n * 2. **lookup** โ the source of truth: check a payment's real status by\n * `pidx` after the customer returns (never trust the callback alone).\n *\n * Amounts are always in **paisa** (integer): NPR 10 โ `1000`. Authentication is\n * a server-side `Authorization: Key <secretKey>` header. Non-2xx responses throw\n * a {@link KhaltiError} carrying Khalti's parsed `detail`.\n *\n * Isomorphic: Node 20+, edge runtimes and browsers via global `fetch`\n * (injectable). Zero dependencies.\n */\n\n/* ------------------------------------------------------------------ *\n * Endpoints & types\n * ------------------------------------------------------------------ */\n\nexport type KhaltiEnv = \"test\" | \"prod\";\n\n/** Khalti API base URLs. */\nexport const KHALTI_BASE_URLS: Record<KhaltiEnv, string> = {\n test: \"https://a.khalti.com/api/v2\",\n prod: \"https://khalti.com/api/v2\",\n};\n\n/** Possible values of a Khalti payment `status`. */\nexport type KhaltiStatus =\n | \"Completed\"\n | \"Pending\"\n | \"Initiated\"\n | \"Refunded\"\n | \"Expired\"\n | \"User canceled\"\n | \"Partially Refunded\";\n\nexport interface KhaltiCustomerInfo {\n name?: string;\n email?: string;\n phone?: string;\n}\n\nexport interface KhaltiAmountBreakdown {\n label: string;\n /** In paisa. */\n amount: number;\n}\n\nexport interface InitiatePayload {\n /** Where Khalti redirects the customer after payment. */\n return_url: string;\n /** Your site's base URL. */\n website_url: string;\n /** Total payable amount in **paisa** (integer). */\n amount: number;\n /** Your unique order id. */\n purchase_order_id: string;\n /** Human-readable order name. */\n purchase_order_name: string;\n customer_info?: KhaltiCustomerInfo;\n amount_breakdown?: KhaltiAmountBreakdown[];\n product_details?: unknown[];\n}\n\nexport interface InitiateResponse {\n pidx: string;\n payment_url: string;\n expires_at: string;\n expires_in: number;\n}\n\nexport interface LookupResponse {\n pidx: string;\n /** In paisa. */\n total_amount: number;\n status: KhaltiStatus | string;\n transaction_id: string | null;\n /** In paisa. */\n fee: number;\n refunded: boolean;\n}\n\nexport interface KhaltiClientOpts {\n secretKey: string;\n env?: KhaltiEnv;\n fetch?: typeof fetch;\n}\n\n/* ------------------------------------------------------------------ *\n * Errors\n * ------------------------------------------------------------------ */\n\n/** Thrown on any non-2xx Khalti response, carrying the parsed error body. */\nexport class KhaltiError extends Error {\n /** HTTP status code. */\n readonly status: number;\n /** Khalti's `detail` field (or the raw error payload). */\n readonly detail: unknown;\n\n constructor(message: string, status: number, detail: unknown) {\n super(message);\n this.name = \"KhaltiError\";\n this.status = status;\n this.detail = detail;\n // Restore prototype chain for instanceof across transpile targets.\n Object.setPrototypeOf(this, KhaltiError.prototype);\n }\n}\n\n/* ------------------------------------------------------------------ *\n * Internal request helper\n * ------------------------------------------------------------------ */\n\nasync function post<T>(path: string, body: unknown, opts: KhaltiClientOpts): Promise<T> {\n const base = KHALTI_BASE_URLS[opts.env ?? \"test\"];\n const doFetch = opts.fetch ?? globalThis.fetch;\n if (!doFetch) throw new Error(\"@lacspace/khalti: global fetch is unavailable; pass opts.fetch.\");\n\n const res = await doFetch(`${base}${path}`, {\n method: \"POST\",\n headers: {\n Authorization: `Key ${opts.secretKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n\n let parsed: unknown = undefined;\n const text = await res.text();\n if (text) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = text;\n }\n }\n\n if (!res.ok) {\n const detail =\n parsed && typeof parsed === \"object\" && \"detail\" in (parsed as Record<string, unknown>)\n ? (parsed as Record<string, unknown>).detail\n : parsed;\n const message =\n typeof detail === \"string\" ? detail : `Khalti request failed with status ${res.status}`;\n throw new KhaltiError(message, res.status, detail);\n }\n\n return parsed as T;\n}\n\n/* ------------------------------------------------------------------ *\n * Public API\n * ------------------------------------------------------------------ */\n\n/**\n * Initiate a Khalti payment. POSTs to `/epayment/initiate/` and returns the\n * `pidx` and `payment_url` to redirect the customer to.\n *\n * @example\n * const { payment_url, pidx } = await initiate(\n * {\n * return_url: \"https://myshop.np/khalti/return\",\n * website_url: \"https://myshop.np\",\n * amount: 1000, // NPR 10, in paisa\n * purchase_order_id: \"order-42\",\n * purchase_order_name: \"Test order\",\n * },\n * { secretKey: process.env.KHALTI_SECRET!, env: \"test\" },\n * );\n */\nexport async function initiate(\n payload: InitiatePayload,\n opts: KhaltiClientOpts,\n): Promise<InitiateResponse> {\n return post<InitiateResponse>(\"/epayment/initiate/\", payload, opts);\n}\n\n/**\n * Look up a payment's real status by `pidx` โ the authoritative check to run\n * after the customer returns. POSTs `{ pidx }` to `/epayment/lookup/`.\n *\n * @example\n * const r = await lookup(pidx, { secretKey, env: \"test\" });\n * if (r.status === \"Completed\") fulfilOrder();\n */\nexport async function lookup(pidx: string, opts: KhaltiClientOpts): Promise<LookupResponse> {\n return post<LookupResponse>(\"/epayment/lookup/\", { pidx }, opts);\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lacspace/khalti",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Khalti KPG-2 (ePayment API v2, Nepal) client โ initiate payments, look up status, typed errors and Key auth over global fetch. Zero-dependency, isomorphic (Node, edge, browser).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsup",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"keywords": [
|
|
30
|
+
"nepal",
|
|
31
|
+
"payment",
|
|
32
|
+
"payment-gateway",
|
|
33
|
+
"khalti",
|
|
34
|
+
"kpg-2",
|
|
35
|
+
"epayment",
|
|
36
|
+
"esewa",
|
|
37
|
+
"fetch",
|
|
38
|
+
"web-crypto",
|
|
39
|
+
"edge",
|
|
40
|
+
"isomorphic",
|
|
41
|
+
"typescript"
|
|
42
|
+
],
|
|
43
|
+
"author": "Lacspace <contact@lacspace.com>",
|
|
44
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
45
|
+
"homepage": "https://developer.lacspace.com/packages/khalti",
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/lacspace/npm-packages.git",
|
|
49
|
+
"directory": "khalti"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/lacspace/npm-packages/issues"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=20"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|