> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# محول Fastify

> تعلم كيفية دمج مدفوعات دودي مع مشروع Fastify App Router الخاص بك باستخدام محول NextJS الخاص بنا. يغطي الدفع، بوابة العملاء، الويب هوكس، وإعداد البيئة الآمنة.

<CardGroup cols={2}>
  <Card title="Checkout Handler" icon="cart-shopping" href="#checkout-route-handler">
    قم بدمج صفحة دفع Dodo Payments في تطبيق Fastify الخاص بك.
  </Card>

  <Card title="Customer Portal" icon="user" href="#customer-portal-route-handler">
    اسمح للعملاء بإدارة الاشتراكات والتفاصيل.
  </Card>

  <Card title="Webhooks" icon="bell" href="#webhook-route-handler">
    استقبل وعرّف أحداث webhook الخاصة بـ Dodo Payments.
  </Card>
</CardGroup>

## التثبيت

<Steps>
  <Step title="Install the package">
    قم بتشغيل الأمر التالي في جذر المشروع الخاص بك:

    ```bash theme={null}
    npm install @dodopayments/fastify
    ```
  </Step>

  <Step title="Set up environment variables">
    أنشئ ملف <code>.env</code> في جذر المشروع الخاص بك:

    ```env expandable theme={null}
    DODO_PAYMENTS_API_KEY=your-api-key
    DODO_PAYMENTS_RETURN_URL=https://yourapp.com/success
    DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
    DODO_PAYMENTS_ENVIRONMENT="test_mode" or "live_mode""
    ```

    <Warning>
      لا تقم بتضمين ملف <code>.env</code> الخاص بك أو الأسرار في نظام التحكم بالإصدارات.
    </Warning>
  </Step>
</Steps>

## أمثلة معالج المسار

<Info>
  تفترض جميع الأمثلة أنك تستخدم Fastify App Router.
</Info>

<Tabs>
  <Tab title="Checkout Handler">
    <Info>
      استخدم هذه المعالجة لدمج صفحة دفع Dodo Payments في تطبيق Fastify الخاص بك. تدعم تدفقات الدفع الثابتة (GET) والديناميكية (POST) وجلسات (POST).
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
        // route.ts
        import { Checkout } from '@dodopayments/fastify';
        import Fastify from 'fastify'

        const fastify = Fastify({})
        const checkoutGet = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'static'
        });

        const checkoutPost = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'dynamic'
        });

        const checkoutSession = Checkout({
            bearerToken: process.env.DODO_PAYMENTS_API_KEY,
            environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
            returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
            type: 'session'
        });

        fastify.get('/api/checkout', checkoutGet.getHandler);
        fastify.post('/api/checkout', checkoutPost.postHandler);
        fastify.post('/api/checkout-session', checkoutSession.postHandler);
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Static Checkout Curl example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/api/checkout?productId=pdt_fqJhl7pxKWiLhwQR042rh' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Dynamic Checkout Curl example expandable theme={null}
      curl --request POST \
      --url https://example.com/api/checkout \
      --header 'Content-Type: application/json' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test \
      --data '{
      "billing": {
        "city": "Texas",
        "country": "US",
        "state": "Texas",
        "street": "56, hhh",
        "zipcode": "560000"
      },
      "customer": {
        "email": "test@example.com",
        	"name": "test"
      },
      "metadata": {},
      "payment_link": true,
        "product_id": "pdt_QMDuvLkbVzCRWRQjLNcs",
        "quantity": 1,
        "billing_currency": "USD",
        "discount_codes": ["IKHZ23M9GQ"],
        "return_url": "https://example.com",
        "trial_period_days": 10
      }'
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Checkout Session Curl example expandable theme={null}
      curl --request POST \
      --url https://example.com/api/checkout-session \
      --header 'Content-Type: application/json' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test \
      --data '{
      "product_cart": [
        {
          "product_id": "pdt_QMDuvLkbVzCRWRQjLNcs",
          "quantity": 1
        }
      ],
      "customer": {
        "email": "test@example.com",
        "name": "test"
      },
      "return_url": "https://example.com/success"
      }'
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Customer Portal Handler">
    <Info>
      استخدم هذه المعالجة للسماح للعملاء بإدارة اشتراكاتهم وتفاصيلهم عبر بوابة عملاء Dodo Payments.
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
      // route.ts
      import { CustomerPortal } from "@dodopayments/fastify";
      import Fastify from 'fastify'

      const fastify = Fastify({})
      const customerPortalHandler = CustomerPortal({
          bearerToken: process.env.DODO_PAYMENTS_API_KEY,
          environment: process.env.DODO_PAYMENTS_ENVIRONMENT
      });
      fastify.get('/api/customer-portal', customerPortalHandler);
      ```
    </CodeGroup>

    <CodeGroup>
      ```curl Customer Portal Curl example expandable theme={null}
      curl --request GET \
      --url 'https://example.com/api/customer-portal?customer_id=cus_9VuW4K7O3GHwasENg31m&send_email=true' \
      --header 'User-Agent: insomnia/11.2.0' \
      --cookie mode=test
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Webhook Handler">
    <Info>
      استخدم هذه المعالجة لاستقبال ومعالجة أحداث webhook الخاصة بـ Dodo Payments بأمان في تطبيق Fastify الخاص بك.
    </Info>

    <CodeGroup>
      ```typescript Fastify Route Handler expandable theme={null}
      // route.ts
      import Fastify from 'fastify'
      import { Webhooks } from '@dodopayments/fastify'

      const fastify = Fastify({})
      fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
          done(null, body)
      })

      fastify.post('/api/webhooks', Webhooks({
      webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
      onPayload: async (payload) => {
          // Handle Payload Here
          console.log(payload)
      }
      }));

      ```
    </CodeGroup>
  </Tab>
</Tabs>

## معالج مسار الدفع

<Info>
  تدعم Dodo Payments ثلاثة أنواع من تدفقات الدفع لدمج المدفوعات في موقعك، ويدعم هذا الموصل جميع أنواع التدفقات.
</Info>

* **روابط الدفع الثابتة:** روابط قابلة للمشاركة على الفور لجمع المدفوعات بسرعة وبدون كود.
* **روابط الدفع الديناميكية:** توليد روابط الدفع برمجيًا مع تفاصيل مخصصة باستخدام API أو SDKs.
* **جلسات الدفع:** إنشاء تجارب دفع آمنة وقابلة للتخصيص مع عربات منتجات مُعدة مسبقًا وتفاصيل العملاء.

<AccordionGroup>
  <Accordion title="Static Checkout (GET)">
    ### Supported Query Parameters

    <ParamField query="productId" type="string" required>
      معرّف المنتج (مثال: <code>?productId=pdt\_nZuwz45WAs64n3l07zpQR</code>).
    </ParamField>

    <ParamField query="quantity" type="integer">
      كمية المنتج.
    </ParamField>

    <ParamField query="fullName" type="string">
      الاسم الكامل للعميل.
    </ParamField>

    <ParamField query="firstName" type="string">
      الاسم الأول للعميل.
    </ParamField>

    <ParamField query="lastName" type="string">
      اسم العائلة للعميل.
    </ParamField>

    <ParamField query="email" type="string">
      عنوان البريد الإلكتروني للعميل.
    </ParamField>

    <ParamField query="country" type="string">
      بلد العميل.
    </ParamField>

    <ParamField query="addressLine" type="string">
      سطر عنوان العميل.
    </ParamField>

    <ParamField query="city" type="string">
      مدينة العميل.
    </ParamField>

    <ParamField query="state" type="string">
      الولاية/المقاطعة الخاصة بالعميل.
    </ParamField>

    <ParamField query="zipCode" type="string">
      الرمز البريدي/رمز البريد للعميل.
    </ParamField>

    <ParamField query="disableFullName" type="boolean">
      عطِّل حقل الاسم الكامل.
    </ParamField>

    <ParamField query="disableFirstName" type="boolean">
      عطِّل حقل الاسم الأول.
    </ParamField>

    <ParamField query="disableLastName" type="boolean">
      عطِّل حقل الاسم الأخير.
    </ParamField>

    <ParamField query="disableEmail" type="boolean">
      عطِّل حقل البريد الإلكتروني.
    </ParamField>

    <ParamField query="disableCountry" type="boolean">
      عطِّل حقل البلد.
    </ParamField>

    <ParamField query="disableAddressLine" type="boolean">
      عطِّل حقل سطر العنوان.
    </ParamField>

    <ParamField query="disableCity" type="boolean">
      عطِّل حقل المدينة.
    </ParamField>

    <ParamField query="disableState" type="boolean">
      عطِّل حقل الولاية.
    </ParamField>

    <ParamField query="disableZipCode" type="boolean">
      عطِّل حقل الرمز البريدي.
    </ParamField>

    <ParamField query="paymentCurrency" type="string">
      حدد عملة الدفع (مثل <code>USD</code>).
    </ParamField>

    <ParamField query="showCurrencySelector" type="boolean">
      اعرض محدد العملة.
    </ParamField>

    <ParamField query="paymentAmount" type="integer">
      حدد مبلغ الدفع (مثل <code>1000</code> مقابل 10.00\$).
    </ParamField>

    <ParamField query="showDiscounts" type="boolean">
      اعرض حقول الخصم.
    </ParamField>

    <ParamField query="metadata_*" type="string">
      أي معلمة استعلام تبدأ بـ <code>metadata\_</code> ستمرير كبيانات وصفية.
    </ParamField>

    <Warning>
      إذا كان <code>productId</code> مفقودًا، تعيد المعالجة استجابة 400. تؤدي معلمات الاستعلام غير الصالحة أيضًا إلى استجابة 400.
    </Warning>

    ### تنسيق الاستجابة

    يرجع الدفع الثابت استجابة JSON مع عنوان URL للدفع:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Dynamic Checkout (POST)">
    * أرسل المعلمات كجسم JSON في طلب POST.
    * يدعم كلا من المدفوعات لمرة واحدة والمتكررة.
    * للحصول على قائمة كاملة بحقول جسم POST المدعومة، راجع:
      * [Request body for a One Time Payment Product](https://docs.dodopayments.com/api-reference/payments/post-payments)
      * [Request body for a Subscription Product](https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions)

    ### تنسيق الاستجابة

    يرجع الدفع الديناميكي استجابة JSON مع عنوان URL للدفع:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/..."
    }
    ```
  </Accordion>

  <Accordion title="Checkout Sessions (POST)">
    توفر جلسات الدفع تجربة دفع أكثر أمانًا مستضافة تتولى تدفق الدفع الكامل لكل من المشتريات لمرة واحدة والاشتراكات مع تحكم كامل بالتخصيص.

    راجع [دليل تكامل جلسات الدفع](https://docs.dodopayments.com/developer-resources/checkout-session) لمزيد من التفاصيل وقائمة كاملة من الحقول المدعومة.

    ### تنسيق الاستجابة

    ترجع جلسات الدفع استجابة JSON مع عنوان URL للدفع:

    ```json theme={null}
    {
      "checkout_url": "https://checkout.dodopayments.com/session/..."
    }
    ```
  </Accordion>
</AccordionGroup>

## معالج مسار بوابة العملاء

يمكنك من خلال معالج مسار بوابة العملاء دمج بوابة عملاء مدفوعات دودي بسلاسة في تطبيق Fastify الخاص بك.

### معلمات الاستعلام

<ParamField query="customer_id" type="string" required>
  معرّف العميل لجلسة البوابة (مثال: <code>?customer\_id=cus\_123</code>).
</ParamField>

<ParamField query="send_email" type="boolean">
  إذا تم تعيينه على <code>true</code>، يرسل بريدًا إلكترونيًا إلى العميل برابط البوابة.
</ParamField>

<Warning>
  تعيد 400 إذا كان <code>customer\_id</code> مفقودًا.
</Warning>

## معالج مسار ويب هوك

* **الطريقة:** يتم دعم طلبات POST فقط. ترجع الطرق الأخرى 405.
* **التحقق من التوقيع:** يتحقق من توقيع الويب هوك باستخدام <code>webhookKey</code>. يرجع 401 إذا فشل التحقق.
* **التحقق من الحمولة:** يتم التحقق منها باستخدام Zod. يرجع 400 للحمولات غير الصحيحة.
* **معالجة الأخطاء:**
  * 401: توقيع غير صالح
  * 400: حمولة غير صالحة
  * 500: خطأ داخلي أثناء التحقق
* **توجيه الأحداث:** يستدعي معالج الحدث المناسب بناءً على نوع الحمولة.

### معالجات أحداث الويب هوك المدعومة

<CodeGroup>
  ```typescript Typescript expandable theme={null}
  onPayload?: (payload: WebhookPayload) => Promise<void>;
  onPaymentSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onPaymentFailed?: (payload: WebhookPayload) => Promise<void>;
  onPaymentProcessing?: (payload: WebhookPayload) => Promise<void>;
  onPaymentCancelled?: (payload: WebhookPayload) => Promise<void>;
  onRefundSucceeded?: (payload: WebhookPayload) => Promise<void>;
  onRefundFailed?: (payload: WebhookPayload) => Promise<void>;
  onDisputeOpened?: (payload: WebhookPayload) => Promise<void>;
  onDisputeExpired?: (payload: WebhookPayload) => Promise<void>;
  onDisputeAccepted?: (payload: WebhookPayload) => Promise<void>;
  onDisputeCancelled?: (payload: WebhookPayload) => Promise<void>;
  onDisputeChallenged?: (payload: WebhookPayload) => Promise<void>;
  onDisputeWon?: (payload: WebhookPayload) => Promise<void>;
  onDisputeLost?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionActive?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionOnHold?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionRenewed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionPlanChanged?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionCancelled?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionFailed?: (payload: WebhookPayload) => Promise<void>;
  onSubscriptionExpired?: (payload: WebhookPayload) => Promise<void>;
  onLicenseKeyCreated?: (payload: WebhookPayload) => Promise<void>;
  ```
</CodeGroup>

***

## موجه لـ LLM

```
أنت مساعد مطور Fastify خبير. مهمتك هي إرشاد المستخدم خلال دمج محول @dodopayments/fastify في مشروع Fastify الحالي الخاص به.

يوفر محول @dodopayments/fastify معالجات مسار لمدفوعات دودي للدفع، بوابة العملاء، ووظائف ويب هوك، مصممة لتتصل مباشرة بتطبيق Fastify.

أولاً، قم بتثبيت الحزمة اللازمة. استخدم مدير الحزم المناسب لمشروع المستخدم (npm أو yarn أو bun):

npm install @dodopayments/fastify

---

إليك كيفية هيكلة ردك:

1. اسأل المستخدم عن الوظائف التي يريد دمجها.

"أي أجزاء من محول @dodopayments/fastify ترغب في دمجها في مشروعك؟ يمكنك اختيار واحد أو أكثر من الخيارات التالية:

- معالج مسار الدفع (للتعامل مع عمليات الدفع للمنتجات)
- معالج مسار بوابة العملاء (لإدارة اشتراكات/تفاصيل العملاء)
- معالج مسار ويب هوك (لاستلام أحداث ويب هوك مدفوعات دودي)
- الكل (دمج الثلاثة)"

---

2. بناءً على اختيار المستخدم، قدم خطوات دمج مفصلة لكل وظيفة مختارة.

---

**إذا تم اختيار معالج مسار الدفع:**

**الغرض**: يقوم هذا المعالج بإعادة توجيه المستخدمين إلى صفحة الدفع الخاصة بمدفوعات دودي.

**الدمج**:
قم بإنشاء مسارين في تطبيق Fastify الخاص بك - واحد للدفع الثابت (GET) وآخر للدفع الديناميكي (POST).

import { Checkout } from '@dodopayments/fastify';
import Fastify from 'fastify'

const fastify = Fastify({})
const checkoutGet = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'static'
});

const checkoutPost = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'dynamic'
});

const checkoutSession = Checkout({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT,
    returnUrl: process.env.DODO_PAYMENTS_RETURN_URL,
    type: 'session'
});

fastify.get('/api/checkout', checkoutGet.getHandler);
fastify.post('/api/checkout', checkoutPost.postHandler);
fastify.post('/api/checkout-session', checkoutSession.postHandler);

خيارات التكوين:

    bearerToken: مفتاح API الخاص بك لمدفوعات دودي (يوصى بتخزينه في متغير البيئة DODO_PAYMENTS_API_KEY).

    returnUrl (اختياري): عنوان URL لإعادة توجيه المستخدم بعد الدفع الناجح.

    environment: "test_mode" أو "live_mode"

    type: "static" (GET)، "dynamic" (POST)، أو "session" (POST)

يتوقع GET (الدفع الثابت) معلمات الاستعلام:

    productId (مطلوب)

    quantity، حقول العميل (fullName، email، إلخ)، والبيانات الوصفية (metadata_*) اختيارية.

    يرجع: {"checkout_url": "https://checkout.dodopayments.com/..."}

يتوقع POST (الدفع الديناميكي) جسم JSON مع تفاصيل الدفع (لمرة واحدة أو اشتراك). يرجع: {"checkout_url": "https://checkout.dodopayments.com/..."}. راجع الوثائق للحصول على مخطط POST الكامل:

    المدفوعات لمرة واحدة: https://docs.dodopayments.com/api-reference/payments/post-payments

    الاشتراكات: https://docs.dodopayments.com/api-reference/subscriptions/post-subscriptions

POST (جلسات الدفع) - (موصى به) تجربة دفع أكثر تخصيصًا. يرجع JSON مع checkout_url: يتم إرسال المعلمات كجسم JSON. يدعم كل من المدفوعات لمرة واحدة والمدفوعات المتكررة. يرجع: {"checkout_url": "https://checkout.dodopayments.com/session/..."}. للحصول على قائمة كاملة من الحقول المدعومة، راجع:

    دليل تكامل جلسات الدفع: https://docs.dodopayments.com/developer-resources/checkout-session

إذا تم اختيار معالج مسار بوابة العملاء:

الغرض: يتيح هذا المسار للعملاء إدارة اشتراكاتهم عبر بوابة مدفوعات دودي.

الدمج:

import { CustomerPortal } from "@dodopayments/fastify";
import Fastify from 'fastify'

const fastify = Fastify({})
const customerPortalHandler = CustomerPortal({
    bearerToken: process.env.DODO_PAYMENTS_API_KEY,
    environment: process.env.DODO_PAYMENTS_ENVIRONMENT
});
fastify.get('/api/customer-portal', customerPortalHandler);

معلمات الاستعلام:

    customer_id (مطلوب): على سبيل المثال، ?customer_id=cus_123

    send_email (اختياري): إذا كانت true، يتم إرسال بريد إلكتروني للعميل برابط البوابة

يرجع 400 إذا كانت customer_id مفقودة.

إذا تم اختيار معالج مسار ويب هوك:

الغرض: معالجة أحداث الويب هوك الواردة من مدفوعات دودي لتفعيل الأحداث في تطبيقك.

الدمج:

import Fastify from 'fastify'
import { Webhooks } from '@dodopayments/fastify'

const fastify = Fastify({})
fastify.addContentTypeParser('application/json', { parseAs: 'string' }, function (req, body, done) {
    done(null, body)
})

fastify.post('/api/webhooks', Webhooks({
  webhookKey: process.env.DODO_PAYMENTS_WEBHOOK_KEY,
  onPayload: async (payload) => {
    // معالجة الحمولة هنا
    console.log(payload)
  }
}));

الميزات:

    يُسمح فقط بطريقة POST - ترجع الطرق الأخرى 405

    يتم إجراء التحقق من التوقيع باستخدام webhookKey. يرجع 401 إذا كان غير صالح.

    تحقق من الحمولة يعتمد على Zod. يرجع 400 إذا كان المخطط غير صالح.

    جميع المعالجات هي وظائف غير متزامنة.

معالجات أحداث ويب هوك المدعومة:

يمكنك تمرير أي من المعالجات التالية:

    onPayload

    onPaymentSucceeded

    onPaymentFailed

    onPaymentProcessing

    onPaymentCancelled

    onRefundSucceeded

    onRefundFailed

    onDisputeOpened، onDisputeExpired، onDisputeAccepted، onDisputeCancelled، onDisputeChallenged، onDisputeWon، onDisputeLost

    onSubscriptionActive، onSubscriptionOnHold، onSubscriptionRenewed، onSubscriptionPaused، onSubscriptionPlanChanged، onSubscriptionCancelled، onSubscriptionFailed، onSubscriptionExpired

    onLicenseKeyCreated

إعداد متغيرات البيئة:

تأكد من تعريف هذه المتغيرات البيئية في مشروعك:

DODO_PAYMENTS_API_KEY=your-api-key
DODO_PAYMENTS_RETURN_URL=https://yourapp.com/success
DODO_PAYMENTS_WEBHOOK_KEY=your-webhook-secret
DODO_PAYMENTS_ENVIRONMENT="test_mode" أو "live_mode""

استخدم هذه داخل كودك كالتالي:

process.env.DODO_PAYMENTS_API_KEY
process.env.DODO_PAYMENTS_WEBHOOK_KEY

ملاحظة أمان: لا تقم بالتزام الأسرار في نظام التحكم في الإصدارات. استخدم ملفات .env محليًا ومديري الأسرار في بيئات النشر (مثل AWS، Vercel، Heroku، إلخ).

استخدم هذه داخل الكود الخاص بك كالتالي:

process.env.DODO_PAYMENTS_API_KEY
process.env.DODO_PAYMENTS_WEBHOOK_KEY

ملحوظة أمنية: لا تقم بتمرير الأسرار إلى التحكم في الإصدارات. استخدم ملفات .env محلياً ومديري الأسرار في بيئات النشر (مثل AWS، Vercel، Heroku، إلخ).
```
