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支付 退款的更多相关文章

  1. Core3.1 微信v3 JSAPI支付

    1.前言 "小魏呀,这个微信支付还要多久?","快了快了老板,就等着最后一步了...","搞快点哈,就等着上线呢","...... ...

  2. 微信v3 JSAPI最新接口错误 get_brand_wcpay_request:fail

    WxPay.JsApiPay.php文件下 原始接口代码 /** * * 获取jsapi支付的参数 * @param array $UnifiedOrderResult 统一支付接口返回的数据 * @ ...

  3. 微信JSApi支付~集成到MVC环境后的最后一个坑(网上没有这种解决方案)

    返回目录 大叔第一人 之前写了关于微信的坑<微信JSApi支付~坑和如何填坑>,今天将微信的jsapi支付封装到了MVC环境里,当然也出现了一些新的坑,如支付参数应该是Json对象而不是J ...

  4. 微信支付系列(2)——jsapi支付源码解析

    版权声明:转载请注明出处:http://blog.csdn.net/m0sh1 http://www.share345.com 在微信支付 开发者文档页面 下载最新的 PHP SDK http://m ...

  5. 微信小程序支付及退款流程详解

    微信小程序的支付和退款流程 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下. 首先说明一下,微信小程序支付的主要逻辑集中在后端,前端 ...

  6. 微信小程序支付开发之申请退款

    微信小程序支付跟微信公众号支付类似,这里不另做记录,如果没有开发过支付,可以查看我关于微信支付的文章 重点记录微信小程序申请退款开发过程中遇到一些坑. 退款接口比支付接口接口多了一个 双向证书 证书介 ...

  7. 微信 之jsapi实现支付

    一.微信公众号号后台支付配置 附微信支付参考文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 二.微信支付类封装 该类可以实现付款码支付.JSA ...

  8. 微信小程序支付以及微信退款开发

    最近公司项目急着测试,需要开发微信小程序+微信支付+微信退款,本着这几天的一些研究,决定记录一下开发的过程. 本着知识分享的原则,希望对大家有所帮助. 本篇针对的是微信小程序的支付开发,如果有对微信公 ...

  9. 网站如何接入微信公众号JSAPI支付PHP版

    1.首先,我们要有一个微信公众号(分类类型有订阅号,服务号,企业号)我们的微信公众号一定是个服务号只有它才有微信支付接口.. 并且这个微信公众号一定要进行微信认证才能申请微信支付接口. 2.申请JSA ...

随机推荐

  1. python +pycharm+selenium 环境搭建

    一:首先安装python:   https://www.python.org/downloads/: 下载完后一步步的点击安装,验证是否安装成功:打开win+r 打开cmd命令,输入python -V ...

  2. Linux嵌入式学习-网络配置-ping外网、主机和域名

    之前用的nfs挂载的文件系统,今天用yaffs2制作的文件系统并写入到nandflash中.但是网络却无法使用了. 首先,我们配置网卡. ifconfig eth0 192.168.1.230 bro ...

  3. HTML中,大小不确定图片的水平垂直居中

    html: css: div{ width:400px;height:300px;text-align:center;font-size:0;*font-size:200px;} div:after{ ...

  4. JAVA编程能力提升学习图

    阿里大神毕玄整理的关于进阶JAVA的学习体系,知道下...

  5. 每日一个linux命令6 -- mv

    mv test.log test1.txt 文件改名 mv test1.log test3 文件移动 mv test1.log test2.log test3.log test4 将1,2,3.log ...

  6. PHP设计模式之代理模式

    代理模式定义 为其他对象提供一种代理,以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用. 代理模式使用场景 当需要隐藏一 ...

  7. go语言中运算符

    Go语言学习笔记(运算符)-day01 go语言中与其他语言一样,存在多种运算符,下表列出了go语言中的运算符类型 算数运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 算数运算符 运算符 描述 ...

  8. WPF学习笔记01_XAML之简介

    简介 XAML (发音"zammel" 咋么儿),用于实例化.NET对象的标记语言,主要用于构造WPF的用户界面.类似html标记语言. 通过XAML,程序员可以用代码的方式对界面 ...

  9. 【十天自制软渲染器】DAY 01:图形学学习建议与环境搭建

    推荐直接阅读博客原文,更新更及时,阅读体验更佳 「十天自制软渲染器」这个标题我承认标题党了.在对图形学一无所知的情况下想十天自制一个软渲染器,就好似一节课没上过却试图一个晚上看完<30 天精通 ...

  10. 【C++】《C++ Primer 》第十六章

    第十六章 模板与泛型编程 面向对象编程和泛型编程都能处理在编写程序时不知道类型的情况. OOP能处理类型在程序允许之前都未知的情况. 泛型编程在编译时就可以获知类型. 一.定义模板 模板:模板是泛型编 ...