微信统一下单开发文档: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 微信小程序统一下单的更多相关文章

  1. 微信小程序-统一下单、微信支付(Java后台)

    1.首先分享 微信统一下单接口: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1   微信接口 签名 对比网址: https: ...

  2. SpringBoot2.0微信小程序支付多次回调问题

    SpringBoot2.0微信小程序支付多次回调问题 WxJava - 微信开发 Java SDK(开发工具包); 支持包括微信支付.开放平台.公众号.企业微信/企业号.小程序等微信功能的后端开发. ...

  3. 微信小程序统一服务消息下发接口 公众号和小程序消息都可以在一个接口推送了

    昨天晚上,2018年9月11日,微信官方又更新了一大波的小程序功能.重点我们来谈谈这个功能,微信叫做统一服务消息下发接口. 这个是官方的文档  统一服务消息 · 小程序https://develope ...

  4. Lazy freeing of keys 对数据的额异步 同步操作 Redis 4.0 微信小程序

    https://github.com/antirez/redis/blob/4.0-rc1/00-RELEASENOTES 数据缓存 · 小程序 https://developers.weixin.q ...

  5. 微信小程序(应用号)资源汇总整理

    微信小应用资源汇总整理 开源项目 WeApp - 微信小程序版的微信 wechat-weapp-redux-todos - 微信小程序集成Redux实现的Todo list wechat-weapp- ...

  6. 黄聪:微信小程序(应用号)资源汇总整理(转)

    微信小应用资源汇总整理 开源项目 WeApp - 微信小程序版的微信 wechat-weapp-redux-todos - 微信小程序集成Redux实现的Todo list wechat-weapp- ...

  7. 微信小程序学习指南

    作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  8. 微信小程序rpx单位

    rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应.规定屏幕宽为750rpx.如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375p ...

  9. 微信小程序尺寸单位rpx以及样式相关介绍

    rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应.规定屏幕宽为750rpx.如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375p ...

  10. SpringBoot实现微信小程序登录的完整例子

    目录 一.登录流程 二.后端实现 1.SpringBoot项目结构树 2.实现auth.code2Session 接口的封装 3.建立用户信息表及用户增删改查的管理 4.实现登录认证及令牌生成 三.前 ...

随机推荐

  1. 系统日志查询之journalctl

    journalctl是什么 查询系统日志的工具 journalctl -xe是什么意思 -xe是排查问题时最常用的参数:-e 从结尾开始看-x 相关目录(如:问题相关的网址) journalctl - ...

  2. winform窗体无边框拖动

    1:引用命名空间 using System.Runtime.InteropServices; 2:想要拖动窗体的控件绑定MouseDown事件 点击查看代码 //窗体移动 [DllImport(&qu ...

  3. N皇后问题(DFS-深度优先算法)

    N皇后问题(DFS-深度优先算法) 题目描述: 在 N×N 的方格棋盘放置了 N 个皇后,使得它们不相互攻击(即任意 22 个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成 45° 的斜线上. ...

  4. acode连接termux

    在acode中安装AcodeX - Terminal插件 在termux中运行 curl -sL https://raw.githubusercontent.com/bajrangCoder/acod ...

  5. AD使用插件生成交互式BOM

    AD使用插件生成交互式BOM 效果图镇楼: 下面来说一下怎么搞,过程其实也很简单,就加载一个脚本的事儿. 1.下载AD用交互式BOM插件 首先前往GitHub下载这位大佬开发的插件 地址:https: ...

  6. 刷到一个 MLSQL 语言

    在 https://www.infoq.cn/video/2vFUBYfxFcoFWmSm5WOj 刷到一个 MLSQL 语言,主页 https://www.mlsql.tech/home ,意思是用 ...

  7. Archlinux常用软件推荐 更新于2022年5月

    必装软件# xdg-user-dirs-gtk 执行 xdg-user-dirs-gtk-update 可将更新Home目录路径 包管理工具# yay 代替pacman的包管理 downgrade p ...

  8. Qt/C++音视频开发53-本地摄像头推流/桌面推流/文件推流/监控推流等

    一.前言 编写这个推流程序,最开始设计的时候是用视频文件推流,后面陆续增加了监控摄像头推流(其实就是rtsp视频流).网络电台和视频推流(一般是rtmp或者http开头m3u8结尾的视频流).本地摄像 ...

  9. Qt音视频开发27-Onvif设备搜索

    一.前言 最近业余时间主要研究音视频开发这块,前面的文章写了好多种视频监控内核,一旦将这些内核搞定以后,视频监控的相关功能水到渠成.做视频监控系统,绕不过onvif这玩意,这玩意主要就是为了统一一个大 ...

  10. Qt编写安防视频监控系统35-onvif抓拍图片

    一.前言 以前不知道onvif也可以做抓拍功能,直到近期重新用Onvif Device Test Tool工具测试的时候,发现还有抓图的接口,于是抓跑分析出要收发的数据,然后加入到自己封装的onvif ...