diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinAuthExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinAuthExtensions.cs
new file mode 100644
index 00000000..af674807
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientExecuteCgibinAuthExtensions.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+using Flurl;
+using Flurl.Http;
+
+namespace SKIT.FlurlHttpClient.Wechat.Work
+{
+ public static class WechatWorkClientExecuteCgibinAuthExtensions
+ {
+ ///
+ /// 异步调用 [GET] /cgi-bin/auth/getuserinfo 接口。
+ /// REF: https://developer.work.weixin.qq.com/document/path/91023
+ /// REF: https://developer.work.weixin.qq.com/document/path/91437
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteCgibinAuthGetUserInfoAsync(this WechatWorkClient client, Models.CgibinAuthGetUserInfoRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Get, "cgi-bin", "auth", "getuserinfo")
+ .SetQueryParam("access_token", request.AccessToken)
+ .SetQueryParam("code", request.Code);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, cancellationToken: cancellationToken);
+ }
+
+ ///
+ /// 异步调用 [POST] /cgi-bin/auth/getuserdetail 接口。
+ /// REF: https://developer.work.weixin.qq.com/document/path/95833
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task ExecuteCgibinAuthGetUserDetailAsync(this WechatWorkClient client, Models.CgibinAuthGetUserDetailRequest request, CancellationToken cancellationToken = default)
+ {
+ if (client is null) throw new ArgumentNullException(nameof(client));
+ if (request is null) throw new ArgumentNullException(nameof(request));
+
+ IFlurlRequest flurlReq = client
+ .CreateRequest(request, HttpMethod.Post, "cgi-bin", "auth", "getuserdetail")
+ .SetQueryParam("access_token", request.AccessToken);
+
+ return await client.SendRequestWithJsonAsync(flurlReq, cancellationToken: cancellationToken);
+ }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientParameterExtensions.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientParameterExtensions.cs
index 216b5058..bd25062d 100644
--- a/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientParameterExtensions.cs
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Extensions/WechatWorkClientParameterExtensions.cs
@@ -1,7 +1,8 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Flurl;
+using static SKIT.FlurlHttpClient.Wechat.Work.Models.CgibinSchoolAgentGetAllowScopeResponse.Types;
namespace SKIT.FlurlHttpClient.Wechat.Work
{
@@ -77,6 +78,22 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
///
///
public static string GenerateParameterizedUrlForConnectOAuth2Authorize(this WechatWorkClient client, string redirectUrl, string scope, string? state = null)
+ {
+ return GenerateParameterizedUrlForConnectOAuth2Authorize(client, agentId: client.Credentials.AgentId.GetValueOrDefault(), redirectUrl: redirectUrl, scope: scope, state: state);
+ }
+
+ ///
+ /// 生成企业号网页授权 URL。
+ /// REF: https://developer.work.weixin.qq.com/document/path/91022
+ /// REF: https://developer.work.weixin.qq.com/document/path/91120
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string GenerateParameterizedUrlForConnectOAuth2Authorize(this WechatWorkClient client, int agentId, string redirectUrl, string scope, string? state = null)
{
return new Url("https://open.weixin.qq.com")
.AppendPathSegments("connect", "oauth2", "authorize")
@@ -85,6 +102,7 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
.SetQueryParam("response_type", "code")
.SetQueryParam("scope", scope)
.SetQueryParam("state", state)
+ .SetQueryParam("agentid", agentId)
.SetFragment("wechat_redirect")
.ToString();
}
@@ -101,11 +119,28 @@ namespace SKIT.FlurlHttpClient.Wechat.Work
///
///
public static string GenerateParameterizedUrlForSSOQrcodeConnectAuthorize(this WechatWorkClient client, string redirectUrl, string? state = null, string? language = null, string? userType = null)
+ {
+ return GenerateParameterizedUrlForSSOQrcodeConnectAuthorize(client, agentId: client.Credentials.AgentId.GetValueOrDefault(), redirectUrl: redirectUrl, state: state, language: language, userType: userType);
+ }
+
+ ///
+ /// 生成企业号扫码授权 URL。
+ /// REF: https://developer.work.weixin.qq.com/document/path/91019
+ /// REF: https://developer.work.weixin.qq.com/document/path/91124
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string GenerateParameterizedUrlForSSOQrcodeConnectAuthorize(this WechatWorkClient client, int agentId, string redirectUrl, string? state = null, string? language = null, string? userType = null)
{
return new Url("https://open.work.weixin.qq.com")
.AppendPathSegments("wwopen", "sso", "qrConnect")
.SetQueryParam("appid", client.Credentials.CorpId)
- .SetQueryParam("agentid", client.Credentials.AgentId)
+ .SetQueryParam("agentid", agentId)
.SetQueryParam("redirect_uri", redirectUrl)
.SetQueryParam("state", state)
.SetQueryParam("lang", language)
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserDetailRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserDetailRequest.cs
new file mode 100644
index 00000000..79f108fe
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserDetailRequest.cs
@@ -0,0 +1,15 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/auth/getuserdetail 接口的请求。
+ ///
+ public class CgibinAuthGetUserDetailRequest : WechatWorkRequest
+ {
+ ///
+ /// 获取或设置成员票据。
+ ///
+ [Newtonsoft.Json.JsonProperty("user_ticket")]
+ [System.Text.Json.Serialization.JsonPropertyName("user_ticket")]
+ public string UserTicket { get; set; } = string.Empty;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserDetailResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserDetailResponse.cs
new file mode 100644
index 00000000..150755b7
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserDetailResponse.cs
@@ -0,0 +1,65 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [POST] /cgi-bin/auth/getuserdetail 接口的响应。
+ ///
+ public class CgibinAuthGetUserDetailResponse : WechatWorkResponse
+ {
+ ///
+ /// 获取或设置成员 UserId。
+ ///
+ [Newtonsoft.Json.JsonProperty("userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("userid")]
+ public string UserId { get; set; } = default!;
+
+ ///
+ /// 获取或设置性别。
+ ///
+ [Newtonsoft.Json.JsonProperty("gender")]
+ [System.Text.Json.Serialization.JsonPropertyName("gender")]
+ [System.Text.Json.Serialization.JsonNumberHandling(System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString)]
+ public int Gender { get; set; }
+
+ ///
+ /// 获取或设置头像 URL。
+ ///
+ [Newtonsoft.Json.JsonProperty("avatar")]
+ [System.Text.Json.Serialization.JsonPropertyName("avatar")]
+ public string? AvatarUrl { get; set; }
+
+ ///
+ /// 获取或设置员工个人二维码 URL。
+ ///
+ [Newtonsoft.Json.JsonProperty("qr_code")]
+ [System.Text.Json.Serialization.JsonPropertyName("qr_code")]
+ public string? QrcodeUrl { get; set; }
+
+ ///
+ /// 获取或设置手机号码。
+ ///
+ [Newtonsoft.Json.JsonProperty("mobile")]
+ [System.Text.Json.Serialization.JsonPropertyName("mobile")]
+ public string? MobileNumber { get; set; }
+
+ ///
+ /// 获取或设置邮箱地址。
+ ///
+ [Newtonsoft.Json.JsonProperty("email")]
+ [System.Text.Json.Serialization.JsonPropertyName("email")]
+ public string? Email { get; set; }
+
+ ///
+ /// 获取或设置企业邮箱地址。
+ ///
+ [Newtonsoft.Json.JsonProperty("biz_mail")]
+ [System.Text.Json.Serialization.JsonPropertyName("biz_mail")]
+ public string? BusinessEmail { get; set; }
+
+ ///
+ /// 获取或设置地址。
+ ///
+ [Newtonsoft.Json.JsonProperty("address")]
+ [System.Text.Json.Serialization.JsonPropertyName("address")]
+ public string? Address { get; set; }
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserInfoRequest.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserInfoRequest.cs
new file mode 100644
index 00000000..75e96a1c
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserInfoRequest.cs
@@ -0,0 +1,15 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [GET] /cgi-bin/auth/getuserinfo 接口的请求。
+ ///
+ public class CgibinAuthGetUserInfoRequest : WechatWorkRequest
+ {
+ ///
+ /// 获取或设置成员授权码。
+ ///
+ [Newtonsoft.Json.JsonIgnore]
+ [System.Text.Json.Serialization.JsonIgnore]
+ public string Code { get; set; } = string.Empty;
+ }
+}
diff --git a/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserInfoResponse.cs b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserInfoResponse.cs
new file mode 100644
index 00000000..f93f45da
--- /dev/null
+++ b/src/SKIT.FlurlHttpClient.Wechat.Work/Models/CgibinAuth/CgibinAuthGetUserInfoResponse.cs
@@ -0,0 +1,36 @@
+namespace SKIT.FlurlHttpClient.Wechat.Work.Models
+{
+ ///
+ /// 表示 [GET] /cgi-bin/auth/getuserinfo 接口的响应。
+ ///
+ public class CgibinAuthGetUserInfoResponse : WechatWorkResponse
+ {
+ ///
+ /// 获取或设置成员 UserId。
+ ///
+ [Newtonsoft.Json.JsonProperty("userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("userid")]
+ public string? UserId { get; set; }
+
+ ///
+ /// 获取或设置成员票据。
+ ///
+ [Newtonsoft.Json.JsonProperty("user_ticket")]
+ [System.Text.Json.Serialization.JsonPropertyName("user_ticket")]
+ public string? UserTicket { get; set; }
+
+ ///
+ /// 获取或设置非企业成员的标识。
+ ///
+ [Newtonsoft.Json.JsonProperty("openid")]
+ [System.Text.Json.Serialization.JsonPropertyName("openid")]
+ public string? OpenId { get; set; }
+
+ ///
+ /// 获取或设置外部联系人 ID。
+ ///
+ [Newtonsoft.Json.JsonProperty("external_userid")]
+ [System.Text.Json.Serialization.JsonPropertyName("external_userid")]
+ public string? ExternalUserId { get; set; }
+ }
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinAuth/CgibinAuthGetUserDetailResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinAuth/CgibinAuthGetUserDetailResponse.json
new file mode 100644
index 00000000..3d34d553
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinAuth/CgibinAuthGetUserDetailResponse.json
@@ -0,0 +1,12 @@
+{
+ "errcode": 0,
+ "errmsg": "ok",
+ "userid": "lisi",
+ "gender": "1",
+ "avatar": "http://shp.qpic.cn/bizmp/xxxxxxxxxxx/0",
+ "qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=vcfc13b01dfs78e981c",
+ "mobile": "13800000000",
+ "email": "zhangsan@gzdev.com",
+ "biz_mail": "zhangsan@qyycs2.wecom.work",
+ "address": "广州市海珠区新港中路"
+}
diff --git a/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinAuth/CgibinAuthGetUserInfoResponse.json b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinAuth/CgibinAuthGetUserInfoResponse.json
new file mode 100644
index 00000000..d9641d56
--- /dev/null
+++ b/test/SKIT.FlurlHttpClient.Wechat.Work.UnitTests/ModelSamples/CgibinAuth/CgibinAuthGetUserInfoResponse.json
@@ -0,0 +1,8 @@
+{
+ "errcode": 0,
+ "errmsg": "ok",
+ "userid": "USERID",
+ "user_ticket": "USER_TICKET",
+ "openid": "OPENID",
+ "external_userid": "EXTERNAL_USERID"
+}