# FlutterFlow

FlutterFlow يُترجم إلى تطبيق يحملُه المستخدم الخاص بك، لذا السؤال ليس عن الحقول التي يجب ملؤها، بل عن مكان ظهور المفتاح. الطلب أدناه أُرسل إلى الإنتاج بنفس الشكل الذي يُنشئه النداء؛ الخطوات في FlutterFlow مكتوبة وفق وثائق FlutterFlow حتى 2026-09-17.

أولاً أنشئ مفتاحًا كما هو موضح في القسم [المفتاح للأتمتة](/integrations/#ключ-для-автоматизації)، مع النطاق `chart`.

<Aside type="caution" title="المفتاح في النداء العادي يذهب مع التطبيق">
النداء غير المحدد كخاص يُنفّذ من الجهاز، ورأسه (header) موجود داخل الحزمة المترجمة لـ iOS وAndroid والويب، حيث يمكن لأي شخص قراءته. اجعل النداء **خاصًا**: عندها يمرره FlutterFlow عبر Firebase Cloud Function، ويبقى المفتاح على الخادم. الفحص الخاص بـ FlutterFlow هو تحميل كود المشروع والبحث عن المفتاح في ملفات الواجهة الأمامية، وهو متاح فقط في الخطة المدفوعة.
</Aside>

## 1. أنشئ النداء

افتح **API Calls**، اضغط **+ Add**، اختر **Create API Call** واملأ:

- **API Call Name**: `Natal chart`.
- **Method Type**: `POST`.
- **URL**:

  ```
  https://api.astroway.info/v1/chart
  ```

- تبويب **Headers**، **+ Add Header**: سطر واحد `X-Api-Key: ` ثم مفتاحك. السطر الثاني `Content-Type: application/json`.
- تبويب **Variables**: خمس متغيّرات من نوع String، `date`, `time`, `timezone`, `latitude`, `longitude`، كل واحدة بقيمة افتراضية من JSON أدناه.
- تبويب **Body**، في القائمة المنسدلة **JSON**: الصق JSON واسحب المتغيّرات إليه.

```json
{
  "date": "1990-05-15",
  "time": "14:30:00",
  "timezone": "Europe/Kyiv",
  "latitude": "50.45",
  "longitude": "30.52"
}
```

خط العرض والطول يبقيان كسلاسل عن قصد: API يقبل `"50.45"` كعدد، والسلسلة تسهّل سحب المتغيّرات.

اضغط **Add Call**، افتح **Response & Test**، اضغط **Test API Call** وشاهد الرد في **Test Response**. `data.input.timezoneOffset` يُرجع كـ `4`: هذا هو الانحراف الذي كان لدى كييف في ذلك التاريخ.

## 2. اجعل النداء خاصًا

في **Advanced Settings** للنداء فعل **Make Private**، اضغط **Save**، ثم **Deploy APIs**. الآن يُنفّذ النداء في Firebase Cloud Function، لذا يحتاج المشروع إلى Firebase متصل وخطة Firebase تشمل Cloud Functions.

<Aside type="caution" title="النداءات الخاصة لا ترث رؤوس المجموعة">
إذا وضعت المفتاح على **API Group** بدلاً من النداء نفسه، سيتوقف FlutterFlow عن إرساله في اللحظة التي يصبح فيها النداء خاصًا: رؤوس المجموعة لا تُورّث للنداءات الخاصة. أضف `X-Api-Key` إلى النداء نفسه، وإلا سيُعيد أول تشغيل خاص `401`.
</Aside>

هناك أمران آخران تقولهما وثائق FlutterFlow صراحةً: المفتاح المرسل من الواجهة الأمامية، مثلًا عبر remote config، يبقى مكشوفًا حتى في النداء الخاص، والشكل الآمن هو رأس (header) مضمّن في النداء نفسه.

## 3. اقرأ الرد

في **JSON Paths** اضغط **+ Add JSON Path** وأعط كل واحد اسمًا:

| الاسم | JSON Path |
|---|---|
| `ascendant` | `$.data.houses.ascendant` |
| `sunLongitude` | `$.data.planets[0].longitude` |
| `moonLongitude` | `$.data.planets[1].longitude` |
| `offsetUsed` | `$.data.input.timezoneOffset` |

الإشارة هي الطول مقسومًا على 30 ومقربًا للأسفل، كفهرس في قائمة من اثني عشر اسمًا: على سبيل المثال Ascendant `159.26` يعطي `5`، أي العذراء. يكفي دالة مخصصة من أربع أسطر أو قائمة من اثني عشر سطرًا والفهرس.

## لا يمكن لتجميع الويب الاتصال بنا من المتصفح

تم القياس في 2026-09-17 من صفحة على نطاق خارجي: `POST /v1/chart` يرد على preflight بدون رأس `access-control-allow-origin`، وChrome يحظر الطلب. المتصفح على نطاق آخر يرد فقط على `/v1/public/*` و `/v1/embed/*`.

FlutterFlow يجرِّي النداءات عبر بروكسي خاص به في المصمم، في وضع Run و Test، لذا النداء الذي يعمل هناك قد يفشل بعد نشر تطبيق الويب. هناك حلّان، ونحن نوصي بالأول:

- **اجعل النداء خاصًا**، كما في الأعلى. عندها يُنفّذ في Cloud Function، وليس في المتصفح، وهذا يزيل فورًا كل من مشكلة المفتاح ومشكلة CORS.
- **ضع خلفية خاصة أمامنا**، إذا كان لديك واحدة بالفعل. إعدادات البروكسي في FlutterFlow، مع proxy URL الخاص، موثقة للمصمم ووضعيات Run و Test؛ لا تتحدث الوثائق عن تجميع الويب المنشور، لذا لا تعتمد عليها هناك.

المفتاح العام `pk_` لا يحل هذه المشكلة: فهو يتيح فقط `/v1/public/*` و `/v1/embed/*`، ومن تجميعات iOS و Android يُرفض تمامًا لأنه لا يرسل web-origin.

## الأخطاء

- **`401`** في نداء خاص: المفتاح موجود على المجموعة، وليس على النداء.
- **`400 INVALID_FIELD` مع `timezone` في `details`**: المنطقة فارغة، يجب أن تكون اختصارًا مثل `EST` أو اسم منطقة.
- **`400` مع `date` أو `time` في `details`**: الصيغة ليست `YYYY-MM-DD` / `HH:MM:SS`.
- **`403 ENDPOINT_NOT_IN_SCOPE`**: النطاق `chart` غير موجود في مجال المفتاح.
- **`429 KEY_BUDGET_EXHAUSTED`**: المفتاح استهلك ميزانيته؛ قم بزيادة الميزانية في لوحة التحكم.

<Aside type="note">
الخطة المجانية لـ FlutterFlow تسمح باثنين من API-ендпоінти للمشروع ولا تدعم استيراد OpenAPI، لذا يضاف النداء يدويًا، ويتبقى مكان واحد. API لا يجري جيوكود: الإحداثيات تُؤخذ من حقولك الخاصة أو من خدمة جيوكود لديك مفتاح لها.
</Aside>
