一、微信小程式支付 1、微信小程式端請求支付介面 商戶在小程式中先調用該介面在微信支付服務後臺生成預支付交易單,返回正確的預支付交易後調起支付。具體可以查看介面示例。 介面傳入參數示例: 介面返回示例: 二、介面調用(C#) 1、支付介面方法 2、支付結果通知API 3、Utility類 4、Pay ...
一、微信小程式支付
1、微信小程式端請求支付介面
商戶在小程式中先調用該介面在微信支付服務後臺生成預支付交易單,返回正確的預支付交易後調起支付。具體可以查看介面示例。
介面傳入參數示例:
<xml> <appid>wx2421b1c4370ec43b</appid> <attach>支付測試</attach> <body>JSAPI支付測試</body> <mch_id>10000100</mch_id> <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str> <notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url> <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid> <out_trade_no>1415659990</out_trade_no> <spbill_create_ip>14.23.150.211</spbill_create_ip> <total_fee>1</total_fee> <trade_type>JSAPI</trade_type> <sign>0CB01533B8C1EF103065174F50BCA001</sign> </xml>
介面返回示例:
<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> <appid><![CDATA[wx2421b1c4370ec43b]]></appid> <mch_id><![CDATA[10000100]]></mch_id> <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str> <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid> <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign> <result_code><![CDATA[SUCCESS]]></result_code> <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id> <trade_type><![CDATA[JSAPI]]></trade_type> </xml>
二、介面調用(C#)
1、支付介面方法
//獲取請求數據 Dictionary<string, string> strParam = new Dictionary<string, string>(); //小程式ID strParam.Add("appid", PayInfo.appid); //附加數據 strParam.Add("attach", PayInfo.attach); //商品描述 strParam.Add("body", PayInfo.body); //商戶號 strParam.Add("mch_id", PayInfo.mchid); //隨機字元串 strParam.Add("nonce_str", PayInfo.nonceStr); //通知地址 (非同步接收微信支付結果通知的回調地址,通知url必須為外網可訪問的url,不能攜帶參數。) strParam.Add("notify_url", PayInfo.notifyUrl); //用戶標識 strParam.Add("openid", openId); //商戶訂單號 strParam.Add("out_trade_no", orderNum); //終端IP strParam.Add("spbill_create_ip", PayInfo.addrIp); //標價金額 strParam.Add("total_fee", Convert.ToInt32(orderTotal * 100).ToString()); //交易類型 strParam.Add("trade_type", PayInfo.tradeType); strParam.Add("sign", PayHelper.GetSignInfo(strParam, PayInfo.key)); //獲取預支付ID string preInfo = Utility.PostHttpResponse(PayInfo.orderUrl, PayHelper.CreateXmlParam(strParam)); string strCode = PayHelper.GetXmlValue(preInfo, "return_code"); string strMsg = PayHelper.GetXmlValue(preInfo, "return_msg"); if (strCode == "SUCCESS") { //再次簽名 string nonecStr = PayInfo.nonceStr; string timeStamp = PayInfo.timeStamp; string package = "prepay_id=" + PayHelper.GetXmlValue(preInfo, "prepay_id"); Dictionary<string, string> singInfo = new Dictionary<string, string>(); singInfo.Add("appId", PayInfo.appid); singInfo.Add("nonceStr", nonecStr); singInfo.Add("package", package); singInfo.Add("signType", PayInfo.signType); singInfo.Add("timeStamp", timeStamp); //返回參數 info.Msg = strMsg; info.Code = strCode; info.Id = orderId; info.appId = PayInfo.appid; info.orderGuId = orderNum; info.Package = package; info.TimeStamp = timeStamp; info.NonceStr = nonecStr; info.SignType = PayInfo.signType; info.PaySign = PayHelper.GetSignInfo(singInfo, PayInfo.key); listMsg.Add(info); result = u.SuccessMsg(listMsg, "", ""); } else { info.Code = strCode; info.Msg = strMsg; listMsg.Add(info); result = u.FailMsg(listMsg); }
2、支付結果通知API
/// <summary> /// 支付結果通知API /// </summary> /// <returns></returns> [HttpPost] public string OrderNotify() { string strResult = string.Empty; try { //1.獲取微信通知的參數 string strXML = Utility.GetPostStr(); //判斷是否請求成功 if (PayHelper.GetXmlValue(strXML, "return_code") == "SUCCESS") { //判斷是否支付成功 if (PayHelper.GetXmlValue(strXML, "result_code") == "SUCCESS") { //獲得簽名 string getSign = PayHelper.GetXmlValue(strXML, "sign"); //進行簽名 string sign = PayHelper.GetSignInfo(PayHelper.GetFromXml(strXML), PayInfo.key); if (sign == getSign) { //校驗訂單信息 string wxOrderNum = PayHelper.GetXmlValue(strXML, "transaction_id"); //微信訂單號 string orderNum = PayHelper.GetXmlValue(strXML, "out_trade_no"); //商戶訂單號 string orderTotal = PayHelper.GetXmlValue(strXML, "total_fee"); string openid = PayHelper.GetXmlValue(strXML, "openid"); //校驗訂單是否存在 if (true) { //2.更新訂單的相關狀態 //3.返回一個xml格式的結果給微信伺服器 if (obj > 0) { strResult = PayHelper.GetReturnXml("SUCCESS", "OK"); } else { strResult = PayHelper.GetReturnXml("FAIL", "訂單狀態更新失敗"); } } else { strResult = PayHelper.GetReturnXml("FAIL", "支付結果中微信訂單號資料庫不存在!"); } } else { strResult = PayHelper.GetReturnXml("FAIL", "簽名不一致!"); } } else { strResult = PayHelper.GetReturnXml("FAIL", "支付通知失敗!"); } } else { strResult = PayHelper.GetReturnXml("FAIL", "支付通知失敗!"); } #endregion } catch (Exception ex) { } return strResult; }
3、Utility類
/// <summary> /// 獲得Post過來的數據 /// </summary> /// <returns></returns> public static string GetPostStr() { Int32 intLen = Convert.ToInt32(HttpContext.Current.Request.InputStream.Length); byte[] b = new byte[intLen]; HttpContext.Current.Request.InputStream.Read(b, 0, intLen); return Encoding.UTF8.GetString(b); } /// <summary> /// 模擬POST提交 /// </summary> /// <param name="url">請求地址</param> /// <param name="xmlParam">xml參數</param> /// <returns>返回結果</returns> public static string PostHttpResponse(string url, string xmlParam) { HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url); myHttpWebRequest.Method = "POST"; myHttpWebRequest.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; // Encode the data byte[] encodedBytes = Encoding.UTF8.GetBytes(xmlParam); myHttpWebRequest.ContentLength = encodedBytes.Length; // Write encoded data into request stream Stream requestStream = myHttpWebRequest.GetRequestStream(); requestStream.Write(encodedBytes, 0, encodedBytes.Length); requestStream.Close(); HttpWebResponse result; try { result = (HttpWebResponse)myHttpWebRequest.GetResponse(); } catch { return string.Empty; } if (result.StatusCode == HttpStatusCode.OK) { using (Stream mystream = result.GetResponseStream()) { using (StreamReader reader = new StreamReader(mystream)) { return reader.ReadToEnd(); } } } return null; }
4、PayHelper類
#region 生成簽名 /// <summary> /// 獲取簽名數據 ///</summary> /// <param name="strParam"></param> /// <param name="key"></param> /// <returns></returns> public static string GetSignInfo(Dictionary<string, string> strParam, string key) { int i = 0; string sign = string.Empty; StringBuilder sb = new StringBuilder(); try { foreach (KeyValuePair<string, string> temp in strParam) { if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign") { continue; } i++; sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&"); } sb.Append("key=" + key.Trim() + ""); sign = MD5Core.GetHashString(sb.ToString(), Encoding.UTF8).ToUpper(); } catch (Exception ex) { Utility.AddLog("PayHelper", "GetSignInfo", ex.Message, ex); } return sign; } #endregion #region XML 處理 /// <summary> /// 獲取XML值 /// </summary> /// <param name="strXml">XML字元串</param> /// <param name="strData">欄位值</param> /// <returns></returns> public static string GetXmlValue(string strXml, string strData) { string xmlValue = string.Empty; XmlDocument xmlDocument = new XmlDocument(); xmlDocument.LoadXml(strXml); var selectSingleNode = xmlDocument.DocumentElement.SelectSingleNode(strData); if (selectSingleNode != null) { xmlValue = selectSingleNode.InnerText; } return xmlValue; } /// <summary> /// 集合轉換XML數據 (拼接成XML請求數據) /// </summary> /// <param name="strParam">參數</param> /// <returns></returns> public static string CreateXmlParam(Dictionary<string, string> strParam) { StringBuilder sb = new StringBuilder(); try { sb.Append("<xml>"); foreach (KeyValuePair<string, string> k in strParam) { if (k.Key == "attach" || k.Key == "body" || k.Key == "sign") { sb.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">"); } else { sb.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">"); } } sb.Append("</xml>"); } catch (Exception ex) { Utility.AddLog("PayHelper", "CreateXmlParam", ex.Message, ex); } return sb.ToString(); } /// <summary> /// XML數據轉換集合(XML數據拼接成字元串) /// </summary> /// <param name="xmlString"></param> /// <returns></returns> public static Dictionary<string, string> GetFromXml(string xmlString) { Dictionary<string, string> sParams = new Dictionary<string, string>(); 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) { Utility.AddLog("PayHelper", "GetFromXml", ex.Message, ex); } return sParams; } /// <summary> /// 返回通知 XML /// </summary> /// <param name="returnCode"></param> /// <param name="returnMsg"></param> /// <returns></returns> public static string GetReturnXml(string returnCode, string returnMsg) { StringBuilder sb = new StringBuilder(); sb.Append("<xml>"); sb.Append("<return_code><![CDATA[" + returnCode + "]]></return_code>"); sb.Append("<return_msg><![CDATA[" + returnMsg + "]]></return_msg>"); sb.Append("</xml>"); return sb.ToString(); } #endregion
5、PayInfo類
public class PayInfo { /// <summary> /// 小程式登錄API /// </summary> public static string loginUrl = ConfigurationManager.AppSettings["loginurl"].ToString(); /// <summary> /// 統一下單API /// </summary> public static string orderUrl = ConfigurationManager.AppSettings["orderurl"].ToString(); /// <summary> /// 支付結果通知API /// </summary> public static string notifyUrl = ConfigurationManager.AppSettings["notifyurl"].ToString(); /// <summary> /// 查詢訂單API /// </summary> public static string queryUrl = ConfigurationManager.AppSettings["queryurl"].ToString(); /// <summary> /// 申請退款API /// </summary> public static string refundUrl = ConfigurationManager.AppSettings["refundurl"].ToString(); /// <summary> /// 退款通知API /// </summary> public static string refundNotifyUrl = ConfigurationManager.AppSettings["refundnotifyurl"].ToString(); /// <summary> /// 退款通知API /// </summary> public static string refundQueryUrl = ConfigurationManager.AppSettings["refundqueryurl"].ToString(); /// <summary> /// 小程式唯一標識 /// </summary> public static string appid = ConfigurationManager.AppSettings["appid"].ToString(); /// <summary> /// 小程式的 app secret /// </summary> public static string secret = ConfigurationManager.AppSettings["secret"].ToString(); /// <summary> /// 小程式的授權類型 /// </summary> public static string grantType = ConfigurationManager.AppSettings["grant_type"].ToString(); /// <summary> /// 商戶號(微信支付分配的商戶號) /// </summary> public static string mchid = ConfigurationManager.AppSettings["mch_id"].ToString(); /// <summary> ///商戶平臺設置的密鑰key /// </summary> public static string key = ConfigurationManager.AppSettings["key"].ToString(); /// <summary> /// 隨機字元串不長於 32 位 /// </summary> public static string nonceStr = PayHelper.GetNonceStr(); /// <summary> /// 時間戳 從1970年1月1日00:00:00至今的秒數,即當前的時間 /// </summary> public static string timeStamp = PayHelper.GetTimeStamp(); /// <summary> /// 終端IP APP和網頁支付提交用戶端IP, /// </summary> public static string addrIp = PayHelper.GetIP; /// <summary> /// 交易類型 小程式取值如下:JSAPI /// </summary> public static string tradeType = "JSAPI"; /// <summary> /// 簽名類型 預設為MD5,支持HMAC-SHA256和MD5。 /// </summary> public static string signType = "MD5"; /// <summary> /// 商品描述 商品簡單描述,該欄位請按照規範傳遞 /// </summary> public static string body = "奇小愛的異想世界-支付"; /// <summary> /// 附加數據 在查詢API和支付通知中原樣返回 /// </summary> public static string attach = "微信支付信息"; /// <summary> /// 簽名,參與簽名參數:appid,mch_id,transaction_id,out_trade_no,nonce_str,key /// </summary> public string sign = ""; /// <summary> /// 微信訂單號,優先使用 /// </summary> public static string transactionid = ""; /// <summary> /// 商戶系統內部訂單號 /// </summary> public static string out_trade_no = ""; /// <summary> /// 商戶退款單號 /// </summary> public static string out_refund_no = ""; /// <summary> /// 退款金額 /// </summary> public static decimal refundfee; /// <summary> /// 訂單金額 /// </summary> public static decimal totalfee; }
三、微信小程式調用
1、小程式調用方法,發起支付,具體如下:
微信小程式支付方發起微信支付。
2、示例代碼:
wx.requestPayment({ 'timeStamp': '', 'nonceStr': '', 'package': '', 'signType': 'MD5', 'paySign': '', 'success':function(res){ }, 'fail':function(res){ } })
3、測試完成支付
優秀是一種習慣,歡迎大家關註學習