评论

开源微信支付 v3 版 .Net SDK(支持 .NET Core / Framework,完整封装全部 v3 API)

.NET Core & Framework 微信支付 v3 版 API SDK,可跨平台,支持直连商户 & 服务商,请求自动签名,提供 RSA、AES-GCM、SHA-256 工具类。

基于 Flurl.Http 的微信支付 API v3 版 .NET SDK。

注意:本库仅支持 v3 版 API,如需 v2 版 API 请移步 SKIT.FlurlHttpClient.Wechat.TenpayV2

GitHub 项目地址:https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat

Gitee 项目地址:https://gitee.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat

NuGet 项目地址:https://www.nuget.org/packages/SKIT.FlurlHttpClient.Wechat.TenpayV3


前言

目前网络上还没有基于微信支付 v3 版 API 完整封装的 .NET 客户端(大部分只提供了基础的如支付、退款一类 API 封装),遑论开源了;这都 2021 年了,官方本身提供的示例代码还只能运行在 .NET Framework on Windows 上;就连 RSA 签名这么基础的东西都没有人封装(确切的说是因为 RSA 有很多种分块模式和填充模式,网上能找到的往往只封装了其中一种,但却未必符合微信支付的要求)。

于是萌生了自己封装一个库的想法,打算解决这几个痛点,同时也是推广一下微软官方的 System.Text.Json


特性

  • 基于 Flurl.Http,可与 IHttpClientFactory 集成。
  • 支持 .NET Framework 4.6.1+、.NET Standard 2.0+、.NET Core 2.0+、.NET 5、.NET 6。
  • 支持 Windows / Linux / macOS 多平台部署。
  • 支持 System.Text.Json(默认)和 Newtonsoft.Json 两种序列化方式。
  • 异步式编程。
  • 强类型接口模型。
  • 支持拦截器功能。
  • 完整、完善、完全的微信支付 API 封装,支持目前(截至 2021-12-01)微信支付提供的全部 v3 版 API
  • 支持直连商户服务商两种模式。
  • 请求时自动生成签名,无需开发者手动干预。
  • 提供了微信支付所需的 RSAAESSHA-256 等算法工具类。
  • 提供 SourceLink,方便项目无源码调试。
  • 提供了生成 JS-SDK/APP 调起支付参数及签名加密请求敏感数据解析响应敏感数据解析回调通知事件敏感数据等扩展方法。

基础用法

安装:

# 通过 NuGet 安装
> Install-Package SKIT.FlurlHttpClient.Wechat.TenpayV3

# 通过 dotnet-tools 安装
> dotnet add package SKIT.FlurlHttpClient.Wechat.TenpayV3

你也可通过 Visual Studio NuGet 管理器图形化界面安装(注意搜索时需勾选“包括预发行版”)。

初始化:

using SKIT.FlurlHttpClient.Wechat;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;

/* 平台证书管理器,具体用法请参见文档的高级技巧 */
var manager = new InMemoryCertificateManager();
/* 仅列出必须配置项。也包含一些诸如超时时间、UserAgent 等的配置项 */
var options = new WechatTenpayClientOptions()
{
    MerchantId = "微信商户号",
    MerchantV3Secret = "微信商户 v3 API 密钥",
    MerchantCertificateSerialNumber = "微信商户证书序列号",
    MerchantCertificatePrivateKey = "-----BEGIN PRIVATE KEY-----微信商户证书私钥-----END PRIVATE KEY-----",
    PlatformCertificateManager = manager
};
var client = new WechatTenpayClient(options);

请求 & 响应:

using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;

/* 以 JSAPI 统一下单接口为例 */
var request = new CreatePayTransactionJsapiRequest()
{
    OutTradeNumber = "商户订单号",
    AppId = "微信 AppId",
    Description = "订单描述",
    ExpireTime = DateTimeOffset.Now.AddMinutes(15),
    NotifyUrl = "https://example.com",
    Amount = new Models.CreatePayTransactionJsapiRequest.Types.Amount()
    {
        Total = 100
    },
    Payer = new Models.CreatePayTransactionJsapiRequest.Types.Payer()
    {
        OpenId = "用户 OpenId"
    }
};
var response = await client.ExecuteCreatePayTransactionJsapiAsync(request);
if (response.IsSuccessful())
{
    Console.WriteLine("PrepayId:" + response.PrepayId);
}
else
{
    Console.WriteLine("HTTP 状态:" + response.RawStatus);
    Console.WriteLine("错误代码:" + response.ErrorCode);
    Console.WriteLine("错误描述:" + response.ErrorMessage);
}

验证响应签名:

/* 一般情况下可以跳过验证响应的签名 */
bool valid = client.VerifyResponseSignature(response);

生成客户端 JS-SDK 调起支付所需参数:

/* 字典结构,包含客户端 JS-SDK 调起支付所需的完整参数 */
var paramMap = client.GenerateParametersForJsapiPayRequest(request.AppId, response.PrepayId);

验签、解析并解密微信回调通知中的敏感信息:

string callbackJson = "{ 微信商户平台发来的 JSON 格式的通知内容 }";
string callbackTimestamp = "微信回调通知中的 Wechatpay-Timestamp 标头";
string callbackNonce = "微信回调通知中的 Wechatpay-Nonce 标头";
string callbackSignature = "微信回调通知中的 Wechatpay-Signature 标头";
string callbackSerialNumber = "微信回调通知中的 Wechatpay-Serial 标头";
 
bool valid = client.VerifyEventSignature(callbackTimestamp, callbackNonce, callbackJson, callbackSignature, callbackSerialNumber);
if (valid)
{
    /* 将 JSON 反序列化得到通知对象 */
    /* 你也可以将 WechatTenpayEvent 类型直接绑定到 MVC 模型上,这样就不再需要手动反序列化 */
    var callbackModel = client.DeserializeEvent(callbackJson);
    if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
    {
        /* 根据事件类型,解密得到支付通知敏感数据 */
        var callbackResource = client.DecryptEventResource<Events.TransactionResource>(callbackModel);
        string outTradeNumber = callbackResource.OutTradeNumber;
        string transactionId = callbackResource.TransactionId;
        Console.WriteLine("订单 {0} 已完成支付,交易单号为 {1}", outTradeNumber, transactionId);
    }
}

更多使用说明请阅读项目仓库中的开发文档。

项目仓库中还包含了一个示例项目,以供开发者快速掌握本库的使用方法。


高级技巧

点此查看完整文档

最后一次编辑于  2022-07-21  
点赞 10
收藏
评论

17 个评论

  • T
    T
    2022-07-24

    我在控制台测试,执行到ExecuteCreateTransferBatchAsync方法程序直接关闭终止,也不抛异常。

    2022-07-24
    赞同 4
    回复 3
    • willin
      willin
      2022-11-07
      解决了吗
      2022-11-07
      回复
    • 🍓 ℃
      🍓 ℃
      2022-12-18
      我也是这样 大佬解决了吗
      2022-12-18
      回复
    • Le.Le
      Le.Le
      2023-11-16
      MerchantCertificatePrivateKey    这个东西是key的路径么
      2023-11-16
      回复
  • wilsonจุ๊บ
    wilsonจุ๊บ
    2022-11-29

    发起支付,提示签名失败

    2022-11-29
    赞同 1
    回复 2
    • 手可摘星辰
      手可摘星辰
      2023-01-01
      我也是发起支付就签名错误怎么解决的
      2023-01-01
      回复
    • Le.Le
      Le.Le
      2023-11-16
      MerchantCertificatePrivateKey 这个东西是key的路径么
      2023-11-16
      回复
  • 姜先生
    姜先生
    2021-07-22

    给一套事例

    2021-07-22
    赞同 1
    回复
  • 超载
    超载
    2023-03-20

    支持netcore3.1?

    2023-03-20
    赞同
    回复
  • ᝰꫛꫀꪝ
    ᝰꫛꫀꪝ
    2023-02-21

    【微信支付V3-支付回调签名校验】调用 VerifyEventSignature 方法进行校验 返回结果为false ,有人知道怎么搞吗

    2023-02-21
    赞同
    回复 1
    • While
      While
      2023-12-22
      哥你解决了么
      2023-12-22
      回复
  • 手可摘星辰
    手可摘星辰
    2023-01-01

    请问下调用ExecuteCreatePayTransactionJsapiAsync 签名错误怎么解决阿 找几天了确实不知道错在哪

    2023-01-01
    赞同
    回复
  • 猫哥
    猫哥
    2022-10-14

    当协商历史中有图片就报错了。

    接口:ExecuteQueryMerchantServiceComplaintNegotiationHistoriesAsync

    报错如下

    [JsonException: The JSON value could not be converted to SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.QueryMerchantServiceComplaintNegotiationHistoriesResponse+Types+NegotiationHistory+Types+ComplaintMedia[]. Path: $.data[2].complaint_media_list | LineNumber: 0 | BytePositionInLine: 534.]
       System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType) +89
       System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value) +96
       System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) +458
       System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader) +275
       System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) +932
       System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value) +458
       System.Text.Json.Serialization.JsonCollectionConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value) +315dr 
    
    2022-10-14
    赞同
    回复 1
    • 猫哥
      猫哥
      2022-10-21
      The JSON value could not be converted to SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.QueryMerchantServiceComplaintNegotiationHistoriesResponse+Types+NegotiationHistory+Types+ComplaintMedia[]. Path: $.data[4].complaint_media_list | LineNumber: 0 | BytePositionInLine: 1261
      2022-10-21
      回复
  • 给生活充点电
    给生活充点电
    2022-09-29

    【微信支付V3-支付回调签名校验】调用 VerifyEventSignature 方法进行校验 返回结果为false 并且 错误信息为null。已经拿到证书(-----BEGIN CERTIFICATE-----......-----END CERTIFICATE-----)序列号与应答序列号一致。@楼主

    2022-09-29
    赞同
    回复
  • cli
    cli
    2022-09-26

    大佬,我用这个sdk再windows运行正常,再Linux上会报一个:The request with exception: The SSL connection could not be established,这个错误,这是我Linux环境问题还是咋回事?

    2022-09-26
    赞同
    回复
  • 巧合
    巧合
    2022-09-06

    有授权怎么做吗。

    2022-09-06
    赞同
    回复

正在加载...

登录 后发表内容