說是手機充值系統有點裝了,其實就是調用了聚合數據的支付介面,其實挺簡單的事 但是我發現博客園竟然沒有類似文章,我就個出頭鳥把我的代碼貢獻出來吧 首先說準備工作: 去聚合數據申請賬號-添加手機支付的認證-認證通過後為賬戶充值。 上述工作完成後,開始準備開發要用到的必要參數: appid:在個人中心-我 ...
說是手機充值系統有點裝了,其實就是調用了聚合數據的支付介面,其實挺簡單的事 但是我發現博客園竟然沒有類似文章,我就個出頭鳥把我的代碼貢獻出來吧
首先說準備工作:
去聚合數據申請賬號-添加手機支付的認證-認證通過後為賬戶充值。
上述工作完成後,開始準備開發要用到的必要參數:
appid:在個人中心-我的數據中可找到對應的APPKEY(每個不同的介面都需要使用對應的appkey)
openid:個人中心-用戶中心-賬戶信息(這個是唯一的程式中會使用到)
對應的介面都有比較詳細的數據接收已經返回參數的說明,具體開發中會用到,具體的請查看鏈接:https://www.juhe.cn/docs/api/id/85
接下來要準備開發中的用到幾個輔助函數,在對應的API文檔中有示例代碼,也可以使用下麵的:
1 /// <summary> 2 /// Http (GET/POST) 3 /// </summary> 4 /// <param name="url">請求URL</param> 5 /// <param name="parameters">請求參數</param> 6 /// <param name="method">請求方法</param> 7 /// <returns>響應內容</returns> 8 static string sendPost(string url, IDictionary<string, string> parameters, string method) 9 { 10 if (method.ToLower() == "post") 11 { 12 HttpWebRequest req = null; 13 HttpWebResponse rsp = null; 14 System.IO.Stream reqStream = null; 15 try 16 { 17 req = (HttpWebRequest)WebRequest.Create(url); 18 req.Method = method; 19 req.KeepAlive = false; 20 req.ProtocolVersion = HttpVersion.Version10; 21 req.Timeout = 5000; 22 req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; 23 byte[] postData = Encoding.UTF8.GetBytes(BuildQuery(parameters, "utf8")); 24 reqStream = req.GetRequestStream(); 25 reqStream.Write(postData, 0, postData.Length); 26 rsp = (HttpWebResponse)req.GetResponse(); 27 Encoding encoding = Encoding.GetEncoding(rsp.CharacterSet); 28 return GetResponseAsString(rsp, encoding); 29 } 30 catch (Exception ex) 31 { 32 return ex.Message; 33 } 34 finally 35 { 36 if (reqStream != null) reqStream.Close(); 37 if (rsp != null) rsp.Close(); 38 } 39 } 40 else 41 { 42 //創建請求 43 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + "?" + BuildQuery(parameters, "utf8")); 44 45 //GET請求 46 request.Method = "GET"; 47 request.ReadWriteTimeout = 5000; 48 request.ContentType = "text/html;charset=UTF-8"; 49 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 50 Stream myResponseStream = response.GetResponseStream(); 51 StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); 52 53 //返回內容 54 string retString = myStreamReader.ReadToEnd(); 55 return retString; 56 } 57 } 58 /// <summary> 59 /// 把響應流轉換為文本。 60 /// </summary> 61 /// <param name="rsp">響應流對象</param> 62 /// <param name="encoding">編碼方式</param> 63 /// <returns>響應文本</returns> 64 static string GetResponseAsString(HttpWebResponse rsp, Encoding encoding) 65 { 66 System.IO.Stream stream = null; 67 StreamReader reader = null; 68 try 69 { 70 // 以字元流的方式讀取HTTP響應 71 stream = rsp.GetResponseStream(); 72 reader = new StreamReader(stream, encoding); 73 return reader.ReadToEnd(); 74 } 75 finally 76 { 77 // 釋放資源 78 if (reader != null) reader.Close(); 79 if (stream != null) stream.Close(); 80 if (rsp != null) rsp.Close(); 81 } 82 } 83 /// <summary> 84 /// 組裝普通文本請求參數。 85 /// </summary> 86 /// <param name="parameters">Key-Value形式請求參數字典</param> 87 /// <returns>URL編碼後的請求數據</returns> 88 static string BuildQuery(IDictionary<string, string> parameters, string encode) 89 { 90 StringBuilder postData = new StringBuilder(); 91 bool hasParam = false; 92 IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator(); 93 while (dem.MoveNext()) 94 { 95 string name = dem.Current.Key; 96 string value = dem.Current.Value; 97 // 忽略參數名或參數值為空的參數 98 if (!string.IsNullOrEmpty(name))//&& !string.IsNullOrEmpty(value) 99 { 100 if (hasParam) 101 { 102 postData.Append("&"); 103 } 104 postData.Append(name); 105 postData.Append("="); 106 if (encode == "gb2312") 107 { 108 postData.Append(HttpUtility.UrlEncode(value, Encoding.GetEncoding("gb2312"))); 109 } 110 else if (encode == "utf8") 111 { 112 postData.Append(HttpUtility.UrlEncode(value, Encoding.UTF8)); 113 } 114 else 115 { 116 postData.Append(value); 117 } 118 hasParam = true; 119 } 120 } 121 return postData.ToString(); 122 } 123 /// <summary> 124 /// 獲取時間戳 125 /// </summary> 126 /// <returns></returns> 127 public static string GetTimeStamp() 128 { 129 TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); 130 return Convert.ToInt64(ts.TotalSeconds).ToString(); 131 }View Code
這幾個函數具體的功能就不用說了 ,是代碼很簡單,都是網路鏈接發送請求和接受請求是時用的,我主要介紹的是點中未提供的一些
示例代碼中用到了JsonObject這個類 代碼中提供的是CSDN的鏈接,竟然還要2積分才能下載,坑爹啊 在這裡我給大家分享出來吧 http://pan.baidu.com/s/1hsqF51y
在項目中應用DLL加入using Xfrog.Net;命名空間
準備工作結束
接下來就進入正式編碼階段了 ,開始前我準備說一下重點,其實介面的代碼並不複雜,我想說了還是思路吧
1.驗證當前賬戶餘額是否夠本次充值:調用 http://op.juhe.cn/ofpay/mobile/yue 具體參數參看:https://www.juhe.cn/docs/api/id/85
2.檢測手機號是否可以充值:調用http://op.juhe.cn/ofpay/mobile/telcheck 具體參數參看:https://www.juhe.cn/docs/api/id/85/aid/213
3.調用手機直衝介面: http://op.juhe.cn/ofpay/mobile/onlineorder 具體參數參看: https://www.juhe.cn/docs/api/id/85/aid/214
4.調用訂單查詢介面:http://op.juhe.cn/ofpay/mobile/ordersta 具體參數參看:https://www.juhe.cn/docs/api/id/85/aid/586
5.編寫回調處理頁面:QQ上搜索聚合數據的客服,給他賬號和回調地址後,讓他幫助設置,具體的回調地址接受參數查看:http://code.juhe.cn/docs/detail/id/1565
具體代碼貼出:
//1.賬戶餘額查詢 string url1 = "http://op.juhe.cn/ofpay/mobile/yue"; var parameters1 = new Dictionary<string, string>(); string timestamp = GetTimeStamp(); parameters1.Add("timestamp", timestamp); //當前時間戳,如:1432788379 parameters1.Add("key", appkey);//你申請的key string signstr =openid+ appkey+timestamp; parameters1.Add("sign", CommonManager.String.EncryptMD5SystemDefaultMethod(signstr, false, true)); //校驗值,md5(<b>OpenID</b>+key+timestamp),OpenID在個人中心查詢 string result1 = sendPost(url1, parameters1, "get"); JsonObject newObj1 = new JsonObject(result1); String errorCode1 = newObj1["error_code"].Value; //查詢餘額是否成功 if (errorCode1 == "0") { //判斷餘額是否夠本次充值 if (double.Parse(newObj1["result"]["money"].Value) > double.Parse(Integrals)) { //msg.InnerText="餘額充足!"; //5.檢測手機號碼是否能充值 string url5 = "http://op.juhe.cn/ofpay/mobile/telcheck"; var parameters5 = new Dictionary<string, string>(); parameters5.Add("phoneno", phone); //手機號碼 parameters5.Add("cardnum", Integrals); //充值金額,目前可選:5、10、20、30、50、100、300 parameters5.Add("key", appkey);//你申請的key string result5 = sendPost(url5, parameters5, "get"); JsonObject newObj5 = new JsonObject(result5); String errorCode5 = newObj5["error_code"].Value; if (errorCode5 == "0") { //可以充值 //7.手機直充介面 string url7 = "http://op.juhe.cn/ofpay/mobile/onlineorder"; var parameters7 = new Dictionary<string, string>(); parameters7.Add("phoneno", phone); //手機號碼 parameters7.Add("cardnum", Integrals); //充值金額,目前可選:5、10、20、30、50、100、300 parameters7.Add("orderid", orderstr); //商家訂單號,8-32位字母數字組合 parameters7.Add("key", appkey);//你申請的key string md5str = openid + appkey + phone + Integrals + orderstr; parameters7.Add("sign", CommonManager.String.EncryptMD5SystemDefaultMethod(md5str, false, true)); //校驗值,md5(<b>OpenID</b>+key+phoneno+cardnum+orderid),OpenID在個人中心查詢 string result7 = sendPost(url7, parameters7, "get"); JsonObject newObj7 = new JsonObject(result7); String errorCode7 = newObj7["error_code"].Value; if (errorCode7 == "0") { msg.InnerText = "充值訂單創建成功,等待商戶充值後查看訂單狀態!"; DbSession.Default.FromSql( @"UPDATE TOP(1) TPropLog SET Jhorderid=@Jhorderid,PropStatus=@PropStatus WHERE ID = @ID") .AddInputParameter("@ID", DbType.Int32, id) .AddInputParameter("@PropStatus", DbType.Int32, 3) .AddInputParameter("@Jhorderid", DbType.String, newObj7["result"]["sporder_id"].Value) .Execute(); status.SelectedValue = "3"; } else { msg.InnerText = "充值訂單失敗!失敗原因:" + newObj7["reason"].Value; } } else { msg.InnerText = "手機號不能充值!原因:" + newObj1["reason"].Value; } } else { msg.InnerText = "餘額不足請充值!當前賬戶餘額為:" + newObj1["result"]["money"].Value; } } else { msg.InnerText="餘額查詢失敗!"; }
裡面有幾個點註意一下:
1.需要sign簽名的幾個介面需要按照格式使用MD5進行一個轉換,MD5轉換的函數網上一大把相信你的項目中也有了我就不提供了 ,按照他提供的格式組織簽名就行了
2.我的訂單查詢介面是寫在另外一個函數里的,因為我的邏輯充值後單獨可以查詢,可根據情況自行更改。
3.回調頁面是POST方式傳值,所以接受的時候按照他提供的參數接收就行了,根據返回的訂單號跟新本地數據
//聚合話費充值回調頁面,頁面的設置需要聯繫聚合客服更改 protected void Page_Load(object sender, EventArgs e) { var sporder_id = CommonManager.Web.Request("sporder_id", "");//聚合訂單ID var orderid = CommonManager.Web.Request("orderid", ""); //鼎鼎訂單ID var sta = CommonManager.Web.Request("sta", ""); //充值狀態1:成功 9:失敗 if (sta == "1") { //更新訂單狀態為充值成功 DbSession.Default.FromSql( @"UPDATE TOP(1) TPropLog SET PropStatus=@PropStatus WHERE Jhorderid = @Jhorderid") .AddInputParameter("@PropStatus", DbType.Int32, 4) .AddInputParameter("@Jhorderid", DbType.String, sporder_id) .Execute(); Response.Clear(); Response.Write("success"); Response.End(); } if (sta == "9") { //更新訂單狀態為充值成功 DbSession.Default.FromSql( @"UPDATE TOP(1) TPropLog SET PropStatus=@PropStatus WHERE Jhorderid = @Jhorderid") .AddInputParameter("@PropStatus", DbType.Int32, 5) .AddInputParameter("@Jhorderid", DbType.String, sporder_id) .Execute(); Response.Clear(); Response.Write("success"); Response.End(); //更新訂單狀態為充值失敗 } }
重點回顧:
1.JsonObject.DLL下載
2.簽名順序和字元要按照提供的做
3.回調地址要找客服設置
4.單個手機號每天有充值數量和次數的限制,超過次數會導致訂單一直提示進行中,最後失敗,失敗也會有回調提示的
5.測試的時候可以將vs自帶的iis調試工具配合ngrok映射到外網,這樣直接就可以調試回調頁面,改天我會寫一個簡單的教程,如何使用vs預設的iis映射到外網進行調試(微信的外網調試也可以這麼做,非常方便哦)