69 changed files with 2489 additions and 3096 deletions
@ -1,239 +1,239 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.30011.22 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{14B8F528-C649-4FAD-9BBB-6C979ED403E1}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{0CA2F891-7E8E-453B-9FEF-ADCBEB7795DD}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "account", "account", "{4F06C65B-22CC-466E-B3FD-3F695DD38191}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity-server", "identity-server", "{7AB942D5-D139-4F9F-9342-71534AA3A5AC}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{BD964040-90B2-4179-A5EB-5830F5C7E073}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{7EE9651C-17B0-4343-A2ED-92439F8C9019}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FD2DDD48-8F84-4924-BBAF-52080AB32267}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "modules\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "modules\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{80A418EB-6149-4684-80EF-D8574B91FE2B}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{53E90646-2933-4381-9386-6BC6ED16E71A}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{99B60A42-29DA-4D91-9255-B90F53BC6D6E}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{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}.Release|Any CPU.ActiveCfg = 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B} = {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} |
|||
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF} = {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} |
|||
{4F06C65B-22CC-466E-B3FD-3F695DD38191} = {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} |
|||
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1} = {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} |
|||
{E22445B9-7039-4DA1-B547-BAB437D6D2B3} = {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} |
|||
{0F87C16B-8E91-4B25-B501-AD81F8EC599E} = {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} |
|||
{177B6CD3-1690-416D-9B37-A821093DEFBD} = {BD964040-90B2-4179-A5EB-5830F5C7E073} |
|||
{7EE9651C-17B0-4343-A2ED-92439F8C9019} = {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} |
|||
{23536755-4F00-4929-9C5E-D4CABD1CC513} = {BD964040-90B2-4179-A5EB-5830F5C7E073} |
|||
{80A418EB-6149-4684-80EF-D8574B91FE2B} = {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} |
|||
{720120B4-76F6-4701-9426-611BB8F84515} = {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} |
|||
{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} |
|||
{99B60A42-29DA-4D91-9255-B90F53BC6D6E} = {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} |
|||
{AD1C3335-A2A1-49C1-A6DB-817C54859B65} = {7EE9651C-17B0-4343-A2ED-92439F8C9019} |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {785FFF4D-BC59-499E-88A3-7CB7A7667228} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.30011.22 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{14B8F528-C649-4FAD-9BBB-6C979ED403E1}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{0CA2F891-7E8E-453B-9FEF-ADCBEB7795DD}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "account", "account", "{4F06C65B-22CC-466E-B3FD-3F695DD38191}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity-server", "identity-server", "{7AB942D5-D139-4F9F-9342-71534AA3A5AC}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "identity", "identity", "{BD964040-90B2-4179-A5EB-5830F5C7E073}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{7EE9651C-17B0-4343-A2ED-92439F8C9019}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{FD2DDD48-8F84-4924-BBAF-52080AB32267}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Settings", "modules\common\LINGYUN.Abp.Settings\LINGYUN.Abp.Settings.csproj", "{A8C83B9C-C9BF-48EF-80FF-D4FE2C936EFC}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.ExceptionHandling", "modules\common\LINGYUN.Abp.ExceptionHandling\LINGYUN.Abp.ExceptionHandling.csproj", "{80A418EB-6149-4684-80EF-D8574B91FE2B}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{53E90646-2933-4381-9386-6BC6ED16E71A}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tenants", "tenants", "{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.MultiTenancy", "modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj", "{99B60A42-29DA-4D91-9255-B90F53BC6D6E}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{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}.Release|Any CPU.ActiveCfg = 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{DC379D12-77E1-4600-8E99-AAD9B92C3A1B} = {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} |
|||
{DA57672C-501D-4CAF-8BF2-4D93B2D460BF} = {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} |
|||
{4F06C65B-22CC-466E-B3FD-3F695DD38191} = {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} |
|||
{A4DFDE21-1931-46B5-8381-36B6EB6E51E1} = {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} |
|||
{E22445B9-7039-4DA1-B547-BAB437D6D2B3} = {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} |
|||
{0F87C16B-8E91-4B25-B501-AD81F8EC599E} = {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} |
|||
{177B6CD3-1690-416D-9B37-A821093DEFBD} = {BD964040-90B2-4179-A5EB-5830F5C7E073} |
|||
{7EE9651C-17B0-4343-A2ED-92439F8C9019} = {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} |
|||
{23536755-4F00-4929-9C5E-D4CABD1CC513} = {BD964040-90B2-4179-A5EB-5830F5C7E073} |
|||
{80A418EB-6149-4684-80EF-D8574B91FE2B} = {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} |
|||
{720120B4-76F6-4701-9426-611BB8F84515} = {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} |
|||
{89BA9708-62E5-4FD6-A28A-CF9E1C26DCAE} = {14B8F528-C649-4FAD-9BBB-6C979ED403E1} |
|||
{99B60A42-29DA-4D91-9255-B90F53BC6D6E} = {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} |
|||
{AD1C3335-A2A1-49C1-A6DB-817C54859B65} = {7EE9651C-17B0-4343-A2ED-92439F8C9019} |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {785FFF4D-BC59-499E-88A3-7CB7A7667228} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
|
|||
@ -1,267 +1,274 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.30011.22 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{E7A821D8-85B5-4098-897D-5A814BD8131D}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{C00828FB-E7D5-4086-BA50-02022594AB73}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime", "modules\common\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj", "{07BCD006-F2F2-4685-8887-E8BEB18745FD}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM", "modules\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj", "{55B9F554-1754-4EF9-B325-B33421D4F6A9}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications", "modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj", "{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{78164C5C-63B9-4FB6-ACC9-6496E236C946}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{3B87330F-A303-4413-B653-1C9536C74109}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "message", "message", "{D58F1DF5-2DFE-40A2-B136-7606D4CDE903}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{42800C56-9473-4B96-BF29-1B0F25C867F4}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{B5E23AED-3068-4CFE-84B0-3B7725665506}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{C00828FB-E7D5-4086-BA50-02022594AB73} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{8C973655-DF59-40D8-B206-82344575A8CF} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{54395254-0383-4932-B2E4-50932DAD7D10} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D} = {E7A821D8-85B5-4098-897D-5A814BD8131D} |
|||
{78164C5C-63B9-4FB6-ACC9-6496E236C946} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{3B87330F-A303-4413-B653-1C9536C74109} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} |
|||
{D58F1DF5-2DFE-40A2-B136-7606D4CDE903} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} |
|||
{454059F7-D087-439A-A724-80BDFE94776F} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {6238659A-7267-49B9-A499-8746BDEED6B8} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.30011.22 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "modules", "modules", "{0C7AA298-2957-4D71-A8F1-1C3C7932A1B3}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "services", "services", "{E7A821D8-85B5-4098-897D-5A814BD8131D}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{C00828FB-E7D5-4086-BA50-02022594AB73}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.RealTime", "modules\common\LINGYUN.Abp.RealTime\LINGYUN.Abp.RealTime.csproj", "{07BCD006-F2F2-4685-8887-E8BEB18745FD}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.IM", "modules\common\LINGYUN.Abp.IM\LINGYUN.Abp.IM.csproj", "{55B9F554-1754-4EF9-B325-B33421D4F6A9}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Notifications", "modules\common\LINGYUN.Abp.Notifications\LINGYUN.Abp.Notifications.csproj", "{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wechat", "wechat", "{78164C5C-63B9-4FB6-ACC9-6496E236C946}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WeChat", "modules\wechat\LINGYUN.Abp.WeChat\LINGYUN.Abp.WeChat.csproj", "{3B87330F-A303-4413-B653-1C9536C74109}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "message", "message", "{D58F1DF5-2DFE-40A2-B136-7606D4CDE903}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{42800C56-9473-4B96-BF29-1B0F25C867F4}" |
|||
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}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{B5E23AED-3068-4CFE-84B0-3B7725665506}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
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}" |
|||
EndProject |
|||
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}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{8C973655-DF59-40D8-B206-82344575A8CF}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{54395254-0383-4932-B2E4-50932DAD7D10}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3B87330F-A303-4413-B653-1C9536C74109}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{454059F7-D087-439A-A724-80BDFE94776F}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{32D4DB5D-74D1-4166-85EA-B2D8F14B8058}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{C49B50D4-5D63-47E6-82F7-E742181CF9DE}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{DC71289C-18A7-4E4B-A653-E66941EB19AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{DC71289C-18A7-4E4B-A653-E66941EB19AE}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{DC71289C-18A7-4E4B-A653-E66941EB19AE}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{DC71289C-18A7-4E4B-A653-E66941EB19AE}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{C00828FB-E7D5-4086-BA50-02022594AB73} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} |
|||
{07BCD006-F2F2-4685-8887-E8BEB18745FD} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{60E37E86-ACA6-4464-9592-B0D8EFB629BD} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{85B39FCE-6778-497C-A12E-6777C7FE651A} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{8C973655-DF59-40D8-B206-82344575A8CF} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{55B9F554-1754-4EF9-B325-B33421D4F6A9} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{7AC8C076-87E2-48ED-8AB3-C1F737F55DD1} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{C6F494D3-2C41-46DF-BCAD-F74D3E53CDE1} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{3531699A-9FF9-4F8C-BEAD-9D114FE8E519} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{50DE8ABF-B50A-4AAB-A69B-4E727AFDB6B5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{2094F03B-FC73-4B3F-88CB-F7951E22FED5} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{554E5BCA-7F88-4E7C-86ED-8B6DE3A3A802} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{92E4CAD4-F5B9-4B16-B7BC-4A40DC1E93F1} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{DB8CE5AF-1888-4C51-97C3-2188BE50FAF9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{54395254-0383-4932-B2E4-50932DAD7D10} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{3E9CCC0A-DAD5-4F32-8EAE-654D67DEE2B9} = {D58F1DF5-2DFE-40A2-B136-7606D4CDE903} |
|||
{8168B7B4-9F6B-4658-A28C-D0F9D10AB93D} = {E7A821D8-85B5-4098-897D-5A814BD8131D} |
|||
{78164C5C-63B9-4FB6-ACC9-6496E236C946} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} |
|||
{93971F1F-F6AC-4F83-8119-21260FCE2828} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{3B87330F-A303-4413-B653-1C9536C74109} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} |
|||
{D58F1DF5-2DFE-40A2-B136-7606D4CDE903} = {0C7AA298-2957-4D71-A8F1-1C3C7932A1B3} |
|||
{3A4601FE-B091-43A3-AEE6-6440BB37B277} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} |
|||
{454059F7-D087-439A-A724-80BDFE94776F} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{64E2622A-611D-4056-9497-0B52A91DC59C} = {78164C5C-63B9-4FB6-ACC9-6496E236C946} |
|||
{5714481A-BDF5-4860-9158-3B18D3018EC5} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{B5E23AED-3068-4CFE-84B0-3B7725665506} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{E5257008-A0AD-473F-91B0-864FC601B84B} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{DB425943-CEE6-4FF6-A0EE-233B6ADA3BD7} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{25267137-08BE-44A6-9F7E-7783CC8C62E8} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{CB6D56DA-539B-4D4F-81CD-D683ADEBFB5F} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{097319B9-D062-4A54-8F8C-001C180E2CB3} = {42800C56-9473-4B96-BF29-1B0F25C867F4} |
|||
{737EF17D-477F-4C73-A4CC-0DA6CBD3BB97} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{0B6AAACE-A1DE-4063-8DA8-E7EBA30186E4} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{05DCBA6B-480A-4D2F-9855-F66F5B7F3A48} = {C00828FB-E7D5-4086-BA50-02022594AB73} |
|||
{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,54 +1,56 @@ |
|||
using LINGYUN.Abp.IdentityServer.WeChat.MiniProgram; |
|||
using LINGYUN.Abp.IdentityServer.WeChat.Official; |
|||
using LINGYUN.Abp.WeChat.MiniProgram; |
|||
using LINGYUN.Abp.WeChat.Official; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
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.WeChat |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpWeChatOfficialModule), |
|||
typeof(AbpWeChatMiniProgramModule), |
|||
typeof(AbpIdentityServerDomainModule))] |
|||
public class AbpIdentityServerWeChatModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
PreConfigure<IIdentityServerBuilder>(builder => |
|||
{ |
|||
builder.AddProfileService<WeChatMiniProgramProfileService>(); |
|||
|
|||
// TODO: 两个类型不通用配置项,不然只需要一个
|
|||
builder.AddExtensionGrantValidator<WeChatMiniProgramGrantValidator>(); |
|||
builder.AddExtensionGrantValidator<WeChatOfficialGrantValidator>(); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpIdentityServerWeChatModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<AbpIdentityServerResource>() |
|||
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/WeChat/Localization"); |
|||
}); |
|||
|
|||
context.Services |
|||
.AddAuthentication() |
|||
.AddWeChat(); |
|||
} |
|||
} |
|||
} |
|||
using LINGYUN.Abp.Identity.WeChat; |
|||
using LINGYUN.Abp.IdentityServer.WeChat.MiniProgram; |
|||
using LINGYUN.Abp.IdentityServer.WeChat.Official; |
|||
using LINGYUN.Abp.WeChat.MiniProgram; |
|||
using LINGYUN.Abp.WeChat.Official; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
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.WeChat |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpWeChatOfficialModule), |
|||
typeof(AbpWeChatMiniProgramModule), |
|||
typeof(AbpIdentityWeChatModule), |
|||
typeof(AbpIdentityServerDomainModule))] |
|||
public class AbpIdentityServerWeChatModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
PreConfigure<IIdentityServerBuilder>(builder => |
|||
{ |
|||
builder.AddProfileService<WeChatMiniProgramProfileService>(); |
|||
|
|||
// TODO: 两个类型不通用配置项,不然只需要一个
|
|||
builder.AddExtensionGrantValidator<WeChatMiniProgramGrantValidator>(); |
|||
builder.AddExtensionGrantValidator<WeChatOfficialGrantValidator>(); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpIdentityServerWeChatModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<AbpIdentityServerResource>() |
|||
.AddVirtualJson("/LINGYUN/Abp/IdentityServer/WeChat/Localization"); |
|||
}); |
|||
|
|||
context.Services |
|||
.AddAuthentication() |
|||
.AddWeChat(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,47 +1,47 @@ |
|||
using IdentityServer4.Services; |
|||
using LINGYUN.Abp.WeChat.MiniProgram; |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Options; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer.Localization; |
|||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram |
|||
{ |
|||
/// <summary>
|
|||
/// 对于小程序绑定用户的扩展授权验证器
|
|||
/// </summary>
|
|||
public class WeChatMiniProgramGrantValidator : WeChatGrantValidator |
|||
{ |
|||
public override string GrantType => AbpWeChatMiniProgramConsts.GrantType; |
|||
|
|||
public override string LoginProviderKey => AbpWeChatMiniProgramConsts.ProviderKey; |
|||
|
|||
public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod; |
|||
|
|||
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } |
|||
|
|||
public WeChatMiniProgramGrantValidator( |
|||
IEventService eventService, |
|||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|||
UserManager<IdentityUser> userManager, |
|||
IIdentityUserRepository userRepository, |
|||
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, |
|||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, |
|||
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) |
|||
: base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) |
|||
{ |
|||
MiniProgramOptionsFactory = miniProgramOptionsFactory; |
|||
} |
|||
|
|||
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) |
|||
{ |
|||
var options = await MiniProgramOptionsFactory.CreateAsync(); |
|||
|
|||
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); |
|||
} |
|||
} |
|||
} |
|||
using IdentityServer4.Services; |
|||
using LINGYUN.Abp.WeChat.MiniProgram; |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Options; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer.Localization; |
|||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat.MiniProgram |
|||
{ |
|||
/// <summary>
|
|||
/// 对于小程序绑定用户的扩展授权验证器
|
|||
/// </summary>
|
|||
public class WeChatMiniProgramGrantValidator : WeChatGrantValidator |
|||
{ |
|||
public override string GrantType => AbpWeChatMiniProgramConsts.GrantType; |
|||
|
|||
public override string LoginProvider => AbpWeChatMiniProgramConsts.ProviderName; |
|||
|
|||
public override string AuthenticationMethod => AbpWeChatMiniProgramConsts.AuthenticationMethod; |
|||
|
|||
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } |
|||
|
|||
public WeChatMiniProgramGrantValidator( |
|||
IEventService eventService, |
|||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|||
UserManager<IdentityUser> userManager, |
|||
IIdentityUserRepository userRepository, |
|||
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, |
|||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, |
|||
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) |
|||
: base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) |
|||
{ |
|||
MiniProgramOptionsFactory = miniProgramOptionsFactory; |
|||
} |
|||
|
|||
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) |
|||
{ |
|||
var options = await MiniProgramOptionsFactory.CreateAsync(); |
|||
|
|||
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,46 +1,46 @@ |
|||
using IdentityServer4.Services; |
|||
using LINGYUN.Abp.WeChat.Official; |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer.Localization; |
|||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
|||
{ |
|||
/// <summary>
|
|||
/// 对于公众平台绑定用户的扩展授权验证器
|
|||
/// </summary>
|
|||
public class WeChatOfficialGrantValidator : WeChatGrantValidator |
|||
{ |
|||
public override string GrantType => AbpWeChatOfficialConsts.GrantType; |
|||
|
|||
public override string LoginProviderKey => AbpWeChatOfficialConsts.ProviderKey; |
|||
|
|||
public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod; |
|||
|
|||
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; } |
|||
|
|||
public WeChatOfficialGrantValidator( |
|||
IEventService eventService, |
|||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|||
UserManager<IdentityUser> userManager, |
|||
IIdentityUserRepository userRepository, |
|||
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, |
|||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, |
|||
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory) |
|||
: base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) |
|||
{ |
|||
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory; |
|||
} |
|||
|
|||
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) |
|||
{ |
|||
var options = await WeChatOfficialOptionsFactory.CreateAsync(); |
|||
|
|||
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); |
|||
} |
|||
} |
|||
} |
|||
using IdentityServer4.Services; |
|||
using LINGYUN.Abp.WeChat.Official; |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer.Localization; |
|||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
|||
{ |
|||
/// <summary>
|
|||
/// 对于公众平台绑定用户的扩展授权验证器
|
|||
/// </summary>
|
|||
public class WeChatOfficialGrantValidator : WeChatGrantValidator |
|||
{ |
|||
public override string GrantType => AbpWeChatOfficialConsts.GrantType; |
|||
|
|||
public override string LoginProvider => AbpWeChatOfficialConsts.ProviderName; |
|||
|
|||
public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod; |
|||
|
|||
protected AbpWeChatOfficialOptionsFactory WeChatOfficialOptionsFactory { get; } |
|||
|
|||
public WeChatOfficialGrantValidator( |
|||
IEventService eventService, |
|||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|||
UserManager<IdentityUser> userManager, |
|||
IIdentityUserRepository userRepository, |
|||
IStringLocalizer<Volo.Abp.Identity.Localization.IdentityResource> identityLocalizer, |
|||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer, |
|||
AbpWeChatOfficialOptionsFactory weChatOfficialOptionsFactory) |
|||
: base(eventService, weChatOpenIdFinder, userManager, userRepository, identityLocalizer, identityServerLocalizer) |
|||
{ |
|||
WeChatOfficialOptionsFactory = weChatOfficialOptionsFactory; |
|||
} |
|||
|
|||
protected override async Task<WeChatOpenId> FindOpenIdAsync(string code) |
|||
{ |
|||
var options = await WeChatOfficialOptionsFactory.CreateAsync(); |
|||
|
|||
return await WeChatOpenIdFinder.FindAsync(code, options.AppId, options.AppSecret); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,71 +1,71 @@ |
|||
using LINGYUN.Abp.WeChat; |
|||
using LINGYUN.Abp.WeChat.Official; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
|||
{ |
|||
/// <summary>
|
|||
/// 与微信公众号认证相关的静态(可变)常量
|
|||
/// </summary>
|
|||
public static class WeChatOfficialOAuthConsts |
|||
{ |
|||
/// <summary>
|
|||
/// 微信个人信息标识
|
|||
/// </summary>
|
|||
public static string ProfileKey { get; set; } = "wechat.profile"; |
|||
/// <summary>
|
|||
/// 微信提供者标识
|
|||
/// </summary>
|
|||
public static string ProviderKey => AbpWeChatOfficialConsts.ProviderKey; |
|||
/// <summary>
|
|||
/// 微信提供者显示名称
|
|||
/// </summary>
|
|||
public static string DisplayName => AbpWeChatGlobalConsts.DisplayName; |
|||
/// <summary>
|
|||
/// 回调地址
|
|||
/// </summary>
|
|||
public static string CallbackPath { get; set; } = "/signin-wechat"; |
|||
|
|||
/// <summary>
|
|||
/// 微信客户端外的网页登录
|
|||
/// </summary>
|
|||
public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect"; |
|||
|
|||
/// <summary>
|
|||
/// 微信客户端内的网页登录
|
|||
/// </summary>
|
|||
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; |
|||
|
|||
/// <summary>
|
|||
/// 用户允许授权后通过返回的code换取access_token地址
|
|||
/// </summary>
|
|||
public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token"; |
|||
|
|||
/// <summary>
|
|||
/// 使用access_token获取用户个人信息地址
|
|||
/// </summary>
|
|||
public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; |
|||
/// <summary>
|
|||
/// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
|
|||
/// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
|
|||
/// <br />
|
|||
/// <br />
|
|||
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
|
|||
/// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
|
|||
/// </remarks>
|
|||
public const string UserInfoScope = "snsapi_userinfo"; |
|||
/// <summary>
|
|||
/// 不弹出授权页面,直接跳转,只能获取用户openid
|
|||
/// <br />
|
|||
/// <br />
|
|||
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
|
|||
/// 用户感知的就是直接进入了回调页(往往是业务页面)
|
|||
/// </remarks>
|
|||
public const string LoginScope = "snsapi_login"; |
|||
} |
|||
} |
|||
using LINGYUN.Abp.WeChat; |
|||
using LINGYUN.Abp.WeChat.Official; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat.Official |
|||
{ |
|||
/// <summary>
|
|||
/// 与微信公众号认证相关的静态(可变)常量
|
|||
/// </summary>
|
|||
public static class WeChatOfficialOAuthConsts |
|||
{ |
|||
/// <summary>
|
|||
/// 微信个人信息标识
|
|||
/// </summary>
|
|||
public static string ProfileKey { get; set; } = "wechat.profile"; |
|||
/// <summary>
|
|||
/// 微信提供者标识
|
|||
/// </summary>
|
|||
public static string ProviderKey => AbpWeChatOfficialConsts.ProviderName; |
|||
/// <summary>
|
|||
/// 微信提供者显示名称
|
|||
/// </summary>
|
|||
public static string DisplayName => AbpWeChatGlobalConsts.DisplayName; |
|||
/// <summary>
|
|||
/// 回调地址
|
|||
/// </summary>
|
|||
public static string CallbackPath { get; set; } = "/signin-wechat"; |
|||
|
|||
/// <summary>
|
|||
/// 微信客户端外的网页登录
|
|||
/// </summary>
|
|||
public const string QrConnectEndpoint = "https://open.weixin.qq.com/connect/qrconnect"; |
|||
|
|||
/// <summary>
|
|||
/// 微信客户端内的网页登录
|
|||
/// </summary>
|
|||
public const string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; |
|||
|
|||
/// <summary>
|
|||
/// 用户允许授权后通过返回的code换取access_token地址
|
|||
/// </summary>
|
|||
public const string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token"; |
|||
|
|||
/// <summary>
|
|||
/// 使用access_token获取用户个人信息地址
|
|||
/// </summary>
|
|||
public const string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; |
|||
/// <summary>
|
|||
/// 弹出授权页面,可通过openid拿到昵称、性别、所在地。
|
|||
/// 并且, 即使在未关注的情况下,只要用户授权,也能获取其信息
|
|||
/// <br />
|
|||
/// <br />
|
|||
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。
|
|||
/// 但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息
|
|||
/// </remarks>
|
|||
public const string UserInfoScope = "snsapi_userinfo"; |
|||
/// <summary>
|
|||
/// 不弹出授权页面,直接跳转,只能获取用户openid
|
|||
/// <br />
|
|||
/// <br />
|
|||
/// 详询: <see cref="https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html"/>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// 以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。
|
|||
/// 用户感知的就是直接进入了回调页(往往是业务页面)
|
|||
/// </remarks>
|
|||
public const string LoginScope = "snsapi_login"; |
|||
} |
|||
} |
|||
|
|||
@ -1,116 +1,143 @@ |
|||
|
|||
using IdentityModel; |
|||
using IdentityServer4.Events; |
|||
using IdentityServer4.Models; |
|||
using IdentityServer4.Services; |
|||
using IdentityServer4.Validation; |
|||
using LINGYUN.Abp.WeChat; |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using LINGYUN.Abp.WeChat.Security.Claims; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer.Localization; |
|||
using Volo.Abp.Security.Claims; |
|||
using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource; |
|||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat |
|||
{ |
|||
public abstract class WeChatGrantValidator : IExtensionGrantValidator |
|||
{ |
|||
public abstract string GrantType { get; } |
|||
public abstract string LoginProviderKey { get; } |
|||
public abstract string AuthenticationMethod { get; } |
|||
|
|||
public ILogger Logger { protected get; set; } |
|||
protected IEventService EventService { get; } |
|||
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } |
|||
protected IIdentityUserRepository UserRepository { get; } |
|||
protected UserManager<IdentityUser> UserManager { get; } |
|||
protected IStringLocalizer<IdentityResource> IdentityLocalizer { get; } |
|||
protected IStringLocalizer<AbpIdentityServerResource> IdentityServerLocalizer { get; } |
|||
|
|||
public WeChatGrantValidator( |
|||
IEventService eventService, |
|||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|||
UserManager<IdentityUser> userManager, |
|||
IIdentityUserRepository userRepository, |
|||
IStringLocalizer<IdentityResource> identityLocalizer, |
|||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer) |
|||
{ |
|||
EventService = eventService; |
|||
UserManager = userManager; |
|||
UserRepository = userRepository; |
|||
WeChatOpenIdFinder = weChatOpenIdFinder; |
|||
IdentityLocalizer = identityLocalizer; |
|||
IdentityServerLocalizer = identityServerLocalizer; |
|||
|
|||
Logger = NullLogger<WeChatGrantValidator>.Instance; |
|||
} |
|||
|
|||
protected abstract Task<WeChatOpenId> FindOpenIdAsync(string code); |
|||
|
|||
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, IdentityServerLocalizer["InvalidGrant:GrantTypeInvalid"]); |
|||
return; |
|||
} |
|||
// TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey
|
|||
var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); |
|||
if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogWarning("Invalid grant type: wechat code not found"); |
|||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatCodeNotFound"]); |
|||
return; |
|||
} |
|||
|
|||
var wechatOpenId = await FindOpenIdAsync(wechatCode); |
|||
var currentUser = await UserManager.FindByLoginAsync(LoginProviderKey, wechatOpenId.OpenId); |
|||
if (currentUser == null) |
|||
{ |
|||
Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId); |
|||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]); |
|||
return; |
|||
} |
|||
|
|||
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(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
using IdentityModel; |
|||
using IdentityServer4.Events; |
|||
using IdentityServer4.Models; |
|||
using IdentityServer4.Services; |
|||
using IdentityServer4.Validation; |
|||
using LINGYUN.Abp.WeChat; |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using LINGYUN.Abp.WeChat.Security.Claims; |
|||
using LINGYUN.Abp.WeChat.Settings; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.Extensions.Localization; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Guids; |
|||
using Volo.Abp.Identity; |
|||
using Volo.Abp.IdentityServer.Localization; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Security.Claims; |
|||
using Volo.Abp.Settings; |
|||
using Volo.Abp.Uow; |
|||
using IdentityResource = Volo.Abp.Identity.Localization.IdentityResource; |
|||
using IdentityUser = Volo.Abp.Identity.IdentityUser; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.WeChat |
|||
{ |
|||
public abstract class WeChatGrantValidator : IExtensionGrantValidator |
|||
{ |
|||
public abstract string GrantType { get; } |
|||
public abstract string LoginProvider { get; } |
|||
public abstract string AuthenticationMethod { get; } |
|||
|
|||
public ILogger Logger { protected get; set; } |
|||
public IAbpLazyServiceProvider ServiceProvider { protected get; set; } |
|||
|
|||
protected IEventService EventService { get; } |
|||
protected IWeChatOpenIdFinder WeChatOpenIdFinder { get; } |
|||
protected IIdentityUserRepository UserRepository { get; } |
|||
protected UserManager<IdentityUser> UserManager { get; } |
|||
protected IStringLocalizer<IdentityResource> IdentityLocalizer { get; } |
|||
protected IStringLocalizer<AbpIdentityServerResource> IdentityServerLocalizer { get; } |
|||
|
|||
public WeChatGrantValidator( |
|||
IEventService eventService, |
|||
IWeChatOpenIdFinder weChatOpenIdFinder, |
|||
UserManager<IdentityUser> userManager, |
|||
IIdentityUserRepository userRepository, |
|||
IStringLocalizer<IdentityResource> identityLocalizer, |
|||
IStringLocalizer<AbpIdentityServerResource> identityServerLocalizer) |
|||
{ |
|||
EventService = eventService; |
|||
UserManager = userManager; |
|||
UserRepository = userRepository; |
|||
WeChatOpenIdFinder = weChatOpenIdFinder; |
|||
IdentityLocalizer = identityLocalizer; |
|||
IdentityServerLocalizer = identityServerLocalizer; |
|||
|
|||
Logger = NullLogger<WeChatGrantValidator>.Instance; |
|||
} |
|||
|
|||
protected abstract Task<WeChatOpenId> FindOpenIdAsync(string code); |
|||
|
|||
[UnitOfWork] |
|||
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, IdentityServerLocalizer["InvalidGrant:GrantTypeInvalid"]); |
|||
return; |
|||
} |
|||
// TODO: 统一命名规范, 微信认证传递的 code 改为 WeChatOpenIdConsts.WeCahtCodeKey
|
|||
var wechatCode = raw.Get(AbpWeChatGlobalConsts.TokenName); |
|||
if (wechatCode.IsNullOrWhiteSpace() || wechatCode.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogWarning("Invalid grant type: wechat code not found"); |
|||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatCodeNotFound"]); |
|||
return; |
|||
} |
|||
|
|||
var wechatOpenId = await FindOpenIdAsync(wechatCode); |
|||
var currentUser = await UserManager.FindByLoginAsync(LoginProvider, wechatOpenId.OpenId); |
|||
if (currentUser == null) |
|||
{ |
|||
var settingProvider = ServiceProvider.LazyGetRequiredService<ISettingProvider>(); |
|||
// TODO 检查启用用户注册是否有必要引用账户模块
|
|||
if (! await settingProvider.IsTrueAsync("Abp.Account.IsSelfRegistrationEnabled") || |
|||
! await settingProvider.IsTrueAsync(WeChatSettingNames.EnabledQuickLogin)) |
|||
{ |
|||
Logger.LogWarning("Invalid grant type: wechat openid not register", wechatOpenId.OpenId); |
|||
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, IdentityServerLocalizer["InvalidGrant:WeChatNotRegister"]); |
|||
return; |
|||
} |
|||
var guiGenerator = ServiceProvider.LazyGetRequiredService<IGuidGenerator>(); |
|||
var currentTenant = ServiceProvider.LazyGetRequiredService<ICurrentTenant>(); |
|||
var userName = "wxid-" + wechatOpenId.OpenId.ToMd5().ToLower(); |
|||
var userEmail = $"{userName}@{currentTenant.Name ?? "default"}.io"; |
|||
currentUser = new IdentityUser(guiGenerator.Create(), userName, userEmail, currentTenant.Id); |
|||
(await UserManager.CreateAsync(currentUser)).CheckErrors(); |
|||
(await UserManager.AddLoginAsync( |
|||
currentUser, |
|||
new UserLoginInfo( |
|||
LoginProvider, |
|||
wechatOpenId.OpenId, |
|||
LoginProvider))).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(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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> |
|||
@ -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"); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +0,0 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer |
|||
{ |
|||
public interface IWeChatResourceDataSeeder |
|||
{ |
|||
Task CreateStandardResourcesAsync(); |
|||
} |
|||
} |
|||
@ -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!" |
|||
} |
|||
} |
|||
@ -1,10 +0,0 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"SelfRegistrationDisabledMessage": "应用程序未开放注册,请联系管理员添加新用户.", |
|||
"InvalidGrant:GrantTypeInvalid": "不被允许的授权类型!", |
|||
"InvalidGrant:WeChatTokenInvalid": "微信认证失败!", |
|||
"InvalidGrant:WeChatCodeNotFound": "微信登录时获取的 code 为空或不存在!", |
|||
"InvalidGrant:WeChatNotRegister": "用户微信账号未绑定!" |
|||
} |
|||
} |
|||
@ -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 |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -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()); |
|||
} |
|||
} |
|||
} |
|||
@ -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"; |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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")); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -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"}"; |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -1,17 +0,0 @@ |
|||
# LINGYUN.Abp.IdentityServer.WeChatValidator |
|||
|
|||
废弃模块,模块层次不清晰,微信有多端平台,不同平台授权规则不一致 |
|||
|
|||
#### 注意 |
|||
|
|||
|
|||
|
|||
## 配置使用 |
|||
|
|||
|
|||
```csharp |
|||
[DependsOn(typeof(AbpIdentityServerWeChatValidatorModule))] |
|||
public class YouProjectModule : AbpModule |
|||
{ |
|||
// other |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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 |
|||
{ |
|||
} |
|||
} |
|||
@ -1,46 +1,47 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Identity; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.Authorization |
|||
{ |
|||
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)] |
|||
[ExposeServices(typeof(IUserWeChatOpenIdFinder))] |
|||
public class UserWeChatOpenIdFinder : IUserWeChatOpenIdFinder |
|||
{ |
|||
protected IdentityUserManager UserManager { get; } |
|||
|
|||
public UserWeChatOpenIdFinder( |
|||
IdentityUserManager userManager) |
|||
{ |
|||
UserManager = userManager; |
|||
} |
|||
|
|||
public virtual async Task<string> FindByUserIdAsync(Guid userId) |
|||
{ |
|||
var user = await UserManager.FindByIdAsync(userId.ToString()); |
|||
|
|||
return GetUserOpenIdOrNull(user); |
|||
} |
|||
|
|||
public virtual async Task<string> FindByUserNameAsync(string userName) |
|||
{ |
|||
var user = await UserManager.FindByNameAsync(userName); |
|||
|
|||
return GetUserOpenIdOrNull(user); |
|||
} |
|||
|
|||
protected string GetUserOpenIdOrNull(IdentityUser user) |
|||
{ |
|||
// 微信扩展登录后openid存储在Login中
|
|||
var userLogin = user?.Logins |
|||
.Where(login => login.LoginProvider == AbpWeChatAuthorizationConsts.ProviderKey) |
|||
.FirstOrDefault(); |
|||
|
|||
return userLogin?.ProviderKey; |
|||
} |
|||
} |
|||
} |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Identity; |
|||
|
|||
namespace LINGYUN.Abp.Identity.WeChat.OpenId |
|||
{ |
|||
[Dependency(ServiceLifetime.Transient, ReplaceServices = true)] |
|||
[ExposeServices(typeof(IUserWeChatOpenIdFinder))] |
|||
public class UserWeChatOpenIdFinder : IUserWeChatOpenIdFinder |
|||
{ |
|||
protected IdentityUserManager UserManager { get; } |
|||
|
|||
public UserWeChatOpenIdFinder( |
|||
IdentityUserManager userManager) |
|||
{ |
|||
UserManager = userManager; |
|||
} |
|||
|
|||
public virtual async Task<string> FindByUserIdAsync(Guid userId, string provider) |
|||
{ |
|||
var user = await UserManager.FindByIdAsync(userId.ToString()); |
|||
|
|||
return GetUserOpenIdOrNull(user, provider); |
|||
} |
|||
|
|||
public virtual async Task<string> FindByUserNameAsync(string userName, string provider) |
|||
{ |
|||
var user = await UserManager.FindByNameAsync(userName); |
|||
|
|||
return GetUserOpenIdOrNull(user, provider); |
|||
} |
|||
|
|||
protected string GetUserOpenIdOrNull(IdentityUser user, string provider) |
|||
{ |
|||
// 微信扩展登录后openid存储在Login中
|
|||
var userLogin = user?.Logins |
|||
.Where(login => login.LoginProvider == provider) |
|||
.FirstOrDefault(); |
|||
|
|||
return userLogin?.ProviderKey; |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.WeChat |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpDddApplicationContractsModule))] |
|||
public class AbpWeChatApplicationContractsModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -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 |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -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; } |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.WeChat |
|||
{ |
|||
public static class WeChatRemoteServiceConsts |
|||
{ |
|||
public const string RemoteServiceName = "AbpWeChat"; |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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 |
|||
{ |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -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 |
|||
{ |
|||
} |
|||
} |
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +1,21 @@ |
|||
namespace LINGYUN.Abp.WeChat.MiniProgram |
|||
{ |
|||
public class AbpWeChatMiniProgramConsts |
|||
{ |
|||
/// <summary>
|
|||
/// 微信小程序对应的Provider名称
|
|||
/// </summary>
|
|||
public static string ProviderKey { get; set; } = "WeChat.MiniProgram"; |
|||
|
|||
/// <summary>
|
|||
/// 微信小程序授权类型
|
|||
/// </summary>
|
|||
public static string GrantType { get; set; } = "wx-mp"; |
|||
|
|||
/// <summary>
|
|||
/// 微信小程序授权方法名称
|
|||
/// </summary>
|
|||
public static string AuthenticationMethod { get; set; } = "wma"; |
|||
public static string HttpClient { get; set; } = "Abp.WeChat.MiniProgram"; |
|||
} |
|||
} |
|||
namespace LINGYUN.Abp.WeChat.MiniProgram |
|||
{ |
|||
public class AbpWeChatMiniProgramConsts |
|||
{ |
|||
/// <summary>
|
|||
/// 微信小程序对应的Provider名称
|
|||
/// </summary>
|
|||
public static string ProviderName { get; set; } = "WeChat.MiniProgram"; |
|||
|
|||
/// <summary>
|
|||
/// 微信小程序授权类型
|
|||
/// </summary>
|
|||
public static string GrantType { get; set; } = "wx-mp"; |
|||
|
|||
/// <summary>
|
|||
/// 微信小程序授权方法名称
|
|||
/// </summary>
|
|||
public static string AuthenticationMethod { get; set; } = "wma"; |
|||
public static string HttpClient { get; set; } = "Abp.WeChat.MiniProgram"; |
|||
} |
|||
} |
|||
|
|||
@ -1,38 +1,36 @@ |
|||
using LINGYUN.Abp.WeChat.Localization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Settings; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpWeChatModule), |
|||
typeof(AbpSettingsModule))] |
|||
public class AbpWeChatMiniProgramModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpWeChatMiniProgramModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<WeChatResource>() |
|||
.AddVirtualJson("/LINGYUN/Abp/WeChat/MiniProgram/Localization/Resources"); |
|||
}); |
|||
|
|||
context.Services.AddHttpClient(AbpWeChatMiniProgramConsts.HttpClient, options => |
|||
{ |
|||
options.BaseAddress = new Uri("https://api.weixin.qq.com"); |
|||
}); |
|||
|
|||
context.Services.AddAbpDynamicOptions<AbpWeChatMiniProgramOptions, AbpWeChatMiniProgramOptionsManager>(); |
|||
} |
|||
} |
|||
} |
|||
using LINGYUN.Abp.WeChat.Localization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpWeChatModule))] |
|||
public class AbpWeChatMiniProgramModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpWeChatMiniProgramModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<WeChatResource>() |
|||
.AddVirtualJson("/LINGYUN/Abp/WeChat/MiniProgram/Localization/Resources"); |
|||
}); |
|||
|
|||
context.Services.AddHttpClient(AbpWeChatMiniProgramConsts.HttpClient, options => |
|||
{ |
|||
options.BaseAddress = new Uri("https://api.weixin.qq.com"); |
|||
}); |
|||
|
|||
context.Services.AddAbpDynamicOptions<AbpWeChatMiniProgramOptions, AbpWeChatMiniProgramOptionsManager>(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,24 +1,24 @@ |
|||
using Newtonsoft.Json; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages |
|||
{ |
|||
public class SubscribeMessageResponse |
|||
{ |
|||
[JsonProperty("errcode")] |
|||
public int ErrorCode { get; set; } |
|||
|
|||
[JsonProperty("errmsg")] |
|||
public string ErrorMessage { get; set; } |
|||
|
|||
public bool IsSuccessed => ErrorCode == 0; |
|||
|
|||
public void ThrowIfNotSuccess() |
|||
{ |
|||
if (ErrorCode != 0) |
|||
{ |
|||
throw new AbpException($"Send wechat weapp notification error:{ErrorMessage}"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
using Newtonsoft.Json; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages |
|||
{ |
|||
public class SubscribeMessageResponse |
|||
{ |
|||
[JsonProperty("errcode")] |
|||
public int ErrorCode { get; set; } |
|||
|
|||
[JsonProperty("errmsg")] |
|||
public string ErrorMessage { get; set; } |
|||
|
|||
public bool IsSuccessed => ErrorCode == 0; |
|||
|
|||
public void ThrowIfNotSuccess() |
|||
{ |
|||
if (ErrorCode != 0) |
|||
{ |
|||
throw new AbpException($"Send wechat weapp notification error:{ErrorMessage}"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,106 +1,106 @@ |
|||
using Newtonsoft.Json; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages |
|||
{ |
|||
public class SubscribeMessage |
|||
{ |
|||
/// <summary>
|
|||
/// 接收者(用户)的 openid
|
|||
/// </summary>
|
|||
[JsonProperty("touser")] |
|||
public string ToUser { get; set; } |
|||
/// <summary>
|
|||
/// 所需下发的订阅模板id
|
|||
/// </summary>
|
|||
[JsonProperty("template_id")] |
|||
public string TemplateId { get; set; } |
|||
/// <summary>
|
|||
/// 点击模板卡片后的跳转页面,仅限本小程序内的页面。
|
|||
/// 支持带参数,(示例index?foo=bar)。
|
|||
/// 该字段不填则模板无跳转
|
|||
/// </summary>
|
|||
[JsonProperty("page")] |
|||
public string Page { get; set; } |
|||
/// <summary>
|
|||
/// 跳转小程序类型:
|
|||
/// developer为开发版;trial为体验版;formal为正式版;
|
|||
/// 默认为正式版
|
|||
/// </summary>
|
|||
[JsonProperty("miniprogram_state")] |
|||
public string MiniProgramState { get; set; } |
|||
/// <summary>
|
|||
/// 进入小程序查看”的语言类型,
|
|||
/// 支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),
|
|||
/// 默认为zh_CN
|
|||
/// </summary>
|
|||
[JsonProperty("lang")] |
|||
public string Lang { get; set; } = "zh_CN"; |
|||
/// <summary>
|
|||
/// 模板内容,
|
|||
/// 格式形如 { "key1": { "value": any }, "key2": { "value": any } }
|
|||
/// </summary>
|
|||
[JsonProperty("data")] |
|||
public Dictionary<string, MessageData> Data { get; set; } = new Dictionary<string, MessageData>(); |
|||
|
|||
public SubscribeMessage() { } |
|||
public SubscribeMessage( |
|||
string openId, |
|||
string templateId, |
|||
string redirectPage = "", |
|||
string state = "formal", |
|||
string miniLang = "zh_CN") |
|||
{ |
|||
ToUser = openId; |
|||
TemplateId = templateId; |
|||
Page = redirectPage; |
|||
MiniProgramState = state; |
|||
Lang = miniLang; |
|||
} |
|||
|
|||
public SubscribeMessage WriteData(string prefix, string key, object value) |
|||
{ |
|||
// 只截取符合标记的数据
|
|||
if (key.StartsWith(prefix)) |
|||
{ |
|||
key = key.Replace(prefix, ""); |
|||
if (!Data.ContainsKey(key)) |
|||
{ |
|||
Data.Add(key, new MessageData(value)); |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
public SubscribeMessage WriteData(string prefix, IDictionary<string, object> setData) |
|||
{ |
|||
foreach (var kv in setData) |
|||
{ |
|||
WriteData(prefix, kv.Key, kv.Value); |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
public SubscribeMessage WriteData(IDictionary<string, object> setData) |
|||
{ |
|||
foreach (var kv in setData) |
|||
{ |
|||
if (!Data.ContainsKey(kv.Key)) |
|||
{ |
|||
Data.Add(kv.Key, new MessageData(kv.Value)); |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
} |
|||
|
|||
public class MessageData |
|||
{ |
|||
public object Value { get; } |
|||
|
|||
public MessageData(object value) |
|||
{ |
|||
Value = value; |
|||
} |
|||
} |
|||
} |
|||
using Newtonsoft.Json; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages |
|||
{ |
|||
public class SubscribeMessage |
|||
{ |
|||
/// <summary>
|
|||
/// 接收者(用户)的 openid
|
|||
/// </summary>
|
|||
[JsonProperty("touser")] |
|||
public string ToUser { get; set; } |
|||
/// <summary>
|
|||
/// 所需下发的订阅模板id
|
|||
/// </summary>
|
|||
[JsonProperty("template_id")] |
|||
public string TemplateId { get; set; } |
|||
/// <summary>
|
|||
/// 点击模板卡片后的跳转页面,仅限本小程序内的页面。
|
|||
/// 支持带参数,(示例index?foo=bar)。
|
|||
/// 该字段不填则模板无跳转
|
|||
/// </summary>
|
|||
[JsonProperty("page")] |
|||
public string Page { get; set; } |
|||
/// <summary>
|
|||
/// 跳转小程序类型:
|
|||
/// developer为开发版;trial为体验版;formal为正式版;
|
|||
/// 默认为正式版
|
|||
/// </summary>
|
|||
[JsonProperty("miniprogram_state")] |
|||
public string MiniProgramState { get; set; } |
|||
/// <summary>
|
|||
/// 进入小程序查看”的语言类型,
|
|||
/// 支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),
|
|||
/// 默认为zh_CN
|
|||
/// </summary>
|
|||
[JsonProperty("lang")] |
|||
public string Lang { get; set; } = "zh_CN"; |
|||
/// <summary>
|
|||
/// 模板内容,
|
|||
/// 格式形如 { "key1": { "value": any }, "key2": { "value": any } }
|
|||
/// </summary>
|
|||
[JsonProperty("data")] |
|||
public Dictionary<string, MessageData> Data { get; set; } = new Dictionary<string, MessageData>(); |
|||
|
|||
public SubscribeMessage() { } |
|||
public SubscribeMessage( |
|||
string openId, |
|||
string templateId, |
|||
string redirectPage = "", |
|||
string state = "formal", |
|||
string miniLang = "zh_CN") |
|||
{ |
|||
ToUser = openId; |
|||
TemplateId = templateId; |
|||
Page = redirectPage; |
|||
MiniProgramState = state; |
|||
Lang = miniLang; |
|||
} |
|||
|
|||
public SubscribeMessage WriteData(string prefix, string key, object value) |
|||
{ |
|||
// 只截取符合标记的数据
|
|||
if (key.StartsWith(prefix)) |
|||
{ |
|||
key = key.Replace(prefix, ""); |
|||
if (!Data.ContainsKey(key)) |
|||
{ |
|||
Data.Add(key, new MessageData(value)); |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
public SubscribeMessage WriteData(string prefix, IDictionary<string, object> setData) |
|||
{ |
|||
foreach (var kv in setData) |
|||
{ |
|||
WriteData(prefix, kv.Key, kv.Value); |
|||
} |
|||
return this; |
|||
} |
|||
|
|||
public SubscribeMessage WriteData(IDictionary<string, object> setData) |
|||
{ |
|||
foreach (var kv in setData) |
|||
{ |
|||
if (!Data.ContainsKey(kv.Key)) |
|||
{ |
|||
Data.Add(kv.Key, new MessageData(kv.Value)); |
|||
} |
|||
} |
|||
return this; |
|||
} |
|||
} |
|||
|
|||
public class MessageData |
|||
{ |
|||
public object Value { get; } |
|||
|
|||
public MessageData(object value) |
|||
{ |
|||
Value = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,121 +1,117 @@ |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using LINGYUN.Abp.WeChat.Token; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Microsoft.Extensions.Options; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Net.Http; |
|||
using System.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages |
|||
{ |
|||
public class SubscribeMessager : ISubscribeMessager, ITransientDependency |
|||
{ |
|||
public ILogger<SubscribeMessager> Logger { get; set; } |
|||
protected IHttpClientFactory HttpClientFactory { get; } |
|||
protected IJsonSerializer JsonSerializer { get; } |
|||
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } |
|||
protected IWeChatTokenProvider WeChatTokenProvider { get; } |
|||
protected IUserWeChatOpenIdFinder UserWeChatOpenIdFinder { get; } |
|||
public SubscribeMessager( |
|||
IJsonSerializer jsonSerializer, |
|||
IHttpClientFactory httpClientFactory, |
|||
IWeChatTokenProvider weChatTokenProvider, |
|||
IUserWeChatOpenIdFinder userWeChatOpenIdFinder, |
|||
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) |
|||
{ |
|||
JsonSerializer = jsonSerializer; |
|||
HttpClientFactory = httpClientFactory; |
|||
WeChatTokenProvider = weChatTokenProvider; |
|||
UserWeChatOpenIdFinder = userWeChatOpenIdFinder; |
|||
MiniProgramOptionsFactory = miniProgramOptionsFactory; |
|||
|
|||
Logger = NullLogger<SubscribeMessager>.Instance; |
|||
} |
|||
|
|||
public virtual async Task SendAsync( |
|||
Guid toUser, |
|||
string templateId, |
|||
string page = "", |
|||
string lang = "zh_CN", |
|||
string state = "formal", |
|||
Dictionary<string, object> data = null, |
|||
CancellationToken cancellation = default) |
|||
{ |
|||
var openId = await UserWeChatOpenIdFinder.FindByUserIdAsync(toUser, AbpWeChatMiniProgramConsts.ProviderKey); |
|||
if (openId.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogWarning("Can not found openId, Unable to send WeChat message!"); |
|||
return; |
|||
} |
|||
var messageData = new SubscribeMessage(openId, templateId, page, state, lang); |
|||
if (data != null) |
|||
{ |
|||
messageData.WriteData(data); |
|||
} |
|||
await SendAsync(messageData, cancellation); |
|||
} |
|||
|
|||
public virtual async Task SendAsync(SubscribeMessage message, CancellationToken cancellationToken = default) |
|||
{ |
|||
var options = await MiniProgramOptionsFactory.CreateAsync(); |
|||
|
|||
var weChatToken = await WeChatTokenProvider.GetTokenAsync(options.AppId, options.AppSecret, cancellationToken); |
|||
var requestParamters = new Dictionary<string, string> |
|||
{ |
|||
{ "access_token", weChatToken.AccessToken } |
|||
}; |
|||
var weChatSendNotificationUrl = "https://api.weixin.qq.com"; |
|||
var weChatSendNotificationPath = "/cgi-bin/message/subscribe/send"; |
|||
var requestUrl = BuildRequestUrl(weChatSendNotificationUrl, weChatSendNotificationPath, requestParamters); |
|||
var responseContent = await MakeRequestAndGetResultAsync(requestUrl, message, cancellationToken); |
|||
var response = JsonSerializer.Deserialize<SubscribeMessageResponse>(responseContent); |
|||
|
|||
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 = JsonSerializer.Serialize(message); |
|||
var requestContent = new StringContent(sendDataContent); |
|||
var requestMessage = new HttpRequestMessage(HttpMethod.Post, url) |
|||
{ |
|||
Content = requestContent |
|||
}; |
|||
|
|||
var response = await client.SendAsync(requestMessage, cancellationToken); |
|||
if (!response.IsSuccessStatusCode) |
|||
{ |
|||
throw new AbpException($"WeChat send subscribe message http request service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}"); |
|||
} |
|||
var resultContent = await response.Content.ReadAsStringAsync(); |
|||
|
|||
return resultContent; |
|||
} |
|||
|
|||
protected virtual string BuildRequestUrl(string uri, string path, IDictionary<string, string> paramters) |
|||
{ |
|||
var requestUrlBuilder = new StringBuilder(128); |
|||
requestUrlBuilder.Append(uri); |
|||
requestUrlBuilder.Append(path).Append("?"); |
|||
foreach (var paramter in paramters) |
|||
{ |
|||
requestUrlBuilder.AppendFormat("{0}={1}", paramter.Key, paramter.Value); |
|||
requestUrlBuilder.Append("&"); |
|||
} |
|||
requestUrlBuilder.Remove(requestUrlBuilder.Length - 1, 1); |
|||
return requestUrlBuilder.ToString(); |
|||
} |
|||
} |
|||
} |
|||
using LINGYUN.Abp.WeChat.OpenId; |
|||
using LINGYUN.Abp.WeChat.Token; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Newtonsoft.Json; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Net.Http; |
|||
using System.Text; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.MiniProgram.Messages |
|||
{ |
|||
public class SubscribeMessager : ISubscribeMessager, ITransientDependency |
|||
{ |
|||
public ILogger<SubscribeMessager> Logger { get; set; } |
|||
protected IHttpClientFactory HttpClientFactory { get; } |
|||
protected AbpWeChatMiniProgramOptionsFactory MiniProgramOptionsFactory { get; } |
|||
protected IWeChatTokenProvider WeChatTokenProvider { get; } |
|||
protected IUserWeChatOpenIdFinder UserWeChatOpenIdFinder { get; } |
|||
public SubscribeMessager( |
|||
IHttpClientFactory httpClientFactory, |
|||
IWeChatTokenProvider weChatTokenProvider, |
|||
IUserWeChatOpenIdFinder userWeChatOpenIdFinder, |
|||
AbpWeChatMiniProgramOptionsFactory miniProgramOptionsFactory) |
|||
{ |
|||
HttpClientFactory = httpClientFactory; |
|||
WeChatTokenProvider = weChatTokenProvider; |
|||
UserWeChatOpenIdFinder = userWeChatOpenIdFinder; |
|||
MiniProgramOptionsFactory = miniProgramOptionsFactory; |
|||
|
|||
Logger = NullLogger<SubscribeMessager>.Instance; |
|||
} |
|||
|
|||
public virtual async Task SendAsync( |
|||
Guid toUser, |
|||
string templateId, |
|||
string page = "", |
|||
string lang = "zh_CN", |
|||
string state = "formal", |
|||
Dictionary<string, object> data = null, |
|||
CancellationToken cancellation = default) |
|||
{ |
|||
var openId = await UserWeChatOpenIdFinder.FindByUserIdAsync(toUser, AbpWeChatMiniProgramConsts.ProviderName); |
|||
if (openId.IsNullOrWhiteSpace()) |
|||
{ |
|||
Logger.LogWarning("Can not found openId, Unable to send WeChat message!"); |
|||
return; |
|||
} |
|||
var messageData = new SubscribeMessage(openId, templateId, page, state, lang); |
|||
if (data != null) |
|||
{ |
|||
messageData.WriteData(data); |
|||
} |
|||
await SendAsync(messageData, cancellation); |
|||
} |
|||
|
|||
public virtual async Task SendAsync(SubscribeMessage message, CancellationToken cancellationToken = default) |
|||
{ |
|||
var options = await MiniProgramOptionsFactory.CreateAsync(); |
|||
|
|||
var weChatToken = await WeChatTokenProvider.GetTokenAsync(options.AppId, options.AppSecret, cancellationToken); |
|||
var requestParamters = new Dictionary<string, string> |
|||
{ |
|||
{ "access_token", weChatToken.AccessToken } |
|||
}; |
|||
var weChatSendNotificationUrl = "https://api.weixin.qq.com"; |
|||
var weChatSendNotificationPath = "/cgi-bin/message/subscribe/send"; |
|||
var requestUrl = BuildRequestUrl(weChatSendNotificationUrl, weChatSendNotificationPath, requestParamters); |
|||
var responseContent = await MakeRequestAndGetResultAsync(requestUrl, message, cancellationToken); |
|||
var response = JsonConvert.DeserializeObject<SubscribeMessageResponse>(responseContent); |
|||
|
|||
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); |
|||
var requestContent = new StringContent(sendDataContent); |
|||
var requestMessage = new HttpRequestMessage(HttpMethod.Post, url) |
|||
{ |
|||
Content = requestContent |
|||
}; |
|||
|
|||
var response = await client.SendAsync(requestMessage, cancellationToken); |
|||
if (!response.IsSuccessStatusCode) |
|||
{ |
|||
throw new AbpException($"WeChat send subscribe message http request service returns error! HttpStatusCode: {response.StatusCode}, ReasonPhrase: {response.ReasonPhrase}"); |
|||
} |
|||
var resultContent = await response.Content.ReadAsStringAsync(); |
|||
|
|||
return resultContent; |
|||
} |
|||
|
|||
protected virtual string BuildRequestUrl(string uri, string path, IDictionary<string, string> paramters) |
|||
{ |
|||
var requestUrlBuilder = new StringBuilder(128); |
|||
requestUrlBuilder.Append(uri); |
|||
requestUrlBuilder.Append(path).Append("?"); |
|||
foreach (var paramter in paramters) |
|||
{ |
|||
requestUrlBuilder.AppendFormat("{0}={1}", paramter.Key, paramter.Value); |
|||
requestUrlBuilder.Append("&"); |
|||
} |
|||
requestUrlBuilder.Remove(requestUrlBuilder.Length - 1, 1); |
|||
return requestUrlBuilder.ToString(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,22 +1,22 @@ |
|||
namespace LINGYUN.Abp.WeChat.Official |
|||
{ |
|||
public class AbpWeChatOfficialConsts |
|||
{ |
|||
/// <summary>
|
|||
/// 微信公众号对应的Provider名称
|
|||
/// </summary>
|
|||
public static string ProviderKey { get; set; } = "WeChat.Official"; |
|||
|
|||
/// <summary>
|
|||
/// 微信公众平台授权类型
|
|||
/// </summary>
|
|||
public static string GrantType { get; set; } = "wx-op"; |
|||
|
|||
/// <summary>
|
|||
/// 微信公众平台授权方法名称
|
|||
/// </summary>
|
|||
public static string AuthenticationMethod { get; set; } = "woa"; |
|||
|
|||
public static string HttpClient { get; set; } = "Abp.WeChat.Official"; |
|||
} |
|||
} |
|||
namespace LINGYUN.Abp.WeChat.Official |
|||
{ |
|||
public class AbpWeChatOfficialConsts |
|||
{ |
|||
/// <summary>
|
|||
/// 微信公众号对应的Provider名称
|
|||
/// </summary>
|
|||
public static string ProviderName { get; set; } = "WeChat.Official"; |
|||
|
|||
/// <summary>
|
|||
/// 微信公众平台授权类型
|
|||
/// </summary>
|
|||
public static string GrantType { get; set; } = "wx-op"; |
|||
|
|||
/// <summary>
|
|||
/// 微信公众平台授权方法名称
|
|||
/// </summary>
|
|||
public static string AuthenticationMethod { get; set; } = "woa"; |
|||
|
|||
public static string HttpClient { get; set; } = "Abp.WeChat.Official"; |
|||
} |
|||
} |
|||
|
|||
@ -1,116 +1,124 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using LINGYUN.Abp.WeChat.Localization; |
|||
using LINGYUN.Abp.WeChat.MiniProgram.Settings; |
|||
using LINGYUN.Abp.WeChat.Official.Settings; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.SettingManagement |
|||
{ |
|||
public class WeChatSettingAppService : ApplicationService, IWeChatSettingAppService |
|||
{ |
|||
protected ISettingManager SettingManager { get; } |
|||
protected IPermissionChecker PermissionChecker { get; } |
|||
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
|||
|
|||
public WeChatSettingAppService( |
|||
ISettingManager settingManager, |
|||
IPermissionChecker permissionChecker, |
|||
ISettingDefinitionManager settingDefinitionManager) |
|||
{ |
|||
SettingManager = settingManager; |
|||
PermissionChecker = permissionChecker; |
|||
SettingDefinitionManager = settingDefinitionManager; |
|||
LocalizationResource = typeof(WeChatResource); |
|||
} |
|||
|
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync() |
|||
{ |
|||
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); |
|||
} |
|||
|
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync() |
|||
{ |
|||
return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); |
|||
} |
|||
|
|||
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"]); |
|||
|
|||
// 无权限返回空结果,直接报错的话,网关聚合会抛出异常
|
|||
if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.Official)) |
|||
{ |
|||
#region 公众号
|
|||
|
|||
var officialSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.Official"], L["Description:WeChat.Official"]); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppId), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppId, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppSecret), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppSecret, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.Url), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Url, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.Token), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Token, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.EncodingAESKey), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.EncodingAESKey, providerName, providerKey), |
|||
ValueType.String); |
|||
|
|||
#endregion
|
|||
} |
|||
|
|||
if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.MiniProgram)) |
|||
{ |
|||
#region 小程序
|
|||
|
|||
var miniProgramSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.MiniProgram"], L["Description:WeChat.MiniProgram"]); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppId), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppId, providerName, providerKey), |
|||
ValueType.String); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppSecret), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppSecret, providerName, providerKey), |
|||
ValueType.String); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.Token), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.Token, providerName, providerKey), |
|||
ValueType.String); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.EncodingAESKey), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.EncodingAESKey, providerName, providerKey), |
|||
ValueType.String); |
|||
|
|||
#endregion
|
|||
} |
|||
|
|||
settingGroups.Add(wechatSettingGroup); |
|||
return new ListResultDto<SettingGroupDto>(settingGroups); |
|||
} |
|||
} |
|||
} |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using LINGYUN.Abp.WeChat.Localization; |
|||
using LINGYUN.Abp.WeChat.MiniProgram.Settings; |
|||
using LINGYUN.Abp.WeChat.Official.Settings; |
|||
using LINGYUN.Abp.WeChat.Settings; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.SettingManagement |
|||
{ |
|||
public class WeChatSettingAppService : ApplicationService, IWeChatSettingAppService |
|||
{ |
|||
protected ISettingManager SettingManager { get; } |
|||
protected IPermissionChecker PermissionChecker { get; } |
|||
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
|||
|
|||
public WeChatSettingAppService( |
|||
ISettingManager settingManager, |
|||
IPermissionChecker permissionChecker, |
|||
ISettingDefinitionManager settingDefinitionManager) |
|||
{ |
|||
SettingManager = settingManager; |
|||
PermissionChecker = permissionChecker; |
|||
SettingDefinitionManager = settingDefinitionManager; |
|||
LocalizationResource = typeof(WeChatResource); |
|||
} |
|||
|
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync() |
|||
{ |
|||
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); |
|||
} |
|||
|
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync() |
|||
{ |
|||
return await GetAllForProviderAsync(GlobalSettingValueProvider.ProviderName, null); |
|||
} |
|||
|
|||
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 loginSetting = wechatSettingGroup.AddSetting(L["UserLogin"], L["UserLogin"]); |
|||
loginSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatSettingNames.EnabledQuickLogin), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatSettingNames.EnabledQuickLogin, providerName, providerKey), |
|||
ValueType.Boolean); |
|||
|
|||
// 无权限返回空结果,直接报错的话,网关聚合会抛出异常
|
|||
if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.Official)) |
|||
{ |
|||
#region 公众号
|
|||
|
|||
var officialSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.Official"], L["Description:WeChat.Official"]); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppId), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppId, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.AppSecret), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.AppSecret, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.Url), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Url, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.Token), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.Token, providerName, providerKey), |
|||
ValueType.String); |
|||
officialSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatOfficialSettingNames.EncodingAESKey), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatOfficialSettingNames.EncodingAESKey, providerName, providerKey), |
|||
ValueType.String); |
|||
|
|||
#endregion
|
|||
} |
|||
|
|||
if (await PermissionChecker.IsGrantedAsync(WeChatSettingPermissionNames.MiniProgram)) |
|||
{ |
|||
#region 小程序
|
|||
|
|||
var miniProgramSetting = wechatSettingGroup.AddSetting(L["DisplayName:WeChat.MiniProgram"], L["Description:WeChat.MiniProgram"]); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppId), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppId, providerName, providerKey), |
|||
ValueType.String); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.AppSecret), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.AppSecret, providerName, providerKey), |
|||
ValueType.String); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.Token), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.Token, providerName, providerKey), |
|||
ValueType.String); |
|||
miniProgramSetting.AddDetail( |
|||
SettingDefinitionManager.Get(WeChatMiniProgramSettingNames.EncodingAESKey), |
|||
StringLocalizerFactory, |
|||
await SettingManager.GetOrNullAsync(WeChatMiniProgramSettingNames.EncodingAESKey, providerName, providerKey), |
|||
ValueType.String); |
|||
|
|||
#endregion
|
|||
} |
|||
|
|||
settingGroups.Add(wechatSettingGroup); |
|||
return new ListResultDto<SettingGroupDto>(settingGroups); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,42 +1,44 @@ |
|||
using LINGYUN.Abp.WeChat.Localization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Polly; |
|||
using System; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.WeChat |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpCachingModule), |
|||
typeof(AbpFeaturesModule), |
|||
typeof(AbpJsonModule))] |
|||
public class AbpWeChatModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpWeChatModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<WeChatResource>("zh-Hans") |
|||
.AddVirtualJson("/LINGYUN/Abp/WeChat/Localization/Resources"); |
|||
}); |
|||
|
|||
context.Services.AddHttpClient(AbpWeChatGlobalConsts.HttpClient, |
|||
options => |
|||
{ |
|||
options.BaseAddress = new Uri("https://api.weixin.qq.com"); |
|||
}).AddTransientHttpErrorPolicy(builder => |
|||
builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)))); |
|||
} |
|||
} |
|||
} |
|||
using LINGYUN.Abp.WeChat.Localization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Polly; |
|||
using System; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Settings; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.WeChat |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpCachingModule), |
|||
typeof(AbpFeaturesModule), |
|||
typeof(AbpJsonModule), |
|||
typeof(AbpSettingsModule))] |
|||
public class AbpWeChatModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpWeChatModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<WeChatResource>("zh-Hans") |
|||
.AddVirtualJson("/LINGYUN/Abp/WeChat/Localization/Resources"); |
|||
}); |
|||
|
|||
context.Services.AddHttpClient(AbpWeChatGlobalConsts.HttpClient, |
|||
options => |
|||
{ |
|||
options.BaseAddress = new Uri("https://api.weixin.qq.com"); |
|||
}).AddTransientHttpErrorPolicy(builder => |
|||
builder.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(Math.Pow(2, i)))); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.WeChat.Crypto |
|||
{ |
|||
public interface IWeChatCryptoService |
|||
{ |
|||
string Decrypt(string encryptedData, string iv, string sessionKey); |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -1,12 +1,12 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
public interface IUserWeChatOpenIdFinder |
|||
{ |
|||
Task<string> FindByUserIdAsync(Guid userId, string provider); |
|||
|
|||
Task<string> FindByUserNameAsync(string userName, string provider); |
|||
} |
|||
} |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
public interface IUserWeChatOpenIdFinder |
|||
{ |
|||
Task<string> FindByUserIdAsync(Guid userId, string provider); |
|||
|
|||
Task<string> FindByUserNameAsync(string userName, string provider); |
|||
} |
|||
} |
|||
|
|||
@ -1,9 +1,17 @@ |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
public interface IWeChatOpenIdFinder |
|||
{ |
|||
Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret); |
|||
} |
|||
} |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
public interface IWeChatOpenIdFinder |
|||
{ |
|||
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); |
|||
} |
|||
} |
|||
|
|||
@ -1,24 +1,32 @@ |
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
public class WeChatOpenIdCacheItem |
|||
{ |
|||
public string Code { get; set; } |
|||
|
|||
public WeChatOpenId WeChatOpenId { get; set; } |
|||
public WeChatOpenIdCacheItem() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public WeChatOpenIdCacheItem(string code, WeChatOpenId weChatOpenId) |
|||
{ |
|||
Code = code; |
|||
WeChatOpenId = weChatOpenId; |
|||
} |
|||
|
|||
public static string CalculateCacheKey(string appId, string code) |
|||
{ |
|||
return "app:" + appId + ";code:" + code; |
|||
} |
|||
} |
|||
} |
|||
using System; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
public class WeChatOpenIdCacheItem |
|||
{ |
|||
public string Code { get; set; } |
|||
|
|||
public WeChatOpenId WeChatOpenId { get; set; } |
|||
public WeChatOpenIdCacheItem() |
|||
{ |
|||
|
|||
} |
|||
|
|||
public WeChatOpenIdCacheItem(string code, WeChatOpenId weChatOpenId) |
|||
{ |
|||
Code = code; |
|||
WeChatOpenId = weChatOpenId; |
|||
} |
|||
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,95 +1,117 @@ |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)] |
|||
[ExposeServices(typeof(IWeChatOpenIdFinder))] |
|||
public class WeChatOpenIdFinder : IWeChatOpenIdFinder |
|||
{ |
|||
public ILogger<WeChatOpenIdFinder> Logger { get; set; } |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
protected IHttpClientFactory HttpClientFactory { get; } |
|||
protected IJsonSerializer JsonSerializer { get; } |
|||
protected IDistributedCache<WeChatOpenIdCacheItem> Cache { get; } |
|||
public WeChatOpenIdFinder( |
|||
ICurrentTenant currentTenant, |
|||
IJsonSerializer jsonSerializer, |
|||
IHttpClientFactory httpClientFactory, |
|||
IDistributedCache<WeChatOpenIdCacheItem> cache) |
|||
{ |
|||
CurrentTenant = currentTenant; |
|||
JsonSerializer = jsonSerializer; |
|||
HttpClientFactory = httpClientFactory; |
|||
|
|||
Cache = cache; |
|||
|
|||
Logger = NullLogger<WeChatOpenIdFinder>.Instance; |
|||
} |
|||
public virtual async Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret) |
|||
{ |
|||
// TODO: 如果需要获取SessionKey的话呢,需要再以openid作为标识来缓存一下吗
|
|||
// 或者前端保存code,通过传递code来获取
|
|||
return (await GetCacheItemAsync(code, appId, appSecret)).WeChatOpenId; |
|||
} |
|||
|
|||
protected virtual async Task<WeChatOpenIdCacheItem> GetCacheItemAsync(string code, string appId, string appSecret) |
|||
{ |
|||
var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(appId, code); |
|||
|
|||
Logger.LogDebug($"WeChatOpenIdFinder.GetCacheItemAsync: {cacheKey}"); |
|||
|
|||
var cacheItem = await Cache.GetAsync(cacheKey); |
|||
|
|||
if (cacheItem != null) |
|||
{ |
|||
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); |
|||
|
|||
var request = new WeChatOpenIdRequest |
|||
{ |
|||
BaseUrl = client.BaseAddress.AbsoluteUri, |
|||
AppId = appId, |
|||
Secret = appSecret, |
|||
Code = code |
|||
}; |
|||
|
|||
var response = await client.RequestWeChatOpenIdAsync(request); |
|||
var responseContent = await response.Content.ReadAsStringAsync(); |
|||
var weChatOpenIdResponse = JsonSerializer.Deserialize<WeChatOpenIdResponse>(responseContent); |
|||
var weChatOpenId = weChatOpenIdResponse.ToWeChatOpenId(); |
|||
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); |
|||
|
|||
Logger.LogDebug($"Finished setting the cache item: {cacheKey}"); |
|||
|
|||
return cacheItem; |
|||
} |
|||
} |
|||
} |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Newtonsoft.Json; |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.Users; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
[Dependency(ServiceLifetime.Singleton, ReplaceServices = true)] |
|||
[ExposeServices(typeof(IWeChatOpenIdFinder))] |
|||
public class WeChatOpenIdFinder : IWeChatOpenIdFinder |
|||
{ |
|||
public ILogger<WeChatOpenIdFinder> Logger { get; set; } |
|||
protected ICurrentTenant CurrentTenant { get; } |
|||
protected ICurrentUser CurrentUser { get; } |
|||
protected IHttpClientFactory HttpClientFactory { get; } |
|||
protected IDistributedCache<WeChatOpenIdCacheItem> Cache { get; } |
|||
public WeChatOpenIdFinder( |
|||
ICurrentUser currentUser, |
|||
ICurrentTenant currentTenant, |
|||
IHttpClientFactory httpClientFactory, |
|||
IDistributedCache<WeChatOpenIdCacheItem> cache) |
|||
{ |
|||
CurrentUser = currentUser; |
|||
CurrentTenant = currentTenant; |
|||
HttpClientFactory = httpClientFactory; |
|||
|
|||
Cache = cache; |
|||
|
|||
Logger = NullLogger<WeChatOpenIdFinder>.Instance; |
|||
} |
|||
|
|||
public virtual async Task<WeChatOpenId> FindAsync(string appId) |
|||
{ |
|||
if (!CurrentUser.IsAuthenticated) |
|||
{ |
|||
throw new AbpAuthorizationException("Try to get wechat information when the user is not logged in!"); |
|||
} |
|||
var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(appId, CurrentUser.Id.Value); |
|||
var openIdCache = await Cache.GetAsync(cacheKey); |
|||
return openIdCache?.WeChatOpenId ?? |
|||
throw new AbpException("The wechat login session has expired. Use 'wx.login' result code to exchange the sessionKey"); |
|||
} |
|||
|
|||
public virtual async Task<WeChatOpenId> FindAsync(string code, string appId, string appSecret) |
|||
{ |
|||
// TODO: 如果需要获取SessionKey的话呢,需要再以openid作为标识来缓存一下吗
|
|||
// 或者前端保存code,通过传递code来获取
|
|||
return (await GetCacheItemAsync(code, appId, appSecret)).WeChatOpenId; |
|||
} |
|||
|
|||
protected virtual async Task<WeChatOpenIdCacheItem> GetCacheItemAsync(string code, string appId, string appSecret) |
|||
{ |
|||
var cacheKey = WeChatOpenIdCacheItem.CalculateCacheKey(appId, code); |
|||
|
|||
Logger.LogDebug($"WeChatOpenIdFinder.GetCacheItemAsync: {cacheKey}"); |
|||
|
|||
var cacheItem = await Cache.GetAsync(cacheKey); |
|||
|
|||
if (cacheItem != null) |
|||
{ |
|||
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); |
|||
|
|||
var request = new WeChatOpenIdRequest |
|||
{ |
|||
BaseUrl = client.BaseAddress.AbsoluteUri, |
|||
AppId = appId, |
|||
Secret = appSecret, |
|||
Code = code |
|||
}; |
|||
|
|||
var response = await client.RequestWeChatOpenIdAsync(request); |
|||
var responseContent = await response.Content.ReadAsStringAsync(); |
|||
// 改为直接引用 Newtownsoft.Json
|
|||
var weChatOpenIdResponse = JsonConvert.DeserializeObject<WeChatOpenIdResponse>(responseContent); |
|||
var weChatOpenId = weChatOpenIdResponse.ToWeChatOpenId(); |
|||
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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,63 +1,63 @@ |
|||
using Newtonsoft.Json; |
|||
using System; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
/// <summary>
|
|||
/// 微信OpenId返回对象
|
|||
/// </summary>
|
|||
public class WeChatOpenIdResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 错误码
|
|||
/// </summary>
|
|||
[JsonProperty("errcode")] |
|||
public string ErrorCode { get; set; } |
|||
/// <summary>
|
|||
/// 会话密钥
|
|||
/// </summary>
|
|||
[JsonProperty("session_key")] |
|||
public string SessionKey { get; set; } |
|||
/// <summary>
|
|||
/// 用户唯一标识
|
|||
/// </summary>
|
|||
[JsonProperty("openid")] |
|||
public string OpenId { get; set; } |
|||
/// <summary>
|
|||
/// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回
|
|||
/// </summary>
|
|||
[JsonProperty("unionid")] |
|||
public string UnionId { get; set; } |
|||
/// <summary>
|
|||
/// 错误消息
|
|||
/// </summary>
|
|||
public string ErrorMessage |
|||
{ |
|||
get |
|||
{ |
|||
switch (ErrorCode) |
|||
{ |
|||
case "-1": return "系统繁忙,此时请开发者稍候再试"; |
|||
case "0": return string.Empty; |
|||
case "40029": return "code 无效"; |
|||
case "45011": return "频率限制,每个用户每分钟100次"; |
|||
default: return $"未定义的异常代码:{ErrorCode},请重试"; |
|||
}; |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 微信认证成功没有errorcode或者errorcode为0
|
|||
/// </summary>
|
|||
public bool IsError => !ErrorCode.IsNullOrWhiteSpace() && !"0".Equals(ErrorCode); |
|||
|
|||
public WeChatOpenId ToWeChatOpenId() |
|||
{ |
|||
if(IsError) |
|||
{ |
|||
throw new AbpException(ErrorMessage); |
|||
} |
|||
return new WeChatOpenId(OpenId, SessionKey, UnionId); |
|||
} |
|||
} |
|||
} |
|||
using Newtonsoft.Json; |
|||
using System; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.OpenId |
|||
{ |
|||
/// <summary>
|
|||
/// 微信OpenId返回对象
|
|||
/// </summary>
|
|||
public class WeChatOpenIdResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 错误码
|
|||
/// </summary>
|
|||
[JsonProperty("errcode")] |
|||
public string ErrorCode { get; set; } |
|||
/// <summary>
|
|||
/// 会话密钥
|
|||
/// </summary>
|
|||
[JsonProperty("session_key")] |
|||
public string SessionKey { get; set; } |
|||
/// <summary>
|
|||
/// 用户唯一标识
|
|||
/// </summary>
|
|||
[JsonProperty("openid")] |
|||
public string OpenId { get; set; } |
|||
/// <summary>
|
|||
/// 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回
|
|||
/// </summary>
|
|||
[JsonProperty("unionid")] |
|||
public string UnionId { get; set; } |
|||
/// <summary>
|
|||
/// 错误消息
|
|||
/// </summary>
|
|||
public string ErrorMessage |
|||
{ |
|||
get |
|||
{ |
|||
switch (ErrorCode) |
|||
{ |
|||
case "-1": return "系统繁忙,此时请开发者稍候再试"; |
|||
case "0": return string.Empty; |
|||
case "40029": return "code 无效"; |
|||
case "45011": return "频率限制,每个用户每分钟100次"; |
|||
default: return $"未定义的异常代码:{ErrorCode},请重试"; |
|||
}; |
|||
} |
|||
} |
|||
/// <summary>
|
|||
/// 微信认证成功没有errorcode或者errorcode为0
|
|||
/// </summary>
|
|||
public bool IsError => !ErrorCode.IsNullOrWhiteSpace() && !"0".Equals(ErrorCode); |
|||
|
|||
public WeChatOpenId ToWeChatOpenId() |
|||
{ |
|||
if(IsError) |
|||
{ |
|||
throw new AbpException(ErrorMessage); |
|||
} |
|||
return new WeChatOpenId(OpenId, SessionKey, UnionId); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -1,7 +1,12 @@ |
|||
namespace LINGYUN.Abp.WeChat.Settings |
|||
{ |
|||
public static class WeChatSettingNames |
|||
{ |
|||
public const string Prefix = "Abp.WeChat"; |
|||
} |
|||
} |
|||
namespace LINGYUN.Abp.WeChat.Settings |
|||
{ |
|||
public static class WeChatSettingNames |
|||
{ |
|||
public const string Prefix = "Abp.WeChat"; |
|||
/// <summary>
|
|||
/// 启用快捷登录
|
|||
/// 通过微信code登录时,如果没有注册用户信息且此配置启用时,直接创建新用户并关联openid
|
|||
/// </summary>
|
|||
public const string EnabledQuickLogin = Prefix + ".EnabledQuickLogin"; |
|||
} |
|||
} |
|||
|
|||
@ -1,92 +1,90 @@ |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.Token |
|||
{ |
|||
public class WeChatTokenProvider : IWeChatTokenProvider, ISingletonDependency |
|||
{ |
|||
public ILogger<WeChatTokenProvider> Logger { get; set; } |
|||
protected IHttpClientFactory HttpClientFactory { get; } |
|||
protected IJsonSerializer JsonSerializer { get; } |
|||
protected IDistributedCache<WeChatTokenCacheItem> Cache { get; } |
|||
public WeChatTokenProvider( |
|||
IJsonSerializer jsonSerializer, |
|||
IHttpClientFactory httpClientFactory, |
|||
IDistributedCache<WeChatTokenCacheItem> cache) |
|||
{ |
|||
JsonSerializer = jsonSerializer; |
|||
HttpClientFactory = httpClientFactory; |
|||
|
|||
Cache = cache; |
|||
|
|||
Logger = NullLogger<WeChatTokenProvider>.Instance; |
|||
} |
|||
|
|||
public virtual async Task<WeChatToken> GetTokenAsync( |
|||
string appId, |
|||
string appSecret, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
return (await GetCacheItemAsync("WeChatToken", appId, appSecret, cancellationToken)).WeChatToken; |
|||
} |
|||
|
|||
protected virtual async Task<WeChatTokenCacheItem> GetCacheItemAsync( |
|||
string provider, |
|||
string appId, |
|||
string appSecret, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
var cacheKey = WeChatTokenCacheItem.CalculateCacheKey(provider, appId); |
|||
|
|||
Logger.LogDebug($"WeChatTokenProvider.GetCacheItemAsync: {cacheKey}"); |
|||
|
|||
var cacheItem = await Cache.GetAsync(cacheKey, token: cancellationToken); |
|||
|
|||
if (cacheItem != null) |
|||
{ |
|||
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); |
|||
|
|||
var request = new WeChatTokenRequest |
|||
{ |
|||
BaseUrl = client.BaseAddress.AbsoluteUri, |
|||
AppSecret = appSecret, |
|||
AppId = appId, |
|||
GrantType = "client_credential" |
|||
}; |
|||
|
|||
var response = await client.RequestWeChatCodeTokenAsync(request, cancellationToken); |
|||
var responseContent = await response.Content.ReadAsStringAsync(); |
|||
var weChatTokenResponse = JsonSerializer.Deserialize<WeChatTokenResponse>(responseContent); |
|||
var weChatToken = weChatTokenResponse.ToWeChatToken(); |
|||
cacheItem = new WeChatTokenCacheItem(appId, weChatToken); |
|||
|
|||
Logger.LogDebug($"Setting the cache item: {cacheKey}"); |
|||
|
|||
var cacheOptions = new DistributedCacheEntryOptions |
|||
{ |
|||
// 设置绝对过期时间为Token有效期剩余的二分钟
|
|||
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(weChatToken.ExpiresIn - 120) |
|||
}; |
|||
|
|||
await Cache.SetAsync(cacheKey, cacheItem, cacheOptions, token: cancellationToken); |
|||
|
|||
Logger.LogDebug($"Finished setting the cache item: {cacheKey}"); |
|||
|
|||
return cacheItem; |
|||
} |
|||
} |
|||
} |
|||
using Microsoft.Extensions.Caching.Distributed; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Newtonsoft.Json; |
|||
using System; |
|||
using System.Net.Http; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.Token |
|||
{ |
|||
public class WeChatTokenProvider : IWeChatTokenProvider, ISingletonDependency |
|||
{ |
|||
public ILogger<WeChatTokenProvider> Logger { get; set; } |
|||
protected IHttpClientFactory HttpClientFactory { get; } |
|||
protected IDistributedCache<WeChatTokenCacheItem> Cache { get; } |
|||
public WeChatTokenProvider( |
|||
IHttpClientFactory httpClientFactory, |
|||
IDistributedCache<WeChatTokenCacheItem> cache) |
|||
{ |
|||
HttpClientFactory = httpClientFactory; |
|||
|
|||
Cache = cache; |
|||
|
|||
Logger = NullLogger<WeChatTokenProvider>.Instance; |
|||
} |
|||
|
|||
public virtual async Task<WeChatToken> GetTokenAsync( |
|||
string appId, |
|||
string appSecret, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
return (await GetCacheItemAsync("WeChatToken", appId, appSecret, cancellationToken)).WeChatToken; |
|||
} |
|||
|
|||
protected virtual async Task<WeChatTokenCacheItem> GetCacheItemAsync( |
|||
string provider, |
|||
string appId, |
|||
string appSecret, |
|||
CancellationToken cancellationToken = default) |
|||
{ |
|||
var cacheKey = WeChatTokenCacheItem.CalculateCacheKey(provider, appId); |
|||
|
|||
Logger.LogDebug($"WeChatTokenProvider.GetCacheItemAsync: {cacheKey}"); |
|||
|
|||
var cacheItem = await Cache.GetAsync(cacheKey, token: cancellationToken); |
|||
|
|||
if (cacheItem != null) |
|||
{ |
|||
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); |
|||
|
|||
var request = new WeChatTokenRequest |
|||
{ |
|||
BaseUrl = client.BaseAddress.AbsoluteUri, |
|||
AppSecret = appSecret, |
|||
AppId = appId, |
|||
GrantType = "client_credential" |
|||
}; |
|||
|
|||
var response = await client.RequestWeChatCodeTokenAsync(request, cancellationToken); |
|||
var responseContent = await response.Content.ReadAsStringAsync(); |
|||
// 改为直接引用 Newtownsoft.Json
|
|||
var weChatTokenResponse = JsonConvert.DeserializeObject<WeChatTokenResponse>(responseContent); |
|||
var weChatToken = weChatTokenResponse.ToWeChatToken(); |
|||
cacheItem = new WeChatTokenCacheItem(appId, weChatToken); |
|||
|
|||
Logger.LogDebug($"Setting the cache item: {cacheKey}"); |
|||
|
|||
var cacheOptions = new DistributedCacheEntryOptions |
|||
{ |
|||
// 设置绝对过期时间为Token有效期剩余的二分钟
|
|||
AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(weChatToken.ExpiresIn - 120) |
|||
}; |
|||
|
|||
await Cache.SetAsync(cacheKey, cacheItem, cacheOptions, token: cancellationToken); |
|||
|
|||
Logger.LogDebug($"Finished setting the cache item: {cacheKey}"); |
|||
|
|||
return cacheItem; |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,41 +1,41 @@ |
|||
using Newtonsoft.Json; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.Token |
|||
{ |
|||
/// <summary>
|
|||
/// 微信访问令牌返回对象
|
|||
/// </summary>
|
|||
public class WeChatTokenResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 错误码
|
|||
/// </summary>
|
|||
[JsonProperty("errcode")] |
|||
public int ErrorCode { get; set; } |
|||
/// <summary>
|
|||
/// 错误消息
|
|||
/// </summary>
|
|||
[JsonProperty("errmsg")] |
|||
public string ErrorMessage { get; set; } |
|||
/// <summary>
|
|||
/// 访问令牌
|
|||
/// </summary>
|
|||
[JsonProperty("access_token")] |
|||
public string AccessToken { get; set; } |
|||
/// <summary>
|
|||
/// 过期时间,单位(s)
|
|||
/// </summary>
|
|||
[JsonProperty("expires_in")] |
|||
public int ExpiresIn { get; set; } |
|||
|
|||
public WeChatToken ToWeChatToken() |
|||
{ |
|||
if(ErrorCode != 0) |
|||
{ |
|||
throw new AbpException(ErrorMessage); |
|||
} |
|||
return new WeChatToken(AccessToken, ExpiresIn); |
|||
} |
|||
} |
|||
} |
|||
using Newtonsoft.Json; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WeChat.Token |
|||
{ |
|||
/// <summary>
|
|||
/// 微信访问令牌返回对象
|
|||
/// </summary>
|
|||
public class WeChatTokenResponse |
|||
{ |
|||
/// <summary>
|
|||
/// 错误码
|
|||
/// </summary>
|
|||
[JsonProperty("errcode")] |
|||
public int ErrorCode { get; set; } |
|||
/// <summary>
|
|||
/// 错误消息
|
|||
/// </summary>
|
|||
[JsonProperty("errmsg")] |
|||
public string ErrorMessage { get; set; } |
|||
/// <summary>
|
|||
/// 访问令牌
|
|||
/// </summary>
|
|||
[JsonProperty("access_token")] |
|||
public string AccessToken { get; set; } |
|||
/// <summary>
|
|||
/// 过期时间,单位(s)
|
|||
/// </summary>
|
|||
[JsonProperty("expires_in")] |
|||
public int ExpiresIn { get; set; } |
|||
|
|||
public WeChatToken ToWeChatToken() |
|||
{ |
|||
if(ErrorCode != 0) |
|||
{ |
|||
throw new AbpException(ErrorMessage); |
|||
} |
|||
return new WeChatToken(AccessToken, ExpiresIn); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -1,310 +1,314 @@ |
|||
using DotNetCore.CAP; |
|||
using Hangfire; |
|||
using LINGYUN.Abp.AspNetCore.HttpOverrides; |
|||
using LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json; |
|||
using LINGYUN.Abp.BackgroundJobs.Hangfire; |
|||
using LINGYUN.Abp.EventBus.CAP; |
|||
using LINGYUN.Abp.ExceptionHandling; |
|||
using LINGYUN.Abp.ExceptionHandling.Notifications; |
|||
using LINGYUN.Abp.Hangfire.Storage.MySql; |
|||
using LINGYUN.Abp.IM.SignalR; |
|||
using LINGYUN.Abp.MessageService.EntityFrameworkCore; |
|||
using LINGYUN.Abp.MessageService.Localization; |
|||
using LINGYUN.Abp.MultiTenancy.DbFinder; |
|||
using LINGYUN.Abp.Notifications.SignalR; |
|||
using LINGYUN.Abp.Notifications.Sms; |
|||
using LINGYUN.Abp.Notifications.WeChat.MiniProgram; |
|||
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Cors; |
|||
using Microsoft.AspNetCore.DataProtection; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.Caching.StackExchangeRedis; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.OpenApi.Models; |
|||
using StackExchange.Redis; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Text.Encodings.Web; |
|||
using System.Text.Unicode; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Auditing; |
|||
using Volo.Abp.AspNetCore.Authentication.JwtBearer; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.AspNetCore.Security.Claims; |
|||
using Volo.Abp.AspNetCore.Uow; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.BackgroundWorkers; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Caching.StackExchangeRedis; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement.EntityFrameworkCore; |
|||
using Volo.Abp.Security.Claims; |
|||
using Volo.Abp.Security.Encryption; |
|||
using Volo.Abp.SettingManagement.EntityFrameworkCore; |
|||
using Volo.Abp.TenantManagement.EntityFrameworkCore; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.MessageService |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpMessageServiceApplicationModule), |
|||
typeof(AbpMessageServiceHttpApiModule), |
|||
typeof(AbpAspNetCoreMultiTenancyModule), |
|||
typeof(AbpMessageServiceEntityFrameworkCoreModule), |
|||
typeof(AbpTenantManagementEntityFrameworkCoreModule), |
|||
typeof(AbpSettingManagementEntityFrameworkCoreModule), |
|||
typeof(AbpPermissionManagementEntityFrameworkCoreModule), |
|||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), |
|||
typeof(AbpHangfireMySqlStorageModule), |
|||
typeof(AbpBackgroundJobsHangfireModule), |
|||
typeof(AbpBackgroundWorkersModule), |
|||
typeof(AbpIMSignalRModule), |
|||
typeof(AbpNotificationsSmsModule), |
|||
typeof(AbpNotificationsSignalRModule), |
|||
typeof(AbpNotificationsWeChatMiniProgramModule), |
|||
typeof(AbpNotificationsExceptionHandlingModule), |
|||
typeof(AbpAspNetCoreSignalRProtocolJsonModule), |
|||
typeof(AbpCAPEventBusModule), |
|||
typeof(AbpDbFinderMultiTenancyModule), |
|||
typeof(AbpCachingStackExchangeRedisModule), |
|||
typeof(AbpAspNetCoreHttpOverridesModule), |
|||
typeof(AbpAutofacModule) |
|||
)] |
|||
public class AbpMessageServiceHttpApiHostModule : AbpModule |
|||
{ |
|||
private const string DefaultCorsPolicyName = "Default"; |
|||
|
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
PreConfigure<CapOptions>(options => |
|||
{ |
|||
options |
|||
.UseMySql(configuration.GetConnectionString("Default")) |
|||
.UseRabbitMQ(rabbitMQOptions => |
|||
{ |
|||
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); |
|||
}) |
|||
.UseDashboard(); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
|||
var configuration = hostingEnvironment.BuildConfiguration(); |
|||
|
|||
// 配置Ef
|
|||
Configure<AbpDbContextOptions>(options => |
|||
{ |
|||
options.UseMySQL(); |
|||
}); |
|||
|
|||
Configure<AbpAspNetCoreAuditingOptions>(options => |
|||
{ |
|||
options.IgnoredUrls.AddIfNotContains("/hangfire"); |
|||
}); |
|||
|
|||
// 中文序列化的编码问题
|
|||
Configure<AbpSystemTextJsonSerializerOptions>(options => |
|||
{ |
|||
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); |
|||
}); |
|||
|
|||
// 加解密
|
|||
Configure<AbpStringEncryptionOptions>(options => |
|||
{ |
|||
var encryptionConfiguration = configuration.GetSection("Encryption"); |
|||
if (encryptionConfiguration.Exists()) |
|||
{ |
|||
options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase; |
|||
options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists() |
|||
? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"]) |
|||
: options.DefaultSalt; |
|||
options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists() |
|||
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"]) |
|||
: options.InitVectorBytes; |
|||
} |
|||
}); |
|||
|
|||
Configure<AbpExceptionHandlingOptions>(options => |
|||
{ |
|||
// 加入需要处理的异常类型
|
|||
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>(); |
|||
options.Handlers.Add<AbpInitializationException>(); |
|||
options.Handlers.Add<ObjectDisposedException>(); |
|||
options.Handlers.Add<StackOverflowException>(); |
|||
options.Handlers.Add<OutOfMemoryException>(); |
|||
options.Handlers.Add<System.Data.Common.DbException>(); |
|||
options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>(); |
|||
options.Handlers.Add<System.Data.DBConcurrencyException>(); |
|||
}); |
|||
|
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpMessageServiceHttpApiHostModule>("LINGYUN.Abp.MessageService"); |
|||
}); |
|||
|
|||
// 多租户
|
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = true; |
|||
}); |
|||
|
|||
var tenantResolveCfg = configuration.GetSection("App:Domains"); |
|||
if (tenantResolveCfg.Exists()) |
|||
{ |
|||
Configure<AbpTenantResolveOptions>(options => |
|||
{ |
|||
var domains = tenantResolveCfg.Get<string[]>(); |
|||
foreach (var domain in domains) |
|||
{ |
|||
options.AddDomainTenantResolver(domain); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
Configure<AbpDistributedCacheOptions>(options => |
|||
{ |
|||
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生
|
|||
options.KeyPrefix = "LINGYUN.Abp.Application"; |
|||
// 滑动过期30天
|
|||
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30); |
|||
// 绝对过期60天
|
|||
options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); |
|||
}); |
|||
|
|||
Configure<RedisCacheOptions>(options => |
|||
{ |
|||
var redisConfig = ConfigurationOptions.Parse(options.Configuration); |
|||
options.ConfigurationOptions = redisConfig; |
|||
options.InstanceName = configuration["Redis:InstanceName"]; |
|||
}); |
|||
|
|||
// Swagger
|
|||
context.Services.AddSwaggerGen( |
|||
options => |
|||
{ |
|||
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MessageService API", Version = "v1" }); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.CustomSchemaIds(type => type.FullName); |
|||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme |
|||
{ |
|||
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", |
|||
Name = "Authorization", |
|||
In = ParameterLocation.Header, |
|||
Scheme = "bearer", |
|||
Type = SecuritySchemeType.Http, |
|||
BearerFormat = "JWT" |
|||
}); |
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
{ |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
{ |
|||
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } |
|||
}, |
|||
new string[] { } |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
context.Services.AddCors(options => |
|||
{ |
|||
options.AddPolicy(DefaultCorsPolicyName, builder => |
|||
{ |
|||
builder |
|||
.WithOrigins( |
|||
configuration["App:CorsOrigins"] |
|||
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToArray() |
|||
) |
|||
.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", "简体中文")); |
|||
|
|||
options.Resources |
|||
.Get<MessageServiceResource>() |
|||
.AddVirtualJson("/Localization/HttpApiHost"); |
|||
}); |
|||
|
|||
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |
|||
.AddJwtBearer(options => |
|||
{ |
|||
options.Authority = configuration["AuthServer:Authority"]; |
|||
options.RequireHttpsMetadata = false; |
|||
options.Audience = configuration["AuthServer:ApiName"]; |
|||
}); |
|||
|
|||
if (!hostingEnvironment.IsDevelopment()) |
|||
{ |
|||
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); |
|||
context.Services |
|||
.AddDataProtection() |
|||
.PersistKeysToStackExchangeRedis(redis, "MessageService-Protection-Keys"); |
|||
} |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
// http调用链
|
|||
app.UseCorrelationId(); |
|||
// 虚拟文件系统
|
|||
app.UseStaticFiles(); |
|||
// 本地化
|
|||
app.UseAbpRequestLocalization(); |
|||
//路由
|
|||
app.UseRouting(); |
|||
// 跨域
|
|||
app.UseCors(DefaultCorsPolicyName); |
|||
// 加入自定义中间件
|
|||
app.UseSignalRJwtToken(); |
|||
// TODO: 还有没有其他方法在iframe中传递身份令牌?
|
|||
app.UseHangfireAuthorication(); |
|||
// 认证
|
|||
app.UseAuthentication(); |
|||
// jwt
|
|||
app.UseJwtTokenMiddleware(); |
|||
// 授权
|
|||
app.UseAuthorization(); |
|||
// 多租户
|
|||
app.UseMultiTenancy(); |
|||
// Swagger
|
|||
app.UseSwagger(); |
|||
// Swagger可视化界面
|
|||
app.UseSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API"); |
|||
}); |
|||
// 审计日志
|
|||
app.UseAuditing(); |
|||
app.UseHangfireServer(); |
|||
app.UseHangfireDashboard(); |
|||
// 路由
|
|||
app.UseConfiguredEndpoints(); |
|||
} |
|||
} |
|||
} |
|||
using DotNetCore.CAP; |
|||
using Hangfire; |
|||
using LINGYUN.Abp.AspNetCore.HttpOverrides; |
|||
using LINGYUN.Abp.AspNetCore.SignalR.Protocol.Json; |
|||
using LINGYUN.Abp.BackgroundJobs.Hangfire; |
|||
using LINGYUN.Abp.EventBus.CAP; |
|||
using LINGYUN.Abp.ExceptionHandling; |
|||
using LINGYUN.Abp.ExceptionHandling.Notifications; |
|||
using LINGYUN.Abp.Hangfire.Storage.MySql; |
|||
using LINGYUN.Abp.Identity.WeChat; |
|||
using LINGYUN.Abp.IM.SignalR; |
|||
using LINGYUN.Abp.MessageService.EntityFrameworkCore; |
|||
using LINGYUN.Abp.MessageService.Localization; |
|||
using LINGYUN.Abp.MultiTenancy.DbFinder; |
|||
using LINGYUN.Abp.Notifications.SignalR; |
|||
using LINGYUN.Abp.Notifications.Sms; |
|||
using LINGYUN.Abp.Notifications.WeChat.MiniProgram; |
|||
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|||
using Microsoft.AspNetCore.Builder; |
|||
using Microsoft.AspNetCore.Cors; |
|||
using Microsoft.AspNetCore.DataProtection; |
|||
using Microsoft.AspNetCore.Hosting; |
|||
using Microsoft.Extensions.Caching.StackExchangeRedis; |
|||
using Microsoft.Extensions.Configuration; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Hosting; |
|||
using Microsoft.OpenApi.Models; |
|||
using StackExchange.Redis; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Text.Encodings.Web; |
|||
using System.Text.Unicode; |
|||
using Volo.Abp; |
|||
using Volo.Abp.AspNetCore.Auditing; |
|||
using Volo.Abp.AspNetCore.Authentication.JwtBearer; |
|||
using Volo.Abp.AspNetCore.MultiTenancy; |
|||
using Volo.Abp.AspNetCore.Security.Claims; |
|||
using Volo.Abp.AspNetCore.Uow; |
|||
using Volo.Abp.Autofac; |
|||
using Volo.Abp.BackgroundWorkers; |
|||
using Volo.Abp.Caching; |
|||
using Volo.Abp.Caching.StackExchangeRedis; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Identity.EntityFrameworkCore; |
|||
using Volo.Abp.Json; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.PermissionManagement.EntityFrameworkCore; |
|||
using Volo.Abp.Security.Claims; |
|||
using Volo.Abp.Security.Encryption; |
|||
using Volo.Abp.SettingManagement.EntityFrameworkCore; |
|||
using Volo.Abp.TenantManagement.EntityFrameworkCore; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.MessageService |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpMessageServiceApplicationModule), |
|||
typeof(AbpMessageServiceHttpApiModule), |
|||
typeof(AbpAspNetCoreMultiTenancyModule), |
|||
typeof(AbpIdentityWeChatModule), |
|||
typeof(AbpMessageServiceEntityFrameworkCoreModule), |
|||
typeof(AbpIdentityEntityFrameworkCoreModule), |
|||
typeof(AbpTenantManagementEntityFrameworkCoreModule), |
|||
typeof(AbpSettingManagementEntityFrameworkCoreModule), |
|||
typeof(AbpPermissionManagementEntityFrameworkCoreModule), |
|||
typeof(AbpAspNetCoreAuthenticationJwtBearerModule), |
|||
typeof(AbpHangfireMySqlStorageModule), |
|||
typeof(AbpBackgroundJobsHangfireModule), |
|||
typeof(AbpBackgroundWorkersModule), |
|||
typeof(AbpIMSignalRModule), |
|||
typeof(AbpNotificationsSmsModule), |
|||
typeof(AbpNotificationsSignalRModule), |
|||
typeof(AbpNotificationsWeChatMiniProgramModule), |
|||
typeof(AbpNotificationsExceptionHandlingModule), |
|||
typeof(AbpAspNetCoreSignalRProtocolJsonModule), |
|||
typeof(AbpCAPEventBusModule), |
|||
typeof(AbpDbFinderMultiTenancyModule), |
|||
typeof(AbpCachingStackExchangeRedisModule), |
|||
typeof(AbpAspNetCoreHttpOverridesModule), |
|||
typeof(AbpAutofacModule) |
|||
)] |
|||
public class AbpMessageServiceHttpApiHostModule : AbpModule |
|||
{ |
|||
private const string DefaultCorsPolicyName = "Default"; |
|||
|
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var configuration = context.Services.GetConfiguration(); |
|||
|
|||
PreConfigure<CapOptions>(options => |
|||
{ |
|||
options |
|||
.UseMySql(configuration.GetConnectionString("Default")) |
|||
.UseRabbitMQ(rabbitMQOptions => |
|||
{ |
|||
configuration.GetSection("CAP:RabbitMQ").Bind(rabbitMQOptions); |
|||
}) |
|||
.UseDashboard(); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
var hostingEnvironment = context.Services.GetHostingEnvironment(); |
|||
var configuration = hostingEnvironment.BuildConfiguration(); |
|||
|
|||
// 配置Ef
|
|||
Configure<AbpDbContextOptions>(options => |
|||
{ |
|||
options.UseMySQL(); |
|||
}); |
|||
|
|||
Configure<AbpAspNetCoreAuditingOptions>(options => |
|||
{ |
|||
options.IgnoredUrls.AddIfNotContains("/hangfire"); |
|||
}); |
|||
|
|||
// 中文序列化的编码问题
|
|||
Configure<AbpSystemTextJsonSerializerOptions>(options => |
|||
{ |
|||
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); |
|||
}); |
|||
|
|||
// 加解密
|
|||
Configure<AbpStringEncryptionOptions>(options => |
|||
{ |
|||
var encryptionConfiguration = configuration.GetSection("Encryption"); |
|||
if (encryptionConfiguration.Exists()) |
|||
{ |
|||
options.DefaultPassPhrase = encryptionConfiguration["PassPhrase"] ?? options.DefaultPassPhrase; |
|||
options.DefaultSalt = encryptionConfiguration.GetSection("Salt").Exists() |
|||
? Encoding.ASCII.GetBytes(encryptionConfiguration["Salt"]) |
|||
: options.DefaultSalt; |
|||
options.InitVectorBytes = encryptionConfiguration.GetSection("InitVector").Exists() |
|||
? Encoding.ASCII.GetBytes(encryptionConfiguration["InitVector"]) |
|||
: options.InitVectorBytes; |
|||
} |
|||
}); |
|||
|
|||
Configure<AbpExceptionHandlingOptions>(options => |
|||
{ |
|||
// 加入需要处理的异常类型
|
|||
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>(); |
|||
options.Handlers.Add<AbpInitializationException>(); |
|||
options.Handlers.Add<ObjectDisposedException>(); |
|||
options.Handlers.Add<StackOverflowException>(); |
|||
options.Handlers.Add<OutOfMemoryException>(); |
|||
options.Handlers.Add<System.Data.Common.DbException>(); |
|||
options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>(); |
|||
options.Handlers.Add<System.Data.DBConcurrencyException>(); |
|||
}); |
|||
|
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpMessageServiceHttpApiHostModule>("LINGYUN.Abp.MessageService"); |
|||
}); |
|||
|
|||
// 多租户
|
|||
Configure<AbpMultiTenancyOptions>(options => |
|||
{ |
|||
options.IsEnabled = true; |
|||
}); |
|||
|
|||
var tenantResolveCfg = configuration.GetSection("App:Domains"); |
|||
if (tenantResolveCfg.Exists()) |
|||
{ |
|||
Configure<AbpTenantResolveOptions>(options => |
|||
{ |
|||
var domains = tenantResolveCfg.Get<string[]>(); |
|||
foreach (var domain in domains) |
|||
{ |
|||
options.AddDomainTenantResolver(domain); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
Configure<AbpDistributedCacheOptions>(options => |
|||
{ |
|||
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生
|
|||
options.KeyPrefix = "LINGYUN.Abp.Application"; |
|||
// 滑动过期30天
|
|||
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30); |
|||
// 绝对过期60天
|
|||
options.GlobalCacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60); |
|||
}); |
|||
|
|||
Configure<RedisCacheOptions>(options => |
|||
{ |
|||
var redisConfig = ConfigurationOptions.Parse(options.Configuration); |
|||
options.ConfigurationOptions = redisConfig; |
|||
options.InstanceName = configuration["Redis:InstanceName"]; |
|||
}); |
|||
|
|||
// Swagger
|
|||
context.Services.AddSwaggerGen( |
|||
options => |
|||
{ |
|||
options.SwaggerDoc("v1", new OpenApiInfo { Title = "MessageService API", Version = "v1" }); |
|||
options.DocInclusionPredicate((docName, description) => true); |
|||
options.CustomSchemaIds(type => type.FullName); |
|||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme |
|||
{ |
|||
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"", |
|||
Name = "Authorization", |
|||
In = ParameterLocation.Header, |
|||
Scheme = "bearer", |
|||
Type = SecuritySchemeType.Http, |
|||
BearerFormat = "JWT" |
|||
}); |
|||
options.AddSecurityRequirement(new OpenApiSecurityRequirement |
|||
{ |
|||
{ |
|||
new OpenApiSecurityScheme |
|||
{ |
|||
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } |
|||
}, |
|||
new string[] { } |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
context.Services.AddCors(options => |
|||
{ |
|||
options.AddPolicy(DefaultCorsPolicyName, builder => |
|||
{ |
|||
builder |
|||
.WithOrigins( |
|||
configuration["App:CorsOrigins"] |
|||
.Split(",", StringSplitOptions.RemoveEmptyEntries) |
|||
.Select(o => o.RemovePostFix("/")) |
|||
.ToArray() |
|||
) |
|||
.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", "简体中文")); |
|||
|
|||
options.Resources |
|||
.Get<MessageServiceResource>() |
|||
.AddVirtualJson("/Localization/HttpApiHost"); |
|||
}); |
|||
|
|||
context.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |
|||
.AddJwtBearer(options => |
|||
{ |
|||
options.Authority = configuration["AuthServer:Authority"]; |
|||
options.RequireHttpsMetadata = false; |
|||
options.Audience = configuration["AuthServer:ApiName"]; |
|||
}); |
|||
|
|||
if (!hostingEnvironment.IsDevelopment()) |
|||
{ |
|||
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]); |
|||
context.Services |
|||
.AddDataProtection() |
|||
.PersistKeysToStackExchangeRedis(redis, "MessageService-Protection-Keys"); |
|||
} |
|||
} |
|||
|
|||
public override void OnApplicationInitialization(ApplicationInitializationContext context) |
|||
{ |
|||
var app = context.GetApplicationBuilder(); |
|||
// http调用链
|
|||
app.UseCorrelationId(); |
|||
// 虚拟文件系统
|
|||
app.UseStaticFiles(); |
|||
// 本地化
|
|||
app.UseAbpRequestLocalization(); |
|||
//路由
|
|||
app.UseRouting(); |
|||
// 跨域
|
|||
app.UseCors(DefaultCorsPolicyName); |
|||
// 加入自定义中间件
|
|||
app.UseSignalRJwtToken(); |
|||
// TODO: 还有没有其他方法在iframe中传递身份令牌?
|
|||
app.UseHangfireAuthorication(); |
|||
// 认证
|
|||
app.UseAuthentication(); |
|||
// jwt
|
|||
app.UseJwtTokenMiddleware(); |
|||
// 授权
|
|||
app.UseAuthorization(); |
|||
// 多租户
|
|||
app.UseMultiTenancy(); |
|||
// Swagger
|
|||
app.UseSwagger(); |
|||
// Swagger可视化界面
|
|||
app.UseSwaggerUI(options => |
|||
{ |
|||
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support MessageService API"); |
|||
}); |
|||
// 审计日志
|
|||
app.UseAuditing(); |
|||
app.UseHangfireServer(); |
|||
app.UseHangfireDashboard(); |
|||
// 路由
|
|||
app.UseConfiguredEndpoints(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue