bkash-client 0.0.0-stage → 0.1.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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -2
  3. package/dist/angular.cjs +149 -0
  4. package/dist/angular.cjs.map +1 -0
  5. package/dist/angular.d.cts +21 -0
  6. package/dist/angular.d.ts +21 -0
  7. package/dist/angular.js +29 -0
  8. package/dist/angular.js.map +1 -0
  9. package/dist/bkash-client.browser.global.js +149 -0
  10. package/dist/bkash-client.browser.global.js.map +1 -0
  11. package/dist/chunk-DGUM43GV.js +10 -0
  12. package/dist/chunk-DGUM43GV.js.map +1 -0
  13. package/dist/chunk-FXLW32P4.js +124 -0
  14. package/dist/chunk-FXLW32P4.js.map +1 -0
  15. package/dist/index.cjs +126 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +70 -0
  18. package/dist/index.d.ts +70 -0
  19. package/dist/index.js +4 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/react-native.cjs +68 -0
  22. package/dist/react-native.cjs.map +1 -0
  23. package/dist/react-native.d.cts +35 -0
  24. package/dist/react-native.d.ts +35 -0
  25. package/dist/react-native.js +61 -0
  26. package/dist/react-native.js.map +1 -0
  27. package/dist/react.cjs +190 -0
  28. package/dist/react.cjs.map +1 -0
  29. package/dist/react.d.cts +27 -0
  30. package/dist/react.d.ts +27 -0
  31. package/dist/react.js +65 -0
  32. package/dist/react.js.map +1 -0
  33. package/dist/svelte.cjs +141 -0
  34. package/dist/svelte.cjs.map +1 -0
  35. package/dist/svelte.d.cts +16 -0
  36. package/dist/svelte.d.ts +16 -0
  37. package/dist/svelte.js +21 -0
  38. package/dist/svelte.js.map +1 -0
  39. package/dist/vue.cjs +169 -0
  40. package/dist/vue.cjs.map +1 -0
  41. package/dist/vue.d.cts +21 -0
  42. package/dist/vue.d.ts +21 -0
  43. package/dist/vue.js +45 -0
  44. package/dist/vue.js.map +1 -0
  45. package/package.json +159 -3
package/dist/react.cjs ADDED
@@ -0,0 +1,190 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+
5
+ // src/react.ts
6
+
7
+ // src/index.ts
8
+ var BkashClient = class {
9
+ state = "idle";
10
+ options;
11
+ currentPaymentId = null;
12
+ listeners = /* @__PURE__ */ new Set();
13
+ constructor(options) {
14
+ this.options = {
15
+ createUrl: "/api/bkash/create",
16
+ ...options
17
+ };
18
+ }
19
+ getState() {
20
+ return this.state;
21
+ }
22
+ getPaymentId() {
23
+ return this.currentPaymentId;
24
+ }
25
+ /**
26
+ * Returns human-readable UI guidance for the current client state.
27
+ * Specifically guarantees that unknown or timed-out outcomes are presented as
28
+ * "payment pending, do not pay again" rather than a false failure.
29
+ */
30
+ getStateMessage() {
31
+ switch (this.state) {
32
+ case "idle":
33
+ return "Ready to initiate checkout.";
34
+ case "creating":
35
+ return "Initializing payment session with bKash...";
36
+ case "awaiting_user":
37
+ return "Redirecting to bKash secure payment page...";
38
+ case "verifying":
39
+ return "Verifying payment with bKash...";
40
+ case "success":
41
+ return "Payment completed successfully!";
42
+ case "pending":
43
+ case "timeout":
44
+ return "Payment pending, do not pay again. Please wait while your transaction is reconciled with bKash.";
45
+ case "cancelled":
46
+ return "Payment was cancelled.";
47
+ case "offline":
48
+ return "Device is offline. Please check your internet connection before retrying.";
49
+ case "error":
50
+ return "An error occurred during checkout.";
51
+ default:
52
+ return "";
53
+ }
54
+ }
55
+ subscribe(listener) {
56
+ this.listeners.add(listener);
57
+ return () => this.listeners.delete(listener);
58
+ }
59
+ cancel() {
60
+ this.setState("cancelled");
61
+ this.options.onCancel?.();
62
+ }
63
+ setPending(paymentId) {
64
+ if (paymentId) this.currentPaymentId = paymentId;
65
+ this.setState("pending");
66
+ }
67
+ setState(newState) {
68
+ this.state = newState;
69
+ this.options.onStateChange?.(newState);
70
+ this.listeners.forEach((fn) => fn(newState));
71
+ }
72
+ /**
73
+ * Initiates payment flow by calling the merchant backend,
74
+ * obtaining the gateway URL, and redirecting the customer.
75
+ */
76
+ async checkout(params = {}) {
77
+ if (typeof navigator !== "undefined" && navigator.onLine === false) {
78
+ this.setState("offline");
79
+ const offlineErr = new Error("Device is offline. Please check your internet connection.");
80
+ this.options.onError?.(offlineErr);
81
+ throw offlineErr;
82
+ }
83
+ try {
84
+ this.setState("creating");
85
+ const defaultCallback = typeof window !== "undefined" ? window.location?.href : "";
86
+ const res = await fetch(this.options.createUrl, {
87
+ method: "POST",
88
+ headers: { "Content-Type": "application/json" },
89
+ body: JSON.stringify({
90
+ amount: params.amount,
91
+ invoiceNumber: params.invoiceNumber,
92
+ orderId: params.orderId,
93
+ callbackUrl: this.options.callbackUrl || defaultCallback,
94
+ payerReference: params.payerReference,
95
+ metadata: params.metadata
96
+ })
97
+ });
98
+ if (!res.ok) {
99
+ throw new Error(`Failed to create payment session: HTTP ${res.status}`);
100
+ }
101
+ const data = await res.json();
102
+ if (!data.redirectUrl || !data.paymentId) {
103
+ throw new Error(data.error || "Invalid session response from payment server.");
104
+ }
105
+ this.currentPaymentId = data.paymentId;
106
+ this.setState("awaiting_user");
107
+ if (typeof window !== "undefined" && window.location) {
108
+ window.location.href = data.redirectUrl;
109
+ }
110
+ } catch (err) {
111
+ const error = err instanceof Error ? err : new Error(String(err));
112
+ const isTimeout = error.name === "AbortError" || error.name === "TimeoutError" || /timeout|abort/i.test(error.message);
113
+ if (isTimeout) {
114
+ this.setState("pending");
115
+ } else {
116
+ this.setState("error");
117
+ }
118
+ this.options.onError?.(error);
119
+ throw error;
120
+ }
121
+ }
122
+ reset() {
123
+ this.currentPaymentId = null;
124
+ this.setState("idle");
125
+ }
126
+ };
127
+
128
+ // src/react.ts
129
+ function useBkash(options) {
130
+ const [client] = react.useState(() => new BkashClient(options));
131
+ const [state, setState] = react.useState(client.getState());
132
+ const [error, setError] = react.useState(null);
133
+ react.useEffect(() => {
134
+ return client.subscribe((newState) => setState(newState));
135
+ }, [client]);
136
+ const checkout = react.useCallback(
137
+ async (params) => {
138
+ setError(null);
139
+ try {
140
+ await client.checkout(params);
141
+ } catch (err) {
142
+ const errorObj = err instanceof Error ? err : new Error(String(err));
143
+ setError(errorObj);
144
+ throw errorObj;
145
+ }
146
+ },
147
+ [client]
148
+ );
149
+ const reset = react.useCallback(() => {
150
+ setError(null);
151
+ client.reset();
152
+ }, [client]);
153
+ return {
154
+ state,
155
+ error,
156
+ paymentId: client.getPaymentId(),
157
+ checkout,
158
+ reset,
159
+ client
160
+ };
161
+ }
162
+ function BkashButton({
163
+ amount,
164
+ invoiceNumber,
165
+ orderId,
166
+ options,
167
+ className,
168
+ children
169
+ }) {
170
+ const { state, checkout } = useBkash(options);
171
+ const handleClick = async () => {
172
+ if (state === "creating") return;
173
+ await checkout({ amount, invoiceNumber, orderId });
174
+ };
175
+ return react.createElement(
176
+ "button",
177
+ {
178
+ type: "button",
179
+ onClick: handleClick,
180
+ disabled: state === "creating",
181
+ className: className || "bkash-pay-btn"
182
+ },
183
+ children || (state === "creating" ? "Connecting to bKash..." : "Pay with bKash")
184
+ );
185
+ }
186
+
187
+ exports.BkashButton = BkashButton;
188
+ exports.useBkash = useBkash;
189
+ //# sourceMappingURL=react.cjs.map
190
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/react.ts"],"names":["useState","useEffect","useCallback","createElement"],"mappings":"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","file":"react.cjs","sourcesContent":["/**\n * @bkash/client\n * Universal, headless client SDK for bKash payment integrations.\n */\n\nexport type BkashClientState =\n | 'idle'\n | 'creating'\n | 'awaiting_user'\n | 'verifying'\n | 'success'\n | 'pending'\n | 'cancelled'\n | 'timeout'\n | 'offline'\n | 'error';\n\nexport interface BkashClientOptions {\n /**\n * Endpoint on merchant backend to create payment session.\n * Defaults to \"/api/bkash/create\".\n */\n createUrl?: string;\n /**\n * Callback URL registered with merchant backend.\n */\n callbackUrl?: string;\n /**\n * Hook triggered on state transition.\n */\n onStateChange?: (state: BkashClientState) => void;\n /**\n * Hook triggered when payment completes successfully.\n */\n onSuccess?: (paymentId: string) => void;\n /**\n * Hook triggered on payment error.\n */\n onError?: (error: Error) => void;\n /**\n * Hook triggered if user cancels payment.\n */\n onCancel?: () => void;\n}\n\n/**\n * All fields are optional hints. bkash-server decides the amount and invoice from its own\n * data and ignores any amount or invoice sent from the browser.\n */\nexport interface InitiateCheckoutParams {\n amount?: number | string;\n invoiceNumber?: string;\n orderId?: string;\n payerReference?: string;\n metadata?: Record<string, string>;\n}\n\nexport class BkashClient {\n private state: BkashClientState = 'idle';\n private options: BkashClientOptions;\n private currentPaymentId: string | null = null;\n private listeners = new Set<(state: BkashClientState) => void>();\n\n constructor(options?: BkashClientOptions) {\n this.options = {\n createUrl: '/api/bkash/create',\n ...options,\n };\n }\n\n public getState(): BkashClientState {\n return this.state;\n }\n\n public getPaymentId(): string | null {\n return this.currentPaymentId;\n }\n\n /**\n * Returns human-readable UI guidance for the current client state.\n * Specifically guarantees that unknown or timed-out outcomes are presented as\n * \"payment pending, do not pay again\" rather than a false failure.\n */\n public getStateMessage(): string {\n switch (this.state) {\n case 'idle':\n return 'Ready to initiate checkout.';\n case 'creating':\n return 'Initializing payment session with bKash...';\n case 'awaiting_user':\n return 'Redirecting to bKash secure payment page...';\n case 'verifying':\n return 'Verifying payment with bKash...';\n case 'success':\n return 'Payment completed successfully!';\n case 'pending':\n case 'timeout':\n return 'Payment pending, do not pay again. Please wait while your transaction is reconciled with bKash.';\n case 'cancelled':\n return 'Payment was cancelled.';\n case 'offline':\n return 'Device is offline. Please check your internet connection before retrying.';\n case 'error':\n return 'An error occurred during checkout.';\n default:\n return '';\n }\n }\n\n public subscribe(listener: (state: BkashClientState) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n public cancel(): void {\n this.setState('cancelled');\n this.options.onCancel?.();\n }\n\n public setPending(paymentId?: string): void {\n if (paymentId) this.currentPaymentId = paymentId;\n this.setState('pending');\n }\n\n private setState(newState: BkashClientState): void {\n this.state = newState;\n this.options.onStateChange?.(newState);\n this.listeners.forEach((fn) => fn(newState));\n }\n\n /**\n * Initiates payment flow by calling the merchant backend,\n * obtaining the gateway URL, and redirecting the customer.\n */\n public async checkout(params: InitiateCheckoutParams = {}): Promise<void> {\n // Offline pre-check\n if (typeof navigator !== 'undefined' && navigator.onLine === false) {\n this.setState('offline');\n const offlineErr = new Error('Device is offline. Please check your internet connection.');\n this.options.onError?.(offlineErr);\n throw offlineErr;\n }\n\n try {\n this.setState('creating');\n\n const defaultCallback = typeof window !== 'undefined' ? window.location?.href : '';\n const res = await fetch(this.options.createUrl!, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n amount: params.amount,\n invoiceNumber: params.invoiceNumber,\n orderId: params.orderId,\n callbackUrl: this.options.callbackUrl || defaultCallback,\n payerReference: params.payerReference,\n metadata: params.metadata,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Failed to create payment session: HTTP ${res.status}`);\n }\n\n const data = (await res.json()) as {\n redirectUrl?: string;\n paymentId?: string;\n error?: string;\n };\n if (!data.redirectUrl || !data.paymentId) {\n throw new Error(data.error || 'Invalid session response from payment server.');\n }\n\n this.currentPaymentId = data.paymentId;\n this.setState('awaiting_user');\n\n // Launch bKash Hosted Checkout\n if (typeof window !== 'undefined' && window.location) {\n window.location.href = data.redirectUrl;\n }\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n const isTimeout =\n error.name === 'AbortError' ||\n error.name === 'TimeoutError' ||\n /timeout|abort/i.test(error.message);\n\n if (isTimeout) {\n // Under AUD-08: timeout / unknown outcome MUST display pending (\"do not pay again\")\n this.setState('pending');\n } else {\n this.setState('error');\n }\n\n this.options.onError?.(error);\n throw error;\n }\n }\n\n public reset(): void {\n this.currentPaymentId = null;\n this.setState('idle');\n }\n}\n","import { useState, useEffect, useCallback, createElement } from 'react';\nimport {\n BkashClient,\n type BkashClientOptions,\n type BkashClientState,\n type InitiateCheckoutParams,\n} from './index.js';\n\nexport function useBkash(options?: BkashClientOptions) {\n const [client] = useState(() => new BkashClient(options));\n const [state, setState] = useState<BkashClientState>(client.getState());\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n return client.subscribe((newState) => setState(newState));\n }, [client]);\n\n const checkout = useCallback(\n async (params: InitiateCheckoutParams) => {\n setError(null);\n try {\n await client.checkout(params);\n } catch (err: unknown) {\n const errorObj = err instanceof Error ? err : new Error(String(err));\n setError(errorObj);\n throw errorObj;\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setError(null);\n client.reset();\n }, [client]);\n\n return {\n state,\n error,\n paymentId: client.getPaymentId(),\n checkout,\n reset,\n client,\n };\n}\n\nexport interface BkashButtonProps {\n amount?: number | string;\n invoiceNumber?: string;\n orderId?: string;\n options?: BkashClientOptions;\n className?: string;\n children?: any;\n}\n\nexport function BkashButton({\n amount,\n invoiceNumber,\n orderId,\n options,\n className,\n children,\n}: BkashButtonProps) {\n const { state, checkout } = useBkash(options);\n\n const handleClick = async () => {\n if (state === 'creating') return;\n await checkout({ amount, invoiceNumber, orderId });\n };\n\n return createElement(\n 'button',\n {\n type: 'button',\n onClick: handleClick,\n disabled: state === 'creating',\n className: className || 'bkash-pay-btn',\n },\n children || (state === 'creating' ? 'Connecting to bKash...' : 'Pay with bKash')\n );\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import * as react from 'react';
2
+ import { BkashClientOptions, BkashClientState, InitiateCheckoutParams, BkashClient } from './index.cjs';
3
+
4
+ declare function useBkash(options?: BkashClientOptions): {
5
+ state: BkashClientState;
6
+ error: Error | null;
7
+ paymentId: string | null;
8
+ checkout: (params: InitiateCheckoutParams) => Promise<void>;
9
+ reset: () => void;
10
+ client: BkashClient;
11
+ };
12
+ interface BkashButtonProps {
13
+ amount?: number | string;
14
+ invoiceNumber?: string;
15
+ orderId?: string;
16
+ options?: BkashClientOptions;
17
+ className?: string;
18
+ children?: any;
19
+ }
20
+ declare function BkashButton({ amount, invoiceNumber, orderId, options, className, children, }: BkashButtonProps): react.DetailedReactHTMLElement<{
21
+ type: string;
22
+ onClick: () => Promise<void>;
23
+ disabled: boolean;
24
+ className: string;
25
+ }, HTMLElement>;
26
+
27
+ export { BkashButton, type BkashButtonProps, useBkash };
@@ -0,0 +1,27 @@
1
+ import * as react from 'react';
2
+ import { BkashClientOptions, BkashClientState, InitiateCheckoutParams, BkashClient } from './index.js';
3
+
4
+ declare function useBkash(options?: BkashClientOptions): {
5
+ state: BkashClientState;
6
+ error: Error | null;
7
+ paymentId: string | null;
8
+ checkout: (params: InitiateCheckoutParams) => Promise<void>;
9
+ reset: () => void;
10
+ client: BkashClient;
11
+ };
12
+ interface BkashButtonProps {
13
+ amount?: number | string;
14
+ invoiceNumber?: string;
15
+ orderId?: string;
16
+ options?: BkashClientOptions;
17
+ className?: string;
18
+ children?: any;
19
+ }
20
+ declare function BkashButton({ amount, invoiceNumber, orderId, options, className, children, }: BkashButtonProps): react.DetailedReactHTMLElement<{
21
+ type: string;
22
+ onClick: () => Promise<void>;
23
+ disabled: boolean;
24
+ className: string;
25
+ }, HTMLElement>;
26
+
27
+ export { BkashButton, type BkashButtonProps, useBkash };
package/dist/react.js ADDED
@@ -0,0 +1,65 @@
1
+ import { BkashClient } from './chunk-FXLW32P4.js';
2
+ import './chunk-DGUM43GV.js';
3
+ import { useState, useEffect, useCallback, createElement } from 'react';
4
+
5
+ function useBkash(options) {
6
+ const [client] = useState(() => new BkashClient(options));
7
+ const [state, setState] = useState(client.getState());
8
+ const [error, setError] = useState(null);
9
+ useEffect(() => {
10
+ return client.subscribe((newState) => setState(newState));
11
+ }, [client]);
12
+ const checkout = useCallback(
13
+ async (params) => {
14
+ setError(null);
15
+ try {
16
+ await client.checkout(params);
17
+ } catch (err) {
18
+ const errorObj = err instanceof Error ? err : new Error(String(err));
19
+ setError(errorObj);
20
+ throw errorObj;
21
+ }
22
+ },
23
+ [client]
24
+ );
25
+ const reset = useCallback(() => {
26
+ setError(null);
27
+ client.reset();
28
+ }, [client]);
29
+ return {
30
+ state,
31
+ error,
32
+ paymentId: client.getPaymentId(),
33
+ checkout,
34
+ reset,
35
+ client
36
+ };
37
+ }
38
+ function BkashButton({
39
+ amount,
40
+ invoiceNumber,
41
+ orderId,
42
+ options,
43
+ className,
44
+ children
45
+ }) {
46
+ const { state, checkout } = useBkash(options);
47
+ const handleClick = async () => {
48
+ if (state === "creating") return;
49
+ await checkout({ amount, invoiceNumber, orderId });
50
+ };
51
+ return createElement(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ onClick: handleClick,
56
+ disabled: state === "creating",
57
+ className: className || "bkash-pay-btn"
58
+ },
59
+ children || (state === "creating" ? "Connecting to bKash..." : "Pay with bKash")
60
+ );
61
+ }
62
+
63
+ export { BkashButton, useBkash };
64
+ //# sourceMappingURL=react.js.map
65
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/react.ts"],"names":[],"mappings":";;;;AAQO,SAAS,SAAS,OAAA,EAA8B;AACrD,EAAA,MAAM,CAAC,MAAM,CAAA,GAAI,QAAA,CAAS,MAAM,IAAI,WAAA,CAAY,OAAO,CAAC,CAAA;AACxD,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,IAAI,QAAA,CAA2B,MAAA,CAAO,UAAU,CAAA;AACtE,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAuB,IAAI,CAAA;AAErD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,OAAO,OAAO,SAAA,CAAU,CAAC,QAAA,KAAa,QAAA,CAAS,QAAQ,CAAC,CAAA;AAAA,EAC1D,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,MAAM,QAAA,GAAW,WAAA;AAAA,IACf,OAAO,MAAA,KAAmC;AACxC,MAAA,QAAA,CAAS,IAAI,CAAA;AACb,MAAA,IAAI;AACF,QAAA,MAAM,MAAA,CAAO,SAAS,MAAM,CAAA;AAAA,MAC9B,SAAS,GAAA,EAAc;AACrB,QAAA,MAAM,QAAA,GAAW,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AACnE,QAAA,QAAA,CAAS,QAAQ,CAAA;AACjB,QAAA,MAAM,QAAA;AAAA,MACR;AAAA,IACF,CAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,KAAA,GAAQ,YAAY,MAAM;AAC9B,IAAA,QAAA,CAAS,IAAI,CAAA;AACb,IAAA,MAAA,CAAO,KAAA,EAAM;AAAA,EACf,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA;AAEX,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA,EAAW,OAAO,YAAA,EAAa;AAAA,IAC/B,QAAA;AAAA,IACA,KAAA;AAAA,IACA;AAAA,GACF;AACF;AAWO,SAAS,WAAA,CAAY;AAAA,EAC1B,MAAA;AAAA,EACA,aAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,EAAE,KAAA,EAAO,QAAA,EAAS,GAAI,SAAS,OAAO,CAAA;AAE5C,EAAA,MAAM,cAAc,YAAY;AAC9B,IAAA,IAAI,UAAU,UAAA,EAAY;AAC1B,IAAA,MAAM,QAAA,CAAS,EAAE,MAAA,EAAQ,aAAA,EAAe,SAAS,CAAA;AAAA,EACnD,CAAA;AAEA,EAAA,OAAO,aAAA;AAAA,IACL,QAAA;AAAA,IACA;AAAA,MACE,IAAA,EAAM,QAAA;AAAA,MACN,OAAA,EAAS,WAAA;AAAA,MACT,UAAU,KAAA,KAAU,UAAA;AAAA,MACpB,WAAW,SAAA,IAAa;AAAA,KAC1B;AAAA,IACA,QAAA,KAAa,KAAA,KAAU,UAAA,GAAa,wBAAA,GAA2B,gBAAA;AAAA,GACjE;AACF","file":"react.js","sourcesContent":["import { useState, useEffect, useCallback, createElement } from 'react';\nimport {\n BkashClient,\n type BkashClientOptions,\n type BkashClientState,\n type InitiateCheckoutParams,\n} from './index.js';\n\nexport function useBkash(options?: BkashClientOptions) {\n const [client] = useState(() => new BkashClient(options));\n const [state, setState] = useState<BkashClientState>(client.getState());\n const [error, setError] = useState<Error | null>(null);\n\n useEffect(() => {\n return client.subscribe((newState) => setState(newState));\n }, [client]);\n\n const checkout = useCallback(\n async (params: InitiateCheckoutParams) => {\n setError(null);\n try {\n await client.checkout(params);\n } catch (err: unknown) {\n const errorObj = err instanceof Error ? err : new Error(String(err));\n setError(errorObj);\n throw errorObj;\n }\n },\n [client]\n );\n\n const reset = useCallback(() => {\n setError(null);\n client.reset();\n }, [client]);\n\n return {\n state,\n error,\n paymentId: client.getPaymentId(),\n checkout,\n reset,\n client,\n };\n}\n\nexport interface BkashButtonProps {\n amount?: number | string;\n invoiceNumber?: string;\n orderId?: string;\n options?: BkashClientOptions;\n className?: string;\n children?: any;\n}\n\nexport function BkashButton({\n amount,\n invoiceNumber,\n orderId,\n options,\n className,\n children,\n}: BkashButtonProps) {\n const { state, checkout } = useBkash(options);\n\n const handleClick = async () => {\n if (state === 'creating') return;\n await checkout({ amount, invoiceNumber, orderId });\n };\n\n return createElement(\n 'button',\n {\n type: 'button',\n onClick: handleClick,\n disabled: state === 'creating',\n className: className || 'bkash-pay-btn',\n },\n children || (state === 'creating' ? 'Connecting to bKash...' : 'Pay with bKash')\n );\n}\n"]}
@@ -0,0 +1,141 @@
1
+ 'use strict';
2
+
3
+ // src/index.ts
4
+ var BkashClient = class {
5
+ state = "idle";
6
+ options;
7
+ currentPaymentId = null;
8
+ listeners = /* @__PURE__ */ new Set();
9
+ constructor(options) {
10
+ this.options = {
11
+ createUrl: "/api/bkash/create",
12
+ ...options
13
+ };
14
+ }
15
+ getState() {
16
+ return this.state;
17
+ }
18
+ getPaymentId() {
19
+ return this.currentPaymentId;
20
+ }
21
+ /**
22
+ * Returns human-readable UI guidance for the current client state.
23
+ * Specifically guarantees that unknown or timed-out outcomes are presented as
24
+ * "payment pending, do not pay again" rather than a false failure.
25
+ */
26
+ getStateMessage() {
27
+ switch (this.state) {
28
+ case "idle":
29
+ return "Ready to initiate checkout.";
30
+ case "creating":
31
+ return "Initializing payment session with bKash...";
32
+ case "awaiting_user":
33
+ return "Redirecting to bKash secure payment page...";
34
+ case "verifying":
35
+ return "Verifying payment with bKash...";
36
+ case "success":
37
+ return "Payment completed successfully!";
38
+ case "pending":
39
+ case "timeout":
40
+ return "Payment pending, do not pay again. Please wait while your transaction is reconciled with bKash.";
41
+ case "cancelled":
42
+ return "Payment was cancelled.";
43
+ case "offline":
44
+ return "Device is offline. Please check your internet connection before retrying.";
45
+ case "error":
46
+ return "An error occurred during checkout.";
47
+ default:
48
+ return "";
49
+ }
50
+ }
51
+ subscribe(listener) {
52
+ this.listeners.add(listener);
53
+ return () => this.listeners.delete(listener);
54
+ }
55
+ cancel() {
56
+ this.setState("cancelled");
57
+ this.options.onCancel?.();
58
+ }
59
+ setPending(paymentId) {
60
+ if (paymentId) this.currentPaymentId = paymentId;
61
+ this.setState("pending");
62
+ }
63
+ setState(newState) {
64
+ this.state = newState;
65
+ this.options.onStateChange?.(newState);
66
+ this.listeners.forEach((fn) => fn(newState));
67
+ }
68
+ /**
69
+ * Initiates payment flow by calling the merchant backend,
70
+ * obtaining the gateway URL, and redirecting the customer.
71
+ */
72
+ async checkout(params = {}) {
73
+ if (typeof navigator !== "undefined" && navigator.onLine === false) {
74
+ this.setState("offline");
75
+ const offlineErr = new Error("Device is offline. Please check your internet connection.");
76
+ this.options.onError?.(offlineErr);
77
+ throw offlineErr;
78
+ }
79
+ try {
80
+ this.setState("creating");
81
+ const defaultCallback = typeof window !== "undefined" ? window.location?.href : "";
82
+ const res = await fetch(this.options.createUrl, {
83
+ method: "POST",
84
+ headers: { "Content-Type": "application/json" },
85
+ body: JSON.stringify({
86
+ amount: params.amount,
87
+ invoiceNumber: params.invoiceNumber,
88
+ orderId: params.orderId,
89
+ callbackUrl: this.options.callbackUrl || defaultCallback,
90
+ payerReference: params.payerReference,
91
+ metadata: params.metadata
92
+ })
93
+ });
94
+ if (!res.ok) {
95
+ throw new Error(`Failed to create payment session: HTTP ${res.status}`);
96
+ }
97
+ const data = await res.json();
98
+ if (!data.redirectUrl || !data.paymentId) {
99
+ throw new Error(data.error || "Invalid session response from payment server.");
100
+ }
101
+ this.currentPaymentId = data.paymentId;
102
+ this.setState("awaiting_user");
103
+ if (typeof window !== "undefined" && window.location) {
104
+ window.location.href = data.redirectUrl;
105
+ }
106
+ } catch (err) {
107
+ const error = err instanceof Error ? err : new Error(String(err));
108
+ const isTimeout = error.name === "AbortError" || error.name === "TimeoutError" || /timeout|abort/i.test(error.message);
109
+ if (isTimeout) {
110
+ this.setState("pending");
111
+ } else {
112
+ this.setState("error");
113
+ }
114
+ this.options.onError?.(error);
115
+ throw error;
116
+ }
117
+ }
118
+ reset() {
119
+ this.currentPaymentId = null;
120
+ this.setState("idle");
121
+ }
122
+ };
123
+
124
+ // src/svelte.ts
125
+ function createBkashStore(options) {
126
+ const client = new BkashClient(options);
127
+ return {
128
+ subscribe: (run) => {
129
+ run({ state: client.getState(), paymentId: client.getPaymentId() });
130
+ return client.subscribe((state) => {
131
+ run({ state, paymentId: client.getPaymentId() });
132
+ });
133
+ },
134
+ checkout: (params) => client.checkout(params),
135
+ reset: () => client.reset()
136
+ };
137
+ }
138
+
139
+ exports.createBkashStore = createBkashStore;
140
+ //# sourceMappingURL=svelte.cjs.map
141
+ //# sourceMappingURL=svelte.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/svelte.ts"],"names":[],"mappings":"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","file":"svelte.cjs","sourcesContent":["/**\n * @bkash/client\n * Universal, headless client SDK for bKash payment integrations.\n */\n\nexport type BkashClientState =\n | 'idle'\n | 'creating'\n | 'awaiting_user'\n | 'verifying'\n | 'success'\n | 'pending'\n | 'cancelled'\n | 'timeout'\n | 'offline'\n | 'error';\n\nexport interface BkashClientOptions {\n /**\n * Endpoint on merchant backend to create payment session.\n * Defaults to \"/api/bkash/create\".\n */\n createUrl?: string;\n /**\n * Callback URL registered with merchant backend.\n */\n callbackUrl?: string;\n /**\n * Hook triggered on state transition.\n */\n onStateChange?: (state: BkashClientState) => void;\n /**\n * Hook triggered when payment completes successfully.\n */\n onSuccess?: (paymentId: string) => void;\n /**\n * Hook triggered on payment error.\n */\n onError?: (error: Error) => void;\n /**\n * Hook triggered if user cancels payment.\n */\n onCancel?: () => void;\n}\n\n/**\n * All fields are optional hints. bkash-server decides the amount and invoice from its own\n * data and ignores any amount or invoice sent from the browser.\n */\nexport interface InitiateCheckoutParams {\n amount?: number | string;\n invoiceNumber?: string;\n orderId?: string;\n payerReference?: string;\n metadata?: Record<string, string>;\n}\n\nexport class BkashClient {\n private state: BkashClientState = 'idle';\n private options: BkashClientOptions;\n private currentPaymentId: string | null = null;\n private listeners = new Set<(state: BkashClientState) => void>();\n\n constructor(options?: BkashClientOptions) {\n this.options = {\n createUrl: '/api/bkash/create',\n ...options,\n };\n }\n\n public getState(): BkashClientState {\n return this.state;\n }\n\n public getPaymentId(): string | null {\n return this.currentPaymentId;\n }\n\n /**\n * Returns human-readable UI guidance for the current client state.\n * Specifically guarantees that unknown or timed-out outcomes are presented as\n * \"payment pending, do not pay again\" rather than a false failure.\n */\n public getStateMessage(): string {\n switch (this.state) {\n case 'idle':\n return 'Ready to initiate checkout.';\n case 'creating':\n return 'Initializing payment session with bKash...';\n case 'awaiting_user':\n return 'Redirecting to bKash secure payment page...';\n case 'verifying':\n return 'Verifying payment with bKash...';\n case 'success':\n return 'Payment completed successfully!';\n case 'pending':\n case 'timeout':\n return 'Payment pending, do not pay again. Please wait while your transaction is reconciled with bKash.';\n case 'cancelled':\n return 'Payment was cancelled.';\n case 'offline':\n return 'Device is offline. Please check your internet connection before retrying.';\n case 'error':\n return 'An error occurred during checkout.';\n default:\n return '';\n }\n }\n\n public subscribe(listener: (state: BkashClientState) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n public cancel(): void {\n this.setState('cancelled');\n this.options.onCancel?.();\n }\n\n public setPending(paymentId?: string): void {\n if (paymentId) this.currentPaymentId = paymentId;\n this.setState('pending');\n }\n\n private setState(newState: BkashClientState): void {\n this.state = newState;\n this.options.onStateChange?.(newState);\n this.listeners.forEach((fn) => fn(newState));\n }\n\n /**\n * Initiates payment flow by calling the merchant backend,\n * obtaining the gateway URL, and redirecting the customer.\n */\n public async checkout(params: InitiateCheckoutParams = {}): Promise<void> {\n // Offline pre-check\n if (typeof navigator !== 'undefined' && navigator.onLine === false) {\n this.setState('offline');\n const offlineErr = new Error('Device is offline. Please check your internet connection.');\n this.options.onError?.(offlineErr);\n throw offlineErr;\n }\n\n try {\n this.setState('creating');\n\n const defaultCallback = typeof window !== 'undefined' ? window.location?.href : '';\n const res = await fetch(this.options.createUrl!, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n amount: params.amount,\n invoiceNumber: params.invoiceNumber,\n orderId: params.orderId,\n callbackUrl: this.options.callbackUrl || defaultCallback,\n payerReference: params.payerReference,\n metadata: params.metadata,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Failed to create payment session: HTTP ${res.status}`);\n }\n\n const data = (await res.json()) as {\n redirectUrl?: string;\n paymentId?: string;\n error?: string;\n };\n if (!data.redirectUrl || !data.paymentId) {\n throw new Error(data.error || 'Invalid session response from payment server.');\n }\n\n this.currentPaymentId = data.paymentId;\n this.setState('awaiting_user');\n\n // Launch bKash Hosted Checkout\n if (typeof window !== 'undefined' && window.location) {\n window.location.href = data.redirectUrl;\n }\n } catch (err: unknown) {\n const error = err instanceof Error ? err : new Error(String(err));\n const isTimeout =\n error.name === 'AbortError' ||\n error.name === 'TimeoutError' ||\n /timeout|abort/i.test(error.message);\n\n if (isTimeout) {\n // Under AUD-08: timeout / unknown outcome MUST display pending (\"do not pay again\")\n this.setState('pending');\n } else {\n this.setState('error');\n }\n\n this.options.onError?.(error);\n throw error;\n }\n }\n\n public reset(): void {\n this.currentPaymentId = null;\n this.setState('idle');\n }\n}\n","import {\n BkashClient,\n type BkashClientOptions,\n type BkashClientState,\n type InitiateCheckoutParams,\n} from './index.js';\n\nexport interface BkashSvelteStore {\n subscribe: (run: (value: { state: BkashClientState; paymentId: string | null }) => void) => () => void;\n checkout: (params: InitiateCheckoutParams) => Promise<void>;\n reset: () => void;\n}\n\n/**\n * Svelte readable store wrapper for bKash Client.\n */\nexport function createBkashStore(options?: BkashClientOptions): BkashSvelteStore {\n const client = new BkashClient(options);\n\n return {\n subscribe: (run) => {\n run({ state: client.getState(), paymentId: client.getPaymentId() });\n return client.subscribe((state) => {\n run({ state, paymentId: client.getPaymentId() });\n });\n },\n checkout: (params) => client.checkout(params),\n reset: () => client.reset(),\n };\n}\n"]}
@@ -0,0 +1,16 @@
1
+ import { BkashClientState, InitiateCheckoutParams, BkashClientOptions } from './index.cjs';
2
+
3
+ interface BkashSvelteStore {
4
+ subscribe: (run: (value: {
5
+ state: BkashClientState;
6
+ paymentId: string | null;
7
+ }) => void) => () => void;
8
+ checkout: (params: InitiateCheckoutParams) => Promise<void>;
9
+ reset: () => void;
10
+ }
11
+ /**
12
+ * Svelte readable store wrapper for bKash Client.
13
+ */
14
+ declare function createBkashStore(options?: BkashClientOptions): BkashSvelteStore;
15
+
16
+ export { type BkashSvelteStore, createBkashStore };
@@ -0,0 +1,16 @@
1
+ import { BkashClientState, InitiateCheckoutParams, BkashClientOptions } from './index.js';
2
+
3
+ interface BkashSvelteStore {
4
+ subscribe: (run: (value: {
5
+ state: BkashClientState;
6
+ paymentId: string | null;
7
+ }) => void) => () => void;
8
+ checkout: (params: InitiateCheckoutParams) => Promise<void>;
9
+ reset: () => void;
10
+ }
11
+ /**
12
+ * Svelte readable store wrapper for bKash Client.
13
+ */
14
+ declare function createBkashStore(options?: BkashClientOptions): BkashSvelteStore;
15
+
16
+ export { type BkashSvelteStore, createBkashStore };
package/dist/svelte.js ADDED
@@ -0,0 +1,21 @@
1
+ import { BkashClient } from './chunk-FXLW32P4.js';
2
+ import './chunk-DGUM43GV.js';
3
+
4
+ // src/svelte.ts
5
+ function createBkashStore(options) {
6
+ const client = new BkashClient(options);
7
+ return {
8
+ subscribe: (run) => {
9
+ run({ state: client.getState(), paymentId: client.getPaymentId() });
10
+ return client.subscribe((state) => {
11
+ run({ state, paymentId: client.getPaymentId() });
12
+ });
13
+ },
14
+ checkout: (params) => client.checkout(params),
15
+ reset: () => client.reset()
16
+ };
17
+ }
18
+
19
+ export { createBkashStore };
20
+ //# sourceMappingURL=svelte.js.map
21
+ //# sourceMappingURL=svelte.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/svelte.ts"],"names":[],"mappings":";;;;AAgBO,SAAS,iBAAiB,OAAA,EAAgD;AAC/E,EAAA,MAAM,MAAA,GAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAEtC,EAAA,OAAO;AAAA,IACL,SAAA,EAAW,CAAC,GAAA,KAAQ;AAClB,MAAA,GAAA,CAAI,EAAE,OAAO,MAAA,CAAO,QAAA,IAAY,SAAA,EAAW,MAAA,CAAO,YAAA,EAAa,EAAG,CAAA;AAClE,MAAA,OAAO,MAAA,CAAO,SAAA,CAAU,CAAC,KAAA,KAAU;AACjC,QAAA,GAAA,CAAI,EAAE,KAAA,EAAO,SAAA,EAAW,MAAA,CAAO,YAAA,IAAgB,CAAA;AAAA,MACjD,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,QAAA,EAAU,CAAC,MAAA,KAAW,MAAA,CAAO,SAAS,MAAM,CAAA;AAAA,IAC5C,KAAA,EAAO,MAAM,MAAA,CAAO,KAAA;AAAM,GAC5B;AACF","file":"svelte.js","sourcesContent":["import {\n BkashClient,\n type BkashClientOptions,\n type BkashClientState,\n type InitiateCheckoutParams,\n} from './index.js';\n\nexport interface BkashSvelteStore {\n subscribe: (run: (value: { state: BkashClientState; paymentId: string | null }) => void) => () => void;\n checkout: (params: InitiateCheckoutParams) => Promise<void>;\n reset: () => void;\n}\n\n/**\n * Svelte readable store wrapper for bKash Client.\n */\nexport function createBkashStore(options?: BkashClientOptions): BkashSvelteStore {\n const client = new BkashClient(options);\n\n return {\n subscribe: (run) => {\n run({ state: client.getState(), paymentId: client.getPaymentId() });\n return client.subscribe((state) => {\n run({ state, paymentId: client.getPaymentId() });\n });\n },\n checkout: (params) => client.checkout(params),\n reset: () => client.reset(),\n };\n}\n"]}