الانتقال إلى المحتوى الرئيسي
في هذا الدليل، ستقوم ببناء PixelGen AI - خدمة نموذجية لتوليد الصور باستخدام AI توضح الفواتير القائمة على الاستخدام. سنقوم بإنشاء كل شيء من الصفر: عداد الفواتير، تكوين المنتج، وكود التطبيق النموذجي الذي يولد الصور ويتتبع الاستخدام في الوقت الفعلي.
يوفر هذا الدرس مثالًا على رمز تنفيذ لتطبيق قائم على الطرفية. يمكنك تعديل هذا الرمز لإطار العمل الذي تستخدمه (React أو Vue أو Angular أو غيرها) وتخصيص طريقة إدخال المستخدم حسب احتياجات تطبيقك.
بنهاية هذا الدليل، سيكون لديك خدمة نموذجية تعمل تتضمن:
  • توليد الصور باستخدام واجهة برمجة التطبيقات DALL-E من OpenAI
  • تتبع كل توليد صورة للفواتير
  • فرض رسوم على العملاء تلقائيًا بناءً على الاستخدام
  • التعامل مع مستويات جودة مختلفة (قياسية مقابل HD)

ما الذي نبنيه

لنبدأ بفهم خدمة PixelGen AI الخاصة بنا:
  • الخدمة: توليد الصور باستخدام واجهة برمجة التطبيقات DALL-E من OpenAI
  • نموذج التسعير: دفع مقابل كل صورة (0.05 دولار لكل صورة)
  • الطبقة المجانية: 10 صور مجانية لكل عميل شهريًا
  • خيارات الجودة: صور قياسية وHD (نفس السعر للتبسيط)
قبل أن نبدأ، تأكد من أن لديك:
  • حساب Dodo Payments
  • الوصول إلى واجهة برمجة تطبيقات OpenAI
  • دراية أساسية بـ TypeScript/Node.js

الخطوة 1: إنشاء عداد الاستخدام الخاص بك

سنبدأ بإنشاء عداد في لوحة معلومات Dodo Payments الخاصة بك سيتتبع كل صورة تولدها خدمتنا. اعتبر هذا بمثابة “عداد” يتتبع الأحداث القابلة للفوترة.
ما الذي نبنيه: مقياس باسم “Image Generation Meter” يحصي في كل مرة يتم فيها إنشاء صورة باستخدام خدمتنا.
1

Open the Meters section

  1. سجّل الدخول إلى لوحة تحكم Dodo Payments الخاصة بك
  2. انقر على Meters في الشريط الجانبي الأيسر
  3. انقر على زر Create Meter
يجب أن ترى نموذجًا سنقوم من خلاله بتكوين تتبع إنشاء الصور.
2

Fill in the basic meter information

سنُدخل الآن التفاصيل المحددة لخدمة PixelGen AI الخاصة بنا:Meter Name: انسخ والصق هذا تمامًا → Image Generation MeterDescription: انسخ هذا → Tracks each AI image generation request made by customers using our DALL-E powered serviceEvent Name: هذا أمر حاسم - انسخه تمامًا → image.generated
يجب أن يطابق اسم الحدث image.generated تمامًا ما سنرسله لاحقًا من رمز التطبيق. أسماء الأحداث حساسة لحالة الأحرف!
3

Configure how we count images

قم بإعداد التجميع (كيفية احتساب العداد لأحداثنا):نوع التجميع: اختر العدد من القائمة المنسدلةMeasurement Unit: اكتب → images
نستخدم “Count” لأننا نريد فرض رسوم على كل صورة يتم إنشاؤها، وليس حسب الحجم أو وقت الإنشاء. كل صورة ناجحة = وحدة قابلة للفوترة واحدة.
4

Add quality filtering

نريد التأكد من أننا نحسب فقط الصور الشرعية (وليس عمليات الاختبار أو الفشل):
  1. Enable Event Filtering: فعّل هذا الخيار ON
  2. Filter Logic: اختر OR (هذا يعني “احسب إذا كان أي من هذه الشروط صحيحًا”)
  3. Add the first condition:
    • Property Key: quality
    • Comparator: equals
    • Value: standard
  4. Click “Add Condition” للحالة الثانية:
    • Property Key: quality
    • Comparator: equals
    • Value: hd
يعني هذا الإعداد أننا سنحسب فقط الأحداث التي تكون الجودة فيها إما “standard” أو “hd” - مما يفلتر أي أحداث اختبار أو طلبات غير صحيحة.
5

Create your meter

  1. تأكد من أن جميع إعداداتك تطابق القيم أعلاه
  2. انقر على Create Meter
تم إنشاء العداد! أصبح “Image Generation Meter” جاهزًا لبدء تسجيل عمليات إنشاء الصور. سنربطه الآن بمنتج فوترة.

الخطوة 2: إنشاء منتج الفواتير الخاص بك

الآن نحتاج إلى إنشاء منتج يحدد تسعيرنا (0.05 دولار لكل صورة مع 10 صور مجانية). هذا يربط عدادنا بالفواتير الفعلية.
ما الذي نبنيه: منتج يسمى “PixelGen AI - Image Generation” يفرض 0.05$ عن كل صورة بعد أول 10 صور مجانية كل شهر.
1

Navigate to Products

  1. في لوحة تحكم Dodo Payments، انقر على Products في الشريط الجانبي الأيسر
  2. انقر على Create Product
  3. اختر Usage-Based كنوع المنتج
هذا يخبر Dodo Payments أن الفوترة ستكون بناءً على استخدام العداد، وليس اشتراكًا ثابتًا.
2

Enter product details

املأ هذه القيم الدقيقة لخدمة PixelGen AI الخاصة بنا:Product Name: انسخ هذا → PixelGen AI - Image GenerationDescription: انسخ هذا → AI-powered image generation service with pay-per-use billingصورة المنتج: قم بتحميل صورة واضحة وذات صلة.
ستظهر هذه المعلومات في فواتير العملاء، لذا اجعلها واضحة ومهنية.
3

Connect your meter

قبل ربط العداد الخاص بك، تأكد من أنك قد اخترت الفواتير القائمة على الاستخدام كنوع السعر لمنتجك.بالإضافة إلى ذلك، اضبط السعر الثابت على 0 لضمان أن العملاء يُفرض عليهم الرسوم بناءً على استخدامهم فقط، دون أي رسوم أساسية.الآن، اربط العداد الذي أنشأته للتو:
  1. قم بالتمرير لأسفل إلى قسم العداد المرتبط
  2. انقر على إضافة عدادات
  3. من القائمة المنسدلة، اختر “عداد توليد الصور” (الذي أنشأته سابقًا)
  4. تأكد من أنه يظهر في تكوين منتجك
تم الآن ربط العداد بنجاح بهذا المنتج.
4

Set your pricing

هنا نُحدد نموذج عملنا:
Price Per Unit: أدخل → 0.05 (هذا 0.05$ لكل صورة)Free Threshold: أدخل → 10 (يحصل العملاء على 10 صور مجانية كل شهر)
كيفية عمل الفوترة: إذا أنشأ العميل 25 صورة في الشهر، فسوف يُفرض عليه مقابل 15 صورة (25 - 10 مجانية) = 15 × 0.05=0.75 = 0.75
5

Save your product

  1. راجع جميع الإعدادات:
    • الاسم: PixelGen AI - Image Generation
    • العداد: Image Generation Meter
    • السعر: 0.05$ لكل صورة
    • المستوى المجاني: 10 صور
  2. انقر على Save Changes
تم إنشاء المنتج! تم الآن تكوين الفوترة. سيتم فرض رسوم تلقائيًا على العملاء استنادًا إلى استخدامهم في إنشاء الصور.

الخطوة 3: إجراء عملية شراء تجريبية

قبل أن نبدأ في استيعاب أحداث الاستخدام، نحتاج إلى إجراء عملية شراء تجريبية.
1

Get your payment link

  1. في لوحة تحكم Dodo Payments، اذهب إلى Products
  2. اعثر على المنتج “PixelGen AI - Image Generation”
  3. انقر على زر Share بجانب المنتج
  4. انسخ رابط الدفع الذي يظهر
سيبدو رابط الدفع مشابهًا لـ: https://test.checkout.dodopayments.com/buy/pdt_IgPWlRsfpbPd5jQKezzW1?quantity=1
2

Complete a test purchase

  1. افتح رابط الدفع في علامة تبويب جديدة بالمتصفح
  2. أدخل بيانات الدفع التجريبية وأكمل عملية الشراء.
بعد إتمام الدفع بنجاح، ستحصل على معرف عميل سنستخدمه في رمز التطبيق الخاص بنا.
3

Find your customer ID

  1. عد إلى لوحة تحكم Dodo Payments
  2. انتقل إلى Customers في الشريط الجانبي الأيسر
  3. اعثر على العميل الذي أنشأته للتو (بالبريد الإلكتروني التجريبي)
  4. انسخ معرف العميل - سيبدو مثل cus_abc123def456
احفظ هذا المعرف - سنقوم بتضمينه بشكل ثابت في رمز التطبيق التجريبي لضمان تتبع الأحداث بشكل صحيح.

الخطوة 4: بناء التطبيق النموذجي

الآن لدينا إعداد الفواتير مكتمل وعميل تجريبي تم إنشاؤه. دعنا نبني تطبيق PixelGen AI النموذجي الذي يولد الصور ويتتبع الاستخدام تلقائيًا للفواتير.
1

Set up your project

أنشئ مجلدًا جديدًا وابدأ المشروع:
mkdir pixelgen-ai
cd pixelgen-ai
npm init -y
2

Install dependencies

ثبت الحزم التي نحتاجها:
npm install openai dotenv
npm install -D typescript @types/node ts-node
3

Create the main application

أنشئ ملفًا يسمى index.ts ونسخ كود التطبيق الكامل هذا:
إليك تطبيق PixelGen AI الكامل مع الفواتير المدمجة:
import 'dotenv/config';
import OpenAI from 'openai';
import * as readline from 'readline';
import { randomUUID } from 'crypto';

// Initialize OpenAI client
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

// Dodo Payments configuration
const DODO_PAYMENTS_CONFIG = {
  apiKey: process.env.DODO_PAYMENTS_API_KEY,
  baseUrl: 'https://test.dodopayments.com',
  customerId: 'cus_FX5FAB43aShGyiHJGIqjB', // Replace with your actual customer ID from Step 3
};

// DALL-E 3 pricing (as of 2024-2025)
const PRICING = {
  'standard': 0.040, // $0.040 per image (1024×1024)
  'hd': 0.080,       // $0.080 per image (1024×1024, HD quality)
};

interface ImageGenerationOptions {
  prompt: string;
  model?: 'dall-e-3' | 'dall-e-2';
  quality?: 'standard' | 'hd';
  size?: '1024x1024' | '1792x1024' | '1024x1792';
  style?: 'vivid' | 'natural';
}

interface UsageEvent {
  event_id: string;
  customer_id: string;
  event_name: string;
  timestamp: string;
  metadata: {
    quality: string;
  };
}

/**
 * Send usage event to Dodo Payments for billing tracking
 */
async function sendUsageEvent(event: UsageEvent): Promise<void> {
  try {
    console.log('Sending usage event to Dodo Payments...');
    console.log(`URL: ${DODO_PAYMENTS_CONFIG.baseUrl}/events/ingest`);
    console.log(`API Key present: ${!!DODO_PAYMENTS_CONFIG.apiKey}`);
    console.log(`API Key length: ${DODO_PAYMENTS_CONFIG.apiKey?.length || 0}`);
    console.log(`Customer ID: ${DODO_PAYMENTS_CONFIG.customerId}`);
    
    const requestBody = {
      events: [event]
    };
    console.log('Request body:', JSON.stringify(requestBody, null, 2));
    
    const headers = {
      'Authorization': `Bearer ${DODO_PAYMENTS_CONFIG.apiKey}`,
      'Content-Type': 'application/json',
    }
    console.log('Headers:', headers);
    const response = await fetch(`${DODO_PAYMENTS_CONFIG.baseUrl}/events/ingest`, {
      method: 'POST',
      headers: headers,
      body: JSON.stringify(requestBody),
    });

    console.log(`Response status: ${response.status}`);
    console.log(`Response headers:`, Object.fromEntries(response.headers.entries()));

    if (!response.ok) {
      const errorData = await response.text();
      console.log(`Error response body: ${errorData}`);
      throw new Error(`HTTP ${response.status}: ${errorData}`);
    }

    const result = await response.json();
    console.log('Usage event sent successfully');
    console.log(`   • Event ID: ${event.event_id}`);
    console.log(`   • Customer: ${event.customer_id}`);
    console.log(`   • Quality: ${event.metadata.quality}`);
    
  } catch (error) {
    console.error('Failed to send usage event:', error);
    // In production, you might want to queue failed events for retry
    throw error;
  }
}

async function generateImage(options: ImageGenerationOptions) {
  const startTime = Date.now();
  const eventId = randomUUID();
  
  try {
    console.log('Generating image...');
    console.log(`Prompt: "${options.prompt}"`);
    console.log(`Quality: ${options.quality || 'standard'}`);
    console.log(`Size: ${options.size || '1024x1024'}`);
    
    const response = await openai.images.generate({
      model: options.model || 'dall-e-3',
      prompt: options.prompt,
      n: 1,
      size: options.size || '1024x1024',
      quality: options.quality || 'standard',
      style: options.style || 'vivid',
    });

    const endTime = Date.now();
    const duration = (endTime - startTime) / 1000;
    const cost = PRICING[options.quality || 'standard'];
    
    // Create usage event for Dodo Payments
    const usageEvent: UsageEvent = {
      event_id: eventId,
      customer_id: DODO_PAYMENTS_CONFIG.customerId!,
      event_name: 'image.generated',
      timestamp: new Date().toISOString(),
      metadata: {
        quality: options.quality || 'standard',
      }
    };

    // Send usage event to Dodo Payments for billing
    await sendUsageEvent(usageEvent);
    
    console.log('\nImage generated successfully!');
    console.log(`Generation Stats:`);
    console.log(`   • Duration: ${duration.toFixed(2)} seconds`);
    console.log(`   • Quality: ${options.quality || 'standard'}`);
    console.log(`   • Cost: $${cost.toFixed(3)}`);
    console.log(`   • Image URL: ${response.data?.[0]?.url}`);
    
    if (response.data?.[0]?.revised_prompt) {
      console.log(`   • Revised prompt: "${response.data[0].revised_prompt}"`);
    }

    return {
      imageUrl: response.data?.[0].url,
      revisedPrompt: response.data?.[0].revised_prompt,
      cost: cost,
      duration: duration,
      eventId: eventId,
    };

  } catch (error) {
    console.error('Error generating image:', error);
    
    // Send failure event for monitoring (optional)
    try {
      const failureEvent: UsageEvent = {
        event_id: eventId,
        customer_id: DODO_PAYMENTS_CONFIG.customerId!,
        event_name: 'image.generation.failed',
        timestamp: new Date().toISOString(),
        metadata: {
          quality: options.quality || 'standard',
        }
      };
      
      // Note: You might want to create a separate meter for failed attempts
      // await sendUsageEvent(failureEvent);
    } catch (eventError) {
      console.error('Failed to send failure event:', eventError);
    }
    
    throw error;
  }
}

async function getUserInput(): Promise<string> {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });

  return new Promise((resolve) => {
    rl.question('Enter your image prompt: ', (answer) => {
      rl.close();
      resolve(answer);
    });
  });
}

async function main() {
  console.log('PixelGen AI - Image Generator with Usage Billing\n');
  
  // Validate environment variables
  const requiredEnvVars = [
    'OPENAI_API_KEY',
    'DODO_PAYMENTS_API_KEY'
  ];
  
  for (const envVar of requiredEnvVars) {
    if (!process.env[envVar]) {
      console.error(`Error: ${envVar} environment variable is not set.`);
      console.log('Please set all required environment variables:');
      console.log('export OPENAI_API_KEY="your-openai-key"');
      console.log('export DODO_PAYMENTS_API_KEY="your-dodo-api-key"');
      console.log('Note: Customer ID is hardcoded in the application');
      process.exit(1);
    }
  }

  try {
    const prompt = await getUserInput();
    
    if (!prompt.trim()) {
      console.log('No prompt provided. Exiting...');
      return;
    }

    const result = await generateImage({
      prompt: prompt.trim(),
      quality: 'standard', // Change to 'hd' for higher quality (costs more)
      size: '1024x1024',
      style: 'vivid'
    });

    console.log('\nProcess completed successfully!');
    console.log(`Billing Information:`);
    console.log(`   • Total cost: $${result.cost.toFixed(3)}`);
    console.log(`   • Event ID: ${result.eventId}`);
    console.log(`   • Billing will be processed automatically via Dodo Payments`);
    
  } catch (error) {
    console.error('Application error:', error);
    process.exit(1);
  }
}

// Run the application
if (require.main === module) {
  main().catch(console.error);
}

الخطوة 5: اختبار تطبيقك النموذجي

حان الوقت لاختبار خدمة PixelGen AI النموذجية الخاصة بنا ورؤية الفواتير في العمل! دعنا نتأكد من أن كل شيء يعمل من البداية إلى النهاية.
ما الذي نختبره: سننشئ بعض الصور، نتأكد من وصول الأحداث إلى Dodo Payments، ونضبط أن حساب الفوترة صحيح.
1

Set up your environment

أولًا، تأكد من إعداد كل شيء:
  1. أنشئ ملف .env في مجلد pixelgen-ai
  2. أضف مفاتيح واجهة برمجة التطبيقات الفعلية الخاصة بك:
OPENAI_API_KEY=sk-your-actual-openai-key
DODO_PAYMENTS_API_KEY=your-actual-dodo-api-key
# Customer ID is hardcoded in the application
  1. قم بتثبيت التبعيات وتشغيل التطبيق:
npm install
npm start
تأكد من استخدام مفاتيح واجهة برمجة التطبيقات الحقيقية وتحديث معرف العميل المضمن في الرمز بالمعرف الفعلي من الخطوة 3!
2

Generate your first test image

عند تشغيل التطبيق، سترى:
PixelGen AI - Image Generator with Usage Billing

Enter your image prompt:
جرب هذا الطلب: “روبوت لطيف يرسم منظرًا طبيعيًا”يجب أن ترى مخرجات مثل هذه:
Generating image...
Prompt: "A cute robot painting a landscape"
Quality: standard
Size: 1024x1024

Sending usage event to Dodo Payments...
Usage event sent successfully
   • Event ID: 550e8400-e29b-41d4-a716-446655440000
   • Customer: cus_atXa1lklCRRzMicTqfiw2
   • Quality: standard

Image generated successfully!
Generation Stats:
   • Duration: 8.45 seconds
   • Quality: standard
   • Cost: $0.040
   • Image URL: https://oaidalleapi...
إذا رأيت “Usage event sent successfully”، فإن تكامل الفوترة يعمل!
3

Generate a few more images

لننشئ 2-3 صور إضافية لاختبار عدة أحداث. جرّب هذه المطالبات:
  1. “غروب الشمس فوق الجبال مع سحب بنفسجية”
  2. “آلة قهوة ستيمبانك في مطبخ فيكتوري”
  3. “تنين ودود يقرأ كتابًا في مكتبة”
في كل مرة، راقب رسالة “Usage event sent successfully”.
4

Check your Dodo Payments dashboard

لنؤكد الآن أن الأحداث تتلقاها الخدمة:
  1. افتح لوحة معلومات Dodo Payments الخاصة بك
  2. انتقل إلى الفواتير القائمة على الاستخدام → *عداداتعداد توليد الصور
  3. انقر على علامة التبويب الأحداث
  4. يجب أن ترى أحداث توليد الصور الخاصة بك مدرجة
ما الذي يجب التحقق منه:
  • أسماء الأحداث: image.generated
  • معرف العميل: معرف العميل التجريبي الخاص بك
يجب أن ترى حدثًا لكل صورة أنشأتها!
5

Verify billing calculations

لنتحقق مما إذا كان عد الاستخدام يعمل:
  1. في عدادك، انتقل إلى علامة التبويب العملاء
  2. ابحث عن عميلك التجريبي
  3. تحقق من عمود “الوحدات المستهلكة”
6

Test the billing threshold

لنتجاوز الآن الحد المجاني لنرى الفوترة تعمل:
  1. قم بتوليد 8 صور أخرى (للوصول إلى 12 إجماليًا)
  2. تحقق من لوحة عدادك مرة أخرى
  3. يجب أن ترى الآن:
    • الوحدات المستهلكة: 12
    • الوحدات القابلة للفوترة: 2 (12 - 10 مجانية)
    • مبلغ الفواتير: 0.10 دولار
نجاح! تعمل الفوترة على أساس الاستخدام بشكل مثالي. سيتم فرض رسوم تلقائيًا على العملاء استنادًا إلى الاستخدام الفعلي لإنشاء الصور.

استكشاف الأخطاء وإصلاحها

المشاكل الشائعة وحلولها:
الأسباب المحتملة:
  • لا يتطابق اسم الحدث مع تكوين العداد تمامًا
  • معرف العميل غير موجود في حسابك
  • مفتاح واجهة البرمجة غير صالح أو منتهي
  • مشاكل في الاتصال بالشبكة
الحلول:
  1. تحقق من تطابق اسم الحدث مع تكوين العداد تمامًا (حساس لحالة الأحرف)
  2. تأكد من وجود معرف العميل في Dodo Payments
  3. اختبر مفتاح واجهة البرمجة باستدعاء بسيط
  4. تحقق من الاتصال بالشبكة وإعدادات الجدار الناري

تهانينا! لقد أنشأت PixelGen AI

لقد أنشأت بنجاح مقتطفًا لتوليد الصور باستخدام AI مع فواتير قائمة على الاستخدام! إليك ما أنجزته:

Usage Meter

تم إنشاء “Image Generation Meter” الذي يتتبع كل حدث إنشاء صورة

Billing Product

تم تكوين الأسعار عند 0.05$ لكل صورة مع 10 صور مجانية شهريًا

AI Application

تم بناء تطبيق TypeScript يعمل ينشئ الصور باستخدام DALL-E من OpenAI

Automated Billing

تم دمج تتبع الأحداث في الوقت الفعلي الذي يفوّتر العملاء تلقائيًا