# التطوير المحلي (/ar/integrate/webhooks/local-development)

حوّل تسليمات الـ webhook لجهازك وأنت بتبني. ابني، صلّح، أعد الإرسال، وكرّر.

XPay مش بيقدر يسلّم الـ webhooks لـ `localhost`. علشان تجرّب المعالِج بتاعك على أحداث وضع الاختبار الحقيقية وأنت بتبني، اكشف سيرفر التطوير بتاعك عن طريق نفق (tunnel) بيديك رابط HTTPS عام، ووجّه نقطة نهاية webhook في وضع الاختبار للرابط ده، وكرّر شغلك.

التدفق بيبقى كده:

1. شغّل المعالِج بتاعك محليًا على منفذ (خلّينا نقول `3000`).
2. شغّل نفق بيمرّر رابط HTTPS عام للمنفذ ده.
3. في لوحة التحكم، وأنت في وضع الاختبار، أنشئ نقطة نهاية webhook بتشاور على رابط النفق.
4. أطلق أحداث (دفعة اختبار، استرداد، وهكذا) واتفرّج عليها وهي بتوصل جهازك.
5. لما حاجة تبوظ، صلّح المعالِج واضغط **Resend** للحدث اللي فشل من الـ Workbench. مش محتاج تعيد تشغيل الإجراء الأصلي.

## ظبّط نفق [#ظبّط-نفق]

أي أداة بتمرّر رابط HTTPS عام لمنفذ محلي بتعمل الشغل. اختيارين شائعين:

| الأداة            | رابط ثابت                                  | ملاحظات                                                                                                                                 |
| ----------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| Cloudflare Tunnel | أيوة، لما تنشئ نفق باسم                    | مجاني. النفق اللي ليه اسم بيحتفظ بنفس اسم المضيف عبر إعادة التشغيل. الأنسب للتطوير اللي بيشتغل لفترة طويلة. الـ CLI اسمه `cloudflared`. |
| ngrok             | عشوائي مع كل إعادة تشغيل في الخطة المجانية | بيبدأ بسرعة. الخطة المجانية بتغيّر اسم المضيف مع كل إعادة تشغيل، فبتعدّل رابط النقطة في كل مرة.                                         |

اختار اللي عندك بالفعل. تدفق الـ webhook مش بيفرق معاه مين اللي وقّع شهادة الـ TLS بتاعتك.

<Tabs items="[&#x22;Cloudflare Tunnel&#x22;, &#x22;ngrok&#x22;]">
  <Tab value="Cloudflare Tunnel">
    <Steps>
      <Step>
        ### شغّل المعالِج بتاعك [#شغّل-المعالِج-بتاعك]

        ابدأ سيرفر التطوير بتاعك على أي منفذ المعالِج بيستمع عليه. الأمثلة تحت بتستخدم `3000`.
      </Step>

      <Step>
        ### ابدأ نفق سريع [#ابدأ-نفق-سريع]

        أبسط مسار: نفق لمرة واحدة بيديك رابط `*.trycloudflare.com` عشوائي.

        ```bash
        cloudflared tunnel --url http://localhost:3000
        ```

        الأمر بيطبع رابط عام بالشكل `https://random-words-1234.trycloudflare.com`. انسخه.

        علشان اسم مضيف ثابت عبر إعادة التشغيل، ظبّط نفق باسم وملف إعدادات ([توثيق Cloudflare](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/get-started/create-local-tunnel/)). بعد ما تظبطه، النفق بيحتفظ بنفس الرابط للأبد.
      </Step>

      <Step>
        ### ضيف الرابط كنقطة نهاية webhook [#ضيف-الرابط-كنقطة-نهاية-webhook]

        في لوحة التحكم، انتقل لـ **وضع الاختبار**، افتح **المطورين ← Webhooks**، واضغط **إضافة نقطة نهاية**. استخدم:

        * **رابط نقطة النهاية**: `https://random-words-1234.trycloudflare.com/webhooks/xpay` (رابط النفق بتاعك زائد مسار المعالِج).
        * **الأحداث**: اختار اللي المعالِج بتاعك بيهتم بيها. `checkout.session.completed` هي نقطة البداية المعتادة.

        اضغط **إضافة نقطة نهاية**، انسخ الـ `whsec_*` من النافذة، والصقه في بيئة التطوير بتاعتك (`.env.local`، أو `direnv`، أو أي حاجة بتستخدمها):

        ```bash
        XPAY_WEBHOOK_SECRET=whsec_...
        ```

        أعد تشغيل سيرفر التطوير بتاعك علشان متغيّر البيئة يتحمّل.
      </Step>
    </Steps>
  </Tab>

  <Tab value="ngrok">
    <Steps>
      <Step>
        ### شغّل المعالِج بتاعك [#شغّل-المعالِج-بتاعك-1]

        ```bash
        # في الـ terminal اللي فيه سيرفر التطوير بتاعك
        pnpm dev # أو أي حاجة بتستخدمها
        ```
      </Step>

      <Step>
        ### افتح نفق [#افتح-نفق]

        ```bash
        ngrok http 3000
        ```

        الـ terminal بيعرض سطر `Forwarding` فيه رابط `https://*.ngrok-free.app`. انسخه.
      </Step>

      <Step>
        ### ضيف الرابط كنقطة نهاية webhook [#ضيف-الرابط-كنقطة-نهاية-webhook-1]

        في **وضع الاختبار** بلوحة التحكم، افتح **المطورين ← Webhooks ← إضافة نقطة نهاية**، الصق رابط النفق، اختار الأحداث، انسخ الـ `whsec_*` في بيئتك، وأعد تشغيل المعالِج.
      </Step>

      <Step>
        ### حدّث الرابط في كل مرة تعيد فيها تشغيل ngrok [#حدّث-الرابط-في-كل-مرة-تعيد-فيها-تشغيل-ngrok]

        الخطة المجانية بتغيّر اسم المضيف العام في كل مرة `ngrok http` بيعيد التشغيل. لما ده يحصل:

        * افتح النقطة في **المطورين ← Webhooks**، اضغط قائمة الـ `⋮`، اختار **تعديل webhook**، وغيّر الرابط.
        * الـ `whsec_*` مش بيتغير لما تعدّل، فبيئة المعالِج بتاعك بتفضل زي ما هي.
      </Step>
    </Steps>
  </Tab>
</Tabs>

## أطلق أحداث علشان تختبر [#أطلق-أحداث-علشان-تختبر]

أي حاجة بتطلق webhook في الإنتاج بتطلق نفس الحدث في وضع الاختبار. أسرع المسارات علشان تجيب حركة على المعالِج بتاعك:

* **اعمل دفعة اختبار.** أنشئ رابط دفع في لوحة التحكم، افتحه، وادفع ببطاقة النجاح `5123 4500 0000 0008` وتاريخ انتهاء `01/39`. شوف [وضع الاختبار وبطاقات الاختبار](/get-started/test-mode) للجدول الكامل وتواريخ انتهاء الفشل.
* **اعمل استرداد اختبار.** من لوحة التحكم في وضع الاختبار، افتح معاملة ناجحة واضغط **رد المبلغ**. المعالِج بيستقبل `refund.created` و`charge.refunded`.
* **أعد إرسال حدث.** تبويب الأحداث في الـ Workbench بيحتفظ بكل أحداث وضع الاختبار لمدة 90 يوم. اضغط **Resend** على أي تسليم علشان تغذّي المعالِج بنفس الحمولة دي تاني. شوف [إعادة الإرسال والمحاولات](/integrate/webhooks/replaying-and-retries).

دورة شغل نموذجية وأنت بتبني: اعمل دفعة اختبار واحدة، اتفرّج عليها وهي بتوصل المعالِج بتاعك، صلّح اللي باظ، اضغط **Resend**، وكرّر. مش محتاج تعمل دفعة جديدة في كل تكرار.

## قائمة الموافقة النهائية قبل ما تحوّل للحساب الفعلي [#قائمة-الموافقة-النهائية-قبل-ما-تحوّل-للحساب-الفعلي]

قبل ما تبطّل الاختبار محليًا وتنتقل للحساب الفعلي، اتأكد من كل واحدة من دول على أحداثك اللي اتسلّمت عن طريق النفق:

* **التوقيعات بتتفحص.** المُتحقق بتاعك بيرجع 400 على محتوى متلاعَب فيه. اختبره يدويًا بتغيير بايت واحد من طلب متسجَّل.
* **إعادة الإرسال بلا تكرار.** اضغط **Resend** على نفس الحدث خمس مرات. تنفيذ الطلب بيشتغل مرة واحدة بس.
* **التوقيعات الغلط مش بتوقّع المعالِج.** إرجاع 400 تمام؛ بس رمي 500 بسبب خطأ في قراءة ترويسة بيبقى رائحة أمنية وحشة.
* **المعالِج بيردّ بالإقرار خلال 30 ثانية.** لو شغلك بياخد وقت أطول، حوّله لطابور (queue) وارجع 200 على طول. XPay بيعتبر أي حاجة أبطأ فشل وبيعيد المحاولة.
* **سر التوقيع مش متعمل له commit.** بيعيش في ملف بيئة محلي أو مدير أسرار، مش في الريبو بتاعك.

لما الخمسة كلهم ينجحوا على أحداث الاختبار، تبقى جاهز تضيف نقطة منفصلة للحساب الفعلي برابطها الخاص وبـ `whsec_*` الخاص بيها. خلّي النقطتين مشتركين في نفس الأحداث؛ وطوّر وانشر كل واحدة لوحدها.

## رايح فين بعد كده [#رايح-فين-بعد-كده]

<Cards>
  <Card icon="<Cable />" title="إعداد نقطة نهاية" href="/integrate/webhooks/setting-up-an-endpoint">
    شرح خطوة بخطوة لحقول لوحة التحكم، ومختار الأحداث، ونافذة سر التوقيع.
  </Card>

  <Card icon="<ShieldCheck />" title="التحقق من التوقيعات" href="/integrate/webhooks/verifying-signatures">
    كود التحقق، ووصفات المحتوى الخام حسب إطار العمل، ونمط عدم التكرار.
  </Card>

  <Card icon="<RefreshCw />" title="إعادة الإرسال والمحاولات" href="/integrate/webhooks/replaying-and-retries">
    جدول إعادة المحاولة وزرّ إعادة الإرسال اللي هتعتمد عليه وأنت بتنقّح.
  </Card>

  <Card icon="<Braces />" title="مرجع الأحداث" href="/integrate/webhooks/event-reference">
    كل حدث تقدر تشترك فيه، وشكل الغلاف، واللي بيحمله `data.object`.
  </Card>

  <Card icon="<Network />" title="نموذج الكائنات" href="/integrate/object-model">
    إزاي جلسة الدفع، وPayment Intent، وCharge، وRefund، والعميل بيرتبطوا.
  </Card>
</Cards>