评论

ASP.NET Core 微信支付(安装版)

为了更方便大家的使用,我直接把代码打包上传到nuget,大家可以直接在nuget里面搜索:AspNetCore.WeChatPayAPIv3 安装到项目中就可以使用了。

前言

        为了更方便大家的使用,我直接把代码打包上传到nuget,大家可以直接在nuget里面搜索:AspNetCore.WeChatPayAPIv3安装到项目中就可以使用了。

代码实战

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using AspNetCore.WeChatPayAPIv3.Helper;
using AspNetCore.WeChatPayAPIv3.Models;
using AspNetCore.WeChatPayAPIv3.Models.ClostOrder;
using AspNetCore.WeChatPayAPIv3.Models.GenerateOrder;
using AspNetCore.WeChatPayAPIv3.Models.QueryOrder;
using AspNetCore.WeChatPayAPIv3.Models.QueryRefunds;
using AspNetCore.WeChatPayAPIv3.Models.Refunds;
using AspNetCore.WeChatPayAPIv3.Models.RefundsCallback;
using AspNetCore.WeChatPayAPIv3.Models.WxPayCallback;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Configuration;
namespace DaWen.WeChatPay.Controllers
{
    public class WeChatPayTestController : ControllerBase
    {
        private readonly ILogger<WeChatPayTestController> _logger;
        private readonly IConfiguration _configuration;

        public WeChatPayTestController(ILogger<WeChatPayTestController> logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }

        /// <summary>
        /// 统一下单接口
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("api/WeChatPayTest/GenerateOrder")]
        public async Task<AppPayModel> GenerateOrder()
        {
            var orderNumber = $"{DateTime.Now:yyyyMMddHHmmssff}{CodeHelper.CreateNumCode(3)}";
            var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey);
            var notify_url = _configuration["notify_url"]; //这个放在配置文件,从配置文件读取比较灵活,或者写到数据库中
            var payodel = await helper.UnionGenerateOrder("好东西啊", 1, orderNumber, notify_url, "附加信息测试啊");

            #region 为APP生成下单所需的参数,看个人实际需求,也可以APP自己生成所需的参数

            var signModel = WxPayForAppHelper.GetSign(WxPayConst.appid, payodel.prepay_id, WxPayConst.privateKey);

            #endregion

            return signModel;
        }

        /// <summary>
        /// 查询订单接口 -- 测试数据:2021033119240567226
        /// </summary>
        [HttpGet, Route("api/WeChatPayTest/QueryOrder")]
        public async Task<WxPayStatusRespModel> QueryOrder(string orderNumber)
        {
            var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey);
            var payModel = await helper.QueryOrder(orderNumber);
            return payModel;
        }

        /// <summary>
        /// 查询订单接口 -- 测试数据:2021033119240567226
        /// </summary>
        [HttpGet, Route("api/WeChatPayTest/CloseOrder")]
        public async Task<ClostOrderRespModel> CloseOrder(string orderNumber)
        {
            var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey);
            var payModel = await helper.ClostOrder(orderNumber);
            return payModel;
        }

        /// <summary>
        /// 微信支付成功结果回调接口
        /// </summary>
        /// <returns>退款通知http应答码为200且返回状态码为SUCCESS才会当做商户接收成功,否则会重试。注意:重试过多会导致微信支付端积压过多通知而堵塞,影响其他正常通知。</returns>
        [HttpPost, Route("api/WeChatPayTest/WxPayCallback")]
        [AllowAnonymous]
        public async Task<WxPayCallbackRespModel> WxPayCallback()
        {
            #region 获取字符串流

            /**
             * .NET 获取字符串流
             *  System.IO.Stream s = HttpContext.Current.Request.InputStream;
                int count = 0;
                byte[] buffer = new byte[1024];
                StringBuilder builder = new StringBuilder();
                while ((count = s.Read(buffer, 0, 1024)) > 0)
                {
                    builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
                }
                s.Flush();
                s.Close();
                s.Dispose();
             */

            var buffer = new MemoryStream();
            Request.Body.CopyTo(buffer);

            #endregion
            //我没有使用官方的那种验证数据安全性的方法,我解密出来数据之后,直接拿着订单号再去查询一下订单状态,然后再更新到数据库中。我嫌麻烦……

            var str = Encoding.UTF8.GetString(buffer.GetBuffer());
            var wxPayNotifyModel = str.ToObject<WxPayNotifyModel>();
            var resource = wxPayNotifyModel?.resource ?? new WxPayResourceModel();
            var decryptStr = AesGcmHelper.AesGcmDecrypt(resource.associated_data, resource.nonce, resource.ciphertext, WxPayConst.APIV3Key);
            var decryptModel = decryptStr.ToObject<WxPayResourceDecryptModel>();

            var viewModel = new WxPayCallbackRespModel();
            if (string.IsNullOrEmpty(decryptModel.out_trade_no))
            {
                viewModel.code = "FAIL";
                viewModel.message = "数据解密失败";
            }
            else
            {
                var resp = await QueryOrder(decryptModel.out_trade_no);
                //然后进行数据库更新处理……等等其他操作
            }

            return viewModel;
        }

        /// <summary>
        /// 退款接口 -- 测试数据:2021033119240567226
        /// </summary>
        [HttpGet, Route("api/WeChatPayTest/Refunds")]
        public async Task<RefundsRespModel> Refunds(string orderNumber)
        {
            var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey);
            var refundNumber = $"{DateTime.Now:yyyyMMddHHmmssff}{CodeHelper.CreateNumCode(3)}";
            var payModel = await helper.Refunds(orderNumber, refundNumber, "测试退款行不行", 1, 2, "https://xxxxx.top/api/WeChatPayTest/RefundsCallback");
            return payModel;
        }

        /// <summary>
        /// 退款通知回调接口
        /// </summary>
        /// <returns>退款通知http应答码为200且返回状态码为SUCCESS才会当做商户接收成功,否则会重试。注意:重试过多会导致微信支付端积压过多通知而堵塞,影响其他正常通知。</returns>
        [HttpPost, Route("api/WeChatPayTest/RefundsCallback")]
        [AllowAnonymous]
        public async Task<RefundsCallbackRespModel> RefundsCallback()
        {
            #region 获取字符串流

            /**
             * .NET 获取字符串流
             *  System.IO.Stream s = HttpContext.Current.Request.InputStream;
                int count = 0;
                byte[] buffer = new byte[1024];
                StringBuilder builder = new StringBuilder();
                while ((count = s.Read(buffer, 0, 1024)) > 0)
                {
                    builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
                }
                s.Flush();
                s.Close();
                s.Dispose();
             */

            var buffer = new MemoryStream();
            Request.Body.CopyTo(buffer);

            #endregion
            //我没有使用官方的那种验证数据安全性的方法,我解密出来数据之后,直接拿着商户退款订单号再去查询一下订单状态,然后再更新到数据库中。我嫌麻烦……

            var str = Encoding.UTF8.GetString(buffer.GetBuffer());
            var wxPayNotifyModel = str.ToObject<RefundsCallbackModel>();
            var resource = wxPayNotifyModel?.resource ?? new RefundsCallbackResourceModel();
            var decryptStr = AesGcmHelper.AesGcmDecrypt(resource.associated_data, resource.nonce, resource.ciphertext, WxPayConst.APIV3Key);
            var decryptModel = decryptStr.ToObject<RefundsCallbackDecryptModel>();

            var viewModel = new RefundsCallbackRespModel();
            if (string.IsNullOrEmpty(decryptModel.out_trade_no))
            {
                viewModel.code = "FAIL";
                viewModel.message = "数据解密失败";
            }
            else
            {
                var resp = await QueryRefunds(decryptModel.out_refund_no);
                //然后进行数据库更新处理……等等其他操作
            }

            return viewModel;
        }

        /// <summary>
        /// 查询退款结果接口
        /// </summary>
        /// <param name="refundNumber">商户系统内部的退款单号,商户系统内部唯一</param>
        /// <returns></returns>
        [HttpGet, Route("api/WeChatPayTest/QueryRefunds")]
        public async Task<QueryRefundsOrderRespModel> QueryRefunds(string refundNumber)
        {
            var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey);
            var payModel = await helper.QueryRefundsOrder(refundNumber);
            return payModel;
        }
    }
}
最后一次编辑于  2021-04-09  
点赞 1
收藏
评论

2 个评论

  • 生如夏花
    生如夏花
    2023-06-14

    楼主你好,我添加 var helper = new WxPayHelper(WxPayConst.appid, WxPayConst.mchid, WxPayConst.serialNo, WxPayConst.privateKey); 报错

    System.FormatException:“The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.”

    2023-06-14
    赞同
    回复
  • 未来
    未来
    2022-10-18

    你好,Core版本发布到Centos服务器上,小程序调起支付API,签名这里报错,请问这个怎么解决

    2022-10-18
    赞同
    回复 1
    • 大稳·杨
      大稳·杨
      2022-10-18
      你的.NET CORE 版本是多少?
      2022-10-18
      回复
登录 后发表内容