init commit

This commit is contained in:
Fu Diwei
2021-05-10 15:30:00 +08:00
commit 5b13f3f558
916 changed files with 38562 additions and 0 deletions

View File

@@ -0,0 +1 @@
appsettings.local.json

View File

@@ -0,0 +1,3 @@
{
"ip_list": [ "127.0.0.1", "127.0.0.2", "101.226.103.0/25" ]
}

View File

@@ -0,0 +1,3 @@
{
"ip_list": [ "127.0.0.1", "127.0.0.2", "101.226.103.0/25" ]
}

View File

@@ -0,0 +1,6 @@
{
"errcode": 0,
"errmsg": "ok",
"ticket": "bxLdikRXVbTPdHSM05e5u5sUoXNKdvsdshFKA",
"expires_in": 7200
}

View File

@@ -0,0 +1,4 @@
{
"access_token": "ACCESS_TOKEN",
"expires_in": 7200
}

View File

@@ -0,0 +1,5 @@
{
"tag": {
"name": "广东"
}
}

View File

@@ -0,0 +1,6 @@
{
"tag": {
"id": 134,
"name": "广东"
}
}

View File

@@ -0,0 +1,5 @@
{
"tag": {
"id": 134
}
}

View File

@@ -0,0 +1,4 @@
{
"errcode": 0,
"errmsg": "ok"
}

View File

@@ -0,0 +1,19 @@
{
"tags": [
{
"id": 1,
"name": "每天一罐可乐星人",
"count": 0
},
{
"id": 2,
"name": "星标组",
"count": 0
},
{
"id": 127,
"name": "广东",
"count": 5
}
]
}

View File

@@ -0,0 +1,6 @@
{
"tag": {
"id": 134,
"name": "广东人"
}
}

View File

@@ -0,0 +1,4 @@
{
"errcode": 0,
"errmsg": "ok"
}

View File

@@ -0,0 +1,4 @@
{
"tagid": 134,
"next_openid": ""
}

View File

@@ -0,0 +1,10 @@
{
"count": 2,
"data": {
"openid": [
"ocYxcuAEy30bX0NXmGn4ypqx3tI0",
"ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"
]
},
"next_openid": "ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"
}

View File

@@ -0,0 +1,3 @@
{
"openid": "ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"
}

View File

@@ -0,0 +1,3 @@
{
"tagid_list": [ 134, 2 ]
}

View File

@@ -0,0 +1,7 @@
{
"openid_list": [
"ocYxcuAEy30bX0NXmGn4ypqx3tI0",
"ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"
],
"tagid": 134
}

View File

@@ -0,0 +1,7 @@
{
"openid_list": [
"ocYxcuAEy30bX0NXmGn4ypqx3tI0",
"ocYxcuBt0mRugKZ7tGAHPnUaOW7Y"
],
"tagid": 134
}

View File

@@ -0,0 +1,3 @@
{
"openid_list": [ "OPENID1", "OPENID2" ]
}

View File

@@ -0,0 +1,3 @@
{
"openid_list": [ "OPENID1", "OPENID2" ]
}

View File

@@ -0,0 +1,12 @@
{
"total": 23000,
"count": 10000,
"data": {
"openid": [
"OPENID1",
"OPENID2",
"OPENID10000"
]
},
"next_openid": "OPENID10000"
}

View File

@@ -0,0 +1,12 @@
{
"user_list": [
{
"openid": "otvxTs4dckWG7imySrJd6jSi0CWE",
"lang": "zh_CN"
},
{
"openid": "otvxTs_JZ6SEiP0imdhpi50fuSZg",
"lang": "zh_CN"
}
]
}

View File

@@ -0,0 +1,31 @@
{
"user_info_list": [
{
"subscribe": 1,
"openid": "otvxTs4dckWG7imySrJd6jSi0CWE",
"nickname": "iWithery",
"sex": 1,
"language": "zh_CN",
"city": "揭阳",
"province": "广东",
"country": "中国",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/xbIQx1GRqdvyqkMMhEaGOX802l1CyqMJNgUzKP8MeAeHFicRDSnZH7FY4XB7p8XHXIf6uJA2SCunTPicGKezDC4saKISzRj3nz/0",
"subscribe_time": 1434093047,
"unionid": "oR5GjjgEhCMJFyzaVZdrxZ2zRRF4",
"remark": "",
"groupid": 0,
"tagid_list": [ 128, 2 ],
"subscribe_scene": "ADD_SCENE_QR_CODE",
"qr_scene": 98765,
"qr_scene_str": ""
},
{
"subscribe": 0,
"openid": "otvxTs_JZ6SEiP0imdhpi50fuSZg"
}
]
}

View File

@@ -0,0 +1,19 @@
{
"subscribe": 1,
"openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
"nickname": "Band",
"sex": 1,
"language": "zh_CN",
"city": "广州",
"province": "广东",
"country": "中国",
"headimgurl": "http://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"subscribe_time": 1382694957,
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL",
"remark": "",
"groupid": 0,
"tagid_list": [ 128, 2 ],
"subscribe_scene": "ADD_SCENE_QR_CODE",
"qr_scene": 98765,
"qr_scene_str": ""
}

View File

@@ -0,0 +1,4 @@
{
"openid": "oDF3iY9ffA-hqb2vVvbr7qxf6A0Q",
"remark": "pangzi"
}

View File

@@ -0,0 +1,4 @@
{
"errcode": 0,
"errmsg": "ok"
}

View File

@@ -0,0 +1,8 @@
{
"total": 2,
"count": 2,
"data": {
"openid": [ "OPENID1", "OPENID2" ]
},
"next_openid": "NEXT_OPENID"
}

View File

@@ -0,0 +1,4 @@
{
"errcode": 0,
"errmsg": "ok"
}

View File

@@ -0,0 +1,5 @@
{
"openid": "OPENID",
"unionid": "UNIONID",
"session_key": "SESSION_KEY"
}

View File

@@ -0,0 +1,7 @@
{
"access_token": "ACCESS_TOKEN",
"expires_in": 7200,
"refresh_token": "REFRESH_TOKEN",
"openid": "OPENID",
"scope": "SCOPE"
}

View File

@@ -0,0 +1,7 @@
{
"access_token": "ACCESS_TOKEN",
"expires_in": 7200,
"refresh_token": "REFRESH_TOKEN",
"openid": "OPENID",
"scope": "SCOPE"
}

View File

@@ -0,0 +1,11 @@
{
"openid": "OPENID",
"nickname": "NICKNAME",
"sex": 1,
"province": "PROVINCE",
"city": "CITY",
"country": "COUNTRY",
"headimgurl": "https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege": [ "PRIVILEGE1", "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

View File

@@ -0,0 +1,32 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove=".gitignore" />
<Content Include="appsettings.json" />
<Content Include="appsettings.local.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="ModelSamples/**/*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\SKIT.FlurlHttpClient.Wechat.Api\SKIT.FlurlHttpClient.Wechat.Api.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,14 @@
using System;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
class TestClients
{
static TestClients()
{
Instance = new WechatApiClient(TestConfigs.WechatAppId, TestConfigs.WechatAppSecret);
}
public static readonly WechatApiClient Instance;
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.IO;
using System.Text.Json;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
class TestConfigs
{
static TestConfigs()
{
// NOTICE: 请在项目根目录下建立 appsettings.local.json按照 appsettings.json 的格式填入测试参数。
// WARN: 敏感信息请不要提交到 git
using var stream = File.OpenRead("appsettings.local.json");
using var json = JsonDocument.Parse(stream);
var config = json.RootElement.GetProperty("WechatConfig");
WechatAppId = config.GetProperty("AppId").GetString();
WechatAppSecret = config.GetProperty("AppSecret").GetString();
WechatAccessToken = config.GetProperty("AccessToken").GetString();
WechatOpenId = config.GetProperty("OpenId").GetString();
}
public static readonly string WechatAppId;
public static readonly string WechatAppSecret;
public static readonly string WechatAccessToken;
public static readonly string WechatOpenId;
}
}

View File

@@ -0,0 +1,292 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class WechatApiDefinitionTests
{
private static readonly Assembly _assembly = Assembly.Load("SKIT.FlurlHttpClient.Wechat.Api");
[Fact(DisplayName = "验证模型定义")]
public void ModelDefinitionsTest()
{
static void SetPropertiesValueRecursively(object obj)
{
var lstProperty = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var tProperty in lstProperty)
{
if (tProperty.SetMethod == null || !tProperty.SetMethod.IsPublic)
continue;
if (tProperty.PropertyType.IsPrimitive)
{
// noop
}
else if (tProperty.PropertyType.IsArray)
{
Type tEl = tProperty.PropertyType.Assembly.GetType(tProperty.PropertyType.FullName.Replace("[]", string.Empty));
object propEl = (tEl == typeof(string)) ? string.Empty : Activator.CreateInstance(tEl);
propEl = Convert.ChangeType(propEl, tEl);
SetPropertiesValueRecursively(propEl);
Array prop = Array.CreateInstance(tEl, 1);
prop.SetValue(propEl, 0);
tProperty.SetValue(obj, prop);
}
else if (tProperty.PropertyType == typeof(string))
{
tProperty.SetValue(obj, string.Empty);
}
else if (tProperty.PropertyType.Namespace == "System" &&
tProperty.PropertyType.Name.StartsWith("Nullable"))
{
// noop
}
else if (tProperty.PropertyType.Namespace == "System.Collections.Generic" &&
(tProperty.PropertyType.Name.StartsWith("IDictionary") || tProperty.PropertyType.Name.StartsWith("Dictionary")))
{
// noop
}
else if (tProperty.PropertyType.Namespace == "System.Collections.Generic" &&
(tProperty.PropertyType.Name.StartsWith("IList") || tProperty.PropertyType.Name.StartsWith("List")))
{
Type tGeneric = tProperty.PropertyType.GetGenericArguments().Single();
object propEl = (tGeneric == typeof(string)) ? string.Empty : Activator.CreateInstance(tGeneric);
propEl = Convert.ChangeType(propEl, tGeneric);
SetPropertiesValueRecursively(propEl);
Type tList = typeof(List<>).MakeGenericType(new Type[] { tGeneric });
object prop = Activator.CreateInstance(tList);
tList.GetMethod("Add").Invoke(prop, new[] { propEl });
tProperty.SetValue(obj, prop);
}
else
{
object prop = Activator.CreateInstance(tProperty.PropertyType);
SetPropertiesValueRecursively(prop);
tProperty.SetValue(obj, prop);
}
}
};
var lstModel = _assembly.GetTypes()
.Where(e =>
e.Namespace != null &&
e.Namespace.Equals(_assembly.GetName().Name + "Models") &&
e.IsClass &&
!e.IsAbstract &&
!e.IsInterface &&
!e.IsNested
)
.ToList();
var exceptions = new List<Type>();
foreach (Type tModel in lstModel)
{
// 模型命名结尾必为 Request 或 Response
if (!tModel.Name.EndsWith("Request") && !tModel.Name.EndsWith("Response"))
{
exceptions.Add(tModel);
continue;
}
// Request 必继承自 WechatApiRequest、且有同名 Response
if (tModel.Name.EndsWith("Request"))
{
if (!typeof(WechatApiRequest).IsAssignableFrom(tModel))
{
exceptions.Add(tModel);
continue;
}
if (!lstModel.Any(e => e.Name == $"{tModel.Name.Substring(0, tModel.Name.Length - "Request".Length)}Response"))
{
exceptions.Add(tModel);
continue;
}
}
// Request 必继承自 WechatApiResponse、且有同名 Request
if (tModel.Name.EndsWith("Response"))
{
if (!typeof(WechatApiResponse).IsAssignableFrom(tModel))
{
exceptions.Add(tModel);
continue;
}
if (!lstModel.Any(e => e.Name == $"{tModel.Name.Substring(0, tModel.Name.Length - "Response".Length)}Request"))
{
exceptions.Add(tModel);
continue;
}
}
// 递归构造模型,并尝试 JSON 序列化以检测是否有序列化问题
try
{
object instance = _assembly.CreateInstance(tModel.Namespace + "." + tModel.Name);
SetPropertiesValueRecursively(instance);
new FlurlNewtonsoftJsonSerializer().Serialize(instance);
new FlurlSystemTextJsonSerializer().Serialize(instance);
}
catch (Exception ex)
{
throw new Exception($"Serialize `{tModel.Name}` failed.", ex);
}
}
Assert.Empty(exceptions);
}
[Fact(DisplayName = "验证接口定义")]
public void InterfaceDefinitionsTest()
{
var lstInterface = _assembly.GetTypes()
.Where(e =>
e.Namespace != null &&
e.Namespace.Equals(_assembly.GetName().Name) &&
e.Name.StartsWith("WechatApiClientExecute") &&
e.Name.EndsWith("Extensions")
)
.ToList();
var exceptions = new List<MethodInfo>();
foreach (Type tInterface in lstInterface)
{
var lstMethod = tInterface.GetMethods()
.Where(e =>
e.IsPublic &&
e.IsStatic &&
e.GetParameters().FirstOrDefault().ParameterType == typeof(WechatApiClient)
)
.ToList();
foreach (MethodInfo tMethod in lstMethod)
{
var lstParam = tMethod.GetParameters();
// 参数签名必为 this client + request + cancelToken
if (lstParam.Length != 3)
{
exceptions.Add(tMethod);
continue;
}
// 第二个参数必为 WechatApiRequest 子类
if (!typeof(WechatApiRequest).IsAssignableFrom(lstParam[1].ParameterType))
{
exceptions.Add(tMethod);
continue;
}
// 方法名与第二个参数、返回值均有相同命名
string func = tMethod.Name;
string para = lstParam[1].ParameterType.Name;
string retv = tMethod.ReturnType.GenericTypeArguments.FirstOrDefault()?.Name;
if (para == null || !para.EndsWith("Request"))
{
exceptions.Add(tMethod);
continue;
}
else if (retv == null || !retv.EndsWith("Response"))
{
exceptions.Add(tMethod);
continue;
}
else if (!string.Equals(func, $"Execute{para.Substring(0, para.Length - "Request".Length)}Async"))
{
exceptions.Add(tMethod);
continue;
}
else if (!string.Equals(func, $"Execute{retv.Substring(0, retv.Length - "Response".Length)}Async"))
{
exceptions.Add(tMethod);
continue;
}
}
}
Assert.Empty(exceptions);
}
[Fact(DisplayName = "验证字段定义")]
public void FieldDefinitionsTest()
{
static string[] GetFiles(string path)
{
var results = new List<string>();
string[] dirs = Directory.GetDirectories(path);
string[] files = Directory.GetFiles(path);
results.AddRange(files);
foreach (string dir in dirs)
{
results.AddRange(GetFiles(dir));
}
return results.ToArray();
}
string workdir = Path.Combine(Environment.CurrentDirectory, "ModelSamples");
Assert.True(Directory.Exists(workdir));
var lstFile = GetFiles(workdir)
.Where(e => string.Equals(Path.GetExtension(e), ".json", StringComparison.InvariantCultureIgnoreCase))
.ToList();
Assert.NotEmpty(lstFile);
var exceptions = new List<string>();
foreach (string file in lstFile)
{
string json = File.ReadAllText(file);
string name = Path.GetFileNameWithoutExtension(file);
Type type = _assembly.GetType($"{_assembly.GetName().Name}.Models.{name}");
if (type == null)
{
exceptions.Add(name);
continue;
}
try
{
var settings = FlurlNewtonsoftJsonSerializer.GetDefaultSerializerSettings();
settings.CheckAdditionalContent = true;
settings.MissingMemberHandling = Newtonsoft.Json.MissingMemberHandling.Error;
new FlurlNewtonsoftJsonSerializer(settings).Deserialize(json, type);
new FlurlSystemTextJsonSerializer().Deserialize(json, type);
}
catch (Exception ex)
{
exceptions.Add(name);
if (ex is Newtonsoft.Json.JsonException)
throw new Exception($"Deserialize `{name}` by Newtonsoft.Json failed.", ex);
else if (ex is System.Text.Json.JsonException)
throw new Exception($"Deserialize `{name}` by System.Text.Json failed.", ex);
else
throw new Exception($"Deserialize `{name}` failed.", ex);
}
}
Assert.Empty(exceptions);
}
}
}

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class WechatApiExecuteCgibinWithAccessTokenTests
{
[Fact(DisplayName = "[GET] /cgi-bin/ticket/getticket")]
public async Task CgibinTicketGetTicketTest()
{
var request = new Models.CgibinTicketGetTicketRequest()
{
AccessToken = TestConfigs.WechatAccessToken
};
var response = await TestClients.Instance.ExecuteCgibinTicketGetTicketAsync(request);
Assert.NotNull(response.Ticket);
}
[Fact(DisplayName = "[GET] /cgi-bin/getcallbackip")]
public async Task CgibinGetCallbackIpTest()
{
var request = new Models.CgibinGetCallbackIpRequest()
{
AccessToken = TestConfigs.WechatAccessToken
};
var response = await TestClients.Instance.ExecuteCgibinGetCallbackIpAsync(request);
Assert.NotEmpty(response.IPList);
}
[Fact(DisplayName = "[GET] /cgi-bin/get_api_domain_ip")]
public async Task CgibinGetApiDomainIpTest()
{
var request = new Models.CgibinGetApiDomainIpRequest()
{
AccessToken = TestConfigs.WechatAccessToken
};
var response = await TestClients.Instance.ExecuteCgibinGetApiDomainIpAsync(request);
Assert.NotEmpty(response.IPList);
}
[Fact(DisplayName = "[GET] /cgi-bin/user/info")]
public async Task CgibinUserInfoTest()
{
var request = new Models.CgibinUserInfoRequest()
{
AccessToken = TestConfigs.WechatAccessToken,
OpenId = TestConfigs.WechatOpenId
};
var response = await TestClients.Instance.ExecuteCgibinUserInfoAsync(request);
Assert.NotEmpty(response.OpenId);
Assert.NotEmpty(response.Nickname);
Assert.True(response.Subscribe == 1);
}
[Fact(DisplayName = "[POST] /cgi-bin/user/info/batchget")]
public async Task CgibinUserInfoBatchGetTest()
{
var request = new Models.CgibinUserInfoBatchGetRequest()
{
AccessToken = TestConfigs.WechatAccessToken,
UserList = new Models.CgibinUserInfoBatchGetRequest.Types.User[]
{
new Models.CgibinUserInfoBatchGetRequest.Types.User() { OpenId = TestConfigs.WechatOpenId }
}
};
var response = await TestClients.Instance.ExecuteCgibinUserInfoBatchGetAsync(request);
Assert.NotEmpty(response.UserList);
Assert.NotEmpty(response.UserList.First().OpenId);
Assert.NotEmpty(response.UserList.First().Nickname);
Assert.True(response.UserList.First().Subscribe == 1);
}
[Fact(DisplayName = "[POST] /cgi-bin/user/info/updateremark")]
public async Task CgibinUserInfoUpdateRemarkTest()
{
var request = new Models.CgibinUserInfoUpdateRemarkRequest()
{
AccessToken = TestConfigs.WechatAccessToken,
OpenId = TestConfigs.WechatOpenId,
Remark = "FAKE_REMARK"
};
var response = await TestClients.Instance.ExecuteCgibinUserInfoUpdateRemarkAsync(request);
Assert.Equal(0, response.ErrorCode);
}
[Fact(DisplayName = "[GET] /cgi-bin/user")]
public async Task CgibinUserTest()
{
var request = new Models.CgibinUserRequest()
{
AccessToken = TestConfigs.WechatAccessToken
};
var response = await TestClients.Instance.ExecuteCgibinUserAsync(request);
Assert.NotEmpty(response.Data.OpenIdList);
Assert.True(response.Total > 0);
Assert.True(response.Count > 0);
}
[Fact(DisplayName = "[POST] /cgi-bin/tags/create")]
public async Task CgibinTagsCreateTest()
{
var request = new Models.CgibinTagsCreateRequest()
{
AccessToken = TestConfigs.WechatAccessToken,
Tag = new Models.CgibinTagsCreateRequest.Types.Tag()
{
Name = "FAKE_TAGNAME"
}
};
var response = await TestClients.Instance.ExecuteCgibinTagsCreateAsync(request);
Assert.True(response.Tag.Id > 0);
Assert.Equal(request.Tag.Name, response.Tag.Name);
}
[Fact(DisplayName = "[POST] /cgi-bin/tags/get")]
public async Task CgibinTagsGetTest()
{
var request = new Models.CgibinTagsGetRequest()
{
AccessToken = TestConfigs.WechatAccessToken
};
var response = await TestClients.Instance.ExecuteCgibinTagsGetAsync(request);
Assert.NotEmpty(response.Tags);
Assert.True(response.Tags.First().Id > 0);
Assert.NotNull(response.Tags.First().Name);
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class WechatApiExecuteCgibinWithAppSecretTests
{
[Fact(DisplayName = "[GET] /sns/cgi-bin/token")]
public async Task CgibinTokenTest()
{
var request = new Models.CgibinTokenRequest();
var response = await TestClients.Instance.ExecuteCgibinTokenAsync(request);
Assert.NotNull(response.AccessToken);
}
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class WechatApiExecuteSnsWithAccessTokenTests
{
[Fact(DisplayName = "[GET] /sns/userinfo")]
public async Task SnsUserInfoTest()
{
var request = new Models.SnsUserInfoRequest()
{
AccessToken = "FAKE_SNSACCESSTOKEN",
OpenId = TestConfigs.WechatOpenId
};
var response = await TestClients.Instance.ExecuteSnsUserInfoAsync(request);
Assert.NotNull(response.OpenId);
Assert.NotNull(response.Nickname);
}
[Fact(DisplayName = "[GET] /sns/auth")]
public async Task SnsAuthTest()
{
var request = new Models.SnsAuthRequest()
{
AccessToken = "FAKE_SNSACCESSTOKEN",
OpenId = TestConfigs.WechatOpenId
};
var response = await TestClients.Instance.ExecuteSnsAuthAsync(request);
Assert.Equal(0, response.ErrorCode);
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Api.UnitTests
{
public class WechatApiExecuteSnsWithAppSecretTests
{
[Fact(DisplayName = "[GET] /sns/oauth2/access_token")]
public async Task SnsOAuth2AccessTokenTest()
{
var request = new Models.SnsOAuth2AccessTokenRequest()
{
Code = "FAKE_CODE"
};
var response = await TestClients.Instance.ExecuteSnsOAuth2AccessTokenAsync(request);
Assert.NotNull(response.AccessToken);
Assert.NotNull(response.RefreshToken);
Assert.NotNull(response.OpenId);
}
[Fact(DisplayName = "[GET] /sns/oauth2/refresh_token")]
public async Task SnsOAuth2RefreshTokenTest()
{
var request = new Models.SnsOAuth2RefreshTokenRequest()
{
RefreshToken = "FAKE_REFRESHTOKEN"
};
var response = await TestClients.Instance.ExecuteSnsOAuth2RefreshTokenAsync(request);
Assert.NotNull(response.AccessToken);
Assert.NotNull(response.RefreshToken);
}
[Fact(DisplayName = "[GET] /sns/jscode2session")]
public async Task SnsJsCode2SessionTest()
{
var request = new Models.SnsJsCode2SessionRequest()
{
JsCode = "FAKE_CODE"
};
var response = await TestClients.Instance.ExecuteSnsJsCode2SessionAsync(request);
Assert.NotNull(response.OpenId);
Assert.NotNull(response.SessionKey);
}
}
}

View File

@@ -0,0 +1,8 @@
{
"WechatConfig": {
"AppId": "请在此填写用于测试的微信 AppId",
"AppSecret": "请在此填写用于测试的微信 AppSecret",
"AccessToken": "请在此填写用于测试的微信 AccessToken",
"OpenId": "请在此填写用于测试的微信用户唯一标识"
}
}