Çalıştığım AX partner AGC Yazılım'daki bir müşterimizin hizmet aldığı servis Rest Api kullanıyordu. Forumlarda AX 2012 için yazılmış değişik örnekler buldum fakat hiçbirini çalıştırmayı başaramadım. O noktada baştan başlamaya karar verdim.
Önce bilgisayarıma Postman'ın ücretsiz versiyonunu yükledim. Postman ile müşterinin servisini kullanmayı başardım.
Daha sonra Postman'ın C# RestSharp kütüphanesi kodu üretme özelliğiyle C# koduna sahip oldum:
Bu kodu AX ile deploy edilebilecek bir koda çevirmeden önce projeme RestSharp kütüphanesini import etmem gerekiyordu. Visual Studio 2013 Package Manager Console ile aşağıdaki komutu yazıp import etmeye çalıştığımda
Install-Package RestSharp
"The underlying connection was closed: An unexpected error occurred on a send." hatası aldım. Hatanın çözümünü bir forum sayfasında buldum. Aşağıdaki kodu bir .REG dosyasına yazıp çalıştırınca artık Nuget pakedi yüklenebiliyordu:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319]
"SchUseStrongCrypto"=dword:00000001
Bir başka forum sayfasından Visual Studio 2013 ile çalışan son RestSharp versiyonunu öğrendim ve import edebildim:
Install-Package RestSharp -Version 103.1.0
Artık çalışan ve AX içinde deploy edebildiğim bir kodum vardı:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RestSharp;
namespace Ingenico
{
public class Ingenico
{
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Body { get; set; }
public string Idx { get; set; }
public string getPaymentSummaryReport()
{
var client = new RestClient("https://XXXXXXXXXXXXXXX/GetPaymentSummaryReport");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Operator", "XXXXXXX");
request.AddHeader("Authorization", "Basic XXXXXXX");
request.AddHeader("Content-Type", "application/json");
Body = "{\r\n\"ReportId\": "+Idx+",\r\n\"SerialList\": [\r\n\"\"\r\n],\r\n\"StartDate\": \""+StartDate+
"\",\r\n\"EndDate\": \""+EndDate+
"\",\r\n\"ExternalField\": \"\",\r\n\"ReceiptNo\": 0,\r\n\"ZNo\": 0,\r\n\"GetSummary\": true,\r\n\"SaleFlags\": 0,\r\n\"DeviceGroupName\": \"\"\r\n}\r\n \r\n";
request.AddParameter("application/json",Body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
return response.Content;
}
}
}
Kodu deploy edip AX içinde çalıştırmaya kalktığımda proje klasöründeki RestSharp.DLL ve RestSharp.XML dosyalarını da aradığını ve AX'ın bunları bin klasörüne kopyalamadığını gördüm. Bu dosyaları server ve client bin klasörlerine kopyaladım:
Artık servise erişebiliyordum:
Ingenico.Ingenico o = new Ingenico.Ingenico();
str a;
try
{
o.set_StartDate("2020-10-01");
o.set_EndDate("2020-10-01");
o.set_Idx("111111111111");
a = o.getPaymentSummaryReport();
info(a);
Gelen Json stringi çözümleyebilmek için de yine bir blogdan faydalandım.
class AGCingenico
{
Array jsonArray;
}
Önce bu metod ile json string çözümleniyor:
void parseJson(str _json)
{
Array jsonArray;
container con;
int jsonSubstrNo, i;
TextBuffer textBuffer;
Array returnArray = new Array(Types::Class);
#Define.LBracket('{')
#Define.RBracket('}')
str st;
int fnd;
fnd = strScan(_json,"]",1,strLen(_json));
st="{"+subStr(_json,fnd+2,strlen(_json) - fnd -1);
con+=st;
// extract the json substrings and add them to a Array
textBuffer = new TextBuffer();
textBuffer.setText(_json);
while (textBuffer.nextToken(0, #LBracket+#RBracket))
{
if ((jsonSubstrNo mod 2) > 0)
{
st =#LBracket + textBuffer.token() + #RBracket;
con += st;
}
jsonSubstrNo++;
}
for (i = 1; i <= conLen(con); i++)
{
returnArray.value(i, RetailCommonWebAPI::getMapFromJsonString(conPeek(con, i)));
}
jsonArray = returnArray;
}
Daha sonra bu metod ile tabloya atıyorum:
void jsonToTable()
{
MapIterator mi;
Map data;
int i;
str value;
for (i = 1; i <= jsonArray.lastIndex(); i++)
{
data = jsonArray.value(i);
mi = new MapIterator(data);
tmpTable.clear();
while (mi.more())
{
value = data.lookup(mi.key());
switch (mi.key())
{
case "ErrCode":
this.parmErrCode(str2int(value));
break;
case "ErrDesc":
this.parmErrStr(value);
break;
case "Amount":
tmpTable.Amount = str2num_RU(value);
break;
case "AmountCredit":
tmpTable.AmountCredit = str2num_RU(value);
break;
...
...
...
Bütün iş bitti derken son bir sürprizle daha karşılaştım. Client tarafında düzgün çalışan kod CIL içinde tip dönüştürmeyle ilgili bir hata veriyordu. Bunun çözümünü de yine bir forum sayfasından buldum. Martin Drab çözümü nokta atışı veriyordu. RetailCommonWebAPI sınıfında aşağıdaki düzeltmeyi yaptım ve başka hata kalmamıştı:
//AGC memre 29.9.20
//private static Map getMap(CLRObject _dict)
private static Map getMap(System.Collections.IDictionary _dict)
//http://dev.goshoom.net/en/2016/01/x-to-cil-object-must-implement-iconvertible/#comment-135186
//AGC memre
{
Sonuç olarak AX 2012 ile Rest Api kullanımı her ne kadar kolay olsa da ortamı uyarlayana kadar çeşitli pürüzler çıkıyor, neyse ki forumlar ve bloglar var. :)