المحتويات

المقدمة

المتطلبات الأساسية

المتطلبات

المكونات المستخدمة

التكوين

نظرة عامة

الوحدات

إنشاء رمز مميز

إختبار API

واجهات برمجة التطبيقات (API) مع معلمات الرأس

واجهات برمجة التطبيقات (API) مع معلمات الاستعلام

المقدمة

يصف هذا وثيقة كيف أن يستعمل المختلف APIs يتوفر على cisco مادة حفازة مركز يستعمل Python.

المتطلبات الأساسية

المتطلبات

معرفة أساسية حول:

- مركز Catalyst من Cisco

- واجهات برمجة التطبيقات

- بايثون

المكونات المستخدمة

- Cisco Catalyst Center 2.3.5.x

- بايثون 3.x.x

تم إنشاء المعلومات الواردة في هذا المستند من الأجهزة الموجودة في بيئة معملية خاصة. بدأت جميع الأجهزة المُستخدمة في هذا المستند بتكوين ممسوح (افتراضي). إذا كانت شبكتك قيد التشغيل، فتأكد من فهمك للتأثير المحتمل لأي أمر.

ملاحظة: لا يوفر مركز المساعدة التقنية (TAC) من Cisco الدعم التقني ل Python. إذا واجهت مشاكل مع Python، يرجى الاتصال بدعم Python للحصول على المساعدة التقنية.

التكوين

نظرة عامة

يحتوي مركز Cisco Catalyst على العديد من واجهات برمجة التطبيقات (API) المتوفرة. للتحقق من أي واجهات برمجة التطبيقات يمكن إستخدامها، على مركز Catalyst، انتقل إلى منصة > Developer Toolkit > APIs.

صفحة واجهات برمجة التطبيقات (API) لمركز Catalyst

يكون لكل واجهة برمجة تطبيقات غرضها الخاص، وفقا للمعلومات أو الإجراء الذي يلزم إجراؤه على Catalyst Center. لكي تعمل واجهات برمجة التطبيقات، كمتطلب أساسي، يجب إستخدام رمز مميز للمصادقة بشكل صحيح إلى Catalyst Center والحصول على إستجابة واجهة برمجة تطبيقات ناجحة. يقوم الرمز المميز بتعريف امتيازات المتصل المتصل بالراحة وفقا لذلك.

ومن المهم أيضا تحديد المكونات التي تشكل واجهة برمجة تطبيقات والتي هي كما يلي:

- url: نقطة النهاية التي توفر الوصول إلى مورد معين.

- الطريقة: يجب أن تتضمن جميع واجهات برمجة التطبيقات طريقة. وهو يحدد الإجراء/العملية التي يرغب العميل في تنفيذها لنقطة النهاية المحددة. الأمثلة: نشر، الحصول، وضع، حذف.

- العنوان: يوفر معلومات إضافية حول الطلب بتنسيق أزواج القيمة الأساسية. على سبيل المثال، يوفر رأس التخويل أسلوب مصادقة باستخدام بيانات الاعتماد.

- المحددات: المتغيرات التي توفر تعليمات محددة إلى نقطة النهاية باستخدام واجهة برمجة التطبيقات (API). يمكن أن تكون المعلمات جزءا من URL لنقطة النهاية.

- الحمولة: البيانات التي تتطلب إرسالها إلى نقطة النهاية أثناء إستدعاء واجهة برمجة التطبيقات (API).

ملاحظة: أحلت ل كثير معلومة أكثر تفصيلا حول كل API يتوفر على مادة حفازة مركز، ال API مرجع مرشد.

الوحدات

وحدات Python النمطية المستخدمة:

- الطلبات: تسمح هذه الوحدة النمطية بإرسال طلبات HTTP/1.1 إلى عناوين URL معينة. للحصول على مزيد من المعلومات حول الوحدة النمطية، راجع دليل وحدة الطلب.

- base64: يوفر وظائف التشفير وفك التشفير. للحصول على مزيد من المعلومات حول الوحدة النمطية، راجع دليل وحدة base64.

- json: تسمح هذه الوحدة النمطية بالحصول على بيانات محددة من إستجابة واجهة برمجة التطبيقات. للحصول على مزيد من المعلومات حول الوحدة النمطية، راجع دليل الوحدة النمطية json.

ملاحظة: للحصول على مزيد من المعلومات حول كيفية تثبيت وحدات Python النمطية، راجع تثبيت وثائق وحدات Python النمطية.

إنشاء رمز مميز

يجب إستخدام واجهة برمجة التطبيقات (API) المسماة Authentication API لإنشاء رمز مميز جديد.

واجهة برمجة تطبيقات المصادقة:

POST      https://

/dna/system/api/v1/auth/token

من المهم الإشارة إلى أن الرمز المميز الذي يتم إنشاؤه صالح لمدة ساعة واحدة. بعد 1 ساعة، يجب إنشاء رمز مميز جديد باستخدام واجهة برمجة التطبيقات (API) نفسها المذكورة أعلاه.

في ملف Python جديد، قم باستيراد الوحدات النمطية (الطلبات، base64 و json) متبوعة بإنشاء أربعة متغيرات:

import requests

import base64

import json

user = 'user'    # User to login to Catalyst Center

password = 'password'    # Password to login to Catalyst Center

token = ''    # Variable to store the token string

authorizationBase64 = ''   # Variable that stores Base64 encoded string of "username:password"

تدعم واجهة برمجة تطبيقات المصادقة المصادقة الأساسية كرمز مميز للتخويل في الرأس. المصادقة الأساسية هي طريقة يمكن إستخدامها للمصادقة على نقطة نهاية، توفر اسم مستخدم وكلمة مرور مفصولين بفاصلة (username:password). يتم تشفير كلا القيمتين من خلال base64، وتقوم نقطة النهاية بفك ترميز بيانات اعتماد تسجيل الدخول والتحقق، إذا كان المستخدم يستطيع الوصول أو لا.

لإنشاء السلسلة المؤمنة Base64 لاسم المستخدم وكلمة المرور، يتم إستخدام الوحدة النمطية base64. ولإنجاز ذلك، يتم إستخدام وظيفة التشفير B64Code.

byte_string = (f'{user}:{password}').encode("ascii")

authorizationBase64 = base64.b64encode(byte_string).decode()

من الرمز أعلاه، تم إنشاء متغير byte_string باستخدام الدالة '.encode("ascii"). وذلك لأن الدالة base64.b64encode تتطلب كائن يشبه البايت. لاحظ أيضا أن متغيرات المستخدم وكلمة المرور تم إستخدامها للاحتفاظ بتنسيق السلسلة 'user:password'. وأخيرا، تم إنشاء سلسلة بايت مرمزة من خلال base64 باستخدام المستخدم وكلمة المرور. باستخدام الطريقة 'decode()'، تم تحويل القيمة إلى كائن str.

للتحقق من ذلك، يمكنك طباعة القيمة لمتغير authorizationBase64:

print(authorizationBase64)

مثال على الإخراج:

am9yZ2QhbDI6Sm9yZ2VhbDXxXxXx

تحذير: ليس base64 خوارزمية تشفير. يجب ألا يتم إستخدامه لأغراض الأمان. كما تدعم واجهة برمجة تطبيقات المصادقة تشفير مفتاح AES كرمز مميز للتخويل في الرأس الذي يوفر المزيد من الأمان.

الآن أن base64 يرمز خيط كان خلقت يستعمل المستعمل وكلمة أن يصدق إلى، مادة حفازة مركز، هو وقت أن يباشر مع ال API صحة هوية API إستدعاء يستعمل الوحدة نمطية طلب. يسمح أيضا الدالة طلب، بالحصول على كائن إستجابة يحتوي على نص الطلب.

مشابك سيارات الأسلوب:

requests.request(“method”, “url”, **kwargs)

**kwargs يعني أي معلمة تم تمريرها إلى الطلب، على سبيل المثال، ملفات تعريف الارتباط وعملاء المستخدم والحمولة والرؤوس وما إلى ذلك.

تحدد واجهة برمجة تطبيقات المصادقة أن الطريقة هي POST، وURL هي "/dna/system/api/v1/auth/token" ويلزم تحديد المصادقة الأساسية في الرأس.

يتم إنشاء هذه المتغيرات لاستخدامها لدالة الطلب().

url = https://

/api/system/v1/auth/token

headers = {

‘content-type’: “application/json”,

‘Authorization’: ‘Basic ’ + authorizationBase64

}

بالنسبة لمتغير الرؤوس، تم تحديد أمرين. الأول هو نوع المحتوى، والذي يحدد نوع وسائط المورد المرسل إلى نقطة النهاية (يساعد ذلك نقطة النهاية على تحليل البيانات ومعالجتها بدقة). الثاني هو Authorization، والذي، في هذه الحالة، يتم إرسال AuthorizationBase64 (الذي يقوم بتخزين السلسلة المؤمنة للقاعدة 64) كمعلمة للمصادقة إلى مركز Catalyst.

الآن، قم بالمتابعة لاستخدام وظيفة الطلب () لإجراء إستدعاء API. يوضح الرمز التالي ترتيب الدالة:

response = requests.request(“POST”, url, headers=headers)

تم إنشاء متغير الاستجابة لتخزين بيانات إستدعاء API الذي تم إجراؤه.

لطباعة الاستجابة التي تم الحصول عليها، أستخدم وظيفة الطباعة مع طريقة النص() في متغير الاستجابة. يقوم النص () بإنشاء كائن str باستخدام الاستجابة التي تم تلقيها من مركز Catalyst.

print(response.text)

مثال على الإخراج:

{“Token”:“eyJhbGci0iJSUzI1NiIsInR5JK09s1zVmNjk0NjhkNTFhNDJ1ZWeLCU291cmNlIjoiaW50ZXJuYWwiLCW2vMPUbU0JNlqxOXNe1jMzY1LTQ5MWEtODljNC0yZmE2YjVhM2

!--- Output is supressed

ملاحظة: إذا كان Catalyst Center يستخدم شهادة موقعة ذاتيا، يمكن أن يفشل طلب واجهة برمجة التطبيقات مع الخطأ التالي:

requests.exceptions.SSLError: HTTPSConnectionPool(host='X.X.X.X', port=443): Max retries exceeded with url: /api/system/v1/auth/token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1000)')))

لإصلاح هذه المشكلة، تحتاج إلى إضافة معلمة التحقق من الصحة ك خطأ إلى وظيفة الطلب. يتجاهل هذا التحقق من شهادة SSL من نقطة النهاية (Catalyst Center).

response = requests.request(“POST”, url, headers=headers, verify=False)

من الاستجابة التي تم تلقيها من إستدعاء مصادقة API، لاحظ أن الهيكل مماثل لقاموس في Python على أي حال، وأنه كائن str.

للتحقق من نوع كائن، أستخدم الدالة type().

print(type(response.text))

الذي يرجع المخرج التالي:

لأغراض عملية، فقط الرمز المميز يحتاج أن يكون استخرجت من الإستجابة إستلمت من ال API، وليس السلسلة بأكملها، لأن، in order to استعملت الآخر مادة حفازة مركز APIs، فقط الرمز المميز ينبغي كنت تمرر كمعلمة.

بما أن الاستجابة التي تم تلقيها من إستدعاء API تحتوي على بنية مماثلة لقاموس في Python ولكن نوع الكائن هو STR، فإن الكائن المذكور يحتاج إلى أن يتم تحويله إلى قاموس باستخدام وحدة json. يستخرج هذا قيمة الرمز المميز من السلسلة الكاملة التي تم تلقيها من واجهة برمجة التطبيقات (API).

للقيام بذلك، تقوم الدالة json.load() بتحويل السلسلة إلى قاموس لاستخراج قيمة الرمز المميز فقط لاحقا وتعيينها مباشرة إلى متغير الرمز المميز الخاص بنا.

token = json.loads(response.text)  # Converting the response.text string value into a dictionary (It is creating a JSON object).

token = (token["Token"])  # Extracting just the token value by specifying the key as a parameter.

للتحقق من أن متغير الرمز المميز يحتوي على الرمز المميز فقط كقيمة له، انتقل إلى طباعته.

print(token)

مثال على الإخراج:

eyJhbGci0iJSUzI1NiIsInR5JK09s1zVmNjk0NjhkNTFhNDJ1ZWeLCU291cmNlIjoiaW50ZXJuYWwiLCW2vMPUbU0JNlqxOXNe1jMzY1LTQ5MWEtODljNC0yZmE2YjVhM2

!--- Output is supressed

تلميح: بما أن كل رمز مميز تم إنشاؤه ينتهي في ساعة واحدة بشكل افتراضي، فيمكن إنشاء أسلوب Python يحتوي على الرمز لإنشاء رمز مميز واستدعاؤه في كل مرة تنتهي فيها مدة صلاحية الرمز المميز، بدون الاضطرار إلى تشغيل البرنامج بالكامل عن طريق إستدعاء الأسلوب الذي تم إنشاؤه.

إختبار API

الآن بعد تعيين الرمز المميز بنجاح إلى متغير الرمز المميز، يمكن إستخدام واجهات برمجة تطبيقات Catalyst Center المتوفرة.

في هذه الحالة، يتم إختبار واجهة برمجة تطبيقات ملخص تكوين عقد مركز بنية الشبكة الرقمية (DNA) من Cisco.

ملخص تكوين عقد مركز بنية الشبكة الرقمية من Cisco

GET     https://

/dna/intent/api/v1/nodes-config

توفر واجهة برمجة التطبيقات (API) هذه تفاصيل حول التكوين الحالي ل Catalyst Center مثل، خادم NTP الذي تم تكوينه، اسم العقدة، إرتباط داخل نظام المجموعة، وضع LACP، وما إلى ذلك.

يحدد Cisco DNA Center Node Configuration Summary API، في هذه الحالة، أن الطريقة المستخدمة هي GET، URL هو /dna/intent/api/v1/node-config"، ونظرا لأنه قد تم إستخراج سلسلة الرمز المميز وتخصيصها لمتغير الرمز المميز، فإن هذه المرة يتم تمرير الرمز المميز كمتغير في رأس إستدعاء API X-Auth-Token': متبوعة بالرمز المميز.

يقوم هذا بمصادقة الطلب على Catalyst Center لكل إستدعاء API يتم إجراؤه. تذكر أن كل رمز مميز يستغرق ساعة واحدة. بعد 1 ساعة، يجب إنشاء رمز مميز جديد لمتابعة إجراء مكالمات API إلى Catalyst Center.

تابع إلى إنشاء المتغيرات لاختبار API:

nodeInfo_url = "https://

/dna/intent/api/v1/nodes-config"

nodeInfo_headers = {

'X-Auth-Token': token

}

nodeInfoResponse = requests.request("GET", nodeInfo_url, headers=nodeInfo_headers)

تم إنشاء المتغير nodeInfo_url لتخزين عنوان URL لواجهة برمجة التطبيقات الخاصة بنا. يقوم المتغير nodeInfo_headers بتخزين رؤوس واجهة برمجة التطبيقات الخاصة بنا. في هذه الحالة، تم تمرير 'X-Auth-Token:' ومتغير الرمز المميز كمعلمات لمصادقة الطلب بنجاح إلى Catalyst Center. وأخيرا، يقوم المتغير nodeInfoResponse بتخزين إستجابة واجهة برمجة التطبيقات.

للتحقق من صحة الاستجابة المتلقاة، يمكنك إستخدام وظيفة الطباعة().

مثال على الإخراج:

{"response": {"nodes": [{"name": "Catalyst Center", "id": "ea5dbec1-fbb6-4339-9242-7694eb1cXxXx", "network": [{"slave": ["enp9s0"], "lacp_supported": true, "intra_cluster_link": false, "interface": "enterprise", "inet6": {}, "inet": {"routes": [{"netmask": "255.255.0.0"

!--- Output is supressed

ملاحظة: في حالة إستخدام شهادة موقعة ذاتيا في Catalyst Center، يمكن أن يفشل طلب واجهة برمجة التطبيقات مع الخطأ التالي:

requests.exceptions.SSLError: HTTPSConnectionPool(host='X.X.X.X', port=443): Max retries exceeded with url: /api/system/v1/auth/token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate in certificate chain (_ssl.c:1000)')))

لإصلاح هذه المشكلة، تحتاج إلى إضافة معلمة التحقق من الصحة ك خطأ إلى الطلب. يمنع هذا التحقق من شهادة SSL من نقطة النهاية (Catalyst Center).

nodeInfoResponse = requests.request("GET", nodeInfo_url, headers=nodeInfo_headers, verify=False)

قد يكون من الصعب قراءة الاستجابة التي تم تلقيها من واجهة برمجة التطبيقات. باستخدام وحدة json() النمطية، يمكن طباعة الاستجابة في سلسلة أكثر قابلية للقراءة. أولا، يجب تحميل إستجابة واجهة برمجة التطبيقات إلى كائن JSON باستخدام الدالة json.load() التي يتبعها الدالة json.dumps():

jsonFormat = (json.loads(nodeInfoResponse.text)) # Creating a JSON object from the string received from the API response.

print(json.dumps(jsonFormat, indent=1)) # Printing the response in a more readable string using the dumps() function.

json.dumps: ترجع هذه الدالة كائن JSON الذي تم أخذه كمعلمة في سلسلة JSON المنسقة.

مسافة بادئة: تحدد هذه المعلمة مستوى المسافة البادئة لسلسلة JSON المنسقة.

مثال على الإخراج:

{

"response": {

"nodes": [

{

"name": "X.X.X.X",

"id": "ea5dbec1-fbb6-4339-9242-7694eb1xXxX",

"network": [

{

"slave": [

"enp9s0"

],

"lacp_supported": true,

"intra_cluster_link": false,

!--- Output is supressed

واجهات برمجة التطبيقات (API) مع معلمات الرأس

هناك بعض واجهات برمجة التطبيقات التي تتطلب إرسال بعض المعلمات في الرأس للعمل كما هو متوقع. في هذه الحالة، يتم إختبار واجهة برمجة تطبيقات Get Client Enrichment Details (واجهة برمجة التطبيقات).

GET        https://

/dna/intent/api/v1/client-enrichment-details

للتحقق من معلمات الرؤوس المطلوبة لواجهة برمجة التطبيقات للعمل كما هو متوقع، انتقل إلى منصة > Developer Toolkit > APIs > الحصول على تفاصيل إثراء العميل وانقر فوق اسم واجهة برمجة التطبيقات. تفتح نافذة جديدة وتعرض تحت خيار المعلمات معلمات الرؤوس المطلوبة لعمل واجهة برمجة التطبيقات.

في هذه الحالة، بالنسبة للمعلمة entity_type، وفقا للوصف، يمكن أن تكون القيمة network_user_id أو mac_address ويجب أن تحتوي المعلمة entity_value على قيمة نوع الوحدة التي تم تعريفها.

لمتابعة ذلك، تم تحديد متغيرين جديدين، entity_type وentity_value مع قيمهما المقابلة:

entity_type = 'mac_address'   #This value could be either 'network_user_id' or 'mac_address'.

entity_value = 'e4:5f:02:ff:xx:xx'    #Depending of the 'entity_type' used, need to add the corresponding value for 'entity_value'. In this case, 'mac_address' value was chosen for 'entity_type' parameter so, a MAC Address was assigned to the 'entity_value' parameter.

يتم إنشاء متغيرات جديدة أيضا لتنفيذ إستدعاء API. يتم تخزين عنوان URL الخاص باستدعاء API في متغير userEnrichment_url. يتم تخزين الرؤوس في متغير userEnrichmentHeaders. يتم تخزين الاستجابة المتلقاة في متغير UserEnrichmentResponse.

userEnrichment_url = "https://

/dna/intent/api/v1/user-enrichment-details"

userEnrichmentHeaders = {

'X-Auth-Token': token,

'entity_type': entity_type,

'entity_value': entity_value,

}

userEnrichmentResponse = requests.request("GET", userEnrichment_url, headers=userEnrichmentHeaders)

كما يمكنك أن ترى، من userEnrichmentHeaders، تم تمرير entity_type وentity_value كمعلمات رأس لاستدعاء API، مع متغير token.

للتحقق من صحة الاستجابة المتلقاة، أستخدم وظيفة الطباعة().

print(userEnrichmentResponse.text)

مثال على الإخراج:

[ {

"userDetails" : {

"id" : "E4:5F:02:FF:xx:xx",

"connectionStatus" : "CONNECTED",

"tracked" : "No",

"hostType" : "WIRELESS",

"userId" : null,

"duid" : "",

"identifier" : "jonberrypi-1",

"hostName" : "jonberrypi-1",

"hostOs" : null,

"hostVersion" : null,

"subType" : "RaspberryPi-Device",

"firmwareVersion" : null,

"deviceVendor" : null,

"deviceForm" : null,

"salesCode" : null,

"countryCode" : null,

"lastUpdated" : 1721225220000,

"healthScore" : [ {

"healthType" : "OVERALL",

"reason" : "",

"score" : 10

}, {

"healthType" : "ONBOARDED",

"reason" : "",

"score" : 4

!--- Output is suppressed

واجهات برمجة التطبيقات (API) مع معلمات الاستعلام

يمكن إستخدام معلمات الاستعلام لتصفية عدد معين من النتائج التي تم إرجاعها بواسطة API. تتم إضافة هذه المعلمات إلى URL الخاص ب API.

تم إختبار إستدعاء واجهة برمجة تطبيقات الحصول على قائمة الأجهزة.

GET          https://10.88.244.133/dna/intent/api/v1/network-device

ترجع واجهة برمجة تطبيقات الحصول على قائمة الأجهزة (API) قائمة بجميع الأجهزة التي تتم إضافتها في مركز Catalyst. في حالة طلب تفاصيل لجهاز معين، يمكن لمعلمات الاستعلام المساعدة في تصفية معلومات محددة.

للتحقق من معلمات الاستعلام المتوفرة ل API، انتقل إلى Platform > Developer Toolkit > APIs > الحصول على قائمة الأجهزة وانقر فوق اسم واجهة برمجة التطبيقات. تفتح نافذة جديدة وتعرض ضمن خيار المعلمات معلمات الاستعلام المتاحة ل API.

في هذا المثال، يتم إستخدام معلمات استعلام managementIpAddress وserialNumber (مع مراعاة أن ذلك غير ضروري لاستخدام جميع معلمات الاستعلام لاستدعاء API). قم بالمتابعة لإنشاء القيم المقابلة وتعيينها لكل من معلمات الاستعلام.

managementIpAddress = '10.82.143.250'

serialNumber = 'FDO25160X9L'

كما ذكر أعلاه، تتم إضافة معلمات الاستعلام في عنوان URL الخاص ب API، وتحديدا في نهايته، باستخدام ‘؟’ متبوعة بمعلمات الاستعلام.

في حالة إستخدام معلمات استعلام متعددة، يتم وضع علامة '& ' بينهما لتكوين ما يسمى سلسلة استعلام.

يوضح المثال التالي كيفية إضافة معلمات الاستعلام إلى متغير deviceListUrl الذي يقوم بتخزين عنوان URL الخاص باستدعاء API.

deviceListUrl = "https://

/dna/intent/api/v1/network-device?managementIpAddresss=" + managementIpAddress + "&serialNumber=" + serialNumber

لاحظ أن المتغيرات التي تم إنشاؤها مسبقا تم إلحاقها بسلسلة عنوان URL. بمعنى آخر، السلسلة الكاملة لعنوان الربط تبدو كما يلي:

deviceListUrl = "https://

/dna/intent/api/v1/network-device?managementIpAddresss=10.82.143.250&serialNumber=FDO25160X9L"

تابع إستدعاء API، يتم إنشاء متغير deviceListHeaders لتخزين رؤوس API مع متغير الرمز المميز الذي تم تمريره كمعلمة ويقوم المتغير deviceListResponse بتخزين إستجابة API.

deviceListHeaders = {

'X-Auth-Token': token,

}

deviceListResponse = requests.request("GET", deviceListUrl, headers=deviceListHeaders)

للتحقق من صحة الاستجابة المتلقاة، يمكنك إستخدام وظيفة الطباعة().

print(deviceListResponse.text)

مثال على الإخراج:

{"response":[{"family":"Switches and Hubs","description":"Cisco IOS Software [Cupertino], Catalyst L3 Switch Software (CAT9K_IOSXE), Version 17.9.4a, RELEASE SOFTWARE (fc3) Technical Support: http://www.cisco.com/techsupport Copyright (c) 1986-2023 by Cisco Systems, Inc. Compiled Fri 20-Oct-23 10:44 by mcpre","lastUpdateTime":1721205664979,"deviceSupportLevel":"Supported","softwareType":"IOS-XE","softwareVersion":"17.9.4a","serialNumber":"FDO25160X9L","inventoryStatusDetail":"

تلميح: لطباعة الاستجابة بطريقة أكثر قابلية للقراءة، يمكنك إستخدام الوظائف الموضحة في قسم واجهة برمجة التطبيقات (API) json.load() وjson.dumps().