微信小程序之微信支付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 ...
随机推荐
- shell 练习题
1.编写脚本/bin/per.sh,判断当前用户对指定参数文件,是否不可读并且不可写 read -p "Please Input A File: " file if [ ! -e ...
- DAOMYSQLI工具类
<?php //DAOMySQLI.class.php //完成对mysql数据库操作,单例模式 //开发类 //1. 定类名 //2. 定成员属性 //3. 定成员方法[查询,dml操作] f ...
- python爬虫基础10-selenium大全4/8-Webelement
Selenium笔记(4)Webelement 本文集链接:https://www.jianshu.com/nb/25338984 这是通过find方法找到的页面元素,此对象提供了多种方法,让我们可以 ...
- Python入门基本语法
Python入门 以下主要讲述Python的一些基础语法,包含行的缩进在python中的重要意义,python中常见的保留字和引号的使用,如何实现单行注释和多行注释. print("he ...
- markdown快捷键
分组 功能 操作 快捷键 设置标题 一级标题 Heading1 Ctrl+1 二级标题 Heading2 Ctrl+2 三级标题 Heading3 Ctrl+3 四级标题 Heading4 Ctrl+ ...
- build.xml: 21: Class not found: javac1.8
在eclipse里运用ant时经常碰到class not found的错误提示,从而编译失败,其实是eclipse中本身的ant版本太老造成该的,但我今天安装的ant是1.8.4,感觉已经很新了,但编 ...
- 15年多校第一场七题hdu5294
要做这题,先要明白图的割,说白了就是 为了让原点无法到汇点要删几条边(之所以叫割,就是在图面上切一刀,减掉最小的边是原点和汇点成为两个集合),想到了割先放着一会用. 题中说只有沿最短路走才有可能追上, ...
- Python并发(二)
并发是指一次处理多件事,而并行是指一次做多件事.二者不同,但互相有联系.打个比方:像Python的多线程,就是并发,因为Python的解释器GIL是线程不安全的,一次只允许执行一个线程的Python字 ...
- JAVA 基础--final 关键字的用法
在java中,final的含义在不同的场景下有细微的差别,in a word,它指的是“不可变的” 1.修饰数据.这里的可以看到被final修饰的变量,值不能被改变,但是 package FinalT ...
- 自建NAS如何使用大于2TB的硬盘(从分区开始)
目录 自建NAS如何使用大于2TB的硬盘(从分区开始) 对分区进行格式化 挂载到某一目录(需设置开机自动挂载) 上传文件测试: 补充 自建NAS如何使用大于2TB的硬盘(从分区开始) 需求说明: 自建 ...