Core3.1 微信v3 JSAPI支付 退款
1、前言
上一篇写了《Core3.1 微信v3 JSAPI支付》,这个属于v3的接口规则,现在研究了下退款的接口我写的时候它属于v2接口规则文档。但凡微信支付文档里面写清楚点我也不会在这里记录一下。
2、干货
接口文档https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml 现在看看是v3接口的了 我的天,他们在逗我玩一样,v2的写好了v3就放出来了。命途多舛啊。 v2请求的是xml文档格式的,这里又要温习一下旧知识了。
当时我记得清清楚楚 就说了请求要加签名,证书双向验证。官网文档没有写。Net的怎么加载证书 就说了一句windows下面直接安装证书就好了。结果 都是Bad Request 还是人工咨询吧 到最后才把代码找给我。我问人工客户地址给我看看,他说没有地址(肺都气炸。。。)
3、代码
这是封装的一个请求 ,代码加在上篇文章里面的那个请求里面
/// <summary>
///postXML请求
/// </summary>
/// <param name="url">地址</param>
/// <param name="requestString">参数(json格式)</param>
/// <param name="path">p12文件路径</param>
/// <param name="certPwd">密码</param>
/// <returns>string</returns>
public string PostXml(string url, string requestString,string path, string certPwd)
{
var handler = new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = SslProtocols.Tls12,
ServerCertificateCustomValidationCallback = (x, y, z, m) => true,
}; //var path = Path.Combine(AppContext.BaseDirectory, "cert\\iot3rd.p12");
handler.ClientCertificates.Add(new X509Certificate2(path, certPwd)); var client = new HttpClient(handler); var content = new StringContent(requestString);
content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
//GetAwaiter().GetResult();
var httpResponseMessage = client.PostAsync(url, content).Result.Content.ReadAsStringAsync().Result;
return httpResponseMessage;
}
最主要的就是加了认证文件,p12文件路径跟密码,一般密码都是商户号。这就是微信文档说的双向验证
拼接请求参数,官网文档有验证这个的。排序的话我自己手动固定排序的,就那几个字段ABCDEFG都可以看到0.0。
/// <summary>
/// 退费需要的字符
/// </summary>
/// <param name="hospInfo"></param>
/// <param name="regOrder"></param>
/// <returns></returns>
private string RequestRetreatParmar(Entity.Models.HospInfo hospInfo, RegOrder regOrder)
{
var guid = Guid.NewGuid().ToString("N").Substring(0, 30);
var retreatNo = OrderHelper.GenerateNo("CFTF");
int money = Convert.ToInt32(regOrder.OwnFee * 100);
//签名
string message = $"appid={hospInfo.WxAppid}&mch_id={hospInfo.WxMchid}&nonce_str={guid}&out_refund_no={retreatNo}&refund_desc=客户预约挂号退款&refund_fee={money}&total_fee={money}&transaction_id={regOrder.PlatformTradeId}&key={hospInfo.WxKey}";
var signMd5 = SecurityHelper.MD5EncrytString(message).ToUpper();
var dto = new
{
xml= new
{
appid = hospInfo.WxAppid,
mch_id = hospInfo.WxMchid,
nonce_str = guid,
sign = signMd5,
transaction_id = regOrder.PlatformTradeId,
out_refund_no = retreatNo,
total_fee = money,
refund_fee = money,
refund_desc = "客户预约挂号退款",
}
};
var json = JsonConvert.SerializeObject(dto); return json;
}
我把这里MD5加密的代码也贴上
/// md5加密
/// </summary>
/// <param name="inputString">字符串</param>
/// <returns>加密过的字符串(不可以解密)</returns>
public static string MD5EncrytString(string inputString)
{
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] buffer = Encoding.UTF8.GetBytes(inputString);
byte[] md5Buffer = md5.ComputeHash(buffer);
md5.Clear();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < md5Buffer.Length; i++)
{
sb.Append(md5Buffer[i].ToString("x2"));
}
return sb.ToString();
}
请求这里,只要Return_code等于SUCCESS下面就可以做自己的业务逻辑了。里面返回的字段肯定有一个是你自己写了传进去的。通过这个字段查询数据库完成自己的逻辑。
//微信退费操作
var url = RequestUrl.PAYREFUND;
var json = RequestRetreatParmar(hospInfoMoidel, regOrderModel);
var xml = JsonConvert.DeserializeXmlNode(json);
var postData = xml.InnerXml;
var pathfile = _webHostEnvironment.WebRootPath + "/arsjkll/apiclient_cert.p12";
var wxPostResult = _httpClientFactoryHelper.PostXml(url, postData, pathfile, hospInfoMoidel.WxSslcertpassword);
SaveLog("WeChatTuiFei", wxPostResult);
var resultRep = wxPostResult.Replace("<![CDATA[", "").Replace("]]>", "");
XmlDocument doc = new XmlDocument();
doc.LoadXml(resultRep);
string jsonText = JsonConvert.SerializeXmlNode(doc);
SaveLog("WeChatTuiFei", jsonText);
var resultModel = JsonConvert.DeserializeObject<RetreatNoResulDtoXml>(jsonText);
var resultModelXml = resultModel.Xml;
if (resultModelXml.Result_Code == "SUCCESS")
{
regOrderModel.RefundNo = resultModelXml.Out_Refund_No;
regOrderModel.RefundState = 1;
regOrderModel.RefundResult = resultModelXml.Return_Code;
regOrderModel.RefundTime = DateTime.Now; payLogModel.RefundNo = resultModelXml.Out_Refund_No;
payLogModel.RefundState = 1;
payLogModel.RefundResult = resultModelXml.Return_Code;
payLogModel.RefundTime = DateTime.Now;
await _db.SaveChangesAsync();
return Result.ToSuccess(resultModel);
}
else
return Result.ToFail(resultModelXml.Return_Msg);
我这里没有用notify_url返回接口 直接得到结果。下面是接收的Dto
public class RetreatNoResulDtoXml
{
public RetreatNoResulDto Xml { get; set; }
}
/// <summary>
/// 退号|退费结果
/// </summary>
public class RetreatNoResulDto
{
/// <summary>
/// 返回状态码
/// SUCCESS:退款申请接收成功,结果通过退款查询接口查询
/// FAIL:提交业务失败
/// 此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
/// 示例值:SUCCESS
/// </summary>
public string Return_Code { get; set; }
/// <summary>
/// 返回信息
/// 返回信息,如非空,为错误原因
/// 签名失败
/// 参数格式校验错误
/// 示例值:签名失败
/// </summary>
public string Return_Msg { get; set; } //返回状态码(return_code)为SUCCESS的时候,包含以下字段 /// <summary>
/// 业务结果
/// SUCCESS/FAIL
/// 示例值:SUCCESS
/// </summary>
public string Result_Code { get; set; }
/// <summary>
/// 错误代码
/// 示例值:SYSTEMERROR
/// </summary>
public string Err_Code { get; set; }
/// <summary>
/// 错误代码描述
/// 结果信息描述
///示例值:系统错误
/// </summary>
public string Err_Code_Des { get; set; }
public string Appid { get; set; }
public string Mch_Id { get; set; }
public string Sub_Appid { get; set; }
public string Sub_Mch_Id { get; set; }
public string Nonce_Str { get; set; }
/// <summary>
/// 签名
/// </summary>
public string Sign { get; set; }
public string Transaction_Id { get; set; }
public string Out_Trade_No { get; set; }
public string Out_Refund_No { get; set; }
public string Refund_Id { get; set; }
public int Refund_Fee { get; set; }
public int Settlement_Refund_Fee { get; set; }
public int Total_Fee { get; set; }
public int Settlement_Total_Fee { get; set; }
public string Fee_Type { get; set; }
public int Cash_Fee { get; set; } }
返回的结果我存了日志 真不知道中间<![CDATA[SUCCESS]]> 这个花里胡哨的是咋想的 我直接 全部替换 "" 了。
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx6ed9112323b1f1d3e04]]></appid>
<mch_id><![CDATA[16045678769]]></mch_id>
<nonce_str><![CDATA[9xonPINPBGO4y8WW]]></nonce_str>
<sign><![CDATA[DABC2420B7B03FBA4D0027A9EBBF54D7]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[42000009呜呜呜呜276477024]]></transaction_id>
<out_trade_no><![CDATA[YYGH20210129164746001]]></out_trade_no>
<out_refund_no><![CDATA[CFTF20210129164806002]]></out_refund_no>
<refund_id><![CDATA[50300407262021012905921959108]]></refund_id>
<refund_channel><![CDATA[]]></refund_channel>
<refund_fee>440</refund_fee>
<coupon_refund_fee>0</coupon_refund_fee>
<total_fee>440</total_fee>
<cash_fee>440</cash_fee>
<coupon_refund_count>0</coupon_refund_count>
<cash_refund_fee>440</cash_refund_fee>
</xml>
4、总结
看着几行代码 还给我排队等了好久终于问人工解决的,之前都没说请求头里面加载用户证书,可能是v3出来了没太在意吧。后面看看 v3接口 看样子应该跟统一下单一样了吧只要调用请求那个方法就可以了!
时间,抓起了就是黄金,虚度了就是流水;书,看了就是知识,没看就是废纸;理想,努力了才叫梦想,放弃了那只是妄想。努力,虽然未必会收获,但放弃,就一定一无所获。
Core3.1 微信v3 JSAPI支付 退款的更多相关文章
- Core3.1 微信v3 JSAPI支付
1.前言 "小魏呀,这个微信支付还要多久?","快了快了老板,就等着最后一步了...","搞快点哈,就等着上线呢","...... ...
- 微信v3 JSAPI最新接口错误 get_brand_wcpay_request:fail
WxPay.JsApiPay.php文件下 原始接口代码 /** * * 获取jsapi支付的参数 * @param array $UnifiedOrderResult 统一支付接口返回的数据 * @ ...
- 微信JSApi支付~集成到MVC环境后的最后一个坑(网上没有这种解决方案)
返回目录 大叔第一人 之前写了关于微信的坑<微信JSApi支付~坑和如何填坑>,今天将微信的jsapi支付封装到了MVC环境里,当然也出现了一些新的坑,如支付参数应该是Json对象而不是J ...
- 微信支付系列(2)——jsapi支付源码解析
版权声明:转载请注明出处:http://blog.csdn.net/m0sh1 http://www.share345.com 在微信支付 开发者文档页面 下载最新的 PHP SDK http://m ...
- 微信小程序支付及退款流程详解
微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端 ...
- 微信小程序支付开发之申请退款
微信小程序支付跟微信公众号支付类似,这里不另做记录,如果没有开发过支付,可以查看我关于微信支付的文章 重点记录微信小程序申请退款开发过程中遇到一些坑. 退款接口比支付接口接口多了一个 双向证书 证书介 ...
- 微信 之jsapi实现支付
一.微信公众号号后台支付配置 附微信支付参考文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 二.微信支付类封装 该类可以实现付款码支付.JSA ...
- 微信小程序支付以及微信退款开发
最近公司项目急着测试,需要开发微信小程序+微信支付+微信退款,本着这几天的一些研究,决定记录一下开发的过程. 本着知识分享的原则,希望对大家有所帮助. 本篇针对的是微信小程序的支付开发,如果有对微信公 ...
- 网站如何接入微信公众号JSAPI支付PHP版
1.首先,我们要有一个微信公众号(分类类型有订阅号,服务号,企业号)我们的微信公众号一定是个服务号只有它才有微信支付接口.. 并且这个微信公众号一定要进行微信认证才能申请微信支付接口. 2.申请JSA ...
随机推荐
- C语言实现汉诺塔
汉诺塔 要把A柱子上的盘子移动到C柱子上,在移动过程中可以借助B柱子,但是要求小的盘子在上大的盘子在下. 解题思路: 1.把A柱子上的前N-1个盘子借助C柱子,全部移动到B柱子上(过程暂不考虑),再把 ...
- JavaDailyReports10_15
2020-10-15 16:12:16 今天学习了如何实现倒计时控制程序的运行: 1 package timer; 2 3 import java.util.Calendar; 4 import ja ...
- 解决Github下载仓库慢的正确姿势
上个月刚安装了 Manjaro ,然后最近在Manjaro下载Github的项目竟然只有几十b/s,这能忍?对于下载Github上的代码是硬需求,没办法直接探索一下突破的方法了. 方法一:安装chro ...
- <input type="image">表单提交2次 重复插入数据问题
写一个表单提交用到图片:两种代码. <input type="image" src="xxx.gif"onclick="return dosub ...
- netty心跳检测机制
既然是网络通信那么心跳检测肯定是离不开的,netty心跳检测分为读.写.全局 bootstrap.childHandler(new ChannelInitializer<SocketChanne ...
- 发现一个怪象windows 7系统上老是丢包windows 10网络正常
不知何故障,同一个局域网,windows 10系统上不丢包,windows 7系统老是丢包,不知是不是这二个系统的差区别,还是大家都有这样的情况. 相互PC之间ping也又不丢包,只有windos 7 ...
- 分装button组件引发的内存泄漏问题
这个问题其实一开始在vue里写的时候并没有注意到这一点,也没有报错,直到在react里写的时候给我报了一堆错之后,经各种磨烂之后最终找到是分装button组件的问题,既然找到问题在哪就好办了 直接先上 ...
- 【Dart】语言概述
// 导入(import) // 导入核心库 //导入外部库 import 'package:test_api/test_api.dart'; // 导入文件 //import 'path/test. ...
- /usr/local/mysql/bin/mysqlbinlog -vv /var/lib/bin/mysql-bin.000008 --base64-output=DECODE-ROWS --start-pos=307
/usr/local/mysql/bin/mysqlbinlog -vv /var/lib/bin/mysql-bin.000008 --base64-output=DECODE-ROWS --st ...
- kubernets之卷
一 卷的由来以及种类和常用的卷的类型 前面介绍了大部分都是pod的管理以及在集群内部和集群外部如何访问pod,但是我们也了解到,pod是有生命周期的,当pod所在节点下线,或者等其他原因原因导致pod ...