.NetCore微信支付+服务商模式(saas)

准备工作

介绍

微信服务商模式,可以替商户完成收款功能,商户无需自己研发即可完成收款功能。基于saas企业开发可以采用此种模式替商户完成支付流程

引入如下Nuget包依赖

<PackageReference Include="Essensoft.AspNetCore.Payment.WeChatPay" Version="2.4.6" />
<PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="1.8.0" />

支付宝子商户配置

  "WechatPayPartnerPayConfig": { // 微信服务商配置
    "AppId": "wx*************", // 服务商appid
    "MerchantId": "*********", //服务商编号
    "MerchantV3Secret": "***********",
    "MerchantCertSerialNumber": "***********",
    "MerchantCertPrivateKey": "***********",
    "MerchantAppId": "wxf***********",  // 服务商公众号appid
    "MerchantAppSecret": "***********", //公众号秘钥
    "PayExpireTime": "35", //支付过期时间(单位:分)
    "GoldPlanReceiptLink": "https://xxxxx.xxx.com/succeed" // 点金小票前端地址
  },

代码实现

微信支付入口,H5支付和JSAPI支付

 //微信支付
 var wechatPayRequest = new WechatPayCreateRequest {
     MemberCode = memberCode,
     OutTradeNo = orderInfo.OutOrderId,
     Body = orderInfo.ProductName,
     TotalFee = (int)(orderInfo.OrderAmount * 100),
     CallbackUrl = $"{_apiUrlConfigOption.NotifyUrl}/api/Cashier/wechatPayCallback",
     ReturnUrl = request.ReturnUrl,
     OpenId = request.OpenId,
     PayType = request.PayType,
     SubAppId = request.SubAppId,
 };
 if (request.PayType == 20) {
     // 微信h5页面
     wechatPayRequest.ReturnUrl += "?out_trade_no=" + orderInfo.OutOrderId;
 }
 _logger.LogInformation($"微信支付,调服务层基础服务接口,入参:{wechatPayRequest.ToJson()}");
 var rsWechat = request.PayType == 20
     ? await _partnerPaymentService.WechatH5PayCreate(wechatPayRequest)
     : await _partnerPaymentService.WechatJsApiPayCreate(wechatPayRequest);
 _logger.LogInformation($"微信支付,调服务层基础服务接口,结果:{rsWechat?.ToJson()}");
 if (rsWechat == null || rsWechat.Code != "0") {
     return (false, rsWechat?.Message ?? "微信支付失败");
 }
 return (true, rsWechat.Data);

PartnerPaymentService.cs 服务商支付模式核心代码

    /// <summary>
    /// 服务商模式支付
    /// </summary>
    public class PartnerPaymentService : IPartnerPaymentService
    {
        /// <summary>
        /// 实体映射
        /// </summary>
        protected IMapper _mapper;

        private readonly ILogger _logger;
        private readonly ITracer _tracer;

        private readonly IHttpContextAccessor _httpContextAccessor;

        private readonly IAliPaymentService _aliPaymentService;
        private readonly IOptions<AlipayOptions> _optionsAccessor;
        private readonly IOptions<WechatPayPartnerPayConfigOption> _wechatPayPartnerPayConfig;
        private readonly IOptions<AlipayPartnerPayConfigOption> _AlipayPartnerPayConfig;
        private readonly IProxyHttpClient _proxyHttpClient;
        private readonly AppSettings _appSettings;
        private readonly ApiUrlConfigOption _apiUrlConfigOption;

        /// <summary>
        /// 初始化一个<see cref="PartnerPaymentService"/>类型的实例
        /// </summary>
        /// <param name="mapper">实体映射</param>
        /// <param name="logger"></param>
        /// <param name="tracer"></param>
        /// <param name="aliPaymentService"></param>
        /// <param name="optionsAccessor"></param>
        /// <param name="apiEndpoints"></param>
        /// <param name="httpContextAccessor"></param>
        public PartnerPaymentService(IMapper mapper, ILogger<PartnerPaymentService> logger, ITracer tracer, IHttpContextAccessor httpContextAccessor,
            IOptions<WechatPayPartnerPayConfigOption> wechatPayPartnerPayConfig,
            IOptions<AlipayPartnerPayConfigOption> alipayPartnerPayConfig, 
            IAliPaymentService aliPaymentService,
            IOptions<AlipayOptions> optionsAccessor,
            IOptions<ApiUrlConfigOption> apiUrlConfigOption,
            IProxyHttpClient proxyHttpClient,
            AppSettings appSettings) {
            _mapper = mapper;
            _logger = logger;
            _tracer = tracer;
            _httpContextAccessor = httpContextAccessor;
            _wechatPayPartnerPayConfig = wechatPayPartnerPayConfig;
            _AlipayPartnerPayConfig = alipayPartnerPayConfig;
            _aliPaymentService = aliPaymentService;
            _optionsAccessor = optionsAccessor;
            _proxyHttpClient = proxyHttpClient;
            _appSettings = appSettings;
            _apiUrlConfigOption = apiUrlConfigOption.Value;
        }
        #region 微信
        /// <summary>
        /// 微信h5支付
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<DataResponse<string>> WechatH5PayCreate(WechatPayCreateRequest request) {
            _logger.LogInformation($"微信h5支付,入参:{request.ToJson()}");

            var payConfig = await GetWechatPayConfig("WechatPayPartnerPay", request.MemberCode);

            /* 平台证书管理器,具体用法请参见文档 */
            var certManager = new InMemoryCertificateManager();
            /* 仅列出必须配置项。也包含一些诸如超时时间、UserAgent 等的配置项 */
            var options = new WechatTenpayClientOptions() {
                MerchantId = payConfig.MerchantId,
                MerchantV3Secret = payConfig.MerchantV3Secret,
                MerchantCertSerialNumber = payConfig.MerchantCertSerialNumber,
                MerchantCertPrivateKey = payConfig.MerchantCertPrivateKey,
                CertificateManager = certManager
            };
            var client = new WechatTenpayClient(options);

            var ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
            if (ip == "127.0.0.1") {
                string hostName = Dns.GetHostName();
                IPHostEntry iPHostEntry = Dns.GetHostEntry(hostName);
                var addressV = iPHostEntry.AddressList.FirstOrDefault(q => q.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);//ip4地址
                ip = addressV?.ToString();
            }
            var payRequest = new CreatePayPartnerTransactionH5Request {
                AppId = payConfig.AppId,
                SubMerchantId = payConfig.SubMerchantId,

                OutTradeNumber = request.OutTradeNo,
                Description = request.Body,
                ExpireTime = DateTime.Now.AddMinutes(payConfig.PayExpireTime),
                NotifyUrl = request.CallbackUrl,
                Amount = new CreatePayPartnerTransactionH5Request.Types.Amount {
                    Total = request.TotalFee
                },
                Scene = new CreatePayPartnerTransactionH5Request.Types.Scene {
                    ClientIp = ip,
                    H5 = new CreatePayTransactionH5Request.Types.Scene.Types.H5 {
                        Type = "Wap"
                    }
                }
            };
            var response = await client.ExecuteCreatePayPartnerTransactionH5Async(payRequest);
            if (response.IsSuccessful()) {
                var redirectUrl = request.ReturnUrl;
                if (redirectUrl.Contains("%2F")) {
                    redirectUrl = HttpUtility.UrlDecode(redirectUrl);
                }

                var responseResult = $"{response.H5Url}&redirect_url={HttpUtility.UrlEncode(request.ReturnUrl)}";

                _logger.LogInformation($"微信h5支付,结果:{responseResult}");
                return ResponseResult.Execute(responseResult);
            }

            _logger.LogInformation($"微信h5支付,结果:{response.ErrorCode}_{response.ErrorMessage}");
            return new DataResponse<string> { Code = "-1", Message = response.ErrorMessage };
        }

        /// <summary>
        /// 微信JsApi支付
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<DataResponse<string>> WechatJsApiPayCreate(WechatPayCreateRequest request) {
            _logger.LogInformation($"微信JsApi支付,入参:{request.ToJson()}");

            var (options, wechatConfig) = await GetWechatPayOptions(request.MemberCode);
            var client = new WechatTenpayClient(options);

            var payRequest = new CreatePayPartnerTransactionJsapiRequest {
                AppId = wechatConfig.AppId,
                SubMerchantId = wechatConfig.SubMerchantId,

                OutTradeNumber = request.OutTradeNo,
                Description = request.Body,
                ExpireTime = DateTime.Now.AddMinutes(wechatConfig.PayExpireTime),
                NotifyUrl = request.CallbackUrl,
                Amount = new CreatePayPartnerTransactionJsapiRequest.Types.Amount() {
                    Total = request.TotalFee
                },
                Payer = new CreatePayPartnerTransactionJsapiRequest.Types.Payer() {
                    OpenId = request.OpenId
                }
            };
            // 微信小程序支付
            if (request.PayType == 40) {
                payRequest.Payer.OpenId = null;
                payRequest.SubAppId = request.SubAppId;
                payRequest.Payer.SubOpenId = request.OpenId;
            }
            var response = await client.ExecuteCreatePayPartnerTransactionJsapiAsync(payRequest);
            if (response.IsSuccessful()) {
                IDictionary<string, string> parameter = new Dictionary<string, string>();
                if (request.PayType == 40) {
                    // https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_sl_api.php?chapter=7_7&index=5
                    // 服务商模式下应为当前调起支付小程序的appid
                    parameter = client.GenerateParametersForJsapiPayRequest(request.SubAppId, response.PrepayId);
                } else {
                    parameter = client.GenerateParametersForJsapiPayRequest(wechatConfig.AppId, response.PrepayId);
                }

                var responseResult = JsonConvert.SerializeObject(parameter);
                _logger.LogInformation($"微信JsApi支付,结果:{responseResult}");
                return ResponseResult.Execute(responseResult);
            }

            _logger.LogInformation($"微信JsApi支付,结果:{response.ErrorCode}_{response.ErrorMessage}");
            return new DataResponse<string> { Code = "-1", Message = response.ErrorMessage };
        }

        /// <summary>
        /// 微信支付查询
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<DataResponse<PayQueryResponse>> WechatPayQuery(WechatPayQueryRequest request) {
            _logger.LogInformation($"微信支付查询,入参:{request.ToJson()}");

            var (options, wechatConfig) = await GetWechatPayOptions(request.MemberCode);
            var client = new WechatTenpayClient(options);

            var payRequest = new GetPayPartnerTransactionByOutTradeNumberRequest {
                SubMerchantId = wechatConfig.SubMerchantId,
                OutTradeNumber = request.OutTradeNo
            };
            var response = await client.ExecuteGetPayPartnerTransactionByOutTradeNumberAsync(payRequest);
            if (response.IsSuccessful()) {
                var responseResult = new PayQueryResponse {
                    TradeState = response.TradeState,
                    PayNumber = response.TransactionId
                };
                _logger.LogInformation($"微信支付查询,结果:{responseResult.ToJson()}");
                return ResponseResult.Execute(responseResult);
            }

            _logger.LogInformation($"微信支付查询,结果:{response.ErrorCode}_{response.ErrorMessage}");
            return new DataResponse<PayQueryResponse> { Code = "-1", Message = response.ErrorMessage };
        }

        /// <summary>
        /// 微信支付退款
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<DataResponse<bool>> WechatPayRefund(WechatPayRefundRequest request) {
            _logger.LogInformation($"微信支付退款,入参:{request.ToJson()}");

            var (options, wechatConfig) = await GetWechatPayOptions(request.MemberCode);
            var client = new WechatTenpayClient(options);

            var payRequest = new CreateRefundDomesticRefundRequest {
                SubMerchantId = wechatConfig.SubMerchantId,
                OutTradeNumber = request.OutTradeNo,
                OutRefundNumber = $"{request.MemberCode}" + DateTimeOffset.Now.ToString("yyyyMMddHHmmssfff"),
                Amount = new CreateRefundDomesticRefundRequest.Types.Amount() {
                    Total = request.TotalFee,
                    Refund = request.RefundFee
                },
                //Reason = request.RefundDesc
            };
            var response = await client.ExecuteCreateRefundDomesticRefundAsync(payRequest);
            if (response.IsSuccessful()) {
                var responseResult = response.Status;
                _logger.LogInformation($"微信支付退款,结果:{responseResult}");
                return ResponseResult.Execute(true);
            }

            _logger.LogInformation($"微信支付退款,结果:{response.ErrorCode}_{response.ErrorMessage}");
            return new DataResponse<bool> { Code = "-1", Message = response.ErrorMessage };
        }

        /// <summary>
        /// 获得微信公众号静默登录后的openid
        /// </summary>
        /// <returns></returns>
        public async Task<DataResponse<string>> GetWechatOpenId(GetWechatOpenIdRequest request) {
            _logger.LogInformation($"获得得微信公众号静默登录后的openid流程开始");
            try {
                _logger.LogInformation($"获得得微信公众号静默登录后的openid,入参:{request.ToJson()}");
                var payConfig = await this.GetWechatPayConfig("WechatPayPartnerPay");
                var openId = string.Empty;
                //从微信接口获得opeanId
                var url =
                    $"https://api.weixin.qq.com/sns/oauth2/access_token?appid={payConfig.MerchantAppId}&secret={payConfig.MerchantAppSecret}&code={request.Code}&grant_type=authorization_code";

                var proxyHttpClient = _proxyHttpClient.Create(url, HttpMethod.Get);
                var rs = await proxyHttpClient.SendAsString(false);
                _logger.LogInformation($"获得得微信公众号静默登录后的openid,调微信获取结果:{rs?.ToJson()}");

                if (rs.Contains("openid")) {
                    var callData = rs.ToObject<GetWechatOpenIdModel>();
                    openId = callData.Openid;
                }
                _logger.LogInformation($"获得得微信公众号静默登录后的openid,获取的opeanId为:{openId}");
                if (string.IsNullOrWhiteSpace(openId)) {
                    return ResponseResult.Execute(string.Empty, "-1", "没有获取到opeanId");
                }

                return ResponseResult.Execute(openId);
            } catch (Exception e) {
                _logger.LogInformation($"获得得微信公众号静默登录后的openid,系统异常:{e.Message}");
                return ResponseResult.Execute(string.Empty, "-1", $"系统异常:{e.Message}");
            } finally {
                _logger.LogInformation("获得得微信公众号静默登录后的openid流程结束");
            }
        }
        #endregion

        #region 获取支付配置

        /// <summary>
        /// 支付宝服务商支付options
        /// </summary>
        /// <param name="tenantId"></param>
        /// <returns></returns>
        private async Task<(AlipayOptions, AlipayPayPartnerPayConfigModel)> GetAlipayPayOptions(string tenantId = null) {
            var payConfig = await GetAlipayPayConfig("AlipayPartnerPay", tenantId);

            var options = new AlipayOptions {
                AppId = payConfig.AppId,
                AlipayPublicKey = payConfig.AlipayPublicKey,
                AppPrivateKey = payConfig.AppPrivateKey
            };

            return (options, payConfig);
        }

        /// <summary>
        /// 微信服务商支付options
        /// </summary>
        /// <param name="tenantId"></param>
        /// <returns></returns>
        private async Task<(WechatTenpayClientOptions, WechatPayPartnerPayConfigModel)> GetWechatPayOptions(string tenantId = null) {
            var payConfig = await GetWechatPayConfig("WechatPayPartnerPay", tenantId);

            /* 平台证书管理器,具体用法请参见文档 */
            var certManager = new InMemoryCertificateManager();
            /* 仅列出必须配置项。也包含一些诸如超时时间、UserAgent 等的配置项 */
            var options = new WechatTenpayClientOptions() {
                MerchantId = payConfig.MerchantId,
                MerchantV3Secret = payConfig.MerchantV3Secret,
                MerchantCertSerialNumber = payConfig.MerchantCertSerialNumber,
                MerchantCertPrivateKey = payConfig.MerchantCertPrivateKey,
                CertificateManager = certManager
            };

            return (options, payConfig);
        }
        /// <summary>
        /// 获取微信支付配置
        /// </summary>
        /// <param name="parameterCode">系统配置名称</param>
        /// <param name="memberCode">租户编号</param>
        /// <returns></returns>
        public async Task<WechatPayPartnerPayConfigModel> GetWechatPayConfig(string parameterCode, string memberCode = null) {
            var payConfig = new WechatPayPartnerPayConfigModel {
                AppId = _wechatPayPartnerPayConfig.Value.AppId,
                MerchantId = _wechatPayPartnerPayConfig.Value.MerchantId,
                MerchantV3Secret = _wechatPayPartnerPayConfig.Value.MerchantV3Secret,
                MerchantCertSerialNumber = _wechatPayPartnerPayConfig.Value.MerchantCertSerialNumber,
                MerchantCertPrivateKey = _wechatPayPartnerPayConfig.Value.MerchantCertPrivateKey,
                MerchantAppId = _wechatPayPartnerPayConfig.Value.MerchantAppId,
                MerchantAppSecret = _wechatPayPartnerPayConfig.Value.MerchantAppSecret,
                PayExpireTime = _wechatPayPartnerPayConfig.Value.PayExpireTime,
                GoldPlanReceiptLink = _wechatPayPartnerPayConfig.Value.GoldPlanReceiptLink,
            };

            if (!string.IsNullOrWhiteSpace(memberCode)) {
                payConfig.SubMerchantId = "******"; // 子商户号
            }

            return payConfig;
        }
        #endregion
    }

WechatPaymentService.cs底层微信支付核心代码

using System;
using System.Threading.Tasks;
using Essensoft.AspNetCore.Payment.WeChatPay;
using Essensoft.AspNetCore.Payment.WeChatPay.Request;
using Essensoft.AspNetCore.Payment.WeChatPay.Response;
using ICH.Util.Extension;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Payment.WeChatPay.Model;

namespace Payment.WeChatPay
{
    public class WechatPaymentService: IWechatPaymentService
    {
        private readonly IWeChatPayClient _client ;
        public IOptions<WeChatPayOptions> OptionsAccessor { get; set; }
        private readonly ILogger _logger;

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

        public async Task<WeChatPayUnifiedOrderResponse> H5Pay(WeChatPayH5PayModel model)
        {
            _logger.LogInformation($"微信H5支付入参:{model.ToJson()}");

            var request = new WeChatPayUnifiedOrderRequest()
            {
                Body = model.Body,
                OutTradeNo = model.OutTradeNo,
                TotalFee = model.TotalFee,
                SpBillCreateIp = model.SpbillCreateIp,
                NotifyUrl = model.NotifyUrl,
                Attach = model.Attach,
                TradeType = "MWEB",
                TimeStart = DateTime.Now.ToString("yyyyMMddHHmmss"),
                TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss")
            };
            var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);
            _logger.LogInformation($"WeChatPayUnifiedOrderH5Pay:{response.ToJson()}");
            return response;
        }

        public async Task<WeChatPayUnifiedOrderResponse> NativePay(WeChatPayH5PayModel model)
        {
            _logger.LogInformation($"微信 Native支付入参:{model.ToJson()}");

            var request = new WeChatPayUnifiedOrderRequest()
            {
                Body = model.Body,
                OutTradeNo = model.OutTradeNo,
                TotalFee = model.TotalFee,
                SpBillCreateIp = model.SpbillCreateIp,
                NotifyUrl = model.NotifyUrl,
                Attach = model.Attach,
                TradeType = "NATIVE",
                TimeStart = DateTime.Now.ToString("yyyyMMddHHmmss"),
                TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss")
            };
            var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);
            _logger.LogInformation($"WeChatPayUnifiedOrderNativePay:{response.ToJson()}");
            return response;
        }

        public async Task<string> AppPay(WeChatPayAppPayModel model)
        {
            _logger.LogInformation($"微信APP支付入参:{model.ToJson()}");

            var request = new WeChatPayUnifiedOrderRequest()
            {
                Body = model.Body,
                OutTradeNo = model.OutTradeNo,
                TotalFee = model.TotalFee,
                SpBillCreateIp = model.SpbillCreateIp,
                NotifyUrl = model.NotifyUrl,
                TradeType = "APP",
                TimeStart = DateTime.Now.ToString("yyyyMMddHHmmss"),
                TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss")
            };
            var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);

            _logger.LogInformation($"wechatAPPPayResponse:{response.ToJson()}");

            if (response.ReturnCode == "SUCCESS" && response.ResultCode == "SUCCESS")
            {
                var req = new WeChatPayAppSdkRequest()
                {
                    PrepayId = response.PrepayId,
                };
                var parameter = await _client.ExecuteAsync(req, OptionsAccessor.Value);

                return JsonConvert.SerializeObject(parameter);
            }
            return "";
        }

        public async Task<(WeChatPayUnifiedOrderResponse, string)> AppletPay(WeChatPayAppletPayModel model)
        {
            _logger.LogInformation($"微信Applet支付入参:{model.ToJson()}");

            var request = new WeChatPayUnifiedOrderRequest()
            {
                OpenId = model.OpenId,
                Body = model.Body,
                OutTradeNo = model.OutTradeNo,
                TotalFee = model.TotalFee,
                SpBillCreateIp = model.SpbillCreateIp,
                NotifyUrl = model.NotifyUrl,
                Attach = model.Attach,
                TradeType = "JSAPI",
                TimeStart = DateTime.Now.ToString("yyyyMMddHHmmss"),
                TimeExpire = DateTime.Now.AddMinutes(15).ToString("yyyyMMddHHmmss")
            };
            var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);

            _logger.LogInformation($"wechatAppletPayResponse:{response.ToJson()}");

            if (response.ReturnCode == "SUCCESS" && response.ResultCode == "SUCCESS")
            {
                var req = new WeChatPayJsApiSdkRequest()
                {
                    Package = $"prepay_id={response.PrepayId}"
                };
                var parameter = await _client.ExecuteAsync(req, OptionsAccessor.Value);

                return (response, JsonConvert.SerializeObject(parameter));
            }

            return (response, string.Empty);
        }

        public async Task<(bool, WeChatPayRefundResponse)> Refund(WeChatPayRefundModel model)
        {
            _logger.LogInformation($"微信退款申请入参:{model.ToJson()}");

            var request = new WeChatPayRefundRequest()
            {
                OutRefundNo = model.OutRefundNo,
                TransactionId = model.TransactionId,
                OutTradeNo = model.OutTradeNo,
                TotalFee = model.TotalFee,
                RefundFee = model.RefundFee,
                RefundDesc = model.RefundDesc,
                NotifyUrl = model.NotifyUrl,
            };
            var response = await _client.ExecuteAsync(request, OptionsAccessor.Value);

            _logger.LogInformation($"wechatRefundResponse:{response.ToJson()}");

            return (response.ReturnCode == "SUCCESS" && response.ResultCode == "SUCCESS", response);
        }

        public async Task<WeChatPayOrderQueryResponse> Query(WeChatPayOrderQueryModel model)
        {
            var request = new WeChatPayOrderQueryRequest
            {
                TransactionId = model.TransactionId,
                OutTradeNo = model.OutTradeNo
            };

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

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

            _logger.LogInformation($"wechatQueryResponse:{response.ToJson()}");

            return response;
        }

        public async Task<WeChatPayRefundQueryResponse> RefundQuery(WeChatPayRefundQueryModel model)
        {
            var request = new WeChatPayRefundQueryRequest
            {
                RefundId = model.RefundId,
                OutRefundNo = model.OutRefundNo,
                TransactionId = model.TransactionId,
                OutTradeNo = model.OutTradeNo
            };

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

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

            _logger.LogInformation($"微信退款查询返回:{response.ToJson()}");

            return response;
        }
    }
}

总结

  1. 微信支付区分H5支付和JSAPI支付(微信环境打开H5页面支付)
  2. 微信H5支付,需要配置微信子商户H5支付域名地址
  3. 微信JSAPI支付,需要配置微信公众号获取得到openId
  4. 微信JSAPI支付,需要配置点金计划地址
  5. 微信支付金额单位:分
  6. 商户签约为子商户后,得到{“subMerchantId”:“******”}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值