# CatholicPay Integration Flow

This document explains how to integrate CatholicPay (your existing production application) with the Notification Microservice.

## Overview

```
┌─────────────────┐         ┌──────────────────────┐         ┌──────────────────┐
│   CatholicPay   │────────▶│ Notification Service │────────▶│  CatholicPay      │
│  (Your App)     │ Events  │   (This Microservice)│ Notify  │  Users (Mobile/Web)│
└─────────────────┘         └──────────────────────┘         └──────────────────┘
```

**Flow Summary:**
1. CatholicPay sends events to Notification Service
2. Notification Service evaluates rules and creates notifications
3. Notifications are delivered to users via Pusher (real-time) or Push (offline)
4. Users receive notifications in CatholicPay app

---

## Phase 1: Initial Setup

### Step 1: Create Project in Notification Service

**First, you need to get API credentials for CatholicPay.**

**Option A: Via Platform Admin API** (Recommended)

```bash
# 1. Login as platform admin
POST https://notification-service.com/api/v1/platform/auth/login
Body: {
  "email": "admin@platform.com",
  "password": "admin-password"
}
Response: { accessToken, refreshToken }

# 2. Create project for CatholicPay
POST https://notification-service.com/api/v1/platform/projects
Headers: Authorization: Bearer <platform_admin_token>
Body: {
  "name": "CatholicPay",
  "status": "active",
  "plan": "professional",
  "billingEmail": "billing@catholicpay.com",
  "webhookUrl": "https://catholicpay.com/webhooks/notifications",
  "webhookSecret": "your-webhook-secret-here",
  "pusherConfig": {
    "appId": "your-pusher-app-id",
    "key": "your-pusher-key",
    "secret": "your-pusher-secret",
    "cluster": "us2"
  }
}
Response: {
  "id": "project-uuid",
  "apiKey": "pk_prod_abc123...",  ← SAVE THIS!
  "apiSecret": "sk_prod_xyz789..." ← SAVE THIS! (shown only once)
}
```

**Option B: Direct Database** (Not recommended for production)

Manually create project in database (you'll need to hash the API secret yourself).

### Step 2: Store API Credentials in CatholicPay

Add to your CatholicPay environment variables:

```env
NOTIFICATION_SERVICE_URL=https://notification-service.com
NOTIFICATION_API_KEY=pk_prod_abc123...
NOTIFICATION_API_SECRET=sk_prod_xyz789...
NOTIFICATION_WEBHOOK_SECRET=your-webhook-secret-here
```

---

## Phase 2: User Synchronization

### Option A: Sync Existing Users (Bulk)

If you already have users in CatholicPay, sync them to the notification service:

```javascript
// In CatholicPay backend
const axios = require('axios');

async function syncCatholicPayUsers() {
  const catholicPayUsers = await getUsersFromCatholicPayDatabase();
  
  const response = await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/users/sync`,
    {
      users: catholicPayUsers.map(user => ({
        email: user.email,
        externalUserId: user.id.toString(), // CatholicPay user ID
        fullName: user.name,
        roles: user.roles || ['user'],
        // Optional: password will be auto-generated if not provided
      }))
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
        'Content-Type': 'application/json',
      }
    }
  );
  
  console.log(`Synced ${response.data.created} users`);
  return response.data;
}
```

**Note:** Users created via sync will have status `"unverified"` (no password). They'll need to be approved by admin.

### Option B: Create Users On-Demand

When a new user registers in CatholicPay, create them in notification service:

```javascript
// In CatholicPay user registration handler
async function onUserRegistered(catholicPayUser) {
  // Step 1: Create user in notification service
  const createUserResponse = await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/users`,
    {
      email: catholicPayUser.email,
      password: generateRandomPassword(), // Or let them set it later
      fullName: catholicPayUser.name,
      externalUserId: catholicPayUser.id.toString(),
      roles: catholicPayUser.roles || ['user'],
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
      }
    }
  );
  
  const newUserId = createUserResponse.data.id;
  
  // Step 2: Auto-approve the user (if you trust your registration process)
  // First, get admin JWT token (you can cache this token)
  const adminToken = await getAdminJwtToken();
  
  // Then approve the user immediately
  await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/users/${newUserId}/approve`,
    { roles: catholicPayUser.roles || ['user'] },
    {
      headers: {
        'Authorization': `Bearer ${adminToken}`
      }
    }
  );
  
  // User is now active and can login/receive notifications
}

// Helper function to get admin JWT token (cache this token!)
async function getAdminJwtToken() {
  // Option 1: Use a dedicated admin account
  const loginResponse = await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/auth/login`,
    {
      email: process.env.NOTIFICATION_ADMIN_EMAIL,
      password: process.env.NOTIFICATION_ADMIN_PASSWORD,
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
      }
    }
  );
  
  return loginResponse.data.accessToken;
  
  // Option 2: Cache the token and refresh when expired
  // See integration-examples.js for token caching example
}
```

### Step 3: Approve Users

Users need to be approved before they can receive notifications. You can:

**A. Auto-approve trusted users:**

To auto-approve users, you need an admin JWT token. Here's a complete example:

```javascript
// Complete auto-approval flow
async function createAndAutoApproveUser(catholicPayUser) {
  // Step 1: Create user
  const createResponse = await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/users`,
    {
      email: catholicPayUser.email,
      password: generateRandomPassword(),
      fullName: catholicPayUser.name,
      externalUserId: catholicPayUser.id.toString(),
      roles: catholicPayUser.roles || ['user'],
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
      }
    }
  );
  
  const newUserId = createResponse.data.id;
  
  // Step 2: Get admin JWT token (cache this!)
  const adminToken = await getAdminJwtToken();
  
  // Step 3: Immediately approve the user
  await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/users/${newUserId}/approve`,
    { roles: catholicPayUser.roles || ['user'] },
    {
      headers: {
        'Authorization': `Bearer ${adminToken}`
      }
    }
  );
  
  // User is now active and can login/receive notifications
  return createResponse.data;
}

// Helper: Get admin JWT token (with caching)
let cachedAdminToken = null;
let tokenExpiry = null;

async function getAdminJwtToken() {
  // Check if cached token is still valid (refresh before expiry)
  if (cachedAdminToken && tokenExpiry && Date.now() < tokenExpiry - 60000) {
    return cachedAdminToken;
  }
  
  // Login as admin to get new token
  const loginResponse = await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/auth/login`,
    {
      email: process.env.NOTIFICATION_ADMIN_EMAIL, // e.g., 'admin@catholicpay.com'
      password: process.env.NOTIFICATION_ADMIN_PASSWORD,
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
      }
    }
  );
  
  cachedAdminToken = loginResponse.data.accessToken;
  // Tokens typically expire in 1 hour, cache for 50 minutes
  tokenExpiry = Date.now() + (50 * 60 * 1000);
  
  return cachedAdminToken;
}
```

**Important Notes:**
- You need an admin user account in the notification service
- Store admin credentials in environment variables (never commit them!)
- Cache the admin JWT token to avoid logging in for every approval
- The token expires after ~1 hour, so refresh it before expiry

**B. Manual approval via admin panel:**
- Admin logs into notification service
- Views pending users
- Approves them

---

## Phase 3: Setup Notification Rules

Define when and how notifications should be sent based on events.

### Example: Transaction Notification Rule

```javascript
// In CatholicPay admin panel or setup script
async function setupTransactionNotificationRule() {
  // First, login as admin to get JWT token
  const loginResponse = await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/auth/login`,
    {
      email: 'admin@catholicpay.com',
      password: 'admin-password'
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
      }
    }
  );
  
  const jwtToken = loginResponse.data.accessToken;
  
  // Create rule for pending transactions
  await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/rules`,
    {
      name: "Pending Transaction Alert",
      condition: "event.type == 'pending_transaction' && event.payload.amount > 10000",
      targetRoles: ["admin", "finance"],
      title: "Pending Transaction",
      message: "Transaction {{event.payload.transactionId}} for ₦{{event.payload.amount}} is pending approval",
      sound: "alert.mp3",
      action: {
        type: "open_webview",
        url: "https://catholicpay.com/transactions/{{event.payload.transactionId}}",
        editableAddressBar: false
      },
      active: true
    },
    {
      headers: {
        'Authorization': `Bearer ${jwtToken}`
      }
    }
  );
}
```

### Common Rules for CatholicPay

```javascript
const rules = [
  {
    name: "High Value Transaction",
    condition: "event.type == 'pending_transaction' && event.payload.amount > 100000",
    targetRoles: ["admin"],
    title: "High Value Transaction",
    message: "Transaction {{event.payload.transactionId}} for ₦{{event.payload.amount}} requires attention"
  },
  {
    name: "Payment Successful",
    condition: "event.type == 'payment_successful'",
    targetRoles: ["user"],
    title: "Payment Successful",
    message: "Your payment of ₦{{event.payload.amount}} was successful"
  },
  {
    name: "Balance Low",
    condition: "event.type == 'balance_update' && event.payload.newBalance < 1000",
    targetRoles: ["user"],
    title: "Low Balance",
    message: "Your balance is low: ₦{{event.payload.newBalance}}"
  }
];
```

---

## Phase 4: Event Ingestion (The Main Flow)

### When Events Happen in CatholicPay

Whenever something important happens in CatholicPay, send an event to the notification service:

```javascript
// In CatholicPay backend - Transaction Service
async function handleTransactionCreated(transaction) {
  // 1. Process transaction in CatholicPay
  await processTransaction(transaction);
  
  // 2. Send event to notification service
  await axios.post(
    `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/events`,
    {
      type: 'pending_transaction',
      payload: {
        transactionId: transaction.id,
        amount: transaction.amount,
        currency: transaction.currency,
        userId: transaction.userId,
        status: transaction.status,
        // Add any other relevant data
      },
      clientEventId: `tx_${transaction.id}` // For tracking
    },
    {
      headers: {
        'X-API-Key': process.env.NOTIFICATION_API_KEY,
        'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
        'Content-Type': 'application/json',
      }
    }
  );
}
```

### Complete Event Flow

```
┌─────────────────────────────────────────────────────────────────┐
│ 1. Event Occurs in CatholicPay                                  │
│    - Transaction created                                        │
│    - Payment successful                                         │
│    - Balance updated                                             │
└────────────────────┬────────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│ 2. CatholicPay Sends Event                                      │
│    POST /api/v1/events                                          │
│    Headers: X-API-Key, X-API-Secret                             │
│    Body: { type, payload, clientEventId }                       │
└────────────────────┬────────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│ 3. Notification Service Processes Event                         │
│    - Event stored in database                                   │
│    - Active rules evaluated against event                       │
│    - Matching rules create notifications                        │
└────────────────────┬────────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. Notifications Created                                        │
│    - For each matching rule                                     │
│    - For each user in targetRoles                               │
│    - Notification stored in database                            │
└────────────────────┬────────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│ 5. Notification Delivery                                        │
│    ┌──────────────────┐         ┌──────────────────┐          │
│    │ User Online?     │────────▶│ Deliver via Pusher│          │
│    │ (Has Pusher      │  YES    │ (Real-time)       │          │
│    │  connection)    │         └──────────────────┘          │
│    └──────────────────┘                                        │
│           │ NO                                                  │
│           ▼                                                     │
│    ┌──────────────────┐                                        │
│    │ Queue for Push   │                                        │
│    │ Notification     │                                        │
│    │ (FCM/APNs)       │                                        │
│    └──────────────────┘                                        │
└─────────────────────────────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│ 6. User Receives Notification                                   │
│    - In CatholicPay mobile app (via Pusher)                    │
│    - As push notification (if offline)                          │
│    - In CatholicPay web app (via Pusher)                        │
└─────────────────────────────────────────────────────────────────┘
```

### Example: Complete Transaction Flow

```javascript
// In CatholicPay - Transaction Service

// When transaction is created
async function createTransaction(data) {
  // 1. Create transaction in CatholicPay
  const transaction = await db.transactions.create({
    userId: data.userId,
    amount: data.amount,
    currency: 'NGN',
    status: 'pending',
    type: data.type
  });
  
  // 2. Send event to notification service
  await sendEventToNotificationService({
    type: 'pending_transaction',
    payload: {
      transactionId: transaction.id,
      amount: transaction.amount,
      currency: transaction.currency,
      userId: transaction.userId,
      status: 'pending',
      type: transaction.type
    },
    clientEventId: `tx_${transaction.id}`
  });
  
  return transaction;
}

// When transaction is approved
async function approveTransaction(transactionId) {
  const transaction = await db.transactions.update(transactionId, {
    status: 'approved'
  });
  
  // Send event
  await sendEventToNotificationService({
    type: 'transaction_approved',
    payload: {
      transactionId: transaction.id,
      amount: transaction.amount,
      userId: transaction.userId
    }
  });
}

// Helper function
async function sendEventToNotificationService(event) {
  try {
    await axios.post(
      `${process.env.NOTIFICATION_SERVICE_URL}/api/v1/events`,
      event,
      {
        headers: {
          'X-API-Key': process.env.NOTIFICATION_API_KEY,
          'X-API-Secret': process.env.NOTIFICATION_API_SECRET,
          'Content-Type': 'application/json',
        }
      }
    );
  } catch (error) {
    // Log error but don't fail the main operation
    console.error('Failed to send event to notification service:', error);
  }
}
```

---

## Phase 5: Client-Side Integration (CatholicPay Mobile/Web App)

### Step 1: Initialize Pusher in CatholicPay App

```javascript
// In CatholicPay mobile/web app
import Pusher from 'pusher-js';

// Get Pusher config from your project settings
const pusherConfig = {
  key: 'your-pusher-key', // From project.pusherConfig.key
  cluster: 'us2', // From project.pusherConfig.cluster
  authEndpoint: `${NOTIFICATION_SERVICE_URL}/api/v1/users/me/pusher-auth`,
  auth: {
    headers: {
      Authorization: `Bearer ${userJwtToken}` // Get from login
    }
  }
};

const pusher = new Pusher(pusherConfig.key, {
  cluster: pusherConfig.cluster,
  authEndpoint: pusherConfig.authEndpoint,
  auth: pusherConfig.auth
});
```

### Step 2: Subscribe to User's Notification Channel

```javascript
// After user logs in to CatholicPay
async function setupNotifications(userId, jwtToken) {
  // Subscribe to user's private channel
  const channel = pusher.subscribe(`private-user-${userId}`);
  
  // Listen for notifications
  channel.bind('notification', (data) => {
    console.log('New notification:', data);
    
    // Display notification in CatholicPay app
    showNotification({
      id: data.id,
      title: data.title,
      message: data.message,
      sound: data.sound,
      action: data.action
    });
    
    // Play sound if provided
    if (data.sound) {
      playSound(data.sound);
    }
    
    // Handle action (e.g., open transaction detail)
    if (data.action && data.action.type === 'open_webview') {
      openWebView(data.action.url);
    }
  });
}
```

### Step 3: Update Push Tokens

When user logs in or device token changes:

```javascript
// In CatholicPay app - after login
async function updatePushTokens(fcmToken, apnsToken) {
  await axios.patch(
    `${NOTIFICATION_SERVICE_URL}/api/v1/users/me/push-tokens`,
    {
      fcm: fcmToken, // Android
      apns: apnsToken // iOS
    },
    {
      headers: {
        'Authorization': `Bearer ${userJwtToken}`
      }
    }
  );
}
```

### Step 4: Fetch Notifications

```javascript
// In CatholicPay app - notification center
async function fetchNotifications(page = 1) {
  const response = await axios.get(
    `${NOTIFICATION_SERVICE_URL}/api/v1/notifications`,
    {
      params: { page, limit: 20 },
      headers: {
        'Authorization': `Bearer ${userJwtToken}`
      }
    }
  );
  
  return response.data; // { data: [...], meta: {...} }
}

// Get unread count for badge
async function getUnreadCount() {
  const response = await axios.get(
    `${NOTIFICATION_SERVICE_URL}/api/v1/notifications/unread/count`,
    {
      headers: {
        'Authorization': `Bearer ${userJwtToken}`
      }
    }
  );
  
  return response.data.count;
}
```

---

## Phase 6: Webhook Integration (Optional)

If you want to be notified when notifications are delivered/acknowledged:

### Setup Webhook Handler in CatholicPay

```javascript
// In CatholicPay backend - webhook endpoint
app.post('/webhooks/notifications', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  const event = req.headers['x-webhook-event'];
  const payload = JSON.parse(req.body);
  
  // Verify HMAC signature
  const crypto = require('crypto');
  const hmac = crypto.createHmac('sha256', process.env.NOTIFICATION_WEBHOOK_SECRET);
  hmac.update(JSON.stringify(payload));
  const expectedSignature = `sha256=${hmac.digest('hex')}`;
  
  if (signature !== expectedSignature) {
    return res.status(401).send('Invalid signature');
  }
  
  // Handle webhook events
  switch (event) {
    case 'notification.delivered':
      console.log('Notification delivered:', payload.data.notificationId);
      // Update your database, send analytics, etc.
      break;
      
    case 'notification.acknowledged':
      console.log('Notification acknowledged:', payload.data.notificationId);
      // Track user engagement
      break;
      
    case 'quota.warning':
      console.warn('Quota warning:', payload.data);
      // Alert billing team
      break;
      
    case 'quota.exceeded':
      console.error('Quota exceeded:', payload.data);
      // Suspend service, alert billing
      break;
  }
  
  res.status(200).send('OK');
});
```

---

## Complete End-to-End Example

### Scenario: User Makes a Payment in CatholicPay

```javascript
// 1. In CatholicPay - Payment Service
async function processPayment(paymentData) {
  // Create payment record
  const payment = await db.payments.create({
    userId: paymentData.userId,
    amount: paymentData.amount,
    status: 'pending'
  });
  
  // Send event to notification service
  await sendEvent({
    type: 'payment_initiated',
    payload: {
      paymentId: payment.id,
      amount: payment.amount,
      userId: payment.userId
    }
  });
  
  // Process payment (gateway, etc.)
  const result = await processWithGateway(payment);
  
  if (result.success) {
    // Update payment status
    await db.payments.update(payment.id, { status: 'success' });
    
    // Send success event
    await sendEvent({
      type: 'payment_successful',
      payload: {
        paymentId: payment.id,
        amount: payment.amount,
        userId: payment.userId
      }
    });
  } else {
    // Send failure event
    await sendEvent({
      type: 'payment_failed',
      payload: {
        paymentId: payment.id,
        amount: payment.amount,
        userId: payment.userId,
        error: result.error
      }
    });
  }
}

// 2. Notification Service receives event
//    - Evaluates rules
//    - Creates notification: "Payment of ₦5,000 successful"
//    - Checks if user is online (has Pusher connection)

// 3. If user is online:
//    - Notification sent via Pusher to channel "private-user-{userId}"
//    - CatholicPay app receives it in real-time
//    - User sees notification immediately

// 4. If user is offline:
//    - Notification queued for push notification
//    - FCM/APNs sends push notification
//    - User sees notification when they open app

// 5. User opens notification in CatholicPay app
//    - App calls: POST /api/v1/notifications/:id/acknowledge
//    - Webhook sent to CatholicPay (if configured)
```

---

## Integration Checklist

- [ ] **Phase 1: Setup**
  - [ ] Create project in notification service
  - [ ] Get API Key and Secret
  - [ ] Configure Pusher credentials
  - [ ] Store credentials in CatholicPay environment

- [ ] **Phase 2: User Sync**
  - [ ] Sync existing users (bulk)
  - [ ] Setup user creation on registration
  - [ ] Approve users (auto or manual)

- [ ] **Phase 3: Rules**
  - [ ] Create notification rules
  - [ ] Test rules with sample events
  - [ ] Configure sounds and actions

- [ ] **Phase 4: Events**
  - [ ] Identify events to send (transactions, payments, etc.)
  - [ ] Integrate event sending in CatholicPay
  - [ ] Test event ingestion

- [ ] **Phase 5: Client**
  - [ ] Initialize Pusher in CatholicPay app
  - [ ] Subscribe to notification channels
  - [ ] Handle incoming notifications
  - [ ] Update push tokens
  - [ ] Build notification center UI

- [ ] **Phase 6: Webhooks** (Optional)
  - [ ] Setup webhook endpoint in CatholicPay
  - [ ] Verify webhook signatures
  - [ ] Handle webhook events

---

## Common Integration Patterns

### Pattern 1: Transaction Notifications

```javascript
// Send event when transaction status changes
const events = {
  'pending': 'pending_transaction',
  'approved': 'transaction_approved',
  'rejected': 'transaction_rejected',
  'completed': 'transaction_completed'
};

await sendEvent({
  type: events[transaction.status],
  payload: { transactionId, amount, userId, status }
});
```

### Pattern 2: User Activity Notifications

```javascript
// Send event for important user actions
await sendEvent({
  type: 'user_action',
  payload: {
    action: 'login',
    userId: user.id,
    timestamp: new Date().toISOString()
  }
});
```

### Pattern 3: Batch Events

```javascript
// Send multiple events at once
await axios.post(
  `${NOTIFICATION_SERVICE_URL}/api/v1/events/batch`,
  {
    events: [
      { type: 'payment_successful', payload: {...} },
      { type: 'balance_updated', payload: {...} }
    ]
  },
  { headers: { 'X-API-Key': ..., 'X-API-Secret': ... } }
);
```

---

## Troubleshooting

### Issue: Events not creating notifications
**Check:**
- Rules are active
- Event type matches rule condition
- Users have correct roles
- Users are approved (status = "active")

### Issue: Notifications not delivered
**Check:**
- Pusher configuration is correct
- User has active Pusher connection
- Push tokens are updated
- User status is "active"

### Issue: Webhook not receiving events
**Check:**
- Webhook URL is accessible
- Webhook secret matches
- Signature verification is correct

---

## Next Steps

1. Start with Phase 1 (Setup) - Get your API credentials
2. Test with Phase 4 (Events) - Send a test event
3. Setup Phase 3 (Rules) - Create a simple rule
4. Integrate Phase 5 (Client) - Connect your app
5. Scale up - Add more events and rules

For detailed API documentation, see `Public-API.postman_collection.json` and `AUTHENTICATION_FLOW.md`.

