微信小程序之微信支付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 ...
随机推荐
- (71)Received empty response from Zabbix Agent问题解决
刚接触zabbix新手少部分会出现如下错误: Received empty response from Zabbix Agent at [192.168.1.2]. Assuming that age ...
- 【netbeans】netbeans utf-8编码
首先,在你的netbeans的安装文件夹里面找到etc这个文件夹,打开,在里面找到netbeans.conf这个文件,打开,找到这一句netbeans_default_options="-J ...
- pandas时间数据的集成处理
工作中遇到的一个问题: 统计各地区新能源汽车的充电时长 数据来源是北理新源的单日全球的运行数据. 这里仅统计北上广重庆四个地区的 数据处理的代码就省略了 需要整理好的是4个dataframe(数据已保 ...
- Python基础(三)—— print()格式化输出变量
先举一个简单的例子说明: name = 'Jack' answer = input('你好,%s '%(name) + '你认识 Sean 不, 输入 yes or no\n') print('Sea ...
- python中文件操作的六种模式及对文件某一行进行修改的方法
一.python中文件操作的六种模式分为:r,w,a,r+,w+,a+ r叫做只读模式,只可以读取,不可以写入 w叫做写入模式,只可以写入,不可以读取 a叫做追加写入模式,只可以在末尾追加内容,不可以 ...
- 树莓派开发板入门学习笔记1:[转]资料收集及树莓派系统在Ubuntu安装
参考教程(微雪课堂):http://www.waveshare.net/study/portal.php 树莓派实验室: http://shumeipai.nxez.com/2014/12/21/us ...
- NordicSemiconductor.nRF_DeviceFamilyPack 更新历史记录
Version: 8.17.0 (2018-04-27) NordicSemiconductor.nRF_DeviceFamilyPack.8.17.0.packDownload For nRF528 ...
- POJ:2695-The Pilots Brothers' refrigerator
题目链接:http://poj.org/problem?id=2965 The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limi ...
- 数据挖掘算法——Apriori
在上一篇数据挖掘入门算法整理中提到,Apriori算法是关联规则算法中使用最为广泛的算法,这次我们就来学习下该算法的基本知识. 一.算法概述 Apriori 算法是一种最有影响力的挖掘布尔关联规则的频 ...
- xml编辑无提示?这么破!
在学习testng这个单元测试框架时,如果咱们碰到了编辑测试套件xml,不提示的情况(有提示方便咱们学习,并且testng的测试套件定义必须按照他的dtd文件约束来),咱们可以按照下面的步骤去解决这个 ...