微信小程序之微信支付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[]]></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 * ).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 > )
- {
- 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, , 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, , 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 = ;
- 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 = ; 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、测试完成支付
优秀是一种习惯,欢迎大家关注学习
微信小程序之微信支付C#后台(统一下单)的更多相关文章
- 微信小程序腾讯云php后台解决方案
微信小程序腾讯云php后台解决方案 微信小程序前段需要添加必要的文件以配合后端 (1)wafer2-client-sdk sdk提供了几种接口包括登陆,获取用户openid,图片上传等 (2)conf ...
- 微信小程序之微信登陆 —— 微信小程序教程系列(20)
简介: 微信登陆,在新建一个微信小程序Hello World项目的时候,就可以看到项目中出现了我们的微信头像,其实这个Hello World项目,就有一个简化版的微信登陆.只不过是,还没有写入到咱们自 ...
- [转]微信小程序、微信公众号、H5之间相互跳转
本文转自:https://www.cnblogs.com/colorful-paopao1/p/8608609.html 转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加 ...
- 微信小程序、微信公众号、H5之间相互跳转
转自慕课网 一.小程序和公众号 答案是:可以相互关联. 在微信公众号里可以添加小程序. 图片有点小,我把文字打出来吧: 可关联已有的小程序或快速创建小程序.已关联的小程序可被使用在自定义菜单和模版消息 ...
- 微信小程序与微信公众号同一用户登录问题
微信小程序与微信公众号同一用户登录问题 最近在做微信小程序与微信公众号登录合并的接口.整理相关资料以及个人认识的心得写了这篇文章与大家一起分享. 首先,简单说下我遇到的问题是我们的程序调用微信小程序得 ...
- 微信小程序(微信应用号)开发ide安装解决方法
这两天整个技术圈都炸锅了,微信小程序(微信应用号)发布内测,首批200家收到邀请,但是没受邀请的同学,也不用担心,下面介绍一下解决方法. 首先需要下载ide,昨天只需要下载0.9版本的编辑器并替换文件 ...
- 微信小程序(原名微信应用号)开发工具0.9版安装教程
微信小程序全称微信公众平台·小程序,原名微信公众平台·应用号(简称微信应用号) 声明 微信小程序开发工具类似于一个轻量级的IDE集成开发环境,目前仅开放给了少部分受微信官方邀请的人士(据说仅200个名 ...
- 微信小程序(微信应用号)组件讲解[申明:来源于网络]
微信小程序(微信应用号)组件讲解[申明:来源于网络] 地址:http://www.cnblogs.com/muyixiaoguang/p/5902008.html
- 微信小程序和微信公众号的id是一个吗
首先,简单说下我遇到的问题是我们的程序调用微信小程序得到openid,然后通过openID得到用户的唯一标识,用户得以登录,然而,当我们调用微信公众号也同样的到openid,同一以用户两个不同的ope ...
随机推荐
- 【Python学习之四】递归与尾递归
看完廖雪峰老师的教程,感觉尾递归函数是一个相对难点.于是复习一下,思考了一下,发表一些见解,记录一下. 1.递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数 ...
- java实现可安装的exe程序
java实现可安装的exe程序 通过编写Java代码,实现可安装的exe文件的一般思路: 1.在eclipse中创建java项目,然后编写Java代码,将编写好的Java项目导出一个.jar格式的ja ...
- CodeForce--Benches
A. Benches There are nn benches in the Berland Central park. It is known that aiai people are curr ...
- PAT Basic 1079
1079 延迟的回文数(20 分) 给定一个 k+1 位的正整数 N,写成 ak⋯a1a0 的形式,其中对所有 i 有 0≤ai<10 且 ak>0.N 被称 ...
- 爬取豆瓣Top250_Ajax动态页面
爬取网址: 完整代码: import sys from urllib import request, parse import ssl ssl._create_default_https_contex ...
- 03008_ServletContext
1.什么是ServletContext? (1)ServletContext代表是一个web应用的环境(上下文)对象,ServletContext对象 内部封装是该web应用的信息,Servle ...
- JSONP分享-- 在JavaScript中跨域请求
如果你正在开发一个现代的基于web的应用程序,那么你: 在客户端使用JavaScript. 需要集成那些没有完全在你控制之下的服务(或者那些来自不同的域). 在你的浏览器控制台中遇到过这个错误信息: ...
- PHP define() 定义常量
PHP define()函数定义了运行时的常量, 具体语法如下所示: (PHP 4, PHP 5, PHP 7) define — Defines a named constant bool defi ...
- maven项目打包jar,含有依赖jar
在pom文件中添加一下插件 <plugin> <artifactId>maven-assembly-plugin</artifactId> <configur ...
- URAL 1099 Work scheduling 一般图的最大匹配 带花树算法(模板)
R - Work scheduling Time Limit:500MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u ...