最近一段是時間項目可能需要提供短信功能,客戶作為一個 SP 端提供短信 業務;網上搜索了一番,找到了比較不錯的 CMPP30 類的代碼,該代碼基本實現 了 CMPP3.0 協議中的短信收發、網絡重連等功能。本人將其重新改造,提供了 同步發送、異步發送的支持(原先版本的異步發送並非標准的 .NET 異步發送模 式,這部分代碼是一個異步操作實現的“范本”,可供大家參考),增加了對 PROVISION 接口的支持。
本人已將這些代碼打包為一個 RAR 文件,稍後會上傳到 Internet 供大家交 流、學習;下面將對這版 CMPP30 類的 API 進行簡要介紹:
1)用於收發短信 CMPP30 類的 API:
1/**//// <summary>
2/// CMPP30 短信網關通訊組件(供 SP 使用)。
3/// </summary>
4public class CMPP30
5 {
6
7 屬性#region 屬性
8 /**//// <summary>
9 /// SMS 事件。
10 /// </summary>
11 public event EventHandler<SMSEventArgs> SMS;
12 #endregion
13
14 構造函數#region 構造函數
15 /**//// <summary>
16 /// 初始化 <see cref="CMPP30"/> 類新實例。
17 /// </summary>
18 public CMPP30(string spid, string password, string address, int port);
19 #endregion
20
21 公有方法#region 公有方 法
22 /**//// <summary>
23 /// 啟動 CMPP30 服 務。
24 /// </summary>
25 public void Start ();
26 /**//// <summary>
27 /// 發送短信。
28 /// </summary>
29 /// /// <param name="text">
30 /// 信息內容。
31 /// </param>
32 /// <param name="encoding">
33 /// 信息編碼。
34 /// </param>
35 /// <param name="sourceID">
36 /// SP的服務代碼,將顯示在最 終用戶手機上的短信主叫號碼。
37 /// </param>
38 /// <param name="destinations">
39 /// 接收短信的電 話號碼列表。
40 /// </param>
41 /// <param name="serviceID">
42 /// 業務標識(如:woodpack)。
43 /// </param>
44 /// <param name="needReport">
45 /// 是否要求返回狀態報告。
46 /// </param>
47 /// <param name="feeType">
48 /// 資費類別。
49 /// </param>
50 /// <param name="feeUserType">
51 /// 計費用戶。
52 /// </param>
53 /// <param name="feeUser">
54 /// 被計費的號碼(feeUserType 值為 FeeUser 時有效)。
55 /// </param>
56 /// <param name="realUser">
57 /// 被計費號碼的真實身份(“ 真實號碼”或“偽碼”)。
58 /// </param>
59 /// <param name="informationFee">
60 /// 信息費(以“分 ”為單位,如:10 分代表 1角)。
61 /// </param>
62 /// <param name="linkID">
63 /// 點播業務的 LinkID 。
64 /// </param>
65 public CMPP_SUBMIT_RESP Send(
66 string text,
67 CEncoding encoding,
68 string sourceID,
69 string[] destinations,
70 string serviceID,
71 bool needReport,
72 FeeType feeType,
73 FeeUserType feeUserType,
74 string feeUser,
75 bool realUser,
76 int informationFee,
77 string linkID);
78 /**//// <summary>
79 /// 發送短信。
80 /// </summary>
81 public CMPP_SUBMIT_RESP Send(CMPP_SUBMIT submit);
82 /**//// <summary>
83 /// 開始異步 發送短信。
84 /// </summary>
85 /// <param name="text">
86 /// 信息內容。
87 /// </param>
88 /// <param name="encoding">
89 /// 信息編碼。
90 /// </param>
91 /// <param name="sourceID">
92 /// SP的服務代碼,將顯示在最 終用戶手機上的短信主叫號碼。
93 /// </param>
94 /// <param name="destinations">
95 /// 接收短信的電 話號碼列表。
96 /// </param>
97 /// <param name="serviceID">
98 /// 業務標識(如:woodpack)。
99 /// </param>
100 /// <param name="needReport">
101 /// 是否要求返回狀態報告。
102 /// </param>
103 /// <param name="feeType">
104 /// 資費類別。
105 /// </param>
106 /// <param name="feeUserType">
107 /// 計費用戶。
108 /// </param>
109 /// <param name="feeUser">
110 /// 被計費的號碼(feeUserType 值為 FeeUser 時有效)。
111 /// </param>
112 /// <param name="realUser">
113 /// 被計費號碼的真實身份(“真實號碼 ”或“偽碼”)。
114 /// </param>
115 /// <param name="informationFee">
116 /// 信息費(以“分” 為單位,如:10 分代表 1角)。
117 /// </param>
118 /// <param name="linkID">
119 /// 點播業務的 LinkID。
120 /// </param>
121 /// <param name="callback">
122 /// 異步回調函數。
123 /// </param>
124 /// <param name="asyncState">
125 /// 傳遞給異步回調函數的參數。
126 /// </param>
127 public IAsyncResult BeginSend(
128 string text,
129 CEncoding encoding,
130 string sourceID,
131 string[] destinations,
132 string serviceID,
133 bool needReport,
134 FeeType feeType,
135 FeeUserType feeUserType,
136 string feeUser,
137 bool realUser,
138 int informationFee,
139 string linkID,
140 AsyncCallback callback,
141 object asyncState);
142 /**//// <summary>
143 /// 開始異步發送短信。
144 /// </summary>
145 public IAsyncResult BeginSend(
146 CMPP_SUBMIT submit,
147 AsyncCallback cb,
148 object asyncState);
149 /**//// <summary>
150 /// 結束異步發送短信。
151 /// </summary>
152 public CMPP_SUBMIT_RESP EndSend(IAsyncResult ar);
153 /**//// <summary>
154 /// 停止 CMPP30 服務。
155 /// </summary>
156 public void Stop();
157 #endregion
158
159}
CMPP30 類 API
這個類是核心類,我的代碼注釋很清楚,所以就不再贅述;需要注意一下的 就是 Send、BeginSend、EndSend 是符合 .NET 框架標准的異步操作模式;與網 上的 CMPP30 類不用的是 Send 函數要求傳入 CMPP_SUBMIT 數據包並返回一個 CMPP_SUBMIT_RESP 包,這有利於調用者得到由 ISMG 服務器返回的 MsgID 字段 ,否則調用者只能通過 SMS 事件得到 CMPP_SUBMIT_RESP 包,但是僅僅有這個 包是不能與其相對應的CMPP_SUBMIT 進行匹配的。
另外說一下,所有與 ISMG 的交互都會導致 SMS 事件的引發,該事件參數中 會提供一個 SMS_EVENT 枚舉供事件處理程序使用,詳細信息請參考 SMS_EVENT 的代碼。
最後對使用我代碼的朋友說一下,Start 與 Stop 這兩個函數只能調用一次 。如果你的程序中調用 Stop 停止了 CMPP30 服務,則必須重新實例化一個新的 CMPP30 對象來啟動該服務。
2)對 PROVISION 正向訂購/取消接口的支持:
根據 MISC1.6 的描述,對 PROVISION 接口的實現應該采用基於 SOAP 協議 的 WEB 服務技術,我這裡提供了一個 Provision 抽象類,該類繼承自 System.Web.Services.WebService。呵呵,看出來了吧,我的想法就是讓 asmx 頁的後台類繼承 Provision 類。該類封裝了 PROVISION 接口中的 SyncOrderRelationReq 和 SyncOrderRelationResp 包的實現,將這對“發送/ 響應”包的收發變為“一次對 WEB 服務函數的調用”,當接收到 SyncOrderRelationReq 時就調用 Provision 類中的 SyncOrderRelationReq 函 數(WebMethod),並將該函數返回值轉變為一個SyncOrderRelationResp 包返 回給移動的服務器。API 代碼如下:
1/**//// <summary>
2/// 正向(反向)同步 PROVISION 接口服務。
3/// </summary>
4[WebService(Namespace = "http://www.monternet.com/dsmp/schemas/")]
5[SoapDocumentService (RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
6public abstract class Provision : System.Web.Services.WebService
7 {
8
9 屬性#region 屬性
10 /**//// <summary>
11 /// SOAP 消息編號(DSMG 調用該 WEB 服務時 需要設置該信息)。
12 /// </summary>
13 [EditorBrowsable(EditorBrowsableState.Never)]
14 public TransactionID TransactionID;
15 #endregion
16
17 保護方法#region 保護方法
18 /**//// <summary>
19 /// MISC 因為某種情況(如:用戶通過手機短信的方式執行了某操作)更新 了用戶訂購關系(包括:訂購、取消、暫停、激活)的時候,通過此函數發起和 SP 的更新訂購關系的交互。
20 /// </summary>
21 /// <param name="id">
22 /// 消息編號。
23 /// </param>
24 /// <param name="sendAddr">
25 /// 發送方的地址。
26 /// </param>
27 /// <param name="destAddr">
28 /// 接收方的地址。
29 /// </param>
30 /// <param name="feeUserID">
31 /// 計費用戶標識。
32 /// </param>
33 /// <param name="destUserID">
34 /// 使用用戶標識(當使用用戶和計費用戶為同一用戶的時候, FeeUser_ID 和 DestUser_ID 的值相同)。
35 /// </param>
36 /// <param name="linkID">
37 /// 臨時訂購關系的事務 ID。
38 /// </param>
39 /// <param name="actionID">
40 /// 服務狀態管理動作代碼 (1:開通服務;2:停止服務;3:激活服務;4:暫停服務)。
41 /// </param>
42 /// <param name="actionReasonID">
43 /// 產生服務狀態管理動作原因的代 碼(1:用戶發起行為;2:Admin&1860發起行為;3:Boss停機;4: Boss開機;5:Boss過戶;6:Boss銷戶;7:Boss改號;8:扣費失敗導致的服務 取消;9:其他)。
44 /// </param>
45 /// <param name="spid">
46 /// SP 的企業代碼。
47 /// </param>
48 /// <param name="serviceID">
49 /// 業務標識,是數字、字母和符號的組 合(長度為 10,SP的業務類型,數字、字母和符號的組合,由SP自定,如圖片 傳情可定為TPCQ,股票查詢可定義為11),也叫做計費代碼。
50 /// </param>
51 /// <param name="accessMode">
52 /// 服務的訪問方式(1:WEB;2:WAP;3:SMS)。
53 /// </param>
54 /// <param name="featureStr">
55 /// 服務訂購參數(base64加密),內容是長號碼+空格+用戶發送內容 。
56 /// </param>
57 /// <param name="hResult">
58 /// 返回值(0:成功;1:未知錯誤;2-99 :保留;4000:無效的msgtype;4001:無效的action_id;4002:無效的 action_reasonid;4003:無效的SP ID;4004:無效的serviceID;4005:無效 的pseudocode;4006:無效的accessmode;4007:MISC 同步開通服務,但SP 端 已存在訂購關系,且狀態為開通;4008:MISC 同步開通服務,且SP 端不存在訂購 關系,但開通服務失敗;4009:MISC 同步開通服務,但SP 端已存在訂購關系, 且 狀態為暫停;4010:MISC 同步停止服務, 且SP 端存在訂購關系, 但取消服務失 敗;4011:MISC 同步停止服務, 但SP 端不存在訂購關系;4012:MISC 同步暫 停服務, 且SP 端存在訂購關系, 但暫停服務失敗;4013:MISC 同步暫停服務, 但SP 端不存在訂購關系;4014:MISC 同步暫停服務, 但SP 端已存在訂購關系, 且狀態為暫停;4015:MISC 同步激活服務, 但SP 端已存在訂購關系, 且狀態為 開通;4016:MISC 同步激活服務, 但SP 端不存在訂購關系;4017:MISC 同步 激活服務, 且SP 端存在訂購關系, 但激活服務失敗;9000:系統磁盤讀寫錯誤 ;9001:網絡異常;9002:網絡錯誤;9003:業務網關忙,業務網關緩存;9004 :業務網關忙,並且業務網關緩沖區滿,MISC 緩存,並暫時不要發送消息,等 待一段時間重試;9005:MISC 忙,MISC 緩存;9006:MISC 忙,並且MISC 緩沖 區滿,業務網關緩存,並暫時不要發送消息,等待一段時間重試;9007:業務網 關超過限制的流量;9008:MISC 異常,並不可用;9009:業務網關異常,並不 可用;9010:該業務網關沒有權限調用該接口消息;9011:MISC 沒有權限發送 該接口消息給業務網關;9012:版本不支持;9013:消息類型不對,系統不支持 ;9014:驗證錯誤,無法解析SOAP 和XML 結構、缺少必須存在的字段,或者消 息,格式不正確;9015:拒絕消息,服務器無法完成請求的服務)。
59 /// </param>
60 protected abstract void OnSyncOrderRelationReq(
61 string id,
62 AddressInfo sendAddr,
63 AddressInfo destAddr,
64 UserID feeUserID,
65 UserID destUserID,
66 string linkID,
67 int actionID,
68 int actionReasonID,
69 string spid,
70 string serviceID,
71 int accessMode,
72 byte[] featureStr,
73 out int hResult);
74 #endregion
75
76 公有方法#region 公有方法
77 /**//// <summary>
78 /// MISC 因為某種情況(如:用戶通 過手機短信的方式執行了某操作)更新了用戶訂購關系(包括:訂購、取消、暫 停、激活)的時候,通過此函數發起和 SP 的更新訂購關系的交互。
79 /// </summary>
80 /// <param name="Version">
81 /// 接口消息的版本號,目前接口消息的版 本都為“1.5.0”
82 /// </param>
83 /// <param name="MsgType">
84 /// 消息類型。
85 /// </param>
86 /// <param name="Send_Address">
87 /// 發送方的地址。
88 /// </param>
89 /// <param name="Dest_Address">
90 /// 接收方的地址。
91 /// </param>
92 /// <param name="FeeUser_ID">
93 /// 計費用戶標識。
94 /// </param>
95 /// <param name="DestUser_ID">
96 /// 使用用戶標識(當使用用戶和計費 用戶為同一用戶的時候,FeeUser_ID 和 DestUser_ID 的值相同)。
97 /// </param>
98 /// <param name="LinkID">
99 /// 臨時訂購關系的事務 ID。
100 /// </param>
101 /// <param name="ActionID">
102 /// 服務狀態管理動作代碼(1:開通服務 ;2:停止服務;3:激活服務;4:暫停服務)。
103 /// </param>
104 /// <param name="ActionReasonID">
105 /// 產生服務狀態管理動作原因的 代碼(1:用戶發起行為;2:Admin&1860發起行為;3:Boss停機;4: Boss開機;5:Boss過戶;6:Boss銷戶;7:Boss改號;8:扣費失敗導致的服務 取消;9:其他)。
106 /// </param>
107 /// <param name="SPID">
108 /// SP 的企業代碼。
109 /// </param>
110 /// <param name="SPServiceID">
111 /// 業務標識,是數字、字母和符號的 組合(長度為 10,SP的業務類型,數字、字母和符號的組合,由SP自定,如圖 片傳情可定為TPCQ,股票查詢可定義為11),也叫做計費代碼。
112 /// </param>
113 /// <param name="AccessMode">
114 /// 服務的訪問方式(1:WEB;2:WAP ;3:SMS)。
115 /// </param>
116 /// <param name="FeatureStr">
117 /// 服務訂購參數(base64 加密),內容是長號碼+空格+用戶發送內容。
118 /// </param>
119 /// <param name="hRet">
120 /// 返回值(0:成功;1:未知錯誤;2-99:保留;4000:無效的msgtype; 4001:無效的action_id;4002:無效的action_reasonid;4003:無效的SP ID ;4004:無效的serviceID;4005:無效的pseudocode;4006:無效的 accessmode;4007:MISC 同步開通服務,但SP 端已存在訂購關系,且狀態為開通 ;4008:MISC 同步開通服務,且SP 端不存在訂購關系,但開通服務失敗;4009: MISC 同步開通服務,但SP 端已存在訂購關系, 且狀態為暫停;4010:MISC 同步 停止服務, 且SP 端存在訂購關系, 但取消服務失敗;4011:MISC 同步停止服務 , 但SP 端不存在訂購關系;4012:MISC 同步暫停服務, 且SP 端存在訂購關系, 但暫停服務失敗;4013:MISC 同步暫停服務, 但SP 端不存在訂購關系;4014: MISC 同步暫停服務, 但SP 端已存在訂購關系, 且狀態為暫停;4015:MISC 同 步激活服務, 但SP 端已存在訂購關系, 且狀態為開通;4016:MISC 同步激活服 務, 但SP 端不存在訂購關系;4017:MISC 同步激活服務, 且SP 端存在訂購關 系, 但激活服務失敗;9000:系統磁盤讀寫錯誤;9001:網絡異常;9002:網絡 錯誤;9003:業務網關忙,業務網關緩存;9004:業務網關忙,並且業務網關緩 沖區滿,MISC 緩存,並暫時不要發送消息,等待一段時間重試;9005:MISC 忙 ,MISC 緩存;9006:MISC 忙,並且MISC 緩沖區滿,業務網關緩存,並暫時不 要發送消息,等待一段時間重試;9007:業務網關超過限制的流量;9008:MISC 異常,並不可用;9009:業務網關異常,並不可用;9010:該業務網關沒有權限 調用該接口消息;9011:MISC 沒有權限發送該接口消息給業務網關;9012:版 本不支持;9013:消息類型不對,系統不支持;9014:驗證錯誤,無法解析SOAP 和XML 結構、缺少必須存在的字段,或者消息,格式不正確;9015:拒絕消息, 服務器無法完成請求的服務)。
121 /// </param>
122 [WebMethod]
123 [SoapHeader("TransactionID", Direction = SoapHeaderDirection.InOut)]
124 [SoapDocumentMethod ("sim.SyncOrderRelation", RequestElementName = "SyncOrderRelationReq", ResponseElementName = "SyncOrderRelationResp")]
125 [return: System.Xml.Serialization.SoapElementAttribute("return")]
126 [EditorBrowsable(EditorBrowsableState.Never)]
127 public void SyncOrderRelationReq(
128 ref string Version,
129 ref string MsgType,
130 AddressInfo Send_Address,
131 AddressInfo Dest_Address,
132 UserID FeeUser_ID,
133 UserID DestUser_ID,
134 string LinkID,
135 int ActionID,
136 int ActionReasonID,
137 string SPID,
138 string SPServiceID,
139 int AccessMode,
140 byte[] FeatureStr,
141 out int hRet)
142 {
143
144 Version = "1.5.0";
145 MsgType = "SyncOrderRelationResp";
146
147 OnSyncOrderRelationReq(
148 TransactionID == null ? null : TransactionID.ID,
149 Send_Address,
150 Dest_Address,
151 FeeUser_ID,
152 DestUser_ID,
153 LinkID,
154 ActionID,
155 ActionReasonID,
156 SPID, SPServiceID,
157 AccessMode,
158 FeatureStr,
159 out hRet);
160 }
161 #endregion
162
163}
Provision 類的 API
注意:asmx 頁還是需要使用者自己建的,只需要將 asmx 的後台代碼類繼承 Provision 類,並實現抽象函數 OnSyncOrderRelationReq 即可,在該抽象函數 內,記錄手機用戶訂購(或取消)業務的信息。
3)對 PROVISION 反向訂購/取消接口的支持:
最後再簡要地說一下關於對反向訂購/取消的支持,我的實現就是對 dsmp.wsdl 這個 WEB 服務的一個簡單封裝。該 WEB 在移動的服務器上發布。需 要說明的是:根據反向訂購/取消的業務流程,在這個過程中會執行正向訂購/取 消的那個 WEB 服務函數,因為反向訂購/取消業務也會要求SP接收一個 SyncOrderRelationReq 包並返回與其相應的 SyncOrderRelationResp 包。所以 PROVISION 實現的關鍵還是在 Provision 類。
本文配套源碼