@rajeev02/payments 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.
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @rajeev02/payments — Cards & Subscriptions
3
+ * Card tokenization (RBI compliant), saved cards, recurring billing
4
+ */
5
+ export interface CardInfo {
6
+ /** Tokenized card reference (never store raw card numbers) */
7
+ tokenRef: string;
8
+ /** Last 4 digits for display */
9
+ last4: string;
10
+ /** Card network */
11
+ network: "visa" | "mastercard" | "rupay" | "amex" | "dinersclub";
12
+ /** Card type */
13
+ type: "credit" | "debit" | "prepaid";
14
+ /** Issuing bank name */
15
+ issuerBank?: string;
16
+ /** Expiry month */
17
+ expiryMonth: number;
18
+ /** Expiry year */
19
+ expiryYear: number;
20
+ /** Cardholder name */
21
+ holderName?: string;
22
+ /** Whether card supports recurring/mandate */
23
+ supportsRecurring: boolean;
24
+ }
25
+ export interface SubscriptionPlan {
26
+ id: string;
27
+ name: string;
28
+ description?: string;
29
+ amount: number;
30
+ currency: string;
31
+ interval: "daily" | "weekly" | "monthly" | "quarterly" | "yearly";
32
+ intervalCount: number;
33
+ trialDays?: number;
34
+ features?: string[];
35
+ }
36
+ export interface Subscription {
37
+ id: string;
38
+ planId: string;
39
+ customerId: string;
40
+ status: "active" | "paused" | "cancelled" | "past_due" | "trialing" | "expired";
41
+ currentPeriodStart: string;
42
+ currentPeriodEnd: string;
43
+ cancelledAt?: string;
44
+ paymentMethod: "card" | "upi_mandate" | "emandate";
45
+ tokenRef?: string;
46
+ nextBillingDate: string;
47
+ amount: number;
48
+ }
49
+ /**
50
+ * Detect card network from number prefix (first 6 digits)
51
+ */
52
+ export declare function detectCardNetwork(cardNumber: string): CardInfo["network"] | null;
53
+ /**
54
+ * Format card number with spaces: 4111111111111111 → 4111 1111 1111 1111
55
+ */
56
+ export declare function formatCardNumber(cardNumber: string): string;
57
+ /**
58
+ * Validate card number using Luhn algorithm
59
+ */
60
+ export declare function validateCardNumber(cardNumber: string): boolean;
61
+ /**
62
+ * Calculate subscription renewal dates
63
+ */
64
+ export declare function getNextBillingDate(plan: SubscriptionPlan, currentDate?: Date): Date;
65
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cards/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,QAAQ;IACvB,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,CAAC;IACjE,gBAAgB;IAChB,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,wBAAwB;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EACF,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,UAAU,GACV,UAAU,GACV,SAAS,CAAC;IACd,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,aAAa,GAAG,UAAU,CAAC;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,GACjB,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAQ5B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAM3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAgB9D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,gBAAgB,EACtB,WAAW,GAAE,IAAiB,GAC7B,IAAI,CAoBN"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /**
3
+ * @rajeev02/payments — Cards & Subscriptions
4
+ * Card tokenization (RBI compliant), saved cards, recurring billing
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.detectCardNetwork = detectCardNetwork;
8
+ exports.formatCardNumber = formatCardNumber;
9
+ exports.validateCardNumber = validateCardNumber;
10
+ exports.getNextBillingDate = getNextBillingDate;
11
+ /**
12
+ * Detect card network from number prefix (first 6 digits)
13
+ */
14
+ function detectCardNetwork(cardNumber) {
15
+ const digits = cardNumber.replace(/\s/g, "");
16
+ if (digits.startsWith("4"))
17
+ return "visa";
18
+ if (/^5[1-5]/.test(digits) || /^2[2-7]/.test(digits))
19
+ return "mastercard";
20
+ if (/^6(0|5|52[12]|53[89]|5[4-9]|[6-9])/.test(digits))
21
+ return "rupay";
22
+ if (/^3[47]/.test(digits))
23
+ return "amex";
24
+ if (/^3(0[0-5]|[68])/.test(digits))
25
+ return "dinersclub";
26
+ return null;
27
+ }
28
+ /**
29
+ * Format card number with spaces: 4111111111111111 → 4111 1111 1111 1111
30
+ */
31
+ function formatCardNumber(cardNumber) {
32
+ const digits = cardNumber.replace(/\D/g, "");
33
+ if (detectCardNetwork(digits) === "amex") {
34
+ return digits.replace(/(\d{4})(\d{6})(\d{5})/, "$1 $2 $3");
35
+ }
36
+ return digits.replace(/(\d{4})/g, "$1 ").trim();
37
+ }
38
+ /**
39
+ * Validate card number using Luhn algorithm
40
+ */
41
+ function validateCardNumber(cardNumber) {
42
+ const digits = cardNumber.replace(/\D/g, "");
43
+ if (digits.length < 13 || digits.length > 19)
44
+ return false;
45
+ let sum = 0;
46
+ let isEven = false;
47
+ for (let i = digits.length - 1; i >= 0; i--) {
48
+ let d = parseInt(digits[i], 10);
49
+ if (isEven) {
50
+ d *= 2;
51
+ if (d > 9)
52
+ d -= 9;
53
+ }
54
+ sum += d;
55
+ isEven = !isEven;
56
+ }
57
+ return sum % 10 === 0;
58
+ }
59
+ /**
60
+ * Calculate subscription renewal dates
61
+ */
62
+ function getNextBillingDate(plan, currentDate = new Date()) {
63
+ const next = new Date(currentDate);
64
+ switch (plan.interval) {
65
+ case "daily":
66
+ next.setDate(next.getDate() + plan.intervalCount);
67
+ break;
68
+ case "weekly":
69
+ next.setDate(next.getDate() + 7 * plan.intervalCount);
70
+ break;
71
+ case "monthly":
72
+ next.setMonth(next.getMonth() + plan.intervalCount);
73
+ break;
74
+ case "quarterly":
75
+ next.setMonth(next.getMonth() + 3 * plan.intervalCount);
76
+ break;
77
+ case "yearly":
78
+ next.setFullYear(next.getFullYear() + plan.intervalCount);
79
+ break;
80
+ }
81
+ return next;
82
+ }
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cards/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AA0DH,8CAUC;AAKD,4CAMC;AAKD,gDAgBC;AAKD,gDAuBC;AAzED;;GAEG;AACH,SAAgB,iBAAiB,CAC/B,UAAkB;IAElB,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1C,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,YAAY,CAAC;IAC1E,IAAI,oCAAoC,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,OAAO,CAAC;IACtE,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACzC,IAAI,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,YAAY,CAAC;IACxD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,UAAkB;IACjD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,iBAAiB,CAAC,MAAM,CAAC,KAAK,MAAM,EAAE,CAAC;QACzC,OAAO,MAAM,CAAC,OAAO,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,UAAkB;IACnD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC7C,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAE3D,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChC,IAAI,MAAM,EAAE,CAAC;YACX,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,GAAG,CAAC;gBAAE,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,GAAG,IAAI,CAAC,CAAC;QACT,MAAM,GAAG,CAAC,MAAM,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAChC,IAAsB,EACtB,cAAoB,IAAI,IAAI,EAAE;IAE9B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC;IACnC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,KAAK,OAAO;YACV,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;YAClD,MAAM;QACR,KAAK,QAAQ;YACX,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;YACtD,MAAM;QACR,KAAK,SAAS;YACZ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;YACpD,MAAM;QACR,KAAK,WAAW;YACd,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;YACxD,MAAM;QACR,KAAK,QAAQ;YACX,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1D,MAAM;IACV,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @rajeev02/payments
3
+ * Payments Abstraction SDK — India focused
4
+ * UPI, wallets, cards, subscriptions
5
+ *
6
+ * @author Rajeev Kumar Joshi
7
+ * @license MIT
8
+ */
9
+ export { generateUpiUri, generateUpiQrData, validateVpa, getPspName, UPI_PSP_HANDLES, } from "./upi";
10
+ export type { UpiConfig, UpiPaymentRequest, UpiPaymentResult, UpiMandateRequest, } from "./upi";
11
+ export { WalletManager } from "./wallet";
12
+ export type { WalletProvider, WalletConfig, WalletPaymentRequest, WalletPaymentResult, } from "./wallet";
13
+ export { detectCardNetwork, formatCardNumber, validateCardNumber, getNextBillingDate, } from "./cards";
14
+ export type { CardInfo, SubscriptionPlan, Subscription } from "./cards";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,UAAU,EACV,eAAe,GAChB,MAAM,OAAO,CAAC;AACf,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,YAAY,EACV,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,QAAQ,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNextBillingDate = exports.validateCardNumber = exports.formatCardNumber = exports.detectCardNetwork = exports.WalletManager = exports.UPI_PSP_HANDLES = exports.getPspName = exports.validateVpa = exports.generateUpiQrData = exports.generateUpiUri = void 0;
4
+ /**
5
+ * @rajeev02/payments
6
+ * Payments Abstraction SDK — India focused
7
+ * UPI, wallets, cards, subscriptions
8
+ *
9
+ * @author Rajeev Kumar Joshi
10
+ * @license MIT
11
+ */
12
+ var upi_1 = require("./upi");
13
+ Object.defineProperty(exports, "generateUpiUri", { enumerable: true, get: function () { return upi_1.generateUpiUri; } });
14
+ Object.defineProperty(exports, "generateUpiQrData", { enumerable: true, get: function () { return upi_1.generateUpiQrData; } });
15
+ Object.defineProperty(exports, "validateVpa", { enumerable: true, get: function () { return upi_1.validateVpa; } });
16
+ Object.defineProperty(exports, "getPspName", { enumerable: true, get: function () { return upi_1.getPspName; } });
17
+ Object.defineProperty(exports, "UPI_PSP_HANDLES", { enumerable: true, get: function () { return upi_1.UPI_PSP_HANDLES; } });
18
+ var wallet_1 = require("./wallet");
19
+ Object.defineProperty(exports, "WalletManager", { enumerable: true, get: function () { return wallet_1.WalletManager; } });
20
+ var cards_1 = require("./cards");
21
+ Object.defineProperty(exports, "detectCardNetwork", { enumerable: true, get: function () { return cards_1.detectCardNetwork; } });
22
+ Object.defineProperty(exports, "formatCardNumber", { enumerable: true, get: function () { return cards_1.formatCardNumber; } });
23
+ Object.defineProperty(exports, "validateCardNumber", { enumerable: true, get: function () { return cards_1.validateCardNumber; } });
24
+ Object.defineProperty(exports, "getNextBillingDate", { enumerable: true, get: function () { return cards_1.getNextBillingDate; } });
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,6BAMe;AALb,qGAAA,cAAc,OAAA;AACd,wGAAA,iBAAiB,OAAA;AACjB,kGAAA,WAAW,OAAA;AACX,iGAAA,UAAU,OAAA;AACV,sGAAA,eAAe,OAAA;AASjB,mCAAyC;AAAhC,uGAAA,aAAa,OAAA;AAQtB,iCAKiB;AAJf,0GAAA,iBAAiB,OAAA;AACjB,yGAAA,gBAAgB,OAAA;AAChB,2GAAA,kBAAkB,OAAA;AAClB,2GAAA,kBAAkB,OAAA"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * @rajeev02/payments — UPI Module
3
+ * UPI intent, collect request, QR code, autopay mandates
4
+ */
5
+ export interface UpiConfig {
6
+ /** Merchant VPA (e.g., merchant@paytm) */
7
+ merchantVpa: string;
8
+ /** Merchant name shown in UPI apps */
9
+ merchantName: string;
10
+ /** Merchant category code */
11
+ mcc?: string;
12
+ /** Transaction reference prefix */
13
+ txnRefPrefix?: string;
14
+ }
15
+ export interface UpiPaymentRequest {
16
+ /** Amount in INR (paisa precision) */
17
+ amount: number;
18
+ /** Payment description */
19
+ note: string;
20
+ /** Unique transaction reference */
21
+ txnRef?: string;
22
+ /** Customer VPA (for collect requests) */
23
+ customerVpa?: string;
24
+ /** Order ID from your backend */
25
+ orderId: string;
26
+ }
27
+ export interface UpiPaymentResult {
28
+ success: boolean;
29
+ txnId?: string;
30
+ txnRef?: string;
31
+ responseCode?: string;
32
+ approvalRefNo?: string;
33
+ status: "success" | "failed" | "pending" | "cancelled";
34
+ error?: string;
35
+ }
36
+ export interface UpiMandateRequest {
37
+ /** Customer VPA */
38
+ customerVpa: string;
39
+ /** Maximum amount per debit */
40
+ maxAmount: number;
41
+ /** Frequency: DAILY, WEEKLY, FORTNIGHTLY, MONTHLY, BIMONTHLY, QUARTERLY, HALFYEARLY, YEARLY */
42
+ frequency: string;
43
+ /** Start date (ISO) */
44
+ startDate: string;
45
+ /** End date (ISO) */
46
+ endDate: string;
47
+ /** Purpose description */
48
+ purpose: string;
49
+ }
50
+ /**
51
+ * Generate UPI deep link URI for intent-based payment
52
+ * Works with all UPI apps (GPay, PhonePe, Paytm, etc.)
53
+ */
54
+ export declare function generateUpiUri(config: UpiConfig, request: UpiPaymentRequest): string;
55
+ /**
56
+ * Generate UPI QR code data string
57
+ */
58
+ export declare function generateUpiQrData(config: UpiConfig, request: UpiPaymentRequest): string;
59
+ /**
60
+ * Validate a UPI VPA format
61
+ * Format: username@psp (e.g., rajeev@paytm, user@okicici)
62
+ */
63
+ export declare function validateVpa(vpa: string): boolean;
64
+ /**
65
+ * Known UPI PSP handles
66
+ */
67
+ export declare const UPI_PSP_HANDLES: Record<string, string>;
68
+ export declare function getPspName(vpa: string): string | null;
69
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upi/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,SAAS;IACxB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0CAA0C;IAC1C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,+FAA+F;IAC/F,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,0BAA0B;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAcR;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,iBAAiB,GACzB,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAWlD,CAAC;AAEF,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGrD"}
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ /**
3
+ * @rajeev02/payments — UPI Module
4
+ * UPI intent, collect request, QR code, autopay mandates
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.UPI_PSP_HANDLES = void 0;
8
+ exports.generateUpiUri = generateUpiUri;
9
+ exports.generateUpiQrData = generateUpiQrData;
10
+ exports.validateVpa = validateVpa;
11
+ exports.getPspName = getPspName;
12
+ /**
13
+ * Generate UPI deep link URI for intent-based payment
14
+ * Works with all UPI apps (GPay, PhonePe, Paytm, etc.)
15
+ */
16
+ function generateUpiUri(config, request) {
17
+ const txnRef = request.txnRef || `${config.txnRefPrefix || "TXN"}${Date.now()}`;
18
+ const params = new URLSearchParams({
19
+ pa: config.merchantVpa,
20
+ pn: config.merchantName,
21
+ am: request.amount.toFixed(2),
22
+ cu: "INR",
23
+ tn: request.note,
24
+ tr: txnRef,
25
+ });
26
+ if (config.mcc)
27
+ params.set("mc", config.mcc);
28
+ if (request.orderId)
29
+ params.set("tid", request.orderId);
30
+ return `upi://pay?${params.toString()}`;
31
+ }
32
+ /**
33
+ * Generate UPI QR code data string
34
+ */
35
+ function generateUpiQrData(config, request) {
36
+ return generateUpiUri(config, request);
37
+ }
38
+ /**
39
+ * Validate a UPI VPA format
40
+ * Format: username@psp (e.g., rajeev@paytm, user@okicici)
41
+ */
42
+ function validateVpa(vpa) {
43
+ return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9]+$/.test(vpa);
44
+ }
45
+ /**
46
+ * Known UPI PSP handles
47
+ */
48
+ exports.UPI_PSP_HANDLES = {
49
+ "@paytm": "Paytm",
50
+ "@okicici": "Google Pay (ICICI)",
51
+ "@okhdfcbank": "Google Pay (HDFC)",
52
+ "@oksbi": "Google Pay (SBI)",
53
+ "@ybl": "PhonePe (YES Bank)",
54
+ "@ibl": "PhonePe (ICICI)",
55
+ "@axl": "PhonePe (Axis)",
56
+ "@apl": "Amazon Pay",
57
+ "@freecharge": "Freecharge",
58
+ "@upi": "BHIM",
59
+ };
60
+ function getPspName(vpa) {
61
+ const handle = "@" + vpa.split("@")[1];
62
+ return exports.UPI_PSP_HANDLES[handle] ?? null;
63
+ }
64
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/upi/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAuDH,wCAiBC;AAKD,8CAKC;AAMD,kCAEC;AAkBD,gCAGC;AA5DD;;;GAGG;AACH,SAAgB,cAAc,CAC5B,MAAiB,EACjB,OAA0B;IAE1B,MAAM,MAAM,GACV,OAAO,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,IAAI,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,EAAE,EAAE,MAAM,CAAC,WAAW;QACtB,EAAE,EAAE,MAAM,CAAC,YAAY;QACvB,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7B,EAAE,EAAE,KAAK;QACT,EAAE,EAAE,OAAO,CAAC,IAAI;QAChB,EAAE,EAAE,MAAM;KACX,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,GAAG;QAAE,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,OAAO,CAAC,OAAO;QAAE,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,OAAO,aAAa,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,SAAgB,iBAAiB,CAC/B,MAAiB,EACjB,OAA0B;IAE1B,OAAO,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED;;;GAGG;AACH,SAAgB,WAAW,CAAC,GAAW;IACrC,OAAO,gCAAgC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACpD,CAAC;AAED;;GAEG;AACU,QAAA,eAAe,GAA2B;IACrD,QAAQ,EAAE,OAAO;IACjB,UAAU,EAAE,oBAAoB;IAChC,aAAa,EAAE,mBAAmB;IAClC,QAAQ,EAAE,kBAAkB;IAC5B,MAAM,EAAE,oBAAoB;IAC5B,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,gBAAgB;IACxB,MAAM,EAAE,YAAY;IACpB,aAAa,EAAE,YAAY;IAC3B,MAAM,EAAE,MAAM;CACf,CAAC;AAEF,SAAgB,UAAU,CAAC,GAAW;IACpC,MAAM,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,OAAO,uBAAe,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;AACzC,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @rajeev02/payments — Wallet Module
3
+ * Abstraction over PhonePe, Paytm, Amazon Pay, Freecharge wallets
4
+ */
5
+ export type WalletProvider = "paytm" | "phonepe" | "amazon_pay" | "freecharge" | "mobikwik" | "jio_pay";
6
+ export interface WalletConfig {
7
+ provider: WalletProvider;
8
+ merchantId: string;
9
+ merchantKey?: string;
10
+ environment: "sandbox" | "production";
11
+ callbackUrl: string;
12
+ }
13
+ export interface WalletPaymentRequest {
14
+ orderId: string;
15
+ amount: number;
16
+ customerId: string;
17
+ customerPhone?: string;
18
+ customerEmail?: string;
19
+ description?: string;
20
+ }
21
+ export interface WalletPaymentResult {
22
+ success: boolean;
23
+ provider: WalletProvider;
24
+ txnId?: string;
25
+ orderId: string;
26
+ status: "success" | "failed" | "pending" | "cancelled";
27
+ walletBalance?: number;
28
+ error?: string;
29
+ }
30
+ /**
31
+ * Wallet Manager — handles payment flow across wallet providers
32
+ */
33
+ export declare class WalletManager {
34
+ private configs;
35
+ /** Register a wallet provider */
36
+ register(config: WalletConfig): void;
37
+ /** Get all registered wallet providers */
38
+ getAvailableWallets(): WalletProvider[];
39
+ /** Check if a wallet is registered */
40
+ isAvailable(provider: WalletProvider): boolean;
41
+ /** Generate checkout URL/payload for a wallet */
42
+ generateCheckout(provider: WalletProvider, request: WalletPaymentRequest): Record<string, unknown> | null;
43
+ }
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/wallet/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,cAAc,GACtB,OAAO,GACP,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,UAAU,GACV,SAAS,CAAC;AAEd,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,SAAS,GAAG,YAAY,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IACvD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAgD;IAE/D,iCAAiC;IACjC,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAIpC,0CAA0C;IAC1C,mBAAmB,IAAI,cAAc,EAAE;IAIvC,sCAAsC;IACtC,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO;IAI9C,iDAAiD;IACjD,gBAAgB,CACd,QAAQ,EAAE,cAAc,EACxB,OAAO,EAAE,oBAAoB,GAC5B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAgBlC"}
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ /**
3
+ * @rajeev02/payments — Wallet Module
4
+ * Abstraction over PhonePe, Paytm, Amazon Pay, Freecharge wallets
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.WalletManager = void 0;
8
+ /**
9
+ * Wallet Manager — handles payment flow across wallet providers
10
+ */
11
+ class WalletManager {
12
+ constructor() {
13
+ this.configs = new Map();
14
+ }
15
+ /** Register a wallet provider */
16
+ register(config) {
17
+ this.configs.set(config.provider, config);
18
+ }
19
+ /** Get all registered wallet providers */
20
+ getAvailableWallets() {
21
+ return Array.from(this.configs.keys());
22
+ }
23
+ /** Check if a wallet is registered */
24
+ isAvailable(provider) {
25
+ return this.configs.has(provider);
26
+ }
27
+ /** Generate checkout URL/payload for a wallet */
28
+ generateCheckout(provider, request) {
29
+ const config = this.configs.get(provider);
30
+ if (!config)
31
+ return null;
32
+ return {
33
+ provider,
34
+ merchantId: config.merchantId,
35
+ environment: config.environment,
36
+ callbackUrl: config.callbackUrl,
37
+ orderId: request.orderId,
38
+ amount: request.amount,
39
+ customerId: request.customerId,
40
+ phone: request.customerPhone,
41
+ email: request.customerEmail,
42
+ };
43
+ }
44
+ }
45
+ exports.WalletManager = WalletManager;
46
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/wallet/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAqCH;;GAEG;AACH,MAAa,aAAa;IAA1B;QACU,YAAO,GAAsC,IAAI,GAAG,EAAE,CAAC;IAqCjE,CAAC;IAnCC,iCAAiC;IACjC,QAAQ,CAAC,MAAoB;QAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,0CAA0C;IAC1C,mBAAmB;QACjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,sCAAsC;IACtC,WAAW,CAAC,QAAwB;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IAED,iDAAiD;IACjD,gBAAgB,CACd,QAAwB,EACxB,OAA6B;QAE7B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAEzB,OAAO;YACL,QAAQ;YACR,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;YAC/B,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,KAAK,EAAE,OAAO,CAAC,aAAa;YAC5B,KAAK,EAAE,OAAO,CAAC,aAAa;SAC7B,CAAC;IACJ,CAAC;CACF;AAtCD,sCAsCC"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@rajeev02/payments",
3
+ "version": "0.1.0",
4
+ "description": "Payments Abstraction SDK — UPI, wallets, cards, subscriptions, split payments (India-focused)",
5
+ "main": "lib/index.js",
6
+ "author": "Rajeev Kumar Joshi <rajeevjoshi91@gmail.com> (https://rajeev02.github.io)",
7
+ "license": "MIT",
8
+ "types": "lib/index.d.ts",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "clean": "rm -rf lib",
12
+ "prepublishOnly": "npm run build"
13
+ },
14
+ "keywords": [
15
+ "react-native",
16
+ "payments",
17
+ "upi",
18
+ "wallets",
19
+ "india"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/Rajeev02/rajeev-sdk",
24
+ "directory": "packages/payments"
25
+ },
26
+ "homepage": "https://github.com/Rajeev02/rajeev-sdk#readme",
27
+ "bugs": {
28
+ "url": "https://github.com/Rajeev02/rajeev-sdk/issues"
29
+ },
30
+ "files": [
31
+ "lib/",
32
+ "src/",
33
+ "README.md"
34
+ ],
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "peerDependencies": {
39
+ "react": ">=18.3.0",
40
+ "react-native": ">=0.84.0"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "react-native": {
44
+ "optional": true
45
+ }
46
+ },
47
+ "devDependencies": {
48
+ "@types/react": "^19.0.0",
49
+ "typescript": "^5.4.0"
50
+ }
51
+ }
@@ -0,0 +1,132 @@
1
+ /**
2
+ * @rajeev02/payments — Cards & Subscriptions
3
+ * Card tokenization (RBI compliant), saved cards, recurring billing
4
+ */
5
+
6
+ export interface CardInfo {
7
+ /** Tokenized card reference (never store raw card numbers) */
8
+ tokenRef: string;
9
+ /** Last 4 digits for display */
10
+ last4: string;
11
+ /** Card network */
12
+ network: "visa" | "mastercard" | "rupay" | "amex" | "dinersclub";
13
+ /** Card type */
14
+ type: "credit" | "debit" | "prepaid";
15
+ /** Issuing bank name */
16
+ issuerBank?: string;
17
+ /** Expiry month */
18
+ expiryMonth: number;
19
+ /** Expiry year */
20
+ expiryYear: number;
21
+ /** Cardholder name */
22
+ holderName?: string;
23
+ /** Whether card supports recurring/mandate */
24
+ supportsRecurring: boolean;
25
+ }
26
+
27
+ export interface SubscriptionPlan {
28
+ id: string;
29
+ name: string;
30
+ description?: string;
31
+ amount: number;
32
+ currency: string;
33
+ interval: "daily" | "weekly" | "monthly" | "quarterly" | "yearly";
34
+ intervalCount: number;
35
+ trialDays?: number;
36
+ features?: string[];
37
+ }
38
+
39
+ export interface Subscription {
40
+ id: string;
41
+ planId: string;
42
+ customerId: string;
43
+ status:
44
+ | "active"
45
+ | "paused"
46
+ | "cancelled"
47
+ | "past_due"
48
+ | "trialing"
49
+ | "expired";
50
+ currentPeriodStart: string;
51
+ currentPeriodEnd: string;
52
+ cancelledAt?: string;
53
+ paymentMethod: "card" | "upi_mandate" | "emandate";
54
+ tokenRef?: string;
55
+ nextBillingDate: string;
56
+ amount: number;
57
+ }
58
+
59
+ /**
60
+ * Detect card network from number prefix (first 6 digits)
61
+ */
62
+ export function detectCardNetwork(
63
+ cardNumber: string,
64
+ ): CardInfo["network"] | null {
65
+ const digits = cardNumber.replace(/\s/g, "");
66
+ if (digits.startsWith("4")) return "visa";
67
+ if (/^5[1-5]/.test(digits) || /^2[2-7]/.test(digits)) return "mastercard";
68
+ if (/^6(0|5|52[12]|53[89]|5[4-9]|[6-9])/.test(digits)) return "rupay";
69
+ if (/^3[47]/.test(digits)) return "amex";
70
+ if (/^3(0[0-5]|[68])/.test(digits)) return "dinersclub";
71
+ return null;
72
+ }
73
+
74
+ /**
75
+ * Format card number with spaces: 4111111111111111 → 4111 1111 1111 1111
76
+ */
77
+ export function formatCardNumber(cardNumber: string): string {
78
+ const digits = cardNumber.replace(/\D/g, "");
79
+ if (detectCardNetwork(digits) === "amex") {
80
+ return digits.replace(/(\d{4})(\d{6})(\d{5})/, "$1 $2 $3");
81
+ }
82
+ return digits.replace(/(\d{4})/g, "$1 ").trim();
83
+ }
84
+
85
+ /**
86
+ * Validate card number using Luhn algorithm
87
+ */
88
+ export function validateCardNumber(cardNumber: string): boolean {
89
+ const digits = cardNumber.replace(/\D/g, "");
90
+ if (digits.length < 13 || digits.length > 19) return false;
91
+
92
+ let sum = 0;
93
+ let isEven = false;
94
+ for (let i = digits.length - 1; i >= 0; i--) {
95
+ let d = parseInt(digits[i], 10);
96
+ if (isEven) {
97
+ d *= 2;
98
+ if (d > 9) d -= 9;
99
+ }
100
+ sum += d;
101
+ isEven = !isEven;
102
+ }
103
+ return sum % 10 === 0;
104
+ }
105
+
106
+ /**
107
+ * Calculate subscription renewal dates
108
+ */
109
+ export function getNextBillingDate(
110
+ plan: SubscriptionPlan,
111
+ currentDate: Date = new Date(),
112
+ ): Date {
113
+ const next = new Date(currentDate);
114
+ switch (plan.interval) {
115
+ case "daily":
116
+ next.setDate(next.getDate() + plan.intervalCount);
117
+ break;
118
+ case "weekly":
119
+ next.setDate(next.getDate() + 7 * plan.intervalCount);
120
+ break;
121
+ case "monthly":
122
+ next.setMonth(next.getMonth() + plan.intervalCount);
123
+ break;
124
+ case "quarterly":
125
+ next.setMonth(next.getMonth() + 3 * plan.intervalCount);
126
+ break;
127
+ case "yearly":
128
+ next.setFullYear(next.getFullYear() + plan.intervalCount);
129
+ break;
130
+ }
131
+ return next;
132
+ }
package/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @rajeev02/payments
3
+ * Payments Abstraction SDK — India focused
4
+ * UPI, wallets, cards, subscriptions
5
+ *
6
+ * @author Rajeev Kumar Joshi
7
+ * @license MIT
8
+ */
9
+ export {
10
+ generateUpiUri,
11
+ generateUpiQrData,
12
+ validateVpa,
13
+ getPspName,
14
+ UPI_PSP_HANDLES,
15
+ } from "./upi";
16
+ export type {
17
+ UpiConfig,
18
+ UpiPaymentRequest,
19
+ UpiPaymentResult,
20
+ UpiMandateRequest,
21
+ } from "./upi";
22
+
23
+ export { WalletManager } from "./wallet";
24
+ export type {
25
+ WalletProvider,
26
+ WalletConfig,
27
+ WalletPaymentRequest,
28
+ WalletPaymentResult,
29
+ } from "./wallet";
30
+
31
+ export {
32
+ detectCardNetwork,
33
+ formatCardNumber,
34
+ validateCardNumber,
35
+ getNextBillingDate,
36
+ } from "./cards";
37
+ export type { CardInfo, SubscriptionPlan, Subscription } from "./cards";
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @rajeev02/payments — UPI Module
3
+ * UPI intent, collect request, QR code, autopay mandates
4
+ */
5
+
6
+ export interface UpiConfig {
7
+ /** Merchant VPA (e.g., merchant@paytm) */
8
+ merchantVpa: string;
9
+ /** Merchant name shown in UPI apps */
10
+ merchantName: string;
11
+ /** Merchant category code */
12
+ mcc?: string;
13
+ /** Transaction reference prefix */
14
+ txnRefPrefix?: string;
15
+ }
16
+
17
+ export interface UpiPaymentRequest {
18
+ /** Amount in INR (paisa precision) */
19
+ amount: number;
20
+ /** Payment description */
21
+ note: string;
22
+ /** Unique transaction reference */
23
+ txnRef?: string;
24
+ /** Customer VPA (for collect requests) */
25
+ customerVpa?: string;
26
+ /** Order ID from your backend */
27
+ orderId: string;
28
+ }
29
+
30
+ export interface UpiPaymentResult {
31
+ success: boolean;
32
+ txnId?: string;
33
+ txnRef?: string;
34
+ responseCode?: string;
35
+ approvalRefNo?: string;
36
+ status: "success" | "failed" | "pending" | "cancelled";
37
+ error?: string;
38
+ }
39
+
40
+ export interface UpiMandateRequest {
41
+ /** Customer VPA */
42
+ customerVpa: string;
43
+ /** Maximum amount per debit */
44
+ maxAmount: number;
45
+ /** Frequency: DAILY, WEEKLY, FORTNIGHTLY, MONTHLY, BIMONTHLY, QUARTERLY, HALFYEARLY, YEARLY */
46
+ frequency: string;
47
+ /** Start date (ISO) */
48
+ startDate: string;
49
+ /** End date (ISO) */
50
+ endDate: string;
51
+ /** Purpose description */
52
+ purpose: string;
53
+ }
54
+
55
+ /**
56
+ * Generate UPI deep link URI for intent-based payment
57
+ * Works with all UPI apps (GPay, PhonePe, Paytm, etc.)
58
+ */
59
+ export function generateUpiUri(
60
+ config: UpiConfig,
61
+ request: UpiPaymentRequest,
62
+ ): string {
63
+ const txnRef =
64
+ request.txnRef || `${config.txnRefPrefix || "TXN"}${Date.now()}`;
65
+ const params = new URLSearchParams({
66
+ pa: config.merchantVpa,
67
+ pn: config.merchantName,
68
+ am: request.amount.toFixed(2),
69
+ cu: "INR",
70
+ tn: request.note,
71
+ tr: txnRef,
72
+ });
73
+ if (config.mcc) params.set("mc", config.mcc);
74
+ if (request.orderId) params.set("tid", request.orderId);
75
+ return `upi://pay?${params.toString()}`;
76
+ }
77
+
78
+ /**
79
+ * Generate UPI QR code data string
80
+ */
81
+ export function generateUpiQrData(
82
+ config: UpiConfig,
83
+ request: UpiPaymentRequest,
84
+ ): string {
85
+ return generateUpiUri(config, request);
86
+ }
87
+
88
+ /**
89
+ * Validate a UPI VPA format
90
+ * Format: username@psp (e.g., rajeev@paytm, user@okicici)
91
+ */
92
+ export function validateVpa(vpa: string): boolean {
93
+ return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9]+$/.test(vpa);
94
+ }
95
+
96
+ /**
97
+ * Known UPI PSP handles
98
+ */
99
+ export const UPI_PSP_HANDLES: Record<string, string> = {
100
+ "@paytm": "Paytm",
101
+ "@okicici": "Google Pay (ICICI)",
102
+ "@okhdfcbank": "Google Pay (HDFC)",
103
+ "@oksbi": "Google Pay (SBI)",
104
+ "@ybl": "PhonePe (YES Bank)",
105
+ "@ibl": "PhonePe (ICICI)",
106
+ "@axl": "PhonePe (Axis)",
107
+ "@apl": "Amazon Pay",
108
+ "@freecharge": "Freecharge",
109
+ "@upi": "BHIM",
110
+ };
111
+
112
+ export function getPspName(vpa: string): string | null {
113
+ const handle = "@" + vpa.split("@")[1];
114
+ return UPI_PSP_HANDLES[handle] ?? null;
115
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * @rajeev02/payments — Wallet Module
3
+ * Abstraction over PhonePe, Paytm, Amazon Pay, Freecharge wallets
4
+ */
5
+
6
+ export type WalletProvider =
7
+ | "paytm"
8
+ | "phonepe"
9
+ | "amazon_pay"
10
+ | "freecharge"
11
+ | "mobikwik"
12
+ | "jio_pay";
13
+
14
+ export interface WalletConfig {
15
+ provider: WalletProvider;
16
+ merchantId: string;
17
+ merchantKey?: string;
18
+ environment: "sandbox" | "production";
19
+ callbackUrl: string;
20
+ }
21
+
22
+ export interface WalletPaymentRequest {
23
+ orderId: string;
24
+ amount: number;
25
+ customerId: string;
26
+ customerPhone?: string;
27
+ customerEmail?: string;
28
+ description?: string;
29
+ }
30
+
31
+ export interface WalletPaymentResult {
32
+ success: boolean;
33
+ provider: WalletProvider;
34
+ txnId?: string;
35
+ orderId: string;
36
+ status: "success" | "failed" | "pending" | "cancelled";
37
+ walletBalance?: number;
38
+ error?: string;
39
+ }
40
+
41
+ /**
42
+ * Wallet Manager — handles payment flow across wallet providers
43
+ */
44
+ export class WalletManager {
45
+ private configs: Map<WalletProvider, WalletConfig> = new Map();
46
+
47
+ /** Register a wallet provider */
48
+ register(config: WalletConfig): void {
49
+ this.configs.set(config.provider, config);
50
+ }
51
+
52
+ /** Get all registered wallet providers */
53
+ getAvailableWallets(): WalletProvider[] {
54
+ return Array.from(this.configs.keys());
55
+ }
56
+
57
+ /** Check if a wallet is registered */
58
+ isAvailable(provider: WalletProvider): boolean {
59
+ return this.configs.has(provider);
60
+ }
61
+
62
+ /** Generate checkout URL/payload for a wallet */
63
+ generateCheckout(
64
+ provider: WalletProvider,
65
+ request: WalletPaymentRequest,
66
+ ): Record<string, unknown> | null {
67
+ const config = this.configs.get(provider);
68
+ if (!config) return null;
69
+
70
+ return {
71
+ provider,
72
+ merchantId: config.merchantId,
73
+ environment: config.environment,
74
+ callbackUrl: config.callbackUrl,
75
+ orderId: request.orderId,
76
+ amount: request.amount,
77
+ customerId: request.customerId,
78
+ phone: request.customerPhone,
79
+ email: request.customerEmail,
80
+ };
81
+ }
82
+ }