لا يجب أن يكون دمج حلول الامتثال في بورصة العملات المشفرة الخاصة بك معقداً. يرشدك هذا الدليل الشامل خلال تطبيق واجهات API الخاصة بـ Vera AI وLive AML وقاعدة السفر من Defy مع أمثلة كود حقيقية وأفضل الممارسات والأخطاء الشائعة التي يجب تجنبها.
## البدء
### المتطلبات الأساسية
قبل التكامل:
- حساب Defy نشط
- بيانات اعتماد API (مفتاح API + السر)
- بيئة تطوير
- الوصول إلى بيئة الاختبار (Sandbox)
- فهم أساسي لواجهات REST APIs
### مصادقة API
تستخدم جميع واجهات Defy APIs مصادقة مفتاح API مع توقيعات HMAC:
```javascript
const crypto = require('crypto');
function generateSignature(apiSecret, method, path, timestamp, body = '') {
const message = `${method}${path}${timestamp}${body}`;
return crypto
.createHmac('sha256', apiSecret)
.update(message)
.digest('hex');
}
// مثال على الاستخدام
const apiKey = process.env.DEFY_API_KEY;
const apiSecret = process.env.DEFY_API_SECRET;
const timestamp = Date.now().toString();
const method = 'POST';
const path = '/v1/identity/verify';
const body = JSON.stringify({ userId: '12345' });
const signature = generateSignature(apiSecret, method, path, timestamp, body);
// إضافة إلى رؤوس الطلب
const headers = {
'X-Defy-API-Key': apiKey,
'X-Defy-Timestamp': timestamp,
'X-Defy-Signature': signature,
'Content-Type': 'application/json'
};
```
### تثبيت SDK
**Node.js:**
```bash
npm install @defy/compliance-sdk
```
**Python:**
```bash
pip install defy-compliance
```
**Go:**
```bash
go get github.com/defy/compliance-go
```
**PHP:**
```bash
composer require defy/compliance-sdk
```
## تكامل Vera AI (التحقق من الهوية/KYB)
### تدفق التحقق من الهوية للأفراد
**الخطوة 1: بدء جلسة التحقق من الهوية**
```javascript
const { VeraAI } = require('@defy/compliance-sdk');
const vera = new VeraAI({
apiKey: process.env.DEFY_API_KEY,
apiSecret: process.env.DEFY_API_SECRET,
environment: 'production', // أو 'sandbox'
webhookUrl: 'https://your-platform.com/webhooks/vera'
});
// إنشاء جلسة التحقق من الهوية
async function startVerification(userId, userInfo) {
try {
const session = await vera.createSession({
userId: userId,
verificationType: 'individual',
requiredChecks: [
'identity_document',
'proof_of_address',
'biometric',
'sanctions_screening',
'pep_screening'
],
userInfo: {
firstName: userInfo.firstName,
lastName: userInfo.lastName,
dateOfBirth: userInfo.dateOfBirth,
nationality: userInfo.nationality,
email: userInfo.email,
phone: userInfo.phone
},
metadata: {
ipAddress: userInfo.ipAddress,
userAgent: userInfo.userAgent,
signupDate: userInfo.signupDate
}
});
return {
sessionId: session.id,
redirectUrl: session.redirectUrl,
expiresAt: session.expiresAt
};
} catch (error) {
console.error('فشل إنشاء جلسة التحقق من الهوية:', error);
throw error;
}
}
```
**الخطوة 2: معالجة نتائج التحقق**
```javascript
// نقطة نهاية Webhook
app.post('/webhooks/vera', async (req, res) => {
// التحقق من توقيع webhook
const isValid = vera.verifyWebhookSignature(
req.headers['x-defy-signature'],
req.body
);
if (!isValid) {
return res.status(401).json({ error: 'توقيع غير صالح' });
}
const event = req.body;
switch (event.type) {
case 'verification.completed':
await handleVerificationCompleted(event.data);
break;
case 'verification.failed':
await handleVerificationFailed(event.data);
break;
case 'verification.pending_review':
await handleVerificationPendingReview(event.data);
break;
}
res.sendStatus(200);
});
async function handleVerificationCompleted(data) {
const {
userId,
sessionId,
riskScore,
verificationLevel,
checks
} = data;
// تحديث المستخدم في قاعدة البيانات
await db.users.update(userId, {
verificationStatus: 'completed',
kycLevel: verificationLevel,
riskScore: riskScore,
verificationCompletedAt: new Date(),
verificationChecks: checks
});
// تمكين التداول
await enableUserTrading(userId);
// إخطار المستخدم
await sendEmail(userId, 'نجح التحقق من الهوية');
}
```
**الخطوة 3: اتخاذ القرار بناءً على المخاطر**
```javascript
async function makeVerificationDecision(userId, verificationData) {
const { riskScore, checks, flags } = verificationData;
// الموافقة التلقائية للمخاطر المنخفضة
if (riskScore < 30 && allChecksPassed(checks)) {
return {
decision: 'approved',
level: 'standard',
limits: {
dailyDeposit: 50000,
dailyWithdrawal: 50000,
monthlyVolume: 1000000
}
};
}
// المراجعة اليدوية للمخاطر المتوسطة
if (riskScore >= 30 && riskScore < 70) {
await queueForManualReview(userId, verificationData);
return {
decision: 'pending_review',
estimatedTime: '24 ساعة'
};
}
// الرفض للمخاطر العالية
if (riskScore >= 70 || hasCriticalFlags(flags)) {
await logRejection(userId, flags);
return {
decision: 'rejected',
reason: determineRejectionReason(flags)
};
}
}
function allChecksPassed(checks) {
return checks.every(check => check.status === 'passed');
}
function hasCriticalFlags(flags) {
const criticalFlags = [
'sanctions_hit',
'pep_high_risk',
'fraudulent_document',
'stolen_identity'
];
return flags.some(flag => criticalFlags.includes(flag.type));
}
```
### تدفق KYB للشركات
```javascript
async function startKYB(companyId, companyInfo) {
const session = await vera.createSession({
companyId: companyId,
verificationType: 'business',
requiredChecks: [
'company_registry',
'tax_verification',
'ubo_identification',
'authorized_signatories',
'business_license'
],
companyInfo: {
legalName: companyInfo.legalName,
registrationNumber: companyInfo.registrationNumber,
taxId: companyInfo.taxId,
incorporationCountry: companyInfo.country,
businessType: companyInfo.businessType,
website: companyInfo.website
},
ubos: companyInfo.ubos.map(ubo => ({
firstName: ubo.firstName,
lastName: ubo.lastName,
ownership: ubo.ownershipPercentage,
dateOfBirth: ubo.dateOfBirth,
nationality: ubo.nationality
}))
});
return session;
}
```
## تكامل Live AML
### مراقبة المعاملات
**الفحص قبل المعاملة:**
```javascript
const { LiveAML } = require('@defy/compliance-sdk');
const liveAML = new LiveAML({
apiKey: process.env.DEFY_API_KEY,
apiSecret: process.env.DEFY_API_SECRET
});
async function screenTransaction(transaction) {
try {
const result = await liveAML.screenTransaction({
transactionId: transaction.id,
userId: transaction.userId,
type: transaction.type, // 'deposit', 'withdrawal', 'trade'
amount: transaction.amount,
currency: transaction.currency,
blockchain: transaction.blockchain,
addresses: {
from: transaction.fromAddress,
to: transaction.toAddress
},
metadata: {
timestamp: transaction.timestamp,
ipAddress: transaction.ipAddress,
deviceId: transaction.deviceId
}
});
return {
allowed: result.decision === 'approved',
riskScore: result.riskScore,
riskLevel: result.riskLevel,
flags: result.flags,
requiresReview: result.decision === 'manual_review'
};
} catch (error) {
// عند الخطأ، الافتراضي للمراجعة اليدوية للسلامة
console.error('خطأ في فحص AML:', error);
return {
allowed: false,
requiresReview: true,
error: error.message
};
}
}
// الاستخدام في تدفق السحب
app.post('/api/withdraw', async (req, res) => {
const { userId, amount, currency, toAddress } = req.body;
// إنشاء معاملة معلقة
const transaction = await db.transactions.create({
userId,
type: 'withdrawal',
amount,
currency,
toAddress,
status: 'pending_aml_check'
});
// فحص المعاملة
const amlResult = await screenTransaction(transaction);
if (amlResult.allowed) {
// الموافقة والمعالجة
await db.transactions.update(transaction.id, {
status: 'approved',
riskScore: amlResult.riskScore
});
await processWithdrawal(transaction.id);
res.json({ success: true, transactionId: transaction.id });
} else if (amlResult.requiresReview) {
// وضع في قائمة المراجعة اليدوية
await db.transactions.update(transaction.id, {
status: 'pending_review',
riskScore: amlResult.riskScore,
flags: amlResult.flags
});
res.json({
success: false,
status: 'pending_review',
message: 'تم وضع المعاملة في قائمة مراجعة الامتثال'
});
} else {
// الرفض
await db.transactions.update(transaction.id, {
status: 'rejected',
rejectionReason: amlResult.flags
});
res.json({
success: false,
status: 'rejected',
message: 'تم رفض المعاملة لأسباب تتعلق بالامتثال'
});
}
});
```
**التحليل السلوكي:**
```javascript
async function analyzeUserBehavior(userId) {
const behavior = await liveAML.analyzeBehavior({
userId: userId,
timeframe: '30d', // آخر 30 يوماً
includeMetrics: [
'transaction_frequency',
'amount_patterns',
'time_patterns',
'address_diversity',
'counterparty_risk'
]
});
return {
riskScore: behavior.overallRiskScore,
insights: {
transactionFrequency: behavior.metrics.transaction_frequency,
averageAmount: behavior.metrics.average_amount,
peakTradingHours: behavior.metrics.peak_hours,
suspiciousPatterns: behavior.flags
},
recommendations: behavior.recommendations
};
}
```
**فحص العقوبات:**
```javascript
async function screenAddress(address, blockchain) {
const result = await liveAML.screenAddress({
address: address,
blockchain: blockchain,
includeIndirectExposure: true, // فحص 2-3 قفزات
lists: ['OFAC', 'UN', 'EU', 'MASAK'] // القوائم المراد فحصها
});
if (result.hit) {
// تسجيل إصابة العقوبات
await logSanctionsHit({
address: address,
blockchain: blockchain,
matchedLists: result.matches,
severity: result.severity
});
// حظر المعاملة
return {
allowed: false,
reason: 'sanctions_hit',
details: result.matches
};
}
return { allowed: true };
}
```
## تكامل قاعدة السفر
### التواصل بين مزودي VASP
**التحويل الصادر:**
```javascript
const { TravelRule } = require('@defy/compliance-sdk');
const travelRule = new TravelRule({
apiKey: process.env.DEFY_API_KEY,
apiSecret: process.env.DEFY_API_SECRET,
vaspInfo: {
name: 'اسم بورصتك',
did: 'did:web:your-exchange.com',
jurisdiction: 'TR',
license: 'MASAK-2024-001'
}
});
async function handleOutgoingTransfer(transfer) {
// التحقق مما إذا كان المبلغ يتجاوز عتبة قاعدة السفر
const requiresTravelRule = await travelRule.checkThreshold({
amount: transfer.amount,
currency: transfer.currency,
jurisdiction: transfer.jurisdiction
});
if (!requiresTravelRule) {
// المعالجة بشكل طبيعي
return await processTransfer(transfer);
}
// اكتشاف VASP المستفيد
const beneficiaryVASP = await travelRule.discoverVASP({
address: transfer.beneficiaryAddress,
blockchain: transfer.blockchain
});
if (!beneficiaryVASP) {
// محفظة غير مستضافة - جمع معلومات المستفيد من المستخدم
const beneficiaryInfo = await requestBeneficiaryInfo(transfer.userId);
// المعالجة مع العناية الواجبة المعززة
return await processWithEDD(transfer, beneficiaryInfo);
}
// إرسال بيانات قاعدة السفر
const trSession = await travelRule.sendData({
originator: {
name: transfer.originatorName,
address: transfer.originatorAddress,
accountNumber: transfer.userId,
vasp: {
name: 'بورصتك',
did: 'did:web:your-exchange.com'
}
},
beneficiary: {
name: beneficiaryVASP.name,
did: beneficiaryVASP.did,
accountNumber: transfer.beneficiaryAccountId
},
transaction: {
amount: transfer.amount,
currency: transfer.currency,
blockchain: transfer.blockchain
}
});
// انتظار القبول (مع مهلة)
const response = await trSession.waitForResponse({
timeout: 300000 // 5 دقائق
});
if (response.status === 'accepted') {
// ربط بيانات قاعدة السفر بالمعاملة
await db.transactions.update(transfer.id, {
travelRuleSessionId: trSession.id,
travelRuleStatus: 'completed'
});
// معالجة المعاملة
return await processTransfer(transfer);
} else {
// رفض من قبل VASP المستفيد
await db.transactions.update(transfer.id, {
status: 'rejected',
rejectionReason: response.rejectionReason
});
throw new Error(`رفض قاعدة السفر: ${response.rejectionReason}`);
}
}
```
**التحويل الوارد:**
```javascript
// معالج Webhook لبيانات قاعدة السفر الواردة
app.post('/webhooks/travel-rule', async (req, res) => {
const incomingData = req.body;
// التحقق من VASP المُرسل
const vaspValid = await travelRule.verifyVASP(incomingData.originator.vasp);
if (!vaspValid) {
await travelRule.rejectTransfer(incomingData.sessionId, {
reason: 'invalid_vasp',
message: 'تعذر التحقق من VASP المُرسل'
});
return res.sendStatus(200);
}
// فحص العقوبات
const sanctionsResult = await liveAML.screenEntity({
name: incomingData.originator.name,
address: incomingData.originator.address
});
if (sanctionsResult.hit) {
await travelRule.rejectTransfer(incomingData.sessionId, {
reason: 'sanctions_hit',
message: 'المُرسل موجود في قائمة العقوبات'
});
await fileSAR(incomingData, sanctionsResult);
return res.sendStatus(200);
}
// تقييم المخاطر
const riskScore = await calculateIncomingRisk(incomingData);
if (riskScore < 70) {
// القبول التلقائي
await travelRule.acceptTransfer(incomingData.sessionId);
} else {
// وضع في قائمة المراجعة اليدوية
await queueTransferReview(incomingData, riskScore);
}
res.sendStatus(200);
});
```
## معالجة الأخطاء
### منطق إعادة المحاولة
```javascript
async function callAPIWithRetry(apiCall, maxRetries = 3) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await apiCall();
} catch (error) {
lastError = error;
// عدم إعادة المحاولة لأخطاء العميل (4xx)
if (error.statusCode >= 400 && error.statusCode < 500) {
throw error;
}
// التراجع الأسي
if (attempt < maxRetries) {
const delay = Math.min(1000 * Math.pow(2, attempt), 10000);
await sleep(delay);
}
}
}
throw lastError;
}
// الاستخدام
const result = await callAPIWithRetry(() =>
vera.createSession(sessionData)
);
```
### تحديد المعدل
```javascript
const rateLimit = require('express-rate-limit');
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 دقيقة
max: 100, // تحديد كل IP بـ 100 طلب لكل نافذة
message: 'طلبات كثيرة جداً، يرجى المحاولة لاحقاً',
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', apiLimiter);
```
## الاختبار
### بيئة Sandbox
```javascript
// استخدام sandbox للتطوير
const vera = new VeraAI({
apiKey: process.env.DEFY_SANDBOX_API_KEY,
apiSecret: process.env.DEFY_SANDBOX_API_SECRET,
environment: 'sandbox'
});
// الاختبار ببيانات وهمية
const testSession = await vera.createSession({
userId: 'test_user_123',
verificationType: 'individual',
testMode: true,
testScenario: 'approved_low_risk' // أو 'rejected_sanctions', 'pending_review'
});
```
### اختبارات التكامل
```javascript
describe('تكامل Vera AI', () => {
it('يجب إنشاء جلسة التحقق من الهوية بنجاح', async () => {
const session = await vera.createSession({
userId: 'test_123',
verificationType: 'individual'
});
expect(session).toHaveProperty('id');
expect(session).toHaveProperty('redirectUrl');
expect(session.status).toBe('pending');
});
it('يجب معالجة webhook بشكل صحيح', async () => {
const webhookPayload = {
type: 'verification.completed',
data: {
userId: 'test_123',
riskScore: 25,
verificationLevel: 'standard'
}
};
const response = await request(app)
.post('/webhooks/vera')
.send(webhookPayload)
.set('X-Defy-Signature', generateTestSignature(webhookPayload));
expect(response.status).toBe(200);
});
});
```
## أفضل الممارسات
### تحسين الأداء
**1. تخزين استجابات API مؤقتاً:**
```javascript
const redis = require('redis');
const client = redis.createClient();
async function getCachedRiskScore(userId) {
const cached = await client.get(`risk:${userId}`);
if (cached) return JSON.parse(cached);
const riskScore = await liveAML.getRiskScore(userId);
await client.setex(`risk:${userId}`, 3600, JSON.stringify(riskScore));
return riskScore;
}
```
**2. المعالجة الدفعية:**
```javascript
// فحص عناوين متعددة في طلب واحد
const results = await liveAML.batchScreenAddresses({
addresses: [
{ address: '0x123...', blockchain: 'ethereum' },
{ address: '0x456...', blockchain: 'ethereum' },
{ address: 'bc1q789...', blockchain: 'bitcoin' }
]
});
```
**3. المعالجة غير المتزامنة:**
```javascript
// عدم الحظر على الفحوصات غير الحرجة
async function processDeposit(deposit) {
// حرج: فحص العقوبات (حظر)
const sanctionsResult = await liveAML.screenAddress(deposit.fromAddress);
if (sanctionsResult.hit) {
throw new Error('انتهاك العقوبات');
}
// إضافة الرصيد لحساب المستخدم
await creditUserBalance(deposit);
// غير حرج: التحليل السلوكي (غير متزامن)
analyzeBehavior(deposit.userId).catch(err => {
console.error('فشل التحليل السلوكي:', err);
});
return { success: true };
}
```
## المراقبة والتسجيل
### التسجيل
```javascript
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'compliance.log' })
]
});
// تسجيل جميع استدعاءات API
async function loggedAPICall(apiCall, context) {
const startTime = Date.now();
try {
const result = await apiCall();
logger.info('نجح استدعاء API', {
...context,
duration: Date.now() - startTime,
result: result
});
return result;
} catch (error) {
logger.error('فشل استدعاء API', {
...context,
duration: Date.now() - startTime,
error: error.message,
stack: error.stack
});
throw error;
}
}
```
### المقاييس
```javascript
const prometheus = require('prom-client');
// تعريف المقاييس
const kycSessionCounter = new prometheus.Counter({
name: 'verification_sessions_total',
help: 'إجمالي عدد جلسات التحقق المُنشأة',
labelNames: ['status']
});
const amlScreeningDuration = new prometheus.Histogram({
name: 'aml_screening_duration_seconds',
help: 'مدة فحص AML',
buckets: [0.1, 0.5, 1, 2, 5]
});
// تسجيل المقاييس
kycSessionCounter.inc({ status: 'approved' });
const timer = amlScreeningDuration.startTimer();
await screenTransaction(tx);
timer();
```
## الخلاصة
يتطلب التكامل الناجح لواجهات API الخاصة بالامتثال من Defy:
1. المصادقة والأمان الصحيحين
2. معالجة أخطاء قوية
3. اختبار شامل
4. تحسين الأداء
5. المراقبة والتسجيل
**دعم Defy:**
- الوثائق التقنية: https://docs.getdefy.co
- مرجع API: https://api.getdefy.co/docs
- أمثلة SDK: https://github.com/defy/examples
- الدعم: info@getdefy.co
- مجتمع Slack: https://defy-dev.slack.com
ابدأ ببناء منصات عملات مشفرة متوافقة مع Defy اليوم!