在第二講使用delphi+intraweb進行微信開發2—intraweb以.net方式發布(以asp.net mvc4模式部署)在IIS(.net虛擬主機)上我們成功把iw應用部署在了雲端虛擬主機上,在這一講裡,我們將延續第一講的內容回歸微信開發,這次講解微信訊息處理。
首先明確幾個知識點:
1、微信伺服器轉送使用者訊息使用的http post方法,在第一講中關於微信伺服器的http資料提交方法我們並沒有細說,實際上微信進行接入驗證使用的是http get方法;而轉發用戶訊息則使用的http post方法,並且轉發訊息時訊息以xml格式進行編碼,ContentType=text/xml。
2、微信伺服器訊息轉送是可以選擇三種資料傳遞方式的,一、明文;二、加密;三、混合。在這一講了為了調試方便,我們採用明文方式傳遞資料。下一講再講解訊息加密方式的處理。
原本覺得這一講的內容沒什麼難度,要是.net、php甚至是delphi的webbroker都應該很容易實現。但用上iw後發現問題很複雜!
iw處理http請求資料的類別是THttpRequest,但是我看遍了THttpRequest的屬性和方法就沒有找到直接訪問http content的地方,只有個似乎是讀取http content的THttpRequest.ContentFields屬性,但是實際執行程式碼並調試後發現,這個屬性根本無法取到微信伺服器傳遞過來的xml文件,內容總是空的。
經過重複驗證發現這個ContentFields屬性只能對http request時ContentType為application/x-www-form-urlencoded時傳遞的鍵值對內容有效,也就是對於表單類型的提交是可以取到資料的,在第一講的微信存取中就是這種情況,微信傳遞過來的signature、timestamp、nonce等欄位值都是可以透過THttpRequest.ContentFields取出來的。
事情發展到現在完全陷入困境了,那麼ContentType=text/xml時如何用THttpRequest類別的方法取得內容呢?經過研究發現THttpRequest類別有個Files屬性,當時感覺希望就在這個屬性上,畢竟xml也可以當做檔案來上傳不是嗎?呵呵,很遺憾的是,我當時無論怎麼實驗(反組譯dcu都用上了),這個屬性的檔數總是0,這個希望也斷了!
於是乎在iw官方的問題貼論壇上發帖留言開始了求教之路,1天、2天始終有人看沒人回,在屢次搜索相關提問後發現了曾經有人和我遇到同樣的問題,當時作者給了回應說提問者表示不清楚要求發電子郵件給作者代碼,呵呵,算是抓到稻草了,立即冒充提問者給作者發送我的代碼並附上了提問,呀呀,石沉大海啊,呵呵,iw真是想愛你這麼的不容易。
沒有辦法繼續搜尋其他人的提問吧,功夫不負有心人啊,終於找到了一個帖子,裡面提問者和我的問題不相同,但是回答者提到iw demos裡面有個PostFormData範例工程,立即查看我下載的demo,發現根本沒有這個工程,上官網重新下載例子工程,呵呵,終於有了!打開程式碼一看,原來如此!跟第一講一樣就是一行程式碼難受我好幾天。
親們看吧:
就是那個「RegisterContentType」方法,呵呵,你能想到嗎?幫助裡面有提到嗎?我靠!
好吧,總算可以了,那麼接著說,增加了content-type註冊之後,就可以用THttpRequest.Files獲取post過來的xml了,這倒是和我最初的預測差不多,小安慰一下。
親們,我的血淚歷程告訴大家,針對iw這種幫助不完善又沒源代碼的web開發框架,提問區查找和iw demos就是我們最大的依靠了,要用iw就趕快下載個最新的demo看看吧。
剩下就沒什麼好說了,貼個程式碼截圖大夥看看,照著微信的文檔做,比較容易:
TEventHandler類別:
#部署到伺服器上後用微信用戶端測試截圖:
如果你看到這裡了,好吧,我再告訴你個小秘密吧:
#經我反覆測試,那個「RegisterContentType」方法只在SA、ISAPI模式下有效,當我按照第二講說的編譯成library並按照aspx模式部署好後,無論如何也取不到xml文件,僅僅是工程類型由於部署要求做了個變化,其它代碼都沒有任何變化,就是不知道是為什麼,上圖大夥看到的截圖是我以ISAPI方式部署在我伺服器上實現的。
最後再附上微信訊息的xml格式中日期欄位的編解碼函數,微信的日期類型是整形值,所以需要將整形值轉換成TDateTime類型,微信的整形值的計算是以'1970-01-01 00:00:00'作為基準時間計算的秒差。另外要注意的是,微信時間是UTC時間,也就是轉換成北京時間要加上8小時。
///
/// 微信的日期時間都是int64型,是和1970-01-01 00:00:00之間的秒差,這個函數用來回傳1970-01-01 00:00:00時刻
///
///
function## function## ## GetWxBaseDt: TDateTime
;
begin Result##) # := VarToDateTime('1970-01-01 00:00:00'
# ); end;
///
function GetWxNow: Int64;
begin
Result := SecondsBetween(Now, GetWxBaseDt) - 3600 * 8;
end;
function GetWxNowStr: string;
var
i64: Int64;
begin
i64 := GetWxNow;
Result := IntToStr(i64);
end;
##///
/// Pass the CreateTime field value obtained from WeChat xml as a parameter into the function
/// You can use the int type of WeChat Convert the time into TDatetime type
##///
///
ConvertWxDtToDateTime(wxDt: string): TDateTime; var
i64
: Int64; begin
i64
:= StrToInt64(wxDt); Result
:= IncSecond(GetWxBaseDt, i64 + 3600*8); end
;
For more articles related to using delphi+intraweb for WeChat message processing, please pay attention to the PHP Chinese website!