扫码支付-微信支付-netcore

前言

最近公司要求支持PC微信扫码,首先就会去取官方api文档,微信支付官方文档,官方文档由于缺少完整代码对接示例,

步骤

此示例是PC微信扫码支付

引用github封装好的SDK处理微信支付

Nuget安装SDK

Install-Package Essensoft.AspNetCore.Payment.WeChatPay -Version 2.4.3

appsettings.json 配置项

  "WeChatPay": {
    "AppId": "wxxxxxxxxxxxxxxxxxx",
    "MchId": "666666666",
    "Key": "xxxxxxxxxxxxxxxxxxxxxxxx",
    "NotifyUrl": "https://www.xxx.com/api/PayNotify/WechatPayNotify"
  },

新增配置实体类

using Essensoft.AspNetCore.Payment.WeChatPay;
public class WeChatPayOptionsExtend: WeChatPayOptions
{
    /// <summary>
    /// 回调地址
    /// </summary>
    public string NotifyUrl { get; set; }
}

新增支付实体类

/// <summary>
/// 微信Native支付Model
/// </summary>
public class WeChatPayNativePayModel
{
    /// <summary>
    /// 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一
    /// </summary>
    [JsonProperty("out_trade_no")]
    public string OutTradeNo { get; set; }

    /// <summary>
    /// 商品简单描述
    /// </summary>
    [JsonProperty("body")]
    public string Body { get; set; }

    /// <summary>
    /// 订单总金额,单位为分
    /// </summary>
    [JsonProperty("total_fee")]
    public int TotalFee { get; set; }

    /// <summary>
    ///  用户的客户端IP,支持IPV4和IPV6两种格式的IP地址
    /// </summary>
    [JsonProperty("spbill_create_ip")]
    public string SpbillCreateIp { get; set; }

    /// <summary>
    /// 附加数据(在查询API和支付通知中原样返回,可作为自定义参数使用)
    /// </summary>
    [JsonProperty("attach")]
    public string Attach { get; set; }
}
/// <summary>
/// 微信支付查询model
/// </summary>
public class WeChatPayOrderQueryModel
{
    /// <summary>
    /// 微信的订单号(与商户订单号二选一,建议优先使用)
    /// </summary>
    [JsonProperty("transaction_id")]
    public string TransactionId { get; set; }

    /// <summary>
    /// 商户订单号(与微信订单号二选一)
    /// </summary>
    [JsonProperty("out_trade_no")]
    public string OutTradeNo { get; set; }
}

新增UnionPaymentService

    public class WechatPaymentService: IWechatPaymentService
    {
        private readonly IWeChatPayClient _client ;
        public IOptions<WeChatPayOptionsExtend> OptionsAccessor { get; set; }
        private readonly ILogger _logger;
        private readonly ITracer _tracer;

        public WechatPaymentService(IOptions<WeChatPayOptionsExtend> optionsAccessor, ILogger<WechatPaymentService> logger, IWeChatPayClient client, ITracer tracer)
        {
            OptionsAccessor = optionsAccessor;
            _logger = logger;
            _client = client;
            _tracer = tracer;
        }

        /// <summary>
        /// 微信Native支付
        /// 微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。注意:code_url有效期为2小时,过期后扫码不能再发起支付
        /// https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5&index=3
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<WeChatPayUnifiedOrderResponse> NativePay(WeChatPayNativePayModel model)
        {
            IScope spanScope = null;
            try
            {
                spanScope = _tracer.BuildSpan("NativePay")
                    .WithTag(Tags.Component, nameof(WechatPaymentService))
                    .WithBusinessId(model.OutTradeNo)
                    .StartActive();

                _logger.LogInformation($"微信Native支付入参:{model.ToJson()}");

                var request = new WeChatPayUnifiedOrderRequest()
                {
                    Body = model.Body,
                    OutTradeNo = model.OutTradeNo,
                    TotalFee = model.TotalFee,
                    SpBillCreateIp = model.SpbillCreateIp,
                    NotifyUrl = OptionsAccessor.Value.NotifyUrl,
                    Attach = model.Attach,
                    TradeType = "NATIVE",
                    TimeStart = DateTime.Now.ToString("yyyyMMddHHmmss"),
                    TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss")
                };
                _logger.LogInformation($"微信Native支付入参:{request.ToJson()}");
                var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);
                _logger.LogInformation($"微信Native支付出参:{response.ToJson()}");
                return response;
            }
            catch (Exception ex)
            {
                _logger.LogInformation($"微信Native支付异常:{ex.Message},{ex.StackTrace}");
                throw ex;
            }
            finally
            {
                spanScope?.Dispose();
            }

        }

        /// <summary>
        /// 微信支付查询
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<WeChatPayOrderQueryResponse> Query(WeChatPayOrderQueryModel model)
        {
            IScope spanScope = null;
            try
            {
                spanScope = _tracer.BuildSpan("NativePay")
                    .WithTag(Tags.Component, nameof(WechatPaymentService))
                    .WithBusinessId(model.OutTradeNo)
                    .StartActive();

                var request = new WeChatPayOrderQueryRequest
                {
                    TransactionId = model.TransactionId,
                    OutTradeNo = model.OutTradeNo
                };

                _logger.LogInformation($"微信查询入参:{request.ToJson()}");

                var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);

                _logger.LogInformation($"微信查询出参:{response.ToJson()}");

                return response;
            }
            catch (Exception ex)
            {
                _logger.LogInformation($"微信支付查询异常:{ex.Message},{ex.StackTrace}");
                throw ex;
            }
            finally
            {
                spanScope?.Dispose();
            }
        }
    }

新增IWechatPaymentService

public interface IWechatPaymentService
{
   IOptions<WeChatPayOptionsExtend> OptionsAccessor { get; set; }

   /// <summary>
   /// 微信Native支付
   /// 微信后台系统返回链接参数code_url,商户后台系统将code_url值生成二维码图片,用户使用微信客户端扫码后发起支付。注意:code_url有效期为2小时,过期后扫码不能再发起支付
   /// https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5&index=3
   /// </summary>
   /// <param name="model"></param>
   /// <returns></returns>
   Task<WeChatPayUnifiedOrderResponse> NativePay(WeChatPayNativePayModel model);

   /// <summary>
   /// 微信支付查询
   /// </summary>
   /// <param name="model"></param>
   /// <returns></returns>
   Task<WeChatPayOrderQueryResponse> Query(WeChatPayOrderQueryModel model);
}
}

新增PayController,处理发起支付入口

private readonly IWechatPaymentService _wechatPaymentService;
 
 /// <summary>
 /// 微信Native支付
 /// </summary>
 /// <param name="viewMode"></param>
 /// <returns></returns>
 [HttpPost("WeChatNativePay")]
 public async Task<IActionResult> WeChatNativePay([FromBody] WeChatPayNativePayModel viewMode)
 {
     var data = await _wechatPaymentService.NativePay(viewMode);
     if (data.ReturnCode == "SUCCESS" && data.ResultCode == "SUCCESS")
     {

         PayLink payLink = new PayLink(data.CodeUrl);

         return Ok(ResponseResult.Execute(payLink.ToString()));
     }
     return Ok(ResponseResult.Execute("-1", $"{data.ErrCode}{data.ErrCodeDes}{data.ReturnMsg}"));
 }

 /// <summary>
 /// 微信支付查询
 /// </summary>
 /// <param name="viewMode"></param>
 /// <returns></returns>
 [HttpGet("WeChatQuery")]
 public async Task<IActionResult> WeChatQuery([FromQuery] WeChatPayOrderQueryModel viewMode)
 {
     var data = await _wechatPaymentService.Query(viewMode);
     if (data.ReturnCode == "SUCCESS" && data.ResultCode == "SUCCESS")
     {

         WeChatContext context = new WeChatContext(data.ResponseBody);

         //解析返回的订单状态
         WeChatPayOrderQueryResponse response = new WeChatPayXmlParser<WeChatPayOrderQueryResponse>().Parse(context.Context);

         return Ok(ResponseResult.Execute(response));
     }
     return Ok(ResponseResult.Execute("-1", $"{data.ErrCode}{data.ErrCodeDes}"));
 }

新增PayNotifyController,处理异步通知

private readonly IWechatPaymentService _wechatPaymentService;

/// <summary>
/// 微信支付结果通知
/// </summary>
/// <returns></returns>
[HttpPost("WechatPayNotify")]
public async Task<IActionResult> WechatPayNotify()
{
    IScope spanScope = null;
    var result = WeChatPayNotifyResult.Failure;
    try
    {
        //解析返回参数
        Request.EnableRewind();
        var weChatModel = (await GetOrderInfoWechat(Request));
        _logger.LogInformation($"回调参数:{weChatModel.ToJson()}");
        _tracer.ActiveSpan.SetTag("aid", weChatModel?.OutTradeNo);
        Request.Body.Position = 0;
        var notify = await _wclient.ExecuteAsync<WeChatPayUnifiedOrderNotify>(Request, _woptionsAccessor.Value);
        _logger.LogInformation("微信回调参数: " + notify?.ToJson());

        if (notify == null)
        {
            _logger.LogInformation($"微信回调通知为空");
            return NoContent();
        }
        
        if (notify.ReturnCode == "SUCCESS")
        {
            if (notify.ResultCode == "SUCCESS")
            {
                _logger.LogInformation($"微信支付成功:{weChatModel.OutTradeNo}");
                result = WeChatPayNotifyResult.Success;
            }
        }
        return result;
    }
    catch (Exception ex)
    {
        _logger.LogInformation($"微信回调通知异常:{ex.ToString()}");
        return NoContent();
    }
}

/// <summary>
/// 微信回调获取订单信息
/// </summary>
private async Task<WeChatPayUnifiedOrderNotify> GetOrderInfoWechat(HttpRequest request)
{
    var body = await new StreamReader(request.Body, Encoding.UTF8).ReadToEndAsync();
    var parser = new WeChatPayXmlParser<WeChatPayUnifiedOrderNotify>();
    var rsp = parser.Parse(body);
    return rsp;
}

总结

  1. 以上代码仅仅是核心源代码,仅供参考
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值