开发环境:.NET MVC+ ORM框架(EF)
一、参考文档:
1、微信JSAPI支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_3&index=1;
二、开发前准备:
1、必须申请微信公众平台(企业用户开通);
2、必须开通小程序平台,并与微信公众平台进行绑定;
3、必须开通微信商户平台,并妥善保管号商户号和商户密钥;
(值得说明的是:微信商户密钥在拿到手之后,请首先重置三次以上,具体原因不清楚,但是不重置的话,后期开发的时候,微信统一下单接口会频繁报错,而且错误信息莫名其妙,主要报错信息为:“签名错误”,即使你的参数签名在微信的签名校验工具中校验通过,也会提示你“签名错误”,但是此时你无需对接口做任何改动,只需要重置商户密钥3次以上,此问题便可解决)
4、网站升级https协议,因为调用微信支付成功后,微信服务器会对你传值的回调地址(notify_url字段,可以理解为具体的业务逻辑处理方法路径)进行回调,(虽然目前统一下单接口可以回调http协议接口,但是仍然建议网站升级为https协议);
三、支付流程
1、统一下单接口,后台通过统一下单接口,向微信请求下单支付,微信后台接到参数后,会生成一个商户订单,并将预下单id(prepay_id 这个返回字段很重要)返回给后台;
2、后台接收微信返回值,进行二次签名,并将签名的参数返回给小程序前台;
3、小程序端接收到签名参数后,调用 wx.requestPayment 方法,传入参数,调起收银台;
4、用户支付后,微信服务器处理本次支付情况,并回调后台业务处理接口。
四、代码实现
1、微信支付model类:
public class PayModel { /// summary /// 统一下单API /// /summary public static string orderUrl = ConfigurationManager.AppSettings["WXunifiedorder"].ToString(); /// summary /// 支付结果通知API /// /summary public static string notifyUrl = ConfigurationManager.AppSettings["WxPayNotifyurl"].ToString(); /// summary /// 查询订单API /// /summary public static string queryUrl = ConfigurationManager.AppSettings["WxPayQueryOrder"].ToString(); /// summary /// 小程序唯一标识 /// /summary public static string AppID = ConfigurationManager.AppSettings["WxAppId"].ToString(); /// summary /// 小程序的 app secret /// /summary public static string secret = ConfigurationManager.AppSettings["WxSecret"].ToString(); /// summary /// 商户号(微信支付分配的商户号) /// /summary public static string mchid = ConfigurationManager.AppSettings["WxMerchantNo"].ToString(); /// summary ///商户平台设置的密钥key /// /summary public static string WxMerchantKey = ConfigurationManager.AppSettings["WxMerchantKey"].ToString(); /// summary /// 随机字符串不长于 32 位 /// /summary public static string nonceStr = RandomNum.CreateRandomNum(32).ToUpper(); /// summary /// 时间戳 从1970年1月1日00:00:00至今的秒数,即当前的时间 /// /summary public static string timeStamp = Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString(); /// 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 string transactionid = ""; /// summary /// 商户系统内部订单号 /// /summary public string out_trade_no = ""; /// summary /// 订单金额 /// /summary public decimal totalfee=0; }
public class OrderReloadModel { public string return_msg { get; set; } public string return_code { get; set; } public string orderNo { get; set; } public string AppID { get; set; } public string package { get; set; } public string timeStamp { get; set; } public string nonecStr { get; set; } public string signType { get; set; } public string paysign { get; set; } }
2、微信支付帮助类
public class PayHelper { #region 生成签名 /// summary /// 获取签名数据 ////summary /// param name="strParam"/param /// param name="key"/param /// returns/returns public static string GetSignInfo(Dictionarystring, string strParam, string key) { int i = 0; string sign = string.Empty; StringBuilder sb = new StringBuilder(); try { foreach (KeyValuePairstring, 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 = CryptoService.Md5EncryptStr(sb.ToString()).ToUpper(); LogHelper.Writer("服务端参数:" + sb.ToString() + "签名:" + sign, "", 5); } catch (Exception ex) { throw 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(Dictionarystring, string strParam) { StringBuilder sb = new StringBuilder(); try { sb.Append("xml"); foreach (KeyValuePairstring, 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) { throw ex; // AddLog("PayHelper", "CreateXmlParam", ex.Message, ex); } var a = sb.ToString(); return sb.ToString(); } /// summary /// XML数据转换集合(XML数据拼接成字符串) /// /summary /// param name="xmlString"/param /// returns/returns public static Dictionarystring, string GetFromXml(string xmlString) { Dictionarystring, string sParams = new Dictionarystring, 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) { throw 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 /// 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提交 (不需要微信API证书) /// /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"版权声明
即速应用倡导尊重与保护知识产权。如发现本站文章存在版权问题,烦请提供版权疑问、身份证明、版权证明、联系方式等发邮件至197452366@qq.com ,我们将及时处理。本站文章仅作分享交流用途,作者观点不等同于即速应用观点。用户与作者的任何交易与本站无关,请知悉。













