微信APP支付 - C#
最近挺忙的,没时间写东西。然后在弄微信APP支付,网上的搜索一趟,都比较凌乱,我也遇到一些坑,不过也算弄好了,记录分享一下。
1、准备各种调用接口需要的参数,配置app.config。
<!--AppID-->
<add key="AppID" value="" />
<!--AppSecret-->
<add key="AppSecret" value="" />
<!--商户号-->
<add key="MchID" value="" />
<!--APIKey-->
<add key="APIKey" value="" />
2、调用统一下单API,直接上代码了。
/// <summary>
/// Builds the request.
/// </summary>
/// <returns></returns>
public static string BuildRequest()
{
var dicParam = CreateParam();
var signString = CreateURLParamString(dicParam);
var preString = signString + "&key=" + ConfigHelper.APIKey;
var sign = Sign(preString, "utf-8").ToUpper();
dicParam.Add("sign", sign);
return BuildForm(dicParam);
}
/// <summary>
/// Generates the out trade no.
/// </summary>
/// <returns></returns>
private static string GenerateOutTradeNo()
{
var ran = new Random();
return $"{ConfigHelper.MchID}{DateTime.Now:yyyyMMddHHmmss}{ran.Next(999)}";
}
/// <summary>
/// Signs the specified prestr.
/// </summary>
/// <param name="prestr">The prestr.</param>
/// <param name="_input_charset">The input charset.</param>
/// <returns></returns>
private static string Sign(string prestr, string _input_charset)
{
var sb = new StringBuilder(32);
MD5 md5 = new MD5CryptoServiceProvider();
var t = md5.ComputeHash(Encoding.GetEncoding(_input_charset).GetBytes(prestr));
foreach (var t1 in t)
{
sb.Append(t1.ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}
/// <summary>
/// Creates the parameter.
/// </summary>
/// <returns></returns>
private static SortedDictionary<string, string> CreateParam()
{
const string amount = "1";
double dubamount;
double.TryParse(amount, out dubamount);
var notify_url = ConfigHelper.WebSiteUrl + "/api/v1/testWeiXin"; //支付完成后的回调处理页面
const string detail = "xxxx";
var dic = new SortedDictionary<string, string>
{
{"appid", ConfigHelper.AppID},//账号ID
{"mch_id", ConfigHelper.MchID},//商户号
{"nonce_str", Guid.NewGuid().ToString().Replace("-", "")},//随机字符串
{"body", detail}, //商品描述
{"out_trade_no", GenerateOutTradeNo()},//商户订单号
{"total_fee", (dubamount * 100).ToString(CultureInfo.InvariantCulture)},//总金额
{"spbill_create_ip", GeneralHelper.GetIP()},//终端IP
{"notify_url", notify_url},//通知地址
{"trade_type", "APP"}//交易类型
};
return dic;
}
/// <summary>
/// Creates the URL parameter string.
/// </summary>
/// <param name="dicArray">The dic array.</param>
/// <returns></returns>
private static string CreateURLParamString(SortedDictionary<string, string> dicArray)
{
var prestr = new StringBuilder();
foreach (var temp in dicArray.OrderBy(o => o.Key))
{
prestr.Append(temp.Key + "=" + temp.Value + "&");
}
var nLen = prestr.Length;
prestr.Remove(nLen - 1, 1);
return prestr.ToString();
}
/// <summary>
/// Builds the form.
/// </summary>
/// <param name="dicParam">The dic parameter.</param>
/// <returns></returns>
private static string BuildForm(SortedDictionary<string, string> dicParam)
{
var sbXML = new StringBuilder();
sbXML.Append("<xml>");
foreach (var temp in dicParam)
{
sbXML.Append("<" + temp.Key + ">" + temp.Value + "</" + temp.Key + ">");
}
sbXML.Append("</xml>");
return sbXML.ToString();
}
/// <summary>
/// Froms the XML.
/// </summary>
/// <param name="xml">The XML.</param>
/// <returns></returns>
/// <exception cref="Exception">将空的xml串转换为WxPayData不合法!</exception>
public static SortedDictionary<string, string> FromXml(string xml)
{
var sortDic = new SortedDictionary<string, string>();
if (string.IsNullOrEmpty(xml))
{
throw new Exception("将空的xml串转换为WxPayData不合法!");
}
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
var xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
var nodes = xmlNode.ChildNodes;
foreach (XmlNode xn in nodes)
{
var xe = (XmlElement)xn;
if (!sortDic.ContainsKey(xe.Name))
sortDic.Add(xe.Name, xe.InnerText);
}
return sortDic;
}
/// <summary>
/// Posts the specified URL.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="content">The content.</param>
/// <param name="contentType">Type of the content.</param>
/// <returns></returns>
/// <exception cref="Exception">POST请求错误" + e</exception>
public static string Post(string url, string content, string contentType = "application/x-www-form-urlencoded")
{
string result;
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
var stringContent = new StringContent(content, Encoding.UTF8);
var response = client.PostAsync(url, stringContent).Result;
result = response.Content.ReadAsStringAsync().Result;
}
}
catch (Exception e)
{
throw new Exception("POST请求错误" + e);
}
return result;
}
3、生成预付订单,获取prepay_id。
/// <summary>
/// Gets the value from dic.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dic">The dic.</param>
/// <param name="key">The key.</param>
/// <returns></returns>
public static T GetValueFromDic<T>(IDictionary<string, string> dic, string key)
{
string val;
dic.TryGetValue(key, out val);
var returnVal = default(T);
if (val != null)
returnVal = (T)Convert.ChangeType(val, typeof(T));
return returnVal;
}
/// <summary>
/// Builds the application pay.
/// </summary>
/// <param name="prepayid">The prepayid.</param>
/// <returns></returns>
public static string BuildAppPay(string prepayid)
{
var dicParam = CreateWapAndAppPayParam(prepayid);
var signString = CreateURLParamString(dicParam);
var preString = signString + "&key=" + ConfigHelper.APIKey;
var sign = Sign(preString, "utf-8").ToUpper();
dicParam.Add("sign", sign);
return JsonConvert.SerializeObject(
new
{
appid = dicParam["appid"],
partnerid = dicParam["partnerid"],
prepayid = dicParam["prepayid"],
package = dicParam["package"],
noncestr = dicParam["noncestr"],
timestamp = dicParam["timestamp"],
sign = dicParam["sign"]
});
}
/// <summary>
/// Creates the wap and application pay parameter.
/// </summary>
/// <param name="prepayId">The prepay identifier.</param>
/// <returns></returns>
private static SortedDictionary<string, string> CreateWapAndAppPayParam(string prepayId)
{
var dic = new SortedDictionary<string, string>
{
{"appid", ConfigHelper.AppID},//公众账号ID
{"partnerid", ConfigHelper.MchID},//商户号
{"prepayid", prepayId},//预支付交易会话ID
{"package", "Sign=WXPay"},//扩展字段
{"noncestr", Guid.NewGuid().ToString().Replace("-", "")},//随机字符串
{
"timestamp",
(Convert.ToInt32((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds)).ToString()
}//时间戳
};
return dic;
}
/// <summary>
/// Validatons the query result.
/// </summary>
/// <param name="dic">The dic.</param>
/// <returns></returns>
public static bool ValidatonQueryResult(SortedDictionary<string, string> dic)
{
var result = false;
if (dic.ContainsKey("return_code") && dic.ContainsKey("return_code"))
{
if (dic["return_code"] == "SUCCESS" && dic["result_code"] == "SUCCESS")
result = true;
}
if (result) return true;
var sb = new StringBuilder();
foreach (var item in dic.Keys)
{
sb.Append(item + ":" + dic[item] + "|");
}
return false;
}
4、调用获取支付信息,给到APP发起支付操作。
var requestXml = WeiXinUtil.BuildRequest();
var resultXml = WeiXinUtil.Post("https://api.mch.weixin.qq.com/pay/unifiedorder", requestXml);
var dic = WeiXinUtil.FromXml(resultXml);
string returnCode;
dic.TryGetValue("return_code", out returnCode);
if (returnCode == "SUCCESS")
{
var prepay_id = WeiXinUtil.GetValueFromDic<string>(dic, "prepay_id");
if (!string.IsNullOrEmpty(prepay_id))
{
var payInfo = JsonConvert.DeserializeObject<WeiXinUtil.WxPayModel>(WeiXinUtil.BuildAppPay(prepay_id));
json.Add(new JProperty("appid", payInfo.appid));
json.Add(new JProperty("partnerid", payInfo.partnerid));
json.Add(new JProperty("prepayid", payInfo.prepayid));
json.Add(new JProperty("package", payInfo.package));
json.Add(new JProperty("noncestr", payInfo.noncestr));
json.Add(new JProperty("timestamp", payInfo.timestamp));
json.Add(new JProperty("sign", payInfo.sign));
json.Add(new JProperty("code", 0));
json.Add(new JProperty("msg", "成功"));
return this.Jsonp(json.ToString());
}
else
{
json.Add(new JProperty("code", 40028));
json.Add(new JProperty("msg", "支付错误:" + WeiXinUtil.GetValueFromDic<string>(dic, "err_code_des")));
return this.Jsonp(json.ToString());
}
}
else
{
return this.Jsonp(ApiException.OrderFailed());
}
5、APP支付完成,获得回调信息,就OK了。
var context = this.HttpContext;
var request = context.Request;
var verifyResult = false;
var requestXml = WeiXinUtil.GetRequestXmlData(request);
var dic = WeiXinUtil.FromXml(requestXml);
var returnCode = WeiXinUtil.GetValueFromDic<string>(dic, "return_code");
if (!string.IsNullOrEmpty(returnCode) && returnCode == "SUCCESS")//通讯成功
{
var result = WeiXinUtil.WePayNotifyValidation(dic);
if (result)
{
var transactionid = WeiXinUtil.GetValueFromDic<string>(dic, "transaction_id");
if (!string.IsNullOrEmpty(transactionid))
{
var queryXml = WeiXinUtil.BuildQueryRequest(transactionid, dic);
var queryResult = WeiXinUtil.Post("https://api.mch.weixin.qq.com/pay/orderquery", queryXml);
var queryReturnDic = WeiXinUtil.FromXml(queryResult);
if (WeiXinUtil.ValidatonQueryResult(queryReturnDic))//查询成功
{
verifyResult = true;
var status = WeiXinUtil.GetValueFromDic<string>(dic, "result_code");
if (!string.IsNullOrEmpty(status) && status == "SUCCESS")
{
var order = new Order()
{
OrderNumber = WeiXinUtil.GetValueFromDic<string>(dic, "out_trade_no"),
TransactionId = transactionid,
ProductPrice = WeiXinUtil.GetValueFromDic<decimal>(dic, "total_fee") / 100,
TradeType = WeiXinUtil.GetValueFromDic<string>(dic, "trade_type"),
BankType = WeiXinUtil.GetValueFromDic<string>(dic, "bank_type"),
PayDate = DateTime.Parse(WeiXinUtil.GetValueFromDic<string>(dic, "time_end")),
StatusId = 1,
IsPresent = false,
AddDate = DateTime.Now,
IsDelete = false
};
CURD.Add(order, ConfigHelper.WriteDB);
WeiXinUtil.BuildReturnXml("OK", "成功");
}
}
else
WeiXinUtil.BuildReturnXml("FAIL", "订单查询失败");
}
else
WeiXinUtil.BuildReturnXml("FAIL", "支付结果中微信订单号不存在");
}
else
WeiXinUtil.BuildReturnXml("FAIL", "签名失败");
}
else
{
string returnmsg;
dic.TryGetValue("return_msg", out returnmsg);
throw new Exception("异步通知错误:" + returnmsg);
}
return verifyResult;
/// <summary>
/// Gets the request XML data.
/// </summary>
/// <param name="request">The request.</param>
/// <returns></returns>
public static string GetRequestXmlData(HttpRequestBase request)
{
var stream = request.InputStream;
int count;
var buffer = new byte[1024];
var builder = new StringBuilder();
while ((count = stream.Read(buffer, 0, 1024)) > 0)
{
builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
}
stream.Flush();
stream.Close();
return builder.ToString();
}
/// <summary>
/// Wes the pay notify validation.
/// </summary>
/// <param name="dic">The dic.</param>
/// <returns></returns>
public static bool WePayNotifyValidation(SortedDictionary<string, string> dic)
{
var sign = GetValueFromDic<string>(dic, "sign");
if (dic.ContainsKey("sign"))
{
dic.Remove("sign");
}
var tradeType = GetValueFromDic<string>(dic, "trade_type");
var preString = CreateURLParamString(dic);
if (string.IsNullOrEmpty(tradeType))
{
var preSignString = preString + "&key=" + ConfigHelper.APIKey;
var signString = Sign(preSignString, "utf-8").ToUpper();
return signString == sign;
}
else
return false;
}
/// <summary>
/// Builds the query request.
/// </summary>
/// <param name="transactionId">The transaction identifier.</param>
/// <param name="dic">The dic.</param>
/// <returns></returns>
public static string BuildQueryRequest(string transactionId, SortedDictionary<string, string> dic)
{
var dicParam = CreateQueryParam(transactionId);
var signString = CreateURLParamString(dicParam);
var key = ConfigHelper.APIKey;
var preString = signString + "&key=" + key;
var sign = Sign(preString, "utf-8").ToUpper();
dicParam.Add("sign", sign);
return BuildForm(dicParam);
}
/// <summary>
/// Creates the query parameter.
/// </summary>
/// <param name="transactionId">The transaction identifier.</param>
/// <returns></returns>
private static SortedDictionary<string, string> CreateQueryParam(string transactionId)
{
var dic = new SortedDictionary<string, string>
{
{"appid", ConfigHelper.AppID},//公众账号ID
{"mch_id", ConfigHelper.MchID},//商户号
{"nonce_str", Guid.NewGuid().ToString().Replace("-", "")},//随机字符串
{"transaction_id", transactionId}//微信订单号
};
return dic;
}
/// <summary>
/// Builds the return XML.
/// </summary>
/// <param name="code">The code.</param>
/// <param name="returnMsg">The return MSG.</param>
/// <returns></returns>
public static string BuildReturnXml(string code, string returnMsg)
{
return
$"<xml><return_code><![CDATA[{code}]]></return_code><return_msg><![CDATA[{returnMsg}]]></return_msg></xml>";
}
6、总结:这个可以直接拿来用了,反反复复测试了很多遍,遇到的问题有关于钱,还有签名的问题,调试都解决了。继续解决问题,积累经验。
微信APP支付 - C#的更多相关文章
- 微信app支付 ci框架做的
/** * 组合微信app支付 获得prepayid * @param int $order_num */ private function _wxpay_reques ...
- .net 微信APP支付接口的开发流程以及坑
流程 申请APP的微信支付 申请成功之后得到APPID 商户号 以及自己设置商户号的支付密码 这时就可以开发接口了 微信APP支付API:https://pay.weixin.qq.com/wiki/ ...
- 微信app支付android客户端以及.net服务端实现
由于公司运营需要,需要在客户端(android/ios)增加微信以及支付宝支付,在调用微信app支付时遇到一些问题,也算是一些踩过的坑,记录下来 ,希望能对.net开发者服务端网站更快的集成微信app ...
- php开发微信APP支付接口
之前在开发APP中用到了微信支付,因为是第一次用,所以中途也遇到了好多问题,通过查看文档和搜集资料,终于完成了该功能的实现.在这里简单分享一下后台php接口的开发实例. 原文地址:代码汇个人博客 ht ...
- H5使用codovar插件实现微信支付(微信APP支付模式,前端)
H5打包的app实现微信支付及支付宝支付,本章主要详解微信支付,支付宝支付请查看另一篇“H5使用codovar插件实现支付宝支付(支付宝APP支付模式,前端)” ps:本文只试用H5开发的,微信 AP ...
- nodejs+koa2微信app支付,小程序支付
企业付款到零钱文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 1,搞微信支付,先看流程图 https: ...
- asp.net core 微信APP支付(扫码支付,H5支付,公众号支付,app支付)之4
微信app支付需要以下参数,类封装如下 public class WxPayModel { /// <summary> /// 应用ID /// </summary> publ ...
- 微信支付-微信公众号支付,微信H5支付,微信APP支付,微信扫码支付
在支付前,如果使用第三方MVC框架,则使用重写模式,服务器也需要配置该项 if (!-e $request_filename){ rewrite ^/(.*)$ /index.php/$ last; ...
- Android版-微信APP支付
首发地址: Android版-微信APP支付 欢迎留言.转发 微信极速开发系列文章(微信支付.授权获取用户信息等):点击这里 目录 1.注册账号.开发者认证 2.添加应用 3.申请微信支付 4.技术开 ...
随机推荐
- 如何用 js 递归输出树型
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- GMM高斯混合模型 学习(2)
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHpxMjAwODExMjExMDc=/font/5a6L5L2T/fontsize/400/fill/I0 ...
- Java之开发工具(1) - Eclipse 如何设置注释的模板
最常用的注释就是对类的说明和方法的说明,关于这类代码的注释方式,在Eclipse中可以这样进行设置: windows---preferences...---java--code style--code ...
- 每日算法之二十三:Reverse Nodes in k-Group
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. If ...
- 铁通网络没有一个真实的公网IP,NAT转换能不能解决?
铁通网络没有一个真实的公网IP,NAT转换能不能解决? 我的是铁通宽带,现在想用自己的机子做一个动态主机,可是因为铁通垃圾网络的NAT转发问题,使用cn99qdns手动更新动态域名IP后公网能 ...
- Sphinx全文检索引擎测试
数据表 1.documents CREATE TABLE `documents` ( `id` int(13) NOT NULL auto_increment, `group_id` int(11) ...
- 常用/常见Java Web 服务器/应用服务器Logo图文介绍
常用/常见应用服务器介绍:自己总结.整理一些常见的应用服务器,资料主要来源于网上. 常用Java Web 服务器Java Web应用程序需要部署在Java web服务器中运行,常用的Java ...
- mysql优化一
1.show global status 可以列出MySQL服务器运行各种状态值 2.show variables 查询MySQL服务器配置信息 一.慢查询 mysql ...
- SQLServer 2008中SQL增强之三 Merge(在一条语句中使用
SQLServer 2008中SQL增强之三 Merge(在一条语句中使用Insert,Update,Delete) SQL Server 2008提供了一个增强的SQL命令Merge,用法参看M ...
- jQuery knowledge
I have used jquery for many years, but didn't list the problem I ever meeting, so here is a list of ...