diff --git a/src/admin/api/Admin.Application/Admin.Application.csproj b/src/admin/api/Admin.Application/Admin.Application.csproj index e54f562568e824f586ecd770e2d37302d19974e4..d25f15eec83f491a3e1c291beeadccf215951a7a 100644 --- a/src/admin/api/Admin.Application/Admin.Application.csproj +++ b/src/admin/api/Admin.Application/Admin.Application.csproj @@ -25,6 +25,7 @@ + diff --git a/src/admin/api/Admin.Application/Configuration/WeChat/Dto/WeChatSettingEditDto.cs b/src/admin/api/Admin.Application/Configuration/WeChat/Dto/WeChatSettingEditDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..6f86f04e4fdb0d974b22a777e44c2ff4e92a7c7b --- /dev/null +++ b/src/admin/api/Admin.Application/Configuration/WeChat/Dto/WeChatSettingEditDto.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.ComponentModel.DataAnnotations; +namespace Magicodes.Admin.Configuration.WeChat.Dto +{ + public class WeChatSettingEditDto + { + [Required] + public bool IsEnabled { get; set; } + [Required] + public string AppId { get; set; } + [Required] + public string AppSecret { get; set; } + [Required] + public string WeiXinAccount { get; set; } + [Required] + public string Token { get; set; } + } +} diff --git a/src/admin/api/Admin.Application/Configuration/WeChat/IWeChatSettingAppService.cs b/src/admin/api/Admin.Application/Configuration/WeChat/IWeChatSettingAppService.cs new file mode 100644 index 0000000000000000000000000000000000000000..1ac61d063d831d16c84497fbb53c44d05f965c2d --- /dev/null +++ b/src/admin/api/Admin.Application/Configuration/WeChat/IWeChatSettingAppService.cs @@ -0,0 +1,14 @@ +using Magicodes.Admin.Configuration.WeChat.Dto; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Magicodes.Admin.Configuration.WeChat +{ + public interface IWeChatSettingAppService + { + Task GetAllSettings(); + Task UpdateAllSettings(WeChatSettingEditDto input); + } +} diff --git a/src/admin/api/Admin.Application/Configuration/WeChat/WeChatSettingAppService.cs b/src/admin/api/Admin.Application/Configuration/WeChat/WeChatSettingAppService.cs new file mode 100644 index 0000000000000000000000000000000000000000..1555d357f6c424b4913594b4281d192e9621d912 --- /dev/null +++ b/src/admin/api/Admin.Application/Configuration/WeChat/WeChatSettingAppService.cs @@ -0,0 +1,67 @@ +using Abp.Application.Services; +using Abp.Authorization; +using Abp.Configuration; +using Magicodes.Admin.Authorization; +using Magicodes.Admin.Configuration.WeChat.Dto; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Abp.Dependency; +using Abp.Extensions; +using Magicodes.WeChat.Startup; +using Newtonsoft.Json; + +namespace Magicodes.Admin.Configuration.WeChat +{ + [AbpAuthorize(AppPermissions.Pages_Administration_WeChat_Settings)] + public class WeChatSettingAppService : ApplicationService, IWeChatSettingAppService + { + private readonly IAppConfigurationAccessor _appConfigurationAccessor; + private readonly IIocManager _iocManager; + + public WeChatSettingAppService(ISettingDefinitionManager settingDefinitionManager + ,IAppConfigurationAccessor appConfigurationAccessor + , IIocManager iocManager) : base() + { + _appConfigurationAccessor = appConfigurationAccessor; + _iocManager = iocManager; + } + + public async Task GetAllSettings() => new WeChatSettingEditDto() + { + IsEnabled = Convert.ToBoolean(await SettingManager.GetSettingValueAsync(AppSettings.WeChatManagement.IsEnabled)), + AppId = await SettingManager.GetSettingValueAsync(AppSettings.WeChatManagement.AppId), + AppSecret = await SettingManager.GetSettingValueAsync(AppSettings.WeChatManagement.AppSecret), + WeiXinAccount = await SettingManager.GetSettingValueAsync(AppSettings.WeChatManagement.WeiXinAccount), + Token = await SettingManager.GetSettingValueAsync(AppSettings.WeChatManagement.Token) + }; + + public async Task UpdateAllSettings(WeChatSettingEditDto input) + { + await SaveSettings(AppSettings.WeChatManagement.IsEnabled, input.IsEnabled.ToString()); + await SaveSettings(AppSettings.WeChatManagement.AppId, input.AppId); + await SaveSettings(AppSettings.WeChatManagement.AppSecret, input.AppSecret); + await SaveSettings(AppSettings.WeChatManagement.WeiXinAccount, input.WeiXinAccount); + await SaveSettings(AppSettings.WeChatManagement.Token, input.Token); + } + + /// + /// 保存设置 + /// + /// 设置键 + /// 值 + /// + private async Task SaveSettings(string key, string value) + { + if (AbpSession.TenantId.HasValue) + { + await SettingManager.ChangeSettingForTenantAsync(AbpSession.TenantId.Value, key, value); + } + else + { + await SettingManager.ChangeSettingForApplicationAsync(key, value); + } + } + } +} diff --git a/src/admin/api/Admin.Host/Startup/AdminWebHostModule.cs b/src/admin/api/Admin.Host/Startup/AdminWebHostModule.cs index c66720f16cd5a46995bde296fc6e9bd99f02bb84..42c6f3bfd8f84dc05c551029a6ef87807cddd466 100644 --- a/src/admin/api/Admin.Host/Startup/AdminWebHostModule.cs +++ b/src/admin/api/Admin.Host/Startup/AdminWebHostModule.cs @@ -27,6 +27,7 @@ using Magicodes.Unity; using Magicodes.Sms; using Magicodes.WeChat.SDK; using Magicodes.WeChat.SDK.Builder; +using Magicodes.WeChat; namespace Magicodes.Admin.Web.Startup { @@ -35,7 +36,8 @@ namespace Magicodes.Admin.Web.Startup typeof(SmsModule), typeof(AdminWebCoreModule), typeof(AdminAppModule), - typeof(UnityModule) + typeof(UnityModule), + typeof(WeChatModule) )] public class AdminWebHostModule : AbpModule { @@ -95,32 +97,11 @@ namespace Magicodes.Admin.Web.Startup ConfigureExternalAuthProviders(); - ConfigureWeChatSdk(); - - IocManager.RegisterIfNot(); //初始化聊天状态监视 IocManager.Resolve().Initialize(); } - private void ConfigureWeChatSdk() - { - WeChatSDKBuilder.Create() - .WithLoggerAction((tag, message) => { Console.WriteLine(string.Format("Tag:{0}\tMessage:{1}", tag, message)); }) - .Register(WeChatFrameworkFuncTypes.GetKey, model => _appConfiguration["Authentication:WeChat:AppId"]) - .Register(WeChatFrameworkFuncTypes.Config_GetWeChatConfigByKey, - model => - { - var arg = model as WeChatApiCallbackFuncArgInfo; - return new WeChatConfig - { - AppId = _appConfiguration["Authentication:WeChat:AppId"], - AppSecret = _appConfiguration["Authentication:WeChat:AppSecret"] - }; - }) - .Build(); - } - private void ConfigureExternalAuthProviders() { var externalAuthConfiguration = IocManager.Resolve(); diff --git a/src/admin/api/Admin.Host/appsettings.json b/src/admin/api/Admin.Host/appsettings.json index d46615167f901cf4a05980b9b16ada3978d44e0c..e1c164910b8819ad9cdede4b3270c33c687bcf75 100644 --- a/src/admin/api/Admin.Host/appsettings.json +++ b/src/admin/api/Admin.Host/appsettings.json @@ -70,8 +70,10 @@ "Authentication": { "WeChat": { "IsEnabled": "false", - "AppId": "", - "AppSecret": "" + "AppId": "wx24b12a65356ef5ed", + "AppSecret": "4b26c9f5d0766b203ebe393924cb8280", + "WeiXinAccount": "", + "Token": "" }, "Facebook": { "IsEnabled": "false", diff --git a/src/admin/api/Admin.Host/wwwroot/Localization/Admin/Admin-zh-CN.xml b/src/admin/api/Admin.Host/wwwroot/Localization/Admin/Admin-zh-CN.xml index 90d9a3f3c8935377816429aa685fecec38406134..8bd12f7c88876d502404e34b32308df6f154e75e 100644 --- a/src/admin/api/Admin.Host/wwwroot/Localization/Admin/Admin-zh-CN.xml +++ b/src/admin/api/Admin.Host/wwwroot/Localization/Admin/Admin-zh-CN.xml @@ -897,5 +897,8 @@ + + + diff --git a/src/admin/ui/src/app/admin/admin-routing.module.ts b/src/admin/ui/src/app/admin/admin-routing.module.ts index fe0ccadc45b02d611098fd0b81dcacdc0d2c2aff..527d8e5bc96f8ebfcb3ff37c46e22f3f7af69297 100644 --- a/src/admin/ui/src/app/admin/admin-routing.module.ts +++ b/src/admin/ui/src/app/admin/admin-routing.module.ts @@ -25,6 +25,8 @@ import { ColumnInfosComponent } from './columnInfos/columnInfo.component'; import { StorageSettingsComponent } from './settings/storage-settings.component'; import { TransactionLogsComponent } from './transactionLogs/transactionLog.component'; import { MiniProgramSettingsComponent } from './settings/miniProgram-settings.component'; +import { WeChatSettingsComponent } from './settings/weChat-settings.component'; + @NgModule({ imports: [ RouterModule.forChild([ @@ -55,7 +57,9 @@ import { MiniProgramSettingsComponent } from './settings/miniProgram-settings.co { path: 'columnInfo', component: ColumnInfosComponent }, { path: 'storageSettings', component: StorageSettingsComponent }, { path: 'miniProgramSettings', component:MiniProgramSettingsComponent}, - { path: 'transactionLog', component: TransactionLogsComponent } + { path: 'transactionLog', component: TransactionLogsComponent }, + { path: 'weChatSettings', component: WeChatSettingsComponent } + ] } ]) diff --git a/src/admin/ui/src/app/admin/admin.module.ts b/src/admin/ui/src/app/admin/admin.module.ts index 39eb3ff2398b6f3491067ec5be4b9181f745c5b0..8769b122cec9aeb0e0ff4d2172db936385e65a1e 100644 --- a/src/admin/ui/src/app/admin/admin.module.ts +++ b/src/admin/ui/src/app/admin/admin.module.ts @@ -104,6 +104,7 @@ import { ColumnInfosComponent } from './columnInfos/columnInfo.component'; import { CreateOrEditColumnInfoModalComponent } from './columnInfos/create-or-edit-columnInfo-modal.component'; import { StorageSettingsComponent } from './settings/storage-settings.component'; import { MiniProgramSettingsComponent } from './settings/miniProgram-settings.component'; +import { WeChatSettingsComponent } from './settings/weChat-settings.component' import { TransactionLogsComponent } from './transactionLogs/transactionLog.component'; import { CreateOrEditTransactionLogModalComponent } from './transactionLogs/create-or-edit-transactionLog-modal.component'; import { ColumnInfoTreeSelectComponent } from './appComponents/columnInfoTreeSelect/columnInfo-tree-select.component'; @@ -170,6 +171,7 @@ NgxBootstrapDatePickerConfigService.registerNgxBootstrapDatePickerLocales(); SmsCodeSettingsComponent, StorageSettingsComponent, MiniProgramSettingsComponent, + WeChatSettingsComponent, InstallComponent, MaintenanceComponent, EditionsComponent, diff --git a/src/admin/ui/src/app/admin/articleInfos/articleInfo.component.ts b/src/admin/ui/src/app/admin/articleInfos/articleInfo.component.ts index f1c7e03ea088d9d3e16f0e4ba237caed620e21de..61ae22bd3e1a61b99b9c470aff6ecb29d9dd58da 100644 --- a/src/admin/ui/src/app/admin/articleInfos/articleInfo.component.ts +++ b/src/admin/ui/src/app/admin/articleInfos/articleInfo.component.ts @@ -5,21 +5,41 @@ ViewChild, ViewEncapsulation } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { appModuleAnimation } from '@shared/animations/routerTransition'; -import { AppComponentBase } from '@shared/common/app-component-base'; -import { SwitchEntityInputDtoOfInt64 } from '@shared/service-proxies/service-proxies'; +import { + ActivatedRoute +} from '@angular/router'; +import { + appModuleAnimation +} from '@shared/animations/routerTransition'; +import { + AppComponentBase +} from '@shared/common/app-component-base'; +import { + SwitchEntityInputDtoOfInt64 +} from '@shared/service-proxies/service-proxies'; import * as moment from 'moment'; -import { LazyLoadEvent } from 'primeng/components/common/lazyloadevent'; -import { Paginator } from 'primeng/components/paginator/paginator'; -import { Table } from 'primeng/components/table/table'; -import { FileDownloadService } from '@shared/utils/file-download.service'; +import { + LazyLoadEvent +} from 'primeng/components/common/lazyloadevent'; +import { + Paginator +} from 'primeng/components/paginator/paginator'; +import { + Table +} from 'primeng/components/table/table'; +import { + FileDownloadService +} from '@shared/utils/file-download.service'; import { ArticleInfoServiceProxy, GetDataComboItemDtoOfInt64 } from '@shared/service-proxies/service-proxies'; -import { CreateOrEditArticleInfoModalComponent } from './create-or-edit-articleInfo-modal.component'; -import { ArticleInfoArticleTagInfoComponent } from './articleTagInfo.component'; +import { + CreateOrEditArticleInfoModalComponent +} from './create-or-edit-articleInfo-modal.component'; +import { + ArticleInfoArticleTagInfoComponent +} from './articleTagInfo.component'; @Component({ templateUrl: './articleInfo.component.html', diff --git a/src/admin/ui/src/app/admin/settings/weChat-settings.component.html b/src/admin/ui/src/app/admin/settings/weChat-settings.component.html new file mode 100644 index 0000000000000000000000000000000000000000..cdcbecfc012f23572317912484083bcd9f2369e7 --- /dev/null +++ b/src/admin/ui/src/app/admin/settings/weChat-settings.component.html @@ -0,0 +1,51 @@ + + + + + + {{l("WeChatSettings")}} + + + {{l("SettingsHeaderInfo")}} + + + + {{l("SaveAll")}} + + + + + + + + + + + + + {{l("IsEnabled")}}({{l("WeChatSetting")}}) + + + + + {{l("AppId")}} + + + + {{l("Secret")}} + + + + {{l("ToKen")}} + + + + {{l("Account")}} + + + + + + + + diff --git a/src/admin/ui/src/app/admin/settings/weChat-settings.component.ts b/src/admin/ui/src/app/admin/settings/weChat-settings.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..8bc0c2384c4f4078c8fc5d49c7cac3a26de57084 --- /dev/null +++ b/src/admin/ui/src/app/admin/settings/weChat-settings.component.ts @@ -0,0 +1,36 @@ +import { AfterViewChecked, Component, Injector, OnInit } from '@angular/core'; +import { appModuleAnimation } from '@shared/animations/routerTransition'; +import { AppComponentBase } from '@shared/common/app-component-base'; +import { WeChatSettingServiceProxy, WeChatSettingEditDto } from '@shared/service-proxies/service-proxies'; + +@Component({ + templateUrl: './weChat-settings.component.html', + animations: [appModuleAnimation()] +}) +export class WeChatSettingsComponent extends AppComponentBase implements AfterViewChecked { + weChatSettings: WeChatSettingEditDto; + constructor( + injector: Injector, + private _weChatSettingService: WeChatSettingServiceProxy + ) { + super(injector); + } + + ngOnInit(): void { + this._weChatSettingService.getAllSettings() + .subscribe(setting => { + this.weChatSettings = setting; + }); + } + + ngAfterViewChecked(): void { + // $('tabset ul.nav').addClass('m-tabs-line'); + // $('tabset ul.nav li a.nav-link').addClass('m-tabs__link'); + } + + saveAll(): void { + this._weChatSettingService.updateAllSettings(this.weChatSettings).subscribe(result => { + this.notify.info(this.l('SavedSuccessfully')); + }); + } +} diff --git a/src/admin/ui/src/app/shared/layout/nav/app-navigation.service.ts b/src/admin/ui/src/app/shared/layout/nav/app-navigation.service.ts index dcf541e805c8a2050d3fe87f0c296d2263574523..3ee6f896e0e8b95c845a1a9a8cdfc4ad90c8b986 100644 --- a/src/admin/ui/src/app/shared/layout/nav/app-navigation.service.ts +++ b/src/admin/ui/src/app/shared/layout/nav/app-navigation.service.ts @@ -36,7 +36,8 @@ export class AppNavigationService { new AppMenuItem('PaySettings', 'Pages.Administration.Pay.Settings', 'fa fa-cny', '/app/admin/paySettings'), new AppMenuItem('SmsCodeSettings', 'Pages.Administration.SmsCode.Settings', 'fa fa-comments', '/app/admin/smsCodeSettings'), new AppMenuItem('StorageSettings', 'Pages.Administration.Storage.Settings', 'fa fa-database', '/app/admin/storageSettings'), - new AppMenuItem('MiniProgramSetting', 'Pages.Administration.MiniProgram.Settings', 'fa fa-eraser', '/app/admin/miniProgramSettings') + new AppMenuItem('MiniProgramSetting', 'Pages.Administration.MiniProgram.Settings', 'fa fa-eraser', '/app/admin/miniProgramSettings'), + new AppMenuItem('WeChatSettings', 'Pages.Administration.WeChat.Settings', 'fa fa-comments', '/app/admin/weChatSettings') ]), // new AppMenuItem('DemoUiComponents', 'Pages.DemoUiComponents', 'flaticon-shapes', '/app/admin/demo-ui-components'), new AppMenuItem('TransactionLog', 'Pages.TransactionLog', 'flaticon-shapes', '/app/admin/transactionLog'), diff --git a/src/admin/ui/src/shared/service-proxies/service-proxies.ts b/src/admin/ui/src/shared/service-proxies/service-proxies.ts index f0694a2277e62fe8773988e05080cc912760d65c..a3caa1cbbc9dab8c5b68c0a5d26abe74f47cf11b 100644 --- a/src/admin/ui/src/shared/service-proxies/service-proxies.ts +++ b/src/admin/ui/src/shared/service-proxies/service-proxies.ts @@ -12458,6 +12458,122 @@ export class WebLogServiceProxy { } } +@Injectable() +export class WeChatSettingServiceProxy { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ? baseUrl : ""; + } + + /** + * @return Success + */ + getAllSettings(): Observable { + let url_ = this.baseUrl + "/api/services/app/WeChatSetting/GetAllSettings"; + url_ = url_.replace(/[?&]$/, ""); + + let options_ : any = { + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("get", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processGetAllSettings(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processGetAllSettings(response_); + } catch (e) { + return >_observableThrow(e); + } + } else + return >_observableThrow(response_); + })); + } + + protected processGetAllSettings(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response).error instanceof Blob ? (response).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }}; + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 ? WeChatSettingEditDto.fromJS(resultData200) : new WeChatSettingEditDto(); + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null); + } + + /** + * @param input (optional) + * @return Success + */ + updateAllSettings(input: WeChatSettingEditDto | null | undefined): Observable { + let url_ = this.baseUrl + "/api/services/app/WeChatSetting/UpdateAllSettings"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(input); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + }) + }; + + return this.http.request("put", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processUpdateAllSettings(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processUpdateAllSettings(response_); + } catch (e) { + return >_observableThrow(e); + } + } else + return >_observableThrow(response_); + })); + } + + protected processUpdateAllSettings(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response).error instanceof Blob ? (response).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }}; + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => { + return _observableOf(null); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null); + } +} + export class IsTenantAvailableInput implements IIsTenantAvailableInput { tenancyName!: string; @@ -25451,6 +25567,58 @@ export interface IGetLatestWebLogsOutput { latestWebLogLines: string[] | undefined; } +export class WeChatSettingEditDto implements IWeChatSettingEditDto { + isEnabled!: boolean; + appId!: string; + appSecret!: string; + weiXinAccount!: string; + token!: string; + + constructor(data?: IWeChatSettingEditDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(data?: any) { + if (data) { + this.isEnabled = data["isEnabled"]; + this.appId = data["appId"]; + this.appSecret = data["appSecret"]; + this.weiXinAccount = data["weiXinAccount"]; + this.token = data["token"]; + } + } + + static fromJS(data: any): WeChatSettingEditDto { + data = typeof data === 'object' ? data : {}; + let result = new WeChatSettingEditDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["isEnabled"] = this.isEnabled; + data["appId"] = this.appId; + data["appSecret"] = this.appSecret; + data["weiXinAccount"] = this.weiXinAccount; + data["token"] = this.token; + return data; + } +} + +export interface IWeChatSettingEditDto { + isEnabled: boolean; + appId: string; + appSecret: string; + weiXinAccount: string; + token: string; +} + export enum IncomeStatisticsDateInterval { _1 = 1, _2 = 2, diff --git a/src/admin/ui/src/shared/service-proxies/service-proxy.module.ts b/src/admin/ui/src/shared/service-proxies/service-proxy.module.ts index dc80a5e7ecd320a7d9ee1c4bec287dd5db538ddf..5e7d9e49261a5f8dc442b1f807f88ce1cf8233e1 100644 --- a/src/admin/ui/src/shared/service-proxies/service-proxy.module.ts +++ b/src/admin/ui/src/shared/service-proxies/service-proxy.module.ts @@ -48,6 +48,7 @@ import * as ApiServiceProxies from './service-proxies'; ApiServiceProxies.PaySettingsServiceProxy, ApiServiceProxies.SmsCodeSettingServiceProxy, ApiServiceProxies.StorageSettingServiceProxy, + ApiServiceProxies.WeChatSettingServiceProxy, { provide: HTTP_INTERCEPTORS, useClass: AbpHttpInterceptor, multi: true } ] }) diff --git a/src/core/Magicodes.Admin.Core/AdminConsts.cs b/src/core/Magicodes.Admin.Core/AdminConsts.cs index 39dc9f2183a31d0d499207ae70fc54bf39a6685e..240e19a86f665ef8d312c139f06d0e7bac5483af 100644 --- a/src/core/Magicodes.Admin.Core/AdminConsts.cs +++ b/src/core/Magicodes.Admin.Core/AdminConsts.cs @@ -15,5 +15,11 @@ public const string AdminMenuName = "AdminMenus"; public const string ApiPrefix = "api/"; + + public const string WeChatTemplateAPIBaseUrl = "https://api.weixin.qq.com/cgi-bin/template/"; + + public const string WeChatAccessTokenRedisKey = "access_token"; + + public const string WeChatAccessTokenJsonKey = "accessToken"; } } \ No newline at end of file diff --git a/src/core/Magicodes.Admin.Core/Authorization/AppAuthorizationProvider.cs b/src/core/Magicodes.Admin.Core/Authorization/AppAuthorizationProvider.cs index 5f9c8f149c638aaab48339a05100b66bccaf9e00..1d2656b47ddedef991be07669f0e4c9f19bbb6dc 100644 --- a/src/core/Magicodes.Admin.Core/Authorization/AppAuthorizationProvider.cs +++ b/src/core/Magicodes.Admin.Core/Authorization/AppAuthorizationProvider.cs @@ -67,6 +67,8 @@ namespace Magicodes.Admin.Authorization administration.CreateChildPermission(AppPermissions.Pages_Administration_MiniProgram_Settings, L("MiniProgramSetting")); + administration.CreateChildPermission(AppPermissions.Pages_Administration_WeChat_Settings, L("WeChatSettings")); + //TENANT-SPECIFIC PERMISSIONS pages.CreateChildPermission(AppPermissions.Pages_Tenant_Dashboard, L("Dashboard"), multiTenancySides: MultiTenancySides.Tenant); diff --git a/src/core/Magicodes.Admin.Core/Authorization/AppPermissions.cs b/src/core/Magicodes.Admin.Core/Authorization/AppPermissions.cs index 8e7d347c453637027096823d488a25282f52fad6..fe3721a3fcff69d68a24f347c9ebcdb398adf42b 100644 --- a/src/core/Magicodes.Admin.Core/Authorization/AppPermissions.cs +++ b/src/core/Magicodes.Admin.Core/Authorization/AppPermissions.cs @@ -47,6 +47,8 @@ public const string Pages_Administration_Storage_Settings = "Pages.Administration.Storage.Settings"; + public const string Pages_Administration_WeChat_Settings = "Pages.Administration.WeChat.Settings"; + //TENANT-SPECIFIC PERMISSIONS public const string Pages_Tenant_Dashboard = "Pages.Tenant.Dashboard"; diff --git a/src/core/Magicodes.Admin.Core/Configuration/AppSettingProvider.cs b/src/core/Magicodes.Admin.Core/Configuration/AppSettingProvider.cs index 59e8a16490d899db850825b29d49ab9a6d91a3fc..efe2294a46205919130ed25f6f7c2034afa8eb07 100644 --- a/src/core/Magicodes.Admin.Core/Configuration/AppSettingProvider.cs +++ b/src/core/Magicodes.Admin.Core/Configuration/AppSettingProvider.cs @@ -22,7 +22,7 @@ namespace Magicodes.Admin.Configuration context.Manager.GetSettingDefinition(AbpZeroSettingNames.UserManagement.TwoFactorLogin.IsEnabled).DefaultValue = false.ToString().ToLowerInvariant(); return GetHostSettings().Union(GetTenantSettings()).Union(GetSharedSettings()).Union(GetPaySettings()) - .Union(GetSmsCodeSettings()).Union(GetStorageCodeSettings()).Union(GetMiniProgramSettings()); + .Union(GetSmsCodeSettings()).Union(GetStorageCodeSettings()).Union(GetMiniProgramSettings()).Union(GetWeChatSettings()); } private IEnumerable GetHostSettings() => new[] { @@ -149,6 +149,7 @@ namespace Magicodes.Admin.Configuration new SettingDefinition(AppSettings.AliStorageManagement.AccessKeyId, GetFromAppSettings(AppSettings.AliStorageManagement.AccessKeyId, ""),scopes: SettingScopes.Tenant|SettingScopes.Application), new SettingDefinition(AppSettings.AliStorageManagement.AccessKeySecret, GetFromAppSettings(AppSettings.AliStorageManagement.AccessKeySecret, ""),scopes: SettingScopes.Tenant|SettingScopes.Application), new SettingDefinition(AppSettings.AliStorageManagement.EndPoint, GetFromAppSettings(AppSettings.AliStorageManagement.EndPoint, ""),scopes: SettingScopes.Tenant|SettingScopes.Application), + new SettingDefinition(AppSettings.AliStorageManagement.BucketName, GetFromAppSettings(AppSettings.AliStorageManagement.BucketName, ""),scopes: SettingScopes.Tenant|SettingScopes.Application), //腾讯 @@ -159,5 +160,13 @@ namespace Magicodes.Admin.Configuration new SettingDefinition(AppSettings.TencentStorageManagement.Region, GetFromAppSettings(AppSettings.TencentStorageManagement.Region, ""),scopes: SettingScopes.Tenant|SettingScopes.Application), new SettingDefinition(AppSettings.TencentStorageManagement.BucketName, GetFromAppSettings(AppSettings.TencentStorageManagement.BucketName, ""),scopes: SettingScopes.Tenant|SettingScopes.Application), }; + + private IEnumerable GetWeChatSettings() => new[] { + new SettingDefinition(AppSettings.WeChatManagement.AppId, GetFromAppSettings(AppSettings.WeChatManagement.AppId,""),scopes:SettingScopes.Tenant|SettingScopes.Application), + new SettingDefinition(AppSettings.WeChatManagement.AppSecret, GetFromAppSettings(AppSettings.WeChatManagement.AppSecret,""),scopes:SettingScopes.Tenant|SettingScopes.Application), + new SettingDefinition(AppSettings.WeChatManagement.IsEnabled, GetFromAppSettings(AppSettings.WeChatManagement.IsEnabled, "false"), scopes:SettingScopes.Tenant| SettingScopes.Application), + new SettingDefinition(AppSettings.WeChatManagement.WeiXinAccount, GetFromAppSettings(AppSettings.WeChatManagement.WeiXinAccount, ""), scopes:SettingScopes.Tenant| SettingScopes.Application), + new SettingDefinition(AppSettings.WeChatManagement.Token, GetFromAppSettings(AppSettings.WeChatManagement.Token, ""), scopes:SettingScopes.Tenant| SettingScopes.Application), + }; } } diff --git a/src/core/Magicodes.Admin.Core/Configuration/AppSettings.cs b/src/core/Magicodes.Admin.Core/Configuration/AppSettings.cs index e2b6109990aab888592c0971ea5d058aa92907ed..0b10d84a3c4ed1be7a8bf2ecae3cfe1f9b0a5aea 100644 --- a/src/core/Magicodes.Admin.Core/Configuration/AppSettings.cs +++ b/src/core/Magicodes.Admin.Core/Configuration/AppSettings.cs @@ -107,6 +107,14 @@ namespace Magicodes.Admin.Configuration public const string PayNotifyUrl = "App.WeChatPayManagement.PayNotifyUrl"; public const string IsActive = "App.WeChatPayManagement.IsActive"; } + public static class WeChatManagement + { + public const string IsEnabled = "App.WeChatManagement.IsEnabled"; + public const string AppId = "App.WeChatManagement.AppId"; + public const string AppSecret = "App.WeChatManagement.AppSecret"; + public const string WeiXinAccount = "App.WeChatManagement.WeiXinAccount"; + public const string Token = "App.WeChatManagement.Token"; + } /// /// Ѷƴ洢 diff --git a/src/unity/Magicodes.WeChat/Magicodes.WeChat.csproj b/src/unity/Magicodes.WeChat/Magicodes.WeChat.csproj index 4d042bfe56ec93ea10b53d62cefd6a6eca0e80cd..a0eb1678cab0fc4e145dedca2b73eb0b99fefe05 100644 --- a/src/unity/Magicodes.WeChat/Magicodes.WeChat.csproj +++ b/src/unity/Magicodes.WeChat/Magicodes.WeChat.csproj @@ -5,6 +5,7 @@ + diff --git a/src/unity/Magicodes.WeChat/Startup/WeChatConfig.cs b/src/unity/Magicodes.WeChat/Startup/WeChatConfig.cs new file mode 100644 index 0000000000000000000000000000000000000000..cbd892c91895c9836641ed5cbe92c7ee3df5e198 --- /dev/null +++ b/src/unity/Magicodes.WeChat/Startup/WeChatConfig.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Magicodes.WeChat.SDK; + +namespace Magicodes.WeChat.Startup +{ + public class WeChatConfig : IWeChatConfig + { + public string AppId { get; set; } + public string AppSecret { get; set; } + public string WeiXinAccount { get; set; } + public string Token { get; set; } + } +} diff --git a/src/unity/Magicodes.WeChat/Startup/WeChatStartup.cs b/src/unity/Magicodes.WeChat/Startup/WeChatStartup.cs new file mode 100644 index 0000000000000000000000000000000000000000..4949dfdf54f71f0f5fcd0565fc23ee0e23233e21 --- /dev/null +++ b/src/unity/Magicodes.WeChat/Startup/WeChatStartup.cs @@ -0,0 +1,98 @@ +using Abp.Configuration; +using Abp.Dependency; +using Abp.Runtime.Caching; +using Abp.Runtime.Session; +using Castle.Core.Logging; +using Magicodes.Admin; +using Magicodes.Admin.Configuration; +using Magicodes.WeChat.SDK; +using Magicodes.WeChat.SDK.Apis.Token; +using Magicodes.WeChat.SDK.Builder; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Runtime.Serialization.Json; +using System.Threading.Tasks; + +namespace Magicodes.WeChat.Startup +{ + public class WeChatStartup + { + /// + /// 配置公众号 + /// + public static async Task ConfigAsync(ILogger logger, IIocManager iocManager, IConfigurationRoot config, ISettingManager settingManager, ICacheManager _cacheManager) + { + //日志函数 + void LogAction(string tag, string message) + { + if (tag.Equals("error", StringComparison.CurrentCultureIgnoreCase)) + { + logger.Error(message); + } + else + { + logger.Debug(message); + } + }; + + //appsettings中获取配置 + var configInfo = new WeChatConfig + { + AppId = config["Authentication:WeChat:AppId"], + AppSecret = config["Authentication:WeChat:AppSecret"], + WeiXinAccount = config["Authentication:WeChat:WeiXinAccount"], + Token = config["ToKen"] + }; + //如果启用了配置管理则从数据库中得到配置 + if (Convert.ToBoolean(settingManager.GetSettingValue(AppSettings.WeChatManagement.IsEnabled))) + { + configInfo.AppId = settingManager.GetSettingValue(AppSettings.WeChatManagement.AppId); + configInfo.AppSecret = settingManager.GetSettingValue(AppSettings.WeChatManagement.AppSecret); + configInfo.WeiXinAccount = settingManager.GetSettingValue(AppSettings.WeChatManagement.WeiXinAccount); + configInfo.Token = settingManager.GetSettingValue(AppSettings.WeChatManagement.Token); + } + + WeChatSDKBuilder.Create() + .WithLoggerAction(LogAction) + .Register(WeChatFrameworkFuncTypes.GetKey, + model => + { + //使用租户id作为key,来确保不同租户加载不同的公众号配置 + var key = iocManager.Resolve()?.TenantId; + if (key == null) return "0"; + + return key.ToString(); + }) + .Register(WeChatFrameworkFuncTypes.Config_GetWeChatConfigByKey, model => configInfo) + .Register(WeChatFrameworkFuncTypes.APIFunc_GetAccessToken, + model => { + //1)通过配置拿到key + //用租户id创建redis的key + var key = $"{AdminConsts.WeChatAccessTokenRedisKey}{iocManager.Resolve()?.TenantId??0}"; + + //2)通过key从缓存获取AccessToken的一个Json + string tokenResultJson = _cacheManager.GetCache(AdminConsts.WeChatAccessTokenJsonKey).GetOrDefault(key)?.ToString(); + + //3)如果获取成功,则直接返回 + if (tokenResultJson == null) + { + //4)如果获取为空,则通过GetByCustomConfig API获取Token + var tokenResult = WeChatApisContext.Current.TokenApi.GetByCustomConfig(configInfo); + + if (!tokenResult.IsSuccess()) + throw new ApiArgumentException("获取接口访问凭据失败:" + tokenResult.GetFriendlyMessage() + "(" + tokenResult.DetailResult + ")"); + + tokenResultJson = JsonConvert.SerializeObject(tokenResult); + + //5)获取成功写入缓存,缓存时间小于Token过期时间 + _cacheManager.GetCache(AdminConsts.WeChatAccessTokenJsonKey).Set(key, tokenResultJson, tokenResult.ExpiresTime - DateTime.Now); + return tokenResult; + } + return JsonConvert.DeserializeObject(tokenResultJson) as TokenApiResult; + }) + .Build(); + } + } +} diff --git a/src/unity/Magicodes.WeChat/WeChatModule.cs b/src/unity/Magicodes.WeChat/WeChatModule.cs index e674df28a6c8f12c9a37ee422d643fb0c28c0b05..0587f9e3dfb305c589806bae5cb655ea46cf24aa 100644 --- a/src/unity/Magicodes.WeChat/WeChatModule.cs +++ b/src/unity/Magicodes.WeChat/WeChatModule.cs @@ -1,8 +1,13 @@ -using Abp.Modules; +using Abp.Configuration; +using Abp.Modules; using Abp.Reflection.Extensions; +using Abp.Runtime.Caching; using Magicodes.Admin; +using Magicodes.Admin.Configuration; using Magicodes.WeChat.SDK; using Magicodes.WeChat.SDK.Builder; +using Magicodes.WeChat.Startup; +using System; namespace Magicodes.WeChat { @@ -21,25 +26,11 @@ namespace Magicodes.WeChat public override void PostInitialize() { - //TODO: 伍潜 - //1)公众号配置:参考支付配置 - //2)AccessToken统一封装,支持分布式架构 - //3)封装模板消息服务,便于消息发送 + var _settingManager = IocManager.Resolve(); + var _appConfiguration = IocManager.Resolve().Configuration; + var _cacheManager = IocManager.Resolve(); - //WeChatSDKBuilder.Create() - // .WithLoggerAction((tag, message) => { Console.WriteLine(string.Format("Tag:{0}\tMessage:{1}", tag, message)); }) - // .Register(WeChatFrameworkFuncTypes.GetKey, model => _appConfiguration["Authentication:WeChat:AppId"]) - // .Register(WeChatFrameworkFuncTypes.Config_GetWeChatConfigByKey, - // model => - // { - // var arg = model as WeChatApiCallbackFuncArgInfo; - // return new WeChatConfig - // { - // AppId = _appConfiguration["Authentication:WeChat:AppId"], - // AppSecret = _appConfiguration["Authentication:WeChat:AppSecret"] - // }; - // }) - // .Build(); + WeChatStartup.ConfigAsync(Logger, IocManager, _appConfiguration, _settingManager, _cacheManager).Wait(); } } }