Asp.Net Core3.0 微信小程序统一下单
微信统一下单开发文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
微信支付小程序支付文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml
简单记录一下net core3.0对接微信支付的相关代码,网上有很多微信支付的文章,但是一定要仔细看一遍微信的官方文档。
准备工作:
首先要开通小程序的支付能力,按要求提交审核材料,审核通过后,我们可以得到APPID、微信支付商户号mch_id、API密钥key、Appsecret,详见 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=3_1
之后在商户后台绑定同一主体的APPID并授权,发起授权后,商户需要自行前往对应平台确认授权申请。
最后在商户后台设置回调地址。
一、微信支付
1.支付V3
代码只是简单实现退款功能,仅供参考,请勿在生产环境中使用,否则可能造成资金风险。
//支付接口
public async Task<ResponseResult<dynamic>> unifiedorder(int money)
{
var url = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
var req = new GenerateOrderModelForWxPay
{
appid = _appid,
mchid = _mchid,
description = "XXXXX支付交易单",
amount = new WxPayAmountModel
{
total = money,
currency = "CNY"
},
payer = new WxPayerModel
{
openid = "付款人的openid"
},
out_trade_no = DateTime.Now.ToString("yyyyMMddhhmmss"),
notify_url = "http://api.xxxx.com/api/pay/NotifyUrl" //支付回调,自己创建
};
_log.WriteLog(JsonConvert.SerializeObject(req));
var httpHandler = new HttpHandler(_mchid, _serialNo);
HttpClient client = new HttpClient(httpHandler);
var bodyJson = new StringContent(JsonConvert.SerializeObject(req), Encoding.UTF8, "application/json"); //一定要这样传递参数,不然在加密签名的时候获取到的参数就是\\u0这种形式的数据了,不是传递的这样的数据了,导致加密的结果不正确
var response = await client.PostAsync(url, bodyJson);
var respStr = await response.Content.ReadAsStringAsync();//读取统一下单之后的返回结果,这样读取出来的直接就是结果,或者错误原因。这里面就包含prepay_id了
var timeStamp = DateTimeOffset.Now.ToUnixTimeSeconds();
var nonceStr = Path.GetRandomFileName();
string message = $"{_appid}\n{timeStamp}\n{nonceStr}\nprepay_id={JsonConvert.DeserializeObject<dynamic>(respStr).prepay_id}\n";
string signature = httpHandler.Sign(message);
var newObj = new
{
timeStamp= timeStamp.ToString(),
nonceStr = nonceStr,
package= "prepay_id="+JsonConvert.DeserializeObject<dynamic>(respStr).prepay_id,
paySign = signature
};
return new ResponseResult<dynamic>()
{
Code = Constant.Success,
Data=JsonConvert.SerializeObject(newObj),
};
}
//model
public class WxPayAmountModel
{
public int total { get; set; }
public string currency { get; set; }
}
public class WxPayerModel
{
public string openid { get; set; }
}
/// <summary>
/// 支付resource
/// </summary>
public class GenerateOrderModelForWxPay
{
public string appid { get; set; }
public string mchid { get; set; }
public string description { get; set; }
public WxPayAmountModel amount { get; set; }
public WxPayerModel payer { get; set; }
public string out_trade_no { get; set; }
public string notify_url { get; set; }
}
支付完成后,微信返回的结果格式如下:
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></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>
2.支付结果通知:
支付完成后,微信会把相关支付结果及用户信息通过数据流的形式发送给商户,商户需要接收处理,并按文档规范返回应答。
通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)这里通知发送可能会多台服务器进行发送,且发送时间可能会在几秒内,但微信不保证通知最终一定能成功。
支付成功后,微信会将结果通知商户后台,即支付代码里的notify_url链接,该链接是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到微信通知。
微信调用回调地址返回数据格式:
<xml>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<attach><![CDATA[支付测试]]></attach>
<bank_type><![CDATA[CFT]]></bank_type>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[Y]]></is_subscribe>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str>
<openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid>
<out_trade_no><![CDATA[1409811653]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign>
<time_end><![CDATA[20140903131540]]></time_end>
<total_fee>1</total_fee>
<coupon_fee><![CDATA[10]]></coupon_fee>
<coupon_count><![CDATA[1]]></coupon_count>
<coupon_type><![CDATA[CASH]]></coupon_type>
<coupon_id><![CDATA[10000]]></coupon_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
<transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id>
</xml>
获取到微信的通知后,商户处理业务逻辑后要同步返回给微信结果,SUCCESS表示商户接收通知成功并校验成功。
public dynamic NotifyUrl(NotifyDto ret)
{
WxPayAPI.WxPayData res = new WxPayAPI.WxPayData();
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", "订单查询失败"); try
{
if (ret.Event_type == "TRANSACTION.SUCCESS")//支付成功
{
//解密数据报文
var dataJson = AesGcmHelper.AesGcmDecryptFromBase64(_key, ret.Resource.Nonce, ret.Resource.Ciphertext, ret.Resource.Associated_data);
//转换对象接受
var data = JsonConvert.DeserializeObject<PayCipherText>(dataJson);
//处理自己的业务逻辑
TODO... res.SetValue("return_code", "SUCCESS");
res.SetValue("return_msg", "OK");
return Content(res.ToXml());
}
else
{
_log.WriteLog("NotifyFaile:" + JsonConvert.SerializeObject(ret)); }
return Content(res.ToXml());
}
catch (Exception ex)
{
_log.WriteLog(ex.ToString());
return Content(res.ToXml());
}
}
/// 支付结果回调接收参数
public class NotifyDto
{
/// 通知ID通知的唯一ID
/// 示例值:EV-2018022511223320873
public string Id { get; set; }
/// 通知创建时间 通知创建的时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒。
/// 示例值:2015-05-20T13:29:35+08:00
public string Create_time { get; set; }
/// 通知类型 通知的类型,支付成功通知的类型为TRANSACTION.SUCCESS
/// 示例值:TRANSACTION.SUCCESS
public string Event_type { get; set; }
/// 通知数据类型 通知的资源数据类型,支付成功通知为encrypt-resource
/// 示例值:encrypt-resource
public string Resource_type { get; set; }
/// 通知数据 通知资源数据
/// json格式,见示例
public Resource Resource { get; set; }
/// 回调摘要
/// 示例值:支付成功
public string Summary { get; set; }
}
//回报文model
public class PayCipherText
{
public string out_trade_no { get; set; }
public string transaction_id { get; set; }
public string trade_type { get; set; }
public string trade_state { get; set; }
public string trade_state_desc { get; set; }
public string bank_type { get; set; }
public string success_time { get; set; }
public WxPayAmountModel amount { get; set; }
}
这里用到证书和回调报文解密,参考https://wechatpay-api.gitbook.io/wechatpay-api-v3/qian-ming-zhi-nan-1/zheng-shu-he-hui-tiao-bao-wen-jie-mi
Asp.Net Core3.0 微信小程序统一下单的更多相关文章
- 微信小程序-统一下单、微信支付(Java后台)
1.首先分享 微信统一下单接口: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 微信接口 签名 对比网址: https: ...
- SpringBoot2.0微信小程序支付多次回调问题
SpringBoot2.0微信小程序支付多次回调问题 WxJava - 微信开发 Java SDK(开发工具包); 支持包括微信支付.开放平台.公众号.企业微信/企业号.小程序等微信功能的后端开发. ...
- 微信小程序统一服务消息下发接口 公众号和小程序消息都可以在一个接口推送了
昨天晚上,2018年9月11日,微信官方又更新了一大波的小程序功能.重点我们来谈谈这个功能,微信叫做统一服务消息下发接口. 这个是官方的文档 统一服务消息 · 小程序https://develope ...
- Lazy freeing of keys 对数据的额异步 同步操作 Redis 4.0 微信小程序
https://github.com/antirez/redis/blob/4.0-rc1/00-RELEASENOTES 数据缓存 · 小程序 https://developers.weixin.q ...
- 微信小程序(应用号)资源汇总整理
微信小应用资源汇总整理 开源项目 WeApp - 微信小程序版的微信 wechat-weapp-redux-todos - 微信小程序集成Redux实现的Todo list wechat-weapp- ...
- 黄聪:微信小程序(应用号)资源汇总整理(转)
微信小应用资源汇总整理 开源项目 WeApp - 微信小程序版的微信 wechat-weapp-redux-todos - 微信小程序集成Redux实现的Todo list wechat-weapp- ...
- 微信小程序学习指南
作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 微信小程序rpx单位
rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应.规定屏幕宽为750rpx.如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375p ...
- 微信小程序尺寸单位rpx以及样式相关介绍
rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应.规定屏幕宽为750rpx.如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375p ...
- SpringBoot实现微信小程序登录的完整例子
目录 一.登录流程 二.后端实现 1.SpringBoot项目结构树 2.实现auth.code2Session 接口的封装 3.建立用户信息表及用户增删改查的管理 4.实现登录认证及令牌生成 三.前 ...
随机推荐
- 无需配对数据的对比学习图像到图像转换,助力跨域物体检测 | BMVC'24
来源:晓飞的算法工程笔记 公众号,转载请注明出处 论文: Improving Object Detection via Local-global Contrastive Learning 论文地址:h ...
- ZCMU-1038
其实感觉不太难,读懂题意就行,我一开始没有仔细去读感觉就很懵.其题目意思就是一段字符串含有数字和'<'或者'>',一开始从左开始遍历,遇到'>'这类东西换方向,如果有多次遇到就删之前 ...
- 编译器-FIRST集合
语法分析器的两个重要函数 FIRST和FOLLOW FIRST的定义 FIRST(α),可从α推导得到的串的首符号的集合 1.如果X是一个终结符,那么FIRST(X) = X 2.如果X是一个非终 ...
- 《JavaScript 模式》读书笔记(7)— 设计模式3
这一篇,我们学习本篇中最为复杂的三个设计模式,代理模式.中介者模式以及观察者模式.这三个模式很重要!! 七.代理模式 在代理设计模式中,一个对象充当另一个对象的接口.它与外观模式的区别之处在于,外观模 ...
- StarBlog博客Vue前端开发笔记:(2)SASS与SCSS
前言 本项目需要使用 SCSS 来编写页面样式. Sass (Syntactically Awesome Stylesheets)是一个 css 预处理器,而 SCSS 是 Sass 的一种语法格式, ...
- IOS跳转到系统相册及一些其他的URL Scheme
IOS跳转到系统相册及一些其他的URL Scheme APP 间的跳转主要通过 UIApplication.shared.openURL(url) 这种方法来实现的,但iOS10 后又稍加不同,iOS ...
- Ubuntu下安装和开启telnet
安装命令如下 sudo apt-get install openbsd-inetd sudo apt-get install telnetd sudo /etc/init.d/openbsd-in ...
- Qt音视频开发22-音频播放QAudioOutput
一.前言 以前一直以为只有Qt5以后才有QAudioOutput播放音频,其实从Qt4.6开始就有,在Qt6中变成了QAudioSink,功能一样.用QAudioOutput播放音频pcm数据极其方便 ...
- 关于QCustomPlot超级图表的一些冷知识点
开源的图表控件QCustomPlot很经典,作者至少是八星斗圣级别,在曲线数据展示这块性能彪悍,总结了一些容易忽略的经验要点. 可以将XY轴对调,然后形成横向的效果,无论是曲线图还是柱状图,分组图.堆 ...
- Qt编写安防视频监控系统40-onvif线程处理
一.前言 整个onvif模块大部分的功能都有了以后,除了在demo上点点按钮可以执行获取结果显示外,最终还是要应用到视频监控中,在按钮上点点和系统中后台自动运行是两码事,比如onvif校时和事件订阅, ...