Documentation Index
Fetch the complete documentation index at: https://docs.oneclickdz.com/llms.txt
Use this file to discover all available pages before exploring further.
نظرة عامة
بعد تنفيذ طلبات بطاقات الهدايا، احصل على رموز البطاقات من API وسلّمها للعملاء بأمان. رموز البطاقات ذات قيمة مالية ويجب التعامل معها بعناية فائقة.أمر بالغ الأهمية: رموز البطاقات بيانات حساسة قابلة للاستبدال بالمال. شفّرها دائماً عند التخزين والإرسال.
مرجع API
GET /v3/gift-cards/check-order/{orderId}
استرجاع تفاصيل البطاقة المنفَّذة
هيكل بيانات البطاقة
تحتوي الطلبات المنفَّذة على بطاقات بحقلين:{
"cards": [
{
"value": "XXXX-XXXX-XXXX-XXXX", // Primary credential (PIN/code)
"serial": "123456789" // Secondary credential (serial number)
}
]
}
كلا الحقلين value وserial حساسان ويجب حمايتهما.مساعدات التشفير
const crypto = require('crypto');
// Encryption configuration
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // Must be 32 bytes
const ALGORITHM = 'aes-256-gcm';
function encryptCardData(text) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(
ALGORITHM,
Buffer.from(ENCRYPTION_KEY, 'hex'),
iv
);
let encrypted = cipher.update(text, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
iv: iv.toString('hex'),
encryptedData: encrypted,
authTag: authTag.toString('hex')
};
}
function decryptCardData(iv, encryptedData, authTag) {
const decipher = crypto.createDecipheriv(
ALGORITHM,
Buffer.from(ENCRYPTION_KEY, 'hex'),
Buffer.from(iv, 'hex')
);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
// Usage
const encrypted = encryptCardData('XXXX-XXXX-XXXX-XXXX');
const decrypted = decryptCardData(encrypted.iv, encrypted.encryptedData, encrypted.authTag);
التخزين الآمن
شفّر رموز البطاقات دائماً قبل تخزينها في قاعدة البيانات:const crypto = require('crypto');
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY; // Must be 32 bytes
const ALGORITHM = 'aes-256-gcm';
function encryptCardData(cardData) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(
ALGORITHM,
Buffer.from(ENCRYPTION_KEY, 'hex'),
iv
);
const plaintext = JSON.stringify(cardData);
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
iv: iv.toString('hex'),
encryptedData: encrypted,
authTag: authTag.toString('hex')
};
}
function decryptCardData(iv, encryptedData, authTag) {
const decipher = crypto.createDecipheriv(
ALGORITHM,
Buffer.from(ENCRYPTION_KEY, 'hex'),
Buffer.from(iv, 'hex')
);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
let decrypted = decipher.update(encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return JSON.parse(decrypted);
}
// Store encrypted cards
async function storeOrderCards(orderId, cards) {
const encryptedCards = cards.map(card => ({
...encryptCardData(card),
cardType: card.type
}));
await db.orders.updateOne(
{ orderId },
{
$set: {
encryptedCards,
status: 'FULFILLED',
fulfilledAt: new Date()
}
}
);
}
طرق التسليم
1. التسليم عبر البريد الإلكتروني
async function deliverCardsViaEmail(userId, orderId, cards) {
const user = await db.users.findOne({ _id: userId });
// Build email content with cards
const cardList = cards.map((card, index) => `
Card ${index + 1}:
Code: ${card.value}
Serial: ${card.serial}
`).join('\n\n');
await sendEmail({
to: user.email,
subject: 'Your Gift Card Order',
html: `
<h2>Your gift cards are ready!</h2>
<p>Order ID: ${orderId}</p>
<pre>${cardList}</pre>
<p><strong>Important:</strong> Keep these codes secure and don't share them.</p>
`
});
// Mark as delivered
await db.orders.updateOne(
{ orderId },
{ $set: { 'encryptedCards.$[].deliveredAt': new Date() } }
);
console.log(`Delivered ${cards.length} cards to ${user.email}`);
}
2. العرض داخل التطبيق
// API endpoint to display cards in-app
app.get('/api/orders/:orderId/cards', authenticateUser, async (req, res) => {
const { orderId } = req.params;
const userId = req.user.id;
// Verify ownership
const order = await db.orders.findOne({ orderId, userId });
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
if (order.status !== 'FULFILLED') {
return res.status(400).json({ error: 'Order not fulfilled yet' });
}
// Decrypt and return cards
const cards = await getOrderCards(orderId);
res.json({
orderId,
cards: cards.map((card, index) => ({
cardNumber: index + 1,
code: card.value,
serial: card.serial
}))
});
});
3. التحميل الآمن
async function generateSecureCardFile(orderId, cards) {
const content = cards.map((card, index) => `
Gift Card ${index + 1}
Code: ${card.value}
Serial: ${card.serial}
--------------------
`).join('\n');
// Encrypt the file content
const encrypted = encryptCardData(content);
// Store temporarily with unique token
const token = crypto.randomBytes(32).toString('hex');
await db.downloadTokens.insertOne({
token,
orderId,
encrypted,
expiresAt: new Date(Date.now() + 5 * 60 * 1000) // 5 minutes
});
return token;
}
// Download endpoint
app.get('/api/download/:token', async (req, res) => {
const { token } = req.params;
const download = await db.downloadTokens.findOne({ token });
if (!download || download.expiresAt < new Date()) {
return res.status(404).json({ error: 'Download link expired' });
}
const content = decryptCardData(
download.encrypted.iv,
download.encrypted.encryptedData,
download.encrypted.authTag
);
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Disposition', `attachment; filename="cards-${download.orderId}.txt"`);
res.send(content);
// Delete token after use
await db.downloadTokens.deleteOne({ token });
});
تسجيل التدقيق
سجّل أحداث التسليم دون كشف بيانات البطاقة:async function logCardDelivery(orderId, userId, method, cardCount) {
await db.auditLogs.insertOne({
event: 'CARDS_DELIVERED',
orderId,
userId,
method, // 'email', 'in-app', 'download'
cardCount,
timestamp: new Date(),
ipAddress: req.ip,
userAgent: req.headers['user-agent']
});
console.log(`[AUDIT] Delivered ${cardCount} cards for order ${orderId} via ${method}`);
}
// ❌ Never log actual card codes
// console.log('Card code:', card.value); // Don't do this
سير التسليم الكامل
async function completeOrderDelivery(orderId, userId) {
// 1. Check order is fulfilled
const orderStatus = await checkOrderStatus(orderId);
if (orderStatus.status !== 'FULFILLED' && orderStatus.status !== 'PARTIALLY_FILLED') {
throw new Error('Order not ready for delivery');
}
// 2. Store encrypted cards
await storeOrderCards(orderId, userId, orderStatus.cards);
// 3. Deliver to customer
await deliverCardsViaEmail(userId, orderId, orderStatus.cards);
// 4. Log delivery
await logCardDelivery(orderId, userId, 'email', orderStatus.cards.length);
console.log(`✅ Order ${orderId} delivery complete`);
}
قائمة التحقق الأمنية
توليد مفتاح تشفير
أنشئ مفتاح تشفير آمن بطول 32 بايت وخزّنه في متغيرات البيئة
التشفير قبل التخزين
شفّر دائماً بيانات البطاقة قبل الإدراج في قاعدة البيانات
التحقق من ملكية المستخدم
تأكد أن المستخدم يملك الطلب قبل عرض البطاقة
استخدام HTTPS
تأكد من أن جميع طرق التسليم تستخدم نقلاً مشفراً
تسجيل التدقيق
سجّل أحداث التسليم دون تضمين الرموز الفعلية
الحذف الآمن
نفّذ سياسة حذف البطاقات إذا اقتضت اللوائح ذلك
أفضل الممارسات
التشفير في حالة السكون
شفّر دائماً رموز البطاقة قبل تخزينها في قاعدة البيانات
HTTPS فقط
لا ترسل بطاقات عبر اتصالات غير مشفرة
التحقق من الملكية
تحقق أن المستخدم يملك الطلب قبل عرض البطاقة
لا سجلات نصية
لا تسجّل رموز البطاقة كنص عادي في أي مكان
الحذف الآمن
احذف البطاقات بشكل آمن بعد استرجاع العميل لها إذا اقتضت السياسة ذلك
سجل التدقيق
سجّل أحداث التسليم دون تضمين البيانات الحساسة
الخطوات التالية
نظرة عامة
العودة إلى نظرة عامة على التكامل
تتبع الحالة
استعلام حالة الطلب
أفضل ممارسات الأمان
إرشادات الأمان العامة
تقديم الطلبات
تقديم طلبات بطاقات الهدايا
تحميل الكتالوج
جلب المنتجات المتاحة
مرجع API
التوثيق الكامل للـ endpoint