diff --git a/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj b/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj
index 471bff9..14d5c05 100644
--- a/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj
+++ b/src/0-core/HuanMeng.DotNetCore/HuanMeng.DotNetCore.csproj
@@ -16,6 +16,7 @@
+
diff --git a/src/0-core/HuanMeng.DotNetCore/WeChat/MiniProgram.cs b/src/0-core/HuanMeng.DotNetCore/WeChat/MiniProgram.cs
new file mode 100644
index 0000000..a3b5328
--- /dev/null
+++ b/src/0-core/HuanMeng.DotNetCore/WeChat/MiniProgram.cs
@@ -0,0 +1,148 @@
+using Newtonsoft.Json;
+
+using StackExchange.Redis;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HuanMeng.DotNetCore.WeChat
+{
+ ///
+ /// 小程序帮助类
+ ///
+ ///
+ ///
+ ///
+ ///
+ public class MiniProgram(string appId, string secret, IDatabase database, IHttpClientFactory? _httpClientFactory)
+ {
+ public string AppId { get; set; } = appId;
+ string key = $"WeChat:{appId}";
+ // Method to get user's OpenID
+ public async Task<(string openId, string unionid, string session_key)> GetOpenid(string code)
+ {
+ string url = $"https://api.weixin.qq.com/sns/jscode2session?appid={appId}&secret={secret}&js_code={code}&grant_type=authorization_code";
+ var resUserInfo = await GetCurlData(url);
+
+ if (resUserInfo.ContainsKey("errcode"))
+ {
+ return (null, null, null);
+ }
+
+ string openid = resUserInfo.GetValueOrDefault("openid")?.ToString() ?? "";
+ string unionid = resUserInfo.GetValueOrDefault("unionid")?.ToString() ?? "";
+ string session_key = resUserInfo.GetValueOrDefault("session_key")?.ToString() ?? "";
+
+ return new(openid, unionid, session_key);
+
+ }
+
+
+ // Get user info based on access token and openid
+ public async Task GetUserInfoAsync(string openid)
+ {
+ var accessToken = await GetAccessToken();
+ string url = $"https://api.weixin.qq.com/sns/userinfo?access_token={accessToken}&openid={openid}&lang=zh_CN";
+ var response = await GetCurlData(url);
+
+ return response;
+ }
+
+ public async Task GetAccessToken()
+ {
+ var accessTokenInfo = GetConfig();
+
+ if (accessTokenInfo != null)
+ {
+ return accessTokenInfo?.Access_token;
+ }
+ else
+ {
+ string url = $"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appId}&secret={secret}";
+ var resAccessToken = await GetCurlData(url);
+ if (resAccessToken.ContainsKey("errcode"))
+ {
+ throw new Exception("获取微信token失败");
+ }
+
+ string accessToken = resAccessToken["access_token"].ToString();
+ int expiresIn = Convert.ToInt32(resAccessToken["expires_in"]);
+ long accessTokenTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + expiresIn;
+
+ var data = new AccessToken(accessToken, accessTokenTime);
+ SetConfig(data);
+ return accessToken;
+ }
+ }
+
+ // Helper method for GET requests
+ private async Task> GetCurlData(string url)
+ {
+ using HttpClient client = _httpClientFactory.CreateClient();
+ var response = await client.GetStringAsync(url);
+ return JsonConvert.DeserializeObject>(response);
+ }
+
+ // Helper method for POST requests
+ private async Task> PostCurlData(string url, object data)
+ {
+ using HttpClient client = _httpClientFactory.CreateClient();
+ var json = JsonConvert.SerializeObject(data);
+ var content = new StringContent(json, Encoding.UTF8, "application/json");
+ var response = await client.PostAsync(url, content);
+ var result = await response.Content.ReadAsStringAsync();
+ return JsonConvert.DeserializeObject>(result);
+ }
+
+ // Helper method for HTTP POST data
+ private async Task HttpPostData(string url, object data)
+ {
+ using HttpClient client = _httpClientFactory.CreateClient();
+ var json = JsonConvert.SerializeObject(data);
+ var content = new StringContent(json, Encoding.UTF8, "application/json");
+ var response = await client.PostAsync(url, content);
+ return await response.Content.ReadAsStringAsync();
+ }
+
+ private AccessToken? GetConfig()
+ {
+
+ var json = database.StringGet(key);
+ if (!string.IsNullOrEmpty(json))
+ {
+ return JsonConvert.DeserializeObject(json);
+ }
+ return null;
+ }
+
+ private void SetConfig(AccessToken access)
+ {
+ var outTime = new TimeSpan(0, 0, 7000);
+ database.StringSet(key, JsonConvert.SerializeObject(access), outTime);
+ }
+
+ }
+
+ ///
+ ///
+ ///
+ public class AccessToken
+ {
+ public string? Access_token { get; }
+ public long Access_token_time { get; }
+
+ public AccessToken(string? access_token, long access_token_time)
+ {
+ Access_token = access_token;
+ Access_token_time = access_token_time;
+ }
+ public AccessToken()
+ {
+
+ }
+ }
+}
diff --git a/src/0-core/HuanMeng.DotNetCore/WeChat/WXBizDataCrypt.cs b/src/0-core/HuanMeng.DotNetCore/WeChat/WXBizDataCrypt.cs
new file mode 100644
index 0000000..55fde7b
--- /dev/null
+++ b/src/0-core/HuanMeng.DotNetCore/WeChat/WXBizDataCrypt.cs
@@ -0,0 +1,122 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+using Newtonsoft.Json.Linq;
+
+namespace HuanMeng.DotNetCore.WeChat
+{
+
+ ///
+ ///
+ ///
+ public class WXBizDataCrypt
+ {
+ private string appId;
+ private string sessionKey;
+
+ ///
+ /// 构造函数
+ ///
+ /// 小程序的 appId
+ /// 用户在小程序登录后获取的会话密钥
+ public WXBizDataCrypt(string appId, string sessionKey)
+ {
+ this.appId = appId;
+ this.sessionKey = sessionKey;
+ }
+
+ ///
+ /// 检验数据的真实性,并且获取解密后的明文
+ ///
+ /// 加密的用户数据
+ /// 与用户数据一同返回的初始向量
+ /// 解密后的原文
+ /// 成功0,失败返回对应的错误码
+ public int DecryptData(string encryptedData, string iv, out string data)
+ {
+ data = null;
+
+ // 检查 sessionKey 长度
+ if (sessionKey.Length != 24)
+ {
+ return ErrorCode.IllegalAesKey;
+ }
+
+ // 检查 iv 长度
+ if (iv.Length != 24)
+ {
+ return ErrorCode.IllegalIv;
+ }
+
+ try
+ {
+ byte[] aesKey = Convert.FromBase64String(sessionKey);
+ byte[] aesIV = Convert.FromBase64String(iv);
+ byte[] aesCipher = Convert.FromBase64String(encryptedData);
+
+ using (Aes aesAlg = Aes.Create())
+ {
+ aesAlg.Key = aesKey;
+ aesAlg.IV = aesIV;
+ aesAlg.Mode = CipherMode.CBC;
+ aesAlg.Padding = PaddingMode.PKCS7;
+
+ using (ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV))
+ {
+ using (MemoryStream msDecrypt = new MemoryStream(aesCipher))
+ {
+ using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
+ {
+ using (StreamReader srDecrypt = new StreamReader(csDecrypt))
+ {
+ // 解密后的明文
+ data = srDecrypt.ReadToEnd();
+ }
+ }
+ }
+ }
+ }
+
+ JObject dataObj = JObject.Parse(data);
+
+ // 检查 appId
+ if (dataObj["watermark"]["appid"].ToString() != this.appId)
+ {
+ return ErrorCode.IllegalBuffer;
+ }
+
+ return ErrorCode.OK;
+ }
+ catch
+ {
+ return ErrorCode.IllegalBuffer;
+ }
+ }
+ }
+
+ public static class ErrorCode
+ {
+ public const int OK = 0;
+ public const int IllegalAesKey = -41001;
+ public const int IllegalIv = -41002;
+ public const int IllegalBuffer = -41003;
+ }
+
+ public class WXBizDataCryptModel
+ {
+ ///
+ ///
+ ///
+ public string EncryptedData;
+ ///
+ ///
+ ///
+ public string Iv;
+
+
+ public int UserId { get; set; }
+ }
+
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfig.cs b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfig.cs
index 58e2f87..8109160 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfig.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfig.cs
@@ -1,4 +1,5 @@
using HuanMeng.DotNetCore.MultiTenant;
+using HuanMeng.MiaoYu.Code.Payment;
using System;
using System.Collections.Generic;
@@ -38,6 +39,11 @@ namespace HuanMeng.MiaoYu.Code.AppExtend
/// 租户
///
public Guid TenantId { get; set; }
+
+ ///
+ /// 项目支付数据
+ ///
+ public PaymentModel? Payment { get; set; }
}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigExtendServer.cs b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigExtendServer.cs
index e45abb2..5b26e63 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigExtendServer.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigExtendServer.cs
@@ -1,12 +1,5 @@
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HuanMeng.MiaoYu.Code.AppExtend
{
///
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs
index d81915d..0f43dd3 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/AppExtend/AppConfigurationExtend.cs
@@ -168,6 +168,11 @@ namespace HuanMeng.MiaoYu.Code.AppExtend
newAppConfig.ConnectionString = appConfig.ConnectionString;
newAppConfig.DomainName = appConfig.DomainName;
newAppConfig.RedisConnectionString = appConfig.RedisConnectionString;
+ if (appConfig.Payment == null)
+ {
+ appConfig.Payment = new PaymentModel() { };
+ }
+ newAppConfig.Payment = appConfig.Payment;
return newAppConfig;
}
///
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs b/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs
index 121b0b4..b29d76c 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Base/MiaoYuBase.cs
@@ -1,33 +1,18 @@
using AutoMapper;
-using HuanMeng.DotNetCore.Base;
-using HuanMeng.DotNetCore.JwtInfrastructure;
using HuanMeng.DotNetCore.JwtInfrastructure.Interface;
-using HuanMeng.DotNetCore.MultiTenant;
using HuanMeng.DotNetCore.MultiTenant.Contract;
using HuanMeng.MiaoYu.Code.AppExtend;
-using HuanMeng.MiaoYu.Code.Cache;
using HuanMeng.MiaoYu.Code.Cache.Contract;
-using HuanMeng.MiaoYu.Code.DataAccess;
using HuanMeng.MiaoYu.Code.TencentUtile;
-using HuanMeng.MiaoYu.Code.Users.UserAccount;
using HuanMeng.MiaoYu.Code.Users.UserAccount.Contract;
using HuanMeng.MiaoYu.Model.Dto;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
-
using IDatabase = StackExchange.Redis.IDatabase;
namespace HuanMeng.MiaoYu.Code.Base
{
@@ -416,4 +401,21 @@ namespace HuanMeng.MiaoYu.Code.Base
}
#endregion
}
+
+ public static class MiaoYuBaseExtend
+ {
+ ///
+ /// 微信小程序登录验证
+ ///
+ ///
+ ///
+ public static DotNetCore.WeChat.MiniProgram GetMiniProgram(this MiaoYuBase miaoYuBase)
+ {
+ return new DotNetCore.WeChat.MiniProgram(
+ miaoYuBase.AppConfig.Payment?.WeChatConfig?.AppId ?? "",
+ miaoYuBase.AppConfig.Payment?.WeChatConfig?.AppSecret ?? "",
+ miaoYuBase.RedisCache,
+ miaoYuBase.HttpClientFactory);
+ }
+ }
}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/HuanMeng.MiaoYu.Code.csproj b/src/0-core/HuanMeng.MiaoYu.Code/HuanMeng.MiaoYu.Code.csproj
index 2340ba4..2e2e8c4 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/HuanMeng.MiaoYu.Code.csproj
+++ b/src/0-core/HuanMeng.MiaoYu.Code/HuanMeng.MiaoYu.Code.csproj
@@ -27,6 +27,7 @@
+
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentExtend.cs b/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentExtend.cs
index cac5059..8a0ac8e 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentExtend.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentExtend.cs
@@ -13,6 +13,7 @@ using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
+using HuanMeng.MiaoYu.Code.Base;
@@ -108,12 +109,30 @@ namespace HuanMeng.MiaoYu.Code.Payment
///
public static IPayment GetPayment(string payment, MiaoYuBase miaoYuBase)
{
-
+ //miaoYuBase.AppConfig.Payment
if (payment == "zfb")
{
return new AlipayPayment(AlipayConfig, miaoYuBase.TenantInfo, miaoYuBase._UserId);
}
- return new WeChatPayment(wxClient, weChatConfig, miaoYuBase.TenantInfo, miaoYuBase._UserId);
+
+ if (miaoYuBase.AppConfig != null)
+ {
+ if (miaoYuBase.AppConfig.Payment == null)
+ {
+ miaoYuBase.AppConfig.Payment = new PaymentModel()
+ {
+ WeChatConfig = weChatConfig
+ };
+ }
+ if (miaoYuBase.AppConfig.Payment.WeChatConfig == null)
+ {
+ miaoYuBase.AppConfig.Payment.WeChatConfig = weChatConfig;
+ }
+ }
+
+ var _weChatConfig = miaoYuBase.AppConfig.Payment.WeChatConfig ?? weChatConfig;
+ var _wxClient = miaoYuBase.AppConfig.Payment.WxClient ?? wxClient;
+ return new WeChatPayment(_wxClient, _weChatConfig, miaoYuBase.TenantInfo, miaoYuBase._UserId);
}
///
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentModel.cs b/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentModel.cs
new file mode 100644
index 0000000..ecc028e
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Payment/PaymentModel.cs
@@ -0,0 +1,66 @@
+using Alipay.EasySDK.Kernel;
+
+using HuanMeng.MiaoYu.Code.Payment.WeChat;
+
+using SKIT.FlurlHttpClient.Wechat.TenpayV3;
+using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
+using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HuanMeng.MiaoYu.Code.Payment
+{
+ ///
+ ///
+ ///
+ public class PaymentModel
+ {
+ ///
+ /// 微信支付数据
+ ///
+ public WeChatConfig? WeChatConfig { get; set; }
+
+ ///
+ /// 支付宝支付数据
+ ///
+ public Config? AlipayConfig { get; set; }
+
+ ///
+ ///
+ ///
+ private WechatTenpayClient _wxClient;
+ ///
+ /// 微信支付客户端
+ ///
+ public WechatTenpayClient? WxClient
+ {
+ get
+ {
+ if (_wxClient == null)
+ {
+ if (WeChatConfig == null)
+ {
+ return null;
+ }
+ var manager = new InMemoryCertificateManager();
+ /* 仅列出必须配置项。也包含一些诸如超时时间、UserAgent 等的配置项 */
+ var wechatTenpayClientOptions = new WechatTenpayClientOptions()
+ {
+
+ MerchantId = WeChatConfig.MchId,
+ MerchantV3Secret = WeChatConfig.Key,
+ MerchantCertificateSerialNumber = WeChatConfig.MerchantCertificateSerialNumber,
+ MerchantCertificatePrivateKey = WeChatConfig.MerchantCertificatePrivateKey,
+ PlatformCertificateManager = manager
+ };
+ _wxClient = new WechatTenpayClient(wechatTenpayClientOptions);
+ }
+ return _wxClient;
+ }
+ }
+ }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneLoginParams.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneLoginParams.cs
index 035effe..dce38df 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneLoginParams.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/PhoneAccount/PhoneLoginParams.cs
@@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace HuanMeng.MiaoYu.Code.Users.UserAccount.PhoneAccount
{
///
- /// 登录参数
+ /// 登录参数
///
public class PhoneLoginParams : BaseLoginParams
{
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/WeChat/MiniProgramAccountLogin.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/WeChat/MiniProgramAccountLogin.cs
new file mode 100644
index 0000000..f1deb95
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/WeChat/MiniProgramAccountLogin.cs
@@ -0,0 +1,104 @@
+using HuanMeng.MiaoYu.Code.Users.UserAccount.Contract;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using HuanMeng.DotNetCore.WeChat;
+using HuanMeng.MiaoYu.Code.Users.UserAccount.PhoneAccount;
+namespace HuanMeng.MiaoYu.Code.Users.UserAccount.WeChat
+{
+ ///
+ /// PhoneLoginParams
+ ///
+ public class MiniProgramAccountLogin(MiniProgram miniProgram, DAO dao) : IUserAccount
+ {
+ public override async Task LoginAsync(BaseLoginParams loginParams)
+ {
+ var login = loginParams as MiniProgramAccountParams;
+ if (login == null)
+ {
+ throw new ArgumentNullException("登录方式错误");
+ }
+ if (string.IsNullOrEmpty(login.Code))
+ {
+ throw new ArgumentNullException("小程序code不能为空");
+ }
+ (string openId, string unionid, string session_key) = await miniProgram.GetOpenid(login.Code);
+ if (openId == null)
+ {
+ throw new ArgumentNullException("小程序登录失败");
+ }
+ var account = dao.daoDbMiaoYu.context.T_User_MiniProgram_Account.FirstOrDefault(it => it.OpenId == openId); T_User? user = null;
+ if (account == null)
+ {
+ user = new T_User()
+ {
+ UpdatedAt = DateTime.Now,
+ CreatedAt = DateTime.Now,
+ IsActive = true,
+ LastLoginAt = DateTime.Now,
+ LastLoginTypeAt = 2,
+ Email = "",
+ NickName = "微信用户",
+ PhoneNum = "",
+ RegisterType = 2,
+ TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId,
+ UserName = "微信用户",
+ State = 0,
+
+ };
+ dao.daoDbMiaoYu.context.T_User.Add(user);
+ dao.daoDbMiaoYu.context.SaveChanges();
+ account = new T_User_MiniProgram_Account()
+ {
+ CreateAt = DateTime.Now,
+ OpenId = openId,
+ SessionKey = session_key,
+ Unionid = unionid,
+ UpdateAt = DateTime.Now,
+ UserId = user.Id,
+
+
+ };
+ dao.daoDbMiaoYu.context.Add(account);
+ dao.daoDbMiaoYu.context.SaveChanges();
+ }
+ else
+ {
+ user = await dao.daoDbMiaoYu.context.T_User.FirstOrDefaultAsync(it => it.Id == account.UserId);
+
+ }
+ //WXBizDataCrypt wXBizDataCrypt = new WXBizDataCrypt(miniProgram.AppId, session_key);
+ account.UpdateAt = DateTime.Now;
+ account.SessionKey = session_key;
+ if (user == null)
+ {
+ user = new T_User()
+ {
+ UpdatedAt = DateTime.Now,
+ CreatedAt = DateTime.Now,
+ IsActive = true,
+ LastLoginAt = DateTime.Now,
+ LastLoginTypeAt = 2,
+ Email = "",
+ NickName = "微信用户",
+ PhoneNum = "",
+ RegisterType = 2,
+ TenantId = dao.daoDbMiaoYu.context.TenantInfo.TenantId,
+ UserName = "微信用户",
+ State = 0,
+
+ };
+ dao.daoDbMiaoYu.context.T_User.Add(user);
+ }
+ dao.daoDbMiaoYu.context.SaveChanges();
+ return new LoginAccountInfo()
+ {
+ NickName = user.NickName,
+ UserId = user.Id,
+ };
+ }
+ }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/WeChat/MiniProgramAccountParams.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/WeChat/MiniProgramAccountParams.cs
new file mode 100644
index 0000000..90e9ed3
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserAccount/WeChat/MiniProgramAccountParams.cs
@@ -0,0 +1,22 @@
+using HuanMeng.MiaoYu.Code.Users.UserAccount.Contract;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HuanMeng.MiaoYu.Code.Users.UserAccount.WeChat
+{
+ ///
+ ///
+ ///
+ public class MiniProgramAccountParams : BaseLoginParams
+ {
+ ///
+ /// 微信小程序code
+ ///
+ public string Code { get; set; }
+ }
+}
+
diff --git a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs
index f176682..9861560 100644
--- a/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Code/Users/UserBLL.cs
@@ -1,9 +1,11 @@
using HuanMeng.DotNetCore.Base;
+using HuanMeng.DotNetCore.WeChat;
using HuanMeng.MiaoYu.Code.Base;
using HuanMeng.MiaoYu.Code.DataAccess;
using HuanMeng.MiaoYu.Code.Users.UserAccount;
using HuanMeng.MiaoYu.Code.Users.UserAccount.Contract;
using HuanMeng.MiaoYu.Code.Users.UserAccount.PhoneAccount;
+using HuanMeng.MiaoYu.Code.Users.UserAccount.WeChat;
using HuanMeng.MiaoYu.Model.Dto;
using HuanMeng.MiaoYu.Model.Dto.Account;
using HuanMeng.MiaoYu.Model.Dto.Character;
@@ -18,6 +20,7 @@ using Newtonsoft.Json;
using System;
using System.Collections.Generic;
+using System.Data.SqlTypes;
using System.Linq;
using System.Security.Claims;
using System.Text;
@@ -82,6 +85,14 @@ namespace HuanMeng.MiaoYu.Code.Users
Ip = ip
};
}
+ else if (requestLoginModel.LoginType == 2)
+ {//
+ userAccount = new MiniProgramAccountLogin(this.GetMiniProgram(), Dao);
+ loginParams = new MiniProgramAccountParams()
+ {
+ Code = requestLoginModel.Code,
+ };
+ }
else
{
throw new Exception("不支持的登录方式");
@@ -163,6 +174,66 @@ namespace HuanMeng.MiaoYu.Code.Users
});
}
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task GetMiniProgramUserInfo(WXBizDataCryptModel wXBizDataCryptModel)
+ {
+ var appId = this.AppConfig.Payment?.WeChatConfig?.AppId ?? "";
+ var account = Dao.daoDbMiaoYu.context.T_User_MiniProgram_Account.FirstOrDefault(it => it.UserId == wXBizDataCryptModel.UserId);
+ WXBizDataCrypt wXBizDataCrypt = new WXBizDataCrypt(appId, account.SessionKey ?? "");
+ var t = wXBizDataCrypt.DecryptData(wXBizDataCryptModel.EncryptedData, wXBizDataCryptModel.Iv, out var data);
+ if (t == 0)
+ {
+ var jsonData = JsonConvert.DeserializeObject(data);
+ if (jsonData?["nickName"] != null)
+ {
+ string nickName = jsonData?["nickName"]?.ToString();
+ }
+ }
+ return data;
+ }
+
+ ///
+ /// 修改用户昵称
+ ///
+ ///
+ ///
+ ///
+ public async Task> UpdateUserNickName(string nickName)
+ {
+ var user = Dao.daoDbMiaoYu.context.T_User.FirstOrDefault(it => it.Id == _UserId);
+ if (user == null)
+ {
+ throw new Exception("用户不存在");
+ }
+ user.NickName = nickName;
+ await Dao.daoDbMiaoYu.context.SaveChangesAsync();
+ string sqlString = $@"update M_Songs set AuthorName='{nickName}' where AuthorId={_UserId}";
+ await Dao.daoDbMiaoYu.context.Database.ExecuteSqlRawAsync(sqlString);
+ return new BaseResponse(ResonseCode.Success, "", true);
+ }
+
+ ///
+ /// 修改用户头像
+ ///
+ ///
+ ///
+ ///
+ public async Task> UpdateUserIcon(string userIcon)
+ {
+ var user = Dao.daoDbMiaoYu.context.T_User.FirstOrDefault(it => it.Id == _UserId);
+ if (user == null)
+ {
+ throw new Exception("用户不存在");
+ }
+ user.UserIconUrl = userIcon;
+ await Dao.daoDbMiaoYu.context.SaveChangesAsync();
+ return new BaseResponse(ResonseCode.Success, "", true);
+ }
///
/// 交易记录
///
@@ -191,6 +262,7 @@ namespace HuanMeng.MiaoYu.Code.Users
}
return new BaseResponse>(ResonseCode.Success, "", list);
}
+
///
/// 获取未使用的记忆卡列表
///
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs
index 6376f2c..9539c80 100644
--- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/MiaoYuContext.cs
@@ -213,6 +213,11 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
///
public virtual DbSet T_User_MemoryCard { get; set; }
+ ///
+ /// 小程序登录表
+ ///
+ public virtual DbSet T_User_MiniProgram_Account { get; set; }
+
///
/// 手机号登录表
///
@@ -1291,6 +1296,35 @@ public partial class MiaoYuContext : MultiTenantDbContext//DbContext
}
});
+ modelBuilder.Entity(entity =>
+ {
+ entity.HasKey(e => e.Id).HasName("PK__T_User_M__3214EC073889A8B9");
+
+ entity.ToTable(tb => tb.HasComment("小程序登录表"));
+
+ entity.Property(e => e.Id).HasComment("主键");
+ entity.Property(e => e.CreateAt)
+ .HasComment("创建时间")
+ .HasColumnType("datetime");
+ entity.Property(e => e.OpenId)
+ .HasMaxLength(200)
+ .HasComment("用户唯一标识");
+ entity.Property(e => e.SessionKey).HasMaxLength(200);
+ entity.Property(e => e.TenantId).HasComment("租户");
+ entity.Property(e => e.Unionid)
+ .HasMaxLength(200)
+ .HasComment("用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回,详见");
+ entity.Property(e => e.UpdateAt)
+ .HasComment("修改时间")
+ .HasColumnType("datetime");
+ entity.Property(e => e.UserId).HasComment("用户Id");
+ //添加全局筛选器
+ if (this.TenantInfo != null)
+ {
+ entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId);
+ }
+ });
+
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id).HasName("PK__T_User_P__3214EC07987BDDB2");
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs
index 7202cb5..370ac8b 100644
--- a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_Data.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu;
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_MiniProgram_Account.cs b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_MiniProgram_Account.cs
new file mode 100644
index 0000000..2dd67d1
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Model/DbSqlServer/Db_MiaoYu/T_User_MiniProgram_Account.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace HuanMeng.MiaoYu.Model.DbSqlServer.Db_MiaoYu;
+
+///
+/// 小程序登录表
+///
+public partial class T_User_MiniProgram_Account: MultiTenantEntity
+{
+ ///
+ /// 主键
+ ///
+ public virtual int Id { get; set; }
+
+ public override Guid TenantId { get; set; }
+
+ ///
+ /// 用户Id
+ ///
+ public virtual int UserId { get; set; }
+
+ ///
+ /// 用户唯一标识
+ ///
+ public virtual string OpenId { get; set; } = null!;
+
+ ///
+ /// 用户在开放平台的唯一标识符,若当前小程序已绑定到微信开放平台账号下会返回,详见
+ ///
+ public virtual string? Unionid { get; set; }
+
+ public virtual string? SessionKey { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ public virtual DateTime CreateAt { get; set; }
+
+ ///
+ /// 修改时间
+ ///
+ public virtual DateTime UpdateAt { get; set; }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestAccountCommonUser.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestAccountCommonUser.cs
new file mode 100644
index 0000000..acc2439
--- /dev/null
+++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestAccountCommonUser.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HuanMeng.MiaoYu.Model.Dto.Account
+{
+ ///
+ ///
+ ///
+ public class RequestAccountCommonUser
+ {
+ ///
+ ///
+ ///
+ public string NickName { get; set; }
+ }
+
+ ///
+ ///
+ ///
+ public class RequestAccountCommonUserImage
+ {
+ ///
+ ///
+ ///
+ public string UserIcon { get; set; }
+ }
+}
diff --git a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestLoginModel.cs b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestLoginModel.cs
index 208fc4d..3895711 100644
--- a/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestLoginModel.cs
+++ b/src/0-core/HuanMeng.MiaoYu.Model/Dto/Account/RequestLoginModel.cs
@@ -17,7 +17,7 @@ namespace HuanMeng.MiaoYu.Model.Dto.Account
public string? VerificationCode { get; set; }
///
- /// 登录类型,0token登录 1手机号,2邮箱
+ /// 登录类型,0token登录 1手机号,2微信登录
///
public int LoginType { get; set; }
@@ -25,5 +25,10 @@ namespace HuanMeng.MiaoYu.Model.Dto.Account
/// token登录
///
public string? Token { get; set; }
+
+ ///
+ /// 微信小程序登录Code
+ ///
+ public string? Code { get; set; }
}
}
diff --git a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs
index 6f66dfe..cb2ff59 100644
--- a/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs
+++ b/src/2-api/HuanMeng.MiaoYu.WebApi/Controllers/AccountController.cs
@@ -2,6 +2,7 @@ using Azure;
using HuanMeng.DotNetCore.Base;
using HuanMeng.DotNetCore.Utility;
+using HuanMeng.DotNetCore.WeChat;
using HuanMeng.MiaoYu.Code.Mall;
using HuanMeng.MiaoYu.Code.Other;
using HuanMeng.MiaoYu.Code.Users;
@@ -76,6 +77,18 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers
UserBLL userBLL = new UserBLL(ServiceProvider);
return await userBLL.GetUserInfo();
}
+ ///
+ /// 解析微信用户数据
+ ///
+ ///
+ [AllowAnonymous]
+ [HttpPost]
+ public async Task GetMiniProgramUserInfo([FromBody] WXBizDataCryptModel wXBizDataCryptModel)
+ {
+ UserBLL userBLL = new UserBLL(ServiceProvider);
+ return await userBLL.GetMiniProgramUserInfo(wXBizDataCryptModel);
+ }
+
///
/// 我的账户
@@ -98,7 +111,32 @@ namespace HuanMeng.MiaoYu.WebApi.Controllers
{
UserBLL userBLL = new UserBLL(ServiceProvider);
return await userBLL.GetTransactionRecords();
+ }
+ ///
+ /// 修改用户昵称
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> UpdateUserNickName([FromBody] RequestAccountCommonUser requestAccountCommonUser)
+ {
+ UserBLL userBLL = new UserBLL(ServiceProvider);
+ return await userBLL.UpdateUserNickName(requestAccountCommonUser.NickName);
+ }
+
+ ///
+ /// 修改用户头像
+ ///
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> UpdateUserIcon([FromBody] RequestAccountCommonUserImage requestAccountCommonUserImage)
+ {
+ UserBLL userBLL = new UserBLL(ServiceProvider);
+ return await userBLL.UpdateUserIcon(requestAccountCommonUserImage.UserIcon);
}