andy學java系列之J2ME的移動支付系統的客戶端的實現

 

J2ME的移動支付系統的客戶端的實現
整個J2ME客戶端的邏輯架構是由若干個功能模塊組成的,這些功能模塊覆蓋了網絡通信、用戶界面、安全等各個方面的職能,並通過模塊間的通信共同實現了移動支付系統客戶端的功能。
邏輯結構如圖2所示,其中A~F的意義如下:
A:用戶請求交易 / 交易操作結果
B:用戶輸入的交易請求信息 / 服務器端返回的交易結果
C:經過XML加密的請求信息/ 經過XML簽名認證的返回結果
D:經過XML簽名的已加密請求信息 / 解析過的XML返回結果
E:組裝好的經過XML簽名的已加密請求信息的XML數據包 / 網絡通信模塊接收到的XML數據包
F:發向服務器的XML數據包 / 接收到的來自服務器的XML數據包
黑色雙箭頭所表示的是J2ME特有的RMS數據庫的數據。數據庫訪問模塊負責調用J2ME的RMS數據庫的功能接口,對用戶界面模塊用的個性化設置,XML加密和簽名用的私匙和公匙對,網絡通信模塊用的HTTP訪問地址和設置等等數據進行存取,而其它模塊則通過訪問數據庫模塊存取所需數據。
在客戶端系統的實現中,使用了一些第三方API庫:kXML和Bouncy Castle API。其中kXML是XML組裝/解析的工具,而Bouncy Castle API是J2ME應用程序專用的XML加密/解密和簽名/驗證的工具。
客戶端部分的主要模塊實現如下:
1)數據庫訪問模塊
數據庫訪問模塊是所有其它模塊需要用到的模塊,這是因爲它把整個J2ME客戶端需要用到的程序配置和用戶設置存取到J2ME的數據庫中。在J2ME MIDP中定義了一個簡單的基於記錄的數據庫管理系統(Record Management System,RMS),在RMS中Record Store等同於一般數據庫系統中的表(Table),它是記錄了一系列記錄的文件。
數 據庫訪問模塊對RMS進行操作,並對外部模塊提供了兩個存取數據的接口:
按名稱保存數據到RMS的接口:public void setDataToRecordStore(String name, String data)
按名稱從RMS獲取數據的接口:public String getDataFromRecordStore(String name)
2)用戶界面模塊
用戶界面模塊實現人機交互工能,接收用戶輸入,並把操作結果以友善的形式進行輸出。除了使用J2ME提供的Display、Screen、Label、Command、Alert、Form、TextField等高級用戶界面控件外,還需要使用J2ME提供的Canvas、Image等等低級用戶界面API,來實現動畫等特效。
3)XML加密/解密模塊
這兩個模塊負責對服務器端傳來的用RSA算法公匙加密的共享密匙進行解密,然後用共享密匙對機密信息使用Triple DES算法進行加密。
通過使用Bouncy Castle API密碼術包,我們可以輕鬆地對所需要傳輸的交易請求裏面的機密信息進行XML加密和解密。它所提供的org.bouncycastle.crypto包有加密/解密中需要用到的絕大部分的類,另外org.bouncycastle.util包提供了包括Base64編碼轉換、Hex編碼轉換等有用的工具類。在Bouncy Castle API中,公匙、私匙和共享密匙都是對象,在試圖使用它們之前,必須要通過它們的主要參數重構出這些密匙對象。RSA的公匙有Modulus和Exponent兩個主要參數,RSA私匙除了這兩個參數外,還有privExp、dp、dq、p、q、qInv等幾個參數,而Triple DES共享密匙只有單一的key參數。在傳遞這些密匙參數或加密的相關信息時,由於XML加密的很多元素指定使用Base64編碼,因此還需要用到Base64這個工具類。我們定義了一個Encryptor類來處理所有加密/解密的相關的問題。定義的接口如下:
TripleDES加密接口:public byte[] encryptTripleDES (byte[] data) throws CryptoException
 RSA解密接口:public synchronized byte[] decryptRSA(byte[] data) throws CryptoException
4)XML簽名/驗證模塊
   XML簽名過程中,首先生成原始數據的摘要,再對摘要進行簽名。生成摘要的算法一般使用SHA1算法。Bouncy Castle API包同樣提供了生成簽名用的摘要的SHA1Digest類,以及用於數字簽名的RSAEngine、PSSSigner等類。我們定義Signature類封裝所有的處理簽名的功能代碼。定義的接口如下:
   生成摘要:private byte[] getDigest(String mesg) throws Exception
   使用RSA私匙簽名:public byte[] RSASign(byte[] toSign) throws Exception
5)XML組裝/解析模塊
    爲了簡化問題,XML組裝可以使用簡單的字符串拼接來實現,而對於XML解析工作,我們使用kXML來處理。它是一個只佔很小存儲空間的XML語法分析程序,對於J2ME應用程序非常適合。
    kXML有一個非常獨特的DOM操作方法和被稱爲Pull的語法分析方法。DOM是一個與XML相互作用的簡單方法,通常這個XML是一棵完整的XML樹,被解析成一個存放在存儲器中的節點結構,可以通過遍歷這棵樹獲取所有節點信息。它非常簡單易用,但是因爲整棵樹存在於存儲器中造成存儲器的負擔。與DOM不同,Pull語法分析讓程序員從語法分析程序中"拉"出下一個事件,Pull語法分析使處理狀態改變更加容易,因爲你可以發送分析器到不同的函數,維護它們自己的狀態變量。此外,Pull特別適用於J2ME環境中的需要保持儘可能地少的內存佔用的情況,因此我們採用Pull方法進行XML的解析。定義接口如下:
          根據XML節點名稱獲取對應值:private String getXMLNodeValue(String nodeName)
6)   網絡通信模塊
    在J2ME的MIDP 1.0 API中,網絡通信協議支持UDP、HTTP、Socket等等。雖然從理論上說可以使用Socket或UDP協議與外界進行通信,但是一些廠商的MIDP設備可能不支持這些協議,使用這些協議進行通信可能造成程序移植上的問題。而HTTP由於是當今互聯網最主要的通信協議,因此基本上所有廠商的移動終端設備都支持HTTP協議。因此我們採用HTTP協議進行通信。下面給出發送和接收數據的代碼:public String sendAndReceiveByHttp(String url, String strToSend) throws Exception
{
HttpConnection hc = (HttpConnection)Connector.open(url, Connector.READ_WRITE);
  hc.setRequestMethod(HttpConnection.POST);
  hc.setRequestProperty(“Connection”, “Keep-Alive”);
  DataOutputStream dos = hc.openDataOutputStream();
  dos.writeUTF(strToSend);//向目的URL發送數據
  dos.flush();
  dos.close();
  DataInputStream dis = hc.openInputStream();
  String strReceived = dis.readUTF();//接收目的URL的響應數據
  dis.close();
  return strReceived;
}

 

發佈了101 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章