2012年10月9日 星期二

asp 呼叫 .net 的 web service 以 "e政府服務平臺單一登入介接" 為例

asp 呼叫 .net 的 web service 以 "e政府服務平臺單一登入介接" 為例, 原來用 asp 呼叫 wsdl 還滿簡單的.


1. 認識一下 e政府服務平台(Government Service Platform, GSP):

單一登入介接說明

架構圖, 我猜主要應該要看左半邊.



單一登入介接的效益
  • 減少機關/業務重複開發成本:
    各機關業務建置入口網站及業務服務時,對使用者都有認證、授權的共同需求,使用平台的單一登入機制,可以縮短建置時間並減少開發成本。
  • 支援不同的認證方式:
    使用者可使用自然人/工商/機關憑證或一般帳號密碼為登入認證方式。
  • 使用相同的登入帳號、單一的入口網址及登入介面:
    使用者在存取各機關服務時可以不必註冊多個帳號密碼,以達簡化使用及電子化政府便民之目的。


Web Service 位址:
https://www.cp.gov.tw/SEWebApplication/RSMediator.asmx

在登入成功取得token1後,呼叫GetUserProfile傳入token1,取得
userprofile,內含<SecureLevel>可以判定使用者的登入方式
. <SecureLevel>值的意義如下:
. IDPassword:代表帳號密碼登入
. PlatformX509或AnonymousX509:代表憑證登入

單一登入介接說明
其實, 就是登入的 URL 都連到 www.cp.gov.tw , 再把登入後要連的 URL 放在 returnurl 參數裡即可.

登入完成, www.cp.gov.tw 會用 post 的方式把 token1 放在 twGovT1 這個參數傳給 returnurl 裡的程式.


2. 寫 asp 程式呼叫 wsdl:
參考看看下面2支副程式:


'// purpose: 取得 e政府服務平台註冊服務模組介接服務 web service.
function getGspServiceXml(byval twGovT1)
    dim returnValue
    returnValue = ""
    
    '// 設定 Web Service 位址:
    dim ws_HOST
    ws_HOST = "www.cp.gov.tw"
    dim ws_URL
    ws_URL = "https://"& ws_HOST &"/SEWebApplication/RSMediator.asmx"

    '// Web Service SOAP 內容:
    SoapRequestStr = ""
    SoapRequestStr = SoapRequestStr & "<?xml version=""1.0"" encoding=""utf-8""?>"
    SoapRequestStr = SoapRequestStr & "<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">"
    SoapRequestStr = SoapRequestStr & "<soap:Body>"
    SoapRequestStr = SoapRequestStr & "<GetUserProfile xmlns=""http://tempuri.org/"">"
    SoapRequestStr = SoapRequestStr & "<Token1>"& twGovT1 &"</Token1>"
    SoapRequestStr = SoapRequestStr & "</GetUserProfile>"
    SoapRequestStr = SoapRequestStr & "</soap:Body>"
    SoapRequestStr = SoapRequestStr & "</soap:Envelope>"

    '// 送出 SOAP
    dim SoapRequest
    Set SoapRequest = Server.CreateObject("MSXML2.XMLHTTP")
    SoapRequest.Open "POST", ws_URL & "?wsdl", False
    SoapRequest.setRequestHeader "Content-Type", "text/xml;charset=utf-8"
    SoapRequest.setRequestHeader "HOST","www.cp.gov.tw"
    SoapRequest.setRequestHeader "Content-Length",LEN(SoapRequestStr)
    SoapRequest.setRequestHeader "SOAPAction", "http://tempuri.org/GetUserProfile"
    on error resume next
    SoapRequest.Send(SoapRequestStr)
    if err.number <> 0 then
        '// debug, show error message
    else
        '// success.
        returnValue = SoapRequest.responseXML.xml
    end if
    getGspServiceXml = returnValue
    'set SoapRequest = nothing
end function

'// purpose: 取得 e政府服務平台註冊服務模組介接服務 web service 裡的內容.
function getGspDataByXPath(byval soap_return_xml, byval queryXPath)
    dim returnValue
    returnValue = ""
    dim soap_XML
    set soap_XML = server.createObject("Msxml2.DOMDocument")
    soap_XML.async = false
    soap_XML.loadXML(soap_return_xml)
    if soap_XML.parseError.reason <> "" then
        '// load soap xml error.
    else
        if not (soap_XML.documentElement.selectSingleNode("//GetUserProfileResult") is nothing) then
            dim ResultXml
            set ResultXml = server.createObject("Msxml2.DOMDocument")
            ResultXml.async = false
            ResultXmlString = trim("" & soap_XML.documentElement.selectSingleNode("//GetUserProfileResult").text)
            ResultXml.loadXML(ResultXmlString)
            if ResultXml.parseError.reason <> "" then
                '// load soap xml error.
            else
                returnValue = nulltext(ResultXml.selectSingleNode(queryXPath))
            end if
        end if
    end if
    getGspDataByXPath = returnValue
end function

function nullText(byref xNode)
    dim xstr
    xstr = ""
    if not (xNode is nothing) then
        xstr = xNode.text
    end if
    nullText = xStr
end function

主程式如下:
dim soap_return_xml
soap_return_xml = trim("" & getGspServiceXml(twGovT1))
if soap_return_xml <> "" then
    myData = getGspDataByXPath(soap_return_xml, myXPath)
else
    '// Error.
end if

呼叫完, 透過 token 從 web service 取到的 XML 內容如下:
SOAP 回應的XML內容

以我的個案, 要取得 email 來說, 
mailXPath = "//CPWSResponse/Result/UserProfile/ContactInfo/Mail"
mailData = getGspDataByXPath(soap_return_xml, mailXPath)

就可以取到 eMail, 由於我只有要取一次, 所以程式碼沒有寫的很有效率, 如果您要取的欄位很多, 可能要換一個寫法, 會比較有效率一點點.


附註:
如果要介接 e政府, 需要先填寫申請單:
1.e政府服務平臺服務介接申請表_SSO_Service Application.doc

如果沒有填, 就會出現下面的錯誤畫面:
domain name 還沒開通前的畫面.

要解決這個問題很簡單, 設一下 host 就解決了, 先用別的已經通過申請的  domain name即可.

之前 UI 是規畫 id/password 的輸入框是在客戶的網站上, 而不是連到 eGov  去登入, 挑戰直接 submit 到 eGov 的 https://www.cp.gov.tw/portal/Login.aspx, 結果會出現下面的錯誤訊息:
超有趣的錯誤訊息. ╰( ̄▽ ̄)╭

沒有留言:

張貼留言

Facebook 留言板