Browse Source

support wechat quick login.

pull/292/head
cKey 4 years ago
parent
commit
4968b1a4e8
  1. 7
      aspnet-core/LINGYUN.MicroService.IdentityServer.sln
  2. 478
      aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln
  3. 541
      aspnet-core/LINGYUN.MicroService.Messages.sln
  4. 1
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN.Abp.IdentityServer.WeChat.csproj
  5. 110
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/AbpIdentityServerWeChatModule.cs
  6. 94
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs
  7. 92
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs
  8. 142
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialOAuthConsts.cs
  9. 259
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs
  10. 28
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj
  11. 57
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs
  12. 62
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AspNetIdentity/AbpWeChatProfileService.cs
  13. 9
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/IWeChatResourceDataSeeder.cs
  14. 10
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/en.json
  15. 10
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/zh-Hans.json
  16. 85
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatResourceDataSeeder.cs
  17. 74
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs
  18. 16
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs
  19. 111
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs
  20. 16
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatValidatorConsts.cs
  21. 316
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationHandler.cs
  22. 54
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationOptions.cs
  23. 18
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationStateCacheItem.cs
  24. 64
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs
  25. 22
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs
  26. 17
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/README.md
  27. 16
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/BytesExtensions.cs
  28. 17
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/StringExtensions.cs
  29. 63
      aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Text/Json/JsonElementExtensions.cs
  30. 19
      aspnet-core/modules/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN.Abp.Identity.WeChat.csproj
  31. 13
      aspnet-core/modules/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN/Abp/Identity/WeChat/AbpIdentityWeChatModule.cs
  32. 93
      aspnet-core/modules/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN/Abp/Identity/WeChat/OpenId/UserWeChatOpenIdFinder.cs
  33. 14
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN.Abp.WeChat.Application.Contracts.csproj
  34. 11
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/AbpWeChatApplicationContractsModule.cs
  35. 21
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/Dto/Gender.cs
  36. 9
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/Dto/GetUserInfoInput.cs
  37. 37
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/Dto/UserInfoDto.cs
  38. 10
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/ICryptoAppService.cs
  39. 7
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/WeChatRemoteServiceConsts.cs
  40. 19
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN.Abp.WeChat.Application.csproj
  41. 14
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN/Abp/WeChat/AbpWeChatApplicationModule.cs
  42. 42
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN/Abp/WeChat/Crypto/CryptoAppService.cs
  43. 14
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN/Abp/WeChat/WeChatApplicationServiceBase.cs
  44. 14
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.HttpApi/LINGYUN.Abp.WeChat.HttpApi.csproj
  45. 12
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.HttpApi/LINGYUN/Abp/WeChat/AbpWeChatHttpApiModule.cs
  46. 29
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.HttpApi/LINGYUN/Abp/WeChat/Crypto/CryptoController.cs
  47. 42
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramConsts.cs
  48. 74
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramModule.cs
  49. 48
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/Messages/Response.SubscribeMessage.cs
  50. 212
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/Messages/SubscribeMessage.cs
  51. 238
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/Messages/SubscribeMessager.cs
  52. 44
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialConsts.cs
  53. 240
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.SettingManagement/LINGYUN/Abp/WeChat/SettingManagement/WeChatSettingAppService.cs
  54. 86
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatModule.cs
  55. 7
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Crypto/IWeChatCryptoService.cs
  56. 36
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Crypto/WeChatCryptoService.cs
  57. 5
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Localization/Resources/en.json
  58. 5
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Localization/Resources/zh-Hans.json
  59. 24
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/IUserWeChatOpenIdFinder.cs
  60. 26
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/IWeChatOpenIdFinder.cs
  61. 56
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdCacheItem.cs
  62. 212
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdFinder.cs
  63. 126
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdResponse.cs
  64. 28
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Settings/WeChatSettingDefinitionProvider.cs
  65. 19
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Settings/WeChatSettingNames.cs
  66. 182
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenProvider.cs
  67. 82
      aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenResponse.cs
  68. 624
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs
  69. 2
      aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj

7
aspnet-core/LINGYUN.MicroService.IdentityServer.sln

@ -59,6 +59,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "theming", "theming", "{1D7C
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly.AntDesign", "theming\Volo.Abp.AspNetCore.Components.WebAssembly.AntDesign\Volo.Abp.AspNetCore.Components.WebAssembly.AntDesign.csproj", "{596BB67C-7765-4481-9C8B-EAE0D9726B75}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.AspNetCore.Components.WebAssembly.AntDesign", "theming\Volo.Abp.AspNetCore.Components.WebAssembly.AntDesign\Volo.Abp.AspNetCore.Components.WebAssembly.AntDesign.csproj", "{596BB67C-7765-4481-9C8B-EAE0D9726B75}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WeChat", "modules\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj", "{46C3E5D2-7738-4C0F-AC51-C61A024CAF23}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -141,6 +143,10 @@ Global
{596BB67C-7765-4481-9C8B-EAE0D9726B75}.Debug|Any CPU.Build.0 = Debug|Any CPU {596BB67C-7765-4481-9C8B-EAE0D9726B75}.Debug|Any CPU.Build.0 = Debug|Any CPU
{596BB67C-7765-4481-9C8B-EAE0D9726B75}.Release|Any CPU.ActiveCfg = Release|Any CPU {596BB67C-7765-4481-9C8B-EAE0D9726B75}.Release|Any CPU.ActiveCfg = Release|Any CPU
{596BB67C-7765-4481-9C8B-EAE0D9726B75}.Release|Any CPU.Build.0 = Release|Any CPU {596BB67C-7765-4481-9C8B-EAE0D9726B75}.Release|Any CPU.Build.0 = Release|Any CPU
{46C3E5D2-7738-4C0F-AC51-C61A024CAF23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{46C3E5D2-7738-4C0F-AC51-C61A024CAF23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46C3E5D2-7738-4C0F-AC51-C61A024CAF23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46C3E5D2-7738-4C0F-AC51-C61A024CAF23}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -171,6 +177,7 @@ Global
{D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA} = {98887A8F-7040-4FA1-842F-A4C77A61ED09} {D63C0CA8-554D-43F2-8DB4-8B464E4C1CDA} = {98887A8F-7040-4FA1-842F-A4C77A61ED09}
{79CAF2CA-E9E1-48A5-A21F-3786383C12E0} = {98887A8F-7040-4FA1-842F-A4C77A61ED09} {79CAF2CA-E9E1-48A5-A21F-3786383C12E0} = {98887A8F-7040-4FA1-842F-A4C77A61ED09}
{596BB67C-7765-4481-9C8B-EAE0D9726B75} = {1D7CE7E0-37AB-477B-919B-B1EB2899A17E} {596BB67C-7765-4481-9C8B-EAE0D9726B75} = {1D7CE7E0-37AB-477B-919B-B1EB2899A17E}
{46C3E5D2-7738-4C0F-AC51-C61A024CAF23} = {AF8AECC8-0F42-4FC5-B3C0-00987BA8279F}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FCB77471-9ECB-4666-A316-1D6A6285A468} SolutionGuid = {FCB77471-9ECB-4666-A316-1D6A6285A468}

478
aspnet-core/LINGYUN.MicroService.IdentityServerAdmin.sln

@ -1,239 +1,239 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22 VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{14B8F528-C649-4FAD-9BBB-6C979ED403E1}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{14B8F528-C649-4FAD-9BBB-6C979ED403E1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Domain", "modules\identityServer\LINGYUN.Abp.IdentityServer.Domain\LINGYUN.Abp.IdentityServer.Domain.csproj", "{DC379D12-77E1-4600-8E99-AAD9B92C3A1B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Domain", "modules\identityServer\LINGYUN.Abp.IdentityServer.Domain\LINGYUN.Abp.IdentityServer.Domain.csproj", "{DC379D12-77E1-4600-8E99-AAD9B92C3A1B}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Application.Contracts", "modules\identityServer\LINGYUN.Abp.IdentityServer.Application.Contracts\LINGYUN.Abp.IdentityServer.Application.Contracts.csproj", "{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Application.Contracts", "modules\identityServer\LINGYUN.Abp.IdentityServer.Application.Contracts\LINGYUN.Abp.IdentityServer.Application.Contracts.csproj", "{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Application", "modules\identityServer\LINGYUN.Abp.IdentityServer.Application\LINGYUN.Abp.IdentityServer.Application.csproj", "{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.Application", "modules\identityServer\LINGYUN.Abp.IdentityServer.Application\LINGYUN.Abp.IdentityServer.Application.csproj", "{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.EntityFrameworkCore", "modules\identityServer\LINGYUN.Abp.IdentityServer.EntityFrameworkCore\LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj", "{DA57672C-501D-4CAF-8BF2-4D93B2D460BF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.EntityFrameworkCore", "modules\identityServer\LINGYUN.Abp.IdentityServer.EntityFrameworkCore\LINGYUN.Abp.IdentityServer.EntityFrameworkCore.csproj", "{DA57672C-501D-4CAF-8BF2-4D93B2D460BF}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.HttpApi", "modules\identityServer\LINGYUN.Abp.IdentityServer.HttpApi\LINGYUN.Abp.IdentityServer.HttpApi.csproj", "{9C505703-C073-4E7F-9BB5-9DE0631C95AB}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer.HttpApi", "modules\identityServer\LINGYUN.Abp.IdentityServer.HttpApi\LINGYUN.Abp.IdentityServer.HttpApi.csproj", "{9C505703-C073-4E7F-9BB5-9DE0631C95AB}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{0CA2F891-7E8E-453B-9FEF-ADCBEB7795DD}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{0CA2F891-7E8E-453B-9FEF-ADCBEB7795DD}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer4.HttpApi.Host", "services\identity-server\LINGYUN.Abp.IdentityServer4.HttpApi.Host\LINGYUN.Abp.IdentityServer4.HttpApi.Host.csproj", "{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IdentityServer4.HttpApi.Host", "services\identity-server\LINGYUN.Abp.IdentityServer4.HttpApi.Host\LINGYUN.Abp.IdentityServer4.HttpApi.Host.csproj", "{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "account", "account", "{4F06C65B-22CC-466E-B3FD-3F695DD38191}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "account", "account", "{4F06C65B-22CC-466E-B3FD-3F695DD38191}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity-server", "identity-server", "{7AB942D5-D139-4F9F-9342-71534AA3A5AC}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity-server", "identity-server", "{7AB942D5-D139-4F9F-9342-71534AA3A5AC}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{BD964040-90B2-4179-A5EB-5830F5C7E073}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{BD964040-90B2-4179-A5EB-5830F5C7E073}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application.Contracts", "modules\account\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj", "{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application.Contracts", "modules\account\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj", "{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application", "modules\account\LINGYUN.Abp.Account.Application\LINGYUN.Abp.Account.Application.csproj", "{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.Application", "modules\account\LINGYUN.Abp.Account.Application\LINGYUN.Abp.Account.Application.csproj", "{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.HttpApi", "modules\account\LINGYUN.Abp.Account.HttpApi\LINGYUN.Abp.Account.HttpApi.csproj", "{BB1124C0-79F4-4E72-8854-945B3F0AD76D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Account.HttpApi", "modules\account\LINGYUN.Abp.Account.HttpApi\LINGYUN.Abp.Account.HttpApi.csproj", "{BB1124C0-79F4-4E72-8854-945B3F0AD76D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{E22445B9-7039-4DA1-B547-BAB437D6D2B3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain", "modules\identity\LINGYUN.Abp.Identity.Domain\LINGYUN.Abp.Identity.Domain.csproj", "{E22445B9-7039-4DA1-B547-BAB437D6D2B3}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application.Contracts", "modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj", "{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application.Contracts", "modules\identity\LINGYUN.Abp.Identity.Application.Contracts\LINGYUN.Abp.Identity.Application.Contracts.csproj", "{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application", "modules\identity\LINGYUN.Abp.Identity.Application\LINGYUN.Abp.Identity.Application.csproj", "{B07A1763-1B37-4416-8F0C-B938C175A56D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Application", "modules\identity\LINGYUN.Abp.Identity.Application\LINGYUN.Abp.Identity.Application.csproj", "{B07A1763-1B37-4416-8F0C-B938C175A56D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi", "modules\identity\LINGYUN.Abp.Identity.HttpApi\LINGYUN.Abp.Identity.HttpApi.csproj", "{0F87C16B-8E91-4B25-B501-AD81F8EC599E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi", "modules\identity\LINGYUN.Abp.Identity.HttpApi\LINGYUN.Abp.Identity.HttpApi.csproj", "{0F87C16B-8E91-4B25-B501-AD81F8EC599E}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.EntityFrameworkCore", "modules\identity\LINGYUN.Abp.Identity.EntityFrameworkCore\LINGYUN.Abp.Identity.EntityFrameworkCore.csproj", "{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.EntityFrameworkCore", "modules\identity\LINGYUN.Abp.Identity.EntityFrameworkCore\LINGYUN.Abp.Identity.EntityFrameworkCore.csproj", "{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi.Client", "modules\identity\LINGYUN.Abp.Identity.HttpApi.Client\LINGYUN.Abp.Identity.HttpApi.Client.csproj", "{6679A09F-124A-470A-81F5-A94302CEFEE4}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.HttpApi.Client", "modules\identity\LINGYUN.Abp.Identity.HttpApi.Client\LINGYUN.Abp.Identity.HttpApi.Client.csproj", "{6679A09F-124A-470A-81F5-A94302CEFEE4}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.Domain.Identity", "modules\identity\LINGYUN.Abp.PermissionManagement.Domain.Identity\LINGYUN.Abp.PermissionManagement.Domain.Identity.csproj", "{177B6CD3-1690-416D-9B37-A821093DEFBD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.PermissionManagement.Domain.Identity", "modules\identity\LINGYUN.Abp.PermissionManagement.Domain.Identity\LINGYUN.Abp.PermissionManagement.Domain.Identity.csproj", "{177B6CD3-1690-416D-9B37-A821093DEFBD}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{7EE9651C-17B0-4343-A2ED-92439F8C9019}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{7EE9651C-17B0-4343-A2ED-92439F8C9019}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FD2DDD48-8F84-4924-BBAF-52080AB32267}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FD2DDD48-8F84-4924-BBAF-52080AB32267}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "modules\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "modules\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{23536755-4F00-4929-9C5E-D4CABD1CC513}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Domain.Shared", "modules\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj", "{23536755-4F00-4929-9C5E-D4CABD1CC513}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "modules\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{80A418EB-6149-4684-80EF-D8574B91FE2B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "modules\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{80A418EB-6149-4684-80EF-D8574B91FE2B}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling.Emailing", "modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj", "{986B0610-4AC3-499A-AB81-DF15EA06F4D1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling.Emailing", "modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj", "{986B0610-4AC3-499A-AB81-DF15EA06F4D1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{53E90646-2933-4381-9386-6BC6ED16E71A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{53E90646-2933-4381-9386-6BC6ED16E71A}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Authorization", "modules\common\LINGYUN.Abp.Aliyun.Authorization\LINGYUN.Abp.Aliyun.Authorization.csproj", "{720120B4-76F6-4701-9426-611BB8F84515}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Aliyun.Authorization", "modules\common\LINGYUN.Abp.Aliyun.Authorization\LINGYUN.Abp.Aliyun.Authorization.csproj", "{720120B4-76F6-4701-9426-611BB8F84515}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sms.Aliyun", "modules\common\LINGYUN.Abp.Sms.Aliyun\LINGYUN.Abp.Sms.Aliyun.csproj", "{D89ECB96-3349-4E77-B884-C18B30289D0D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Sms.Aliyun", "modules\common\LINGYUN.Abp.Sms.Aliyun\LINGYUN.Abp.Sms.Aliyun.csproj", "{D89ECB96-3349-4E77-B884-C18B30289D0D}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{39B77454-52AB-43BE-AB33-7680719415A6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{39B77454-52AB-43BE-AB33-7680719415A6}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{99B60A42-29DA-4D91-9255-B90F53BC6D6E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{99B60A42-29DA-4D91-9255-B90F53BC6D6E}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.DbFinder", "modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj", "{70C4FA43-0526-48E3-B852-A21395502604}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy.DbFinder", "modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj", "{70C4FA43-0526-48E3-B852-A21395502604}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Validation", "modules\common\LINGYUN.Abp.AspNetCore.Mvc.Validation\LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj", "{B3181D37-F379-4E16-8621-5E739C519393}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.Mvc.Validation", "modules\common\LINGYUN.Abp.AspNetCore.Mvc.Validation\LINGYUN.Abp.AspNetCore.Mvc.Validation.csproj", "{B3181D37-F379-4E16-8621-5E739C519393}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{AD1C3335-A2A1-49C1-A6DB-817C54859B65}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{AD1C3335-A2A1-49C1-A6DB-817C54859B65}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU Release|Any CPU = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU {DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU {DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Release|Any CPU.Build.0 = Release|Any CPU {DC379D12-77E1-4600-8E99-AAD9B92C3A1B}.Release|Any CPU.Build.0 = Release|Any CPU
{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Release|Any CPU.Build.0 = Release|Any CPU {3265F0C5-2D16-4CA8-A980-1B4B3CB928BB}.Release|Any CPU.Build.0 = Release|Any CPU
{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU {DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Release|Any CPU.Build.0 = Release|Any CPU {DBC8DC97-06DD-4496-9D2A-F28FDD379AE4}.Release|Any CPU.Build.0 = Release|Any CPU
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Release|Any CPU.Build.0 = Release|Any CPU {DA57672C-501D-4CAF-8BF2-4D93B2D460BF}.Release|Any CPU.Build.0 = Release|Any CPU
{9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Release|Any CPU.ActiveCfg = Release|Any CPU {9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Release|Any CPU.Build.0 = Release|Any CPU {9C505703-C073-4E7F-9BB5-9DE0631C95AB}.Release|Any CPU.Build.0 = Release|Any CPU
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Debug|Any CPU.Build.0 = Debug|Any CPU {DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Release|Any CPU.ActiveCfg = Release|Any CPU {DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Release|Any CPU.Build.0 = Release|Any CPU {DE9E58E2-268C-4DF0-85AA-FF7F328B62F0}.Release|Any CPU.Build.0 = Release|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Debug|Any CPU.Build.0 = Debug|Any CPU {A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Release|Any CPU.ActiveCfg = Release|Any CPU {A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Release|Any CPU.Build.0 = Release|Any CPU {A4DFDE21-1931-46B5-8381-36B6EB6E51E1}.Release|Any CPU.Build.0 = Release|Any CPU
{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Debug|Any CPU.Build.0 = Debug|Any CPU {6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Release|Any CPU.ActiveCfg = Release|Any CPU {6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Release|Any CPU.Build.0 = Release|Any CPU {6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2}.Release|Any CPU.Build.0 = Release|Any CPU
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Debug|Any CPU.Build.0 = Debug|Any CPU {BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Release|Any CPU.Build.0 = Release|Any CPU {BB1124C0-79F4-4E72-8854-945B3F0AD76D}.Release|Any CPU.Build.0 = Release|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Debug|Any CPU.Build.0 = Debug|Any CPU {E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Release|Any CPU.ActiveCfg = Release|Any CPU {E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Release|Any CPU.Build.0 = Release|Any CPU {E22445B9-7039-4DA1-B547-BAB437D6D2B3}.Release|Any CPU.Build.0 = Release|Any CPU
{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Debug|Any CPU.Build.0 = Debug|Any CPU {116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Release|Any CPU.ActiveCfg = Release|Any CPU {116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Release|Any CPU.Build.0 = Release|Any CPU {116D9D69-ED2C-4F23-9445-3981D8EA0EB7}.Release|Any CPU.Build.0 = Release|Any CPU
{B07A1763-1B37-4416-8F0C-B938C175A56D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B07A1763-1B37-4416-8F0C-B938C175A56D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B07A1763-1B37-4416-8F0C-B938C175A56D}.Debug|Any CPU.Build.0 = Debug|Any CPU {B07A1763-1B37-4416-8F0C-B938C175A56D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B07A1763-1B37-4416-8F0C-B938C175A56D}.Release|Any CPU.ActiveCfg = Release|Any CPU {B07A1763-1B37-4416-8F0C-B938C175A56D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B07A1763-1B37-4416-8F0C-B938C175A56D}.Release|Any CPU.Build.0 = Release|Any CPU {B07A1763-1B37-4416-8F0C-B938C175A56D}.Release|Any CPU.Build.0 = Release|Any CPU
{0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Debug|Any CPU.Build.0 = Debug|Any CPU {0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Release|Any CPU.ActiveCfg = Release|Any CPU {0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Release|Any CPU.Build.0 = Release|Any CPU {0F87C16B-8E91-4B25-B501-AD81F8EC599E}.Release|Any CPU.Build.0 = Release|Any CPU
{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Release|Any CPU.ActiveCfg = Release|Any CPU {BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Release|Any CPU.Build.0 = Release|Any CPU {BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7}.Release|Any CPU.Build.0 = Release|Any CPU
{6679A09F-124A-470A-81F5-A94302CEFEE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6679A09F-124A-470A-81F5-A94302CEFEE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6679A09F-124A-470A-81F5-A94302CEFEE4}.Debug|Any CPU.Build.0 = Debug|Any CPU {6679A09F-124A-470A-81F5-A94302CEFEE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6679A09F-124A-470A-81F5-A94302CEFEE4}.Release|Any CPU.ActiveCfg = Release|Any CPU {6679A09F-124A-470A-81F5-A94302CEFEE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6679A09F-124A-470A-81F5-A94302CEFEE4}.Release|Any CPU.Build.0 = Release|Any CPU {6679A09F-124A-470A-81F5-A94302CEFEE4}.Release|Any CPU.Build.0 = Release|Any CPU
{177B6CD3-1690-416D-9B37-A821093DEFBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {177B6CD3-1690-416D-9B37-A821093DEFBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{177B6CD3-1690-416D-9B37-A821093DEFBD}.Debug|Any CPU.Build.0 = Debug|Any CPU {177B6CD3-1690-416D-9B37-A821093DEFBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{177B6CD3-1690-416D-9B37-A821093DEFBD}.Release|Any CPU.ActiveCfg = Release|Any CPU {177B6CD3-1690-416D-9B37-A821093DEFBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{177B6CD3-1690-416D-9B37-A821093DEFBD}.Release|Any CPU.Build.0 = Release|Any CPU {177B6CD3-1690-416D-9B37-A821093DEFBD}.Release|Any CPU.Build.0 = Release|Any CPU
{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Release|Any CPU.Build.0 = Release|Any CPU {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}.Release|Any CPU.Build.0 = Release|Any CPU
{23536755-4F00-4929-9C5E-D4CABD1CC513}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {23536755-4F00-4929-9C5E-D4CABD1CC513}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{23536755-4F00-4929-9C5E-D4CABD1CC513}.Debug|Any CPU.Build.0 = Debug|Any CPU {23536755-4F00-4929-9C5E-D4CABD1CC513}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23536755-4F00-4929-9C5E-D4CABD1CC513}.Release|Any CPU.ActiveCfg = Release|Any CPU {23536755-4F00-4929-9C5E-D4CABD1CC513}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23536755-4F00-4929-9C5E-D4CABD1CC513}.Release|Any CPU.Build.0 = Release|Any CPU {23536755-4F00-4929-9C5E-D4CABD1CC513}.Release|Any CPU.Build.0 = Release|Any CPU
{80A418EB-6149-4684-80EF-D8574B91FE2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {80A418EB-6149-4684-80EF-D8574B91FE2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80A418EB-6149-4684-80EF-D8574B91FE2B}.Debug|Any CPU.Build.0 = Debug|Any CPU {80A418EB-6149-4684-80EF-D8574B91FE2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80A418EB-6149-4684-80EF-D8574B91FE2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {80A418EB-6149-4684-80EF-D8574B91FE2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80A418EB-6149-4684-80EF-D8574B91FE2B}.Release|Any CPU.Build.0 = Release|Any CPU {80A418EB-6149-4684-80EF-D8574B91FE2B}.Release|Any CPU.Build.0 = Release|Any CPU
{986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Debug|Any CPU.Build.0 = Debug|Any CPU {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Release|Any CPU.ActiveCfg = Release|Any CPU {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Release|Any CPU.Build.0 = Release|Any CPU {986B0610-4AC3-499A-AB81-DF15EA06F4D1}.Release|Any CPU.Build.0 = Release|Any CPU
{53E90646-2933-4381-9386-6BC6ED16E71A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53E90646-2933-4381-9386-6BC6ED16E71A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53E90646-2933-4381-9386-6BC6ED16E71A}.Debug|Any CPU.Build.0 = Debug|Any CPU {53E90646-2933-4381-9386-6BC6ED16E71A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53E90646-2933-4381-9386-6BC6ED16E71A}.Release|Any CPU.ActiveCfg = Release|Any CPU {53E90646-2933-4381-9386-6BC6ED16E71A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53E90646-2933-4381-9386-6BC6ED16E71A}.Release|Any CPU.Build.0 = Release|Any CPU {53E90646-2933-4381-9386-6BC6ED16E71A}.Release|Any CPU.Build.0 = Release|Any CPU
{720120B4-76F6-4701-9426-611BB8F84515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {720120B4-76F6-4701-9426-611BB8F84515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{720120B4-76F6-4701-9426-611BB8F84515}.Debug|Any CPU.Build.0 = Debug|Any CPU {720120B4-76F6-4701-9426-611BB8F84515}.Debug|Any CPU.Build.0 = Debug|Any CPU
{720120B4-76F6-4701-9426-611BB8F84515}.Release|Any CPU.ActiveCfg = Release|Any CPU {720120B4-76F6-4701-9426-611BB8F84515}.Release|Any CPU.ActiveCfg = Release|Any CPU
{720120B4-76F6-4701-9426-611BB8F84515}.Release|Any CPU.Build.0 = Release|Any CPU {720120B4-76F6-4701-9426-611BB8F84515}.Release|Any CPU.Build.0 = Release|Any CPU
{D89ECB96-3349-4E77-B884-C18B30289D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D89ECB96-3349-4E77-B884-C18B30289D0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D89ECB96-3349-4E77-B884-C18B30289D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU {D89ECB96-3349-4E77-B884-C18B30289D0D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D89ECB96-3349-4E77-B884-C18B30289D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU {D89ECB96-3349-4E77-B884-C18B30289D0D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D89ECB96-3349-4E77-B884-C18B30289D0D}.Release|Any CPU.Build.0 = Release|Any CPU {D89ECB96-3349-4E77-B884-C18B30289D0D}.Release|Any CPU.Build.0 = Release|Any CPU
{39B77454-52AB-43BE-AB33-7680719415A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {39B77454-52AB-43BE-AB33-7680719415A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39B77454-52AB-43BE-AB33-7680719415A6}.Debug|Any CPU.Build.0 = Debug|Any CPU {39B77454-52AB-43BE-AB33-7680719415A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39B77454-52AB-43BE-AB33-7680719415A6}.Release|Any CPU.ActiveCfg = Release|Any CPU {39B77454-52AB-43BE-AB33-7680719415A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39B77454-52AB-43BE-AB33-7680719415A6}.Release|Any CPU.Build.0 = Release|Any CPU {39B77454-52AB-43BE-AB33-7680719415A6}.Release|Any CPU.Build.0 = Release|Any CPU
{99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Release|Any CPU.Build.0 = Release|Any CPU {99B60A42-29DA-4D91-9255-B90F53BC6D6E}.Release|Any CPU.Build.0 = Release|Any CPU
{70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.Build.0 = Debug|Any CPU {70C4FA43-0526-48E3-B852-A21395502604}.Debug|Any CPU.Build.0 = Debug|Any CPU
{70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.ActiveCfg = Release|Any CPU {70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.ActiveCfg = Release|Any CPU
{70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.Build.0 = Release|Any CPU {70C4FA43-0526-48E3-B852-A21395502604}.Release|Any CPU.Build.0 = Release|Any CPU
{B3181D37-F379-4E16-8621-5E739C519393}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B3181D37-F379-4E16-8621-5E739C519393}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B3181D37-F379-4E16-8621-5E739C519393}.Debug|Any CPU.Build.0 = Debug|Any CPU {B3181D37-F379-4E16-8621-5E739C519393}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B3181D37-F379-4E16-8621-5E739C519393}.Release|Any CPU.ActiveCfg = Release|Any CPU {B3181D37-F379-4E16-8621-5E739C519393}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B3181D37-F379-4E16-8621-5E739C519393}.Release|Any CPU.Build.0 = Release|Any CPU {B3181D37-F379-4E16-8621-5E739C519393}.Release|Any CPU.Build.0 = Release|Any CPU
{AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Release|Any CPU.Build.0 = Release|Any CPU {AD1C3335-A2A1-49C1-A6DB-817C54859B65}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC} {DC379D12-77E1-4600-8E99-AAD9B92C3A1B} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC}
{3265F0C5-2D16-4CA8-A980-1B4B3CB928BB} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC} {3265F0C5-2D16-4CA8-A980-1B4B3CB928BB} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC}
{DBC8DC97-06DD-4496-9D2A-F28FDD379AE4} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC} {DBC8DC97-06DD-4496-9D2A-F28FDD379AE4} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC}
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC} {DA57672C-501D-4CAF-8BF2-4D93B2D460BF} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC}
{9C505703-C073-4E7F-9BB5-9DE0631C95AB} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC} {9C505703-C073-4E7F-9BB5-9DE0631C95AB} = {7AB942D5-D139-4F9F-9342-71534AA3A5AC}
{DE9E58E2-268C-4DF0-85AA-FF7F328B62F0} = {0CA2F891-7E8E-453B-9FEF-ADCBEB7795DD} {DE9E58E2-268C-4DF0-85AA-FF7F328B62F0} = {0CA2F891-7E8E-453B-9FEF-ADCBEB7795DD}
{4F06C65B-22CC-466E-B3FD-3F695DD38191} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {4F06C65B-22CC-466E-B3FD-3F695DD38191} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{7AB942D5-D139-4F9F-9342-71534AA3A5AC} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {7AB942D5-D139-4F9F-9342-71534AA3A5AC} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{BD964040-90B2-4179-A5EB-5830F5C7E073} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {BD964040-90B2-4179-A5EB-5830F5C7E073} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1} = {4F06C65B-22CC-466E-B3FD-3F695DD38191} {A4DFDE21-1931-46B5-8381-36B6EB6E51E1} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2} = {4F06C65B-22CC-466E-B3FD-3F695DD38191} {6EE4D85F-6035-4AB5-B650-9E3D3A2AA8D2} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{BB1124C0-79F4-4E72-8854-945B3F0AD76D} = {4F06C65B-22CC-466E-B3FD-3F695DD38191} {BB1124C0-79F4-4E72-8854-945B3F0AD76D} = {4F06C65B-22CC-466E-B3FD-3F695DD38191}
{E22445B9-7039-4DA1-B547-BAB437D6D2B3} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {E22445B9-7039-4DA1-B547-BAB437D6D2B3} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{116D9D69-ED2C-4F23-9445-3981D8EA0EB7} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {116D9D69-ED2C-4F23-9445-3981D8EA0EB7} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{B07A1763-1B37-4416-8F0C-B938C175A56D} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {B07A1763-1B37-4416-8F0C-B938C175A56D} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{0F87C16B-8E91-4B25-B501-AD81F8EC599E} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {0F87C16B-8E91-4B25-B501-AD81F8EC599E} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {BF059F48-C8C0-4E17-AC4F-A1D1ADE405C7} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{6679A09F-124A-470A-81F5-A94302CEFEE4} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {6679A09F-124A-470A-81F5-A94302CEFEE4} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{177B6CD3-1690-416D-9B37-A821093DEFBD} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {177B6CD3-1690-416D-9B37-A821093DEFBD} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{7EE9651C-17B0-4343-A2ED-92439F8C9019} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {7EE9651C-17B0-4343-A2ED-92439F8C9019} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{FD2DDD48-8F84-4924-BBAF-52080AB32267} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {FD2DDD48-8F84-4924-BBAF-52080AB32267} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{23536755-4F00-4929-9C5E-D4CABD1CC513} = {BD964040-90B2-4179-A5EB-5830F5C7E073} {23536755-4F00-4929-9C5E-D4CABD1CC513} = {BD964040-90B2-4179-A5EB-5830F5C7E073}
{80A418EB-6149-4684-80EF-D8574B91FE2B} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {80A418EB-6149-4684-80EF-D8574B91FE2B} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{986B0610-4AC3-499A-AB81-DF15EA06F4D1} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {986B0610-4AC3-499A-AB81-DF15EA06F4D1} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{53E90646-2933-4381-9386-6BC6ED16E71A} = {7EE9651C-17B0-4343-A2ED-92439F8C9019} {53E90646-2933-4381-9386-6BC6ED16E71A} = {7EE9651C-17B0-4343-A2ED-92439F8C9019}
{720120B4-76F6-4701-9426-611BB8F84515} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {720120B4-76F6-4701-9426-611BB8F84515} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{D89ECB96-3349-4E77-B884-C18B30289D0D} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {D89ECB96-3349-4E77-B884-C18B30289D0D} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{39B77454-52AB-43BE-AB33-7680719415A6} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {39B77454-52AB-43BE-AB33-7680719415A6} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1}
{99B60A42-29DA-4D91-9255-B90F53BC6D6E} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} {99B60A42-29DA-4D91-9255-B90F53BC6D6E} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}
{70C4FA43-0526-48E3-B852-A21395502604} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} {70C4FA43-0526-48E3-B852-A21395502604} = {89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}
{B3181D37-F379-4E16-8621-5E739C519393} = {FD2DDD48-8F84-4924-BBAF-52080AB32267} {B3181D37-F379-4E16-8621-5E739C519393} = {FD2DDD48-8F84-4924-BBAF-52080AB32267}
{AD1C3335-A2A1-49C1-A6DB-817C54859B65} = {7EE9651C-17B0-4343-A2ED-92439F8C9019} {AD1C3335-A2A1-49C1-A6DB-817C54859B65} = {7EE9651C-17B0-4343-A2ED-92439F8C9019}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {785FFF4D-BC59-499E-88A3-7CB7A7667228} SolutionGuid = {785FFF4D-BC59-499E-88A3-7CB7A7667228}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

541
aspnet-core/LINGYUN.MicroService.Messages.sln

@ -1,267 +1,274 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22 VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{E7A821D8-85B5-4098-897D-5A814BD8131D}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{E7A821D8-85B5-4098-897D-5A814BD8131D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{C00828FB-E7D5-4086-BA50-02022594AB73}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{C00828FB-E7D5-4086-BA50-02022594AB73}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime", "modules\common\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj", "{07BCD006-F2F2-4685-8887-E8BEB18745FD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime", "modules\common\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj", "{07BCD006-F2F2-4685-8887-E8BEB18745FD}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime.SignalR", "modules\common\LINGYUN.Abp.RealTime.SignalR\LINGYUN.Abp.RealTime.SignalR.csproj", "{60E37E86-ACA6-4464-9592-B0D8EFB629BD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime.SignalR", "modules\common\LINGYUN.Abp.RealTime.SignalR\LINGYUN.Abp.RealTime.SignalR.csproj", "{60E37E86-ACA6-4464-9592-B0D8EFB629BD}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.SignalR.JwtToken", "modules\common\LINGYUN.Abp.AspNetCore.SignalR\LINGYUN.Abp.AspNetCore.SignalR.JwtToken.csproj", "{85B39FCE-6778-497C-A12E-6777C7FE651A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.SignalR.JwtToken", "modules\common\LINGYUN.Abp.AspNetCore.SignalR\LINGYUN.Abp.AspNetCore.SignalR.JwtToken.csproj", "{85B39FCE-6778-497C-A12E-6777C7FE651A}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json", "modules\common\LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json\LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json.csproj", "{8C973655-DF59-40D8-B206-82344575A8CF}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json", "modules\common\LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json\LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json.csproj", "{8C973655-DF59-40D8-B206-82344575A8CF}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM", "modules\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj", "{55B9F554-1754-4EF9-B325-B33421D4F6A9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM", "modules\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj", "{55B9F554-1754-4EF9-B325-B33421D4F6A9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM.SignalR", "modules\common\LINGYUN.Abp.IM.SignalR\LINGYUN.Abp.IM.SignalR.csproj", "{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM.SignalR", "modules\common\LINGYUN.Abp.IM.SignalR\LINGYUN.Abp.IM.SignalR.csproj", "{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications", "modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj", "{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications", "modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj", "{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.SignalR", "modules\common\LINGYUN.Abp.Notifications.SignalR\LINGYUN.Abp.Notifications.SignalR.csproj", "{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.SignalR", "modules\common\LINGYUN.Abp.Notifications.SignalR\LINGYUN.Abp.Notifications.SignalR.csproj", "{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain.Shared", "modules\message\LINGYUN.Abp.MessageService.Domain.Shared\LINGYUN.Abp.MessageService.Domain.Shared.csproj", "{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain.Shared", "modules\message\LINGYUN.Abp.MessageService.Domain.Shared\LINGYUN.Abp.MessageService.Domain.Shared.csproj", "{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain", "modules\message\LINGYUN.Abp.MessageService.Domain\LINGYUN.Abp.MessageService.Domain.csproj", "{2094F03B-FC73-4B3F-88CB-F7951E22FED5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain", "modules\message\LINGYUN.Abp.MessageService.Domain\LINGYUN.Abp.MessageService.Domain.csproj", "{2094F03B-FC73-4B3F-88CB-F7951E22FED5}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore", "modules\message\LINGYUN.Abp.MessageService.EntityFrameworkCore\LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj", "{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore", "modules\message\LINGYUN.Abp.MessageService.EntityFrameworkCore\LINGYUN.Abp.MessageService.EntityFrameworkCore.csproj", "{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application.Contracts", "modules\message\LINGYUN.Abp.MessageService.Application.Contracts\LINGYUN.Abp.MessageService.Application.Contracts.csproj", "{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application.Contracts", "modules\message\LINGYUN.Abp.MessageService.Application.Contracts\LINGYUN.Abp.MessageService.Application.Contracts.csproj", "{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application", "modules\message\LINGYUN.Abp.MessageService.Application\LINGYUN.Abp.MessageService.Application.csproj", "{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Application", "modules\message\LINGYUN.Abp.MessageService.Application\LINGYUN.Abp.MessageService.Application.csproj", "{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi", "modules\message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj", "{54395254-0383-4932-B2E4-50932DAD7D10}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi", "modules\message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj", "{54395254-0383-4932-B2E4-50932DAD7D10}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi.Client", "modules\message\LINGYUN.Abp.MessageService.HttpApi.Client\LINGYUN.Abp.MessageService.HttpApi.Client.csproj", "{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi.Client", "modules\message\LINGYUN.Abp.MessageService.HttpApi.Client\LINGYUN.Abp.MessageService.HttpApi.Client.csproj", "{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi.Host", "services\messages\LINGYUN.Abp.MessageService.HttpApi.Host\LINGYUN.Abp.MessageService.HttpApi.Host.csproj", "{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.HttpApi.Host", "services\messages\LINGYUN.Abp.MessageService.HttpApi.Host\LINGYUN.Abp.MessageService.HttpApi.Host.csproj", "{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{78164C5C-63B9-4FB6-ACC9-6496E236C946}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{78164C5C-63B9-4FB6-ACC9-6496E236C946}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation", "modules\common\LINGYUN.Abp.Features.LimitValidation\LINGYUN.Abp.Features.LimitValidation.csproj", "{93971F1F-F6AC-4F83-8119-21260FCE2828}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Features.LimitValidation", "modules\common\LINGYUN.Abp.Features.LimitValidation\LINGYUN.Abp.Features.LimitValidation.csproj", "{93971F1F-F6AC-4F83-8119-21260FCE2828}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{3B87330F-A303-4413-B653-1C9536C74109}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{3B87330F-A303-4413-B653-1C9536C74109}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "message", "message", "{D58F1DF5-2DFE-40A2-B136-7606D4CDE903}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "message", "message", "{D58F1DF5-2DFE-40A2-B136-7606D4CDE903}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{3A4601FE-B091-43A3-AEE6-6440BB37B277}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj", "{3A4601FE-B091-43A3-AEE6-6440BB37B277}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms", "modules\common\LINGYUN.Abp.Notifications.Sms\LINGYUN.Abp.Notifications.Sms.csproj", "{454059F7-D087-439A-A724-80BDFE94776F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms", "modules\common\LINGYUN.Abp.Notifications.Sms\LINGYUN.Abp.Notifications.Sms.csproj", "{454059F7-D087-439A-A724-80BDFE94776F}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj", "{64E2622A-611D-4056-9497-0B52A91DC59C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram", "modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj", "{64E2622A-611D-4056-9497-0B52A91DC59C}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{42800C56-9473-4B96-BF29-1B0F25C867F4}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{42800C56-9473-4B96-BF29-1B0F25C867F4}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms.Tests", "tests\LINGYUN.Abp.Notifications.Sms.Tests\LINGYUN.Abp.Notifications.Sms.Tests.csproj", "{5714481A-BDF5-4860-9158-3B18D3018EC5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Sms.Tests", "tests\LINGYUN.Abp.Notifications.Sms.Tests\LINGYUN.Abp.Notifications.Sms.Tests.csproj", "{5714481A-BDF5-4860-9158-3B18D3018EC5}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{B5E23AED-3068-4CFE-84B0-3B7725665506}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{B5E23AED-3068-4CFE-84B0-3B7725665506}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Tests", "tests\LINGYUN.Abp.Notifications.Tests\LINGYUN.Abp.Notifications.Tests.csproj", "{E5257008-A0AD-473F-91B0-864FC601B84B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.Tests", "tests\LINGYUN.Abp.Notifications.Tests\LINGYUN.Abp.Notifications.Tests.csproj", "{E5257008-A0AD-473F-91B0-864FC601B84B}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests", "tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests.csproj", "{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests", "tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests\LINGYUN.Abp.Notifications.WeChat.MiniProgram.Tests.csproj", "{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{25267137-08BE-44A6-9F7E-7783CC8C62E8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.EntityFrameworkCore.Tests\LINGYUN.Abp.EntityFrameworkCore.Tests.csproj", "{25267137-08BE-44A6-9F7E-7783CC8C62E8}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj", "{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests", "tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests\LINGYUN.Abp.MessageService.EntityFrameworkCore.Tests.csproj", "{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain.Tests", "tests\LINGYUN.Abp.MessageService.Domain.Tests\LINGYUN.Abp.MessageService.Domain.Tests.csproj", "{097319B9-D062-4A54-8F8C-001C180E2CB3}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MessageService.Domain.Tests", "tests\LINGYUN.Abp.MessageService.Domain.Tests\LINGYUN.Abp.MessageService.Domain.Tests.csproj", "{097319B9-D062-4A54-8F8C-001C180E2CB3}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundJobs.Hangfire", "modules\common\LINGYUN.Abp.BackgroundJobs.Hangfire\LINGYUN.Abp.BackgroundJobs.Hangfire.csproj", "{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundJobs.Hangfire", "modules\common\LINGYUN.Abp.BackgroundJobs.Hangfire\LINGYUN.Abp.BackgroundJobs.Hangfire.csproj", "{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Storage.MySql", "modules\common\LINGYUN.Abp.Hangfire.MySqlStorage\LINGYUN.Abp.Hangfire.Storage.MySql.csproj", "{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Storage.MySql", "modules\common\LINGYUN.Abp.Hangfire.MySqlStorage\LINGYUN.Abp.Hangfire.Storage.MySql.csproj", "{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Dashboard", "modules\common\LINGYUN.Abp.Hangfire.Dashboard\LINGYUN.Abp.Hangfire.Dashboard.csproj", "{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Hangfire.Dashboard", "modules\common\LINGYUN.Abp.Hangfire.Dashboard\LINGYUN.Abp.Hangfire.Dashboard.csproj", "{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundWorkers.Hangfire", "modules\common\LINGYUN.Abp.BackgroundWorkers.Hangfire\LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj", "{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.BackgroundWorkers.Hangfire", "modules\common\LINGYUN.Abp.BackgroundWorkers.Hangfire\LINGYUN.Abp.BackgroundWorkers.Hangfire.csproj", "{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{C49B50D4-5D63-47E6-82F7-E742181CF9DE}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.EventBus.CAP", "modules\common\LINGYUN.Abp.EventBus.CAP\LINGYUN.Abp.EventBus.CAP.csproj", "{C49B50D4-5D63-47E6-82F7-E742181CF9DE}"
EndProject EndProject
Global Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.WeChat", "modules\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj", "{DC71289C-18A7-4E4B-A653-E66941EB19AE}"
GlobalSection(SolutionConfigurationPlatforms) = preSolution EndProject
Debug|Any CPU = Debug|Any CPU Global
Release|Any CPU = Release|Any CPU GlobalSection(SolutionConfigurationPlatforms) = preSolution
EndGlobalSection Debug|Any CPU = Debug|Any CPU
GlobalSection(ProjectConfigurationPlatforms) = postSolution Release|Any CPU = Release|Any CPU
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU EndGlobalSection
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.Build.0 = Debug|Any CPU GlobalSection(ProjectConfigurationPlatforms) = postSolution
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.ActiveCfg = Release|Any CPU {07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.Build.0 = Release|Any CPU {07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.Build.0 = Release|Any CPU
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.Build.0 = Release|Any CPU {60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.Build.0 = Debug|Any CPU {60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.Build.0 = Release|Any CPU
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.ActiveCfg = Release|Any CPU {85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.Build.0 = Release|Any CPU {85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.Build.0 = Release|Any CPU
{8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.ActiveCfg = Release|Any CPU {8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.Build.0 = Release|Any CPU {8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.Build.0 = Release|Any CPU
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.ActiveCfg = Release|Any CPU {55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.Build.0 = Release|Any CPU {55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU {55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.Build.0 = Release|Any CPU
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU {7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.Build.0 = Release|Any CPU {7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.Build.0 = Debug|Any CPU {7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.Build.0 = Release|Any CPU
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.ActiveCfg = Release|Any CPU {C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.Build.0 = Release|Any CPU {C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.Build.0 = Debug|Any CPU {C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.Build.0 = Release|Any CPU
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.ActiveCfg = Release|Any CPU {3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.Build.0 = Release|Any CPU {3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.Build.0 = Debug|Any CPU
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.ActiveCfg = Release|Any CPU
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU {3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.Build.0 = Release|Any CPU
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU {50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.Build.0 = Release|Any CPU {50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.Build.0 = Debug|Any CPU {50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.Build.0 = Release|Any CPU
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.ActiveCfg = Release|Any CPU {2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.Build.0 = Release|Any CPU {2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.Build.0 = Debug|Any CPU {2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.Build.0 = Release|Any CPU
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.ActiveCfg = Release|Any CPU {554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.Build.0 = Release|Any CPU {554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.Build.0 = Release|Any CPU
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.ActiveCfg = Release|Any CPU {92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.Build.0 = Release|Any CPU {92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.Build.0 = Debug|Any CPU {92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.Build.0 = Release|Any CPU
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.Build.0 = Release|Any CPU {DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.Build.0 = Release|Any CPU
{54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.ActiveCfg = Release|Any CPU {54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.Build.0 = Release|Any CPU {54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.Build.0 = Debug|Any CPU {54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.Build.0 = Release|Any CPU
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.ActiveCfg = Release|Any CPU {3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.Build.0 = Release|Any CPU {3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.Build.0 = Release|Any CPU
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.ActiveCfg = Release|Any CPU {8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.Build.0 = Release|Any CPU {8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.Build.0 = Debug|Any CPU {8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.Build.0 = Release|Any CPU
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.ActiveCfg = Release|Any CPU {93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.Build.0 = Release|Any CPU {93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.Build.0 = Debug|Any CPU {93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.Build.0 = Release|Any CPU
{3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.Build.0 = Release|Any CPU {3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.Build.0 = Release|Any CPU
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.Build.0 = Release|Any CPU {3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.Build.0 = Debug|Any CPU
{454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.ActiveCfg = Release|Any CPU
{454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.Build.0 = Debug|Any CPU {3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.Build.0 = Release|Any CPU
{454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.ActiveCfg = Release|Any CPU {454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.Build.0 = Release|Any CPU {454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.Build.0 = Debug|Any CPU {454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.Build.0 = Release|Any CPU
{64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.ActiveCfg = Release|Any CPU {64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.Build.0 = Release|Any CPU {64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU {64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.Build.0 = Release|Any CPU
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU {5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.Build.0 = Release|Any CPU {5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.Build.0 = Debug|Any CPU {5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.Build.0 = Release|Any CPU
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.ActiveCfg = Release|Any CPU {B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.Build.0 = Release|Any CPU {B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.Build.0 = Debug|Any CPU {B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.Build.0 = Release|Any CPU
{E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.ActiveCfg = Release|Any CPU {E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.Build.0 = Release|Any CPU {E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU {E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.Build.0 = Release|Any CPU
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.Build.0 = Release|Any CPU {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.Build.0 = Debug|Any CPU {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.Build.0 = Release|Any CPU
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.ActiveCfg = Release|Any CPU {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.Build.0 = Release|Any CPU {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU {25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.Build.0 = Release|Any CPU
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.Build.0 = Release|Any CPU {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.Build.0 = Release|Any CPU
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU {097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.Build.0 = Release|Any CPU {097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.Build.0 = Debug|Any CPU {097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.Build.0 = Release|Any CPU
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.ActiveCfg = Release|Any CPU {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.Build.0 = Release|Any CPU {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.Build.0 = Debug|Any CPU {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.Build.0 = Release|Any CPU
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.ActiveCfg = Release|Any CPU {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.Build.0 = Release|Any CPU {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.Build.0 = Release|Any CPU
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.Build.0 = Release|Any CPU {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.Build.0 = Debug|Any CPU {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.Build.0 = Release|Any CPU
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.ActiveCfg = Release|Any CPU {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.Build.0 = Release|Any CPU {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU {32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.Build.0 = Release|Any CPU
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.Build.0 = Release|Any CPU {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
GlobalSection(SolutionProperties) = preSolution {C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.Build.0 = Release|Any CPU
HideSolutionNode = FALSE {DC71289C-18A7-4E4B-A653-E66941EB19AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
EndGlobalSection {DC71289C-18A7-4E4B-A653-E66941EB19AE}.Debug|Any CPU.Build.0 = Debug|Any CPU
GlobalSection(NestedProjects) = preSolution {DC71289C-18A7-4E4B-A653-E66941EB19AE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C00828FB-E7D5-4086-BA50-02022594AB73} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} {DC71289C-18A7-4E4B-A653-E66941EB19AE}.Release|Any CPU.Build.0 = Release|Any CPU
{07BCD006-F2F2-4685-8887-E8BEB18745FD} = {C00828FB-E7D5-4086-BA50-02022594AB73} EndGlobalSection
{60E37E86-ACA6-4464-9592-B0D8EFB629BD} = {C00828FB-E7D5-4086-BA50-02022594AB73} GlobalSection(SolutionProperties) = preSolution
{85B39FCE-6778-497C-A12E-6777C7FE651A} = {C00828FB-E7D5-4086-BA50-02022594AB73} HideSolutionNode = FALSE
{8C973655-DF59-40D8-B206-82344575A8CF} = {C00828FB-E7D5-4086-BA50-02022594AB73} EndGlobalSection
{55B9F554-1754-4EF9-B325-B33421D4F6A9} = {C00828FB-E7D5-4086-BA50-02022594AB73} GlobalSection(NestedProjects) = preSolution
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1} = {C00828FB-E7D5-4086-BA50-02022594AB73} {C00828FB-E7D5-4086-BA50-02022594AB73} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1} = {C00828FB-E7D5-4086-BA50-02022594AB73} {07BCD006-F2F2-4685-8887-E8BEB18745FD} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519} = {C00828FB-E7D5-4086-BA50-02022594AB73} {60E37E86-ACA6-4464-9592-B0D8EFB629BD} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {85B39FCE-6778-497C-A12E-6777C7FE651A} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{2094F03B-FC73-4B3F-88CB-F7951E22FED5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {8C973655-DF59-40D8-B206-82344575A8CF} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {55B9F554-1754-4EF9-B325-B33421D4F6A9} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {7AC8C076-87E2-48ED-8AB3-C1F737F55DD1} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{54395254-0383-4932-B2E4-50932DAD7D10} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {3531699A-9FF9-4F8C-BEAD-9D114FE8E519} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} {50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D} = {E7A821D8-85B5-4098-897D-5A814BD8131D} {2094F03B-FC73-4B3F-88CB-F7951E22FED5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{78164C5C-63B9-4FB6-ACC9-6496E236C946} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} {554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{93971F1F-F6AC-4F83-8119-21260FCE2828} = {C00828FB-E7D5-4086-BA50-02022594AB73} {92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{3B87330F-A303-4413-B653-1C9536C74109} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} {DB8CE5AF-1888-4C51-97C3-2188BE50FAF9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{D58F1DF5-2DFE-40A2-B136-7606D4CDE903} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} {54395254-0383-4932-B2E4-50932DAD7D10} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{3A4601FE-B091-43A3-AEE6-6440BB37B277} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} {3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903}
{454059F7-D087-439A-A724-80BDFE94776F} = {C00828FB-E7D5-4086-BA50-02022594AB73} {8168B7B4-9F6B-4658-A28C-D0F9D10AB93D} = {E7A821D8-85B5-4098-897D-5A814BD8131D}
{64E2622A-611D-4056-9497-0B52A91DC59C} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} {78164C5C-63B9-4FB6-ACC9-6496E236C946} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}
{5714481A-BDF5-4860-9158-3B18D3018EC5} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {93971F1F-F6AC-4F83-8119-21260FCE2828} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{B5E23AED-3068-4CFE-84B0-3B7725665506} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {3B87330F-A303-4413-B653-1C9536C74109} = {78164C5C-63B9-4FB6-ACC9-6496E236C946}
{E5257008-A0AD-473F-91B0-864FC601B84B} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {3A4601FE-B091-43A3-AEE6-6440BB37B277} = {78164C5C-63B9-4FB6-ACC9-6496E236C946}
{25267137-08BE-44A6-9F7E-7783CC8C62E8} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {454059F7-D087-439A-A724-80BDFE94776F} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {64E2622A-611D-4056-9497-0B52A91DC59C} = {78164C5C-63B9-4FB6-ACC9-6496E236C946}
{097319B9-D062-4A54-8F8C-001C180E2CB3} = {42800C56-9473-4B96-BF29-1B0F25C867F4} {5714481A-BDF5-4860-9158-3B18D3018EC5} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97} = {C00828FB-E7D5-4086-BA50-02022594AB73} {B5E23AED-3068-4CFE-84B0-3B7725665506} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4} = {C00828FB-E7D5-4086-BA50-02022594AB73} {E5257008-A0AD-473F-91B0-864FC601B84B} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48} = {C00828FB-E7D5-4086-BA50-02022594AB73} {DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058} = {C00828FB-E7D5-4086-BA50-02022594AB73} {25267137-08BE-44A6-9F7E-7783CC8C62E8} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
{C49B50D4-5D63-47E6-82F7-E742181CF9DE} = {C00828FB-E7D5-4086-BA50-02022594AB73} {CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
EndGlobalSection {097319B9-D062-4A54-8F8C-001C180E2CB3} = {42800C56-9473-4B96-BF29-1B0F25C867F4}
GlobalSection(ExtensibilityGlobals) = postSolution {737EF17D-477F-4C73-A4CC-0DA6CBD3BB97} = {C00828FB-E7D5-4086-BA50-02022594AB73}
SolutionGuid = {6238659A-7267-49B9-A499-8746BDEED6B8} {0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4} = {C00828FB-E7D5-4086-BA50-02022594AB73}
EndGlobalSection {05DCBA6B-480A-4D2F-9855-F66F5B7F3A48} = {C00828FB-E7D5-4086-BA50-02022594AB73}
EndGlobal {32D4DB5D-74D1-4166-85EA-B2D8F14B8058} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{C49B50D4-5D63-47E6-82F7-E742181CF9DE} = {C00828FB-E7D5-4086-BA50-02022594AB73}
{DC71289C-18A7-4E4B-A653-E66941EB19AE} = {78164C5C-63B9-4FB6-ACC9-6496E236C946}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6238659A-7267-49B9-A499-8746BDEED6B8}
EndGlobalSection
EndGlobal

1
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN.Abp.IdentityServer.WeChat.csproj

@ -17,6 +17,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj" />
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj" /> <ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj" />
<ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj" /> <ProjectReference Include="..\..\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj" />
</ItemGroup> </ItemGroup>

110
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/AbpIdentityServerWeChatModule.cs

@ -1,54 +1,56 @@
using LINGYUN.Abp.IdentityServer.WeChat.MiniProgram; using LINGYUN.Abp.Identity.WeChat;
using LINGYUN.Abp.IdentityServer.WeChat.Official; using LINGYUN.Abp.IdentityServer.WeChat.MiniProgram;
using LINGYUN.Abp.WeChat.MiniProgram; using LINGYUN.Abp.IdentityServer.WeChat.Official;
using LINGYUN.Abp.WeChat.Official; using LINGYUN.Abp.WeChat.MiniProgram;
using Microsoft.AspNetCore.Authentication; using LINGYUN.Abp.WeChat.Official;
using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Authentication;
using Volo.Abp.IdentityServer; using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.IdentityServer;
using Volo.Abp.Localization; using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Localization;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.IdentityServer.WeChat
{ namespace LINGYUN.Abp.IdentityServer.WeChat
[DependsOn( {
typeof(AbpWeChatOfficialModule), [DependsOn(
typeof(AbpWeChatMiniProgramModule), typeof(AbpWeChatOfficialModule),
typeof(AbpIdentityServerDomainModule))] typeof(AbpWeChatMiniProgramModule),
public class AbpIdentityServerWeChatModule : AbpModule typeof(AbpIdentityWeChatModule),
{ typeof(AbpIdentityServerDomainModule))]
public override void PreConfigureServices(ServiceConfigurationContext context) public class AbpIdentityServerWeChatModule : AbpModule
{ {
var configuration = context.Services.GetConfiguration(); public override void PreConfigureServices(ServiceConfigurationContext context)
{
PreConfigure<IIdentityServerBuilder>(builder => var configuration = context.Services.GetConfiguration();
{
builder.AddProfileService<WeChatMiniProgramProfileService>(); PreConfigure<IIdentityServerBuilder>(builder =>
{
// TODO: 两个类型不通用配置项,不然只需要一个 builder.AddProfileService<WeChatMiniProgramProfileService>();
builder.AddExtensionGrantValidator<WeChatMiniProgramGrantValidator>();
builder.AddExtensionGrantValidator<WeChatOfficialGrantValidator>(); // TODO: 两个类型不通用配置项,不然只需要一个
}); builder.AddExtensionGrantValidator<WeChatMiniProgramGrantValidator>();
} builder.AddExtensionGrantValidator<WeChatOfficialGrantValidator>();
});
public override void ConfigureServices(ServiceConfigurationContext context) }
{
Configure<AbpVirtualFileSystemOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.FileSets.AddEmbedded<AbpIdentityServerWeChatModule>(); Configure<AbpVirtualFileSystemOptions>(options =>
}); {
options.FileSets.AddEmbedded<AbpIdentityServerWeChatModule>();
Configure<AbpLocalizationOptions>(options => });
{
options.Resources Configure<AbpLocalizationOptions>(options =>
.Get<AbpIdentityServerResource>() {
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/WeChat/Localization"); options.Resources
}); .Get<AbpIdentityServerResource>()
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/WeChat/Localization");
context.Services });
.AddAuthentication()
.AddWeChat(); context.Services
} .AddAuthentication()
} .AddWeChat();
} }
}
}

94
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/MiniProgram/WeChatMiniProgramGrantValidator.cs

@ -1,47 +1,47 @@
using IdentityServer4.Services; using IdentityServer4.Services;
using LINGYUN.Abp.WeChat.MiniProgram; using LINGYUN.Abp.WeChat.MiniProgram;
using LINGYUN.Abp.WeChat.OpenId; using LINGYUN.Abp.WeChat.OpenId;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.IdentityServer.Localization;
using IdentityUser = Volo.Abp.Identity.IdentityUser; using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram
{ {
/// <summary> /// <summary>
/// 对于小程序绑定用户的扩展授权验证器 /// 对于小程序绑定用户的扩展授权验证器
/// </summary> /// </summary>
public class WeChatMiniProgramGrantValidator : WeChatGrantValidator public class WeChatMiniProgramGrantValidator : WeChatGrantValidator
{ {
public override string GrantType => AbpWeChatMiniProgramConsts.GrantType; public override string GrantType => AbpWeChatMiniProgramConsts.GrantType;
public override string LoginProviderKey => AbpWeChatMiniProgramConsts.ProviderKey; public override string LoginProvider => AbpWeChatMiniProgramConsts.ProviderName;
public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod; public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod;
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; }
public WeChatMiniProgramGrantValidator( public WeChatMiniProgramGrantValidator(
IEventService eventService, IEventService eventService,
IWeChatOpenIdFinder weChatOpenIdFinder, IWeChatOpenIdFinder weChatOpenIdFinder,
UserManager<IdentityUser> userManager, UserManager<IdentityUser> userManager,
IIdentityUserRepository userRepository, IIdentityUserRepository userRepository,
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer,
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer,
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory)
: base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) : base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer)
{ {
MiniProgramOptionsFactory = miniProgramOptionsFactory; MiniProgramOptionsFactory = miniProgramOptionsFactory;
} }
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) protected override async Task<WeChatOpenId> FindOpenIdAsync(string code)
{ {
var options = await MiniProgramOptionsFactory.CreateAsync(); var options = await MiniProgramOptionsFactory.CreateAsync();
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret);
} }
} }
} }

92
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialGrantValidator.cs

@ -1,46 +1,46 @@
using IdentityServer4.Services; using IdentityServer4.Services;
using LINGYUN.Abp.WeChat.Official; using LINGYUN.Abp.WeChat.Official;
using LINGYUN.Abp.WeChat.OpenId; using LINGYUN.Abp.WeChat.OpenId;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.IdentityServer.Localization;
using IdentityUser = Volo.Abp.Identity.IdentityUser; using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.WeChat.Official namespace LINGYUN.Abp.IdentityServer.WeChat.Official
{ {
/// <summary> /// <summary>
/// 对于公众平台绑定用户的扩展授权验证器 /// 对于公众平台绑定用户的扩展授权验证器
/// </summary> /// </summary>
public class WeChatOfficialGrantValidator : WeChatGrantValidator public class WeChatOfficialGrantValidator : WeChatGrantValidator
{ {
public override string GrantType => AbpWeChatOfficialConsts.GrantType; public override string GrantType => AbpWeChatOfficialConsts.GrantType;
public override string LoginProviderKey => AbpWeChatOfficialConsts.ProviderKey; public override string LoginProvider => AbpWeChatOfficialConsts.ProviderName;
public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod; public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod;
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; } protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; }
public WeChatOfficialGrantValidator( public WeChatOfficialGrantValidator(
IEventService eventService, IEventService eventService,
IWeChatOpenIdFinder weChatOpenIdFinder, IWeChatOpenIdFinder weChatOpenIdFinder,
UserManager<IdentityUser> userManager, UserManager<IdentityUser> userManager,
IIdentityUserRepository userRepository, IIdentityUserRepository userRepository,
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer,
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer,
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory) AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory)
: base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) : base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer)
{ {
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory; WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory;
} }
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) protected override async Task<WeChatOpenId> FindOpenIdAsync(string code)
{ {
var options = await WeChatOfficialOptionsFactory.CreateAsync(); var options = await WeChatOfficialOptionsFactory.CreateAsync();
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret);
} }
} }
} }

142
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/Official/WeChatOfficialOAuthConsts.cs

@ -1,71 +1,71 @@
using LINGYUN.Abp.WeChat; using LINGYUN.Abp.WeChat;
using LINGYUN.Abp.WeChat.Official; using LINGYUN.Abp.WeChat.Official;
namespace LINGYUN.Abp.IdentityServer.WeChat.Official namespace LINGYUN.Abp.IdentityServer.WeChat.Official
{ {
/// <summary> /// <summary>
/// 与微信公众号认证相关的静态(可变)常量 /// 与微信公众号认证相关的静态(可变)常量
/// </summary> /// </summary>
public static class WeChatOfficialOAuthConsts public static class WeChatOfficialOAuthConsts
{ {
/// <summary> /// <summary>
/// 微信个人信息标识 /// 微信个人信息标识
/// </summary> /// </summary>
public static string ProfileKey { get; set; } = "wechat.profile"; public static string ProfileKey { get; set; } = "wechat.profile";
/// <summary> /// <summary>
/// 微信提供者标识 /// 微信提供者标识
/// </summary> /// </summary>
public static string ProviderKey => AbpWeChatOfficialConsts.ProviderKey; public static string ProviderKey => AbpWeChatOfficialConsts.ProviderName;
/// <summary> /// <summary>
/// 微信提供者显示名称 /// 微信提供者显示名称
/// </summary> /// </summary>
public static string DisplayName => AbpWeChatGlobalConsts.DisplayName; public static string DisplayName => AbpWeChatGlobalConsts.DisplayName;
/// <summary> /// <summary>
/// 回调地址 /// 回调地址
/// </summary> /// </summary>
public static string CallbackPath { get; set; } = "/signin-wechat"; public static string CallbackPath { get; set; } = "/signin-wechat";
/// <summary> /// <summary>
/// 微信客户端外的网页登录 /// 微信客户端外的网页登录
/// </summary> /// </summary>
public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect"; public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect";
/// <summary> /// <summary>
/// 微信客户端内的网页登录 /// 微信客户端内的网页登录
/// </summary> /// </summary>
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize";
/// <summary> /// <summary>
/// 用户允许授权后通过返回的code换取access_token地址 /// 用户允许授权后通过返回的code换取access_token地址
/// </summary> /// </summary>
public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token"; public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token";
/// <summary> /// <summary>
/// 使用access_token获取用户个人信息地址 /// 使用access_token获取用户个人信息地址
/// </summary> /// </summary>
public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo";
/// <summary> /// <summary>
/// 弹出授权页面,可通过openid拿到昵称、性别、所在地。 /// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
/// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 /// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
/// <br /> /// <br />
/// <br /> /// <br />
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/> /// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。 /// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
/// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息 /// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
/// </remarks> /// </remarks>
public const string UserInfoScope = "snsapi_userinfo"; public const string UserInfoScope = "snsapi_userinfo";
/// <summary> /// <summary>
/// 不弹出授权页面,直接跳转,只能获取用户openid /// 不弹出授权页面,直接跳转,只能获取用户openid
/// <br /> /// <br />
/// <br /> /// <br />
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/> /// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。 /// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
/// 用户感知的就是直接进入了回调页(往往是业务页面) /// 用户感知的就是直接进入了回调页(往往是业务页面)
/// </remarks> /// </remarks>
public const string LoginScope = "snsapi_login"; public const string LoginScope = "snsapi_login";
} }
} }

259
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChat/LINGYUN/Abp/IdentityServer/WeChat/WeChatGrantValidator.cs

@ -1,116 +1,143 @@
 
using IdentityModel; using IdentityModel;
using IdentityServer4.Events; using IdentityServer4.Events;
using IdentityServer4.Models; using IdentityServer4.Models;
using IdentityServer4.Services; using IdentityServer4.Services;
using IdentityServer4.Validation; using IdentityServer4.Validation;
using LINGYUN.Abp.WeChat; using LINGYUN.Abp.WeChat;
using LINGYUN.Abp.WeChat.OpenId; using LINGYUN.Abp.WeChat.OpenId;
using LINGYUN.Abp.WeChat.Security.Claims; using LINGYUN.Abp.WeChat.Security.Claims;
using Microsoft.AspNetCore.Identity; using LINGYUN.Abp.WeChat.Settings;
using Microsoft.Extensions.Localization; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging;
using System; using Microsoft.Extensions.Logging.Abstractions;
using System.Collections.Generic; using System;
using System.Security.Claims; using System.Collections.Generic;
using System.Threading.Tasks; using System.Security.Claims;
using Volo.Abp.Identity; using System.Threading.Tasks;
using Volo.Abp.IdentityServer.Localization; using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims; using Volo.Abp.Guids;
using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource; using Volo.Abp.Identity;
using IdentityUser = Volo.Abp.Identity.IdentityUser; using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.MultiTenancy;
namespace LINGYUN.Abp.IdentityServer.WeChat using Volo.Abp.Security.Claims;
{ using Volo.Abp.Settings;
public abstract class WeChatGrantValidator : IExtensionGrantValidator using Volo.Abp.Uow;
{ using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource;
public abstract string GrantType { get; } using IdentityUser = Volo.Abp.Identity.IdentityUser;
public abstract string LoginProviderKey { get; }
public abstract string AuthenticationMethod { get; } namespace LINGYUN.Abp.IdentityServer.WeChat
{
public ILogger Logger { protected get; set; } public abstract class WeChatGrantValidator : IExtensionGrantValidator
protected IEventService EventService { get; } {
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } public abstract string GrantType { get; }
protected IIdentityUserRepository UserRepository { get; } public abstract string LoginProvider { get; }
protected UserManager<IdentityUser> UserManager { get; } public abstract string AuthenticationMethod { get; }
protected IStringLocalizer<IdentityResource> IdentityLocalizer { get; }
protected IStringLocalizer<AbpIdentityServerResource> IdentityServerLocalizer { get; } public ILogger Logger { protected get; set; }
public IAbpLazyServiceProvider ServiceProvider { protected get; set; }
public WeChatGrantValidator(
IEventService eventService, protected IEventService EventService { get; }
IWeChatOpenIdFinder weChatOpenIdFinder, protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; }
UserManager<IdentityUser> userManager, protected IIdentityUserRepository UserRepository { get; }
IIdentityUserRepository userRepository, protected UserManager<IdentityUser> UserManager { get; }
IStringLocalizer<IdentityResource> identityLocalizer, protected IStringLocalizer<IdentityResource> IdentityLocalizer { get; }
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer) protected IStringLocalizer<AbpIdentityServerResource> IdentityServerLocalizer { get; }
{
EventService = eventService; public WeChatGrantValidator(
UserManager = userManager; IEventService eventService,
UserRepository = userRepository; IWeChatOpenIdFinder weChatOpenIdFinder,
WeChatOpenIdFinder = weChatOpenIdFinder; UserManager<IdentityUser> userManager,
IdentityLocalizer = identityLocalizer; IIdentityUserRepository userRepository,
IdentityServerLocalizer = identityServerLocalizer; IStringLocalizer<IdentityResource> identityLocalizer,
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer)
Logger = NullLogger<WeChatGrantValidator>.Instance; {
} EventService = eventService;
UserManager = userManager;
protected abstract Task<WeChatOpenId> FindOpenIdAsync(string code); UserRepository = userRepository;
WeChatOpenIdFinder = weChatOpenIdFinder;
public async Task ValidateAsync(ExtensionGrantValidationContext context) IdentityLocalizer = identityLocalizer;
{ IdentityServerLocalizer = identityServerLocalizer;
var raw = context.Request.Raw;
var credential = raw.Get(OidcConstants.TokenRequest.GrantType); Logger = NullLogger<WeChatGrantValidator>.Instance;
if (credential == null || !credential.Equals(GrantType)) }
{
Logger.LogWarning("Invalid grant type: not allowed"); protected abstract Task<WeChatOpenId> FindOpenIdAsync(string code);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:GrantTypeInvalid"]);
return; [UnitOfWork]
} public async Task ValidateAsync(ExtensionGrantValidationContext context)
// TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey {
var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); var raw = context.Request.Raw;
if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) var credential = raw.Get(OidcConstants.TokenRequest.GrantType);
{ if (credential == null || !credential.Equals(GrantType))
Logger.LogWarning("Invalid grant type: wechat code not found"); {
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatCodeNotFound"]); Logger.LogWarning("Invalid grant type: not allowed");
return; context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:GrantTypeInvalid"]);
} return;
}
var wechatOpenId = await FindOpenIdAsync(wechatCode); // TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey
var currentUser = await UserManager.FindByLoginAsync(LoginProviderKey, wechatOpenId.OpenId); var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName);
if (currentUser == null) if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace())
{ {
Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId); Logger.LogWarning("Invalid grant type: wechat code not found");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]); context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatCodeNotFound"]);
return; return;
} }
if (await UserManager.IsLockedOutAsync(currentUser)) var wechatOpenId = await FindOpenIdAsync(wechatCode);
{ var currentUser = await UserManager.FindByLoginAsync(LoginProvider, wechatOpenId.OpenId);
Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", currentUser.UserName); if (currentUser == null)
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityLocalizer["Volo.Abp.Identity:UserLockedOut"]); {
return; var settingProvider = ServiceProvider.LazyGetRequiredService<ISettingProvider>();
} // TODO 检查启用用户注册是否有必要引用账户模块
if (! await settingProvider.IsTrueAsync("Abp.Account.IsSelfRegistrationEnabled") ||
var sub = await UserManager.GetUserIdAsync(currentUser); ! await settingProvider.IsTrueAsync(WeChatSettingNames.EnabledQuickLogin))
{
var additionalClaims = new List<Claim>(); Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId);
if (currentUser.TenantId.HasValue) context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]);
{ return;
additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString())); }
} var guiGenerator = ServiceProvider.LazyGetRequiredService<IGuidGenerator>();
additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId)); var currentTenant = ServiceProvider.LazyGetRequiredService<ICurrentTenant>();
if (!wechatOpenId.UnionId.IsNullOrWhiteSpace()) var userName = "wxid-" + wechatOpenId.OpenId.ToMd5().ToLower();
{ var userEmail = $"{userName}@{currentTenant.Name ?? "default"}.io";
additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId)); currentUser = new IdentityUser(guiGenerator.Create(), userName, userEmail, currentTenant.Id);
} (await UserManager.CreateAsync(currentUser)).CheckErrors();
(await UserManager.AddLoginAsync(
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null)); currentUser,
new UserLoginInfo(
context.Result = new GrantValidationResult(sub, AuthenticationMethod, additionalClaims.ToArray()); LoginProvider,
wechatOpenId.OpenId,
// 登录之后需要更新安全令牌 LoginProvider))).CheckErrors();
(await UserManager.UpdateSecurityStampAsync(currentUser)).CheckErrors(); }
}
} if (await UserManager.IsLockedOutAsync(currentUser))
} {
Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", currentUser.UserName);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityLocalizer["Volo.Abp.Identity:UserLockedOut"]);
return;
}
var sub = await UserManager.GetUserIdAsync(currentUser);
var additionalClaims = new List<Claim>();
if (currentUser.TenantId.HasValue)
{
additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString()));
}
additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId));
if (!wechatOpenId.UnionId.IsNullOrWhiteSpace())
{
additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId));
}
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null));
context.Result = new GrantValidationResult(sub, AuthenticationMethod, additionalClaims.ToArray());
// 登录之后需要更新安全令牌
(await UserManager.UpdateSecurityStampAsync(currentUser)).CheckErrors();
}
}
}

28
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN.Abp.IdentityServer.WeChatValidator.csproj

@ -1,28 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\IdentityServer\Localization\WeChatValidator\en.json" />
<None Remove="LINGYUN\Abp\IdentityServer\Localization\WeChatValidator\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\Localization\WeChatValidator\en.json" />
<EmbeddedResource Include="LINGYUN\Abp\IdentityServer\Localization\WeChatValidator\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="Microsoft\DependencyInjection\" />
</ItemGroup>
</Project>

57
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AbpIdentityServerWeChatValidatorModule.cs

@ -1,57 +0,0 @@
using LINGYUN.Abp.IdentityServer.AspNetIdentity;
using LINGYUN.Abp.IdentityServer.WeChatValidator;
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.IdentityServer;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.IdentityServer
{
[DependsOn(
typeof(AbpWeChatAuthorizationModule),
typeof(AbpIdentityServerDomainModule))]
public class AbpIdentityServerWeChatValidatorModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
PreConfigure<IIdentityServerBuilder>(builder =>
{
builder.AddProfileService<AbpWeChatProfileServicee>();
builder.AddExtensionGrantValidator<WeChatTokenGrantValidator>();
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
Configure<WeChatSignatureOptions>(configuration.GetSection("WeChat:Signature"));
context.Services
.AddAuthentication()
.AddWeChat(options => // 加入微信认证登录
{
configuration.GetSection("WeChat:Auth")?.Bind(options);
});
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpIdentityServerWeChatValidatorModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AbpIdentityServerResource>()
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator");
});
}
}
}

62
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/AspNetIdentity/AbpWeChatProfileService.cs

@ -1,62 +0,0 @@
using IdentityServer4.AspNetIdentity;
using IdentityServer4.Models;
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Identity;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Claims;
using Volo.Abp.Uow;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.AspNetIdentity
{
public class AbpWeChatProfileServicee : ProfileService<IdentityUser>
{
protected ICurrentTenant CurrentTenant { get; }
public AbpWeChatProfileServicee(
IdentityUserManager userManager,
IUserClaimsPrincipalFactory<IdentityUser> claimsFactory,
ICurrentTenant currentTenant)
: base(userManager, claimsFactory)
{
CurrentTenant = currentTenant;
}
[UnitOfWork]
public override async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
using (CurrentTenant.Change(context.Subject.FindTenantId()))
{
await base.GetProfileDataAsync(context);
// TODO: 可以从令牌获取openid, 安全性呢?
TryAddWeChatClaim(context, AbpWeChatClaimTypes.OpenId);
TryAddWeChatClaim(context, AbpWeChatClaimTypes.UnionId);
}
}
[UnitOfWork]
public override async Task IsActiveAsync(IsActiveContext context)
{
using (CurrentTenant.Change(context.Subject.FindTenantId()))
{
await base.IsActiveAsync(context);
}
}
protected virtual void TryAddWeChatClaim(ProfileDataRequestContext context, string weChatClaimType)
{
if (context.RequestedClaimTypes.Any(rc => rc.Contains(weChatClaimType)))
{
var weChatClaim = context.Subject.FindFirst(weChatClaimType);
if (weChatClaim != null)
{
context.IssuedClaims.Add(weChatClaim);
}
}
}
}
}

9
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/IWeChatResourceDataSeeder.cs

@ -1,9 +0,0 @@
using System.Threading.Tasks;
namespace LINGYUN.Abp.IdentityServer
{
public interface IWeChatResourceDataSeeder
{
Task CreateStandardResourcesAsync();
}
}

10
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/en.json

@ -1,10 +0,0 @@
{
"culture": "en",
"texts": {
"SelfRegistrationDisabledMessage": "Self-registration is disabled for this application. Please contact the application administrator to register a new user.",
"InvalidGrant:GrantTypeInvalid": "The type of authorization that is not allowed!",
"InvalidGrant:WeChatTokenInvalid": "WeChat authentication failed!",
"InvalidGrant:WeChatCodeNotFound": "The code obtained when WeChat is logged in is empty or does not exist!",
"InvalidGrant:WeChatNotRegister": "User WeChat account not registed!"
}
}

10
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/Localization/WeChatValidator/zh-Hans.json

@ -1,10 +0,0 @@
{
"culture": "zh-Hans",
"texts": {
"SelfRegistrationDisabledMessage": "应用程序未开放注册,请联系管理员添加新用户.",
"InvalidGrant:GrantTypeInvalid": "不被允许的授权类型!",
"InvalidGrant:WeChatTokenInvalid": "微信认证失败!",
"InvalidGrant:WeChatCodeNotFound": "微信登录时获取的 code 为空或不存在!",
"InvalidGrant:WeChatNotRegister": "用户微信账号未绑定!"
}
}

85
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatResourceDataSeeder.cs

@ -1,85 +0,0 @@
using LINGYUN.Abp.WeChat.Authorization;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.IdentityResources;
namespace LINGYUN.Abp.IdentityServer
{
public class WeChatResourceDataSeeder : IWeChatResourceDataSeeder, ITransientDependency
{
protected IIdentityClaimTypeRepository ClaimTypeRepository { get; }
protected IIdentityResourceRepository IdentityResourceRepository { get; }
protected IGuidGenerator GuidGenerator { get; }
public WeChatResourceDataSeeder(
IIdentityResourceRepository identityResourceRepository,
IGuidGenerator guidGenerator,
IIdentityClaimTypeRepository claimTypeRepository)
{
IdentityResourceRepository = identityResourceRepository;
GuidGenerator = guidGenerator;
ClaimTypeRepository = claimTypeRepository;
}
public virtual async Task CreateStandardResourcesAsync()
{
var wechatClaimTypes = new string[]
{
AbpWeChatClaimTypes.AvatarUrl,
AbpWeChatClaimTypes.City,
AbpWeChatClaimTypes.Country,
AbpWeChatClaimTypes.NickName,
AbpWeChatClaimTypes.OpenId,
AbpWeChatClaimTypes.Privilege,
AbpWeChatClaimTypes.Province,
AbpWeChatClaimTypes.Sex,
AbpWeChatClaimTypes.UnionId
};
var wechatResource = new IdentityServer4.Models.IdentityResource(
AbpWeChatAuthorizationConsts.ProfileKey,
AbpWeChatAuthorizationConsts.DisplayName,
wechatClaimTypes);
foreach (var claimType in wechatClaimTypes)
{
await AddClaimTypeIfNotExistsAsync(claimType);
}
await AddIdentityResourceIfNotExistsAsync(wechatResource);
}
protected virtual async Task AddIdentityResourceIfNotExistsAsync(IdentityServer4.Models.IdentityResource resource)
{
if (await IdentityResourceRepository.CheckNameExistAsync(resource.Name))
{
return;
}
await IdentityResourceRepository.InsertAsync(
new IdentityResource(
GuidGenerator.Create(),
resource
)
);
}
protected virtual async Task AddClaimTypeIfNotExistsAsync(string claimType)
{
if (await ClaimTypeRepository.AnyAsync(claimType))
{
return;
}
await ClaimTypeRepository.InsertAsync(
new IdentityClaimType(
GuidGenerator.Create(),
claimType,
isStatic: true
)
);
}
}
}

74
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureMiddleware.cs

@ -1,74 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Collections;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.IdentityServer
{
public class WeChatSignatureMiddleware : IMiddleware, ITransientDependency
{
protected WeChatSignatureOptions Options { get; }
public WeChatSignatureMiddleware(IOptions<WeChatSignatureOptions> options)
{
Options = options.Value;
}
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (context.Request.Path.HasValue)
{
var requestPath = context.Request.Path.Value;
// 访问地址是否与定义的地址匹配
if (requestPath.Equals(Options.RequestPath))
{
var timestamp = context.Request.Query["timestamp"];
var nonce = context.Request.Query["nonce"];
var signature = context.Request.Query["signature"];
var echostr = context.Request.Query["echostr"];
// 验证消息合法性
var check = CheckWeChatSignature(Options.Token, timestamp, nonce, signature);
if (check)
{
// 验证通过需要把微信服务器传递的字符原封不动传回
await context.Response.WriteAsync(echostr);
return;
}
// 微信消息验证不通过
throw new AbpException("Invalid wechat signature");
}
}
// 不属于微信的消息进入下一个中间件
await next(context);
}
protected bool CheckWeChatSignature(string token, string timestamp, string nonce, string signature)
{
var al = new ArrayList
{
token,
timestamp,
nonce
};
// step1 排序
al.Sort();
string signatureStr = string.Empty;
// step2 拼接
for (int i = 0; i < al.Count; i++)
{
signatureStr += al[i];
}
// step3 SHA1加密
byte[] bytes_out = signatureStr.Sha1();
string result = BitConverter.ToString(bytes_out).Replace("-", "");
// step4 比对
if (result.Equals(signature, StringComparison.CurrentCultureIgnoreCase))
{
return true;
}
return false;
}
}
}

16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatSignatureOptions.cs

@ -1,16 +0,0 @@
namespace LINGYUN.Abp.IdentityServer
{
public class WeChatSignatureOptions
{
/// <summary>
/// 微信服务器请求路径
/// 填写在微信开发者中心配置的地址
/// </summary>
public string RequestPath { get; set; }
/// <summary>
/// 微信服务器请求token
/// 填写在微信开发者中心配置的token
/// </summary>
public string Token { get; set; }
}
}

111
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatTokenGrantValidator.cs

@ -1,111 +0,0 @@
using IdentityModel;
using IdentityServer4.Events;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp.Identity;
using Volo.Abp.IdentityServer.Localization;
using Volo.Abp.Security.Claims;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.IdentityServer.WeChatValidator
{
public class WeChatTokenGrantValidator : IExtensionGrantValidator
{
protected ILogger<WeChatTokenGrantValidator> Logger { get; }
protected AbpWeChatAuthorizationOptions Options { get; }
protected IHttpClientFactory HttpClientFactory{ get; }
protected IEventService EventService { get; }
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; }
protected IIdentityUserRepository UserRepository { get; }
protected UserManager<IdentityUser> UserManager { get; }
protected SignInManager<IdentityUser> SignInManager { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
protected PhoneNumberTokenProvider<IdentityUser> PhoneNumberTokenProvider { get; }
public WeChatTokenGrantValidator(
IEventService eventService,
IWeChatOpenIdFinder weChatOpenIdFinder,
IHttpClientFactory httpClientFactory,
UserManager<IdentityUser> userManager,
IIdentityUserRepository userRepository,
SignInManager<IdentityUser> signInManager,
IStringLocalizer<AbpIdentityServerResource> stringLocalizer,
PhoneNumberTokenProvider<IdentityUser> phoneNumberTokenProvider,
IOptions<AbpWeChatAuthorizationOptions> options,
ILogger<WeChatTokenGrantValidator> logger)
{
Logger = logger;
Options = options.Value;
EventService = eventService;
UserManager = userManager;
SignInManager = signInManager;
Localizer = stringLocalizer;
UserRepository = userRepository;
WeChatOpenIdFinder = weChatOpenIdFinder;
HttpClientFactory = httpClientFactory;
PhoneNumberTokenProvider = phoneNumberTokenProvider;
}
public string GrantType => WeChatValidatorConsts.WeChatValidatorGrantTypeName;
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var raw = context.Request.Raw;
var credential = raw.Get(OidcConstants.TokenRequest.GrantType);
if (credential == null || !credential.Equals(GrantType))
{
Logger.LogWarning("Invalid grant type: not allowed");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:GrantTypeInvalid"]);
return;
}
// TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey
var wechatCode = raw.Get(WeChatValidatorConsts.WeChatValidatorTokenName);
if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace())
{
Logger.LogWarning("Invalid grant type: wechat code not found");
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:WeChatCodeNotFound"]);
return;
}
var wechatOpenId = await WeChatOpenIdFinder.FindAsync(wechatCode);
var currentUser = await UserManager.FindByLoginAsync(AbpWeChatAuthorizationConsts.ProviderKey, wechatOpenId.OpenId);
if(currentUser == null)
{
Logger.LogWarning("Invalid grant type: wechat openid: {0} not register", wechatOpenId.OpenId);
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant,
Localizer["InvalidGrant:WeChatNotRegister"]);
return;
}
var sub = await UserManager.GetUserIdAsync(currentUser);
var additionalClaims = new List<Claim>();
if (currentUser.TenantId.HasValue)
{
additionalClaims.Add(new Claim(AbpClaimTypes.TenantId, currentUser.TenantId?.ToString()));
}
additionalClaims.Add(new Claim(AbpWeChatClaimTypes.OpenId, wechatOpenId.OpenId));
if (!wechatOpenId.UnionId.IsNullOrWhiteSpace())
{
additionalClaims.Add(new Claim(AbpWeChatClaimTypes.UnionId, wechatOpenId.UnionId));
}
await EventService.RaiseAsync(new UserLoginSuccessEvent(currentUser.UserName, wechatOpenId.OpenId, null));
context.Result = new GrantValidationResult(sub,
WeChatValidatorConsts.AuthenticationMethods.BasedWeChatAuthentication, additionalClaims.ToArray());
}
}
}

16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/IdentityServer/WeChatValidator/WeChatValidatorConsts.cs

@ -1,16 +0,0 @@
namespace LINGYUN.Abp.IdentityServer.WeChatValidator
{
public class WeChatValidatorConsts
{
public const string WeChatValidatorClientName = "WeChatValidator";
public const string WeChatValidatorGrantTypeName = "wechat";
public const string WeChatValidatorTokenName = "code";
public class AuthenticationMethods
{
public const string BasedWeChatAuthentication = "wca";
}
}
}

316
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationHandler.cs

@ -1,316 +0,0 @@
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Threading.Tasks;
using Volo.Abp.Caching;
namespace Microsoft.AspNetCore.Authentication.WeChat
{
public class WeChatAuthenticationHandler : OAuthHandler<WeChatAuthenticationOptions>
{
protected IDistributedCache<WeChatAuthenticationStateCacheItem> Cache { get; }
public WeChatAuthenticationHandler(
IDistributedCache<WeChatAuthenticationStateCacheItem> cache,
IOptionsMonitor<WeChatAuthenticationOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock)
: base(options, logger, encoder, clock)
{
Cache = cache;
}
protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
{
var address = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, new Dictionary<string, string>
{
["access_token"] = tokens.AccessToken,
["openid"] = tokens.Response.GetRootString("openid")
});
var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
throw new HttpRequestException("An error occurred while retrieving user information.");
}
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
{
Logger.LogError("An error occurred while retrieving the user profile: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
throw new HttpRequestException("An error occurred while retrieving user information.");
}
var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
context.RunClaimActions();
await Events.CreatingTicket(context);
// TODO: 此处通过唯一的 CorrelationId, 将 properties生成的State缓存删除
var state = Request.Query["state"];
var stateCacheKey = WeChatAuthenticationStateCacheItem.CalculateCacheKey(state, null);
await Cache.RemoveAsync(stateCacheKey, token: Context.RequestAborted);
return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
}
/// <summary>
/// code换取access_token
/// </summary>
protected override async Task<OAuthTokenResponse> ExchangeCodeAsync(OAuthCodeExchangeContext context)
{
var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, new Dictionary<string, string>()
{
["appid"] = Options.ClientId,
["secret"] = Options.ClientSecret,
["code"] = context.Code,
["grant_type"] = "authorization_code"
});
var response = await Backchannel.GetAsync(address);
if (!response.IsSuccessStatusCode)
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
}
var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
if (!string.IsNullOrEmpty(payload.GetRootString("errcode")))
{
Logger.LogError("An error occurred while retrieving an access token: the remote server " +
"returned a {Status} response with the following payload: {Headers} {Body}.",
/* Status: */ response.StatusCode,
/* Headers: */ response.Headers.ToString(),
/* Body: */ await response.Content.ReadAsStringAsync());
return OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token."));
}
return OAuthTokenResponse.Success(payload);
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
await base.HandleChallengeAsync(properties);
// TODO: 此处已经生成唯一的 CorrelationId, 可以借此将 properties生成State之后再进行缓存
var state = properties.Items[".xsrf"];
var stateToken = Options.StateDataFormat.Protect(properties);
var stateCacheKey = WeChatAuthenticationStateCacheItem.CalculateCacheKey(state, null);
await Cache
.SetAsync(
stateCacheKey,
new WeChatAuthenticationStateCacheItem(stateToken),
new DistributedCacheEntryOptions
{
AbsoluteExpiration = Clock.UtcNow.AddMinutes(2) // TODO: 设定2分钟过期?
},
token: Context.RequestAborted);
}
/// <summary>
/// 构建用户授权地址
/// </summary>
protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri)
{
var state = properties.Items[".xsrf"];
var isWeChatBrewserRequest = IsWeChatBrowser();
var scope = isWeChatBrewserRequest
? AbpWeChatAuthorizationConsts.UserInfoScope
: FormatScope();
var endPoint = isWeChatBrewserRequest
? Options.AuthorizationEndpoint
: AbpWeChatAuthorizationConsts.QrConnectEndpoint;
var challengeUrl = QueryHelpers.AddQueryString(endPoint, new Dictionary<string, string>
{
["appid"] = Options.ClientId,
["redirect_uri"] = redirectUri,
["response_type"] = "code"
});
challengeUrl += $"&scope={scope}&state={state}";
return challengeUrl;
}
protected override async Task<HandleRequestResult> HandleRemoteAuthenticateAsync()
{
var query = Request.Query;
// TODO: 此处借用唯一的 CorrelationId, 将 properties生成的State缓存取出,进行解密
var state = query["state"];
var stateCacheKey = WeChatAuthenticationStateCacheItem.CalculateCacheKey(state, null);
var stateCacheItem = await Cache.GetAsync(stateCacheKey, token: Context.RequestAborted);
var properties = Options.StateDataFormat.Unprotect(stateCacheItem.State);
if (properties == null)
{
return HandleRequestResult.Fail("The oauth state was missing or invalid.");
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties))
{
return HandleRequestResult.Fail("Correlation failed.", properties);
}
var error = query["error"];
if (!StringValues.IsNullOrEmpty(error))
{
// Note: access_denied errors are special protocol errors indicating the user didn't
// approve the authorization demand requested by the remote authorization server.
// Since it's a frequent scenario (that is not caused by incorrect configuration),
// denied errors are handled differently using HandleAccessDeniedErrorAsync().
// Visit https://tools.ietf.org/html/rfc6749#section-4.1.2.1 for more information.
var errorDescription = query["error_description"];
var errorUri = query["error_uri"];
if (StringValues.Equals(error, "access_denied"))
{
var result = await HandleAccessDeniedErrorAsync(properties);
if (!result.None)
{
return result;
}
var deniedEx = new Exception("Access was denied by the resource owner or by the remote server.");
deniedEx.Data["error"] = error.ToString();
deniedEx.Data["error_description"] = errorDescription.ToString();
deniedEx.Data["error_uri"] = errorUri.ToString();
return HandleRequestResult.Fail(deniedEx, properties);
}
var failureMessage = new StringBuilder();
failureMessage.Append(error);
if (!StringValues.IsNullOrEmpty(errorDescription))
{
failureMessage.Append(";Description=").Append(errorDescription);
}
if (!StringValues.IsNullOrEmpty(errorUri))
{
failureMessage.Append(";Uri=").Append(errorUri);
}
var ex = new Exception(failureMessage.ToString());
ex.Data["error"] = error.ToString();
ex.Data["error_description"] = errorDescription.ToString();
ex.Data["error_uri"] = errorUri.ToString();
return HandleRequestResult.Fail(ex, properties);
}
var code = query["code"];
if (StringValues.IsNullOrEmpty(code))
{
return HandleRequestResult.Fail("Code was not found.", properties);
}
var codeExchangeContext = new OAuthCodeExchangeContext(properties, code, BuildRedirectUri(Options.CallbackPath));
using var tokens = await ExchangeCodeAsync(codeExchangeContext);
if (tokens.Error != null)
{
return HandleRequestResult.Fail(tokens.Error, properties);
}
if (string.IsNullOrEmpty(tokens.AccessToken))
{
return HandleRequestResult.Fail("Failed to retrieve access token.", properties);
}
var identity = new ClaimsIdentity(ClaimsIssuer);
if (Options.SaveTokens)
{
var authTokens = new List<AuthenticationToken>();
authTokens.Add(new AuthenticationToken { Name = "access_token", Value = tokens.AccessToken });
if (!string.IsNullOrEmpty(tokens.RefreshToken))
{
authTokens.Add(new AuthenticationToken { Name = "refresh_token", Value = tokens.RefreshToken });
}
if (!string.IsNullOrEmpty(tokens.TokenType))
{
authTokens.Add(new AuthenticationToken { Name = "token_type", Value = tokens.TokenType });
}
if (!string.IsNullOrEmpty(tokens.ExpiresIn))
{
int value;
if (int.TryParse(tokens.ExpiresIn, NumberStyles.Integer, CultureInfo.InvariantCulture, out value))
{
// https://www.w3.org/TR/xmlschema-2/#dateTime
// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
var expiresAt = Clock.UtcNow + TimeSpan.FromSeconds(value);
authTokens.Add(new AuthenticationToken
{
Name = "expires_at",
Value = expiresAt.ToString("o", CultureInfo.InvariantCulture)
});
}
}
properties.StoreTokens(authTokens);
}
var ticket = await CreateTicketAsync(identity, properties, tokens);
if (ticket != null)
{
return HandleRequestResult.Success(ticket);
}
else
{
return HandleRequestResult.Fail("Failed to retrieve user information from remote server.", properties);
}
}
protected override string FormatScope()
{
return string.Join(",", Options.Scope);
}
protected virtual bool IsWeChatBrowser()
{
var userAgent = Request.Headers[HeaderNames.UserAgent].ToString();
return userAgent.Contains("micromessenger", StringComparison.InvariantCultureIgnoreCase);
}
}
}

54
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationOptions.cs

@ -1,54 +0,0 @@
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Authentication.OAuth;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Text.Json;
namespace Microsoft.AspNetCore.Authentication.WeChat
{
public class WeChatAuthenticationOptions : OAuthOptions
{
public string AppId
{
get => ClientId;
set => ClientId = value;
}
public string AppSecret
{
get => ClientSecret;
set => ClientSecret = value;
}
public WeChatAuthenticationOptions()
{
ClaimsIssuer = AbpWeChatAuthorizationConsts.ProviderKey;
CallbackPath = new PathString(AbpWeChatAuthorizationConsts.CallbackPath);
AuthorizationEndpoint = AbpWeChatAuthorizationConsts.AuthorizationEndpoint;
TokenEndpoint = AbpWeChatAuthorizationConsts.TokenEndpoint;
UserInformationEndpoint = AbpWeChatAuthorizationConsts.UserInformationEndpoint;
Scope.Add(AbpWeChatAuthorizationConsts.LoginScope);
Scope.Add(AbpWeChatAuthorizationConsts.UserInfoScope);
// 这个原始的属性一定要写进去,框架与UserLogin.ProviderKey进行关联判断是否绑定微信
ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "openid");
ClaimActions.MapJsonKey(ClaimTypes.Name, "nickname");
// 把自定义的身份标识写进令牌
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.OpenId, "openid");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.UnionId, "unionid"); // TODO: 可用作tenant对比?
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.NickName, "nickname");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Sex, "sex", ClaimValueTypes.Integer);
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Country, "country");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.Province, "province");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.City, "city");
ClaimActions.MapJsonKey(AbpWeChatClaimTypes.AvatarUrl, "headimgurl");
ClaimActions.MapCustomJson(AbpWeChatClaimTypes.Privilege, user =>
{
return string.Join(",", user.GetStrings("privilege"));
});
}
}
}

18
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChat/WeChatAuthenticationStateCacheItem.cs

@ -1,18 +0,0 @@
namespace Microsoft.AspNetCore.Authentication.WeChat
{
public class WeChatAuthenticationStateCacheItem
{
public string State { get; set; }
public WeChatAuthenticationStateCacheItem() { }
public WeChatAuthenticationStateCacheItem(string state)
{
State = state;
}
public static string CalculateCacheKey(string correlationId, string purpose)
{
return $"ci:{correlationId};p:{purpose ?? "null"}";
}
}
}

64
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Authentication/WeChatAuthenticationExtensions.cs

@ -1,64 +0,0 @@
using LINGYUN.Abp.WeChat.Authorization;
using Microsoft.AspNetCore.Authentication.WeChat;
using Microsoft.Extensions.DependencyInjection;
using System;
namespace Microsoft.AspNetCore.Authentication
{
public static class WeChatAuthenticationExtensions
{
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder)
{
return builder
.AddWeChat(
AbpWeChatAuthorizationConsts.AuthenticationScheme,
AbpWeChatAuthorizationConsts.DisplayName,
options => { });
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder,
Action<WeChatAuthenticationOptions> configureOptions)
{
return builder
.AddWeChat(
AbpWeChatAuthorizationConsts.AuthenticationScheme,
AbpWeChatAuthorizationConsts.DisplayName,
configureOptions);
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder,
string authenticationScheme,
Action<WeChatAuthenticationOptions> configureOptions)
{
return builder
.AddWeChat(
authenticationScheme,
AbpWeChatAuthorizationConsts.DisplayName,
configureOptions);
}
/// <summary>
/// </summary>
public static AuthenticationBuilder AddWeChat(
this AuthenticationBuilder builder,
string authenticationScheme,
string displayName,
Action<WeChatAuthenticationOptions> configureOptions)
{
return builder
.AddOAuth<WeChatAuthenticationOptions, WeChatAuthenticationHandler>(
authenticationScheme,
displayName,
configureOptions);
}
}
}

22
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/Microsoft/AspNetCore/Builder/IdentityServerApplicationBuilderExtensions.cs

@ -1,22 +0,0 @@
using LINGYUN.Abp.IdentityServer;
namespace Microsoft.AspNetCore.Builder
{
public static class IdentityServerApplicationBuilderExtensions
{
/// <summary>
/// 启用中间件可以处理微信服务器消息
/// 用于验证消息是否来自于微信服务器
/// </summary>
/// <param name="builder"></param>
/// <remarks>
/// 也可以用Controller的形式来实现
/// </remarks>
/// <returns></returns>
public static IApplicationBuilder UseWeChatSignature(this IApplicationBuilder builder)
{
builder.UseMiddleware<WeChatSignatureMiddleware>();
return builder;
}
}
}

17
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/README.md

@ -1,17 +0,0 @@
# LINGYUN.Abp.IdentityServer.WeChatValidator
废弃模块,模块层次不清晰,微信有多端平台,不同平台授权规则不一致
#### 注意
## 配置使用
```csharp
[DependsOn(typeof(AbpIdentityServerWeChatValidatorModule))]
public class YouProjectModule : AbpModule
{
// other
}

16
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/BytesExtensions.cs

@ -1,16 +0,0 @@
using System.Security.Cryptography;
namespace System
{
internal static class BytesExtensions
{
public static byte[] Sha1(this byte[] data)
{
using (var sha = SHA1.Create())
{
var hashBytes = sha.ComputeHash(data);
return hashBytes;
}
}
}
}

17
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/StringExtensions.cs

@ -1,17 +0,0 @@
using System.Security.Cryptography;
using System.Text;
namespace System
{
internal static class StringExtensions
{
public static byte[] Sha1(this string str)
{
using (var sha = SHA1.Create())
{
var hashBytes = sha.ComputeHash(Encoding.ASCII.GetBytes(str));
return hashBytes;
}
}
}
}

63
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/System/Text/Json/JsonElementExtensions.cs

@ -1,63 +0,0 @@
using System.Collections.Generic;
namespace System.Text.Json
{
internal static class JsonElementExtensions
{
public static IEnumerable<string> GetRootStrings(this JsonDocument json, string key)
{
return json.RootElement.GetStrings(key);
}
public static IEnumerable<string> GetStrings(this JsonElement json, string key)
{
var result = new List<string>();
if (json.TryGetProperty(key, out JsonElement property) && property.ValueKind == JsonValueKind.Array)
{
foreach (var jsonProp in property.EnumerateArray())
{
result.Add(jsonProp.GetString());
}
}
return result;
}
public static string GetRootString(this JsonDocument json, string key, string defaultValue = "")
{
if (json.RootElement.TryGetProperty(key, out JsonElement property))
{
return property.GetString();
}
return defaultValue;
}
public static string GetString(this JsonElement json, string key, string defaultValue = "")
{
if (json.TryGetProperty(key, out JsonElement property))
{
return property.GetString();
}
return defaultValue;
}
public static int GetRootInt32(this JsonDocument json, string key, int defaultValue = 0)
{
if (json.RootElement.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value))
{
return value;
}
return defaultValue;
}
public static int GetInt32(this JsonElement json, string key, int defaultValue = 0)
{
if (json.TryGetProperty(key, out JsonElement property) && property.TryGetInt32(out int value))
{
return value;
}
return defaultValue;
}
}
}

19
aspnet-core/modules/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN.Abp.Identity.WeChat.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Identity.Domain" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj" />
</ItemGroup>
</Project>

13
aspnet-core/modules/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN/Abp/Identity/WeChat/AbpIdentityWeChatModule.cs

@ -0,0 +1,13 @@
using LINGYUN.Abp.WeChat;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.Identity.WeChat
{
[DependsOn(
typeof(AbpWeChatModule),
typeof(AbpIdentityDomainModule))]
public class AbpIdentityWeChatModule : AbpModule
{
}
}

93
aspnet-core/modules/identityServer/LINGYUN.Abp.IdentityServer.WeChatValidator/LINGYUN/Abp/WeChat/Authorization/UserWeChatOpenIdFinder.cs → aspnet-core/modules/wechat/LINGYUN.Abp.Identity.WeChat/LINGYUN/Abp/Identity/WeChat/OpenId/UserWeChatOpenIdFinder.cs

@ -1,46 +1,47 @@
using Microsoft.Extensions.DependencyInjection; using LINGYUN.Abp.WeChat.OpenId;
using System; using Microsoft.Extensions.DependencyInjection;
using System.Linq; using System;
using System.Threading.Tasks; using System.Linq;
using Volo.Abp.DependencyInjection; using System.Threading.Tasks;
using Volo.Abp.Identity; using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
namespace LINGYUN.Abp.WeChat.Authorization
{ namespace LINGYUN.Abp.Identity.WeChat.OpenId
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)] {
[ExposeServices(typeof(IUserWeChatOpenIdFinder))] [Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
public class UserWeChatOpenIdFinder : IUserWeChatOpenIdFinder [ExposeServices(typeof(IUserWeChatOpenIdFinder))]
{ public class UserWeChatOpenIdFinder : IUserWeChatOpenIdFinder
protected IdentityUserManager UserManager { get; } {
protected IdentityUserManager UserManager { get; }
public UserWeChatOpenIdFinder(
IdentityUserManager userManager) public UserWeChatOpenIdFinder(
{ IdentityUserManager userManager)
UserManager = userManager; {
} UserManager = userManager;
}
public virtual async Task<string> FindByUserIdAsync(Guid userId)
{ public virtual async Task<string> FindByUserIdAsync(Guid userId, string provider)
var user = await UserManager.FindByIdAsync(userId.ToString()); {
var user = await UserManager.FindByIdAsync(userId.ToString());
return GetUserOpenIdOrNull(user);
} return GetUserOpenIdOrNull(user, provider);
}
public virtual async Task<string> FindByUserNameAsync(string userName)
{ public virtual async Task<string> FindByUserNameAsync(string userName, string provider)
var user = await UserManager.FindByNameAsync(userName); {
var user = await UserManager.FindByNameAsync(userName);
return GetUserOpenIdOrNull(user);
} return GetUserOpenIdOrNull(user, provider);
}
protected string GetUserOpenIdOrNull(IdentityUser user)
{ protected string GetUserOpenIdOrNull(IdentityUser user, string provider)
// 微信扩展登录后openid存储在Login中 {
var userLogin = user?.Logins // 微信扩展登录后openid存储在Login中
.Where(login => login.LoginProvider == AbpWeChatAuthorizationConsts.ProviderKey) var userLogin = user?.Logins
.FirstOrDefault(); .Where(login => login.LoginProvider == provider)
.FirstOrDefault();
return userLogin?.ProviderKey;
} return userLogin?.ProviderKey;
} }
} }
}

14
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN.Abp.WeChat.Application.Contracts.csproj

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="4.4.0" />
</ItemGroup>
</Project>

11
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/AbpWeChatApplicationContractsModule.cs

@ -0,0 +1,11 @@
using Volo.Abp.Application;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.WeChat
{
[DependsOn(
typeof(AbpDddApplicationContractsModule))]
public class AbpWeChatApplicationContractsModule : AbpModule
{
}
}

21
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/Dto/Gender.cs

@ -0,0 +1,21 @@
namespace LINGYUN.Abp.WeChat.Crypto
{
/// <summary>
/// 性别
/// </summary>
public enum Gender
{
/// <summary>
/// 未知
/// </summary>
None = 0,
/// <summary>
/// 男性
/// </summary>
Man = 1,
/// <summary>
/// 女性
/// </summary>
Women = 2
}
}

9
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/Dto/GetUserInfoInput.cs

@ -0,0 +1,9 @@
namespace LINGYUN.Abp.WeChat.Crypto
{
public class GetUserInfoInput
{
public string EncryptedData { get; set; }
public string IV { get; set; }
public string Code { get; set; }
}
}

37
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/Dto/UserInfoDto.cs

@ -0,0 +1,37 @@
namespace LINGYUN.Abp.WeChat.Crypto
{
public class UserInfoDto
{
/// <summary>
/// 用户昵称
/// </summary>
public string NickName { get; set; }
/// <summary>
/// 用户头像图片的 URL。
/// URL 最后一个数值代表正方形头像大小(有 0、46、64、96、132 数值可选,0 代表 640x640 的正方形头像,46 表示 46x46 的正方形头像,剩余数值以此类推。默认132),
/// 用户没有头像时该项为空。
/// 若用户更换头像,原有头像 URL 将失效。
/// </summary>
public string AvatarUrl { get; set; }
/// <summary>
/// 性别
/// </summary>
public Gender Gender { get; set; }
/// <summary>
/// 用户所在国家
/// </summary>
public string Country { get; set; }
/// <summary>
/// 用户所在省份
/// </summary>
public string Province { get; set; }
/// <summary>
/// 用户所在城市
/// </summary>
public string City { get; set; }
/// <summary>
/// 显示 country,province,city 所用的语言
/// </summary>
public string Language { get; set; }
}
}

10
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/Crypto/ICryptoAppService.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.WeChat.Crypto
{
public interface ICryptoAppService : IApplicationService
{
Task<UserInfoDto> GetUserInfoAsync(GetUserInfoInput input);
}
}

7
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application.Contracts/LINGYUN/Abp/WeChat/WeChatRemoteServiceConsts.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Abp.WeChat
{
public static class WeChatRemoteServiceConsts
{
public const string RemoteServiceName = "AbpWeChat";
}
}

19
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN.Abp.WeChat.Application.csproj

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Ddd.Application" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.WeChat.Application.Contracts\LINGYUN.Abp.WeChat.Application.Contracts.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.WeChat.MiniProgram\LINGYUN.Abp.WeChat.MiniProgram.csproj" />
</ItemGroup>
</Project>

14
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN/Abp/WeChat/AbpWeChatApplicationModule.cs

@ -0,0 +1,14 @@
using LINGYUN.Abp.WeChat.MiniProgram;
using Volo.Abp.Application;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.WeChat
{
[DependsOn(
typeof(AbpWeChatMiniProgramModule),
typeof(AbpWeChatApplicationContractsModule),
typeof(AbpDddApplicationModule))]
public class AbpWeChatApplicationModule : AbpModule
{
}
}

42
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN/Abp/WeChat/Crypto/CryptoAppService.cs

@ -0,0 +1,42 @@
using LINGYUN.Abp.WeChat.MiniProgram;
using LINGYUN.Abp.WeChat.OpenId;
using Microsoft.AspNetCore.Authorization;
using System;
using System.Threading.Tasks;
using Volo.Abp.Json;
namespace LINGYUN.Abp.WeChat.Crypto
{
[Authorize]
public class CryptoAppService : WeChatApplicationServiceBase, ICryptoAppService
{
protected IJsonSerializer JsonSerializer { get; }
protected IWeChatOpenIdFinder OpenIdFinder { get; }
protected IWeChatCryptoService WeChatCryptoService { get; }
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; }
public CryptoAppService(
IJsonSerializer jsonSerializer,
IWeChatOpenIdFinder openIdFinder,
IWeChatCryptoService weChatCryptoService,
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory)
{
JsonSerializer = jsonSerializer;
OpenIdFinder = openIdFinder;
WeChatCryptoService = weChatCryptoService;
MiniProgramOptionsFactory = miniProgramOptionsFactory;
}
public virtual async Task<UserInfoDto> GetUserInfoAsync(GetUserInfoInput input)
{
var options = await MiniProgramOptionsFactory.CreateAsync();
WeChatOpenId weChatOpenId = input.Code.IsNullOrWhiteSpace()
? await OpenIdFinder.FindAsync(options.AppId)
: await OpenIdFinder.FindAsync(input.Code, options.AppId, options.AppSecret);
var decryptedData = WeChatCryptoService.Decrypt(input.EncryptedData, input.IV, weChatOpenId.SessionKey);
return JsonSerializer.Deserialize<UserInfoDto>(decryptedData);
}
}
}

14
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Application/LINGYUN/Abp/WeChat/WeChatApplicationServiceBase.cs

@ -0,0 +1,14 @@
using LINGYUN.Abp.WeChat.Localization;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.WeChat
{
public abstract class WeChatApplicationServiceBase : ApplicationService
{
protected WeChatApplicationServiceBase()
{
LocalizationResource = typeof(WeChatResource);
ObjectMapperContext = typeof(AbpWeChatApplicationModule);
}
}
}

14
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.HttpApi/LINGYUN.Abp.WeChat.HttpApi.csproj

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="4.4.0" />
</ItemGroup>
</Project>

12
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.HttpApi/LINGYUN/Abp/WeChat/AbpWeChatHttpApiModule.cs

@ -0,0 +1,12 @@
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
namespace LINGYUN.Abp.WeChat
{
[DependsOn(
typeof(AbpWeChatApplicationContractsModule),
typeof(AbpAspNetCoreMvcModule))]
public class AbpWeChatHttpApiModule : AbpModule
{
}
}

29
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.HttpApi/LINGYUN/Abp/WeChat/Crypto/CryptoController.cs

@ -0,0 +1,29 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.WeChat.Crypto
{
[RemoteService(Name = WeChatRemoteServiceConsts.RemoteServiceName)]
[Area("account")]
[ApiVersion("1.0")]
[Route("api/wechat")]
public class CryptoController : AbpController, ICryptoAppService
{
private readonly ICryptoAppService _service;
public CryptoController(
ICryptoAppService service)
{
_service = service;
}
[HttpGet]
[Route("getUserInfo")]
public virtual async Task<UserInfoDto> GetUserInfoAsync(GetUserInfoInput input)
{
return await _service.GetUserInfoAsync(input);
}
}
}

42
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramConsts.cs

@ -1,21 +1,21 @@
namespace LINGYUN.Abp.WeChat.MiniProgram namespace LINGYUN.Abp.WeChat.MiniProgram
{ {
public class AbpWeChatMiniProgramConsts public class AbpWeChatMiniProgramConsts
{ {
/// <summary> /// <summary>
/// 微信小程序对应的Provider名称 /// 微信小程序对应的Provider名称
/// </summary> /// </summary>
public static string ProviderKey { get; set; } = "WeChat.MiniProgram"; public static string ProviderName { get; set; } = "WeChat.MiniProgram";
/// <summary> /// <summary>
/// 微信小程序授权类型 /// 微信小程序授权类型
/// </summary> /// </summary>
public static string GrantType { get; set; } = "wx-mp"; public static string GrantType { get; set; } = "wx-mp";
/// <summary> /// <summary>
/// 微信小程序授权方法名称 /// 微信小程序授权方法名称
/// </summary> /// </summary>
public static string AuthenticationMethod { get; set; } = "wma"; public static string AuthenticationMethod { get; set; } = "wma";
public static string HttpClient { get; set; } = "Abp.WeChat.MiniProgram"; public static string HttpClient { get; set; } = "Abp.WeChat.MiniProgram";
} }
} }

74
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/AbpWeChatMiniProgramModule.cs

@ -1,38 +1,36 @@
using LINGYUN.Abp.WeChat.Localization; using LINGYUN.Abp.WeChat.Localization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.Settings; using Volo.Abp.VirtualFileSystem;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.WeChat.MiniProgram
namespace LINGYUN.Abp.WeChat.MiniProgram {
{ [DependsOn(
[DependsOn( typeof(AbpWeChatModule))]
typeof(AbpWeChatModule), public class AbpWeChatMiniProgramModule : AbpModule
typeof(AbpSettingsModule))] {
public class AbpWeChatMiniProgramModule : AbpModule public override void ConfigureServices(ServiceConfigurationContext context)
{ {
public override void ConfigureServices(ServiceConfigurationContext context) Configure<AbpVirtualFileSystemOptions>(options =>
{ {
Configure<AbpVirtualFileSystemOptions>(options => options.FileSets.AddEmbedded<AbpWeChatMiniProgramModule>();
{ });
options.FileSets.AddEmbedded<AbpWeChatMiniProgramModule>();
}); Configure<AbpLocalizationOptions>(options =>
{
Configure<AbpLocalizationOptions>(options => options.Resources
{ .Get<WeChatResource>()
options.Resources .AddVirtualJson("/LINGYUN/Abp/WeChat/MiniProgram/Localization/Resources");
.Get<WeChatResource>() });
.AddVirtualJson("/LINGYUN/Abp/WeChat/MiniProgram/Localization/Resources");
}); context.Services.AddHttpClient(AbpWeChatMiniProgramConsts.HttpClient, options =>
{
context.Services.AddHttpClient(AbpWeChatMiniProgramConsts.HttpClient, options => options.BaseAddress = new Uri("https://api.weixin.qq.com");
{ });
options.BaseAddress = new Uri("https://api.weixin.qq.com");
}); context.Services.AddAbpDynamicOptions<AbpWeChatMiniProgramOptions, AbpWeChatMiniProgramOptionsManager>();
}
context.Services.AddAbpDynamicOptions<AbpWeChatMiniProgramOptions, AbpWeChatMiniProgramOptionsManager>(); }
} }
}
}

48
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/Messages/Response.SubscribeMessage.cs

@ -1,24 +1,24 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Volo.Abp; using Volo.Abp;
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages namespace LINGYUN.Abp.WeChat.MiniProgram.Messages
{ {
public class SubscribeMessageResponse public class SubscribeMessageResponse
{ {
[JsonProperty("errcode")] [JsonProperty("errcode")]
public int ErrorCode { get; set; } public int ErrorCode { get; set; }
[JsonProperty("errmsg")] [JsonProperty("errmsg")]
public string ErrorMessage { get; set; } public string ErrorMessage { get; set; }
public bool IsSuccessed => ErrorCode == 0; public bool IsSuccessed => ErrorCode == 0;
public void ThrowIfNotSuccess() public void ThrowIfNotSuccess()
{ {
if (ErrorCode != 0) if (ErrorCode != 0)
{ {
throw new AbpException($"Send wechat weapp notification error:{ErrorMessage}"); throw new AbpException($"Send wechat weapp notification error:{ErrorMessage}");
} }
} }
} }
} }

212
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/Messages/SubscribeMessage.cs

@ -1,106 +1,106 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages namespace LINGYUN.Abp.WeChat.MiniProgram.Messages
{ {
public class SubscribeMessage public class SubscribeMessage
{ {
/// <summary> /// <summary>
/// 接收者(用户)的 openid /// 接收者(用户)的 openid
/// </summary> /// </summary>
[JsonProperty("touser")] [JsonProperty("touser")]
public string ToUser { get; set; } public string ToUser { get; set; }
/// <summary> /// <summary>
/// 所需下发的订阅模板id /// 所需下发的订阅模板id
/// </summary> /// </summary>
[JsonProperty("template_id")] [JsonProperty("template_id")]
public string TemplateId { get; set; } public string TemplateId { get; set; }
/// <summary> /// <summary>
/// 点击模板卡片后的跳转页面,仅限本小程序内的页面。 /// 点击模板卡片后的跳转页面,仅限本小程序内的页面。
/// 支持带参数,(示例index?foo=bar)。 /// 支持带参数,(示例index?foo=bar)。
/// 该字段不填则模板无跳转 /// 该字段不填则模板无跳转
/// </summary> /// </summary>
[JsonProperty("page")] [JsonProperty("page")]
public string Page { get; set; } public string Page { get; set; }
/// <summary> /// <summary>
/// 跳转小程序类型: /// 跳转小程序类型:
/// developer为开发版;trial为体验版;formal为正式版; /// developer为开发版;trial为体验版;formal为正式版;
/// 默认为正式版 /// 默认为正式版
/// </summary> /// </summary>
[JsonProperty("miniprogram_state")] [JsonProperty("miniprogram_state")]
public string MiniProgramState { get; set; } public string MiniProgramState { get; set; }
/// <summary> /// <summary>
/// 进入小程序查看”的语言类型, /// 进入小程序查看”的语言类型,
/// 支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文), /// 支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),
/// 默认为zh_CN /// 默认为zh_CN
/// </summary> /// </summary>
[JsonProperty("lang")] [JsonProperty("lang")]
public string Lang { get; set; } = "zh_CN"; public string Lang { get; set; } = "zh_CN";
/// <summary> /// <summary>
/// 模板内容, /// 模板内容,
/// 格式形如 { "key1": { "value": any }, "key2": { "value": any } } /// 格式形如 { "key1": { "value": any }, "key2": { "value": any } }
/// </summary> /// </summary>
[JsonProperty("data")] [JsonProperty("data")]
public Dictionary<string, MessageData> Data { get; set; } = new Dictionary<string, MessageData>(); public Dictionary<string, MessageData> Data { get; set; } = new Dictionary<string, MessageData>();
public SubscribeMessage() { } public SubscribeMessage() { }
public SubscribeMessage( public SubscribeMessage(
string openId, string openId,
string templateId, string templateId,
string redirectPage = "", string redirectPage = "",
string state = "formal", string state = "formal",
string miniLang = "zh_CN") string miniLang = "zh_CN")
{ {
ToUser = openId; ToUser = openId;
TemplateId = templateId; TemplateId = templateId;
Page = redirectPage; Page = redirectPage;
MiniProgramState = state; MiniProgramState = state;
Lang = miniLang; Lang = miniLang;
} }
public SubscribeMessage WriteData(string prefix, string key, object value) public SubscribeMessage WriteData(string prefix, string key, object value)
{ {
// 只截取符合标记的数据 // 只截取符合标记的数据
if (key.StartsWith(prefix)) if (key.StartsWith(prefix))
{ {
key = key.Replace(prefix, ""); key = key.Replace(prefix, "");
if (!Data.ContainsKey(key)) if (!Data.ContainsKey(key))
{ {
Data.Add(key, new MessageData(value)); Data.Add(key, new MessageData(value));
} }
} }
return this; return this;
} }
public SubscribeMessage WriteData(string prefix, IDictionary<string, object> setData) public SubscribeMessage WriteData(string prefix, IDictionary<string, object> setData)
{ {
foreach (var kv in setData) foreach (var kv in setData)
{ {
WriteData(prefix, kv.Key, kv.Value); WriteData(prefix, kv.Key, kv.Value);
} }
return this; return this;
} }
public SubscribeMessage WriteData(IDictionary<string, object> setData) public SubscribeMessage WriteData(IDictionary<string, object> setData)
{ {
foreach (var kv in setData) foreach (var kv in setData)
{ {
if (!Data.ContainsKey(kv.Key)) if (!Data.ContainsKey(kv.Key))
{ {
Data.Add(kv.Key, new MessageData(kv.Value)); Data.Add(kv.Key, new MessageData(kv.Value));
} }
} }
return this; return this;
} }
} }
public class MessageData public class MessageData
{ {
public object Value { get; } public object Value { get; }
public MessageData(object value) public MessageData(object value)
{ {
Value = value; Value = value;
} }
} }
} }

238
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.MiniProgram/LINGYUN/Abp/WeChat/MiniProgram/Messages/SubscribeMessager.cs

@ -1,121 +1,117 @@
using LINGYUN.Abp.WeChat.OpenId; using LINGYUN.Abp.WeChat.OpenId;
using LINGYUN.Abp.WeChat.Token; using LINGYUN.Abp.WeChat.Token;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages {
{ public class SubscribeMessager : ISubscribeMessager, ITransientDependency
public class SubscribeMessager : ISubscribeMessager, ITransientDependency {
{ public ILogger<SubscribeMessager> Logger { get; set; }
public ILogger<SubscribeMessager> Logger { get; set; } protected IHttpClientFactory HttpClientFactory { get; }
protected IHttpClientFactory HttpClientFactory { get; } protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; }
protected IJsonSerializer JsonSerializer { get; } protected IWeChatTokenProvider WeChatTokenProvider { get; }
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } protected IUserWeChatOpenIdFinder UserWeChatOpenIdFinder { get; }
protected IWeChatTokenProvider WeChatTokenProvider { get; } public SubscribeMessager(
protected IUserWeChatOpenIdFinder UserWeChatOpenIdFinder { get; } IHttpClientFactory httpClientFactory,
public SubscribeMessager( IWeChatTokenProvider weChatTokenProvider,
IJsonSerializer jsonSerializer, IUserWeChatOpenIdFinder userWeChatOpenIdFinder,
IHttpClientFactory httpClientFactory, AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory)
IWeChatTokenProvider weChatTokenProvider, {
IUserWeChatOpenIdFinder userWeChatOpenIdFinder, HttpClientFactory = httpClientFactory;
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) WeChatTokenProvider = weChatTokenProvider;
{ UserWeChatOpenIdFinder = userWeChatOpenIdFinder;
JsonSerializer = jsonSerializer; MiniProgramOptionsFactory = miniProgramOptionsFactory;
HttpClientFactory = httpClientFactory;
WeChatTokenProvider = weChatTokenProvider; Logger = NullLogger<SubscribeMessager>.Instance;
UserWeChatOpenIdFinder = userWeChatOpenIdFinder; }
MiniProgramOptionsFactory = miniProgramOptionsFactory;
public virtual async Task SendAsync(
Logger = NullLogger<SubscribeMessager>.Instance; Guid toUser,
} string templateId,
string page = "",
public virtual async Task SendAsync( string lang = "zh_CN",
Guid toUser, string state = "formal",
string templateId, Dictionary<string, object> data = null,
string page = "", CancellationToken cancellation = default)
string lang = "zh_CN", {
string state = "formal", var openId = await UserWeChatOpenIdFinder.FindByUserIdAsync(toUser, AbpWeChatMiniProgramConsts.ProviderName);
Dictionary<string, object> data = null, if (openId.IsNullOrWhiteSpace())
CancellationToken cancellation = default) {
{ Logger.LogWarning("Can not found openId, Unable to send WeChat message!");
var openId = await UserWeChatOpenIdFinder.FindByUserIdAsync(toUser, AbpWeChatMiniProgramConsts.ProviderKey); return;
if (openId.IsNullOrWhiteSpace()) }
{ var messageData = new SubscribeMessage(openId, templateId, page, state, lang);
Logger.LogWarning("Can not found openId, Unable to send WeChat message!"); if (data != null)
return; {
} messageData.WriteData(data);
var messageData = new SubscribeMessage(openId, templateId, page, state, lang); }
if (data != null) await SendAsync(messageData, cancellation);
{ }
messageData.WriteData(data);
} public virtual async Task SendAsync(SubscribeMessage message, CancellationToken cancellationToken = default)
await SendAsync(messageData, cancellation); {
} var options = await MiniProgramOptionsFactory.CreateAsync();
public virtual async Task SendAsync(SubscribeMessage message, CancellationToken cancellationToken = default) var weChatToken = await WeChatTokenProvider.GetTokenAsync(options.AppId, options.AppSecret, cancellationToken);
{ var requestParamters = new Dictionary<string, string>
var options = await MiniProgramOptionsFactory.CreateAsync(); {
{ "access_token", weChatToken.AccessToken }
var weChatToken = await WeChatTokenProvider.GetTokenAsync(options.AppId, options.AppSecret, cancellationToken); };
var requestParamters = new Dictionary<string, string> var weChatSendNotificationUrl = "https://api.weixin.qq.com";
{ var weChatSendNotificationPath = "/cgi-bin/message/subscribe/send";
{ "access_token", weChatToken.AccessToken } var requestUrl = BuildRequestUrl(weChatSendNotificationUrl, weChatSendNotificationPath, requestParamters);
}; var responseContent = await MakeRequestAndGetResultAsync(requestUrl, message, cancellationToken);
var weChatSendNotificationUrl = "https://api.weixin.qq.com"; var response = JsonConvert.DeserializeObject<SubscribeMessageResponse>(responseContent);
var weChatSendNotificationPath = "/cgi-bin/message/subscribe/send";
var requestUrl = BuildRequestUrl(weChatSendNotificationUrl, weChatSendNotificationPath, requestParamters); if (!response.IsSuccessed)
var responseContent = await MakeRequestAndGetResultAsync(requestUrl, message, cancellationToken); {
var response = JsonSerializer.Deserialize<SubscribeMessageResponse>(responseContent); Logger.LogWarning("Send wechat we app subscribe message failed");
Logger.LogWarning($"Error code: {response.ErrorCode}, message: {response.ErrorMessage}");
if (!response.IsSuccessed) }
{ }
Logger.LogWarning("Send wechat we app subscribe message failed");
Logger.LogWarning($"Error code: {response.ErrorCode}, message: {response.ErrorMessage}"); protected virtual async Task<string> MakeRequestAndGetResultAsync(string url, SubscribeMessage message, CancellationToken cancellationToken = default)
} {
} var client = HttpClientFactory.CreateClient(AbpWeChatMiniProgramConsts.HttpClient);
var sendDataContent = JsonConvert.SerializeObject(message);
protected virtual async Task<string> MakeRequestAndGetResultAsync(string url, SubscribeMessage message, CancellationToken cancellationToken = default) var requestContent = new StringContent(sendDataContent);
{ var requestMessage = new HttpRequestMessage(HttpMethod.Post, url)
var client = HttpClientFactory.CreateClient(AbpWeChatMiniProgramConsts.HttpClient); {
var sendDataContent = JsonSerializer.Serialize(message); Content = requestContent
var requestContent = new StringContent(sendDataContent); };
var requestMessage = new HttpRequestMessage(HttpMethod.Post, url)
{ var response = await client.SendAsync(requestMessage, cancellationToken);
Content = requestContent if (!response.IsSuccessStatusCode)
}; {
throw new AbpException($"WeChat send subscribe message http request service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}");
var response = await client.SendAsync(requestMessage, cancellationToken); }
if (!response.IsSuccessStatusCode) var resultContent = await response.Content.ReadAsStringAsync();
{
throw new AbpException($"WeChat send subscribe message http request service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}"); return resultContent;
} }
var resultContent = await response.Content.ReadAsStringAsync();
protected virtual string BuildRequestUrl(string uri, string path, IDictionary<string, string> paramters)
return resultContent; {
} var requestUrlBuilder = new StringBuilder(128);
requestUrlBuilder.Append(uri);
protected virtual string BuildRequestUrl(string uri, string path, IDictionary<string, string> paramters) requestUrlBuilder.Append(path).Append("?");
{ foreach (var paramter in paramters)
var requestUrlBuilder = new StringBuilder(128); {
requestUrlBuilder.Append(uri); requestUrlBuilder.AppendFormat("{0}={1}", paramter.Key, paramter.Value);
requestUrlBuilder.Append(path).Append("?"); requestUrlBuilder.Append("&");
foreach (var paramter in paramters) }
{ requestUrlBuilder.Remove(requestUrlBuilder.Length - 1, 1);
requestUrlBuilder.AppendFormat("{0}={1}", paramter.Key, paramter.Value); return requestUrlBuilder.ToString();
requestUrlBuilder.Append("&"); }
} }
requestUrlBuilder.Remove(requestUrlBuilder.Length - 1, 1); }
return requestUrlBuilder.ToString();
}
}
}

44
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.Official/LINGYUN/Abp/WeChat/Official/AbpWeChatOfficialConsts.cs

@ -1,22 +1,22 @@
namespace LINGYUN.Abp.WeChat.Official namespace LINGYUN.Abp.WeChat.Official
{ {
public class AbpWeChatOfficialConsts public class AbpWeChatOfficialConsts
{ {
/// <summary> /// <summary>
/// 微信公众号对应的Provider名称 /// 微信公众号对应的Provider名称
/// </summary> /// </summary>
public static string ProviderKey { get; set; } = "WeChat.Official"; public static string ProviderName { get; set; } = "WeChat.Official";
/// <summary> /// <summary>
/// 微信公众平台授权类型 /// 微信公众平台授权类型
/// </summary> /// </summary>
public static string GrantType { get; set; } = "wx-op"; public static string GrantType { get; set; } = "wx-op";
/// <summary> /// <summary>
/// 微信公众平台授权方法名称 /// 微信公众平台授权方法名称
/// </summary> /// </summary>
public static string AuthenticationMethod { get; set; } = "woa"; public static string AuthenticationMethod { get; set; } = "woa";
public static string HttpClient { get; set; } = "Abp.WeChat.Official"; public static string HttpClient { get; set; } = "Abp.WeChat.Official";
} }
} }

240
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat.SettingManagement/LINGYUN/Abp/WeChat/SettingManagement/WeChatSettingAppService.cs

@ -1,116 +1,124 @@
using LINGYUN.Abp.SettingManagement; using LINGYUN.Abp.SettingManagement;
using LINGYUN.Abp.WeChat.Localization; using LINGYUN.Abp.WeChat.Localization;
using LINGYUN.Abp.WeChat.MiniProgram.Settings; using LINGYUN.Abp.WeChat.MiniProgram.Settings;
using LINGYUN.Abp.WeChat.Official.Settings; using LINGYUN.Abp.WeChat.Official.Settings;
using System.Collections.Generic; using LINGYUN.Abp.WeChat.Settings;
using System.Threading.Tasks; using System.Collections.Generic;
using Volo.Abp.Application.Dtos; using System.Threading.Tasks;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Dtos;
using Volo.Abp.Authorization.Permissions; using Volo.Abp.Application.Services;
using Volo.Abp.MultiTenancy; using Volo.Abp.Authorization.Permissions;
using Volo.Abp.SettingManagement; using Volo.Abp.MultiTenancy;
using Volo.Abp.Settings; using Volo.Abp.SettingManagement;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.WeChat.SettingManagement
{ namespace LINGYUN.Abp.WeChat.SettingManagement
public class WeChatSettingAppService : ApplicationService, IWeChatSettingAppService {
{ public class WeChatSettingAppService : ApplicationService, IWeChatSettingAppService
protected ISettingManager SettingManager { get; } {
protected IPermissionChecker PermissionChecker { get; } protected ISettingManager SettingManager { get; }
protected ISettingDefinitionManager SettingDefinitionManager { get; } protected IPermissionChecker PermissionChecker { get; }
protected ISettingDefinitionManager SettingDefinitionManager { get; }
public WeChatSettingAppService(
ISettingManager settingManager, public WeChatSettingAppService(
IPermissionChecker permissionChecker, ISettingManager settingManager,
ISettingDefinitionManager settingDefinitionManager) IPermissionChecker permissionChecker,
{ ISettingDefinitionManager settingDefinitionManager)
SettingManager = settingManager; {
PermissionChecker = permissionChecker; SettingManager = settingManager;
SettingDefinitionManager = settingDefinitionManager; PermissionChecker = permissionChecker;
LocalizationResource = typeof(WeChatResource); SettingDefinitionManager = settingDefinitionManager;
} LocalizationResource = typeof(WeChatResource);
}
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync()
{ public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync()
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); {
} return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString());
}
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync()
{ public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync()
return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); {
} return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null);
}
protected virtual async Task<ListResultDto<SettingGroupDto>> GetAllForProviderAsync(string providerName, string providerKey)
{ protected virtual async Task<ListResultDto<SettingGroupDto>> GetAllForProviderAsync(string providerName, string providerKey)
var settingGroups = new List<SettingGroupDto>(); {
var wechatSettingGroup = new SettingGroupDto(L["DisplayName:WeChat"], L["Description:WeChat"]); var settingGroups = new List<SettingGroupDto>();
var wechatSettingGroup = new SettingGroupDto(L["DisplayName:WeChat"], L["Description:WeChat"]);
// 无权限返回空结果,直接报错的话,网关聚合会抛出异常
if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.Official)) var loginSetting = wechatSettingGroup.AddSetting(L["UserLogin"], L["UserLogin"]);
{ loginSetting.AddDetail(
#region 公众号 SettingDefinitionManager.Get(WeChatSettingNames.EnabledQuickLogin),
StringLocalizerFactory,
var officialSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.Official"], L["Description:WeChat.Official"]); await SettingManager.GetOrNullAsync(WeChatSettingNames.EnabledQuickLogin, providerName, providerKey),
officialSetting.AddDetail( ValueType.Boolean);
SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppId),
StringLocalizerFactory, // 无权限返回空结果,直接报错的话,网关聚合会抛出异常
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppId, providerName, providerKey), if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.Official))
ValueType.String); {
officialSetting.AddDetail( #region 公众号
SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppSecret),
StringLocalizerFactory, var officialSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.Official"], L["Description:WeChat.Official"]);
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppSecret, providerName, providerKey), officialSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppId),
officialSetting.AddDetail( StringLocalizerFactory,
SettingDefinitionManager.Get(WeChatOfficialSettingNames.Url), await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppId, providerName, providerKey),
StringLocalizerFactory, ValueType.String);
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Url, providerName, providerKey), officialSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppSecret),
officialSetting.AddDetail( StringLocalizerFactory,
SettingDefinitionManager.Get(WeChatOfficialSettingNames.Token), await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppSecret, providerName, providerKey),
StringLocalizerFactory, ValueType.String);
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Token, providerName, providerKey), officialSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatOfficialSettingNames.Url),
officialSetting.AddDetail( StringLocalizerFactory,
SettingDefinitionManager.Get(WeChatOfficialSettingNames.EncodingAESKey), await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Url, providerName, providerKey),
StringLocalizerFactory, ValueType.String);
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.EncodingAESKey, providerName, providerKey), officialSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatOfficialSettingNames.Token),
StringLocalizerFactory,
#endregion await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Token, providerName, providerKey),
} ValueType.String);
officialSetting.AddDetail(
if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.MiniProgram)) SettingDefinitionManager.Get(WeChatOfficialSettingNames.EncodingAESKey),
{ StringLocalizerFactory,
#region 小程序 await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.EncodingAESKey, providerName, providerKey),
ValueType.String);
var miniProgramSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.MiniProgram"], L["Description:WeChat.MiniProgram"]);
miniProgramSetting.AddDetail( #endregion
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppId), }
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppId, providerName, providerKey), if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.MiniProgram))
ValueType.String); {
miniProgramSetting.AddDetail( #region 小程序
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppSecret),
StringLocalizerFactory, var miniProgramSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.MiniProgram"], L["Description:WeChat.MiniProgram"]);
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppSecret, providerName, providerKey), miniProgramSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppId),
miniProgramSetting.AddDetail( StringLocalizerFactory,
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.Token), await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppId, providerName, providerKey),
StringLocalizerFactory, ValueType.String);
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.Token, providerName, providerKey), miniProgramSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppSecret),
miniProgramSetting.AddDetail( StringLocalizerFactory,
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.EncodingAESKey), await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppSecret, providerName, providerKey),
StringLocalizerFactory, ValueType.String);
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.EncodingAESKey, providerName, providerKey), miniProgramSetting.AddDetail(
ValueType.String); SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.Token),
StringLocalizerFactory,
#endregion await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.Token, providerName, providerKey),
} ValueType.String);
miniProgramSetting.AddDetail(
settingGroups.Add(wechatSettingGroup); SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.EncodingAESKey),
return new ListResultDto<SettingGroupDto>(settingGroups); StringLocalizerFactory,
} await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.EncodingAESKey, providerName, providerKey),
} ValueType.String);
}
#endregion
}
settingGroups.Add(wechatSettingGroup);
return new ListResultDto<SettingGroupDto>(settingGroups);
}
}
}

86
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/AbpWeChatModule.cs

@ -1,42 +1,44 @@
using LINGYUN.Abp.WeChat.Localization; using LINGYUN.Abp.WeChat.Localization;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Polly; using Polly;
using System; using System;
using Volo.Abp.Caching; using Volo.Abp.Caching;
using Volo.Abp.Features; using Volo.Abp.Features;
using Volo.Abp.Json; using Volo.Abp.Json;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.Settings;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.WeChat
{ namespace LINGYUN.Abp.WeChat
[DependsOn( {
typeof(AbpCachingModule), [DependsOn(
typeof(AbpFeaturesModule), typeof(AbpCachingModule),
typeof(AbpJsonModule))] typeof(AbpFeaturesModule),
public class AbpWeChatModule : AbpModule typeof(AbpJsonModule),
{ typeof(AbpSettingsModule))]
public override void ConfigureServices(ServiceConfigurationContext context) public class AbpWeChatModule : AbpModule
{ {
Configure<AbpVirtualFileSystemOptions>(options => public override void ConfigureServices(ServiceConfigurationContext context)
{ {
options.FileSets.AddEmbedded<AbpWeChatModule>(); Configure<AbpVirtualFileSystemOptions>(options =>
}); {
options.FileSets.AddEmbedded<AbpWeChatModule>();
Configure<AbpLocalizationOptions>(options => });
{
options.Resources Configure<AbpLocalizationOptions>(options =>
.Add<WeChatResource>("zh-Hans") {
.AddVirtualJson("/LINGYUN/Abp/WeChat/Localization/Resources"); options.Resources
}); .Add<WeChatResource>("zh-Hans")
.AddVirtualJson("/LINGYUN/Abp/WeChat/Localization/Resources");
context.Services.AddHttpClient(AbpWeChatGlobalConsts.HttpClient, });
options =>
{ context.Services.AddHttpClient(AbpWeChatGlobalConsts.HttpClient,
options.BaseAddress = new Uri("https://api.weixin.qq.com"); options =>
}).AddTransientHttpErrorPolicy(builder => {
builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)))); options.BaseAddress = new Uri("https://api.weixin.qq.com");
} }).AddTransientHttpErrorPolicy(builder =>
} builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i))));
} }
}
}

7
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Crypto/IWeChatCryptoService.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Abp.WeChat.Crypto
{
public interface IWeChatCryptoService
{
string Decrypt(string encryptedData, string iv, string sessionKey);
}
}

36
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Crypto/WeChatCryptoService.cs

@ -0,0 +1,36 @@
using System;
using System.Security.Cryptography;
using System.Text;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WeChat.Crypto
{
public class WeChatCryptoService : IWeChatCryptoService, ITransientDependency
{
public virtual string Decrypt(string encryptedData, string iv, string sessionKey)
{
using var aes = new AesCryptoServiceProvider();
aes.Mode = CipherMode.CBC;
aes.BlockSize = 128;
// 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
aes.Padding = PaddingMode.PKCS7;
//格式化待处理字符串
// 对称解密的目标密文为 Base64_Decode(encryptedData)。
byte[] byte_encryptedData = Convert.FromBase64String(encryptedData);
// 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。
byte[] byte_iv = Convert.FromBase64String(iv);
// 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
byte[] byte_sessionKey = Convert.FromBase64String(sessionKey);
//根据设置好的数据生成解密器实例
using var transform = aes.CreateDecryptor(byte_iv, byte_sessionKey);
//解密
byte[] final = transform.TransformFinalBlock(byte_encryptedData, 0, byte_encryptedData.Length);
//生成结果
string result = Encoding.UTF8.GetString(final);
return result;
}
}
}

5
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Localization/Resources/en.json

@ -4,6 +4,9 @@
"Features:WeChat": "WeChat", "Features:WeChat": "WeChat",
"Permission:WeChat": "WeChat", "Permission:WeChat": "WeChat",
"DisplayName:WeChat": "WeChat", "DisplayName:WeChat": "WeChat",
"Description:WeChat": "WeChat" "Description:WeChat": "WeChat",
"UserLogin": "User Login",
"DisplayName:WeChat.EnabledQuickLogin": "Enabled Quick Login",
"Description:WeChat.EnabledQuickLogin": "Users can login directly with the code given by wx.login when they are not registered"
} }
} }

5
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Localization/Resources/zh-Hans.json

@ -4,6 +4,9 @@
"Features:WeChat": "微信开发", "Features:WeChat": "微信开发",
"Permission:WeChat": "微信开发", "Permission:WeChat": "微信开发",
"DisplayName:WeChat": "微信开发平台", "DisplayName:WeChat": "微信开发平台",
"Description:WeChat": "微信开发平台" "Description:WeChat": "微信开发平台",
"UserLogin": "用户登录",
"DisplayName:WeChat.EnabledQuickLogin": "启用快捷登录",
"Description:WeChat.EnabledQuickLogin": "用户可在未注册时通过 wx.login 得到的code直接登录"
} }
} }

24
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/IUserWeChatOpenIdFinder.cs

@ -1,12 +1,12 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.OpenId namespace LINGYUN.Abp.WeChat.OpenId
{ {
public interface IUserWeChatOpenIdFinder public interface IUserWeChatOpenIdFinder
{ {
Task<string> FindByUserIdAsync(Guid userId, string provider); Task<string> FindByUserIdAsync(Guid userId, string provider);
Task<string> FindByUserNameAsync(string userName, string provider); Task<string> FindByUserNameAsync(string userName, string provider);
} }
} }

26
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/IWeChatOpenIdFinder.cs

@ -1,9 +1,17 @@
using System.Threading.Tasks; using System.Threading.Tasks;
namespace LINGYUN.Abp.WeChat.OpenId namespace LINGYUN.Abp.WeChat.OpenId
{ {
public interface IWeChatOpenIdFinder public interface IWeChatOpenIdFinder
{ {
Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret); Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret);
} /// <summary>
} /// 获取当前登录用户OpenId
/// </summary>
/// <param name="appId">应用标识</param>
/// <returns></returns>
/// <exception cref="Volo.Abp.Authorization.AbpAuthorizationException">用户未登录时</exception>
/// <exception cref="Volo.Abp.AbpException">微信sessionKey过期时</exception>
Task<WeChatOpenId> FindAsync(string appId);
}
}

56
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdCacheItem.cs

@ -1,24 +1,32 @@
namespace LINGYUN.Abp.WeChat.OpenId using System;
{
public class WeChatOpenIdCacheItem namespace LINGYUN.Abp.WeChat.OpenId
{ {
public string Code { get; set; } public class WeChatOpenIdCacheItem
{
public WeChatOpenId WeChatOpenId { get; set; } public string Code { get; set; }
public WeChatOpenIdCacheItem()
{ public WeChatOpenId WeChatOpenId { get; set; }
public WeChatOpenIdCacheItem()
} {
public WeChatOpenIdCacheItem(string code, WeChatOpenId weChatOpenId) }
{
Code = code; public WeChatOpenIdCacheItem(string code, WeChatOpenId weChatOpenId)
WeChatOpenId = weChatOpenId; {
} Code = code;
WeChatOpenId = weChatOpenId;
public static string CalculateCacheKey(string appId, string code) }
{
return "app:" + appId + ";code:" + code; public static string CalculateCacheKey(string appId, Guid userId)
} {
} return "app:" + appId + ";user:" + userId.ToString("D");
} }
public static string CalculateCacheKey(string appId, string code)
{
return "app:" + appId + ";code:" + code;
}
}
}

212
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdFinder.cs

@ -1,95 +1,117 @@
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using System; using Newtonsoft.Json;
using System.Net.Http; using System;
using System.Threading.Tasks; using System.Net.Http;
using Volo.Abp.Caching; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp;
using Volo.Abp.Json; using Volo.Abp.Authorization;
using Volo.Abp.MultiTenancy; using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WeChat.OpenId using Volo.Abp.MultiTenancy;
{ using Volo.Abp.Users;
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)]
[ExposeServices(typeof(IWeChatOpenIdFinder))] namespace LINGYUN.Abp.WeChat.OpenId
public class WeChatOpenIdFinder : IWeChatOpenIdFinder {
{ [Dependency(ServiceLifetime.Singleton, ReplaceServices = true)]
public ILogger<WeChatOpenIdFinder> Logger { get; set; } [ExposeServices(typeof(IWeChatOpenIdFinder))]
protected ICurrentTenant CurrentTenant { get; } public class WeChatOpenIdFinder : IWeChatOpenIdFinder
protected IHttpClientFactory HttpClientFactory { get; } {
protected IJsonSerializer JsonSerializer { get; } public ILogger<WeChatOpenIdFinder> Logger { get; set; }
protected IDistributedCache<WeChatOpenIdCacheItem> Cache { get; } protected ICurrentTenant CurrentTenant { get; }
public WeChatOpenIdFinder( protected ICurrentUser CurrentUser { get; }
ICurrentTenant currentTenant, protected IHttpClientFactory HttpClientFactory { get; }
IJsonSerializer jsonSerializer, protected IDistributedCache<WeChatOpenIdCacheItem> Cache { get; }
IHttpClientFactory httpClientFactory, public WeChatOpenIdFinder(
IDistributedCache<WeChatOpenIdCacheItem> cache) ICurrentUser currentUser,
{ ICurrentTenant currentTenant,
CurrentTenant = currentTenant; IHttpClientFactory httpClientFactory,
JsonSerializer = jsonSerializer; IDistributedCache<WeChatOpenIdCacheItem> cache)
HttpClientFactory = httpClientFactory; {
CurrentUser = currentUser;
Cache = cache; CurrentTenant = currentTenant;
HttpClientFactory = httpClientFactory;
Logger = NullLogger<WeChatOpenIdFinder>.Instance;
} Cache = cache;
public virtual async Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret)
{ Logger = NullLogger<WeChatOpenIdFinder>.Instance;
// TODO: 如果需要获取SessionKey的话呢,需要再以openid作为标识来缓存一下吗 }
// 或者前端保存code,通过传递code来获取
return (await GetCacheItemAsync(code, appId, appSecret)).WeChatOpenId; public virtual async Task<WeChatOpenId> FindAsync(string appId)
} {
if (!CurrentUser.IsAuthenticated)
protected virtual async Task<WeChatOpenIdCacheItem> GetCacheItemAsync(string code, string appId, string appSecret) {
{ throw new AbpAuthorizationException("Try to get wechat information when the user is not logged in!");
var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(appId, code); }
var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(appId, CurrentUser.Id.Value);
Logger.LogDebug($"WeChatOpenIdFinder.GetCacheItemAsync: {cacheKey}"); var openIdCache = await Cache.GetAsync(cacheKey);
return openIdCache?.WeChatOpenId ??
var cacheItem = await Cache.GetAsync(cacheKey); throw new AbpException("The wechat login session has expired. Use 'wx.login' result code to exchange the sessionKey");
}
if (cacheItem != null)
{ public virtual async Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret)
Logger.LogDebug($"Found in the cache: {cacheKey}"); {
return cacheItem; // TODO: 如果需要获取SessionKey的话呢,需要再以openid作为标识来缓存一下吗
} // 或者前端保存code,通过传递code来获取
return (await GetCacheItemAsync(code, appId, appSecret)).WeChatOpenId;
Logger.LogDebug($"Not found in the cache, getting from the httpClient: {cacheKey}"); }
var client = HttpClientFactory.CreateClient(AbpWeChatGlobalConsts.HttpClient); protected virtual async Task<WeChatOpenIdCacheItem> GetCacheItemAsync(string code, string appId, string appSecret)
{
var request = new WeChatOpenIdRequest var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(appId, code);
{
BaseUrl = client.BaseAddress.AbsoluteUri, Logger.LogDebug($"WeChatOpenIdFinder.GetCacheItemAsync: {cacheKey}");
AppId = appId,
Secret = appSecret, var cacheItem = await Cache.GetAsync(cacheKey);
Code = code
}; if (cacheItem != null)
{
var response = await client.RequestWeChatOpenIdAsync(request); Logger.LogDebug($"Found in the cache: {cacheKey}");
var responseContent = await response.Content.ReadAsStringAsync(); return cacheItem;
var weChatOpenIdResponse = JsonSerializer.Deserialize<WeChatOpenIdResponse>(responseContent); }
var weChatOpenId = weChatOpenIdResponse.ToWeChatOpenId();
cacheItem = new WeChatOpenIdCacheItem(code, weChatOpenId); Logger.LogDebug($"Not found in the cache, getting from the httpClient: {cacheKey}");
Logger.LogDebug($"Setting the cache item: {cacheKey}"); var client = HttpClientFactory.CreateClient(AbpWeChatGlobalConsts.HttpClient);
var cacheOptions = new DistributedCacheEntryOptions var request = new WeChatOpenIdRequest
{ {
// 微信官方文档表示 session_key的有效期是3天 BaseUrl = client.BaseAddress.AbsoluteUri,
// https://developers.weixin.qq.com/community/develop/doc/000c2424654c40bd9c960e71e5b009 AppId = appId,
AbsoluteExpiration = DateTimeOffset.Now.AddDays(3).AddSeconds(-120) Secret = appSecret,
// SlidingExpiration = TimeSpan.FromDays(3), Code = code
}; };
var response = await client.RequestWeChatOpenIdAsync(request);
await Cache.SetAsync(cacheKey, cacheItem, cacheOptions); var responseContent = await response.Content.ReadAsStringAsync();
// 改为直接引用 Newtownsoft.Json
Logger.LogDebug($"Finished setting the cache item: {cacheKey}"); var weChatOpenIdResponse = JsonConvert.DeserializeObject<WeChatOpenIdResponse>(responseContent);
var weChatOpenId = weChatOpenIdResponse.ToWeChatOpenId();
return cacheItem; cacheItem = new WeChatOpenIdCacheItem(code, weChatOpenId);
}
} Logger.LogDebug($"Setting the cache item: {cacheKey}");
}
var cacheOptions = new DistributedCacheEntryOptions
{
// 微信官方文档表示 session_key的有效期是3天
// https://developers.weixin.qq.com/community/develop/doc/000c2424654c40bd9c960e71e5b009
AbsoluteExpiration = DateTimeOffset.Now.AddDays(3).AddSeconds(-120)
// SlidingExpiration = TimeSpan.FromDays(3),
};
await Cache.SetAsync(cacheKey, cacheItem, cacheOptions);
if (CurrentUser.IsAuthenticated)
{
await Cache.SetAsync(WeChatOpenIdCacheItem.CalculateCacheKey(appId, CurrentUser.Id.Value), cacheItem, cacheOptions);
}
Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
return cacheItem;
}
}
}

126
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/OpenId/WeChatOpenIdResponse.cs

@ -1,63 +1,63 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using Volo.Abp; using Volo.Abp;
namespace LINGYUN.Abp.WeChat.OpenId namespace LINGYUN.Abp.WeChat.OpenId
{ {
/// <summary> /// <summary>
/// 微信OpenId返回对象 /// 微信OpenId返回对象
/// </summary> /// </summary>
public class WeChatOpenIdResponse public class WeChatOpenIdResponse
{ {
/// <summary> /// <summary>
/// 错误码 /// 错误码
/// </summary> /// </summary>
[JsonProperty("errcode")] [JsonProperty("errcode")]
public string ErrorCode { get; set; } public string ErrorCode { get; set; }
/// <summary> /// <summary>
/// 会话密钥 /// 会话密钥
/// </summary> /// </summary>
[JsonProperty("session_key")] [JsonProperty("session_key")]
public string SessionKey { get; set; } public string SessionKey { get; set; }
/// <summary> /// <summary>
/// 用户唯一标识 /// 用户唯一标识
/// </summary> /// </summary>
[JsonProperty("openid")] [JsonProperty("openid")]
public string OpenId { get; set; } public string OpenId { get; set; }
/// <summary> /// <summary>
/// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回 /// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回
/// </summary> /// </summary>
[JsonProperty("unionid")] [JsonProperty("unionid")]
public string UnionId { get; set; } public string UnionId { get; set; }
/// <summary> /// <summary>
/// 错误消息 /// 错误消息
/// </summary> /// </summary>
public string ErrorMessage public string ErrorMessage
{ {
get get
{ {
switch (ErrorCode) switch (ErrorCode)
{ {
case "-1": return "系统繁忙,此时请开发者稍候再试"; case "-1": return "系统繁忙,此时请开发者稍候再试";
case "0": return string.Empty; case "0": return string.Empty;
case "40029": return "code 无效"; case "40029": return "code 无效";
case "45011": return "频率限制,每个用户每分钟100次"; case "45011": return "频率限制,每个用户每分钟100次";
default: return $"未定义的异常代码:{ErrorCode},请重试"; default: return $"未定义的异常代码:{ErrorCode},请重试";
}; };
} }
} }
/// <summary> /// <summary>
/// 微信认证成功没有errorcode或者errorcode为0 /// 微信认证成功没有errorcode或者errorcode为0
/// </summary> /// </summary>
public bool IsError => !ErrorCode.IsNullOrWhiteSpace() && !"0".Equals(ErrorCode); public bool IsError => !ErrorCode.IsNullOrWhiteSpace() && !"0".Equals(ErrorCode);
public WeChatOpenId ToWeChatOpenId() public WeChatOpenId ToWeChatOpenId()
{ {
if(IsError) if(IsError)
{ {
throw new AbpException(ErrorMessage); throw new AbpException(ErrorMessage);
} }
return new WeChatOpenId(OpenId, SessionKey, UnionId); return new WeChatOpenId(OpenId, SessionKey, UnionId);
} }
} }
} }

28
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Settings/WeChatSettingDefinitionProvider.cs

@ -0,0 +1,28 @@
using LINGYUN.Abp.WeChat.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.WeChat.Settings
{
public class WeChatSettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(
new SettingDefinition(
WeChatSettingNames.EnabledQuickLogin,
// 默认启用
true.ToString(),
L("DisplayName:WeChat.EnabledQuickLogin"),
L("Description:WeChat.EnabledQuickLogin"),
isVisibleToClients: true,
isEncrypted: false)
);
}
protected ILocalizableString L(string name)
{
return LocalizableString.Create<WeChatResource>(name);
}
}
}

19
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Settings/WeChatSettingNames.cs

@ -1,7 +1,12 @@
namespace LINGYUN.Abp.WeChat.Settings namespace LINGYUN.Abp.WeChat.Settings
{ {
public static class WeChatSettingNames public static class WeChatSettingNames
{ {
public const string Prefix = "Abp.WeChat"; public const string Prefix = "Abp.WeChat";
} /// <summary>
} /// 启用快捷登录
/// 通过微信code登录时,如果没有注册用户信息且此配置启用时,直接创建新用户并关联openid
/// </summary>
public const string EnabledQuickLogin = Prefix + ".EnabledQuickLogin";
}
}

182
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenProvider.cs

@ -1,92 +1,90 @@
using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using System; using Newtonsoft.Json;
using System.Net.Http; using System;
using System.Threading; using System.Net.Http;
using System.Threading.Tasks; using System.Threading;
using Volo.Abp.Caching; using System.Threading.Tasks;
using Volo.Abp.DependencyInjection; using Volo.Abp.Caching;
using Volo.Abp.Json; using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WeChat.Token namespace LINGYUN.Abp.WeChat.Token
{ {
public class WeChatTokenProvider : IWeChatTokenProvider, ISingletonDependency public class WeChatTokenProvider : IWeChatTokenProvider, ISingletonDependency
{ {
public ILogger<WeChatTokenProvider> Logger { get; set; } public ILogger<WeChatTokenProvider> Logger { get; set; }
protected IHttpClientFactory HttpClientFactory { get; } protected IHttpClientFactory HttpClientFactory { get; }
protected IJsonSerializer JsonSerializer { get; } protected IDistributedCache<WeChatTokenCacheItem> Cache { get; }
protected IDistributedCache<WeChatTokenCacheItem> Cache { get; } public WeChatTokenProvider(
public WeChatTokenProvider( IHttpClientFactory httpClientFactory,
IJsonSerializer jsonSerializer, IDistributedCache<WeChatTokenCacheItem> cache)
IHttpClientFactory httpClientFactory, {
IDistributedCache<WeChatTokenCacheItem> cache) HttpClientFactory = httpClientFactory;
{
JsonSerializer = jsonSerializer; Cache = cache;
HttpClientFactory = httpClientFactory;
Logger = NullLogger<WeChatTokenProvider>.Instance;
Cache = cache; }
Logger = NullLogger<WeChatTokenProvider>.Instance; public virtual async Task<WeChatToken> GetTokenAsync(
} string appId,
string appSecret,
public virtual async Task<WeChatToken> GetTokenAsync( CancellationToken cancellationToken = default)
string appId, {
string appSecret, return (await GetCacheItemAsync("WeChatToken", appId, appSecret, cancellationToken)).WeChatToken;
CancellationToken cancellationToken = default) }
{
return (await GetCacheItemAsync("WeChatToken", appId, appSecret, cancellationToken)).WeChatToken; protected virtual async Task<WeChatTokenCacheItem> GetCacheItemAsync(
} string provider,
string appId,
protected virtual async Task<WeChatTokenCacheItem> GetCacheItemAsync( string appSecret,
string provider, CancellationToken cancellationToken = default)
string appId, {
string appSecret, var cacheKey = WeChatTokenCacheItem.CalculateCacheKey(provider, appId);
CancellationToken cancellationToken = default)
{ Logger.LogDebug($"WeChatTokenProvider.GetCacheItemAsync: {cacheKey}");
var cacheKey = WeChatTokenCacheItem.CalculateCacheKey(provider, appId);
var cacheItem = await Cache.GetAsync(cacheKey, token: cancellationToken);
Logger.LogDebug($"WeChatTokenProvider.GetCacheItemAsync: {cacheKey}");
if (cacheItem != null)
var cacheItem = await Cache.GetAsync(cacheKey, token: cancellationToken); {
Logger.LogDebug($"Found in the cache: {cacheKey}");
if (cacheItem != null) return cacheItem;
{ }
Logger.LogDebug($"Found in the cache: {cacheKey}");
return cacheItem; Logger.LogDebug($"Not found in the cache, getting from the httpClient: {cacheKey}");
}
var client = HttpClientFactory.CreateClient(AbpWeChatGlobalConsts.HttpClient);
Logger.LogDebug($"Not found in the cache, getting from the httpClient: {cacheKey}");
var request = new WeChatTokenRequest
var client = HttpClientFactory.CreateClient(AbpWeChatGlobalConsts.HttpClient); {
BaseUrl = client.BaseAddress.AbsoluteUri,
var request = new WeChatTokenRequest AppSecret = appSecret,
{ AppId = appId,
BaseUrl = client.BaseAddress.AbsoluteUri, GrantType = "client_credential"
AppSecret = appSecret, };
AppId = appId,
GrantType = "client_credential" var response = await client.RequestWeChatCodeTokenAsync(request, cancellationToken);
}; var responseContent = await response.Content.ReadAsStringAsync();
// 改为直接引用 Newtownsoft.Json
var response = await client.RequestWeChatCodeTokenAsync(request, cancellationToken); var weChatTokenResponse = JsonConvert.DeserializeObject<WeChatTokenResponse>(responseContent);
var responseContent = await response.Content.ReadAsStringAsync(); var weChatToken = weChatTokenResponse.ToWeChatToken();
var weChatTokenResponse = JsonSerializer.Deserialize<WeChatTokenResponse>(responseContent); cacheItem = new WeChatTokenCacheItem(appId, weChatToken);
var weChatToken = weChatTokenResponse.ToWeChatToken();
cacheItem = new WeChatTokenCacheItem(appId, weChatToken); Logger.LogDebug($"Setting the cache item: {cacheKey}");
Logger.LogDebug($"Setting the cache item: {cacheKey}"); var cacheOptions = new DistributedCacheEntryOptions
{
var cacheOptions = new DistributedCacheEntryOptions // 设置绝对过期时间为Token有效期剩余的二分钟
{ AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(weChatToken.ExpiresIn - 120)
// 设置绝对过期时间为Token有效期剩余的二分钟 };
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(weChatToken.ExpiresIn - 120)
}; await Cache.SetAsync(cacheKey, cacheItem, cacheOptions, token: cancellationToken);
await Cache.SetAsync(cacheKey, cacheItem, cacheOptions, token: cancellationToken); Logger.LogDebug($"Finished setting the cache item: {cacheKey}");
Logger.LogDebug($"Finished setting the cache item: {cacheKey}"); return cacheItem;
}
return cacheItem; }
} }
}
}

82
aspnet-core/modules/wechat/LINGYUN.Abp.WeChat/LINGYUN/Abp/WeChat/Token/WeChatTokenResponse.cs

@ -1,41 +1,41 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Volo.Abp; using Volo.Abp;
namespace LINGYUN.Abp.WeChat.Token namespace LINGYUN.Abp.WeChat.Token
{ {
/// <summary> /// <summary>
/// 微信访问令牌返回对象 /// 微信访问令牌返回对象
/// </summary> /// </summary>
public class WeChatTokenResponse public class WeChatTokenResponse
{ {
/// <summary> /// <summary>
/// 错误码 /// 错误码
/// </summary> /// </summary>
[JsonProperty("errcode")] [JsonProperty("errcode")]
public int ErrorCode { get; set; } public int ErrorCode { get; set; }
/// <summary> /// <summary>
/// 错误消息 /// 错误消息
/// </summary> /// </summary>
[JsonProperty("errmsg")] [JsonProperty("errmsg")]
public string ErrorMessage { get; set; } public string ErrorMessage { get; set; }
/// <summary> /// <summary>
/// 访问令牌 /// 访问令牌
/// </summary> /// </summary>
[JsonProperty("access_token")] [JsonProperty("access_token")]
public string AccessToken { get; set; } public string AccessToken { get; set; }
/// <summary> /// <summary>
/// 过期时间,单位(s) /// 过期时间,单位(s)
/// </summary> /// </summary>
[JsonProperty("expires_in")] [JsonProperty("expires_in")]
public int ExpiresIn { get; set; } public int ExpiresIn { get; set; }
public WeChatToken ToWeChatToken() public WeChatToken ToWeChatToken()
{ {
if(ErrorCode != 0) if(ErrorCode != 0)
{ {
throw new AbpException(ErrorMessage); throw new AbpException(ErrorMessage);
} }
return new WeChatToken(AccessToken, ExpiresIn); return new WeChatToken(AccessToken, ExpiresIn);
} }
} }
} }

624
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/AbpMessageServiceHttpApiHostModule.cs

@ -1,310 +1,314 @@
using DotNetCore.CAP; using DotNetCore.CAP;
using Hangfire; using Hangfire;
using LINGYUN.Abp.AspNetCore.HttpOverrides; using LINGYUN.Abp.AspNetCore.HttpOverrides;
using LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json; using LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json;
using LINGYUN.Abp.BackgroundJobs.Hangfire; using LINGYUN.Abp.BackgroundJobs.Hangfire;
using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.EventBus.CAP;
using LINGYUN.Abp.ExceptionHandling; using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Notifications; using LINGYUN.Abp.ExceptionHandling.Notifications;
using LINGYUN.Abp.Hangfire.Storage.MySql; using LINGYUN.Abp.Hangfire.Storage.MySql;
using LINGYUN.Abp.IM.SignalR; using LINGYUN.Abp.Identity.WeChat;
using LINGYUN.Abp.MessageService.EntityFrameworkCore; using LINGYUN.Abp.IM.SignalR;
using LINGYUN.Abp.MessageService.Localization; using LINGYUN.Abp.MessageService.EntityFrameworkCore;
using LINGYUN.Abp.MultiTenancy.DbFinder; using LINGYUN.Abp.MessageService.Localization;
using LINGYUN.Abp.Notifications.SignalR; using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.Notifications.Sms; using LINGYUN.Abp.Notifications.SignalR;
using LINGYUN.Abp.Notifications.WeChat.MiniProgram; using LINGYUN.Abp.Notifications.Sms;
using Microsoft.AspNetCore.Authentication.JwtBearer; using LINGYUN.Abp.Notifications.WeChat.MiniProgram;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Caching.StackExchangeRedis; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models; using Microsoft.Extensions.Hosting;
using StackExchange.Redis; using Microsoft.OpenApi.Models;
using System; using StackExchange.Redis;
using System.Collections.Generic; using System;
using System.Linq; using System.Collections.Generic;
using System.Text; using System.Linq;
using System.Text.Encodings.Web; using System.Text;
using System.Text.Unicode; using System.Text.Encodings.Web;
using Volo.Abp; using System.Text.Unicode;
using Volo.Abp.AspNetCore.Auditing; using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Auditing;
using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Security.Claims; using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Uow; using Volo.Abp.AspNetCore.Security.Claims;
using Volo.Abp.Autofac; using Volo.Abp.AspNetCore.Uow;
using Volo.Abp.BackgroundWorkers; using Volo.Abp.Autofac;
using Volo.Abp.Caching; using Volo.Abp.BackgroundWorkers;
using Volo.Abp.Caching.StackExchangeRedis; using Volo.Abp.Caching;
using Volo.Abp.EntityFrameworkCore; using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Json; using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.Localization; using Volo.Abp.Json;
using Volo.Abp.Modularity; using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.MultiTenancy; using Volo.Abp.Localization;
using Volo.Abp.PermissionManagement.EntityFrameworkCore; using Volo.Abp.Modularity;
using Volo.Abp.Security.Claims; using Volo.Abp.MultiTenancy;
using Volo.Abp.Security.Encryption; using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.Security.Claims;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.Security.Encryption;
using Volo.Abp.VirtualFileSystem; using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
namespace LINGYUN.Abp.MessageService using Volo.Abp.VirtualFileSystem;
{
[DependsOn( namespace LINGYUN.Abp.MessageService
typeof(AbpMessageServiceApplicationModule), {
typeof(AbpMessageServiceHttpApiModule), [DependsOn(
typeof(AbpAspNetCoreMultiTenancyModule), typeof(AbpMessageServiceApplicationModule),
typeof(AbpMessageServiceEntityFrameworkCoreModule), typeof(AbpMessageServiceHttpApiModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule), typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule), typeof(AbpIdentityWeChatModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpMessageServiceEntityFrameworkCoreModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpIdentityEntityFrameworkCoreModule),
typeof(AbpHangfireMySqlStorageModule), typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpBackgroundJobsHangfireModule), typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpBackgroundWorkersModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpIMSignalRModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpNotificationsSmsModule), typeof(AbpHangfireMySqlStorageModule),
typeof(AbpNotificationsSignalRModule), typeof(AbpBackgroundJobsHangfireModule),
typeof(AbpNotificationsWeChatMiniProgramModule), typeof(AbpBackgroundWorkersModule),
typeof(AbpNotificationsExceptionHandlingModule), typeof(AbpIMSignalRModule),
typeof(AbpAspNetCoreSignalRProtocolJsonModule), typeof(AbpNotificationsSmsModule),
typeof(AbpCAPEventBusModule), typeof(AbpNotificationsSignalRModule),
typeof(AbpDbFinderMultiTenancyModule), typeof(AbpNotificationsWeChatMiniProgramModule),
typeof(AbpCachingStackExchangeRedisModule), typeof(AbpNotificationsExceptionHandlingModule),
typeof(AbpAspNetCoreHttpOverridesModule), typeof(AbpAspNetCoreSignalRProtocolJsonModule),
typeof(AbpAutofacModule) typeof(AbpCAPEventBusModule),
)] typeof(AbpDbFinderMultiTenancyModule),
public class AbpMessageServiceHttpApiHostModule : AbpModule typeof(AbpCachingStackExchangeRedisModule),
{ typeof(AbpAspNetCoreHttpOverridesModule),
private const string DefaultCorsPolicyName = "Default"; typeof(AbpAutofacModule)
)]
public override void PreConfigureServices(ServiceConfigurationContext context) public class AbpMessageServiceHttpApiHostModule : AbpModule
{ {
var configuration = context.Services.GetConfiguration(); private const string DefaultCorsPolicyName = "Default";
PreConfigure<CapOptions>(options => public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
options var configuration = context.Services.GetConfiguration();
.UseMySql(configuration.GetConnectionString("Default"))
.UseRabbitMQ(rabbitMQOptions => PreConfigure<CapOptions>(options =>
{ {
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); options
}) .UseMySql(configuration.GetConnectionString("Default"))
.UseDashboard(); .UseRabbitMQ(rabbitMQOptions =>
}); {
} configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions);
})
public override void ConfigureServices(ServiceConfigurationContext context) .UseDashboard();
{ });
var hostingEnvironment = context.Services.GetHostingEnvironment(); }
var configuration = hostingEnvironment.BuildConfiguration();
public override void ConfigureServices(ServiceConfigurationContext context)
// 配置Ef {
Configure<AbpDbContextOptions>(options => var hostingEnvironment = context.Services.GetHostingEnvironment();
{ var configuration = hostingEnvironment.BuildConfiguration();
options.UseMySQL();
}); // 配置Ef
Configure<AbpDbContextOptions>(options =>
Configure<AbpAspNetCoreAuditingOptions>(options => {
{ options.UseMySQL();
options.IgnoredUrls.AddIfNotContains("/hangfire"); });
});
Configure<AbpAspNetCoreAuditingOptions>(options =>
// 中文序列化的编码问题 {
Configure<AbpSystemTextJsonSerializerOptions>(options => options.IgnoredUrls.AddIfNotContains("/hangfire");
{ });
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
}); // 中文序列化的编码问题
Configure<AbpSystemTextJsonSerializerOptions>(options =>
// 加解密 {
Configure<AbpStringEncryptionOptions>(options => options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
{ });
var encryptionConfiguration = configuration.GetSection("Encryption");
if (encryptionConfiguration.Exists()) // 加解密
{ Configure<AbpStringEncryptionOptions>(options =>
options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase; {
options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists() var encryptionConfiguration = configuration.GetSection("Encryption");
? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"]) if (encryptionConfiguration.Exists())
: options.DefaultSalt; {
options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists() options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase;
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"]) options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists()
: options.InitVectorBytes; ? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"])
} : options.DefaultSalt;
}); options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists()
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"])
Configure<AbpExceptionHandlingOptions>(options => : options.InitVectorBytes;
{ }
// 加入需要处理的异常类型 });
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>();
options.Handlers.Add<AbpInitializationException>(); Configure<AbpExceptionHandlingOptions>(options =>
options.Handlers.Add<ObjectDisposedException>(); {
options.Handlers.Add<StackOverflowException>(); // 加入需要处理的异常类型
options.Handlers.Add<OutOfMemoryException>(); options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>();
options.Handlers.Add<System.Data.Common.DbException>(); options.Handlers.Add<AbpInitializationException>();
options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>(); options.Handlers.Add<ObjectDisposedException>();
options.Handlers.Add<System.Data.DBConcurrencyException>(); options.Handlers.Add<StackOverflowException>();
}); options.Handlers.Add<OutOfMemoryException>();
options.Handlers.Add<System.Data.Common.DbException>();
Configure<AbpVirtualFileSystemOptions>(options => options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>();
{ options.Handlers.Add<System.Data.DBConcurrencyException>();
options.FileSets.AddEmbedded<AbpMessageServiceHttpApiHostModule>("LINGYUN.Abp.MessageService"); });
});
Configure<AbpVirtualFileSystemOptions>(options =>
// 多租户 {
Configure<AbpMultiTenancyOptions>(options => options.FileSets.AddEmbedded<AbpMessageServiceHttpApiHostModule>("LINGYUN.Abp.MessageService");
{ });
options.IsEnabled = true;
}); // 多租户
Configure<AbpMultiTenancyOptions>(options =>
var tenantResolveCfg = configuration.GetSection("App:Domains"); {
if (tenantResolveCfg.Exists()) options.IsEnabled = true;
{ });
Configure<AbpTenantResolveOptions>(options =>
{ var tenantResolveCfg = configuration.GetSection("App:Domains");
var domains = tenantResolveCfg.Get<string[]>(); if (tenantResolveCfg.Exists())
foreach (var domain in domains) {
{ Configure<AbpTenantResolveOptions>(options =>
options.AddDomainTenantResolver(domain); {
} var domains = tenantResolveCfg.Get<string[]>();
}); foreach (var domain in domains)
} {
options.AddDomainTenantResolver(domain);
Configure<AbpDistributedCacheOptions>(options => }
{ });
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生 }
options.KeyPrefix = "LINGYUN.Abp.Application";
// 滑动过期30天 Configure<AbpDistributedCacheOptions>(options =>
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30); {
// 绝对过期60天 // 最好统一命名,不然某个缓存变动其他应用服务有例外发生
options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); options.KeyPrefix = "LINGYUN.Abp.Application";
}); // 滑动过期30天
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30);
Configure<RedisCacheOptions>(options => // 绝对过期60天
{ options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
var redisConfig = ConfigurationOptions.Parse(options.Configuration); });
options.ConfigurationOptions = redisConfig;
options.InstanceName = configuration["Redis:InstanceName"]; Configure<RedisCacheOptions>(options =>
}); {
var redisConfig = ConfigurationOptions.Parse(options.Configuration);
// Swagger options.ConfigurationOptions = redisConfig;
context.Services.AddSwaggerGen( options.InstanceName = configuration["Redis:InstanceName"];
options => });
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MessageService API", Version = "v1" }); // Swagger
options.DocInclusionPredicate((docName, description) => true); context.Services.AddSwaggerGen(
options.CustomSchemaIds(type => type.FullName); options =>
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
{ options.SwaggerDoc("v1", new OpenApiInfo { Title = "MessageService API", Version = "v1" });
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", options.DocInclusionPredicate((docName, description) => true);
Name = "Authorization", options.CustomSchemaIds(type => type.FullName);
In = ParameterLocation.Header, options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
Scheme = "bearer", {
Type = SecuritySchemeType.Http, Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
BearerFormat = "JWT" Name = "Authorization",
}); In = ParameterLocation.Header,
options.AddSecurityRequirement(new OpenApiSecurityRequirement Scheme = "bearer",
{ Type = SecuritySchemeType.Http,
{ BearerFormat = "JWT"
new OpenApiSecurityScheme });
{ options.AddSecurityRequirement(new OpenApiSecurityRequirement
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } {
}, {
new string[] { } new OpenApiSecurityScheme
} {
}); Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
}); },
new string[] { }
context.Services.AddCors(options => }
{ });
options.AddPolicy(DefaultCorsPolicyName, builder => });
{
builder context.Services.AddCors(options =>
.WithOrigins( {
configuration["App:CorsOrigins"] options.AddPolicy(DefaultCorsPolicyName, builder =>
.Split(",", StringSplitOptions.RemoveEmptyEntries) {
.Select(o => o.RemovePostFix("/")) builder
.ToArray() .WithOrigins(
) configuration["App:CorsOrigins"]
.WithAbpExposedHeaders() .Split(",", StringSplitOptions.RemoveEmptyEntries)
.SetIsOriginAllowedToAllowWildcardSubdomains() .Select(o => o.RemovePostFix("/"))
.AllowAnyHeader() .ToArray()
.AllowAnyMethod() )
.AllowCredentials(); .WithAbpExposedHeaders()
}); .SetIsOriginAllowedToAllowWildcardSubdomains()
}); .AllowAnyHeader()
.AllowAnyMethod()
// 支持本地化语言类型 .AllowCredentials();
Configure<AbpLocalizationOptions>(options => });
{ });
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); // 支持本地化语言类型
Configure<AbpLocalizationOptions>(options =>
options.Resources {
.Get<MessageServiceResource>() options.Languages.Add(new LanguageInfo("en", "en", "English"));
.AddVirtualJson("/Localization/HttpApiHost"); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
});
options.Resources
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .Get<MessageServiceResource>()
.AddJwtBearer(options => .AddVirtualJson("/Localization/HttpApiHost");
{ });
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = false; context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
options.Audience = configuration["AuthServer:ApiName"]; .AddJwtBearer(options =>
}); {
options.Authority = configuration["AuthServer:Authority"];
if (!hostingEnvironment.IsDevelopment()) options.RequireHttpsMetadata = false;
{ options.Audience = configuration["AuthServer:ApiName"];
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); });
context.Services
.AddDataProtection() if (!hostingEnvironment.IsDevelopment())
.PersistKeysToStackExchangeRedis(redis, "MessageService-Protection-Keys"); {
} var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
} context.Services
.AddDataProtection()
public override void OnApplicationInitialization(ApplicationInitializationContext context) .PersistKeysToStackExchangeRedis(redis, "MessageService-Protection-Keys");
{ }
var app = context.GetApplicationBuilder(); }
// http调用链
app.UseCorrelationId(); public override void OnApplicationInitialization(ApplicationInitializationContext context)
// 虚拟文件系统 {
app.UseStaticFiles(); var app = context.GetApplicationBuilder();
// 本地化 // http调用链
app.UseAbpRequestLocalization(); app.UseCorrelationId();
//路由 // 虚拟文件系统
app.UseRouting(); app.UseStaticFiles();
// 跨域 // 本地化
app.UseCors(DefaultCorsPolicyName); app.UseAbpRequestLocalization();
// 加入自定义中间件 //路由
app.UseSignalRJwtToken(); app.UseRouting();
// TODO: 还有没有其他方法在iframe中传递身份令牌? // 跨域
app.UseHangfireAuthorication(); app.UseCors(DefaultCorsPolicyName);
// 认证 // 加入自定义中间件
app.UseAuthentication(); app.UseSignalRJwtToken();
// jwt // TODO: 还有没有其他方法在iframe中传递身份令牌?
app.UseJwtTokenMiddleware(); app.UseHangfireAuthorication();
// 授权 // 认证
app.UseAuthorization(); app.UseAuthentication();
// 多租户 // jwt
app.UseMultiTenancy(); app.UseJwtTokenMiddleware();
// Swagger // 授权
app.UseSwagger(); app.UseAuthorization();
// Swagger可视化界面 // 多租户
app.UseSwaggerUI(options => app.UseMultiTenancy();
{ // Swagger
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API"); app.UseSwagger();
}); // Swagger可视化界面
// 审计日志 app.UseSwaggerUI(options =>
app.UseAuditing(); {
app.UseHangfireServer(); options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API");
app.UseHangfireDashboard(); });
// 路由 // 审计日志
app.UseConfiguredEndpoints(); app.UseAuditing();
} app.UseHangfireServer();
} app.UseHangfireDashboard();
} // 路由
app.UseConfiguredEndpoints();
}
}
}

2
aspnet-core/services/messages/LINGYUN.Abp.MessageService.HttpApi.Host/LINGYUN.Abp.MessageService.HttpApi.Host.csproj

@ -36,6 +36,7 @@
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="4.4.0" /> <PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Autofac" Version="4.4.0" /> <PackageReference Include="Volo.Abp.Autofac" Version="4.4.0" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="4.4.0" /> <PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="4.4.0" />
<PackageReference Include="Volo.Abp.Identity.EntityFrameworkCore" Version="4.4.0" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="4.4.0" /> <PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="4.4.0" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="4.4.0" /> <PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="4.4.0" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="4.4.0" /> <PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="4.4.0" />
@ -57,6 +58,7 @@
<ProjectReference Include="..\..\..\modules\message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj" /> <ProjectReference Include="..\..\..\modules\message\LINGYUN.Abp.MessageService.HttpApi\LINGYUN.Abp.MessageService.HttpApi.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" /> <ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" />
<ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" /> <ProjectReference Include="..\..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\..\..\modules\wechat\LINGYUN.Abp.Identity.WeChat\LINGYUN.Abp.Identity.WeChat.csproj" />
<ProjectReference Include="..\..\..\modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj" /> <ProjectReference Include="..\..\..\modules\wechat\LINGYUN.Abp.Notifications.WeChat.MiniProgram\LINGYUN.Abp.Notifications.WeChat.MiniProgram.csproj" />
</ItemGroup> </ItemGroup>

Loading…
Cancel
Save