Compare commits
6 Commits
3401856281
...
ea382b1aa1
| Author | SHA1 | Date |
|---|---|---|
|
|
ea382b1aa1 | |
|
|
33b238b156 | |
|
|
9dbbcc98dd | |
|
|
e3a3201a06 | |
|
|
82aede3b9d | |
|
|
e55edf4c63 |
|
|
@ -115,11 +115,11 @@
|
|||
"DockerConfig": {
|
||||
"Prot": "5192:5192",
|
||||
"AspNetCoreEnv": "",
|
||||
"LastEnvName": "29dev",
|
||||
"LastEnvName": "marking001",
|
||||
"RemoveDaysFromPublished": "10",
|
||||
"WorkDir": "",
|
||||
"Volume": "",
|
||||
"Other": "--name wgshare-api -e ASPNETCORE_ENVIRONMENT=Development -e TZ=Asia/Shanghai",
|
||||
"Other": "--name wgshare-api -e ASPNETCORE_ENVIRONMENT=Production -e TZ=Asia/Shanghai",
|
||||
"EnvPairList": [
|
||||
{
|
||||
"EnvName": "29dev",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using AgoraIO.Media;
|
||||
using AgoraIO.Rtm;
|
||||
using Azure;
|
||||
using Mapster;
|
||||
using Masuit.Tools;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
@ -8,10 +9,12 @@ using MiniExcelLibs.Attributes;
|
|||
using MiniExcelLibs.OpenXml;
|
||||
using SqlSugar;
|
||||
using System.IO;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.RegularExpressions;
|
||||
using WGShare.API.Controllers.Basic;
|
||||
using WGShare.API.Helpers;
|
||||
using WGShare.Domain.Constant;
|
||||
using WGShare.Domain.DTOs.MiniProgram;
|
||||
using WGShare.Domain.DTOs.Room;
|
||||
using WGShare.Domain.Entities;
|
||||
using WGShare.Domain.Enums;
|
||||
|
|
@ -35,6 +38,7 @@ namespace WGShare.API.Controllers.Frontend
|
|||
private readonly AgoraHelper _agoraHelper;
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
private readonly OssHelper _ossHelper;
|
||||
private readonly MiniProgramHelper _miniProgramHelper;
|
||||
|
||||
public HomeController(
|
||||
ISqlSugarClient sqlSugar,
|
||||
|
|
@ -42,7 +46,8 @@ namespace WGShare.API.Controllers.Frontend
|
|||
IHttpClientFactory httpClientFactory,
|
||||
AgoraHelper agoraHelper,
|
||||
ILogger<HomeController> logger,
|
||||
OssHelper ossHelper)
|
||||
OssHelper ossHelper,
|
||||
MiniProgramHelper miniProgramHelper)
|
||||
{
|
||||
_sqlSugar = sqlSugar;
|
||||
this._configuration = configuration;
|
||||
|
|
@ -50,6 +55,7 @@ namespace WGShare.API.Controllers.Frontend
|
|||
this._agoraHelper = agoraHelper;
|
||||
this._logger = logger;
|
||||
this._ossHelper = ossHelper;
|
||||
this._miniProgramHelper = miniProgramHelper;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -83,7 +89,7 @@ namespace WGShare.API.Controllers.Frontend
|
|||
//}
|
||||
}
|
||||
|
||||
return PagedResult<RoomOutputDTO>.Create(result, total.Value);
|
||||
return PagedResult<RoomOutputDTO>.Create(result, total.Value, dto.PageSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -291,5 +297,60 @@ namespace WGShare.API.Controllers.Frontend
|
|||
_ossHelper.UploadWithExpireTime(fileName, stream, 10);
|
||||
return _ossHelper.GetAccessFileUrl(fileName, 5);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取房间二维码(缓存10mins)
|
||||
/// </summary>
|
||||
/// <param name="roomNum"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet("r-qrcode")]
|
||||
public async Task<string> GetMiniProgramQrCode([FromQuery] string roomNum, [FromQuery] string env = "release")
|
||||
{
|
||||
var img = RedisHelper.Instance.Get(RedisKeyConstant.WxMiniProgram.GetRoomQrCode(roomNum, env));
|
||||
if (!string.IsNullOrWhiteSpace(img))
|
||||
{
|
||||
return img;
|
||||
}
|
||||
|
||||
var httpClient = _httpClientFactory.CreateClient();
|
||||
var accessToken = await _miniProgramHelper.GetAccessToken();
|
||||
|
||||
var result = await httpClient.PostAsync($@"https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token={accessToken}", new StringContent(new wxacodeunlimitBody
|
||||
{
|
||||
page = "pages/form/index",
|
||||
scene = ("r=" + roomNum),
|
||||
check_path = true,
|
||||
env_version = env,
|
||||
width = 280
|
||||
}.ToJsonString()));
|
||||
if (result == null || !result.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.LogError($@"二维码生成失败,statusCode:{(int)result.StatusCode},content:{await result.Content.ReadAsStringAsync()}");
|
||||
throw Oops.Oh("二维码生成失败!");
|
||||
}
|
||||
var contentType = result.Content.Headers.ContentType?.MediaType;
|
||||
// 如果是图片类型
|
||||
if (contentType != null && contentType.StartsWith("image/"))
|
||||
{
|
||||
// 处理图片数据
|
||||
var imageArr = await result.Content.ReadAsByteArrayAsync();
|
||||
var imgStr = Convert.ToBase64String(imageArr);
|
||||
|
||||
imgStr = QrCodeOptimizerHelper.CompressImage(imgStr, 50);
|
||||
RedisHelper.Instance.Set(RedisKeyConstant.WxMiniProgram.GetRoomQrCode(roomNum, env), imgStr, TimeSpan.FromDays(1));
|
||||
return imgStr;
|
||||
}
|
||||
else if (contentType != null && contentType.Contains("json"))
|
||||
{
|
||||
var apiResult = await result.Content.ReadFromJsonAsync<WxMiniProgramBaseApiResult>();
|
||||
if (apiResult != null)
|
||||
{
|
||||
_logger.LogError($"二维码生成失败,errorCode:{apiResult.errorcode},errmsg:{apiResult.errmsg}");
|
||||
throw Oops.Oh("二维码生成失败");
|
||||
}
|
||||
}
|
||||
_logger.LogError("返回 ContentType 未命中");
|
||||
throw Oops.Oh("二维码生成失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,6 +95,8 @@ namespace WGShare.API.Controllers.Frontend
|
|||
}
|
||||
|
||||
user.IsRoomManager = false;
|
||||
user.EnableCamera = false;
|
||||
user.EnableMicr = false;
|
||||
RedisHelper.Instance.HSet(RedisKeyConstant.SessionManage.GetChannelUserKey(TenantId, inputDTO.RoomNum), inputDTO.UserId, user);
|
||||
|
||||
// 判断是否显示用户
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using System.Text.RegularExpressions;
|
|||
using WGShare.API.Controllers.Basic;
|
||||
using WGShare.API.Helpers;
|
||||
using WGShare.Domain.DTOs.Login;
|
||||
using WGShare.Domain.DTOs.MiniProgram;
|
||||
using WGShare.Domain.DTOs.User;
|
||||
using WGShare.Domain.Entities;
|
||||
using WGShare.Domain.Enums;
|
||||
|
|
@ -26,10 +27,19 @@ namespace WGShare.API.Controllers
|
|||
public class PublicController : BasicController
|
||||
{
|
||||
private readonly ISqlSugarClient _sqlSugar;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly Microsoft.Extensions.Configuration.IConfiguration _configuration;
|
||||
private readonly ILogger<PublicController> _logger;
|
||||
|
||||
public PublicController(ISqlSugarClient sqlSugar)
|
||||
public PublicController(ISqlSugarClient sqlSugar,
|
||||
IHttpClientFactory httpClientFactory,
|
||||
Microsoft.Extensions.Configuration.IConfiguration configuration,
|
||||
ILogger<PublicController> logger)
|
||||
{
|
||||
_sqlSugar = sqlSugar;
|
||||
this._httpClientFactory = httpClientFactory;
|
||||
this._configuration = configuration;
|
||||
this._logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -69,5 +79,26 @@ namespace WGShare.API.Controllers
|
|||
else
|
||||
return value.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取小程序openid
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("mini-openid"), AllowAnonymous]
|
||||
public async Task<string> GetOpenId(string js_code)
|
||||
{
|
||||
var queryString = $@"appid={_configuration["miniProgram:appId"]}&secret={_configuration["miniProgram:appSecret"]}&js_code={js_code}&grant_type=authorization_code";
|
||||
|
||||
var httpclient = _httpClientFactory.CreateClient();
|
||||
var result = await httpclient.GetFromJsonAsync<JsCode2SessionApiResult>($@"https://api.weixin.qq.com/sns/jscode2session?{queryString}");
|
||||
if (result == null || result.errorcode != 0 || string.IsNullOrWhiteSpace(result.openid))
|
||||
{
|
||||
_logger.LogError($"获取openid失败,错误码:{result?.errorcode},错误信息:{result?.errmsg}");
|
||||
|
||||
throw Oops.Oh("小程序登录失败");
|
||||
}
|
||||
|
||||
return result.openid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
using WGShare.Domain.Constant;
|
||||
using WGShare.Domain.DTOs.MiniProgram;
|
||||
using WGShare.Domain.FriendlyException;
|
||||
|
||||
namespace WGShare.API.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// 小程序帮助类
|
||||
/// </summary>
|
||||
public class MiniProgramHelper
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public MiniProgramHelper(IConfiguration configuration)
|
||||
{
|
||||
this._configuration = configuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取access_token
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<string> GetAccessToken()
|
||||
{
|
||||
var accessToken = RedisHelper.Instance.Get<string>(RedisKeyConstant.WxMiniProgram.AccessTokenKey);
|
||||
if (!string.IsNullOrWhiteSpace(accessToken) )
|
||||
{
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
var appId = _configuration["miniProgram:appId"];
|
||||
var secret = _configuration["miniProgram:appSecret"];
|
||||
|
||||
using var httpClient = new HttpClient();
|
||||
|
||||
var result = await httpClient.GetAsync($@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={secret}");
|
||||
if (result == null || !result.IsSuccessStatusCode)
|
||||
{
|
||||
Console.WriteLine($@"微信服务器授权失败,{result.StatusCode},{await result.Content.ReadAsStringAsync()}");
|
||||
throw Oops.Oh("微信服务器授权失败");
|
||||
}
|
||||
var apiResult = await result.Content.ReadFromJsonAsync<AccessTokenApiResult>();
|
||||
if (apiResult == null)
|
||||
{
|
||||
Console.WriteLine($@"微信服务器授权失败,接口返回数据解析失败");
|
||||
throw Oops.Oh("微信服务器授权失败");
|
||||
}
|
||||
if (apiResult.errorcode != 0)
|
||||
{
|
||||
Console.WriteLine($@"微信服务器授权失败,errorCode:{apiResult.errorcode},errmsg:{apiResult.errmsg}");
|
||||
throw Oops.Oh("微信服务器授权失败");
|
||||
}
|
||||
|
||||
RedisHelper.Instance.Set(RedisKeyConstant.WxMiniProgram.AccessTokenKey, apiResult.access_token, TimeSpan.FromSeconds(apiResult.expires_in - 60));
|
||||
return apiResult.access_token;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.Formats.Jpeg;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace WGShare.API.Helpers
|
||||
{
|
||||
public class QrCodeOptimizerHelper
|
||||
{
|
||||
public static string CompressImage(string base64String, int quality)
|
||||
{
|
||||
// 将 Base64 字符串转换为字节数组
|
||||
byte[] imageBytes = Convert.FromBase64String(base64String);
|
||||
|
||||
// 使用 ImageSharp 加载图像
|
||||
using (Image image = Image.Load(imageBytes))
|
||||
{
|
||||
// 设置压缩参数
|
||||
JpegEncoder jpegEncoder = new JpegEncoder
|
||||
{
|
||||
Quality = quality
|
||||
};
|
||||
|
||||
// 创建一个新的内存流来保存压缩后的图像
|
||||
using (MemoryStream compressedMs = new MemoryStream())
|
||||
{
|
||||
image.Save(compressedMs, jpegEncoder);
|
||||
|
||||
// 将压缩后的图像转换回 Base64 字符串
|
||||
byte[] compressedImageBytes = compressedMs.ToArray();
|
||||
return Convert.ToBase64String(compressedImageBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -65,6 +65,7 @@ namespace WGShare.API
|
|||
builder.Services.ConfigureHangfire();
|
||||
builder.Services.AddSingleton(new JwtHelper(configuration));
|
||||
builder.Services.AddSingleton(new AgoraHelper(configuration));
|
||||
builder.Services.AddSingleton(new MiniProgramHelper(configuration));
|
||||
builder.Services.AddSingleton(new OssHelper(configuration));
|
||||
builder.Services.AddHostedService<AgoraCallbackComsuerService>();
|
||||
builder.Services.AddAuth(configuration["Jwt:Issuer"],
|
||||
|
|
|
|||
|
|
@ -144,6 +144,13 @@
|
|||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:WGShare.API.Controllers.Frontend.HomeController.GetMiniProgramQrCode(System.String,System.String)">
|
||||
<summary>
|
||||
获取房间二维码(缓存10mins)
|
||||
</summary>
|
||||
<param name="roomNum"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:WGShare.API.Controllers.Frontend.RoomController">
|
||||
<summary>
|
||||
会议室接口
|
||||
|
|
@ -402,6 +409,12 @@
|
|||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:WGShare.API.Controllers.PublicController.GetOpenId(System.String)">
|
||||
<summary>
|
||||
获取小程序openid
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="F:WGShare.API.Helpers.AgoraHelper.Constant.REDIS_CHANNEL_USERCOUNT">
|
||||
<summary>
|
||||
Redis 键,hash ,每个频道用户数量
|
||||
|
|
@ -465,6 +478,17 @@
|
|||
<returns></returns>
|
||||
<exception cref="T:System.ArgumentException"></exception>
|
||||
</member>
|
||||
<member name="T:WGShare.API.Helpers.MiniProgramHelper">
|
||||
<summary>
|
||||
小程序帮助类
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:WGShare.API.Helpers.MiniProgramHelper.GetAccessToken">
|
||||
<summary>
|
||||
获取access_token
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:WGShare.API.Helpers.OssHelper.GetUploadUrl(System.String,System.String,System.UInt32)">
|
||||
<summary>
|
||||
获取上传url
|
||||
|
|
|
|||
|
|
@ -38,5 +38,9 @@
|
|||
"Endpoint": "oss-cn-chengdu.aliyuncs.com",
|
||||
"Host": "https://wgshare.oss-cn-chengdu.aliyuncs.com/",
|
||||
"BucketName": "wgshare"
|
||||
},
|
||||
"miniProgram": {
|
||||
"appId": "wx99885b1c181cda72",
|
||||
"appSecret": "edd9cdb04c3f59fe70f2a70c396e5b0d"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,5 +86,12 @@ namespace WGShare.Domain.Constant
|
|||
{
|
||||
public static string MeetingRecord => "meeting_record";
|
||||
}
|
||||
|
||||
public class WxMiniProgram
|
||||
{
|
||||
public static string AccessTokenKey => $@"wx_mini_program:accessToken";
|
||||
|
||||
public static string GetRoomQrCode(string roomNum, string env) => $@"wx_mini_program:room_qrcode:{env}:{roomNum}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WGShare.Domain.DTOs.MiniProgram
|
||||
{
|
||||
public class AccessTokenApiResult : WxMiniProgramBaseApiResult
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
public int expires_in { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WGShare.Domain.DTOs.MiniProgram
|
||||
{
|
||||
public class JsCode2SessionApiResult
|
||||
{
|
||||
public string openid { get; set; }
|
||||
public string seesionkey { get; set; }
|
||||
public string unionid { get; set; }
|
||||
public int errorcode { get; set; }
|
||||
public string errmsg { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WGShare.Domain.DTOs.MiniProgram
|
||||
{
|
||||
public class WxMiniProgramBaseApiResult
|
||||
{
|
||||
public int errorcode { get; set; }
|
||||
public string errmsg { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WGShare.Domain.DTOs.MiniProgram
|
||||
{
|
||||
public class wxacodeunlimitBody
|
||||
{
|
||||
public string scene { get; set; }
|
||||
public string page { get; set; }
|
||||
public bool check_path { get; set; }
|
||||
public string env_version { get; set; }
|
||||
public int width { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ namespace WGShare.Domain.GeneralModel
|
|||
public class PagedResult<TEntity>
|
||||
{
|
||||
public PagedResult() { }
|
||||
public PagedResult(IEnumerable<TEntity> list, int total)
|
||||
public PagedResult(IEnumerable<TEntity> list, int total, int pageSize = 10)
|
||||
{
|
||||
Total = total;
|
||||
Items = list;
|
||||
|
|
@ -20,9 +20,19 @@ namespace WGShare.Domain.GeneralModel
|
|||
public int Total { get; set; }
|
||||
public IEnumerable<TEntity> Items { get; private set; }
|
||||
|
||||
public static PagedResult<TEntity> Create(IEnumerable<TEntity> list, int total)
|
||||
private int pageSize = 10;
|
||||
|
||||
public int TotalPage
|
||||
{
|
||||
return new PagedResult<TEntity>(list, total);
|
||||
get
|
||||
{
|
||||
return (int)Math.Ceiling(Total / (double)pageSize);
|
||||
}
|
||||
}
|
||||
|
||||
public static PagedResult<TEntity> Create(IEnumerable<TEntity> list, int total, int pageSize = 10)
|
||||
{
|
||||
return new PagedResult<TEntity>(list, total, pageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue