From 6dec497d675125dbbfb0eab43cec65bb37c64977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=8D=E6=BD=9C?= Date: Thu, 21 Feb 2019 20:35:54 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=BE=AE=E4=BF=A1=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Admin.Application.csproj | 1 + .../WeChat/Dto/WeChatSettingEditDto.cs | 20 +++ .../WeChat/IWeChatSettingAppService.cs | 14 ++ .../WeChat/WeChatSettingAppService.cs | 67 +++++++ .../Admin.Host/Startup/AdminWebHostModule.cs | 25 +-- src/admin/api/Admin.Host/appsettings.json | 6 +- .../Localization/Admin/Admin-zh-CN.xml | 3 + .../ui/src/app/admin/admin-routing.module.ts | 6 +- src/admin/ui/src/app/admin/admin.module.ts | 2 + .../articleInfos/articleInfo.component.ts | 40 +++-- .../settings/weChat-settings.component.html | 51 ++++++ .../settings/weChat-settings.component.ts | 36 ++++ .../layout/nav/app-navigation.service.ts | 3 +- src/admin/ui/src/assets/appconfig.json | 2 +- .../shared/service-proxies/service-proxies.ts | 168 ++++++++++++++++++ .../service-proxies/service-proxy.module.ts | 1 + src/core/Magicodes.Admin.Core/AdminConsts.cs | 6 + .../Authorization/AppAuthorizationProvider.cs | 2 + .../Authorization/AppPermissions.cs | 2 + .../Configuration/AppSettingProvider.cs | 11 +- .../Configuration/AppSettings.cs | 8 + .../Magicodes.WeChat/Magicodes.WeChat.csproj | 1 + .../Magicodes.WeChat/Startup/WeChatConfig.cs | 16 ++ .../Magicodes.WeChat/Startup/WeChatStartup.cs | 98 ++++++++++ src/unity/Magicodes.WeChat/WeChatModule.cs | 29 ++- 25 files changed, 561 insertions(+), 57 deletions(-) create mode 100644 src/admin/api/Admin.Application/Configuration/WeChat/Dto/WeChatSettingEditDto.cs create mode 100644 src/admin/api/Admin.Application/Configuration/WeChat/IWeChatSettingAppService.cs create mode 100644 src/admin/api/Admin.Application/Configuration/WeChat/WeChatSettingAppService.cs create mode 100644 src/admin/ui/src/app/admin/settings/weChat-settings.component.html create mode 100644 src/admin/ui/src/app/admin/settings/weChat-settings.component.ts create mode 100644 src/unity/Magicodes.WeChat/Startup/WeChatConfig.cs create mode 100644 src/unity/Magicodes.WeChat/Startup/WeChatStartup.cs diff --git a/src/admin/api/Admin.Application/Admin.Application.csproj b/src/admin/api/Admin.Application/Admin.Application.csproj index e54f5625..d25f15ee 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 00000000..6f86f04e --- /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 00000000..1ac61d06 --- /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 00000000..1555d357 --- /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 c66720f1..42c6f3bf 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 91bf40a6..75b8baaf 100644 --- a/src/admin/api/Admin.Host/appsettings.json +++ b/src/admin/api/Admin.Host/appsettings.json @@ -69,8 +69,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 b6492835..9ce776a7 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 @@ -895,5 +895,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 fe0ccadc..527d8e5b 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 39eb3ff2..8769b122 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 f1c7e03e..61ae22bd 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 00000000..cdcbecfc --- /dev/null +++ b/src/admin/ui/src/app/admin/settings/weChat-settings.component.html @@ -0,0 +1,51 @@ +
+
+
+
+

+ {{l("WeChatSettings")}} +

+ + {{l("SettingsHeaderInfo")}} + +
+
+ +
+
+
+ +
+
+
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
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 00000000..8bc0c238 --- /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 dcf541e8..3ee6f896 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/assets/appconfig.json b/src/admin/ui/src/assets/appconfig.json index 65f1eb22..3479e2e5 100644 --- a/src/admin/ui/src/assets/appconfig.json +++ b/src/admin/ui/src/assets/appconfig.json @@ -1,5 +1,5 @@ { - "remoteServiceBaseUrl": "http://localhost:5000", + "remoteServiceBaseUrl": "http://localhost:2000", "appBaseUrl": "http://localhost:4200", "localeMappings": [ { 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 880d6cb8..70217952 100644 --- a/src/admin/ui/src/shared/service-proxies/service-proxies.ts +++ b/src/admin/ui/src/shared/service-proxies/service-proxies.ts @@ -12402,6 +12402,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; @@ -25352,6 +25468,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 dc80a5e7..5e7d9e49 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 39dc9f21..240e19a8 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 5f9c8f14..1d2656b4 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 8e7d347c..fe3721a3 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 59e8a164..efe2294a 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 e2b61099..0b10d84a 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 4d042bfe..a0eb1678 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 00000000..cbd892c9 --- /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 00000000..4949dfdf --- /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 e674df28..0587f9e3 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(); } } } -- Gitee