当前位置:
首页 > Python基础教程 >
-
C#教程之微信小程序之微信支付C#后台(统一下单
一、微信小程序支付
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(
栏目列表
最新更新
nodejs爬虫
Python正则表达式完全指南
爬取豆瓣Top250图书数据
shp 地图文件批量添加字段
爬虫小试牛刀(爬取学校通知公告)
【python基础】函数-初识函数
【python基础】函数-返回值
HTTP请求:requests模块基础使用必知必会
Python初学者友好丨详解参数传递类型
如何有效管理爬虫流量?
SQL SERVER中递归
2个场景实例讲解GaussDB(DWS)基表统计信息估
常用的 SQL Server 关键字及其含义
动手分析SQL Server中的事务中使用的锁
openGauss内核分析:SQL by pass & 经典执行
一招教你如何高效批量导入与更新数据
天天写SQL,这些神奇的特性你知道吗?
openGauss内核分析:执行计划生成
[IM002]Navicat ODBC驱动器管理器 未发现数据
初入Sql Server 之 存储过程的简单使用
这是目前我见过最好的跨域解决方案!
减少回流与重绘
减少回流与重绘
如何使用KrpanoToolJS在浏览器切图
performance.now() 与 Date.now() 对比
一款纯 JS 实现的轻量化图片编辑器
关于开发 VS Code 插件遇到的 workbench.scm.
前端设计模式——观察者模式
前端设计模式——中介者模式
创建型-原型模式