Streamlining WeChat API Integration Using Magicodes.Wx.Sdk and WebApiClientCore

The Magicodes.Wx.Sdk aims to provide the most straightforward approach to handling WeChat integrations, covering Official Accounts, Mini Programs, and Enterprise WeChat, including support for Abp VNext modules. This guide focuses on how to contribute to the SDK by defining new API interfaces efficiently.

Core Dependency: WebApiClientCore

The simplicity of the SDK is largely atributed to the WebApiClientCore library. It handles the heavy lifting of HTTP request packaging, parameter mapping, and response validation. You can find the library at https://github.com/dotnetcore/WebApiClient.

Implementation Walkthrough

We will use the "Customer Service Account Management" feature (specifically adding an account) as a case study. The official documentation is available at WeChat Official Docs.

1. Define the API Interface

Create an interface that represents the remote service. By inheriting from IWxApiWithAccessTokenFilter, the SDK automatically appends the access_token query parameter to every request.

/// <summary>
/// Manages customer service accounts
/// </summary>
[HttpHost("https://api.weixin.qq.com/customservice/kfaccount/")]
public interface ICustomerServiceApi : IWxApiWithAccessTokenFilter
{
    /// <summary>
    /// Creates a new customer service account
    /// </summary>
    [HttpPost("add")]
    Task<BaseWxResponse> CreateAccountAsync(NewAccountDto accountDto);

    /// <summary>
    /// Modifies existing account details
    /// </summary>
    [HttpPost("update")]
    Task<BaseWxResponse> ModifyAccountAsync(NewAccountDto accountDto);

    /// <summary>
    /// Removes a customer service account
    /// </summary>
    [HttpPost("del")]
    Task<BaseWxResponse> RemoveAccountAsync(DeleteAccountDto deleteDto);
}

Key Attributes:

2. Define Data Transfer Objects (DTOs)

Create classes to represent the input parameters. Use JsonProperty to map C# properties to JSON keys required by WeChat.

public class NewAccountDto
{
    /// <summary>
    /// Account format: prefix@wechatid
    /// </summary>
    [JsonProperty("kf_account")]
    [Required]
    [StringLength(30)]
    public string AccountId { get; set; }

    /// <summary>
    /// Nickname for the support agent
    /// </summary>
    [JsonProperty("nickname")]
    [StringLength(16)]
    public string AgentName { get; set; }
}

Tip: You can use Visual Studio's "Paste JSON as Classes" feature (Edit > Paste Special) to generate these DTOs quickly from API samples.

3. Handle API Responses

If the endpoint returns specific data, create a response class inheriting from BaseWxResponse. If it only returns a standard success/error code, use BaseWxResponse directly.

public class AuthTokenResponse : BaseWxResponse
{
    /// <summary>
    /// The token value
    /// </summary>
    [JsonProperty("access_token")]
    public string Token { get; set; }

    /// <summary>
    /// Validity duration in seconds
    /// </summary>
    [JsonProperty("expires_in")]
    public int LifeSpan { get; set; }
}

4. Unit Testing

Verify the implementation using xUnit and the test factory provided by the SDK.

public class NotificationApiTest : TestBase, IClassFixture<TestWebApplicationFactory>
{
    private readonly INotificationApi notificationApi;

    public NotificationApiTest(TestWebApplicationFactory factory, ITestOutputHelper output) : base(factory, output)
    {
        notificationApi = GetRequiredService<INotificationApi>();
    }

    [Fact]
    public async Task NotifyUser_ShouldSucceed()
    {
        var response = await notificationApi.SendAsync(new NotificationInput
        {
            Recipient = "oXELNwzZgamuLS0JrJhVgdelzKyw",
            TemplateId = "riid7aad8OKRQD9Ey6dclWBBkrqZSFDhlpKh0_spGLA",
            Payload = new Dictionary<string, TemplateDataItem>
            {
                {"first", new TemplateDataItem("Test")},
                {"keyword1", new TemplateDataItem("User")}
            }
        });

        // Throws WxSdkException if the API call failed
        response.EnsureSuccess();
    }
}

Behind the Scenes

Access Token Management

The IWxApiWithAccessTokenFilter interface acts as a marker that triggers the AccessTokenApiFilter. This filter intercepts outgoing requests to inject the token automatically.

[JsonNetReturn(EnsureMatchAcceptContentType = false)]
[AccessTokenApiFilter]
public interface IWxApiWithAccessTokenFilter { }

The filter logic retrieves the token from the ITokenManager and appends it to the query string:

public class AccessTokenApiFilter : ApiFilterAttribute
{
    public override async Task OnRequestAsync(ApiRequestContext ctx)
    {
        var manager = ctx.HttpContext.ServiceProvider.GetRequiredService<ITokenManager>();
        var token = await manager.GetAccessTokenAsync();
        ctx.HttpContext.RequestMessage.AddUrlQuery("access_token", token);
    }

    public override Task OnResponseAsync(ApiResponseContext ctx) => Task.CompletedTask;
}

Base Response Structure

All standard responses inherit from BaseWxResponse, which handles error code parsing and success verification.

public class BaseWxResponse
{
    [JsonProperty("errcode")]
    public virtual ReturnCodes Code { get; set; }

    [JsonProperty("errmsg")]
    public virtual string ErrorMessage { get; set; }

    public virtual bool IsSuccess() => Code == ReturnCodes.请求成功;

    public virtual string GetFriendlyMessage() => Code.ToString();
}

Tags: WeChat API Magicodes.Wx.Sdk WebApiClientCore C# .NET Core

Posted on Tue, 12 May 2026 17:18:31 +0000 by doddatika