1. 程式人生 > >微信支付----PC掃碼支付(查詢微信支付訂單判斷是否支付成功)

微信支付----PC掃碼支付(查詢微信支付訂單判斷是否支付成功)

微信支付

c#webapi建議前端輪番查詢訂單狀態 #region 查詢掃碼訂單狀態 /// <summary> /// 查詢掃碼支付狀態 /// </summary> /// <param name="out_trade_no">支付訂單號</param> /// <returns></returns> [HttpGet] public ResponseMessage PayMent_Result(string out_trade_no) { if (out_trade_no != null) { PayMent pay = new PayMent(); OrderDetail detail = pay.geidingdan(out_trade_no); if (detail.trade_state == "SUCCESS")//支付成功 { try { 自己的業務邏輯(數據庫等等操作) } catch (Exception ex) { return new ResponseMessage { Code = -1};//系統異常 } return new ResponseMessage { Code = 1 }; } else if (detail.trade_state == "USERPAYING")//用戶支付中 { return new ResponseMessage { Code = 3 }; //return "3"; } else if (detail.trade_state == "NOTPAY")//未支付 { return new ResponseMessage { Code = 2 }; // return "2"; } else if (detail.trade_state == "PAYERROR")//支付失敗 { return new ResponseMessage { Code = 4 }; //return "4"; ; } } return new ResponseMessage { Code = 0 }; //其他狀態 } #endregion #region 返回前端使用的code_url -----自己定義API接口 -----調用NATIVEPayMent 方法傳入方法的參數,判斷返回結果如果為""說明微信統一下單失敗了,可以在統一下單返回結果寫入日誌文件,查看失敗原因。 #endregion ----------ENDAPI--------------------------------------------------------------------------------------------- /// <summary> /// 微信掃碼支付 /// </summary> /// <param name="appid">公眾號ID</param> /// <param name="boby">商品描述</param> /// <param name="mch_id">商戶號</param> /// <param name="spbill_create_ip">終端IP</param> /// <param name="total_fee">金額</param> /// <param name="out_trade_no">商戶訂單號</param> /// <param name="paysignkey">證書密匙</param> /// <param name="product_id">二維碼中包含的商品ID</param> /// <returns></returns> public string NATIVEPayMent (string boby, string spbill_create_ip, Double total_fee, string out_trade_no, string product_id) { UnifiedOrder order = new UnifiedOrder(); order.appid = WXconfig.appid; order.attach = "服務費"; order.body = boby; order.device_info = ""; order.mch_id = WXconfig.mch_id; order.nonce_str = TenpayUtil.getNoncestr(); order.notify_url = Wxconfig.url; order.out_trade_no = out_trade_no; order.product_id = product_id; order.trade_type = "NATIVE"; order.spbill_create_ip = spbill_create_ip; order.total_fee = Convert.ToInt32((total_fee) * 100); TenpayUtil tenpay = new TenpayUtil(); string paySignKey = WXconfig.paysignkey; string code_url = tenpay.getcode_url(order, paySignKey); return code_url; } /// <summary> /// 查詢掃碼訂單情況 /// </summary> /// <param name="out_trade_no">商戶訂單號</param> /// <returns></returns> public OrderDetail geidingdan(string out_trade_no) { TenpayUtil tenpay = new TenpayUtil(); OrderDetail detail = tenpay.getOrderDetail(out_trade_no); return detail; } public class TenpayUtil { #region url /// <summary> /// 統一支付接口 /// </summary> const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; /// <summary> /// 網頁授權接口 /// </summary> const string access_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token"; /// <summary> /// 微信訂單查詢接口 /// </summary> const string OrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery"; #endregion #region 隨機串,時間截 /// <summary> /// 隨機串 /// </summary> public static string getNoncestr() { Random random = new Random(); return MD5Util.GetMD5(random.Next(1000).ToString(), "GBK").ToLower().Replace("s", "S"); } /// <summary> /// 時間截,自1970年以來的秒數 /// </summary> public static string getTimestamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } #endregion /// <summary> /// 網頁授權接口 /// </summary> public static string getAccess_tokenUrl() { return access_tokenUrl; } #region 把微信掃碼支付的回調XML轉換集合 public string GetXml(string xmlstring) { SortedDictionary < string, object> sd= GetInfoFromXml(xmlstring); string reslut = ""; foreach (KeyValuePair<string, object> s in sd) { if (s.Key == "result_code") { reslut= s.Value.ToString(); } } return reslut; } #endregion #region 獲取微信簽名 /// <summary> /// 獲取微信簽名 /// </summary> /// <param name="sParams"></param> /// <returns></returns> public string getsign(SortedDictionary<string, object> sParams, string key) { int i = 0; string sign = string.Empty; StringBuilder sb = new StringBuilder(); foreach (KeyValuePair<string, object> temp in sParams) { if (temp.Value.ToString() == "" || temp.Value == null || temp.Key.ToLower() == "sign") { continue; } i++; sb.Append(temp.Key.Trim() + "=" + temp.Value.ToString() + "&"); } sb.Append("key=" + key.Trim() + ""); string signkey = sb.ToString(); sign = MD5Util.GetMD5(signkey, "utf-8"); //utf-8 return sign; } #endregion #region post數據到指定接口並返回數據 /// <summary> /// post數據到指定接口並返回數據 /// </summary> public string PostXmlToUrl(string url, string postData,string type="") { string returnmsg = ""; using (System.Net.WebClient wc = new System.Net.WebClient()) { if (type != "") { Encoding encoding = Encoding.UTF8; wc.Encoding = System.Text.Encoding.GetEncoding("GB2312"); byte[] data = encoding.GetBytes(postData); returnmsg = Encoding.UTF8.GetString(wc.UploadData(url, "POST", data)); } else returnmsg = wc.UploadString(url, "POST", postData); } return returnmsg; } #endregion #region 獲取code_url /// <summary> /// 獲取code_url /// </summary> public string getcode_url(UnifiedOrder order, string key) { string code_url = ""; string post_data = getUnifiedOrderXml(order, key); string request_data = PostXmlToUrl(UnifiedPayUrl, post_data); //string request_data = HttpRequestutil.RequestUrl(UnifiedPayUrl, post_data, "post"); SortedDictionary<string, object> requestXML = GetInfoFromXml(request_data); foreach (KeyValuePair<string, object> k in requestXML) { if (k.Key == "code_url") { code_url = k.Value.ToString(); break; } } return code_url; } #endregion #region 獲取prepay_id /// <summary> /// 獲取prepay_id /// </summary> public string getPrepay_id(UnifiedOrder order, string key) { string prepay_id = ""; string post_data = getUnifiedOrderXml(order, key); string request_data = PostXmlToUrl(UnifiedPayUrl, post_data); SortedDictionary<string, object> requestXML = GetInfoFromXml(request_data); foreach (KeyValuePair<string, object> k in requestXML) { if (k.Key == "prepay_id") { prepay_id = k.Value.ToString(); break; } } return prepay_id; } #endregion #region 獲取微信訂單明細 /// <summary> /// 獲取微信訂單明細 /// </summary> public OrderDetail getOrderDetail(string out_trade_no) { string post_data = getQueryOrderXml(out_trade_no); string request_data = PostXmlToUrl(OrderQueryUrl, post_data,"1"); OrderDetail orderdetail = new OrderDetail(); SortedDictionary<string, object> requestXML = GetInfoFromXml(request_data); foreach (KeyValuePair<string, object> k in requestXML) { switch (k.Key) { case "retuen_code": orderdetail.result_code = k.Value.ToString(); break; case "return_msg": orderdetail.return_msg = k.Value.ToString(); break; case "appid": orderdetail.appid = k.Value.ToString(); break; case "mch_id": orderdetail.mch_id = k.Value.ToString(); break; case "nonce_str": orderdetail.nonce_str = k.Value.ToString(); break; case "sign": orderdetail.sign = k.Value.ToString(); break; case "result_code": orderdetail.result_code = k.Value.ToString(); break; case "err_code": orderdetail.err_code = k.Value.ToString(); break; case "err_code_des": orderdetail.err_code_des = k.Value.ToString(); break; case "trade_state": orderdetail.trade_state = k.Value.ToString(); break; case "device_info": orderdetail.device_info = k.Value.ToString(); break; case "openid": orderdetail.openid = k.Value.ToString(); break; case "is_subscribe": orderdetail.is_subscribe = k.Value.ToString(); break; case "trade_type": orderdetail.trade_type = k.Value.ToString(); break; case "bank_type": orderdetail.bank_type = k.Value.ToString(); break; case "total_fee": orderdetail.total_fee = k.Value.ToString(); break; case "coupon_fee": orderdetail.coupon_fee = k.Value.ToString(); break; case "fee_type": orderdetail.fee_type = k.Value.ToString(); break; case "transaction_id": orderdetail.transaction_id = k.Value.ToString(); break; case "out_trade_no": orderdetail.out_trade_no = k.Value.ToString(); break; case "attach": orderdetail.attach = k.Value.ToString(); break; case "time_end": orderdetail.time_end = k.Value.ToString(); break; default: break; } } return orderdetail; } #endregion #region #region 把XML數據轉換為SortedDictionary /// <summary> /// 把XML數據轉換為SortedDictionary<string, string>集合 /// </summary> /// <param name="strxml"></param> /// <returns></returns> protected SortedDictionary<string, object> GetInfoFromXml(string xmlstring) { SortedDictionary<string, object> sParams = new SortedDictionary<string, object>(); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlstring); XmlElement root = doc.DocumentElement; int len = root.ChildNodes.Count; for (int i = 0; i < len; i++) { string name = root.ChildNodes[i].Name; if (!sParams.ContainsKey(name)) { sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim()); } } } catch(Exception ex ) { } return sParams; } #endregion #region 微信統一下單接口xml參數整理 /// <summary> /// 微信統一下單接口xml參數整理 /// </summary> /// <param name="order">微信支付參數實例</param> /// <param name="key">密鑰</param> /// <returns></returns> protected string getUnifiedOrderXml(UnifiedOrder order, string key) { string return_string = string.Empty; SortedDictionary<string, object> sParams = new SortedDictionary<string, object>(); sParams.Add("appid", order.appid); sParams.Add("attach", order.attach); sParams.Add("body", order.body); sParams.Add("device_info", order.device_info); sParams.Add("mch_id", order.mch_id); sParams.Add("nonce_str", order.nonce_str); sParams.Add("notify_url", order.notify_url); //當 trade_type=JSAPI 時必輸入 sParams.Add("openid", order.openid); //當 trade_type=NATIVE 時必輸入 // sParams.Add("product_id", order.product_id); sParams.Add("out_trade_no", order.out_trade_no); sParams.Add("spbill_create_ip", order.spbill_create_ip); sParams.Add("total_fee", order.total_fee); sParams.Add("trade_type", order.trade_type); order.sign = getsign(sParams, key); sParams.Add("sign", order.sign); //拼接成XML請求數據 StringBuilder sbPay = new StringBuilder(); foreach (KeyValuePair<string, object> k in sParams) { if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") { sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); } else { sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); } } return_string = string.Format("<xml>{0}</xml>", sbPay.ToString()); byte[] byteArray = Encoding.UTF8.GetBytes(return_string); return_string = Encoding.GetEncoding("GBK").GetString(byteArray); Byte[] temp = Encoding.UTF8.GetBytes(return_string); string dataGBK = Encoding.GetEncoding("utf-8").GetString(temp); return return_string; // GBK } #endregion #region 微信訂單查詢接口XML參數整理 /// <summary> /// 微信訂單查詢接口XML參數整理 /// </summary> /// <param name="queryorder">微信訂單查詢參數實例</param> /// <param name="key">密鑰</param> /// <returns></returns> protected string getQueryOrderXml(string out_trade_no) { string return_string = string.Empty; SortedDictionary<string, object> sParams = new SortedDictionary<string, object>(); sParams.Add("appid", WXconfig.appid); sParams.Add("mch_id", WXconfig.mch_id); // sParams.Add("transaction_id", queryorder.transaction_id); sParams.Add("out_trade_no", out_trade_no); sParams.Add("nonce_str", getNoncestr()); string sign = getsign(sParams, WXconfig.paysignkey); sParams.Add("sign", sign); //拼接成XML請求數據 StringBuilder sbPay = new StringBuilder(); foreach (KeyValuePair<string, object> k in sParams) { if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") { sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); } else { sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); } } return_string = string.Format("<xml>{0}</xml>", sbPay.ToString().TrimEnd(',')); return return_string; } #endregion #endregion } public class MD5Util { public MD5Util() { // // TODO: 在此處添加構造函數邏輯 // } /// <summary> /// /** 獲取大寫的MD5簽名結果 */ /// </summary> /// <param name="encypStr">數據</param> /// <param name="charset">編碼格式</param> /// <returns></returns> public static string GetMD5(string encypStr, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //創建md5對象 byte[] inputBye; byte[] outputBye; //使用GB2312編碼方式把字符串轉化為字節數組. try { inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr); } catch (Exception ex) { inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; } /// <summary> /// SHA1加密 /// </summary> /// <param name="str"></param> /// <returns></returns> public static string sha1(string str) { return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "sha1").ToLower(); } }



1.1 獲取掃碼支付的結果接口(建議輪番獲取狀態)

請求方式:http get

接口參數說明

名稱

類型

必填

說明

out_trade_no

String

支付訂單ID

返回結果: code :1//支付成功

返回結果: code :2//未支付

返回結果: code :3//用戶支付中

返回結果: code :4//支付失敗

返回結果: code :0//其他狀態

返回結果: code :-1//系統異常

備註:(code 不為-11的時候輪番調取接口,建議時間為1s~2s,-1的時候,提示系統異常,聯系管理員。為1的時候跳到完成頁面。)


訂單查詢說明:微信支付雖然有回調(個人認為比較坑),這裏我是用了自己支付訂單號去查詢微信支付的該訂單狀態。(微信文檔有說明,有2個方式,一個回調,一個用支付訂單查詢訂單狀態)

微信支付----PC掃碼支付(查詢微信支付訂單判斷是否支付成功)