Lightweight Open-Source WeChat Mini Program SDK
The Magicodes.WxMiniProgram.Sdk is a lightweight SDK for WeChat Mini Programs, compatible with both .NET Framework and .NET Core. It includes ABP module integration for out-of-the-box functionality.
Key Features
- Lightweight SDK for simplified WeChat Mini Program server-side API implementation
- Support for .NET Framework and .NET Core
- ABP module integration with zero-configuration setup
- Comprehensive API coverage for various Mini Program functionalities
- Built-in access token management
- Parameter validation through attributes
- Distributed architecture support with caching capabilities
Installation
Package Installation
For ABP integration, install the appropriate NuGet package:
Install-Package Magicodes.WxMiniProgram.Sdk.Abp
Module Configuration
In your ABP module class, add the dependency:
[DependsOn(typeof(WxMiniProgramSdkModule))]
public class YourModule : AbpModule
{
// Your module implementation
}
Usage
After installation, you can inject the required services via constructor or property injection:
public class MiniProgramService
{
private readonly IMiniProgramApiService _apiService;
public MiniProgramService(IMiniProgramApiService apiService)
{
_apiService = apiService;
}
public async Task<byte[]> GenerateQrCodeAsync(string path)
{
return await _apiService.CreateQrCodeAsync(path);
}
}
Configuration
ABP Integration
Configure your Mini Program credentials in the appsettings.:
"App_MiniProgram": {
"MiniProgramAppId": "your_app_id",
"MiniProgramAppSecret": "your_app_secret"
}
Non-ABP Integration
For non-ABP projects, manually configure the MiniProgramOptions:
services.Configure<MiniProgramOptions>(options =>
{
options.MiniProgramAppId = "your_app_id";
options.MiniProgramAppSecret = "your_app_secret";
});
Distributed Cache Setup
Memory Cache
For development or single-host services:
services.AddDistributedMemoryCache();
Redis Cache
For Redis-based distributed caching:
services.AddDistributedRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "MiniProgramCache";
});
Contributing New APIs
To add new API endpoints to the SDK:
- Create a new directory in the Services folder for your module
- Add an AppService class inheriting from ServiceBase
- Implement your API logic using the provided base methods
- Write comprehensive unit tests
Example: Adding a QR Code API
/// <summary>
/// Generates a permanent QR code for Mini Programs
/// </summary>
/// <param name="path">Path to redirect to after scanning</param>
/// <param name="width">QR code width in pixels (280-1280)</param>
/// <returns>QR code image bytes</returns>
public async Task<byte[]> GeneratePermanentQrCodeAsync(string path, int width = 430)
{
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentException("Path cannot be empty", nameof(path));
var request = new QrCodeRequest
{
Path = path,
Width = width,
AutoColor = false,
LineColor = new Color { R = 0, G = 0, B = 0 },
IsTransparent = false
};
return await DownloadDataAsync("wxa/getwxacode", HttpMethod.Post, request);
}
Example: Authentication API
/// <summary>
/// Authenticates user using Mini Program login credentials
/// </summary>
/// <param name="authorizationCode">Code received from Mini Program login</param>
/// <returns>Authentication response with session information</returns>
public async Task<AuthenticationResult> AuthenticateAsync(string authorizationCode)
{
if (string.IsNullOrWhiteSpace(authorizationCode))
throw new ArgumentException("Authorization code cannot be empty", nameof(authorizationCode));
var requestUrl = $"sns/jscode2session?appid={_config.AppId}&secret={_config.Secret}&js_code={authorizationCode}&grant_type=authorization_code";
return await GetAsync<AuthenticationResult>(requestUrl);
}
Testing
Unit tests should verify both successful responses and error handling:
public class MiniProgramApiTests
{
private readonly IMiniProgramApiService _apiService;
private readonly ITestOutputHelper _testOutput;
public MiniProgramApiTests(ITestOutputHelper testOutput)
{
_testOutput = testOutput;
_apiService = GetRequiredService<IMiniProgramApiService>();
}
[Fact]
public async Task GetAccessToken_ShouldReturnValidToken()
{
// Arrange
var expectedExpiration = TimeSpan.FromHours(2);
// Act
var result = await _apiService.GetAccessTokenAsync();
// Assert
result.Should().NotBeNull();
result.IsSuccess().Should().BeTrue();
result.AccessToken.Should().NotBeNullOrWhiteSpace();
result.ExpiresIn.Should().BeGreaterThan(expectedExpiration.TotalSeconds);
_testOutput.WriteLine($"Access token: {result.AccessToken}");
}
}