feat: add referral qrcode generation provider

This commit is contained in:
xiong
2026-07-26 20:45:14 +08:00
parent 4279795d46
commit 7c1fe7688b
11 changed files with 490 additions and 8 deletions

View File

@@ -4,6 +4,7 @@ using Microsoft.Extensions.DependencyInjection;
using Npgsql;
using Tiku.Application.Commerce;
using Tiku.Application.Auth;
using Tiku.Application.Growth;
using Tiku.Application.Storage;
using Tiku.Domain.Identity;
using Tiku.Domain.Tenancy;
@@ -14,6 +15,7 @@ namespace Tiku.IntegrationTests.Api;
public sealed class ApiTestFactory(
IWechatOAuthClient? wechatOAuthClient = null,
IObjectStorageService? objectStorageService = null,
IReferralQrcodeGenerator? referralQrcodeGenerator = null,
IPaymentProviderGateway? paymentProviderGateway = null) : WebApplicationFactory<Program>
{
private readonly string databaseName = Guid.NewGuid().ToString();
@@ -45,6 +47,11 @@ public sealed class ApiTestFactory(
services.AddSingleton(objectStorageService);
}
if (referralQrcodeGenerator is not null)
{
services.AddSingleton(referralQrcodeGenerator);
}
if (paymentProviderGateway is not null)
{
services.AddSingleton(paymentProviderGateway);

View File

@@ -301,6 +301,23 @@ public sealed class AssetAccessEndpointTests
return Task.FromResult(Signed("GET", request.Bucket, request.ObjectKey, request.ExpiresIn));
}
public Task<ObjectStorageWriteResult> WriteObjectAsync(
ObjectStorageWriteRequest request,
CancellationToken cancellationToken = default)
{
return Task.FromResult(new ObjectStorageWriteResult(
request.Provider,
request.Bucket,
request.ObjectKey,
new Uri($"https://storage.example.test/{request.ObjectKey}"),
request.FileSizeBytes,
request.MimeType,
request.ChecksumSha256,
"fake-etag",
new Dictionary<string, string>(),
"fake-write"));
}
public Task<ObjectStorageMetadata> HeadObjectAsync(
ObjectStorageHeadRequest request,
CancellationToken cancellationToken = default)

View File

@@ -381,6 +381,23 @@ public sealed class AssetManagementEndpointTests
"fake-signed-url"));
}
public Task<ObjectStorageWriteResult> WriteObjectAsync(
ObjectStorageWriteRequest request,
CancellationToken cancellationToken = default)
{
return Task.FromResult(new ObjectStorageWriteResult(
request.Provider,
request.Bucket,
request.ObjectKey,
new Uri($"https://storage.example.test/{request.ObjectKey}"),
request.FileSizeBytes,
request.MimeType,
request.ChecksumSha256,
"fake-etag",
new Dictionary<string, string>(),
"fake-write"));
}
public Task<ObjectStorageMetadata> HeadObjectAsync(
ObjectStorageHeadRequest request,
CancellationToken cancellationToken = default)

View File

@@ -81,7 +81,8 @@ public sealed class ReferralEndpointTests
[Fact]
public async Task Member_can_bind_referral_and_create_qrcode()
{
await using var factory = new ApiTestFactory();
var qrcodeGenerator = new FakeReferralQrcodeGenerator();
await using var factory = new ApiTestFactory(referralQrcodeGenerator: qrcodeGenerator);
var seed = await SeedReferralAsync(factory, includeCode: true);
using var client = factory.CreateClient();
await LoginAsync(client, seed.Student);
@@ -106,7 +107,12 @@ public sealed class ReferralEndpointTests
Assert.Equal(seed.Referrer.UserId, bindItem.Lead.ReferrerUserId);
Assert.Equal(HttpStatusCode.OK, qrcode.StatusCode);
Assert.Equal("Ready", qrcodeItem!.Status);
Assert.StartsWith("miniapp://", qrcodeItem.QrcodeUrl, StringComparison.Ordinal);
Assert.Equal("https://cdn.example.test/referral/qrcode.png", qrcodeItem.QrcodeUrl);
Assert.Equal(1, qrcodeGenerator.CallCount);
Assert.Equal("wechat-miniapp", qrcodeGenerator.LastRequest!.Provider);
Assert.Equal("pages/home/index", qrcodeGenerator.LastRequest.Page);
Assert.Equal($"ref={qrcodeItem.RefCode}", qrcodeGenerator.LastRequest.Scene);
Assert.Equal("fake-referral-qrcode-generator", qrcodeItem.Metadata.GetProperty("generatedBy").GetString());
using var scope = factory.Services.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<TikuDbContext>();
@@ -308,6 +314,24 @@ public sealed class ReferralEndpointTests
return document.RootElement.Clone();
}
private sealed class FakeReferralQrcodeGenerator : IReferralQrcodeGenerator
{
public int CallCount { get; private set; }
public ReferralQrcodeGenerateRequest? LastRequest { get; private set; }
public Task<ReferralQrcodeGenerateResult> GenerateAsync(
ReferralQrcodeGenerateRequest request,
CancellationToken cancellationToken = default)
{
CallCount++;
LastRequest = request;
return Task.FromResult(new ReferralQrcodeGenerateResult(
"https://cdn.example.test/referral/qrcode.png",
request.Provider,
JsonSerializer.SerializeToElement(new { generatedBy = "fake-referral-qrcode-generator" })));
}
}
private sealed record LoginSeed(Guid TenantId, Guid UserId, string Phone);
private sealed record ReferralSeed(