انتقل إلى المحتوى الرئيسي

مثال على التكامل مع 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.

الحدث order delivery بالمعرّف order_delivery: الوحدة orders، والمخزن test_order_storage، والحالة order_delivery، مع تحديد "Integrations".

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)

قسم "Integration collections": تظهر في القائمة المجموعة delivery المنشأة بالمعرّف delivery.

1.6. أنشئ طلبًا تجريبيًا

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

طلب POST إلى /api/content/orders-storage/marker/order_storage/orders بجسم JSON لطلب تجريبي: النموذج order_form، والدفع paypal، والمنتج 1 × 2.

طلب POST إلى /api/content/integration-collections/marker/delivery/rows: سجل للطلب 1 بالنموذج delivery_form وبيانات المستلم.

2. إنشاء شحنة​

2.1. تتبع حدث التسليم

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

عقدة order delivery event: قيمة "Set" هي msg.orderEvent، والحدث order delivery محدد في "Events".


2.2. الحصول على رمز الوصول

عقدة auth body: الكود في حقل "Function" يعيّن msg.payload مع client_credentials وYOUR_CLIENT_ID وYOUR_CLIENT_SECRET وترويسة Content-Type.

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".

عقدة auth request: قيمة "Method" هي POST، و"Data" هي Send as request body، و"Link" هي https://apis-sandbox.fedex.com/oauth/token، و"Return" هي Object JSON.


عقدة set access token: الكود في حقل "Function" ينسخ access_token من msg.payload إلى msg.access_token.

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"
}

عقدة find collection rows: قيمة "Type" هي Receiving all records belonging to the collection، وفي "Query parameters" كائن JSON يتضمن marker delivery وentityType orders وentityId orderEvent.order.id.


عقدة shipment data: الكود في حقل "Function" يبني الترويسات مع رمز Bearer وبيانات المستلم من سجل المجموعة.

// نحصل على رمز الوصول المحفوظ سابقًا
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".

عقدة shipment request: قيمة "Method" هي POST، و"Data" هي Send as request body، و"Link" هي https://apis-sandbox.fedex.com/ship/v1/shipments، و"Return" هي Object JSON.


عقدة debug باسم debug fedex shipment: قيمة "Output" هي msg.payload.


عقدة update row data: الكود في حقل "Function" يبني formData جديدة لسجل المجموعة تتضمن الحقلين transaction_id وship_datestamp من استجابة FedEx.

// نحصل على بيانات الشحنة
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;

عقدة update collection row: الطريقة "Changing a record in the collection" محددة في "Type"، وحقل "Query parameters" فارغ.


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"
}

عقدة order delivery started: النوع هو تحديث حالة طلب في مخزن الطلبات، والمعاملان id وorderId، وفي الجسم statusIdentifier.


عقدة debug باسم debug status update 1: قيمة "Output" هي msg.payload.


3. تتبع حالة الشحنة​

3.1. الحصول على الطلبات المراد تتبعها

عقدة set interval: قيمة حقل "interval" هي 60.


  • اسحب عقدة 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
}

عقدة find orders by status: قيمة "Type" هي Receiving all orders belonging to the order storage object، وفي "Query parameters" كائن JSON يتضمن statusIdentifier order_delivery_started وlimit 100 وid 1.


عقدة set orders: الكود في حقل "Function" يكتب msg.payload.items في msg.payload.

msg.payload = msg.payload.items;

return msg;

عقدة split: قيمة "Property" هي payload، و"Length" هي 1.


  • اسحب عقدة 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
}

عقدة find collection rows: قيمة "Type" هي Receiving all records belonging to the collection، وفي "Query parameters" كائن JSON يتضمن marker delivery وentityId payload.id وentityType orders.


نافذة "Node Information" لعقدة function باسم "set row": الكود في حقل "Function" يكتب العنصر الأول من msg.payload.items في msg.payload

msg.payload = msg.payload.items[0]

return msg;

نافذة "Node Information" لعقدة "switch": الخاصية "payload"، والوضع "check all rules"، والشرط المحدد في القاعدة "not empty"


نافذة "Node Information" لعقدة function باسم "set trackingNummber": الكود في حقل "Function" يأخذ من formData قيمة الحقل ذي المعرّف tracking_number ويكتبها في msg.trackingNumber

msg.trackingNumber = msg.payload
.formData
.find(item => item.marker === 'tracking_number')
.value;

msg.collection = msg.payload;

return msg;

3.2. الحصول على رمز الوصول

نافذة "Node Information" لعقدة function باسم "auth body": الكود في حقل "Function" يبني جسم طلب رمز الوصول مع grant_type وclient_id وclient_secret، والقيمتان المؤقتتان YOUR_CLIENT_ID وYOUR_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".

نافذة "Node Information" لعقدة http request باسم "auth request": الطريقة "POST"، و"Send as request body"، والعنوان apis-sandbox.fedex.com/oauth/token، وقيمة "Return" هي "Object JSON"


3.3. الحصول على حالة الشحنة

نافذة "Node Information" لعقدة function باسم "tracking data": الكود في حقل "Function" يعيّن ترويسة التفويض Bearer برمز الوصول، وجسم طلب يتضمن trackingNumber

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".

نافذة "Node Information" لعقدة http request باسم "tracking request": الطريقة "POST"، و"Send as request body"، والعنوان apis-sandbox.fedex.com/track/v1/trackingnumbers، وقيمة "Return" هي "Object JSON"


نافذة "Node Information" لعقدة function باسم "set tracking result": الكود في حقل "Function" يكتب نتيجة التتبع من msg.payload.output في msg.payload

msg.payload = msg.payload.output.completeTrackResults[0].trackResults[0].latestStatusDetail.statusByLocale;

return msg;

3.4. تحديث حالة الطلب

نافذة "Node Information" لعقدة switch باسم "check ship status": الخاصية "payload"، والشرط "=="، والقيمة "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"
}

نافذة "Node Information" لعقدة "update status": النوع هو تحديث حالة الطلب، وفي "Query parameters" المعاملان id وorderId، وفي "Request body" المعامل statusIdentifier بالقيمة ready_for_pickup


نافذة "Node Information" لعقدة debug باسم "debug status update 2": القيمة المحددة في حقل "Output" هي msg.payload