最近在忙一個酒店預訂系統項目,已集成API XML,但是提交酒店訂單到API之后,訂單的狀態要實行與API同步。因為可能下一分鍾,API的訂單狀態可能已經確認,但本地訂單狀態還是 處理當中的。
當客人打開某個訂單詳細信息的時候,再去Call 一次API的狀態。這是既傳統,又笨的方法。
但是問題 接踵而至
1. 訂單處理既然不及時,又不准時。
2. API提供商不給單條記錄去同步狀態。
等等。
詳細解決方案:
用SSIS 設計 腳本任務, 再部署SSIS包任務,每2分鍾Call一次API。
步驟:
1.生成Post XML代碼
T-SQL CODE
ALTER proc [dbo].[BookingXML] as declare @XmlOutput xml declare @a nvarchar(max) set @XmlOutput = ( select distinct a.APICode as hmcref from dbo.HotelBooking a left join dbo.sys_Procduct b on a.FID=b.FID where isnull(a.APICode,'')<>'' and isnull(a.APIStatus,'') in ('IC','CA','OR') --and a.BDT>=Getdate() and b.Del=0 FOR XML Path(''), ROOT('hmcreflist'), ELEMENTS) if cast(@XmlOutput as nvarchar(max))<>'' begin set @a = '<request><company>aa</company><id>bb</id><pass>cc</pass><lang>SIM</lang>{@Str}</request>' select cast(replace(@a, '{@Str}', cast(@XmlOutput as nvarchar(max))) as xml) end else begin select '' end
XML CODE
<request> <company>aa</company> <id>bb</id> <pass>cc</pass> <lang>SIM</lang> <hmcreflist> <hmcref>W2049850</hmcref> <hmcref>W2049856</hmcref> <hmcref>W2050473</hmcref> <hmcref>W2050522</hmcref> <hmcref>W2050593</hmcref> <hmcref>W2050594</hmcref> </hmcreflist> </request>
2.設計SSIS包
設置ResultSet XML
結果集 變量名稱為 user::XMLOutput 結果名稱為0
腳本任務
PrecompileScriptIntoBinaryCode 要設為False, 否則提示 “IDE未成生成二進制的錯誤”
ReadWriteVariables 設為sql 任務的ResultSet 的變量 XMLOutput
重點來了
點擊 “設計腳本”,使用HttpWebRequest用post發送請求,再用HtppWebResponse返回XML,再用根據訂單號update 狀態。
VB.net讀取sql server ResultSet變量
Dts.Variables("XMLOutput")
腳本任務鏈接Sql server數據庫, 原先在 連接管理設置有 AServ 名稱連接器,有腳本任務直接調用就行。
Dts.Connections.Item("AServ").AcquireConnection(Nothing) Dim conn As New SqlClient.SqlConnection(Dts.Connections.Item("AServ").ConnectionString)
注:用 IO.StreamWriter 生成操作和返回的日志,方便以后維護。
請把全局和腳體任務的MaximumErrorCount調大一點,這樣發生錯誤之后,會繼續執行任務。
完整的VB.net如下:
其中 Admin_UpdateBookingStatus 自定義訂單狀態處理儲存過程。
Imports System Imports System.IO Imports System.Net Imports System.Data Imports System.Text Imports System.Math Imports System.Xml Imports Microsoft.SqlServer.Dts.Runtime Public Class ScriptMain Public Sub Main() ' ' Add your code here ' 'Dts.TaskResult = Dts.Results.Success Dim XMLString As String = " " If Dts.Variables("XMLOutput").Value.ToString <> "" Then XMLString = Dts.Variables("XMLOutput").Value.ToString.Replace("<ROOT>", "").Replace("</ROOT>", "") XMLString = "<?xml version=""1.0"" encoding=""UTF-8"" ?>" + XMLString Dim request As WebRequest = WebRequest.Create("http://www.abc.com/api/ddd.php") ' Set the Method property of the request to POST. request.Method = "POST" ' Create POST data and convert it to a byte array. Dim postData As String = XMLString Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData) ' Set the ContentType property of the WebRequest. request.ContentType = "application/soap+xml; charset=utf-8" ' Set the ContentLength property of the WebRequest. request.ContentLength = byteArray.Length 'Get the request stream. Dim dataStream As Stream = request.GetRequestStream() ' Write the data to the request stream. dataStream.Write(byteArray, 0, byteArray.Length) ' Close the Stream object. dataStream.Close() ' Get the response. Dim response As WebResponse = request.GetResponse() ' Get the stream containing content returned by the server. dataStream = response.GetResponseStream() ' Open the stream using a StreamReader for easy access. Dim reader As New StreamReader(dataStream) Dim xmlDoc As New XmlDocument() xmlDoc.LoadXml(reader.ReadToEnd()) Dim HMCREF As XmlNodeList Dim STATUSCODE As XmlNodeList HMCREF = xmlDoc.SelectNodes("//HMCREF") STATUSCODE = xmlDoc.SelectNodes("//STATUSCODE") ' Read the content. Dim BNO As String = "" Dim Status As String = "" Dim i As Integer Dim bstr As String = "" bstr = "E:\\log\\bookingstatus\\log-" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt" If HMCREF.Count = STATUSCODE.Count Then For i = 0 To HMCREF.Count - 1 If STATUSCODE.Item(i).InnerText() <> "" And HMCREF.Item(i).InnerText() <> "" Then If BNO <> "" Then BNO = BNO + "," + HMCREF.Item(i).InnerText() Else BNO = HMCREF.Item(i).InnerText() End If If Status <> "" Then Status = Status + "," + STATUSCODE.Item(i).InnerText() Else Status = STATUSCODE.Item(i).InnerText() End If End If Next Else GenerateXmlFile(bstr, "'&XML=" + xmlDoc.InnerXml) End If If BNO <> "" And Status <> "" Then Dts.Connections.Item("AServ").AcquireConnection(Nothing) Dim conn As New SqlClient.SqlConnection(Dts.Connections.Item("AServ").ConnectionString) Dim cmd As New SqlClient.SqlCommand conn.Open() cmd.Connection = conn cmd.CommandTimeout = 300 cmd.CommandText = " Admin_UpdateBookingStatus '" + BNO + "', '" + Status + "' " cmd.ExecuteNonQuery() conn.Close() GenerateXmlFile(bstr, "SQL = Admin_UpdateBookingStatus '" + BNO + "', '" + Status + "'&XML=" + xmlDoc.InnerXml) End If dataStream.Close() response.Close() End If End Sub Public Sub GenerateXmlFile(ByVal filePath As String, ByVal fileContents As String) Dim objStreamWriter As IO.StreamWriter Try objStreamWriter = New IO.StreamWriter(filePath) objStreamWriter.Write(fileContents) objStreamWriter.Close() Catch Excep As Exception MsgBox(Excep.Message) End Try Dts.TaskResult = Dts.Results.Success End Sub End Class