Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
190c4da
development to staging (#212)
nexera-release[bot] Dec 14, 2023
2613f9d
development to staging (#214)
nexera-release[bot] Dec 14, 2023
9291480
Merge pull request #217 from NexeraProtocol/development
nexera-release[bot] Dec 14, 2023
0d8e925
Merge pull request #229 from NexeraProtocol/development
nexera-release[bot] Mar 1, 2024
2fe7787
Merge pull request #232 from NexeraProtocol/development
nexera-release[bot] Mar 7, 2024
a13b7e5
Merge pull request #240 from NexeraProtocol/development
nexera-release[bot] Mar 12, 2024
aa508ac
Merge pull request #250 from NexeraProtocol/development
nexera-release[bot] Apr 11, 2024
6181c45
Merge pull request #255 from NexeraProtocol/development
nexera-release[bot] Apr 25, 2024
36f00e6
Merge pull request #260 from NexeraProtocol/development
nexera-release[bot] May 6, 2024
b02ecee
Merge pull request #267 from NexeraProtocol/development
nexera-release[bot] May 6, 2024
82f7ed1
Merge pull request #279 from NexeraProtocol/development
nexera-release[bot] Jul 2, 2024
e0944ca
Merge pull request #283 from NexeraProtocol/development
nexera-release[bot] Jul 9, 2024
46c3450
Merge pull request #295 from NexeraProtocol/development
nexera-release[bot] Jul 15, 2024
532eb27
Merge pull request #299 from NexeraProtocol/development
nexera-release[bot] Jul 23, 2024
c3bb3ff
Merge pull request #332 from UnbloktTechnology/development
nexera-release[bot] Aug 19, 2024
f3cee21
Merge pull request #343 from UnbloktTechnology/development
nexera-release[bot] Aug 29, 2024
4fc6bdc
Merge pull request #396 from UnbloktTechnology/development
nexera-release[bot] Sep 20, 2024
86630d2
Merge pull request #404 from UnbloktTechnology/development
nexera-release[bot] Sep 25, 2024
1ec77c4
Merge pull request #406 from UnbloktTechnology/development
nexera-release[bot] Sep 25, 2024
7d6dddb
Merge pull request #420 from UnbloktTechnology/development
nexera-release[bot] Oct 15, 2024
ae6ffe2
Merge pull request #430 from UnbloktTechnology/development
nexera-release[bot] Nov 17, 2024
026bc69
Merge pull request #439 from UnbloktTechnology/development
nexera-release[bot] Jan 7, 2025
b450661
Merge pull request #443 from UnbloktTechnology/development
nexera-release[bot] Jan 20, 2025
b4a8d86
feat: implement wallet/no-wallet flow
CamCompilot Feb 13, 2025
e8e80c9
bump deploy
markoftw Feb 13, 2025
7100d30
fix package name
markoftw Feb 13, 2025
ffb9416
add eslint
markoftw Feb 13, 2025
cd44a85
fix component
markoftw Feb 13, 2025
4acd882
add eslint
markoftw Feb 13, 2025
b92de77
fixes
markoftw Feb 13, 2025
6fd4d64
fixing deployment
CamCompilot Feb 14, 2025
d154ed7
css
CamCompilot Feb 14, 2025
79f5de4
css improvement
CamCompilot Feb 14, 2025
c5e1f57
customer screening
CamCompilot Feb 19, 2025
777ccd9
fixes
CamCompilot Feb 20, 2025
fc3911f
customer to individual + last api call
CamCompilot Mar 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions code-examples/individual-screening/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# ComPilot Individual Screening Example

This example demonstrates how to implement Individual screening using ComPilot's API. It includes:

- Real-time Individual status updates via WebSocket
- Webhook handling with signature verification
- Frontend visualization of screening status
- Example implementation in TypeScript

## Structure

```
┌─────────────────┐
│ │
│ ComPilot API │
│ │
└────────┬────────┘
│ Webhooks
API Calls │
┌──────────────────┘
┌────────────┐ ┌───────────────┐ ┌─────────────┐
│ │ │ │ │ │
│ Frontend │◄──►│ Backend │◄──►│ ngrok │
│ │ │ (TypeScript) │ │ │
└────────────┘ └───────────────┘ └─────────────┘
▲ ▲
│ │
└────────────────────┘
WebSocket Updates
```

## Components

### Frontend (Next.js)
- Provides the developer interface for testing individual screening
- Displays real-time status updates via WebSocket
- Shows detailed webhook logs
- Located in `/frontend`

### Backend (TypeScript)
- Built with Express.js
- Uses WebSocket
- Located in `/backend-typescript`

## Data Flow

1. **Individual Submission**
- Frontend sends individual data to backend (`POST /workflows/{workflowID}/customers`)
- Backend forwards request to ComPilot API
- ComPilot returns 200 OK
- Frontend displays initial status

2. **Status Updates**
- ComPilot sends webhook to backend via ngrok
- Backend broadcasts update via WebSocket
- Frontend updates UI in real-time

## Setup Requirements

1. **ComPilot Account**
- API Key
- Webhook Secret
- Individual Screening workflow
- CMS Project ID

2. **Development Tools**
- Node.js
- ngrok (for webhook testing)

## Getting Started

1. Set up the backend following its README
2. Configure the frontend to point to your backend
3. Start both services

For detailed setup instructions, see:
- [Frontend README](./frontend/README.md)
- [Backend TypeScript README](./backend-typescript/README.md)

## Documentation

- [ComPilot Documentation](https://docs.compilot.ai)
- [API Reference](https://docs.compilot.ai/developers/api)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# API Configuration
COMPILOT_API_URL=https://api.compilot.ai
COMPILOT_API_KEY=

# Webhook Configuration
WEBHOOK_SECRET=

# Workflow ID
COMPILOT_TMS_WORKFLOW_ID=

# Server Configuration
PORT=3001
NODE_ENV=development

# Optional: If you need to specify a custom webhook URL for ComPilot to call back
WEBHOOK_URL=
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
node_modules/
dist/

# environment variables
.env
.env.local

# IDE
.idea/
.vscode/

# package managers
yarn.lock
package-lock.json

# misc
.DS_Store
113 changes: 113 additions & 0 deletions code-examples/individual-screening/backend-typescript/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
ComPilot Customer Screening Example - Backend TypeScript

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya encore ecrit Customer Screening

====================================================

This example demonstrates how to build a backend server that handles customer screening and status updates using ComPilot's API. It includes real-time updates via WebSocket and webhook processing.

## Features

- Express.js REST API for customer screening
- WebSocket server for real-time status updates
- Webhook handler with SVIX signature verification
- Support for Individual and Business customers
- Customer screening status tracking and broadcasting

## Prerequisites

- Access to ComPilot dashboard with an API key
- A customer screening workflow set up in your workspace
- Node.js and npm/yarn installed
- ngrok for webhook testing

## Project Structure

```
src/
├── controllers/
│ ├── WebhookController.ts # Webhook handling and verification
│ └── customers.ts # Customer screening submission
├── services/
│ └── compilot.ts # ComPilot API integration
├── routes/
│ ├── customers.ts # Customer routes
│ └── webhookRoutes.ts # Webhook routes
├── websocket/
│ └── index.ts # WebSocket server implementation
└── types/
└── customer.ts # Type definitions
```

## Getting Started

1. Install dependencies:
```bash
yarn install
```

2. Set up environment variables:
```bash
cp .env.example .env
```

3. Update `.env` with your configuration:
```env
# API Configuration
COMPILOT_API_URL=https://api.compilot.ai
COMPILOT_API_KEY=your_api_key

# Webhook Configuration
WEBHOOK_SECRET=your_webhook_secret

# Workflow ID
COMPILOT_SCREENING_WORKFLOW_ID=your_workflow_id

# Server Configuration
PORT=8080
NODE_ENV=development
```

4. Start ngrok tunnel:
```bash
ngrok http 8080
```

5. Configure webhook URL in ComPilot dashboard with your ngrok URL

6. Start the server:
```bash
yarn dev
```

## API Endpoints

### Customer Screening
```http
POST /api/customers
Content-Type: application/json

{
"workspaceId": "your_workspace_id",
"organizationId": "your_organization_id",
"workflowId": "your_workflow_id"
}
```

### Webhook Endpoint
```http
POST /
```
Handles ComPilot webhook events with SVIX signature verification.

### WebSocket
```
WS /ws
```
Provides real-time customer screening status updates to connected clients.

## Documentation

- [ComPilot Documentation](https://docs.compilot.ai)
- [API Reference](https://docs.compilot.ai/developers/api)

## Related

- [Frontend Implementation](../frontend)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "transaction-monitor-backend",
"version": "1.0.0",
"description": "Transaction monitoring example backend",
"main": "dist/index.js",
"scripts": {
"start": "node dist/index.js",
"dev": "nodemon src/index.ts",
"build": "tsc",
"lint": "eslint src/**/*.ts",
"format": "prettier --write \"src/**/*.ts\""
},
"dependencies": {
"@nexeraid/identity-schemas": "^2.72.0",
"axios": "^1.6.7",
"cors": "^2.8.5",
"dotenv": "^16.4.1",
"express": "^4.21.2",
"uuid": "^11.0.4",
"ws": "^8.18.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
"@types/node": "^20.11.16",
"@types/uuid": "^10.0.0",
"@types/ws": "^8.5.13",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.56.0",
"nodemon": "^3.0.3",
"prettier": "^3.2.5",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { Request, Response } from 'express';
import { IWebSocketServer } from '../websocket';
import crypto from 'crypto';

/**
* Controller handling ComPilot webhook events.
* This controller:
* 1. Receives webhook events from ComPilot
* 2. Verifies webhook signatures using SVIX
* 3. Broadcasts verified events to connected WebSocket clients
*
* Required environment variables:
* - WEBHOOK_SECRET: The webhook signing secret from ComPilot
*/
export class WebhookController {
private webhookSecret: string;

constructor(private wsServer: IWebSocketServer) {
this.webhookSecret = process.env.WEBHOOK_SECRET || '';
}

/**
* Verifies the authenticity of incoming webhooks using SVIX signatures.
*
* @param payload - The webhook payload to verify
* @param headers - The request headers containing SVIX signature details
* @returns boolean - Whether the signature is valid
*/
private verifySignature(payload: any, headers: any): boolean {
try {
if (!this.webhookSecret) {
return true; // Skip verification if no secret is configured
}

const svixId = headers['svix-id'];
const svixTimestamp = headers['svix-timestamp'];
const svixSignature = headers['svix-signature'];

if (!svixId || !svixTimestamp || !svixSignature) {
return false;
}

const message = Buffer.from(`${svixId}.${svixTimestamp}.${JSON.stringify(payload)}`);
const secretKey = this.webhookSecret.replace('whsec_', '');
const secretBytes = Buffer.from(secretKey, 'base64');

const computedSignature = crypto
.createHmac('sha256', secretBytes)
.update(message)
.digest('base64');

const expectedSignature = svixSignature.split(',')[1];
return crypto.timingSafeEqual(
Buffer.from(computedSignature),
Buffer.from(expectedSignature)
);
} catch (error) {
console.error('❌ Signature verification failed:', error);
return false;
}
}

/**
* Handles incoming webhook requests.
* 1. Logs the received webhook
* 2. Verifies the webhook signature
* 3. Broadcasts the webhook data to all connected clients
*
* Expected webhook format:
* {
* type: string, // e.g., 'transaction.updated'
* payload: {
* transactionId: string,
* status: string,
* ...other fields
* }
* }
*/
handleWebhook = (req: Request, res: Response): void => {
try {
console.log('📦 WEBHOOK RECEIVED:', {
eventType: req.body.eventType,
customerId: req.body.payload.customerId,
externalCustomerId: req.body.payload.externalCustomerId,
status: req.body.payload.status
});

if (!this.verifySignature(req.body, req.headers)) {
res.status(401).json({ error: 'Invalid signature' });
return;
}

// Broadcast to all connected clients
console.log('📤 Broadcasting webhook:', req.body);
this.wsServer.broadcast(req.body);
res.json({ received: true });
} catch (error) {
console.error('❌ Webhook error:', error);
res.status(500).json({ error: 'Internal server error' });
}
}
}
Loading