@qazuor/qzpay-core 1.0.1 → 1.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.
package/README.md CHANGED
@@ -80,8 +80,8 @@ await billing.subscriptions.cancel('sub_123');
80
80
  ### Payment Operations
81
81
 
82
82
  ```typescript
83
- // Create payment
84
- const payment = await billing.payments.create({
83
+ // Process a payment
84
+ const payment = await billing.payments.process({
85
85
  customerId: 'cus_123',
86
86
  amount: 2999, // $29.99 in cents
87
87
  currency: 'USD',
@@ -91,8 +91,26 @@ const payment = await billing.payments.create({
91
91
  // Retrieve payment
92
92
  const status = await billing.payments.get('pay_123');
93
93
 
94
+ // Get payments by customer
95
+ const payments = await billing.payments.getByCustomerId('cus_123');
96
+
97
+ // Record an external payment (already processed by provider)
98
+ const recorded = await billing.payments.record({
99
+ id: 'pay_external_123',
100
+ customerId: 'cus_123',
101
+ amount: 2999,
102
+ currency: 'USD',
103
+ status: 'succeeded',
104
+ providerPaymentId: 'pi_xxx',
105
+ provider: 'stripe'
106
+ });
107
+
94
108
  // Refund payment
95
- await billing.payments.refund('pay_123', { amount: 1500 });
109
+ await billing.payments.refund({
110
+ paymentId: 'pay_123',
111
+ amount: 1500, // Optional: partial refund
112
+ reason: 'requested_by_customer'
113
+ });
96
114
  ```
97
115
 
98
116
  ### Events
@@ -113,27 +131,44 @@ billing.on('payment.succeeded', (event) => {
113
131
 
114
132
  ### Metrics
115
133
 
116
- ```typescript
117
- import { createMetricsService } from '@qazuor/qzpay-core';
118
-
119
- const metrics = createMetricsService({ storage });
134
+ The `billing.metrics` service provides business intelligence and analytics:
120
135
 
121
- // Get MRR
122
- const mrr = await metrics.getMRR({ currency: 'USD' });
123
- console.log('Current MRR:', mrr.current);
136
+ ```typescript
137
+ // Get Monthly Recurring Revenue
138
+ const mrr = await billing.metrics.getMrr({ currency: 'USD' });
139
+ console.log('Current MRR:', mrr.currentMrr);
140
+ console.log('Previous MRR:', mrr.previousMrr);
141
+ console.log('Net New MRR:', mrr.netNewMrr);
142
+
143
+ // Get subscription metrics by status
144
+ const subMetrics = await billing.metrics.getSubscriptionMetrics();
145
+ console.log('Active:', subMetrics.active);
146
+ console.log('Trialing:', subMetrics.trialing);
147
+ console.log('Canceled:', subMetrics.canceled);
148
+ console.log('Past Due:', subMetrics.pastDue);
149
+
150
+ // Get revenue metrics for a period
151
+ const revenue = await billing.metrics.getRevenueMetrics({
152
+ startDate: new Date('2024-01-01'),
153
+ endDate: new Date('2024-12-31'),
154
+ currency: 'USD'
155
+ });
156
+ console.log('Total Revenue:', revenue.totalRevenue);
157
+ console.log('Refunds:', revenue.totalRefunds);
124
158
 
125
- // Get churn rate
126
- const churn = await metrics.getChurnRate({
127
- from: new Date('2024-01-01'),
128
- to: new Date('2024-12-31')
159
+ // Get churn metrics
160
+ const churn = await billing.metrics.getChurnMetrics({
161
+ startDate: new Date('2024-01-01'),
162
+ endDate: new Date('2024-12-31')
129
163
  });
164
+ console.log('Churn Rate:', churn.churnRate);
165
+ console.log('Churned MRR:', churn.churnedMrr);
130
166
 
131
- // Get revenue metrics
132
- const revenue = await metrics.getRevenueMetrics({
133
- from: new Date('2024-01-01'),
134
- to: new Date('2024-12-31'),
167
+ // Get all dashboard metrics aggregated
168
+ const dashboard = await billing.metrics.getDashboard({
135
169
  currency: 'USD'
136
170
  });
171
+ console.log('Dashboard:', dashboard);
137
172
  ```
138
173
 
139
174
  ### Health Checks
@@ -203,11 +238,266 @@ const billing = new QZPayBilling({
203
238
  | `billing.payments` | Payment processing |
204
239
  | `billing.invoices` | Invoice management |
205
240
  | `billing.plans` | Plan configuration |
206
- | `billing.prices` | Price management |
207
241
  | `billing.promoCodes` | Promotional codes |
208
242
  | `billing.entitlements` | Feature entitlements |
209
243
  | `billing.limits` | Usage limits |
210
244
  | `billing.addons` | Add-on management |
245
+ | `billing.paymentMethods` | Payment method management |
246
+ | `billing.metrics` | Business metrics and analytics |
247
+
248
+ ### Entitlements Service
249
+
250
+ Manage feature access based on subscriptions:
251
+
252
+ ```typescript
253
+ // Check if customer has an entitlement
254
+ const hasAccess = await billing.entitlements.check('cus_123', 'advanced_analytics');
255
+ if (hasAccess) {
256
+ // Show advanced analytics
257
+ }
258
+
259
+ // Get all entitlements for a customer
260
+ const entitlements = await billing.entitlements.getByCustomerId('cus_123');
261
+
262
+ // Grant an entitlement manually
263
+ await billing.entitlements.grant('cus_123', 'beta_features', 'manual', 'admin_grant');
264
+
265
+ // Revoke an entitlement
266
+ await billing.entitlements.revoke('cus_123', 'beta_features');
267
+ ```
268
+
269
+ ### Limits Service
270
+
271
+ Track and enforce usage limits:
272
+
273
+ ```typescript
274
+ // Check if customer is within limit
275
+ const result = await billing.limits.check('cus_123', 'api_calls');
276
+ console.log('Allowed:', result.allowed);
277
+ console.log('Current:', result.currentValue);
278
+ console.log('Max:', result.maxValue);
279
+ console.log('Remaining:', result.remaining);
280
+
281
+ // Get all limits for a customer
282
+ const limits = await billing.limits.getByCustomerId('cus_123');
283
+
284
+ // Increment usage
285
+ await billing.limits.increment('cus_123', 'api_calls', 1);
286
+
287
+ // Set a limit value
288
+ await billing.limits.set('cus_123', 'api_calls', 10000);
289
+
290
+ // Record usage (for audit/history)
291
+ await billing.limits.recordUsage('cus_123', 'api_calls', 5, 'increment');
292
+ ```
293
+
294
+ ### Add-ons Service
295
+
296
+ Manage subscription add-ons:
297
+
298
+ ```typescript
299
+ // Create an add-on definition
300
+ const addon = await billing.addons.create({
301
+ name: 'Extra Storage',
302
+ unitAmount: 500, // $5.00 in cents
303
+ currency: 'USD',
304
+ billingInterval: 'month',
305
+ compatiblePlanIds: ['plan_pro', 'plan_enterprise']
306
+ });
307
+
308
+ // Get add-ons compatible with a plan
309
+ const addons = await billing.addons.getByPlanId('plan_pro');
310
+
311
+ // Add an add-on to a subscription
312
+ const result = await billing.addons.addToSubscription({
313
+ subscriptionId: 'sub_123',
314
+ addOnId: 'addon_extra_storage',
315
+ quantity: 2
316
+ });
317
+ console.log('Proration amount:', result.prorationAmount);
318
+
319
+ // Get add-ons attached to a subscription
320
+ const subscriptionAddons = await billing.addons.getBySubscriptionId('sub_123');
321
+
322
+ // Update add-on quantity
323
+ await billing.addons.updateSubscriptionAddOn('sub_123', 'addon_extra_storage', {
324
+ quantity: 5
325
+ });
326
+
327
+ // Remove add-on from subscription
328
+ await billing.addons.removeFromSubscription('sub_123', 'addon_extra_storage');
329
+ ```
330
+
331
+ ### Payment Methods Service
332
+
333
+ Manage customer payment methods:
334
+
335
+ ```typescript
336
+ // Create a payment method
337
+ const paymentMethod = await billing.paymentMethods.create({
338
+ customerId: 'cus_123',
339
+ type: 'card',
340
+ providerPaymentMethodId: 'pm_xxx',
341
+ provider: 'stripe',
342
+ card: {
343
+ brand: 'visa',
344
+ last4: '4242',
345
+ expMonth: 12,
346
+ expYear: 2025
347
+ },
348
+ setAsDefault: true
349
+ });
350
+
351
+ // Get payment methods for a customer
352
+ const methods = await billing.paymentMethods.getByCustomerId('cus_123');
353
+
354
+ // Get the default payment method
355
+ const defaultMethod = await billing.paymentMethods.getDefault('cus_123');
356
+
357
+ // Set a payment method as default
358
+ await billing.paymentMethods.setDefault('cus_123', 'pm_456');
359
+
360
+ // Update a payment method
361
+ await billing.paymentMethods.update('pm_123', {
362
+ card: { expMonth: 1, expYear: 2026 }
363
+ });
364
+
365
+ // Delete a payment method
366
+ await billing.paymentMethods.delete('pm_123');
367
+ ```
368
+
369
+ ### Saved Card Service
370
+
371
+ Unified interface for saving and managing payment cards across providers.
372
+
373
+ ```typescript
374
+ import { createSavedCardService } from '@qazuor/qzpay-stripe'; // or '@qazuor/qzpay-mercadopago'
375
+
376
+ const cardService = createSavedCardService({
377
+ provider: 'stripe',
378
+ stripeSecretKey: 'sk_xxx',
379
+ getProviderCustomerId: async (customerId) => {
380
+ const customer = await db.customers.findById(customerId);
381
+ return customer.stripeCustomerId;
382
+ },
383
+ });
384
+
385
+ // Save a card
386
+ const card = await cardService.save({
387
+ customerId: 'local_cus_123',
388
+ paymentMethodId: 'pm_xxx', // From Stripe.js
389
+ setAsDefault: true,
390
+ });
391
+
392
+ // List all cards
393
+ const cards = await cardService.list('local_cus_123');
394
+
395
+ // Set card as default (Stripe only)
396
+ await cardService.setDefault('local_cus_123', 'pm_xxx');
397
+
398
+ // Remove a card
399
+ await cardService.remove('local_cus_123', 'pm_xxx');
400
+ ```
401
+
402
+ **Provider Differences:**
403
+
404
+ | Feature | Stripe | MercadoPago |
405
+ |---------|--------|-------------|
406
+ | Save card | `paymentMethodId` | `token` |
407
+ | List cards | ✅ | ✅ |
408
+ | Remove card | ✅ | ✅ |
409
+ | Set default | ✅ Native | ❌ Track in your DB |
410
+
411
+ **Note:** MercadoPago doesn't support default payment methods natively. Your application must track the default card ID in its database.
412
+
413
+ ### Subscription Lifecycle Service
414
+
415
+ Automates subscription renewals, trial conversions, and payment retries.
416
+
417
+ ```typescript
418
+ import { createSubscriptionLifecycle } from '@qazuor/qzpay-core';
419
+
420
+ const lifecycle = createSubscriptionLifecycle(billing, storage, {
421
+ gracePeriodDays: 7,
422
+ retryIntervals: [1, 3, 5], // Retry after 1, 3, and 5 days
423
+ trialConversionDays: 0, // Convert immediately when trial ends
424
+
425
+ // Process payment callback
426
+ processPayment: async (input) => {
427
+ const result = await stripe.paymentIntents.create({
428
+ amount: input.amount,
429
+ currency: input.currency,
430
+ customer: await getStripeCustomerId(input.customerId),
431
+ payment_method: input.paymentMethodId,
432
+ confirm: true,
433
+ off_session: true,
434
+ });
435
+ return {
436
+ success: result.status === 'succeeded',
437
+ paymentId: result.id,
438
+ error: result.last_payment_error?.message,
439
+ };
440
+ },
441
+
442
+ // Get default payment method callback
443
+ getDefaultPaymentMethod: async (customerId) => {
444
+ const pm = await db.paymentMethods.findDefault(customerId);
445
+ return pm ? {
446
+ id: pm.id,
447
+ providerPaymentMethodId: pm.stripePaymentMethodId
448
+ } : null;
449
+ },
450
+
451
+ // Optional: event callback for logging/notifications
452
+ onEvent: async (event) => {
453
+ console.log(`[${event.type}] Subscription: ${event.subscriptionId}`);
454
+
455
+ // Send notifications
456
+ if (event.type === 'subscription.renewal_failed') {
457
+ await sendEmail({
458
+ to: customer.email,
459
+ subject: 'Payment Failed',
460
+ body: 'Your subscription payment failed. Please update your payment method.'
461
+ });
462
+ }
463
+ },
464
+ });
465
+
466
+ // Run from a cron job
467
+ const results = await lifecycle.processAll();
468
+ console.log('Renewals:', results.renewals);
469
+ console.log('Trial conversions:', results.trialConversions);
470
+ console.log('Retries:', results.retries);
471
+ console.log('Cancellations:', results.cancellations);
472
+
473
+ // Or run individual operations
474
+ await lifecycle.processRenewals();
475
+ await lifecycle.processTrialConversions();
476
+ await lifecycle.processRetries();
477
+ await lifecycle.processCancellations();
478
+ ```
479
+
480
+ **Lifecycle Events:**
481
+
482
+ - `subscription.renewed` - Subscription successfully renewed
483
+ - `subscription.renewal_failed` - Renewal payment failed
484
+ - `subscription.trial_converted` - Trial converted to paid
485
+ - `subscription.trial_conversion_failed` - Trial conversion failed
486
+ - `subscription.entered_grace_period` - Entered grace period after failed payment
487
+ - `subscription.retry_scheduled` - Payment retry scheduled
488
+ - `subscription.retry_succeeded` - Retry payment succeeded
489
+ - `subscription.retry_failed` - All retries exhausted
490
+ - `subscription.canceled_nonpayment` - Canceled due to non-payment
491
+
492
+ **Cron Setup Example:**
493
+
494
+ ```typescript
495
+ // Run every hour
496
+ cron.schedule('0 * * * *', async () => {
497
+ const results = await lifecycle.processAll();
498
+ console.log(`Processed ${results.renewals.processed} renewals`);
499
+ });
500
+ ```
211
501
 
212
502
  ## Utility Functions
213
503