@neocleus/razorpay-firebase-functions 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.
Files changed (62) hide show
  1. package/README.md +165 -0
  2. package/lib/admin.d.ts +8 -0
  3. package/lib/admin.js +155 -0
  4. package/lib/admin.js.map +1 -0
  5. package/lib/api.d.ts +4 -0
  6. package/lib/api.js +203 -0
  7. package/lib/api.js.map +1 -0
  8. package/lib/callables/subscriptions.d.ts +9 -0
  9. package/lib/callables/subscriptions.js +138 -0
  10. package/lib/callables/subscriptions.js.map +1 -0
  11. package/lib/handlers/payments.d.ts +4 -0
  12. package/lib/handlers/payments.js +135 -0
  13. package/lib/handlers/payments.js.map +1 -0
  14. package/lib/handlers/subscriptions.d.ts +4 -0
  15. package/lib/handlers/subscriptions.js +87 -0
  16. package/lib/handlers/subscriptions.js.map +1 -0
  17. package/lib/index.d.ts +29 -0
  18. package/lib/index.js +88 -0
  19. package/lib/index.js.map +1 -0
  20. package/lib/logs.d.ts +10 -0
  21. package/lib/logs.js +36 -0
  22. package/lib/logs.js.map +1 -0
  23. package/lib/security.d.ts +1 -0
  24. package/lib/security.js +14 -0
  25. package/lib/security.js.map +1 -0
  26. package/lib/triggers/createCustomer.d.ts +4 -0
  27. package/lib/triggers/createCustomer.js +79 -0
  28. package/lib/triggers/createCustomer.js.map +1 -0
  29. package/lib/triggers/createOrder.d.ts +6 -0
  30. package/lib/triggers/createOrder.js +173 -0
  31. package/lib/triggers/createOrder.js.map +1 -0
  32. package/lib/triggers/createSubscription.d.ts +6 -0
  33. package/lib/triggers/createSubscription.js +211 -0
  34. package/lib/triggers/createSubscription.js.map +1 -0
  35. package/lib/triggers/onUserDeleted.d.ts +5 -0
  36. package/lib/triggers/onUserDeleted.js +118 -0
  37. package/lib/triggers/onUserDeleted.js.map +1 -0
  38. package/lib/triggers/syncClaims.d.ts +5 -0
  39. package/lib/triggers/syncClaims.js +92 -0
  40. package/lib/triggers/syncClaims.js.map +1 -0
  41. package/lib/types.d.ts +43 -0
  42. package/lib/types.js +3 -0
  43. package/lib/types.js.map +1 -0
  44. package/lib/utils/customerMapping.d.ts +9 -0
  45. package/lib/utils/customerMapping.js +68 -0
  46. package/lib/utils/customerMapping.js.map +1 -0
  47. package/lib/utils/ensureCustomer.d.ts +10 -0
  48. package/lib/utils/ensureCustomer.js +78 -0
  49. package/lib/utils/ensureCustomer.js.map +1 -0
  50. package/lib/utils/index.d.ts +15 -0
  51. package/lib/utils/index.js +75 -0
  52. package/lib/utils/index.js.map +1 -0
  53. package/lib/utils/processingLock.d.ts +12 -0
  54. package/lib/utils/processingLock.js +78 -0
  55. package/lib/utils/processingLock.js.map +1 -0
  56. package/lib/utils/retry.d.ts +9 -0
  57. package/lib/utils/retry.js +53 -0
  58. package/lib/utils/retry.js.map +1 -0
  59. package/lib/utils/typedFirestore.d.ts +25 -0
  60. package/lib/utils/typedFirestore.js +77 -0
  61. package/lib/utils/typedFirestore.js.map +1 -0
  62. package/package.json +37 -0
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildSyncClaimsOnSubscriptionChange = void 0;
37
+ const firestore_1 = require("firebase-functions/v2/firestore");
38
+ const admin = __importStar(require("firebase-admin"));
39
+ const logs_1 = require("../logs");
40
+ const buildSyncClaimsOnSubscriptionChange = (config) => {
41
+ const syncClaimsHandler = async (event) => {
42
+ if (!config.syncCustomClaims) {
43
+ return;
44
+ }
45
+ const uid = event.params.uid;
46
+ try {
47
+ const allSubsSnap = await admin.firestore()
48
+ .collection(config.customersCollection)
49
+ .doc(uid)
50
+ .collection('subscriptions')
51
+ .get();
52
+ const activeRoles = new Set();
53
+ const allRazorpayRoles = new Set();
54
+ allSubsSnap.forEach(doc => {
55
+ const data = doc.data();
56
+ const role = data.firebaseRole;
57
+ const status = data.status;
58
+ if (role && typeof role === 'string') {
59
+ allRazorpayRoles.add(role);
60
+ if (status === 'active' || status === 'authenticated') {
61
+ activeRoles.add(role);
62
+ }
63
+ }
64
+ });
65
+ const userRec = await admin.auth().getUser(uid);
66
+ const mergedClaims = { ...(userRec.customClaims || {}) };
67
+ let updated = false;
68
+ allRazorpayRoles.forEach(role => {
69
+ if (!activeRoles.has(role) && mergedClaims[role]) {
70
+ delete mergedClaims[role];
71
+ updated = true;
72
+ }
73
+ });
74
+ activeRoles.forEach(role => {
75
+ if (!mergedClaims[role]) {
76
+ mergedClaims[role] = true;
77
+ updated = true;
78
+ }
79
+ });
80
+ if (updated) {
81
+ await admin.auth().setCustomUserClaims(uid, mergedClaims);
82
+ logs_1.logs.info(`Synced claims for ${uid}: [${Object.keys(mergedClaims).join(', ')}]`);
83
+ }
84
+ }
85
+ catch (error) {
86
+ logs_1.logs.error(new Error(`Failed to sync claims for ${uid}: ${error.message}`));
87
+ }
88
+ };
89
+ return (0, firestore_1.onDocumentWritten)(`${config.customersCollection}/{uid}/subscriptions/{subscriptionId}`, syncClaimsHandler);
90
+ };
91
+ exports.buildSyncClaimsOnSubscriptionChange = buildSyncClaimsOnSubscriptionChange;
92
+ //# sourceMappingURL=syncClaims.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"syncClaims.js","sourceRoot":"","sources":["../../src/triggers/syncClaims.ts"],"names":[],"mappings":"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"}
package/lib/types.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import * as admin from 'firebase-admin';
2
+ import * as Shared from '@neocleus/razorpay-firebase-types';
3
+ export type SanitizedPlan = Shared.SanitizedPlan<admin.firestore.FieldValue, admin.firestore.Timestamp>;
4
+ export type ProductDoc = Shared.ProductDoc<admin.firestore.FieldValue, admin.firestore.Timestamp>;
5
+ export type CustomerDoc = Shared.CustomerDoc<admin.firestore.FieldValue, admin.firestore.Timestamp>;
6
+ export type CheckoutSessionDoc = Shared.CheckoutSessionDoc<admin.firestore.FieldValue, admin.firestore.Timestamp>;
7
+ export type SubscriptionDoc = Shared.SubscriptionDoc<admin.firestore.FieldValue, admin.firestore.Timestamp>;
8
+ export type WebhookEventDoc = Shared.WebhookEventDoc<admin.firestore.FieldValue, admin.firestore.Timestamp>;
9
+ export interface RazorpayUserConfig {
10
+ keyId: string;
11
+ keySecret: string;
12
+ webhookSecret: string;
13
+ customersCollection?: string;
14
+ productsCollection?: string;
15
+ syncCustomers?: boolean;
16
+ eventarcChannel?: string;
17
+ allowedEventTypes?: string[];
18
+ }
19
+ export interface RazorpaySyncConfig {
20
+ keyId: string;
21
+ keySecret: string;
22
+ webhookSecret: string;
23
+ customersCollection: string;
24
+ productsCollection: string;
25
+ syncCustomers: boolean;
26
+ eventarcChannel?: string;
27
+ allowedEventTypes?: string[];
28
+ }
29
+ export interface WebhookEntityWrapper {
30
+ entity?: Record<string, any>;
31
+ id?: string;
32
+ }
33
+ export interface WebhookPayload {
34
+ payment?: WebhookEntityWrapper;
35
+ order?: WebhookEntityWrapper;
36
+ subscription?: WebhookEntityWrapper;
37
+ }
38
+ export interface WebhookEvent {
39
+ event: string;
40
+ id: string;
41
+ payload: WebhookPayload;
42
+ created_at?: number;
43
+ }
package/lib/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Look up a Firebase UID using the strictly mapped Razorpay Customer ID.
3
+ * This prevents notes.uid spoofing by enforcing a server-side verified mapping.
4
+ *
5
+ * NOTE: For production scale, you must create a single-field index in Firestore
6
+ * on the customers collection's `razorpay_customer_id` field (or a collection group index)
7
+ * to avoid full collection scans and ensure O(1) performance.
8
+ */
9
+ export declare function getUidByCustomerId(customerId: string, customersCollectionPath: string): Promise<string | null>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.getUidByCustomerId = getUidByCustomerId;
37
+ const admin = __importStar(require("firebase-admin"));
38
+ const typedFirestore_1 = require("./typedFirestore");
39
+ /**
40
+ * Look up a Firebase UID using the strictly mapped Razorpay Customer ID.
41
+ * This prevents notes.uid spoofing by enforcing a server-side verified mapping.
42
+ *
43
+ * NOTE: For production scale, you must create a single-field index in Firestore
44
+ * on the customers collection's `razorpay_customer_id` field (or a collection group index)
45
+ * to avoid full collection scans and ensure O(1) performance.
46
+ */
47
+ async function getUidByCustomerId(customerId, customersCollectionPath) {
48
+ if (!customerId)
49
+ return null;
50
+ const db = admin.firestore();
51
+ const typedFs = new typedFirestore_1.TypedFirestore(db, {
52
+ customersCollection: customersCollectionPath,
53
+ productsCollection: '',
54
+ keyId: '',
55
+ keySecret: '',
56
+ webhookSecret: '',
57
+ syncCustomers: true
58
+ });
59
+ const snap = await typedFs.getCustomersCollection()
60
+ .where('razorpay_customer_id', '==', customerId)
61
+ .limit(1)
62
+ .get();
63
+ if (snap.empty) {
64
+ return null;
65
+ }
66
+ return snap.docs[0].id;
67
+ }
68
+ //# sourceMappingURL=customerMapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"customerMapping.js","sourceRoot":"","sources":["../../src/utils/customerMapping.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAWA,gDA0BC;AArCD,sDAAwC;AACxC,qDAAkD;AAElD;;;;;;;GAOG;AACI,KAAK,UAAU,kBAAkB,CACpC,UAAkB,EAClB,uBAA+B;IAE/B,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,+BAAc,CAAC,EAAE,EAAE;QACnC,mBAAmB,EAAE,uBAAuB;QAC5C,kBAAkB,EAAE,EAAE;QACtB,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,aAAa,EAAE,EAAE;QACjB,aAAa,EAAE,IAAI;KACtB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,sBAAsB,EAAE;SAC9C,KAAK,CAAC,sBAAsB,EAAE,IAAI,EAAE,UAAU,CAAC;SAC/C,KAAK,CAAC,CAAC,CAAC;SACR,GAAG,EAAE,CAAC;IAEX,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,10 @@
1
+ import Razorpay from 'razorpay';
2
+ import { RazorpaySyncConfig } from '../types';
3
+ /**
4
+ * Ensures a Razorpay customer exists for the given Firebase UID.
5
+ * If no customer is linked and syncCustomers is enabled, creates one via the Razorpay API
6
+ * and stores the mapping in Firestore.
7
+ *
8
+ * @returns The Razorpay customer ID, or null if not found and creation is disabled/failed.
9
+ */
10
+ export declare function ensureRazorpayCustomer(uid: string, config: RazorpaySyncConfig, rzp: Razorpay): Promise<string | null>;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ensureRazorpayCustomer = ensureRazorpayCustomer;
37
+ const admin = __importStar(require("firebase-admin"));
38
+ const firestore_1 = require("firebase-admin/firestore");
39
+ const logs_1 = require("../logs");
40
+ const typedFirestore_1 = require("./typedFirestore");
41
+ /**
42
+ * Ensures a Razorpay customer exists for the given Firebase UID.
43
+ * If no customer is linked and syncCustomers is enabled, creates one via the Razorpay API
44
+ * and stores the mapping in Firestore.
45
+ *
46
+ * @returns The Razorpay customer ID, or null if not found and creation is disabled/failed.
47
+ */
48
+ async function ensureRazorpayCustomer(uid, config, rzp) {
49
+ const db = admin.firestore();
50
+ const typedFs = new typedFirestore_1.TypedFirestore(db, config);
51
+ const customerDocRef = typedFs.getCustomerDoc(uid);
52
+ const customerDoc = await customerDocRef.get();
53
+ const customerData = customerDoc.data() || {};
54
+ const existingCustomerId = customerData.razorpay_customer_id;
55
+ if (existingCustomerId) {
56
+ return existingCustomerId;
57
+ }
58
+ if (!config.syncCustomers) {
59
+ logs_1.logs.info(`No linked Razorpay customer ID for UID ${uid} and syncCustomers is disabled.`);
60
+ return null;
61
+ }
62
+ const userRec = await admin.auth().getUser(uid).catch(() => null);
63
+ const newCustomer = await rzp.customers.create({
64
+ name: userRec?.displayName || customerData.name || 'Firebase User',
65
+ email: userRec?.email || customerData.email || undefined,
66
+ contact: userRec?.phoneNumber || customerData.phone || undefined,
67
+ fail_existing: 0,
68
+ });
69
+ const razorpayCustomerId = newCustomer.id;
70
+ const updateData = {
71
+ razorpay_customer_id: razorpayCustomerId,
72
+ updated_at: firestore_1.FieldValue.serverTimestamp()
73
+ };
74
+ await customerDocRef.set(updateData, { merge: true });
75
+ logs_1.logs.info(`Created Razorpay customer ${razorpayCustomerId} for UID ${uid}`);
76
+ return razorpayCustomerId;
77
+ }
78
+ //# sourceMappingURL=ensureCustomer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensureCustomer.js","sourceRoot":"","sources":["../../src/utils/ensureCustomer.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,wDAsCC;AApDD,sDAAwC;AACxC,wDAAsD;AAEtD,kCAA+B;AAE/B,qDAAkD;AAElD;;;;;;GAMG;AACI,KAAK,UAAU,sBAAsB,CACxC,GAAW,EACX,MAA0B,EAC1B,GAAa;IAEb,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,+BAAc,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAC/C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,GAAG,EAAE,CAAC;IAC/C,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,EAAE,IAAK,EAA2B,CAAC;IACxE,MAAM,kBAAkB,GAAG,YAAY,CAAC,oBAAoB,CAAC;IAE7D,IAAI,kBAAkB,EAAE,CAAC;QACrB,OAAO,kBAAkB,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QACxB,WAAI,CAAC,IAAI,CAAC,0CAA0C,GAAG,iCAAiC,CAAC,CAAC;QAC1F,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAClE,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC;QAC3C,IAAI,EAAE,OAAO,EAAE,WAAW,IAAI,YAAY,CAAC,IAAI,IAAI,eAAe;QAClE,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,YAAY,CAAC,KAAK,IAAI,SAAS;QACxD,OAAO,EAAE,OAAO,EAAE,WAAW,IAAI,YAAY,CAAC,KAAK,IAAI,SAAS;QAChE,aAAa,EAAE,CAAC;KACnB,CAAC,CAAC;IAEH,MAAM,kBAAkB,GAAG,WAAW,CAAC,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAyB;QACrC,oBAAoB,EAAE,kBAAkB;QACxC,UAAU,EAAE,sBAAU,CAAC,eAAe,EAAE;KAC3C,CAAC;IACF,MAAM,cAAc,CAAC,GAAG,CAAC,UAAyB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,WAAI,CAAC,IAAI,CAAC,6BAA6B,kBAAkB,YAAY,GAAG,EAAE,CAAC,CAAC;IAE5E,OAAO,kBAAkB,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import * as admin from 'firebase-admin';
2
+ import { Plans } from 'razorpay/dist/types/plans';
3
+ import { RazorpaySyncConfig, SanitizedPlan, ProductDoc } from '../types';
4
+ /**
5
+ * Helper to sanitize Razorpay plan data for Firestore storage.
6
+ */
7
+ export declare const sanitizePlan: (plan: Plans.RazorPayPlans) => SanitizedPlan;
8
+ export declare const generateProductId: (plan: Plans.RazorPayPlans) => string;
9
+ export declare const generatePlanKey: (plan: Plans.RazorPayPlans) => string;
10
+ /**
11
+ * Syncs a Razorpay plan to a Firestore product document.
12
+ * Creates or updates the product document with the plan's details.
13
+ * Shared between buildCreatePlan and buildSyncPlans.
14
+ */
15
+ export declare const syncPlanToProduct: (plan: Plans.RazorPayPlans, db: admin.firestore.Firestore, config: RazorpaySyncConfig) => Promise<ProductDoc>;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.syncPlanToProduct = exports.generatePlanKey = exports.generateProductId = exports.sanitizePlan = void 0;
4
+ const firestore_1 = require("firebase-admin/firestore");
5
+ const typedFirestore_1 = require("./typedFirestore");
6
+ /**
7
+ * Helper to sanitize Razorpay plan data for Firestore storage.
8
+ */
9
+ const sanitizePlan = (plan) => {
10
+ const sanitizedPlan = {
11
+ id: plan.id,
12
+ entity: plan.entity,
13
+ interval: plan.interval,
14
+ period: plan.period,
15
+ item: plan.item ? plan.item : null,
16
+ notes: plan.notes || {},
17
+ active: true, // Plans don't return an active boolean at the top level
18
+ created_at: plan.created_at,
19
+ updated_at: firestore_1.FieldValue.serverTimestamp(),
20
+ _synced_via: 'admin_api'
21
+ };
22
+ if (plan.item && plan.item.active !== undefined) {
23
+ sanitizedPlan.active = !!plan.item.active;
24
+ }
25
+ return sanitizedPlan;
26
+ };
27
+ exports.sanitizePlan = sanitizePlan;
28
+ const generateProductId = (plan) => {
29
+ if (plan.notes && plan.notes.productId) {
30
+ return String(plan.notes.productId);
31
+ }
32
+ if (plan.item && plan.item.name) {
33
+ return plan.item.name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-+)+/g, '');
34
+ }
35
+ return `prod_${plan.id}`;
36
+ };
37
+ exports.generateProductId = generateProductId;
38
+ const generatePlanKey = (plan) => {
39
+ if (plan.interval > 1) {
40
+ return `${plan.interval}_${plan.period}`;
41
+ }
42
+ return plan.period;
43
+ };
44
+ exports.generatePlanKey = generatePlanKey;
45
+ /**
46
+ * Syncs a Razorpay plan to a Firestore product document.
47
+ * Creates or updates the product document with the plan's details.
48
+ * Shared between buildCreatePlan and buildSyncPlans.
49
+ */
50
+ const syncPlanToProduct = async (plan, db, config) => {
51
+ const productId = (0, exports.generateProductId)(plan);
52
+ const planKey = (0, exports.generatePlanKey)(plan);
53
+ const typedFs = new typedFirestore_1.TypedFirestore(db, config);
54
+ const docRef = typedFs.getProductDoc(productId);
55
+ const productSnap = await docRef.get();
56
+ const productData = productSnap.data() || {
57
+ id: productId,
58
+ name: plan.item?.name || 'Razorpay Product',
59
+ description: plan.item?.description || '',
60
+ active: true,
61
+ allowedPlans: {},
62
+ created_at: firestore_1.FieldValue.serverTimestamp(),
63
+ };
64
+ productData.allowedPlans = productData.allowedPlans || {};
65
+ productData.allowedPlans[planKey] = plan.id;
66
+ productData.plans = productData.plans || {};
67
+ productData.plans[planKey] = (0, exports.sanitizePlan)(plan);
68
+ productData.type = 'subscription';
69
+ productData.updated_at = firestore_1.FieldValue.serverTimestamp();
70
+ productData._synced_via = 'admin_api';
71
+ await docRef.set(productData, { merge: true });
72
+ return productData;
73
+ };
74
+ exports.syncPlanToProduct = syncPlanToProduct;
75
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import * as admin from 'firebase-admin';
2
+ /**
3
+ * Acquires a processing lock on a Firestore document via a transaction.
4
+ * Prevents duplicate processing of the same document by multiple function invocations.
5
+ *
6
+ * @param docRef - The Firestore document reference to lock.
7
+ * @param isTerminal - A predicate that returns true if the document is already in a
8
+ * terminal state (e.g., has an order_id, subscription_id, or paid status).
9
+ * @returns true if the lock was successfully acquired, false if the document is already
10
+ * processed or currently being processed within the timeout window.
11
+ */
12
+ export declare function acquireProcessingLock(docRef: admin.firestore.DocumentReference, isTerminal: (data: admin.firestore.DocumentData) => boolean): Promise<boolean>;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.acquireProcessingLock = acquireProcessingLock;
37
+ const admin = __importStar(require("firebase-admin"));
38
+ const firestore_1 = require("firebase-admin/firestore");
39
+ const PROCESSING_TIMEOUT_MS = 120_000; // 2 minutes
40
+ /**
41
+ * Acquires a processing lock on a Firestore document via a transaction.
42
+ * Prevents duplicate processing of the same document by multiple function invocations.
43
+ *
44
+ * @param docRef - The Firestore document reference to lock.
45
+ * @param isTerminal - A predicate that returns true if the document is already in a
46
+ * terminal state (e.g., has an order_id, subscription_id, or paid status).
47
+ * @returns true if the lock was successfully acquired, false if the document is already
48
+ * processed or currently being processed within the timeout window.
49
+ */
50
+ async function acquireProcessingLock(docRef, isTerminal) {
51
+ let acquired = false;
52
+ await admin.firestore().runTransaction(async (transaction) => {
53
+ const docSnap = await transaction.get(docRef);
54
+ if (!docSnap.exists)
55
+ return;
56
+ const data = docSnap.data();
57
+ if (!data)
58
+ return;
59
+ if (isTerminal(data)) {
60
+ acquired = false;
61
+ return;
62
+ }
63
+ if (data.status === 'processing') {
64
+ const processingAt = data.processing_at?.toDate();
65
+ if (processingAt && (Date.now() - processingAt.getTime()) < PROCESSING_TIMEOUT_MS) {
66
+ acquired = false;
67
+ return; // Still processing within timeout window
68
+ }
69
+ }
70
+ transaction.update(docRef, {
71
+ status: 'processing',
72
+ processing_at: firestore_1.FieldValue.serverTimestamp(),
73
+ });
74
+ acquired = true;
75
+ });
76
+ return acquired;
77
+ }
78
+ //# sourceMappingURL=processingLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processingLock.js","sourceRoot":"","sources":["../../src/utils/processingLock.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,sDAkCC;AAjDD,sDAAwC;AACxC,wDAAsD;AAEtD,MAAM,qBAAqB,GAAG,OAAO,CAAC,CAAC,YAAY;AAEnD;;;;;;;;;GASG;AACI,KAAK,UAAU,qBAAqB,CACvC,MAAyC,EACzC,UAA2D;IAE3D,IAAI,QAAQ,GAAG,KAAK,CAAC;IAErB,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QACzD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,MAAM;YAAE,OAAO;QAE5B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,QAAQ,GAAG,KAAK,CAAC;YACjB,OAAO;QACX,CAAC;QAED,IAAI,IAAI,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YAClD,IAAI,YAAY,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,qBAAqB,EAAE,CAAC;gBAChF,QAAQ,GAAG,KAAK,CAAC;gBACjB,OAAO,CAAC,yCAAyC;YACrD,CAAC;QACL,CAAC;QAED,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE;YACvB,MAAM,EAAE,YAAY;YACpB,aAAa,EAAE,sBAAU,CAAC,eAAe,EAAE;SAC9C,CAAC,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AACpB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Retry a fetch function with exponential backoff on 429 (Rate Limited) responses.
3
+ * Shared across payment and subscription webhook handlers.
4
+ */
5
+ export declare function fetchWithBackoff<T>(fetchFn: () => Promise<T>, retries?: number, backoffMs?: number): Promise<T>;
6
+ /**
7
+ * Determine if an error is transient/retryable (e.g. rate limit, server error, network drop).
8
+ */
9
+ export declare function isTransientError(err: any): boolean;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchWithBackoff = fetchWithBackoff;
4
+ exports.isTransientError = isTransientError;
5
+ const logs_1 = require("../logs");
6
+ /**
7
+ * Retry a fetch function with exponential backoff on 429 (Rate Limited) responses.
8
+ * Shared across payment and subscription webhook handlers.
9
+ */
10
+ async function fetchWithBackoff(fetchFn, retries = 3, backoffMs = 500) {
11
+ let attempt = 0;
12
+ while (attempt < retries) {
13
+ try {
14
+ return await fetchFn();
15
+ }
16
+ catch (err) {
17
+ attempt++;
18
+ if (err.statusCode === 429 && attempt < retries) {
19
+ logs_1.logs.info(`Rate limited (429). Retrying in ${backoffMs}ms (Attempt ${attempt} of ${retries})`);
20
+ await new Promise(resolve => setTimeout(resolve, backoffMs));
21
+ backoffMs *= 2; // Exponential backoff
22
+ }
23
+ else {
24
+ throw err;
25
+ }
26
+ }
27
+ }
28
+ throw new Error('Max retries reached');
29
+ }
30
+ /**
31
+ * Determine if an error is transient/retryable (e.g. rate limit, server error, network drop).
32
+ */
33
+ function isTransientError(err) {
34
+ if (!err)
35
+ return false;
36
+ const statusCode = err.statusCode;
37
+ if (statusCode) {
38
+ return statusCode >= 500 || statusCode === 429;
39
+ }
40
+ // No status code — check for network, timeout, or connection errors
41
+ const message = (err.message || '').toLowerCase();
42
+ const code = err.code;
43
+ return (code === 'DEADLINE_EXCEEDED' ||
44
+ code === 'UNAVAILABLE' ||
45
+ code === 'ETIMEDOUT' ||
46
+ code === 'ECONNRESET' ||
47
+ code === 'ECONNREFUSED' ||
48
+ code === 'ENOTFOUND' ||
49
+ message.includes('timeout') ||
50
+ message.includes('network') ||
51
+ message.includes('fetch'));
52
+ }
53
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":";;AAMA,4CAiBC;AAKD,4CAoBC;AAhDD,kCAA+B;AAE/B;;;GAGG;AACI,KAAK,UAAU,gBAAgB,CAAI,OAAyB,EAAE,OAAO,GAAG,CAAC,EAAE,SAAS,GAAG,GAAG;IAC7F,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,OAAO,GAAG,OAAO,EAAE,CAAC;QACvB,IAAI,CAAC;YACD,OAAO,MAAM,OAAO,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAChB,OAAO,EAAE,CAAC;YACV,IAAI,GAAG,CAAC,UAAU,KAAK,GAAG,IAAI,OAAO,GAAG,OAAO,EAAE,CAAC;gBAC9C,WAAI,CAAC,IAAI,CAAC,mCAAmC,SAAS,eAAe,OAAO,OAAO,OAAO,GAAG,CAAC,CAAC;gBAC/F,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;gBAC7D,SAAS,IAAI,CAAC,CAAC,CAAC,sBAAsB;YAC1C,CAAC;iBAAM,CAAC;gBACJ,MAAM,GAAG,CAAC;YACd,CAAC;QACL,CAAC;IACL,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,GAAQ;IACrC,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC;IAClC,IAAI,UAAU,EAAE,CAAC;QACb,OAAO,UAAU,IAAI,GAAG,IAAI,UAAU,KAAK,GAAG,CAAC;IACnD,CAAC;IACD,oEAAoE;IACpE,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAClD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC;IACtB,OAAO,CACH,IAAI,KAAK,mBAAmB;QAC5B,IAAI,KAAK,aAAa;QACtB,IAAI,KAAK,WAAW;QACpB,IAAI,KAAK,YAAY;QACrB,IAAI,KAAK,cAAc;QACvB,IAAI,KAAK,WAAW;QACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAC5B,CAAC;AACN,CAAC"}
@@ -0,0 +1,25 @@
1
+ import * as admin from 'firebase-admin';
2
+ import { Orders } from 'razorpay/dist/types/orders';
3
+ import { Payments } from 'razorpay/dist/types/payments';
4
+ import { Subscriptions } from 'razorpay/dist/types/subscriptions';
5
+ import { RazorpaySyncConfig, CustomerDoc, ProductDoc, CheckoutSessionDoc, SubscriptionDoc, WebhookEventDoc } from '../types';
6
+ export declare class TypedFirestore {
7
+ private db;
8
+ private config;
9
+ constructor(db: admin.firestore.Firestore, config: RazorpaySyncConfig);
10
+ getCustomersCollection(): admin.firestore.CollectionReference<CustomerDoc, admin.firestore.DocumentData>;
11
+ getCustomerDoc(uid: string): admin.firestore.DocumentReference<CustomerDoc, admin.firestore.DocumentData>;
12
+ getProductsCollection(): admin.firestore.CollectionReference<ProductDoc, admin.firestore.DocumentData>;
13
+ getProductDoc(productId: string): admin.firestore.DocumentReference<ProductDoc, admin.firestore.DocumentData>;
14
+ getCheckoutSessionsCollection(uid: string): admin.firestore.CollectionReference<CheckoutSessionDoc, admin.firestore.DocumentData>;
15
+ getCheckoutSessionDoc(uid: string, sessionId: string): admin.firestore.DocumentReference<CheckoutSessionDoc, admin.firestore.DocumentData>;
16
+ getCheckoutSessionOrderDoc(uid: string, sessionId: string): admin.firestore.DocumentReference<Orders.RazorpayOrder, admin.firestore.DocumentData>;
17
+ getCheckoutSessionPaymentDoc(uid: string, sessionId: string): admin.firestore.DocumentReference<Payments.RazorpayPayment, admin.firestore.DocumentData>;
18
+ getSubscriptionsCollection(uid: string): admin.firestore.CollectionReference<SubscriptionDoc, admin.firestore.DocumentData>;
19
+ getSubscriptionDoc(uid: string, subscriptionId: string): admin.firestore.DocumentReference<SubscriptionDoc, admin.firestore.DocumentData>;
20
+ getSubscriptionDetailsDoc(uid: string, subscriptionId: string): admin.firestore.DocumentReference<Subscriptions.RazorpaySubscription, admin.firestore.DocumentData>;
21
+ getSubscriptionPaymentsCollection(uid: string, subscriptionId: string): admin.firestore.CollectionReference<Payments.RazorpayPayment, admin.firestore.DocumentData>;
22
+ getSubscriptionPaymentDoc(uid: string, subscriptionId: string, paymentId: string): admin.firestore.DocumentReference<Payments.RazorpayPayment, admin.firestore.DocumentData>;
23
+ getWebhookEventsCollection(): admin.firestore.CollectionReference<WebhookEventDoc, admin.firestore.DocumentData>;
24
+ getWebhookEventDoc(eventId: string): admin.firestore.DocumentReference<WebhookEventDoc, admin.firestore.DocumentData>;
25
+ }