مثال على التكامل مع FedEx
يوضح هذا الدرس كيفية التكامل مع FedEx.
1. التحضير
1.1. أنشئ حسابًا في FedEx
أنشئ حسابًا على بوابة المطورين.
1.2. أنشئ المشاريع واحصل على رموز الوصول
أنشئ مشروعين في قسم مشاريعي، واحفظ client id وclient secret لكل منهما.
المشروع الأول لإدارة الشحنات:
المشروع الثاني لتتبع الشحنات:
1.3. أنشئ حالات التسليم
في علامة تبويب الحالات الخاصة بمخزن الطلبات، أنشئ الحالات (يفتح في علامة تبويب جديدة) التالية:
- order_delivery
- order_delivery_started
- ready_for_pickup
1.4. أنشئ حدثًا لتتبع الحالات
في وحدة Events (يفتح في علامة تبويب جديدة)، أنشئ حدثًا يتتبع تغيّر حالة الطلب إلى order_delivery.

1.5. أنشئ مجموعة للتسليم
في وحدة Integration Collections (يفتح في علامة تبويب جديدة)، أنشئ مجموعة للتسليم بالسمات التالية:
- name (
string) - address (
string) - phone_number (
string) - city (
string) - state_code (
string) - postal_code (
string) - country_code (
string) - tracking_number (
string) - transaction_id (
string) - ship_datestamp (
string) - delivery_datestamp (
string)

1.6. أنشئ طلبًا تجريبيًا
أنشئ طلبًا، ثم أنشئ له سجلًا في المجموعة.


2. إنشاء شحنة
2.1. تتبع حدث التسليم
- اسحب عقدة events (يفتح في علامة تبويب جديدة) إلى مساحة العمل.
- أدخل اسم العقدة.
- غيّر القيمة في حقل "Set" إلى "orderEvent".
- يُحفظ الحدث في الكائن "msg.orderEvent"، ويمكنك استخدامه في العقد الأخرى.
- اختر من القائمة الحدث الذي أنشأته "order delivery"، ثم انقر على "submit".

2.2. الحصول على رمز الوصول
- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".
- استبدل
YOUR_CLIENT_IDوOUR_CLIENT_SECRETبقيمك.

msg.payload = {
'grant_type': 'client_credentials',
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET'
}
msg.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
return msg;
لمزيد من التفاصيل حول المعاملات، راجع وثائق FedEx.
- اسحب عقدة http request (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- في حقل Method، اختر "POST".
- في حقل Data، اختر "Send as request body".
- في حقل Link، الصق الرا بط
https://apis-sandbox.fedex.com/oauth/token. - في حقل Return، اختر "Object JSON".

- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".

msg.access_token = msg.payload.access_token;
return msg;
2.3. إنشاء شحنة
- اسحب عقدة admin-api (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- اختر الطريقة "Receiving all records belonging to the collection"، والصق الكود التالي في حقل "Data".
{
"entityType": "orders",
"entityId": "{{orderEvent.order.id}}",
"langCode": "en_US",
"offset": 0,
"limit": 1,
"marker": "delivery"
}

- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".

// نحصل على رمز الوصول المحفوظ سابقًا
const token = msg.access_token;
// نعيّن الترويسات
msg.headers = {
'Content-Type': 'application/json',
'authorization': `Bearer ${token}`
};
// نحصل على المجموعات من الخطوة السابقة
const collection = msg.payload.items[0];
// نحوّل المصفوفة إلى كائن
const formData = collection.formData.reduce((acc, item) => {
acc[item.marker] = item.value;
return acc;
}, {});
// نعيّن بيانات المستلم من النموذج
const recipient = {
"address": {
"streetLines": [
formData.address
],
"city": formData.city,
"stateOrProvinceCode": formData.state_code,
"postalCode": formData.postal_code,
"countryCode": formData.country_code
},
"contact": {
"personName": formData.name,
"phoneNumber": formData.phone_number
}
}
// نحفظ بيانات المجموعة في msg لاستخدامها لاحقًا
msg.collection = collection;
// نعيّن معاملات الطلب إلى FedEx
msg.payload = {
"labelResponseOptions": "URL_ONLY",
"accountNumber": {
"value": "510087020"
},
"requestedShipment": {
"shipper": {
"contact": {
"personName": "SENDER NAME",
"phoneNumber": "9018328595"
},
"address": {
"streetLines": [
"SENDER ADDRESS 1"
],
"city": "MEMPHIS",
"stateOrProvinceCode": "TN",
"postalCode": "38116",
"countryCode": "US"
}
},
"recipients": [
recipient
],
"serviceType": "STANDARD_OVERNIGHT",
"packagingType": "YOUR_PACKAGING",
"pickupType": "DROPOFF_AT_FEDEX_LOCATION",
"shippingChargesPayment": {
"paymentType": "SENDER",
"payor": {
"responsibleParty": {
"accountNumber": {
"value": "510087020",
"key": ""
}
},
"address": {
"streetLines": [
"SENDER ADDRESS 1"
],
"city": "MEMPHIS",
"stateOrProvinceCode": "TN",
"postalCode": "38116",
"countryCode": "US"
}
}
},
"labelSpecification": {},
"requestedPackageLineItems": [
{
"customerReferences": [
{
"customerReferenceType": "CUSTOMER_REFERENCE",
"value": `Collection${collection.id}`
}
],
"weight": {
"units": "LB",
"value": "20"
}
}
]
}
};
return msg;
لمزيد من التفاصيل حول المعاملات، راجع وثائق FedEx.
- اسحب عقدة http request (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- في حقل Method، اختر "POST".
- في حقل Data، اختر "Send as request body".
- في حقل Link، الصق الرابط
https://apis-sandbox.fedex.com/ship/v1/shipments. - في حقل Return، اختر "Object JSON".

- اسحب عقدة debug (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.

- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".

// نحصل على بيانات الشحنة
const shipment = msg.payload.output.transactionShipments[0];
// نحصل على بيانات المجموعة المحفوظة سابقًا
const collection = msg.collection;
// نكتب بيانات الشحنة في سمات النموذج
const newFormData = [
...collection.formData
.filter(item => !['transaction_id', 'ship_datestamp', 'delivery_datestamp', 'tracking_number'].includes(item.marker)),
{
marker: 'transaction_id',
value: msg.payload.transactionId,
type: 'string'
},
{
marker: 'ship_datestamp',
value: shipment.shipDatestamp,
type: 'string'
},
{
marker: 'delivery_datestamp',
value: shipment.pieceResponses[0].deliveryDatestamp,
type: 'string'
},
{
marker: 'tracking_number',
value: shipment.masterTrackingNumber,
type: 'string'
}
]
// نعيّن معاملات تحديث المجموعة
msg.params = {
langCode: 'en_US',
id: collection.id,
marker: 'delivery'
}
msg.data = {
formIdentifier: 'delivery_form',
formData: {
en_US: newFormData
},
entityId: collection.entityId,
entityType: collection.entityType
}
// نحفظ بيانات المجموعة لاستخدامها لاحقًا
msg.collection = collection;
return msg;
- اسحب عقدة admin-api (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- اختر الطريقة "Changing a record in the collection".

2.4. تحديث حالة الطلب
- اسحب عقدة admin-api (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- اختر الطريقة "Updating the status of an order belonging to the order storage object".
- الصق الكود التالي في حقل "Query parameters".
{
"id": 1,
"orderId": "{{collection.entityId}}"
}
- الصق الكود التالي في حقل "Request body".
{
"statusIdentifier": "order_delivery_started"
}

- اسحب عقدة debug (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.

3. تتبع حالة الشحنة
3.1. الحصول على الطلبات المراد تتبعها
- اسحب عقدة interval (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- أدخل الفاصل الزمني بالدقائق.

- اسحب عقدة admin-api (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- اختر الطريقة "Receiving all orders belonging to the order storage object".
- الصق الكود التالي في حقل "Query parameters".
{
"statusIdentifier": "order_delivery_started",
"langCode": "en_US",
"offset": 0,
"limit": 100,
"id": 1
}

- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".

msg.payload = msg.payload.items;
return msg;
- اسحب عقدة split (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- أدخل الطول.

- اسحب عقدة admin-api (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- اختر الطريقة "Receiving all records belonging to the collection".
- الصق الكود التالي في حقل "Query parameters".
{
"marker": "delivery",
"entityId": "{{payload.id}}",
"entityType": "orders",
"langCode": "en_US",
"limit": 1,
"offset": 0
}

- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".

msg.payload = msg.payload.items[0]
return msg;
- اسحب عقدة switch (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- أضف قاعدة للتحقق، واختر الشرط "not empty".

- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".
![]()
msg.trackingNumber = msg.payload
.formData
.find(item => item.marker === 'tracking_number')
.value;
msg.collection = msg.payload;
return msg;
3.2. الحصول على رمز الوصول
- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".
- استبدل
YOUR_CLIENT_IDوOUR_CLIENT_SECRETبقيمك.

msg.payload = {
'grant_type': 'client_credentials',
'client_id': 'YOUR_CLIENT_ID',
'client_secret': 'YOUR_CLIENT_SECRET'
}
msg.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
return msg;
لمزيد من التفاصيل حول المعاملات، راجع وثائق FedEx.
- اسحب عقدة http request (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- في حقل Method، اختر "POST".
- في حقل Data، اختر "Send as request body".
- في حقل Link، الصق الرابط
https://apis-sandbox.fedex.com/oauth/token. - في حقل Return، اختر "Object JSON".

3.3. الحصول على حالة الشحنة
- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".
![]()
const token = msg.payload.access_token;
msg.headers = {
'content-type': 'application/json',
'authorization': `Bearer ${token}`
};
msg.payload = {
"trackingInfo": [
{
"trackingNumberInfo": {
"trackingNumber": msg.trackingNumber
}
}
],
"includeDetailedScans": true
}
return msg;
لمزيد من التفاصيل حول المعاملات، راجع وثائق FedEx.
- اسحب عقدة http request (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- في حقل Method، اختر "POST".
- في حقل Data، اختر "Send as request body".
- في حقل Link، الصق الرابط
https://apis-sandbox.fedex.com/track/v1/trackingnumbers. - في حقل Return، اختر "Object JSON".
![]()
- اسحب عقدة function (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- الصق الكود من المثال في حقل "Function".
![]()
msg.payload = msg.payload.output.completeTrackResults[0].trackResults[0].latestStatusDetail.statusByLocale;
return msg;
3.4. تحديث حالة الطلب
- اسحب عقدة switch (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- أضف قاعدة للتحقق، واختر الشرط "=="، ثم أدخل القيمة "Ready for pickup".

- اسحب عقدة admin-api (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
- اختر الطريقة "Updating the status of an order belonging to the order storage object".
- الصق الكود التالي في حقل "Query parameters".
{
"id": 1,
"orderId": "{{collection.entityId}}"
}
- الصق الكود التالي في حقل "Request body".
{
"statusIdentifier": "ready_for_pickup"
}

- اسحب عقدة debug (يفتح في علامة تبويب جديدة) إلى مساحة العمل وصِلها بعقدة الخطوة السابقة.
