標籤:解決方案 style uri height public 規律 private 執行個體化 html
概要說明
電子樞紐全稱國家交通運輸物流公用資訊平台,主要提供物流及生產企業進行物流相關資料交換的標準和API,詳細介紹可參考其官網www.logink.org,本文假定閱讀者對該平台已有瞭解,並已成功申請了相應的帳號和資料交換服務。
信用中心是電子樞紐眾多資料服務中的一個,提供物流參與者信用資訊的上傳和查詢,包括運輸車輛、從業人員等。官方的樣本和介紹大多以Java為主,.net的非常少,希望本文可以協助.net開發人員快速掌握資料交換方式。
電子樞紐的資料服務分為兩種,一種稱為資料交換,另一種稱為服務調用。
資料交換是一種類似電子郵件的行為,可以把電子樞紐看作是一個郵件伺服器,發送和接收資料就與收發電子郵件的方式類同。
服務調用就是常規的HTTP請求,主要用於向電子樞紐查詢資訊,例如對於信用中心來說,可以查詢到車輛的運政資訊、誠信記錄等。
本文主要介紹的是服務調用方式,要調用電子樞紐提供的服務,首先必須確保已經開通了相關服務,開通後還需要獲得服務的ID,這些任務都可以從電子樞紐的使用者管理中心完成。
在調用服務前,必須獲得使用者驗證的令牌(Access Token),這項工作可通過統一認證服務完成,獲得令牌後,方可憑令牌調用相關服務。
引入服務
電子樞紐的資料介面都是以Web Service提供的,所以在開始編碼之前,可以先引入相關的服務,在VS裡直接加入服務參考即可,相關的服務地址可以在官網的開放接入中心找到。
值得注意的是,雖然電子樞紐提供的大部分Web Service都可以在VS中直接引入,但還有個別不能採用這種“加入服務參考”的方式,目前已知的就是信用中心服務。對於這種情況,需要在VS中以Web引用的方式來添加,具體方法如下。
右鍵點擊解決方案瀏覽器中項目或引用(Reference)的節點,在菜單中選擇“加入服務參考”(Add Service Reference),在彈出的對話方塊裡點擊“進階”(Advanced),再在彈出的服務引用設定對話方塊裡點擊“添加Web引用”(Add Web Reference)即可調出添加Web引用的對話方塊。
至於為什麼要這樣,由於我對SOAP和WCF沒有太多瞭解,實在沒法回答這個問題,希望這方面的大神可以給出解答。
存取碼
引用添加完以後,VS會為我們自動產生好相應的類型,直接使用就可以。
首先是擷取令牌,統一驗證服務的用戶端類型是AuthenServiceClient,執行個體化以後調用他的authenticate方法,方法簽名如下:
authenticate(string applicant, string userid, string password, string resource)
關於這個方法的具體說明,可參考官方說明。
傳回值的tokenValid屬性指示是否驗證成功,如果為true,可通過token屬性擷取令牌的值。範例程式碼如下:
1 private bool Authenticate(LoginkUser user, string resId, out string token) 2 { 3 AuthenServiceClient clnt = new AuthenServiceClient(); 4 5 var result = clnt.authenticate(user.ExchangeCode, user.ExchangeCode, user.Password, resId); 6 7 if (result.tokenValied) 8 token = result.token; 9 else10 token = null;11 12 clnt.Close();13 14 return token != null;15 }
得到令牌以後,就可以直接調用信用中心的查詢服務了,VS產生的信用中心服務的用戶端類型為LoginkServiceService,執行個體化後調用它的InterfaceName方法。
genericResult InterfaceName(authentication Authentication, publicInformation PublicInformation, string BusinessInformation)
這個方法沒有找到官方的文檔,由於各個參數比較複雜,就不一一介紹了(其實我自己也沒搞明白),直接照抄下面的樣本就可以了。
1 private string CallCreditService(LoginkUser user, string token, string action, string request) 2 { 3 var css = _settings.CreditService; 4 5 Logink.Services.Credit.security security = new Logink.Services.Credit.security(); 6 security.LogisticsExchangeCode = user.ExchangeCode; 7 security.UserTokenID = token; 8 9 Logink.Services.Credit.authentication authentication = new Logink.Services.Credit.authentication();10 authentication.UserName = user.ExchangeCode;11 authentication.UserPassword = user.Password;12 authentication.ServiceId = css.ResourceId;13 authentication.UserId = user.ExchangeCode;14 15 Logink.Services.Credit.publicInformation publicInformation = new Logink.Services.Credit.publicInformation();16 publicInformation.ServiceType = "3";17 publicInformation.ActionType = action;18 19 Logink.Services.Credit.LoginkServiceService service = new Logink.Services.Credit.LoginkServiceService();20 service.Url = css.Url;21 service.Security = security;22 23 var result = service.InterfaceName(authentication, publicInformation, request);24 25 if (result.ResultCode)26 {27 return result.BusinessInformation;28 }29 else30 throw new ExchangeException(result.ExceptionInformationCode, result.ExceptionInformation);31 }
樣本中這個CallCreditService方法已經封裝了調用信用中心服務的各種參數,其中action參數表示業務類型,官網有介紹,下面再詳細說下request參數。
request參數實際上是個經過Base64編碼的XML字串,XML的內容就是各個傳入參數的值,需要注意的是,傳入的這個XML串並不是完整的文檔,而是根節點以下的內容,千萬不要把根節點也傳上來,如果你使用XmlDocument來處理傳入參數,可以使用根節點的InnerXml屬性。
Base64編碼相對來說就比較簡單了,System.Convert類型直接支援轉換為Base64,預設情況下電子樞紐使用的是UTF8編碼,在編/解碼時不要搞錯,否則會查不到資料或出現亂碼。
1 private string XmlToBase64(string xml)2 {3 if (string.IsNullOrEmpty(xml))4 return xml;5 6 return Convert.ToBase64String(Encoding.Utf8.GetBytes(xml));7 }
最後,需要處理的是InterfaceName的傳回值,傳回值的ResultCode指示是否調用成功,如果不成功可通過ExceptionInformationCode屬性擷取錯誤碼,否則可以通過BusinessInformation屬性擷取返回的文本。
返回的文本同樣是一個Base64編碼的XML字串,轉換成明文以後就可以直接使用了,不過對於明文的處理是一件比較頭痛的事,經過多次實驗最終摸索出以下的規律。
文本為空白串:可能是沒有查詢到相關的內容。
文本不是XML:儘管ResultCode為true,但仍舊可能是出現了錯誤,文本的內容就是出錯資訊。
對於這些情況,我們的程式都應該進行相應的處理。
1 public XmlDocument QueryCredit(QueryParameters parameters) 2 { 3 if (parameters == null) 4 throw new ArgumentNullException(nameof(parameters)); 5 6 AccessToken token; 7 string data; 8 bool forceRenewToken = false; 9 10 retry:11 12 // 通過統一驗證服務擷取使用者的存取權杖13 token = GetToken(_user, _settings.CreditService.ResourceId, forceRenewToken);14 15 // 將傳入參數序列化為XML16 data = parameters.GetXml();17 // 對XML轉換為BASE64編碼18 data = XmlToBase64(data);19 20 try21 {22 // 調用信用中心的Web Service23 data = CallCreditService(_user, token.Value, parameters.ActionName, data);24 }25 catch(ExchangeException ee)26 {27 // 判斷是否需要更新令牌28 if (ee.IsTokenInvalid && !forceRenewToken)29 {30 forceRenewToken = true;31 goto retry;32 }33 else34 throw;35 }36 37 if (!string.IsNullOrEmpty(data))38 {39 // 返回的內容已做了BASE64編碼處理,將它轉換為XML。40 data = Base64ToXml(data);41 42 // 部分情況下平台返回的可能是一串錯誤資訊而非XML,因此對不是"<"開頭的直接按錯誤資訊處理。43 if (data[0] == ‘<‘)44 {45 XmlDocument doc = new XmlDocument();46 doc.LoadXml(data);47 48 return doc;49 }50 else51 throw new ExchangeException(data);52 }53 else54 {55 // 如果返回的內容為空白,可能是沒有查到相關資料。56 throw new ExchangeException("110008", "暫時沒有查到相應資料");57 }58 59 }
到些為止,調用信用中心服務所需的代碼都已經大致做了介紹,把它們串起來以後就形成了一個完整的程式,全部原始碼請點擊此處。由於我的電腦上裝的是VS2015,低版本的VS可能沒辦法開啟,實在抱歉。
相關資源
幾個必須加入的QQ群
213604083:平台接入群,這是必加的一個群,有很多平台的管理員在裡面,一些基礎的問題可以問問他們,當然還有一點很重要的是群裡有開發所需要的許多資源。
383412768:信用接入群,如果要使用信用中心服務,這就是你要找的組織。
363016382:園區通接入群,如果你是為了接入而接入(你懂的),那這裡是也是必須的。
601484722:充裝資料接入群。
用.net訪問電子樞紐信用中心的資料查詢服務