EP 2 : การ Integration ร่วมกับ Microsoft Dynamics 365 for Finance and Operations

--

สำหรับนักพัฒนาแล้ว คงหนีไม่พ้นต้องเจอการทำ Integration Apps บล็อกนี้จึงมาแนะนำการ integrate หรือสร้าง api สำหรับเชื่อมต่อกับ Microsoft Dynamics 365 for Finance and Operations (ซึ่ง 2 วิธีการที่จะแนะนำในวันนี้ ใช้บ่อยมาก)

1. OData Service

OData เป็นโปรโตคอลมาตรฐานสำหรับการดึงข้อมูล ที่สามารถเข้าถึงได้ด้วยเทคโนโลยี HTTP และ JSON, OData service จะถูก public และใช้งานได้ทันที เมื่อเรา build application ผ่านเงื่อนไข Data Entities ที่ IsPublic = Yes

วิธีการใช้งานคือ http://[baseURI]/data , รายการที่แสดงขึ้นมาทั้งหมด คือ data entities ที่เราสามารถเรียกใช้งานได้ เช่น หากเราต้องการข้อมูลลูกค้า ก็ / ต่อท้ายได้เลย http://[baseURI]/data/Customers

รองรับคำสั่งตาม OData standards เช่น

  • ดูข้อมูลทุก Company ในระบบ

http://[baseURI]/data/Customers?cross-company=true

  • ดูข้อมูลเฉพาะ Company ทีเราสนใจ

http://[baseURI]/data/Customers?$filter=dataAreaId eq ‘thmf’&cross-company=true

  • กรองข้อมูลฟิลอื่นๆก็ได้เหมือนกัน (กลุ่มลูกค้ารหัส 20)

http://[baseURI]/data/Customers?$filter=dataAreaId eq ‘thmf’ and CustomerGroupId eq ‘20’&cross-company=true

และเชื่อมต่อกับตัวดึงข้อมูล OData ใน Power BI Desktop ได้อีกด้วย สะดวกมั่กๆ

… เกือบลืมไปอย่าง แวะมาดูการยืนยันตัวตนในการร้องขอใช้ API กันซักนิด

Authentication

OData Services, JSON-based Custom Service, and REST Metadata Service รองรับการยืนยันตัวตนแบบ OAuth 2.0 ดังนั้นเราต้องมาเตรียมตัวกันก่อน

OAuth — Authorization Code Grant Flow

จาก Flow เราต้องทำการ Register Application ที่ Microsoft Azure Active Directory (AAD) ก่อน เพื่อให้ได้ Authorization token มา (Link)

การ request ทุกครั้งจำเป็นต้อง call 2 ครั้ง ครั้งแรกนำ Authorization token ร้องขอไปยัง Azure AD เพื่อให้ได้ Access token มา (ซึ่งมีเวลาหมดอายุ), ครั้งที่สอง นำ Access token ที่ได้มาแนบไปกับการ request API ที่เราต้องการใช้งาน

ลองทดสอบโดยใช้ Postman

ก่อนทดสอบ setup Application (client) ID ที่ได้จาก AAD ในโปรแกรมก่อน

Request 1 : Access Token
POST : https://login.microsoftonline.com/:tenant_id/oauth2/token
Params
tenant_id:c4dc70b8–32c4–4443-afde-530521xxxxxx (ได้จาก AAD)
Body
grant_type:client_credentials
client_id:c8907ca6–09a6–40a6–83ce-e67a4xxxxx (ได้จาก AAD)
client_secret:.Ew2C94l?2elh/rLDszhHFFxxxxxxx (ได้จาก AAD)
resource:[baseURI]

Request 2 : Odata
GET : https://[baseURI]/data/Customers?$filter=dataAreaId eq ‘thmf’&$select=CustomerAccount,Name,AddressDescription,FullPrimaryAddress&cross-company=true
Headers
Authorization:Bearer xxxxxxxxx (จาก access_token Request 1)
Content-Type:application/json
Tests
var json = JSON.parse(responseBody);
tests[“Get customer info”] = !json.error && responseBody !== ‘’ && responseBody !== ‘{}’;

  • ข้อจำกัดของ api คือ URL ที่อยู่ใน VM จะไม่สามารถทดสอบได้ ต้องเป็น URL on-cloud หรือ on premises เท่านั้น

2. JSON-based custom service

เป็น custom service ที่เราสามารถสร้างเองได้จาก X++ classes หรือการเขียนโปรแกรมนั่นเอง มีการรับค่าและรีเทิร์นค่าแบบ JSON (JavaScript Object Notation), ทุก service ที่ถูก custom ขึ้นมา จะถูก deploy เป็น 2 endpoint เสมอ

  • SOAP endpoint

https://<baseurl>/soap/services/UserSessionService?wsdl

  • JSON endpoint

https://<baseurl>/api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo

ตัวอย่างในวันนี้จะเป็นการสร้าง api อย่างง่ายในการเปิดใบสั่งขาย หรือ sales order มาเริ่มกันเลย (coding หน่อยๆ)

ส่วนประกอบของ Object (แอบ Tie-in เบาๆ อิอิ)

Class contract สำหรับดูแลเรื่อง parameter ซึ่งในที่นี้เราให้เป็น List ของรายการสินค้าและจำนวน

[DataContractAttribute]public class QERP_SalesOrderContract{   ItemId itemId;   Qty qty;   [DataMemberAttribute]   public ItemId itemId(ItemId _itemId = itemId)   {      itemId = _itemId;      return itemId;   }   [DataMemberAttribute]   public Qty qty(Qty _qty = qty)   {      qty = _qty;      return qty;   }}

Class info สำหรับ return สถานะและรายละเอียด

[DataContractAttribute]public class QERP_SalesOrderInfo{   boolean success;   str message;   [DataMemberAttribute]   public boolean success(boolean _success = success)   {      success = _success;      return success;   }   [DataMemberAttribute]   public str message(str _message = message)   {      message = _message;      return message;   }}

Class service สำหรับสร้าง sales order

public class QERP_SalesOrderService{[AifCollectionTypeAttribute('salesLineList', Types::Class, classStr(QERP_SalesOrderContract)), SysEntryPointAttribute(true)]public QERP_SalesOrderInfo CreateSalesOrder(DataAreaId dataArea, CustAccount customer, List salesLineList){   QERP_SalesOrderInfo messageInfo = new QERP_SalesOrderInfo();   QERP_SalesOrderContract salesLineData;   SalesTable salesTable;   SalesLine salesLine;   NumberSeq numberSeq;   ListIterator literatorset;   ttsbegin;   changecompany(dataArea)   {   numberSeq = NumberSeq::newGetNum(SalesParameters::numRefSalesId());   salesTable.SalesId = numberSeq.num();   salesTable.initValue();   salesTable.CustAccount = customer;   salesTable.initFromCustTable();   salesTable.insert();   literatorset = new ListIterator(salesLineList);   while (literatorset.more())   {      salesLineData = literatorset.value();      salesLine.clear();      salesLine.SalesId = salesTable.SalesId;      salesLine.ItemId = salesLineData.itemId();      salesLine.SalesQty = salesLineData.qty();      salesLine.createLine(NoYes::Yes, // Validate                   NoYes::Yes, // initFromSalesTable                   NoYes::Yes, // initFromInventTable                   NoYes::Yes, // calcInventQty                   NoYes::No, // searchMarkup                   NoYes::No); // searchPrice      literatorset.next();   }   }   ttscommit;   messageInfo.success(true);   messageInfo.message(strFmt("Sales order '%1' has been created.", salesTable.SalesId));   return messageInfo;   }}

เมื่อ Build application เราก็จะได้ API เรียบร้อย

ทดสอบ request

ใช้ tools ประเภท SoapUI ก็ได้เหมือนกันนะ

จบ…

--

--

Teerapong Mukdapipatkul (Bee) 😄

Microsoft Dynamics 365 Developer at QUICK ERP and Co-Founder at Analytic Business Solutions linkedin.com/in/teerapong-muk