From a82b4607d7ac763234eff084640a18c3dc6ed411 Mon Sep 17 00:00:00 2001 From: colin Date: Tue, 11 Nov 2025 08:44:26 +0800 Subject: [PATCH 1/2] feat(wechat): Add integration of the customer contact module --- .../FodyWeavers.xml | 3 + .../FodyWeavers.xsd | 30 +++ ...YUN.Abp.WeChat.Work.ExternalContact.csproj | 27 +++ .../AbpWeChatWorkExternalContactModule.cs | 78 ++++++++ .../IWeChatWorkAttachmentProvider.cs | 24 +++ .../Attachments/Models/AttachmentType.cs | 20 ++ .../Attachments/Models/MediaType.cs | 25 +++ .../WeChatWorkUploadAttachmentRequest.cs | 41 ++++ .../WeChatWorkUploadAttachmentResponse.cs | 35 ++++ .../WeChatWorkAttachmentProvider.cs | 41 ++++ .../IWeChatWorkExternalContactProvider.cs | 24 +++ .../Contacts/Models/ExternalContactInfo.cs | 73 +++++++ ...WeChatWorkGetExternalContactListRequest.cs | 36 ++++ ...eChatWorkGetExternalContactListResponse.cs | 29 +++ .../WeChatWorkExternalContactProvider.cs | 44 ++++ .../Customers/IWeChatWorkCustomerProvider.cs | 62 ++++++ .../IWeChatWorkCustomerStrategyProvider.cs | 87 ++++++++ .../Customers/Models/CustomerStrategy.cs | 18 ++ .../Customers/Models/CustomerStrategyInfo.cs | 46 +++++ .../Models/CustomerStrategyPrivilege.cs | 183 +++++++++++++++++ .../Customers/Models/CustomerStrategyRange.cs | 61 ++++++ .../Models/CustomerStrategyRangeType.cs | 20 ++ .../Customers/Models/ExternalContactGender.cs | 25 +++ .../Customers/Models/ExternalContactInfo.cs | 88 ++++++++ .../Customers/Models/ExternalContactList.cs | 25 +++ .../Customers/Models/ExternalContactType.cs | 20 ++ .../Customers/Models/FollowUser.cs | 92 +++++++++ .../Customers/Models/FollowUserAddWay.cs | 125 ++++++++++++ .../Customers/Models/FollowUserTag.cs | 39 ++++ .../Customers/Models/FollowUserTagType.cs | 25 +++ .../Models/FollowUserWechatChannel.cs | 25 +++ .../Models/FollowUserWechatChannelSource.cs | 30 +++ .../WeChatWorkBulkGetCustomerRequest.cs | 55 +++++ ...WeChatWorkCreateCustomerStrategyRequest.cs | 74 +++++++ ...WeChatWorkDeleteCustomerStrategyRequest.cs | 28 +++ ...eChatWorkGetCustomerStrategyListRequest.cs | 39 ++++ ...ChatWorkGetCustomerStrategyRangeRequest.cs | 47 +++++ .../WeChatWorkGetCustomerStrategyRequest.cs | 25 +++ .../WeChatWorkUpdateCustomerRemarkRequest.cs | 86 ++++++++ ...WeChatWorkUpdateCustomerStrategyRequest.cs | 75 +++++++ .../WeChatWorkBulkGetCustomerResponse.cs | 48 +++++ ...eChatWorkCreateCustomerStrategyResponse.cs | 21 ++ .../WeChatWorkGetCustomerListResponse.cs | 22 ++ .../Response/WeChatWorkGetCustomerResponse.cs | 37 ++++ ...ChatWorkGetCustomerStrategyListResponse.cs | 29 +++ ...hatWorkGetCustomerStrategyRangeResponse.cs | 30 +++ .../WeChatWorkGetCustomerStrategyResponse.cs | 22 ++ .../Customers/WeChatWorkCustomerProvider.cs | 93 +++++++++ .../WeChatWorkCustomerStrategyProvider.cs | 111 +++++++++++ ...xternalContactFeatureDefinitionProvider.cs | 31 +++ .../WeChatWorkExternalContactFeatureNames.cs | 14 ++ .../Follows/IWeChatWorkFollowUserProvider.cs | 20 ++ .../WeChatWorkGetFollowUserListResponse.cs | 22 ++ .../Follows/WeChatWorkFollowUserProvider.cs | 38 ++++ .../IWeChatWorkGroupChatProvider.cs | 48 +++++ .../GroupChats/Models/GroupChat.cs | 25 +++ .../GroupChats/Models/GroupChatInfo.cs | 67 +++++++ .../GroupChats/Models/GroupChatInvitor.cs | 18 ++ .../GroupChats/Models/GroupChatManager.cs | 18 ++ .../GroupChats/Models/GroupChatMember.cs | 70 +++++++ .../Models/GroupChatMemberJoinScene.cs | 25 +++ .../GroupChats/Models/GroupChatMemberType.cs | 20 ++ .../GroupChats/Models/GroupChatStatus.cs | 30 +++ .../GroupChats/Models/OwnerFilter.cs | 31 +++ .../GroupChats/Models/StatusFilter.cs | 30 +++ .../WeChatWorkGetGroupChatListRequest.cs | 50 +++++ .../Request/WeChatWorkGetGroupChatRequest.cs | 36 ++++ .../WeChatWorkOpengIdToChatIdRequest.cs | 28 +++ .../WeChatWorkGetGroupChatListResponse.cs | 29 +++ .../WeChatWorkGetGroupChatResponse.cs | 22 ++ .../WeChatWorkOpengIdToChatIdResponse.cs | 21 ++ .../GroupChats/WeChatWorkGroupChatProvider.cs | 76 +++++++ .../Localization/Resources/en.json | 7 + .../Localization/Resources/zh-Hans.json | 7 + .../Models/ExternalChaDelMemberEvent.cs | 25 +++ .../Models/ExternalChatAddMemberEvent.cs | 25 +++ .../Models/ExternalChatChangeEvent.cs | 21 ++ .../Models/ExternalChatChangeMemberEvent.cs | 39 ++++ .../Models/ExternalChatChangeNameEvent.cs | 16 ++ .../Models/ExternalChatChangeNoticeEvent.cs | 16 ++ .../Models/ExternalChatChangeOwnerEvent.cs | 16 ++ .../Models/ExternalChatCreateEvent.cs | 16 ++ .../Models/ExternalChatDismissEvent.cs | 16 ++ .../Models/ExternalChatMemberJoinScene.cs | 20 ++ .../Models/ExternalChatMemberQuitScene.cs | 20 ++ .../Models/ExternalChatUpdateEvent.cs | 19 ++ .../Models/ExternalContactChangeEvent.cs | 25 +++ .../Models/ExternalContactCreateEvent.cs | 28 +++ .../Models/ExternalContactCreateHalfEvent.cs | 28 +++ .../Models/ExternalContactDeleteEvent.cs | 23 +++ .../ExternalContactDeleteFollowUserEvent.cs | 16 ++ .../ExternalContactTransferFailEvent.cs | 23 +++ .../Models/ExternalContactUpdateEvent.cs | 17 ++ .../Messages/Models/ExternalTagChangeEvent.cs | 20 ++ .../Messages/Models/ExternalTagCreateEvent.cs | 16 ++ .../Messages/Models/ExternalTagDeleteEvent.cs | 16 ++ .../Models/ExternalTagShuffleEvent.cs | 16 ++ .../Messages/Models/ExternalTagUpdateEvent.cs | 16 ++ .../Models/ExternalAttribute.cs | 25 +++ .../ExternalAttributeDeserializeFactory.cs | 35 ++++ .../Models/ExternalAttributeType.cs | 25 +++ .../Models/ExternalMiniProgramAttribute.cs | 43 ++++ .../ExternalContact/Models/ExternalProfile.cs | 36 ++++ .../Models/ExternalTextAttribute.cs | 29 +++ .../Models/ExternalWebAttribute.cs | 36 ++++ .../ExternalContact/Models/WechatChannel.cs | 25 +++ .../Models/WechatChannelStatus.cs | 20 ++ .../Tags/IWeChatWorkCropTagProvider.cs | 72 +++++++ .../Tags/IWeChatWorkStrategyTagProvider.cs | 60 ++++++ .../ExternalContact/Tags/Models/CropTag.cs | 15 ++ .../Tags/Models/CropTagGroup.cs | 22 ++ .../Tags/Models/StrategyTag.cs | 4 + .../Tags/Models/StrategyTagGroup.cs | 22 ++ .../Work/ExternalContact/Tags/Models/Tag.cs | 36 ++++ .../ExternalContact/Tags/Models/TagGroup.cs | 36 ++++ .../Request/WeChatWorkCreateCropTagRequest.cs | 100 ++++++++++ .../WeChatWorkCreateStrategyTagRequest.cs | 88 ++++++++ .../Request/WeChatWorkDeleteCropTagRequest.cs | 53 +++++ .../WeChatWorkDeleteStrategyTagRequest.cs | 40 ++++ .../WeChatWorkGetCropTagListRequest.cs | 33 +++ .../WeChatWorkGetStrategyTagListRequest.cs | 41 ++++ .../Request/WeChatWorkMarkCropTagRequest.cs | 65 ++++++ .../Request/WeChatWorkUpdateCropTagRequest.cs | 52 +++++ .../WeChatWorkUpdateStrategyTagRequest.cs | 39 ++++ .../WeChatWorkCreateCropTagResponse.cs | 22 ++ .../WeChatWorkCreateStrategyTagResponse.cs | 22 ++ .../WeChatWorkGetCropTagListResponse.cs | 22 ++ .../WeChatWorkGetStrategyTagListResponse.cs | 22 ++ .../Tags/WeChatWorkCropTagProvider.cs | 108 ++++++++++ .../Tags/WeChatWorkStrategyTagProvider.cs | 92 +++++++++ .../IWeChatWorkEmployExtendProvider.cs | 48 +++++ .../IWeChatWorkResignExtendProvider.cs | 60 ++++++ .../Models/GroupChatTransferFailed.cs | 32 +++ .../Transfers/Models/TransferCustomer.cs | 22 ++ .../Models/TransferCustomerResult.cs | 29 +++ .../Transfers/Models/TransferStatus.cs | 30 +++ .../Models/UnassignedCustomerInfo.cs | 29 +++ .../Models/UnassignedTransferCustomer.cs | 25 +++ .../UnassignedTransferCustomerResult.cs | 32 +++ ...hatWorkGetResignedTransferResultRequest.cs | 48 +++++ .../WeChatWorkGetTransferResultRequest.cs | 48 +++++ .../WeChatWorkGetUnassignedListRequest.cs | 27 +++ ...WeChatWorkGroupChatOnjobTransferRequest.cs | 43 ++++ .../WeChatWorkGroupChatTransferRequest.cs | 43 ++++ ...ChatWorkResignedTransferCustomerRequest.cs | 52 +++++ .../WeChatWorkTransferCustomerRequest.cs | 60 ++++++ ...atWorkGetResignedTransferResultResponse.cs | 29 +++ .../WeChatWorkGetTransferResultResponse.cs | 29 +++ .../WeChatWorkGetUnassignedListResponse.cs | 36 ++++ ...eChatWorkGroupChatOnjobTransferResponse.cs | 22 ++ .../WeChatWorkGroupChatTransferResponse.cs | 22 ++ ...hatWorkResignedTransferCustomerResponse.cs | 22 ++ .../WeChatWorkTransferCustomerResponse.cs | 22 ++ .../WeChatWorkEmployExtendProvider.cs | 76 +++++++ .../WeChatWorkResignExtendProvider.cs | 92 +++++++++ .../ExternalProfileNewtonsoftJsonConverter.cs | 70 +++++++ .../README.md | 29 +++ ...WeChatWorkRequestExtensions.Attachments.cs | 33 +++ ...entWeChatWorkRequestExtensions.Contacts.cs | 28 +++ ...ntWeChatWorkRequestExtensions.Customers.cs | 89 +++++++++ ...ientWeChatWorkRequestExtensions.Follows.cs | 23 +++ ...tWeChatWorkRequestExtensions.GroupChats.cs | 69 +++++++ ...tWeChatWorkRequestExtensions.Strategies.cs | 128 ++++++++++++ ...pClientWeChatWorkRequestExtensions.Tags.cs | 188 ++++++++++++++++++ ...ntWeChatWorkRequestExtensions.Transfers.cs | 148 ++++++++++++++ .../HttpClientWeChatWorkRequestExtensions.cs | 5 + .../Http/HttpResponseDeserializeExtensions.cs | 19 ++ .../ExternalProfileSystemTextJsonConverter.cs | 63 ++++++ ...cs => WeChatWorkHttpContentBuildHelper.cs} | 2 +- ...ClientWeChatWorkRequestExtensions.Media.cs | 4 +- .../GlobalUsings.cs | 2 + ...p.WeChat.Work.ExternalContact.Tests.csproj | 20 ++ .../AbpWeChatWorkExternalContactTestBase.cs | 6 + .../AbpWeChatWorkExternalContactTestModule.cs | 22 ++ ...WeChatWorkExternalContactProvider_Tests.cs | 22 ++ .../WeChatWorkCustomerProvider_Tests.cs | 62 ++++++ ...eChatWorkCustomerStrategyProvider_Tests.cs | 49 +++++ .../WeChatWorkFollowUserProvider_Tests.cs | 20 ++ .../WeChatWorkGroupChatProvider_Tests.cs | 47 +++++ .../Tags/WeChatWorkCropTagProvider_Tests.cs | 90 +++++++++ .../WeChat/Work/AbpWeChatWorkTestModule.cs | 11 +- 181 files changed, 7177 insertions(+), 9 deletions(-) create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xml create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xsd create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN.Abp.WeChat.Work.ExternalContact.csproj create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactModule.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/IWeChatWorkAttachmentProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/AttachmentType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/MediaType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Request/WeChatWorkUploadAttachmentRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Response/WeChatWorkUploadAttachmentResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/WeChatWorkAttachmentProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/IWeChatWorkExternalContactProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Models/ExternalContactInfo.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Request/WeChatWorkGetExternalContactListRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Response/WeChatWorkGetExternalContactListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerStrategyProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategy.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyInfo.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyPrivilege.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRange.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRangeType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactGender.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactInfo.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactList.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUser.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserAddWay.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTag.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTagType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannel.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannelSource.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkBulkGetCustomerRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkCreateCustomerStrategyRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkDeleteCustomerStrategyRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyListRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRangeRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerRemarkRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerStrategyRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkBulkGetCustomerResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkCreateCustomerStrategyResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyRangeResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureDefinitionProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureNames.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/IWeChatWorkFollowUserProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/Response/WeChatWorkGetFollowUserListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/IWeChatWorkGroupChatProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChat.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInfo.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInvitor.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatManager.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMember.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberJoinScene.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatStatus.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/OwnerFilter.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/StatusFilter.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatListRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkOpengIdToChatIdRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkOpengIdToChatIdResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/en.json create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/zh-Hans.json create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChaDelMemberEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatAddMemberEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeMemberEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNameEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNoticeEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeOwnerEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatCreateEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatDismissEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberJoinScene.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberQuitScene.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatUpdateEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactChangeEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateHalfEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteFollowUserEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactTransferFailEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactUpdateEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagChangeEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagCreateEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagDeleteEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagShuffleEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagUpdateEvent.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttribute.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeDeserializeFactory.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeType.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalMiniProgramAttribute.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalProfile.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalTextAttribute.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalWebAttribute.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannel.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannelStatus.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkCropTagProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkStrategyTagProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTag.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTagGroup.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTag.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTagGroup.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/Tag.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/TagGroup.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateCropTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateStrategyTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteCropTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteStrategyTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetCropTagListRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetStrategyTagListRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkMarkCropTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateCropTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateStrategyTagRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateCropTagResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateStrategyTagResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetCropTagListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetStrategyTagListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkStrategyTagProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkEmployExtendProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkResignExtendProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/GroupChatTransferFailed.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomer.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomerResult.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferStatus.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedCustomerInfo.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomer.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomerResult.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetResignedTransferResultRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetTransferResultRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetUnassignedListRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatOnjobTransferRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatTransferRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkResignedTransferCustomerRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkTransferCustomerRequest.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetResignedTransferResultResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetTransferResultResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetUnassignedListResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatOnjobTransferResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatTransferResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkResignedTransferCustomerResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkTransferCustomerResponse.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkEmployExtendProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkResignExtendProvider.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/Newtonsoft/Json/ExternalProfileNewtonsoftJsonConverter.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/README.md create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Attachments.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Contacts.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Customers.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Follows.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.GroupChats.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Strategies.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Tags.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Transfers.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpResponseDeserializeExtensions.cs create mode 100644 aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Text/Json/Serialization/ExternalProfileSystemTextJsonConverter.cs rename aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/{HttpContentBuildHelper.cs => WeChatWorkHttpContentBuildHelper.cs} (96%) create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/GlobalUsings.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests.csproj create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestBase.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestModule.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider_Tests.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider_Tests.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider_Tests.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider_Tests.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider_Tests.cs create mode 100644 aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider_Tests.cs diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xml b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xsd b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN.Abp.WeChat.Work.ExternalContact.csproj b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN.Abp.WeChat.Work.ExternalContact.csproj new file mode 100644 index 000000000..730bd0b71 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN.Abp.WeChat.Work.ExternalContact.csproj @@ -0,0 +1,27 @@ + + + + + + + netstandard2.0;netstandard2.1;net8.0;net9.0 + LINGYUN.Abp.WeChat.Work.ExternalContact + LINGYUN.Abp.WeChat.Work.ExternalContact + false + false + false + True + enable + + + + + + + + + + + + + diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactModule.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactModule.cs new file mode 100644 index 000000000..dd18a596b --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactModule.cs @@ -0,0 +1,78 @@ +using LINGYUN.Abp.WeChat.Common; +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +using LINGYUN.Abp.WeChat.Work.Localization; +using Volo.Abp.Localization; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact; + +[DependsOn(typeof(AbpWeChatWorkModule))] +public class AbpWeChatWorkExternalContactModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + // 企业客户变更事件 + options.MapEvent("change_external_contact", context => + { + var changeType = context.GetMessageData("ChangeType"); + return changeType switch + { + "add_external_contact" => context.GetWeChatMessage(), + "edit_external_contact" => context.GetWeChatMessage(), + "add_half_external_contact" => context.GetWeChatMessage(), + "del_external_contact" => context.GetWeChatMessage(), + "del_follow_user" => context.GetWeChatMessage(), + "transfer_fail" => context.GetWeChatMessage(), + _ => throw new AbpWeChatException($"Contact change event change_external_contact:{changeType} is not mounted!"), + }; + }); + // 客户群变更事件 + options.MapEvent("change_external_chat", context => + { + var changeType = context.GetMessageData("ChangeType"); + switch (changeType) + { + case "create": return context.GetWeChatMessage(); + case "update": + // 客户群变更事件 + var updateDetail = context.GetMessageData("UpdateDetail"); + return updateDetail switch + { + "add_member" => context.GetWeChatMessage(), + "del_member" => context.GetWeChatMessage(), + "change_owner" => context.GetWeChatMessage(), + "change_name" => context.GetWeChatMessage(), + "change_notice" => context.GetWeChatMessage(), + _ => throw new AbpWeChatException($"Contact change event change_external_chat:{changeType}:{updateDetail} is not mounted!"), + }; + case "dismiss": return context.GetWeChatMessage(); + default: throw new AbpWeChatException($"Contact change event change_external_chat:{changeType} is not mounted!"); + } + }); + // 企业客户标签事件 + options.MapEvent("change_external_tag", context => + { + var changeType = context.GetMessageData("ChangeType"); + return changeType switch + { + "create" => context.GetWeChatMessage(), + "update" => context.GetWeChatMessage(), + "delete" => context.GetWeChatMessage(), + "shuffle" => context.GetWeChatMessage(), + _ => throw new AbpWeChatException($"Contact change event change_external_tag:{changeType} is not mounted!"), + }; + }); + }); + + Configure(options => + { + options.Resources + .Get() + .AddVirtualJson("/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources"); + }); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/IWeChatWorkAttachmentProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/IWeChatWorkAttachmentProvider.cs new file mode 100644 index 000000000..e35baeb31 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/IWeChatWorkAttachmentProvider.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments; +/// +/// 附件资源接口 +/// +public interface IWeChatWorkAttachmentProvider +{ + /// + /// 上传附件资源 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task UploadAsync( + WeChatWorkUploadAttachmentRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/AttachmentType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/AttachmentType.cs new file mode 100644 index 000000000..096e7bf8f --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/AttachmentType.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Models; +/// +/// 附件类型 +/// +[Description("附件类型")] +public enum AttachmentType +{ + /// + /// 朋友圈 + /// + [Description("朋友圈")] + Moments = 1, + /// + /// 商品图册 + /// + [Description("商品图册")] + ProductCatalogue = 2, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/MediaType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/MediaType.cs new file mode 100644 index 000000000..d122f663c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Models/MediaType.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Models; +/// +/// 媒体文件类型 +/// +[Description("媒体文件类型")] +public enum MediaType +{ + /// + /// 图片 + /// + [Description("图片")] + Image = 1, + /// + /// 视频 + /// + [Description("视频")] + Video = 2, + /// + /// 普通文件 + /// + [Description("普通文件")] + File = 3, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Request/WeChatWorkUploadAttachmentRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Request/WeChatWorkUploadAttachmentRequest.cs new file mode 100644 index 000000000..e1ac87d55 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Request/WeChatWorkUploadAttachmentRequest.cs @@ -0,0 +1,41 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Models; +using Volo.Abp; +using Volo.Abp.Content; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Request; +/// +/// 上传附件资源请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkUploadAttachmentRequest : WeChatWorkRequest +{ + /// + /// 媒体文件类型 + /// + [NotNull] + public MediaType MediaType { get; } + /// + /// 附件类型 + /// + [NotNull] + public AttachmentType AttachmentType { get; } + /// + /// 媒体文件 + /// + [NotNull] + public IRemoteStreamContent Content { get; } + public WeChatWorkUploadAttachmentRequest( + MediaType mediaType, + AttachmentType attachmentType, + IRemoteStreamContent content) + { + Check.NotNull(content, nameof(content)); + + MediaType = mediaType; + AttachmentType = attachmentType; + Content = content; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Response/WeChatWorkUploadAttachmentResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Response/WeChatWorkUploadAttachmentResponse.cs new file mode 100644 index 000000000..46f1045f7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/Response/WeChatWorkUploadAttachmentResponse.cs @@ -0,0 +1,35 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Response; +/// +/// 上传附件资源响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkUploadAttachmentResponse : WeChatWorkResponse +{ + /// + /// 媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file) + /// + [NotNull] + [JsonProperty("type")] + [JsonPropertyName("type")] + public string MediaType { get; set; } + /// + /// 媒体文件上传后获取的唯一标识,三天有效,可使用获取临时素材接口获取 + /// + [NotNull] + [JsonProperty("media_id")] + [JsonPropertyName("media_id")] + public string MediaId { get; set; } + /// + /// 媒体文件上传时间戳 + /// + [NotNull] + [JsonProperty("created_at")] + [JsonPropertyName("created_at")] + public long CreatedAt { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/WeChatWorkAttachmentProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/WeChatWorkAttachmentProvider.cs new file mode 100644 index 000000000..d2e9d5610 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Attachments/WeChatWorkAttachmentProvider.cs @@ -0,0 +1,41 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Response; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkAttachmentProvider : IWeChatWorkAttachmentProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkAttachmentProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task UploadAsync( + WeChatWorkUploadAttachmentRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.UploadAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/IWeChatWorkExternalContactProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/IWeChatWorkExternalContactProvider.cs new file mode 100644 index 000000000..4efe1d1a1 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/IWeChatWorkExternalContactProvider.cs @@ -0,0 +1,24 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts; +/// +/// 外部联系人接口 +/// +public interface IWeChatWorkExternalContactProvider +{ + /// + /// 获取已服务的外部联系人 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetExternalContactListAsync( + WeChatWorkGetExternalContactListRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Models/ExternalContactInfo.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Models/ExternalContactInfo.cs new file mode 100644 index 000000000..2e53003fc --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Models/ExternalContactInfo.cs @@ -0,0 +1,73 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Models; +/// +/// 外部联系人 +/// +public class ExternalContactInfo +{ + /// + /// 是否被成员标记为客户 + /// + [NotNull] + [JsonProperty("is_customer")] + [JsonPropertyName("is_customer")] + public bool IsCustomer { get; set; } + /// + /// 外部联系人临时ID + /// + /// + /// + /// 外部联系人临时id是一个外部联系人的唯一标识,企业可根据此id对外部联系人进行去重统计。
+ /// 但外部联系人临时id仅在一轮遍历查询(从首个分页查询开始到最后一个分页查询完毕)中唯一;
+ /// 每次请求首个数据分页(cursor为空)时,返回的外部联系人临时id和next_cursor将发生变化。 + ///
+ [NotNull] + [JsonProperty("tmp_openid")] + [JsonPropertyName("tmp_openid")] + public string TmpOpenId { get; set; } + /// + /// 外部联系人的externaluserid(如果是客户才返回) + /// + [CanBeNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string? ExternalUserId { get; set; } + /// + /// 脱敏后的外部联系人昵称(如果是其他外部联系人才返回) + /// + [CanBeNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string? Name { get; set; } + /// + /// 添加此外部联系人的企业成员或外部联系人所在群聊的群主userid + /// + [CanBeNull] + [JsonProperty("follow_userid")] + [JsonPropertyName("follow_userid")] + public string? FollowUserId { get; set; } + /// + /// 外部联系人所在的群聊ID(如果群聊被成员标记为客户群才返回) + /// + [CanBeNull] + [JsonProperty("chat_id")] + [JsonPropertyName("chat_id")] + public string? ChatId { get; set; } + /// + /// 外部联系人所在群聊的群名(如果群聊未被成员标记为客户群才返回) + /// + [CanBeNull] + [JsonProperty("chat_name")] + [JsonPropertyName("chat_name")] + public string? ChatName { get; set; } + /// + /// 外部联系人首次添加/进群的时间 + /// + [NotNull] + [JsonProperty("add_time")] + [JsonPropertyName("add_time")] + public long AddTime { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Request/WeChatWorkGetExternalContactListRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Request/WeChatWorkGetExternalContactListRequest.cs new file mode 100644 index 000000000..de2874273 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Request/WeChatWorkGetExternalContactListRequest.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Request; +/// +/// 获取已服务的外部联系人请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetExternalContactListRequest : WeChatWorkRequest +{ + /// + /// 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用可不填 + /// + /// + /// cursor具有有效期,请勿缓存后使用 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; } + /// + /// 返回的最大记录数,整型,默认为1000 + /// + [CanBeNull] + [JsonProperty("limit")] + [JsonPropertyName("limit")] + public int? Limit { get; } + public WeChatWorkGetExternalContactListRequest(string? cursor = null, int? limit = 1000) + { + Cursor = cursor; + Limit = limit; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Response/WeChatWorkGetExternalContactListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Response/WeChatWorkGetExternalContactListResponse.cs new file mode 100644 index 000000000..4492b93ca --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/Response/WeChatWorkGetExternalContactListResponse.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Response; +/// +/// 获取已服务的外部联系人响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetExternalContactListResponse : WeChatWorkResponse +{ + /// + /// 外部联系人列表 + /// + [NotNull] + [JsonProperty("info_list")] + [JsonPropertyName("info_list")] + public ExternalContactInfo[] InfoList { get; set; } + /// + /// 分页游标,再下次请求时填写以获取之后分页的记录,如果已经没有更多的数据则返回空,有效期为4小时 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider.cs new file mode 100644 index 000000000..52179841b --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider.cs @@ -0,0 +1,44 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Response; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkExternalContactProvider : IWeChatWorkExternalContactProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkExternalContactProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetExternalContactListAsync( + WeChatWorkGetExternalContactListRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetExternalContactListAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerProvider.cs new file mode 100644 index 000000000..caba3bf25 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerProvider.cs @@ -0,0 +1,62 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers; +/// +/// 客户管理接口 +/// +public interface IWeChatWorkCustomerProvider +{ + /// + /// 获取客户列表 + /// + /// + /// 详情见: + /// + /// 企业成员的userid + /// + /// + Task GetCustomerListAsync( + string userId, + CancellationToken cancellationToken = default); + /// + /// 批量获取客户详情 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task BulkGetCustomerAsync( + WeChatWorkBulkGetCustomerRequest request, + CancellationToken cancellationToken = default); + /// + /// 获取客户详情 + /// + /// + /// 详情见: + /// + /// 外部联系人的userid,注意不是企业成员的账号 + /// 上次请求返回的next_cursor + /// + /// + Task GetCustomerAsync( + string externalUserid, + string? cursor = null, + CancellationToken cancellationToken = default); + /// + /// 修改客户备注信息 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task UpdateCustomerRemarkAsync( + WeChatWorkUpdateCustomerRemarkRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerStrategyProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerStrategyProvider.cs new file mode 100644 index 000000000..c7dd5cead --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/IWeChatWorkCustomerStrategyProvider.cs @@ -0,0 +1,87 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers; +/// +/// 客户联系规则组管理 +/// +/// +/// 详情见: +/// +public interface IWeChatWorkCustomerStrategyProvider +{ + /// + /// 获取规则组列表 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetCustomerStrategyListAsync( + WeChatWorkGetCustomerStrategyListRequest request, + CancellationToken cancellationToken = default); + /// + /// 获取规则组 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetCustomerStrategyAsync( + WeChatWorkGetCustomerStrategyRequest request, + CancellationToken cancellationToken = default); + /// + /// 获取规则组管理范围 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetCustomerStrategyRangeAsync( + WeChatWorkGetCustomerStrategyRangeRequest request, + CancellationToken cancellationToken = default); + /// + /// 创建新的规则组 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task CreateCustomerStrategyAsync( + WeChatWorkCreateCustomerStrategyRequest request, + CancellationToken cancellationToken = default); + /// + /// 编辑规则组及其管理范围 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task UpdateCustomerStrategyAsync( + WeChatWorkUpdateCustomerStrategyRequest request, + CancellationToken cancellationToken = default); + /// + /// 删除规则组 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task DeleteCustomerStrategyAsync( + WeChatWorkDeleteCustomerStrategyRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategy.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategy.cs new file mode 100644 index 000000000..27b81293a --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategy.cs @@ -0,0 +1,18 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 规则组 +/// +public class CustomerStrategy +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyInfo.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyInfo.cs new file mode 100644 index 000000000..dec0bdb1f --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyInfo.cs @@ -0,0 +1,46 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 规则组详情 +/// +public class CustomerStrategyInfo : CustomerStrategy +{ + /// + /// 父规则组id, 如果当前规则组没父规则组,则为0 + /// + [NotNull] + [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] + public int ParentId { get; set; } + /// + /// 规则组名称 + /// + [NotNull] + [JsonProperty("strategy_name")] + [JsonPropertyName("strategy_name")] + public string StrategyName { get; set; } + /// + /// 规则组创建时间戳 + /// + [NotNull] + [JsonProperty("create_time")] + [JsonPropertyName("create_time")] + public long CreateTime { get; set; } + /// + /// 规则组管理员userid列表 + /// + [NotNull] + [JsonProperty("admin_list")] + [JsonPropertyName("admin_list")] + public string[] AdminList { get; set; } + /// + /// 规则组权限 + /// + [NotNull] + [JsonProperty("privilege")] + [JsonPropertyName("privilege")] + public CustomerStrategyPrivilege Privilege { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyPrivilege.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyPrivilege.cs new file mode 100644 index 000000000..03ce9e057 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyPrivilege.cs @@ -0,0 +1,183 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 规则组权限 +/// +public class CustomerStrategyPrivilege +{ + /// + /// 查看客户列表,基础权限,不可取消 + /// + [NotNull] + [JsonProperty("view_customer_list")] + [JsonPropertyName("view_customer_list")] + public bool ViewCustomerList { get; set; } + /// + /// 查看客户统计数据,基础权限,不可取消 + /// + [NotNull] + [JsonProperty("view_customer_data")] + [JsonPropertyName("view_customer_data")] + public bool ViewCustomerData { get; set; } + /// + /// 查看群聊列表,基础权限,不可取消 + /// + [NotNull] + [JsonProperty("view_room_list")] + [JsonPropertyName("view_room_list")] + public bool ViewRoomList { get; set; } + /// + /// 可使用联系我,基础权限,不可取消 + /// + [NotNull] + [JsonProperty("contact_me")] + [JsonPropertyName("contact_me")] + public bool ContactMe { get; set; } + /// + /// 可加入群聊,基础权限,不可取消 + /// + [NotNull] + [JsonProperty("join_room")] + [JsonPropertyName("join_room")] + public bool JoinRoom { get; set; } + /// + /// 允许分享客户给其他成员,默认为true + /// + [NotNull] + [JsonProperty("share_customer")] + [JsonPropertyName("share_customer")] + public bool ShareCustomer { get; set; } + /// + /// 允许分配离职成员客户,默认为true + /// + [NotNull] + [JsonProperty("oper_resign_customer")] + [JsonPropertyName("oper_resign_customer")] + public bool OperResignCustomer { get; set; } + /// + /// 允许分配离职成员客户群,默认为true + /// + [NotNull] + [JsonProperty("oper_resign_group")] + [JsonPropertyName("oper_resign_group")] + public bool OperResignGroup { get; set; } + /// + /// 允许给企业客户发送消息,默认为true + /// + [NotNull] + [JsonProperty("send_customer_msg")] + [JsonPropertyName("send_customer_msg")] + public bool SendCustomerMsg { get; set; } + /// + /// 允许配置欢迎语,默认为true + /// + [NotNull] + [JsonProperty("edit_welcome_msg")] + [JsonPropertyName("edit_welcome_msg")] + public bool EditWelcomeMsg { get; set; } + /// + /// 允许查看成员联系客户统计,默认为true + /// + [NotNull] + [JsonProperty("view_behavior_data")] + [JsonPropertyName("view_behavior_data")] + public bool ViewBehaviorData { get; set; } + /// + /// 允许查看群聊数据统计,默认为true + /// + [NotNull] + [JsonProperty("view_room_data")] + [JsonPropertyName("view_room_data")] + public bool ViewRoomData { get; set; } + /// + /// 允许发送消息到企业的客户群,默认为true + /// + [NotNull] + [JsonProperty("send_group_msg")] + [JsonPropertyName("send_group_msg")] + public bool SendGroupMsg { get; set; } + /// + /// 允许对企业客户群进行去重,默认为true + /// + [NotNull] + [JsonProperty("room_deduplication")] + [JsonPropertyName("room_deduplication")] + public bool RoomDeduplication { get; set; } + /// + /// 配置快捷回复,默认为true + /// + [NotNull] + [JsonProperty("rapid_reply")] + [JsonPropertyName("rapid_reply")] + public bool RapidReply { get; set; } + /// + /// 转接在职成员的客户,默认为true + /// + [NotNull] + [JsonProperty("onjob_customer_transfer")] + [JsonPropertyName("onjob_customer_transfer")] + public bool OnjobCustomerTransfer { get; set; } + /// + /// 编辑企业成员防骚扰规则,默认为true + /// + [NotNull] + [JsonProperty("edit_anti_spam_rule")] + [JsonPropertyName("edit_anti_spam_rule")] + public bool EditAntiSpamRule { get; set; } + /// + /// 导出客户列表,默认为true + /// + [NotNull] + [JsonProperty("export_customer_list")] + [JsonPropertyName("export_customer_list")] + public bool ExportCustomerList { get; set; } + /// + /// 导出成员客户统计,默认为true + /// + [NotNull] + [JsonProperty("export_customer_data")] + [JsonPropertyName("export_customer_data")] + public bool ExportCustomerData { get; set; } + /// + /// 导出客户群列表,默认为true + /// + [NotNull] + [JsonProperty("export_customer_group_list")] + [JsonPropertyName("export_customer_group_list")] + public bool ExportCustomerGroupList { get; set; } + /// + /// 配置企业客户标签,默认为true + /// + [NotNull] + [JsonProperty("manage_customer_tag")] + [JsonPropertyName("manage_customer_tag")] + public bool ManageCustomerTag { get; set; } + + public static CustomerStrategyPrivilege Default() + { + return new CustomerStrategyPrivilege + { + ViewCustomerList = true, + ViewCustomerData = true, + ViewRoomList = true, + ContactMe = true, + JoinRoom = true, + ShareCustomer = true, + EditWelcomeMsg = true, + ViewBehaviorData = true, + ViewRoomData = true, + SendGroupMsg = true, + RoomDeduplication = true, + RapidReply = true, + OnjobCustomerTransfer = true, + EditAntiSpamRule = true, + ExportCustomerList = true, + ExportCustomerData = true, + ExportCustomerGroupList = true, + ManageCustomerTag = true, + }; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRange.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRange.cs new file mode 100644 index 000000000..f02127f27 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRange.cs @@ -0,0 +1,61 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 规则组管理范围 +/// +public class CustomerStrategyRange +{ + /// + /// 节点类型 + /// + [NotNull] + [JsonProperty("type")] + [JsonPropertyName("type")] + public CustomerStrategyRangeType Type { get; set; } + /// + /// 管理范围内配置的成员userid,仅 Type为 时返回 + /// + [CanBeNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string? UserId { get; set; } + /// + /// 管理范围内配置的部门partyid,仅 Type为 时返回 + /// + [CanBeNull] + [JsonProperty("partyid")] + [JsonPropertyName("partyid")] + public int? PartyId { get; set; } + + public CustomerStrategyRange() + { + + } + + private CustomerStrategyRange( + CustomerStrategyRangeType type, + string? userId = null, + int? partyId = null) + { + Type = type; + UserId = userId; + PartyId = partyId; + } + + public static CustomerStrategyRange Member(string userId) + { + Check.NotNullOrWhiteSpace(userId, nameof(userId)); + + return new CustomerStrategyRange(CustomerStrategyRangeType.Member, userId); + } + public static CustomerStrategyRange Party(int partyId) + { + Check.NotDefaultOrNull(partyId, nameof(partyId)); + + return new CustomerStrategyRange(CustomerStrategyRangeType.Part, partyId: partyId); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRangeType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRangeType.cs new file mode 100644 index 000000000..eb99edafd --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/CustomerStrategyRangeType.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 节点类型 +/// +[Description("节点类型")] +public enum CustomerStrategyRangeType +{ + /// + /// 成员 + /// + [Description("成员")] + Member = 1, + /// + /// 部门 + /// + [Description("部门")] + Part = 2 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactGender.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactGender.cs new file mode 100644 index 000000000..609f42df1 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactGender.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 外部联系人性别 +/// +[Description("外部联系人性别")] +public enum ExternalContactGender +{ + /// + /// 未知 + /// + [Description("未知")] + None = 0, + /// + /// 男性 + /// + [Description("男性")] + Male = 1, + /// + /// 女性 + /// + [Description("女性")] + FeMale = 2, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactInfo.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactInfo.cs new file mode 100644 index 000000000..cf26d5659 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactInfo.cs @@ -0,0 +1,88 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 外部联系人信息 +/// +public class ExternalContactInfo +{ + /// + /// 外部联系人的userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserId { get; set; } + /// + /// 外部联系人的名称 + /// + /// + /// 如果是微信用户,则返回其微信昵称。
+ /// 如果是企业微信联系人,则返回其设置对外展示的别名或实名 + ///
+ [NotNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string Name { get; set; } + /// + /// 外部联系人头像 + /// + [CanBeNull] + [JsonProperty("avatar")] + [JsonPropertyName("avatar")] + public string? Avatar { get; set; } + /// + /// 外部联系人的类型 + /// + [NotNull] + [JsonProperty("type")] + [JsonPropertyName("type")] + public ExternalContactType Type { get; set; } + /// + /// 外部联系人性别 + /// + [NotNull] + [JsonProperty("gender")] + [JsonPropertyName("gender")] + public ExternalContactGender Gender { get; set; } + /// + /// 外部联系人在微信开放平台的唯一身份标识(微信unionid),通过此字段企业可将外部联系人与公众号/小程序用户关联起来。
+ /// 仅当联系人类型是微信用户,且企业绑定了微信开发者ID有此字段 + ///
+ [CanBeNull] + [JsonProperty("unionid")] + [JsonPropertyName("unionid")] + public string? UnionId { get; set; } + /// + /// 外部联系人的职位,如果外部企业或用户选择隐藏职位,则不返回,仅当联系人类型是企业微信用户时有此字段 + /// + [CanBeNull] + [JsonProperty("position")] + [JsonPropertyName("position")] + public string? Position { get; set; } + /// + /// 外部联系人所在企业的简称,仅当联系人类型是企业微信用户时有此字段 + /// + [CanBeNull] + [JsonProperty("corp_name")] + [JsonPropertyName("corp_name")] + public string? CorpName { get; set; } + /// + /// 外部联系人所在企业的主体名称,仅当联系人类型是企业微信用户时有此字段
+ /// 仅企业自建应用可获取 + ///
+ [CanBeNull] + [JsonProperty("corp_full_name")] + [JsonPropertyName("corp_full_name")] + public string? CorpFullName { get; set; } + /// + /// 外部联系人的自定义展示信息 + /// + [CanBeNull] + [JsonProperty("external_profile")] + [JsonPropertyName("external_profile")] + public ExternalProfile? ExternalProfile { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactList.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactList.cs new file mode 100644 index 000000000..7ace31afb --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactList.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 外部联系人列表 +/// +public class ExternalContactList +{ + /// + /// 客户的基本信息 + /// + [NotNull] + [JsonProperty("external_contact")] + [JsonPropertyName("external_contact")] + public ExternalContactInfo ExternalContact { get; set; } + /// + /// 企业成员客户跟进信息 + /// + [NotNull] + [JsonProperty("follow_info")] + [JsonPropertyName("follow_info")] + public FollowUser FollowUser { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactType.cs new file mode 100644 index 000000000..7545230a7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/ExternalContactType.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 外部联系人类型 +/// +[Description("外部联系人类型")] +public enum ExternalContactType +{ + /// + /// 微信用户 + /// + [Description("微信用户")] + WeChat = 1, + /// + /// 企业微信用户 + /// + [Description("企业微信用户")] + WeChatWork = 2, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUser.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUser.cs new file mode 100644 index 000000000..6225a3b76 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUser.cs @@ -0,0 +1,92 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 添加了外部联系人的企业成员 +/// +public class FollowUser +{ + /// + /// 添加了此外部联系人的企业成员userid + /// + [NotNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string UserId { get; set; } + /// + /// 发起添加的userid
+ /// 如果成员主动添加,为成员的userid;
+ /// 如果是客户主动添加,则为客户的外部联系人userid;
+ /// 如果是内部成员共享/管理员分配,则为对应的成员/管理员userid + ///
+ [NotNull] + [JsonProperty("oper_userid")] + [JsonPropertyName("oper_userid")] + public string OperUserId { get; set; } + /// + /// 企业自定义的state参数,用于区分客户具体是通过哪个「联系我」或获客链接添加 + /// + [CanBeNull] + [JsonProperty("state")] + [JsonPropertyName("state")] + public string? State { get; set; } + /// + /// 该成员对此外部联系人的备注 + /// + [CanBeNull] + [JsonProperty("remark")] + [JsonPropertyName("remark")] + public string? Remark { get; set; } + /// + /// 该成员对此外部联系人的描述 + /// + [CanBeNull] + [JsonProperty("description")] + [JsonPropertyName("description")] + public string? Description { get; set; } + /// + /// 该成员添加此外部联系人的时间 + /// + [NotNull] + [JsonProperty("createtime")] + [JsonPropertyName("createtime")] + public long Createtime { get; set; } + /// + /// 外部联系人所打标签列表 + /// + [CanBeNull] + [JsonProperty("tags")] + [JsonPropertyName("tags")] + public List? Tags { get; set; } + /// + /// 该成员对此微信客户备注的企业名称(仅微信客户有该字段) + /// + [CanBeNull] + [JsonProperty("remark_corp_name")] + [JsonPropertyName("remark_corp_name")] + public string? RemarkCorpName { get; set; } + /// + /// 该成员对此客户备注的手机号码,代开发自建应用需要管理员授权才可以获取 + /// + [CanBeNull] + [JsonProperty("remark_mobiles")] + [JsonPropertyName("remark_mobiles")] + public List? RemarkMobiles { get; set; } + /// + /// 该成员添加此客户的来源 + /// + [NotNull] + [JsonProperty("add_way")] + [JsonPropertyName("add_way")] + public FollowUserAddWay AddWay { get; set; } + /// + /// 该成员添加此客户的来源add_way为10时,对应的视频号信息 + /// + [CanBeNull] + [JsonProperty("wechat_channels")] + [JsonPropertyName("wechat_channels")] + public FollowUserWechatChannel? WechatChannel { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserAddWay.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserAddWay.cs new file mode 100644 index 000000000..79caed25c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserAddWay.cs @@ -0,0 +1,125 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 客户来源 +/// +[Description("客户来源")] +public enum FollowUserAddWay +{ + /// + /// 未知来源 + /// + [Description("未知来源")] + None = 0, + /// + /// 扫描二维码 + /// + [Description("扫描二维码")] + ScanQrCode = 1, + /// + /// 搜索手机号 + /// + [Description("搜索手机号")] + SearchPhoneNumber = 2, + /// + /// 名片分享 + /// + [Description("名片分享")] + SharedCard = 3, + /// + /// 群聊 + /// + [Description("群聊")] + GroupChat = 4, + /// + /// 手机通讯录 + /// + [Description("手机通讯录")] + PhoneBook = 5, + /// + /// 微信联系人 + /// + [Description("微信联系人")] + WeChatContact = 6, + /// + /// 安装第三方应用时自动添加的客服人员 + /// + [Description("安装第三方应用时自动添加的客服人员")] + InstallThirdPartyApp = 8, + /// + /// 搜索邮箱 + /// + [Description("搜索邮箱")] + SearchEmail = 9, + /// + /// 视频号添加 + /// + [Description("视频号添加")] + WechatChannel = 10, + /// + /// 通过日程参与人添加 + /// + [Description("通过日程参与人添加")] + SchedulePart = 11, + /// + /// 通过会议参与人添加 + /// + [Description("通过会议参与人添加")] + MeetPart = 12, + /// + /// 添加微信好友对应的企业微信 + /// + [Description("添加微信好友对应的企业微信")] + WeChatFriend = 13, + /// + /// 通过智慧硬件专属客服添加 + /// + [Description("通过智慧硬件专属客服添加")] + SmartHardware = 14, + /// + /// 通过上门服务客服添加 + /// + [Description("通过上门服务客服添加")] + DoorService = 15, + /// + /// 通过获客链接添加 + /// + [Description("通过获客链接添加")] + CustomerAcqLink = 16, + /// + /// 通过定制开发添加 + /// + [Description("通过定制开发添加")] + CustomDevelopment = 17, + /// + /// 通过需求回复添加 + /// + [Description("通过需求回复添加")] + DemandResponse = 18, + /// + /// 通过第三方售前客服添加 + /// + [Description("通过第三方售前客服添加")] + ThirdPartyPreSales = 21, + /// + /// 通过可能的商务伙伴添加 + /// + [Description("通过可能的商务伙伴添加")] + PotentialBusPart = 22, + /// + /// 通过接受微信账号收到的好友申请添加 + /// + [Description("通过接受微信账号收到的好友申请添加")] + WeChatFriendRequest = 24, + /// + /// 内部成员共享 + /// + [Description("内部成员共享")] + SharedByInternalMembers = 201, + /// + /// 管理员/负责人分配 + /// + [Description("管理员/负责人分配")] + AllocationByAdmin = 202 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTag.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTag.cs new file mode 100644 index 000000000..d11bfbd9c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTag.cs @@ -0,0 +1,39 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 外部联系人所打标签 +/// +public class FollowUserTag +{ + /// + /// 该成员添加此外部联系人所打标签的分组名称 + /// + [CanBeNull] + [JsonProperty("group_name")] + [JsonPropertyName("group_name")] + public string? GroupName { get; set; } + /// + /// 该成员添加此外部联系人所打标签名称 + /// + [NotNull] + [JsonProperty("tag_name")] + [JsonPropertyName("tag_name")] + public string TagName { get; set; } + /// + /// 该成员添加此外部联系人所打标签类型 + /// + [NotNull] + [JsonProperty("type")] + [JsonPropertyName("type")] + public FollowUserTagType Type { get; set; } + /// + /// 该成员添加此外部联系人所打企业标签的id,用户自定义类型标签(type=2)不返回 + /// + [CanBeNull] + [JsonProperty("tag_id")] + [JsonPropertyName("tag_id")] + public string? TagId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTagType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTagType.cs new file mode 100644 index 000000000..d8a91a4f6 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserTagType.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 标签类型 +/// +[Description("标签类型")] +public enum FollowUserTagType +{ + /// + /// 企业设置 + /// + [Description("企业设置")] + EnterpriseSettings = 1, + /// + /// 用户自定义 + /// + [Description("用户自定义")] + UserCustom = 2, + /// + /// 规则组标签 + /// + [Description("规则组标签")] + RuleGroupTags = 3, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannel.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannel.cs new file mode 100644 index 000000000..b1a1b6b26 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannel.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 视频号信息 +/// +public class FollowUserWechatChannel +{ + /// + /// 视频号名称 + /// + [NotNull] + [JsonProperty("nickname")] + [JsonPropertyName("nickname")] + public string NickName { get; set; } + /// + /// 视频号添加场景 + /// + [NotNull] + [JsonProperty("source")] + [JsonPropertyName("source")] + public FollowUserWechatChannelSource Source { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannelSource.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannelSource.cs new file mode 100644 index 000000000..fa8eb3433 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Models/FollowUserWechatChannelSource.cs @@ -0,0 +1,30 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +/// +/// 视频号添加场景 +/// +[Description("视频号添加场景")] +public enum FollowUserWechatChannelSource +{ + /// + /// 未知 + /// + [Description("未知")] + None = 0, + /// + /// 视频号主页 + /// + [Description("视频号主页")] + Home = 1, + /// + /// 视频号直播间 + /// + [Description("视频号直播间")] + LiveRoom = 2, + /// + /// 视频号留资服务 + /// + [Description("视频号留资服务")] + RetentionService = 3 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkBulkGetCustomerRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkBulkGetCustomerRequest.cs new file mode 100644 index 000000000..48b84ab1a --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkBulkGetCustomerRequest.cs @@ -0,0 +1,55 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 创建新的规则组请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkBulkGetCustomerRequest : WeChatWorkRequest +{ + /// + /// 企业成员的userid列表,字符串类型,最多支持100个 + /// + [NotNull] + [JsonProperty("userid_list")] + [JsonPropertyName("userid_list")] + public List UserIds { get; } + /// + /// 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用可不填 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; } + /// + /// 返回的最大记录数,整型,最大值100,默认值50,超过最大值时取最大值 + /// + [CanBeNull] + [JsonProperty("limit")] + [JsonPropertyName("limit")] + public int Limit { get; } + public WeChatWorkBulkGetCustomerRequest( + List userIds, + string? cursor = null, + int limit = 50) + { + Check.NotNullOrEmpty(userIds, nameof(userIds)); + Check.Range(limit, nameof(limit), 1, 100); + + if (userIds.Count > 100) + { + throw new ArgumentException("The maximum number of userIds allowed in the list is only 100!"); + } + + UserIds = userIds; + Cursor = cursor; + Limit = limit; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkCreateCustomerStrategyRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkCreateCustomerStrategyRequest.cs new file mode 100644 index 000000000..1fa6506cb --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkCreateCustomerStrategyRequest.cs @@ -0,0 +1,74 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 批量获取客户详情请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkCreateCustomerStrategyRequest : WeChatWorkRequest +{ + /// + /// 父规则组id + /// + [CanBeNull] + [JsonProperty("parent_id")] + [JsonPropertyName("parent_id")] + public int? ParentId { get; set; } + /// + /// 规则组名称 + /// + [NotNull] + [JsonProperty("strategy_name")] + [JsonPropertyName("strategy_name")] + public string StrategyName { get; } + /// + /// 规则组管理员userid列表 + /// + [NotNull] + [JsonProperty("admin_list")] + [JsonPropertyName("admin_list")] + public string[] AdminList { get; } + /// + /// 规则组权限 + /// + [NotNull] + [JsonProperty("privilege")] + [JsonPropertyName("privilege")] + public CustomerStrategyPrivilege Privilege { get; } + /// + /// 规则组管理范围 + /// + [NotNull] + [JsonProperty("range")] + [JsonPropertyName("range")] + public CustomerStrategyRange[] Range { get; } + public WeChatWorkCreateCustomerStrategyRequest( + string strategyName, + string[] adminList, + CustomerStrategyPrivilege? privilege = null, + CustomerStrategyRange[]? range = null) + { + Check.NotNullOrWhiteSpace(strategyName, nameof(strategyName)); + Check.NotNullOrEmpty(adminList, nameof(adminList)); + + if (adminList.Length > 20) + { + throw new ArgumentException("Up to 20 admin list can be configured at a time!"); + } + if (range != null && range.Length > 100) + { + throw new ArgumentException("Up to 100 management range can be configured at a time!"); + } + + StrategyName = strategyName; + AdminList = adminList; + Privilege = privilege ?? CustomerStrategyPrivilege.Default(); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkDeleteCustomerStrategyRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkDeleteCustomerStrategyRequest.cs new file mode 100644 index 000000000..961e2fed6 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkDeleteCustomerStrategyRequest.cs @@ -0,0 +1,28 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 删除规则组请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkDeleteCustomerStrategyRequest : WeChatWorkRequest +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; } + public WeChatWorkDeleteCustomerStrategyRequest(int strategyId) + { + Check.NotDefaultOrNull(strategyId, nameof(strategyId)); + + StrategyId = strategyId; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyListRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyListRequest.cs new file mode 100644 index 000000000..1b5240c7b --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyListRequest.cs @@ -0,0 +1,39 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 获取规则组列表请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerStrategyListRequest : WeChatWorkRequest +{ + /// + /// 分页查询游标,首次调用可不填 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; } + /// + /// 分页大小,默认为1000,最大不超过1000 + /// + [CanBeNull] + [JsonProperty("limit")] + [JsonPropertyName("limit")] + public int? Limit { get; } + public WeChatWorkGetCustomerStrategyListRequest(string? cursor = null, int? limit = 1000) + { + if (limit.HasValue) + { + Check.Range(limit.Value, nameof(limit), 1, 1000); + } + + Cursor = cursor; + Limit = limit; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRangeRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRangeRequest.cs new file mode 100644 index 000000000..415990088 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRangeRequest.cs @@ -0,0 +1,47 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 获取规则组管理范围请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerStrategyRangeRequest : WeChatWorkRequest +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; } + /// + /// 分页查询游标,首次调用可不填 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; } + /// + /// 每个分页的成员/部门节点数,默认为1000,最大为1000 + /// + [CanBeNull] + [JsonProperty("limit")] + [JsonPropertyName("limit")] + public int? Limit { get; } + public WeChatWorkGetCustomerStrategyRangeRequest(int strategyId, string? cursor = null, int? limit = 1000) + { + if (limit.HasValue) + { + Check.Range(limit.Value, nameof(limit), 1, 1000); + } + + StrategyId = strategyId; + Cursor = cursor; + Limit = limit; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRequest.cs new file mode 100644 index 000000000..1efbfb196 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkGetCustomerStrategyRequest.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 获取规则组请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerStrategyRequest : WeChatWorkRequest +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; } + public WeChatWorkGetCustomerStrategyRequest(int strategyId) + { + StrategyId = strategyId; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerRemarkRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerRemarkRequest.cs new file mode 100644 index 000000000..9501a670d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerRemarkRequest.cs @@ -0,0 +1,86 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 修改客户备注信息请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkUpdateCustomerRemarkRequest : WeChatWorkRequest +{ + /// + /// 企业成员的userid + /// + [NotNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string UserId { get; } + /// + /// 外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserId { get; } + /// + /// 此用户对外部联系人的备注,最多20个字符 + /// + [CanBeNull] + [StringLength(20)] + [JsonProperty("remark")] + [JsonPropertyName("remark")] + public string? Remark { get; } + /// + /// 此用户对外部联系人的描述,最多150个字符 + /// + [CanBeNull] + [StringLength(150)] + [JsonProperty("description")] + [JsonPropertyName("description")] + public string? Description { get; } + /// + /// 此用户对外部联系人备注的所属公司名称,最多20个字符 + /// + [CanBeNull] + [StringLength(20)] + [JsonProperty("remark_company")] + [JsonPropertyName("remark_company")] + public string? RemarkCompany { get; } + /// + /// 此用户对外部联系人备注的手机号 + /// + [CanBeNull] + [JsonProperty("remark_mobiles")] + [JsonPropertyName("remark_mobiles")] + public List? RemarkMobiles { get; } + /// + /// 备注图片的mediaid + /// + [CanBeNull] + [JsonProperty("remark_pic_mediaid")] + [JsonPropertyName("remark_pic_mediaid")] + public string? RemarkPictureMediaId { get; } + public WeChatWorkUpdateCustomerRemarkRequest( + string userId, + string externalUserId, + string? remark = null, + string? description = null, + string? remarkCompany = null, + List? remarkMobiles = null, + string? remarkPictureMediaId = null) + { + UserId = Check.NotNullOrWhiteSpace(userId, nameof(userId)); + ExternalUserId = Check.NotNullOrWhiteSpace(externalUserId, nameof(externalUserId)); + Remark = Check.Length(remark, nameof(remark), 20); + Description = Check.Length(description, nameof(description), 150); + RemarkCompany = Check.Length(remarkCompany, nameof(remarkCompany), 20); + RemarkMobiles = remarkMobiles; + RemarkPictureMediaId = remarkPictureMediaId; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerStrategyRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerStrategyRequest.cs new file mode 100644 index 000000000..5167d3130 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Request/WeChatWorkUpdateCustomerStrategyRequest.cs @@ -0,0 +1,75 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +/// +/// 编辑规则组及其管理范围请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkUpdateCustomerStrategyRequest : WeChatWorkRequest +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; } + /// + /// 规则组名称 + /// + [CanBeNull] + [JsonProperty("strategy_name")] + [JsonPropertyName("strategy_name")] + public string? StrategyName { get; set; } + /// + /// 规则组管理员userid列表 + /// + [CanBeNull] + [JsonProperty("admin_list")] + [JsonPropertyName("admin_list")] + public string[]? AdminList { get; set; } + /// + /// 规则组权限 + /// + [CanBeNull] + [JsonProperty("privilege")] + [JsonPropertyName("privilege")] + public CustomerStrategyPrivilege? Privilege { get; set; } + /// + /// 新增管理范围 + /// + [NotNull] + [JsonProperty("range_add")] + [JsonPropertyName("range_add")] + public List CreateRange { get; private set; } + /// + /// 删除管理范围 + /// + [NotNull] + [JsonProperty("range_del")] + [JsonPropertyName("range_del")] + public List DeleteRange { get; private set; } + public WeChatWorkUpdateCustomerStrategyRequest( + int strategyId, + string? strategyName = null, + string[]? adminList = null, + CustomerStrategyPrivilege? privilege = null) + { + Check.NotDefaultOrNull(strategyId, nameof(strategyId)); + + StrategyId = strategyId; + StrategyName = strategyName; + AdminList = adminList; + Privilege = privilege; + + CreateRange = new List(); + DeleteRange = new List(); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkBulkGetCustomerResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkBulkGetCustomerResponse.cs new file mode 100644 index 000000000..75780677a --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkBulkGetCustomerResponse.cs @@ -0,0 +1,48 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 批量获取客户详情响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkBulkGetCustomerResponse : WeChatWorkResponse +{ + /// + /// 外部联系人的userid列表 + /// + [NotNull] + [JsonProperty("external_contact_list")] + [JsonPropertyName("external_contact_list")] + public List ExternalUserId { get; set; } = new List(); + /// + /// 分页游标,再下次请求时填写以获取之后分页的记录,如果已经没有更多的数据则返回空 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } + /// + /// 若请求中所有userid都无有效互通许可,接口直接报错701008。如果部分userid无有效互通许可,接口返回成功 + /// + [CanBeNull] + [JsonProperty("fail_info")] + [JsonPropertyName("fail_info")] + public WeChatWorkBulkGetCustomerFailInfo? FailInfo { get; set; } +} + +public class WeChatWorkBulkGetCustomerFailInfo +{ + /// + /// 无许可的userid列表 + /// + [NotNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public List UnlicensedUseridList { get; set; } = new List(); +} \ No newline at end of file diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkCreateCustomerStrategyResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkCreateCustomerStrategyResponse.cs new file mode 100644 index 000000000..f6aec2f00 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkCreateCustomerStrategyResponse.cs @@ -0,0 +1,21 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 创建新的规则组响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkCreateCustomerStrategyResponse : WeChatWorkResponse +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerListResponse.cs new file mode 100644 index 000000000..4f16db664 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerListResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 获取客户列表响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerListResponse : WeChatWorkResponse +{ + /// + /// 外部联系人的userid列表 + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public List ExternalUserId { get; set; } = new List(); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerResponse.cs new file mode 100644 index 000000000..d465abe38 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerResponse.cs @@ -0,0 +1,37 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 获取客户详情响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerResponse : WeChatWorkResponse +{ + /// + /// 外部联系人信息 + /// + [NotNull] + [JsonProperty("external_contact")] + [JsonPropertyName("external_contact")] + public ExternalContactInfo ExternalContact { get; set; } + /// + /// 添加了此外部联系人的企业成员 + /// + [NotNull] + [JsonProperty("follow_user")] + [JsonPropertyName("follow_user")] + public List FollowUser { get; set; } + /// + /// 分页的cursor,当跟进人多于500人时返回 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyListResponse.cs new file mode 100644 index 000000000..b386da41c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyListResponse.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 获取规则组列表响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerStrategyListResponse : WeChatWorkResponse +{ + /// + /// 规则组列表 + /// + [NotNull] + [JsonProperty("strategy")] + [JsonPropertyName("strategy")] + public CustomerStrategy[] Strategy { get; set; } + /// + /// 分页游标,用于查询下一个分页的数据,无更多数据时不返回 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyRangeResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyRangeResponse.cs new file mode 100644 index 000000000..0c7c715cd --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyRangeResponse.cs @@ -0,0 +1,30 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 获取规则组管理范围响应参数 +/// +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerStrategyRangeResponse : WeChatWorkResponse +{ + /// + /// 规则组管理范围 + /// + [NotNull] + [JsonProperty("range")] + [JsonPropertyName("range")] + public CustomerStrategyRange[] Range { get; set; } + /// + /// 分页游标,用于查询下一个分页的数据,无更多数据时不返回 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyResponse.cs new file mode 100644 index 000000000..0b3eba400 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/Response/WeChatWorkGetCustomerStrategyResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +/// +/// 获取规则组详情响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCustomerStrategyResponse : WeChatWorkResponse +{ + /// + /// 规则组详情 + /// + [NotNull] + [JsonProperty("strategy")] + [JsonPropertyName("strategy")] + public CustomerStrategyInfo Strategy { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider.cs new file mode 100644 index 000000000..eb242ed94 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider.cs @@ -0,0 +1,93 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkCustomerProvider : IWeChatWorkCustomerProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkCustomerProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetCustomerListAsync( + string userId, + CancellationToken cancellationToken = default) + { + Check.NotNullOrWhiteSpace(userId, nameof(userId)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetCustomerListAsync(token.AccessToken, userId, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task BulkGetCustomerAsync( + WeChatWorkBulkGetCustomerRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.BulkGetCustomerAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GetCustomerAsync( + string externalUserid, + string? cursor = null, + CancellationToken cancellationToken = default) + { + Check.NotNullOrWhiteSpace(externalUserid, nameof(externalUserid)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetCustomerAsync(token.AccessToken, externalUserid, cursor, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task UpdateCustomerRemarkAsync( + WeChatWorkUpdateCustomerRemarkRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.UpdateCustomerRemarkAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider.cs new file mode 100644 index 000000000..f2984bb5f --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider.cs @@ -0,0 +1,111 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Response; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkCustomerStrategyProvider : IWeChatWorkCustomerStrategyProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkCustomerStrategyProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetCustomerStrategyListAsync( + WeChatWorkGetCustomerStrategyListRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetCustomerStrategyListAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GetCustomerStrategyAsync( + WeChatWorkGetCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetCustomerStrategyAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GetCustomerStrategyRangeAsync( + WeChatWorkGetCustomerStrategyRangeRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetCustomerStrategyRangeAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task CreateCustomerStrategyAsync( + WeChatWorkCreateCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.CreateCustomerStrategyAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task UpdateCustomerStrategyAsync( + WeChatWorkUpdateCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.UpdateCustomerStrategyAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task DeleteCustomerStrategyAsync( + WeChatWorkDeleteCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.DeleteCustomerStrategyAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureDefinitionProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureDefinitionProvider.cs new file mode 100644 index 000000000..d516615eb --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureDefinitionProvider.cs @@ -0,0 +1,31 @@ +using LINGYUN.Abp.WeChat.Work.Features; +using LINGYUN.Abp.WeChat.Work.Localization; +using Volo.Abp.Features; +using Volo.Abp.Localization; +using Volo.Abp.Validation.StringValues; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +public class WeChatWorkExternalContactFeatureDefinitionProvider : FeatureDefinitionProvider +{ + public override void Define(IFeatureDefinitionContext context) + { + var weChatFeature = context.GetGroupOrNull(WeChatWorkFeatureNames.GroupName); + if (weChatFeature == null) + { + return; + } + + var group = weChatFeature.AddFeature(WeChatWorkExternalContactFeatureNames.GroupName); + group.CreateChild( + WeChatWorkExternalContactFeatureNames.Enable, + defaultValue: "false", + displayName: L("Features:ExternalContactEnable"), + description: L("Features:ExternalContactEnableDesc"), + valueType: new ToggleStringValueType(new BooleanValueValidator())); + } + + private static LocalizableString L(string name) + { + return LocalizableString.Create(name); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureNames.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureNames.cs new file mode 100644 index 000000000..9a9a1b259 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Features/WeChatWorkExternalContactFeatureNames.cs @@ -0,0 +1,14 @@ +using LINGYUN.Abp.WeChat.Work.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +/// +/// 企业微信客户联系模块功能 +/// +public static class WeChatWorkExternalContactFeatureNames +{ + public const string GroupName = WeChatWorkFeatureNames.GroupName + ".ExternalContact"; + /// + /// 启用企业微信客户联系 + /// + public const string Enable = GroupName + ".Enable"; +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/IWeChatWorkFollowUserProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/IWeChatWorkFollowUserProvider.cs new file mode 100644 index 000000000..5772d7a9e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/IWeChatWorkFollowUserProvider.cs @@ -0,0 +1,20 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Follows.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Follows; +/// +/// 企业服务人员管理接口 +/// +public interface IWeChatWorkFollowUserProvider +{ + /// + /// 获取配置了客户联系功能的成员列表 + /// + /// + /// 详情见: + /// + /// + /// + Task GetFollowUserListAsync(CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/Response/WeChatWorkGetFollowUserListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/Response/WeChatWorkGetFollowUserListResponse.cs new file mode 100644 index 000000000..ff0c5d728 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/Response/WeChatWorkGetFollowUserListResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Follows.Response; +/// +/// 获取配置了客户联系功能的成员列表响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetFollowUserListResponse : WeChatWorkResponse +{ + /// + /// 配置了客户联系功能的成员userid列表 + /// + [NotNull] + [JsonProperty("follow_user")] + [JsonPropertyName("follow_user")] + public List FollowUser { get; set; } = new List(); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider.cs new file mode 100644 index 000000000..0391d6b7e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider.cs @@ -0,0 +1,38 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Follows.Response; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Follows; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkFollowUserProvider : IWeChatWorkFollowUserProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkFollowUserProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetFollowUserListAsync(CancellationToken cancellationToken = default) + { + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetFollowUserListAsync(token.AccessToken, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/IWeChatWorkGroupChatProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/IWeChatWorkGroupChatProvider.cs new file mode 100644 index 000000000..d0cf7d078 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/IWeChatWorkGroupChatProvider.cs @@ -0,0 +1,48 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats; +/// +/// 客户群管理接口 +/// +public interface IWeChatWorkGroupChatProvider +{ + /// + /// 获取客户群列表 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetGroupChatListAsync( + WeChatWorkGetGroupChatListRequest request, + CancellationToken cancellationToken = default); + /// + /// 获取客户群详情 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetGroupChatAsync( + WeChatWorkGetGroupChatRequest request, + CancellationToken cancellationToken = default); + /// + /// 客户群opengid转换 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task OpengIdToChatIdAsync( + WeChatWorkOpengIdToChatIdRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChat.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChat.cs new file mode 100644 index 000000000..e9d6f34bb --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChat.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 客户群 +/// +public class GroupChat +{ + /// + /// 客户群ID + /// + [NotNull] + [JsonProperty("chat_id")] + [JsonPropertyName("chat_id")] + public string ChatId { get; set; } + /// + /// 客户群跟进状态 + /// + [NotNull] + [JsonProperty("status")] + [JsonPropertyName("status")] + public GroupChatStatus Status { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInfo.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInfo.cs new file mode 100644 index 000000000..84c173240 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInfo.cs @@ -0,0 +1,67 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 客户群详情 +/// +public class GroupChatInfo +{ + /// + /// 客户群ID + /// + [NotNull] + [JsonProperty("chat_id")] + [JsonPropertyName("chat_id")] + public string ChatId { get; set; } + /// + /// 群名 + /// + [NotNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string Name { get; set; } + /// + /// 群主ID + /// + [NotNull] + [JsonProperty("owner")] + [JsonPropertyName("owner")] + public string Owner { get; set; } + /// + /// 群的创建时间 + /// + [NotNull] + [JsonProperty("create_time")] + [JsonPropertyName("create_time")] + public long CreateTime { get; set; } + /// + /// 群公告 + /// + [CanBeNull] + [JsonProperty("notice")] + [JsonPropertyName("notice")] + public string Notice { get; set; } + /// + /// 群成员列表 + /// + [NotNull] + [JsonProperty("member_list")] + [JsonPropertyName("member_list")] + public GroupChatMember[] MemberList { get; set; } + /// + /// 群管理员列表 + /// + [NotNull] + [JsonProperty("admin_list")] + [JsonPropertyName("admin_list")] + public GroupChatManager[] AdminList { get; set; } + /// + /// 当前群成员版本号。可以配合客户群变更事件减少主动调用本接口的次数 + /// + [NotNull] + [JsonProperty("member_version")] + [JsonPropertyName("member_version")] + public string MemberVersion { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInvitor.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInvitor.cs new file mode 100644 index 000000000..201decd88 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatInvitor.cs @@ -0,0 +1,18 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 邀请者 +/// +public class GroupChatInvitor +{ + /// + /// 邀请者的userid + /// + [NotNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string UserId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatManager.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatManager.cs new file mode 100644 index 000000000..1a53a0781 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatManager.cs @@ -0,0 +1,18 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 群管理员 +/// +public class GroupChatManager +{ + /// + /// 群管理员userid + /// + [NotNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string UserId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMember.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMember.cs new file mode 100644 index 000000000..937f07841 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMember.cs @@ -0,0 +1,70 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 群成员 +/// +public class GroupChatMember +{ + /// + /// 群成员id + /// + [NotNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string UserId { get; set; } + /// + /// 成员类型 + /// + [NotNull] + [JsonProperty("type")] + [JsonPropertyName("type")] + public GroupChatMemberType Type { get; set; } + /// + /// 外部联系人在微信开放平台的唯一身份标识(微信unionid),通过此字段企业可将外部联系人与公众号/小程序用户关联起来。
+ /// 仅当群成员类型是微信用户(包括企业成员未添加好友),且企业绑定了微信开发者ID有此字段 + ///
+ [CanBeNull] + [JsonProperty("unionid")] + [JsonPropertyName("unionid")] + public string? UnionId { get; set; } + /// + /// 入群时间 + /// + [NotNull] + [JsonProperty("join_time")] + [JsonPropertyName("join_time")] + public long JoinTime { get; set; } + /// + /// 入群方式 + /// + [NotNull] + [JsonProperty("join_scene")] + [JsonPropertyName("join_scene")] + public GroupChatMemberJoinScene JoinScene { get; set; } + /// + /// 邀请者。目前仅当是由本企业内部成员邀请入群时会返回该值 + /// + [CanBeNull] + [JsonProperty("invitor")] + [JsonPropertyName("invitor")] + public GroupChatInvitor? Invitor { get; set; } + /// + /// 在群里的昵称 + /// + [CanBeNull] + [JsonProperty("group_nickname")] + [JsonPropertyName("group_nickname")] + public string? GroupNickname { get; set; } + /// + /// 名字。仅当 need_name = 1 时返回
+ /// 如果是微信用户,则返回其在微信中设置的名字
+ /// 如果是企业微信联系人,则返回其设置对外展示的别名或实名 + ///
+ [CanBeNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string? Name { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberJoinScene.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberJoinScene.cs new file mode 100644 index 000000000..8163b711c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberJoinScene.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 入群方式 +/// +[Description("入群方式")] +public enum GroupChatMemberJoinScene +{ + /// + /// 由群成员邀请入群(直接邀请入群) + /// + [Description("直接邀请入群")] + DirectInvitation = 1, + /// + /// 由群成员邀请入群(通过邀请链接入群) + /// + [Description("通过邀请链接入群")] + InvitationLink = 2, + /// + /// 通过扫描群二维码入群 + /// + [Description("通过扫描群二维码入群")] + ScanQrCode = 3, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberType.cs new file mode 100644 index 000000000..f8f4a6219 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatMemberType.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 成员类型 +/// +[Description("成员类型")] +public enum GroupChatMemberType +{ + /// + /// 企业成员 + /// + [Description("企业成员")] + Internal = 1, + /// + /// 外部联系人 + /// + [Description("外部联系人")] + External = 2 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatStatus.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatStatus.cs new file mode 100644 index 000000000..5393313cd --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/GroupChatStatus.cs @@ -0,0 +1,30 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 客户群跟进状态 +/// +[Description("客户群跟进状态")] +public enum GroupChatStatus +{ + /// + /// 跟进人正常 + /// + [Description("跟进人正常")] + Normal = 0, + /// + /// 跟进人离职 + /// + [Description("跟进人离职")] + Leaves = 1, + /// + /// 离职继承中 + /// + [Description("离职继承中")] + Resiging = 2, + /// + /// 离职继承完成 + /// + [Description(" 离职继承完成")] + ResignCompleted = 3, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/OwnerFilter.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/OwnerFilter.cs new file mode 100644 index 000000000..bd0bc24c8 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/OwnerFilter.cs @@ -0,0 +1,31 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 群主过滤 +/// +public class OwnerFilter +{ + /// + /// 用户ID列表。最多100个 + /// + [NotNull] + [JsonProperty("userid_list")] + [JsonPropertyName("userid_list")] + public string[] UserIdList { get; } + public OwnerFilter(string[] userIdList) + { + Check.NotNullOrEmpty(userIdList, nameof(userIdList)); + + if (userIdList.Length > 100) + { + throw new ArgumentException("The maximum number of parameters allowed for group owner filtering is only 100!"); + } + + UserIdList = userIdList; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/StatusFilter.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/StatusFilter.cs new file mode 100644 index 000000000..e4d78e910 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Models/StatusFilter.cs @@ -0,0 +1,30 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +/// +/// 客户群跟进状态过滤 +/// +[Description("客户群跟进状态过滤")] +public enum StatusFilter +{ + /// + /// 所有列表 + /// + [Description("所有列表")] + All = 0, + /// + /// 跟进人离职 + /// + [Description("跟进人离职")] + Leaves = 1, + /// + /// 离职继承中 + /// + [Description("离职继承中")] + Resiging = 2, + /// + /// 离职继承完成 + /// + [Description(" 离职继承完成")] + ResignCompleted = 3, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatListRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatListRequest.cs new file mode 100644 index 000000000..5c86a3e9d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatListRequest.cs @@ -0,0 +1,50 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +/// +/// 获取客户群列表请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetGroupChatListRequest : WeChatWorkRequest +{ + /// + /// 客户群跟进状态过滤 + /// + [CanBeNull] + [JsonProperty("status_filter")] + [JsonPropertyName("status_filter")] + public StatusFilter? StatusFilter { get; set; } + /// + /// 客户群跟进状态过滤 + /// + [CanBeNull] + [JsonProperty("owner_filter")] + [JsonPropertyName("owner_filter")] + public OwnerFilter[]? OwnerFilter { get; set; } + /// + /// 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用不填 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; set; } + /// + /// 分页,预期请求的数据量,取值范围 1 ~ 1000 + /// + [CanBeNull] + [JsonProperty("limit")] + [JsonPropertyName("limit")] + public int Limit { get; } + public WeChatWorkGetGroupChatListRequest(int limit = 1000) + { + Check.Range(limit, nameof(limit), 1, 1000); + + Limit = limit; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatRequest.cs new file mode 100644 index 000000000..4949e0d87 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkGetGroupChatRequest.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +/// +/// 获取客户群详情 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetGroupChatRequest : WeChatWorkRequest +{ + /// + /// 客户群ID + /// + [NotNull] + [JsonProperty("chat_id")] + [JsonPropertyName("chat_id")] + public string ChatId { get; } + /// + /// 是否需要返回群成员的名字group_chat.member_list.name。0-不返回;1-返回。默认不返回 + /// + [CanBeNull] + [JsonProperty("need_name")] + [JsonPropertyName("need_name")] + public int? NeedName { get; } + public WeChatWorkGetGroupChatRequest(string chatId, bool needName = false) + { + Check.NotNullOrWhiteSpace(chatId, nameof(chatId)); + + ChatId = chatId; + NeedName = needName ? 1 : 0; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkOpengIdToChatIdRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkOpengIdToChatIdRequest.cs new file mode 100644 index 000000000..0c3343a3f --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Request/WeChatWorkOpengIdToChatIdRequest.cs @@ -0,0 +1,28 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +/// +/// 客户群opengid转换请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkOpengIdToChatIdRequest : WeChatWorkRequest +{ + /// + /// 小程序在微信获取到的群ID + /// + [NotNull] + [JsonProperty("opengid")] + [JsonPropertyName("opengid")] + public string OpengId { get; } + public WeChatWorkOpengIdToChatIdRequest(string opengId) + { + Check.NotNullOrWhiteSpace(opengId, nameof(opengId)); + + OpengId = opengId; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatListResponse.cs new file mode 100644 index 000000000..1a0d2b81e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatListResponse.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Response; +/// +/// 获取客户群列表响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetGroupChatListResponse : WeChatWorkResponse +{ + /// + /// 客户群列表 + /// + [NotNull] + [JsonProperty("group_chat_list")] + [JsonPropertyName("group_chat_list")] + public GroupChat[] GroupChatList { get; set; } + /// + /// 分页游标,下次请求时填写以获取之后分页的记录。如果该字段返回空则表示已没有更多数据 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatResponse.cs new file mode 100644 index 000000000..8f58bbfb3 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkGetGroupChatResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Response; +/// +/// 获取客户群详情响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetGroupChatResponse : WeChatWorkResponse +{ + /// + /// 客户群详情 + /// + [NotNull] + [JsonProperty("group_chat")] + [JsonPropertyName("group_chat")] + public GroupChatInfo GroupChat { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkOpengIdToChatIdResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkOpengIdToChatIdResponse.cs new file mode 100644 index 000000000..ab1b981d5 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/Response/WeChatWorkOpengIdToChatIdResponse.cs @@ -0,0 +1,21 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Response; +/// +/// 客户群opengid转换响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkOpengIdToChatIdResponse : WeChatWorkResponse +{ + /// + /// 客户群ID,可以用来调用获取客户群详情 + /// + [NotNull] + [JsonProperty("chat_id")] + [JsonPropertyName("chat_id")] + public string ChatId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider.cs new file mode 100644 index 000000000..6600d08a9 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider.cs @@ -0,0 +1,76 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Response; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkGroupChatProvider : IWeChatWorkGroupChatProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkGroupChatProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetGroupChatListAsync( + WeChatWorkGetGroupChatListRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetGroupChatListAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GetGroupChatAsync( + WeChatWorkGetGroupChatRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetGroupChatAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task OpengIdToChatIdAsync( + WeChatWorkOpengIdToChatIdRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.OpengIdToChatIdAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/en.json b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/en.json new file mode 100644 index 000000000..555a57daa --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/en.json @@ -0,0 +1,7 @@ +{ + "culture": "en", + "texts": { + "Features:ExternalContactEnable": "Enable External Contact", + "Features:ExternalContactEnableDesc": "Enable the ability to provide the application with an Enterprise wechat customer contact interface." + } +} \ No newline at end of file diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/zh-Hans.json b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/zh-Hans.json new file mode 100644 index 000000000..038e57240 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Localization/Resources/zh-Hans.json @@ -0,0 +1,7 @@ +{ + "culture": "zh-Hans", + "texts": { + "Features:ExternalContactEnable": "启用客户联系", + "Features:ExternalContactEnableDesc": "启用以使应用拥有企业微信客户联系接口的能力." + } +} \ No newline at end of file diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChaDelMemberEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChaDelMemberEvent.cs new file mode 100644 index 000000000..c5ff046e8 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChaDelMemberEvent.cs @@ -0,0 +1,25 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群成员退群事件推送 +/// +[EventName("external_chat_del_member")] +public class ExternalChaDelMemberEvent : ExternalChatChangeMemberEvent +{ + /// + /// 当是成员退群时有值。表示成员的退群方式
+ /// 0 - 自己退群
+ /// 1 - 群主/群管理员移出
+ ///
+ [XmlElement("QuitScene")] + public ExternalChatMemberQuitScene QuitScene { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatAddMemberEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatAddMemberEvent.cs new file mode 100644 index 000000000..ebd36da90 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatAddMemberEvent.cs @@ -0,0 +1,25 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群成员入群事件推送 +/// +[EventName("external_chat_add_member")] +public class ExternalChatAddMemberEvent : ExternalChatChangeMemberEvent +{ + /// + /// 当是成员入群时有值。表示成员的入群方式
+ /// 0 - 由成员邀请入群(包括直接邀请入群和通过邀请链接入群)
+ /// 3 - 通过扫描群二维码入群
+ ///
+ [XmlElement("JoinScene")] + public ExternalChatMemberJoinScene JoinScene { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeEvent.cs new file mode 100644 index 000000000..9e7ab1eb6 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeEvent.cs @@ -0,0 +1,21 @@ +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群变更事件推送 +/// +public abstract class ExternalChatChangeEvent : WeChatWorkEventMessage +{ + /// + /// 变更类型 + /// + [XmlElement("ChangeType")] + public string ChangeType { get; set; } + /// + /// 群ID + /// + [XmlElement("ChatId")] + public string ChatId { get; set; } +} + diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeMemberEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeMemberEvent.cs new file mode 100644 index 000000000..b64e10b84 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeMemberEvent.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using System.Xml.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群成员变更事件推送 +/// +public abstract class ExternalChatChangeMemberEvent : ExternalChatUpdateEvent +{ + /// + /// 成员变更数量 + /// + [XmlElement("MemChangeCnt")] + public int MemChangeCnt { get; set; } + /// + /// 变更的成员列表 + /// + [XmlElement("MemChangeList")] + public List MemChangeList { get; set; } = new List(); + /// + /// 变更前的群成员版本号 + /// + [XmlElement("LastMemVer")] + public string LastMemVer { get; set; } + /// + /// 变更后的群成员版本号 + /// + [XmlElement("CurMemVer")] + public string CurMemVer { get; set; } +} + +public class ExternalChatChangeMember +{ + /// + /// 成员Id + /// + [XmlElement("Item")] + public string UserId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNameEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNameEvent.cs new file mode 100644 index 000000000..e3480f2a7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNameEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群群名变更事件推送 +/// +[EventName("external_chat_change_name")] +public class ExternalChatChangeNameEvent : ExternalChatUpdateEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNoticeEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNoticeEvent.cs new file mode 100644 index 000000000..ec7d5d485 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeNoticeEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群群公告变更事件推送 +/// +[EventName("external_chat_change_notice")] +public class ExternalChatChangeNoticeEvent : ExternalChatUpdateEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeOwnerEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeOwnerEvent.cs new file mode 100644 index 000000000..ad955f907 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatChangeOwnerEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群群主变更事件推送 +/// +[EventName("external_chat_change_owner")] +public class ExternalChatChangeOwnerEvent : ExternalChatUpdateEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatCreateEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatCreateEvent.cs new file mode 100644 index 000000000..417082072 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatCreateEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群创建事件推送 +/// +[EventName("external_chat_create")] +public class ExternalChatCreateEvent : ExternalChatChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatDismissEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatDismissEvent.cs new file mode 100644 index 000000000..e3fa20623 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatDismissEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群解散事件推送 +/// +[EventName("external_chat_dismiss")] +public class ExternalChatDismissEvent : ExternalChatChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberJoinScene.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberJoinScene.cs new file mode 100644 index 000000000..1eb129638 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberJoinScene.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 成员的入群方式 +/// +[Description("成员的入群方式")] +public enum ExternalChatMemberJoinScene +{ + /// + /// 由成员邀请入群 + /// + [Description("由成员邀请入群")] + MemberInvitation = 0, + /// + /// 通过扫描群二维码入群 + /// + [Description("通过扫描群二维码入群")] + ScanQrCode = 3 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberQuitScene.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberQuitScene.cs new file mode 100644 index 000000000..1a02803ac --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatMemberQuitScene.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 成员的退群方式 +/// +[Description("成员的退群方式")] +public enum ExternalChatMemberQuitScene +{ + /// + /// 自己退群 + /// + [Description("自己退群")] + UserSelf = 0, + /// + /// 群主/群管理员移出 + /// + [Description("群主/群管理员移出")] + Admin = 1 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatUpdateEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatUpdateEvent.cs new file mode 100644 index 000000000..7b981dcdf --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalChatUpdateEvent.cs @@ -0,0 +1,19 @@ +using System.Xml.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户群变更事件推送 +/// +public abstract class ExternalChatUpdateEvent : ExternalChatChangeEvent +{ + /// + /// 变更详情。目前有以下几种:
+ /// add_member : 成员入群
+ /// del_member : 成员退群
+ /// change_owner : 群主变更
+ /// change_name : 群名变更
+ /// change_notice : 群公告变更 + ///
+ [XmlElement("UpdateDetail")] + public string UpdateDetail { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactChangeEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactChangeEvent.cs new file mode 100644 index 000000000..9d6fe930c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactChangeEvent.cs @@ -0,0 +1,25 @@ +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 企业客户变更事件推送 +/// +public abstract class ExternalContactChangeEvent : WeChatWorkEventMessage +{ + /// + /// 变更类型 + /// + [XmlElement("ChangeType")] + public string ChangeType { get; set; } + /// + /// 企业服务人员的UserID + /// + [XmlElement("UserID")] + public string UserId { get; set; } + /// + /// 外部联系人的userid,注意不是企业成员的账号 + /// + [XmlElement("ExternalUserID")] + public string ExternalUserId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateEvent.cs new file mode 100644 index 000000000..03ddacffb --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateEvent.cs @@ -0,0 +1,28 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 添加企业客户事件推送 +/// +[EventName("external_contact_create")] +public class ExternalContactCreateEvent : ExternalContactChangeEvent +{ + /// + /// 添加此用户的「联系我」方式配置的state参数,或在获客链接中指定的customer_channel参数,可用于识别添加此用户的渠道 + /// + [XmlElement("State")] + public string State { get; set; } + /// + /// 欢迎语code,可用于发送欢迎语 + /// + [XmlElement("WelcomeCode")] + public string WelcomeCode { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateHalfEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateHalfEvent.cs new file mode 100644 index 000000000..943b84f86 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactCreateHalfEvent.cs @@ -0,0 +1,28 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 外部联系人免验证添加成员事件 +/// +[EventName("external_contact_create_half")] +public class ExternalContactCreateHalfEvent : ExternalContactChangeEvent +{ + /// + /// 添加此用户的「联系我」方式配置的state参数,或在获客链接中指定的customer_channel参数,可用于识别添加此用户的渠道 + /// + [XmlElement("State")] + public string State { get; set; } + /// + /// 欢迎语code,可用于发送欢迎语 + /// + [XmlElement("WelcomeCode")] + public string WelcomeCode { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteEvent.cs new file mode 100644 index 000000000..c67b70d30 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteEvent.cs @@ -0,0 +1,23 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 删除企业客户事件 +/// +[EventName("external_contact_delete")] +public class ExternalContactDeleteEvent : ExternalContactChangeEvent +{ + /// + /// 删除客户的操作来源,DELETE_BY_TRANSFER表示此客户是因在职继承自动被转接成员删除 + /// + [XmlElement("Source")] + public string Source { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteFollowUserEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteFollowUserEvent.cs new file mode 100644 index 000000000..cdd043073 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactDeleteFollowUserEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 删除跟进成员事件 +/// +[EventName("external_contact_del_follow_user")] +public class ExternalContactDeleteFollowUserEvent : ExternalContactChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactTransferFailEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactTransferFailEvent.cs new file mode 100644 index 000000000..dd60b40a4 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactTransferFailEvent.cs @@ -0,0 +1,23 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 客户接替失败事件 +/// +[EventName("external_contact_transfer_fail")] +public class ExternalContactTransferFailEvent : ExternalContactChangeEvent +{ + /// + /// 接替失败的原因, customer_refused-客户拒绝, customer_limit_exceed-接替成员的客户数达到上限 + /// + [XmlElement("FailReason")] + public string FailReason { get; set; } + + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactUpdateEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactUpdateEvent.cs new file mode 100644 index 000000000..e1f9a777c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalContactUpdateEvent.cs @@ -0,0 +1,17 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 编辑企业客户事件推送 +/// +[EventName("external_contact_update")] +public class ExternalContactUpdateEvent : ExternalContactChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} + diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagChangeEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagChangeEvent.cs new file mode 100644 index 000000000..e6bc43cb7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagChangeEvent.cs @@ -0,0 +1,20 @@ +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using System.Xml.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 企业客户标签变更事件推送 +/// +public abstract class ExternalTagChangeEvent : WeChatWorkEventMessage +{ + /// + /// 变更类型 + /// + [XmlElement("ChangeType")] + public string ChangeType { get; set; } + /// + /// 标签或标签组所属的规则组id,只回调给“客户联系”应用 + /// + [XmlElement("StrategyId")] + public string StrategyId { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagCreateEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagCreateEvent.cs new file mode 100644 index 000000000..cd7e0ff33 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagCreateEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 企业客户标签创建事件推送 +/// +[EventName("change_external_tag_create")] +public class ExternalTagCreateEvent : ExternalTagChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagDeleteEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagDeleteEvent.cs new file mode 100644 index 000000000..730b10915 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagDeleteEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 企业客户标签删除事件推送 +/// +[EventName("change_external_tag_delete")] +public class ExternalTagDeleteEvent : ExternalTagChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagShuffleEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagShuffleEvent.cs new file mode 100644 index 000000000..390a0f7d9 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagShuffleEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 企业客户标签重排事件推送 +/// +[EventName("change_external_tag_shuffle")] +public class ExternalTagShuffleEvent : ExternalTagChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagUpdateEvent.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagUpdateEvent.cs new file mode 100644 index 000000000..1e728d5c2 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Messages/Models/ExternalTagUpdateEvent.cs @@ -0,0 +1,16 @@ +using LINGYUN.Abp.WeChat.Common.Messages; +using LINGYUN.Abp.WeChat.Work.Common.Messages; +using Volo.Abp.EventBus; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Messages.Models; +/// +/// 企业客户标签变更事件推送 +/// +[EventName("change_external_tag_update")] +public class ExternalTagUpdateEvent : ExternalTagChangeEvent +{ + public override WeChatMessageEto ToEto() + { + return new WeChatWorkEventMessageEto(this); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttribute.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttribute.cs new file mode 100644 index 000000000..ef161f3c2 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttribute.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 成员对外属性 +/// +public abstract class ExternalAttribute +{ + /// + /// 属性名称: 需要先确保在管理端有创建该属性,否则会忽略 + /// + [NotNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string Name { get; set; } + /// + /// 属性类型 + /// + [NotNull] + [JsonProperty("type")] + [JsonPropertyName("type")] + public ExternalAttributeType Type { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeDeserializeFactory.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeDeserializeFactory.cs new file mode 100644 index 000000000..fb0975217 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeDeserializeFactory.cs @@ -0,0 +1,35 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Text.Json; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +internal static class ExternalAttributeDeserializeFactory +{ + /// + /// 根据属性类型创建属性(System.Text.Json) + /// + public static ExternalAttribute CreateExternalAttribute(ExternalAttributeType type, JsonElement configElement) + { + return type switch + { + ExternalAttributeType.Text => JsonSerializer.Deserialize(configElement.GetRawText())!, + ExternalAttributeType.Web => JsonSerializer.Deserialize(configElement.GetRawText())!, + ExternalAttributeType.MiniProgram => JsonSerializer.Deserialize(configElement.GetRawText())!, + _ => throw new NotSupportedException($"Attribute type {type} is not supported for the time being"), + }; + } + + /// + /// 根据属性类型创建属性(Newtonsoft.Json) + /// + public static ExternalAttribute CreateExternalAttribute(ExternalAttributeType type, JToken configToken) + { + return type switch + { + ExternalAttributeType.Text => configToken.ToObject()!, + ExternalAttributeType.Web => configToken.ToObject()!, + ExternalAttributeType.MiniProgram => configToken.ToObject()!, + _ => throw new NotSupportedException($"Attribute type {type} is not supported for the time being"), + }; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeType.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeType.cs new file mode 100644 index 000000000..8b003cf05 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalAttributeType.cs @@ -0,0 +1,25 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 属性类型 +/// +[Description("属性类型")] +public enum ExternalAttributeType +{ + /// + /// 文本 + /// + [Description("文本")] + Text = 0, + /// + /// 网页 + /// + [Description("网页")] + Web = 1, + /// + /// 小程序 + /// + [Description("小程序")] + MiniProgram = 2 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalMiniProgramAttribute.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalMiniProgramAttribute.cs new file mode 100644 index 000000000..5935b1ebf --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalMiniProgramAttribute.cs @@ -0,0 +1,43 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 小程序类型属性 +/// +public class ExternalMiniProgramAttribute : ExternalAttribute +{ + /// + /// 小程序 + /// + [NotNull] + [JsonProperty("miniprogram")] + [JsonPropertyName("miniprogram")] + public ExternalMiniProgramModel MiniProgram { get; set; } +} + +public class ExternalMiniProgramModel +{ + /// + /// 小程序appid,必须是有在本企业安装授权的小程序,否则会被忽略 + /// + [NotNull] + [JsonProperty("appid")] + [JsonPropertyName("appid")] + public string AppId { get; set; } + /// + /// 小程序的展示标题,长度限制12个UTF8字符 + /// + [NotNull] + [JsonProperty("title")] + [JsonPropertyName("title")] + public string Title { get; set; } + /// + /// 小程序的页面路径 + /// + [NotNull] + [JsonProperty("pagepath")] + [JsonPropertyName("pagepath")] + public string PagePath { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalProfile.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalProfile.cs new file mode 100644 index 000000000..2b625199c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalProfile.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 成员对外信息 +/// +[System.Text.Json.Serialization.JsonConverter(typeof(ExternalProfileSystemTextJsonConverter))] +[Newtonsoft.Json.JsonConverter(typeof(ExternalProfileNewtonsoftJsonConverter))] +public class ExternalProfile +{ + /// + /// 企业对外简称,需从已认证的企业简称中选填。可在“我的企业”页中查看企业简称认证状态。 + /// + [NotNull] + [JsonProperty("external_corp_name")] + [JsonPropertyName("external_corp_name")] + public string ExternalCorpName { get; set; } + /// + /// 视频号属性。须从企业绑定到企业微信的视频号中选择,可在“我的企业”页中查看绑定的视频号。 + /// 第三方仅通讯录应用可获取;对于非第三方创建的成员,第三方通讯录应用也不可获取 + /// + [NotNull] + [JsonProperty("wechat_channels")] + [JsonPropertyName("wechat_channels")] + public List WechatChannels { get; set; } + /// + /// 属性列表 + /// + [NotNull] + [JsonProperty("external_attr")] + [JsonPropertyName("external_attr")] + public List ExternalAttributes { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalTextAttribute.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalTextAttribute.cs new file mode 100644 index 000000000..b8f3f7d70 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalTextAttribute.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 文本类型属性 +/// +public class ExternalTextAttribute : ExternalAttribute +{ + /// + /// 文本 + /// + [NotNull] + [JsonProperty("text")] + [JsonPropertyName("text")] + public ExternalTextModel Text { get; set; } +} + +public class ExternalTextModel +{ + /// + /// 文本 + /// + [NotNull] + [JsonProperty("value")] + [JsonPropertyName("value")] + public string Value { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalWebAttribute.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalWebAttribute.cs new file mode 100644 index 000000000..e882697a2 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/ExternalWebAttribute.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 网页类型属性 +/// +public class ExternalWebAttribute : ExternalAttribute +{ + /// + /// 网页 + /// + [NotNull] + [JsonProperty("web")] + [JsonPropertyName("web")] + public ExternalWebModel Web { get; set; } +} + +public class ExternalWebModel +{ + /// + /// 网页的url,必须包含http或者https头 + /// + [NotNull] + [JsonProperty("url")] + [JsonPropertyName("url")] + public string Url { get; set; } + /// + /// 网页的展示标题,长度限制12个UTF8字符 + /// + [NotNull] + [JsonProperty("title")] + [JsonPropertyName("title")] + public string Title { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannel.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannel.cs new file mode 100644 index 000000000..953c929fa --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannel.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 视频号属性 +/// +public class WechatChannel +{ + /// + /// 视频号名字(设置后,成员将对外展示该视频号) + /// + [NotNull] + [JsonProperty("nickname")] + [JsonPropertyName("nickname")] + public string NickName { get; set; } + /// + /// 对外展示视频号状态 + /// + [NotNull] + [JsonProperty("status")] + [JsonPropertyName("status")] + public WechatChannelStatus Status { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannelStatus.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannelStatus.cs new file mode 100644 index 000000000..3d994e996 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Models/WechatChannelStatus.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +/// +/// 视频号状态 +/// +[Description("视频号状态")] +public enum WechatChannelStatus +{ + /// + /// 已确认 + /// + [Description("已确认")] + Confirmed = 0, + /// + /// 待确认 + /// + [Description("待确认")] + UnConfirmed = 1, +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkCropTagProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkCropTagProvider.cs new file mode 100644 index 000000000..f943e1e3c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkCropTagProvider.cs @@ -0,0 +1,72 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags; +/// +/// 客户标签管理 +/// +public interface IWeChatWorkCropTagProvider +{ + /// + /// 获取企业标签库 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetCropTagListAsync( + WeChatWorkGetCropTagListRequest request, + CancellationToken cancellationToken = default); + /// + /// 添加企业客户标签 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task CreateCropTagAsync( + WeChatWorkCreateCropTagRequest request, + CancellationToken cancellationToken = default); + /// + /// 编辑企业客户标签 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task UpdateCropTagAsync( + WeChatWorkUpdateCropTagRequest request, + CancellationToken cancellationToken = default); + /// + /// 删除企业客户标签 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task DeleteCropTagAsync( + WeChatWorkDeleteCropTagRequest request, + CancellationToken cancellationToken = default); + /// + /// 编辑客户企业标签 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task MarkCropTagAsync( + WeChatWorkMarkCropTagRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkStrategyTagProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkStrategyTagProvider.cs new file mode 100644 index 000000000..794b6e007 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/IWeChatWorkStrategyTagProvider.cs @@ -0,0 +1,60 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags; +/// +/// 规则组标签管理 +/// +public interface IWeChatWorkStrategyTagProvider +{ + /// + /// 获取指定规则组下的企业客户标签 + /// + /// + /// 详情见: https://developer.work.weixin.qq.com/document/path/94882#%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E8%A7%84%E5%88%99%E7%BB%84%E4%B8%8B%E7%9A%84%E4%BC%81%E4%B8%9A%E5%AE%A2%E6%88%B7%E6%A0%87%E7%AD%BE + /// + /// 请求参数 + /// + /// + Task GetStrategyTagListAsync( + WeChatWorkGetStrategyTagListRequest request, + CancellationToken cancellationToken = default); + /// + /// 为指定规则组创建企业客户标签 + /// + /// + /// 详情见: https://developer.work.weixin.qq.com/document/path/94882#%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E8%A7%84%E5%88%99%E7%BB%84%E4%B8%8B%E7%9A%84%E4%BC%81%E4%B8%9A%E5%AE%A2%E6%88%B7%E6%A0%87%E7%AD%BE + /// + /// 请求参数 + /// + /// + Task CreateStrategyTagAsync( + WeChatWorkCreateStrategyTagRequest request, + CancellationToken cancellationToken = default); + /// + /// 编辑指定规则组下的企业客户标签 + /// + /// + /// 详情见: https://developer.work.weixin.qq.com/document/path/94882#%E7%BC%96%E8%BE%91%E6%8C%87%E5%AE%9A%E8%A7%84%E5%88%99%E7%BB%84%E4%B8%8B%E7%9A%84%E4%BC%81%E4%B8%9A%E5%AE%A2%E6%88%B7%E6%A0%87%E7%AD%BE + /// + /// 请求参数 + /// + /// + Task UpdateStrategyTagAsync( + WeChatWorkUpdateStrategyTagRequest request, + CancellationToken cancellationToken = default); + /// + /// 删除指定规则组下的企业客户标签 + /// + /// + /// 详情见: https://developer.work.weixin.qq.com/document/path/94882#%E5%88%A0%E9%99%A4%E6%8C%87%E5%AE%9A%E8%A7%84%E5%88%99%E7%BB%84%E4%B8%8B%E7%9A%84%E4%BC%81%E4%B8%9A%E5%AE%A2%E6%88%B7%E6%A0%87%E7%AD%BE + /// + /// 请求参数 + /// + /// + Task DeleteStrategyTagAsync( + WeChatWorkDeleteStrategyTagRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTag.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTag.cs new file mode 100644 index 000000000..ebcf7ba48 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTag.cs @@ -0,0 +1,15 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +public class CropTag : Tag +{ + /// + /// 标签是否已经被删除,只在指定tag_id/group_id进行查询时返回 + /// + [NotNull] + [JsonProperty("deleted")] + [JsonPropertyName("deleted")] + public bool Deleted { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTagGroup.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTagGroup.cs new file mode 100644 index 000000000..db8f9770e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/CropTagGroup.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +public class CropTagGroup : TagGroup +{ + /// + /// 标签组是否已经被删除,只在指定tag_id进行查询时返回 + /// + [NotNull] + [JsonProperty("deleted")] + [JsonPropertyName("deleted")] + public bool Deleted { get; set; } + /// + /// 标签列表 + /// + [NotNull] + [JsonProperty("tag")] + [JsonPropertyName("tag")] + public CropTag[] Tag { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTag.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTag.cs new file mode 100644 index 000000000..f0ebd22c8 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTag.cs @@ -0,0 +1,4 @@ +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +public class StrategyTag : Tag +{ +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTagGroup.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTagGroup.cs new file mode 100644 index 000000000..7f49f7e41 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/StrategyTagGroup.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +public class StrategyTagGroup : TagGroup +{ + /// + /// 标签组所属的规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; set; } + /// + /// 标签列表 + /// + [NotNull] + [JsonProperty("tag")] + [JsonPropertyName("tag")] + public StrategyTag[] Tag { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/Tag.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/Tag.cs new file mode 100644 index 000000000..e625fcb66 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/Tag.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +public abstract class Tag +{ + /// + /// 标签id + /// + [NotNull] + [JsonProperty("id")] + [JsonPropertyName("id")] + public string Id { get; set; } + /// + /// 标签名称 + /// + [NotNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string Name { get; set; } + /// + /// 标签创建时间 + /// + [NotNull] + [JsonProperty("create_time")] + [JsonPropertyName("create_time")] + public long CreateTime { get; set; } + /// + /// 标签排序的次序值,order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [NotNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int Order { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/TagGroup.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/TagGroup.cs new file mode 100644 index 000000000..6fcd9ddac --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Models/TagGroup.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +public abstract class TagGroup +{ + /// + /// 标签组id + /// + [NotNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string GroupId { get; set; } + /// + /// 标签组名称 + /// + [NotNull] + [JsonProperty("group_name")] + [JsonPropertyName("group_name")] + public string GroupName { get; set; } + /// + /// 标签组创建时间 + /// + [NotNull] + [JsonProperty("create_time")] + [JsonPropertyName("create_time")] + public long CreateTime { get; set; } + /// + /// 标签组排序的次序值,order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [NotNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int Order { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateCropTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateCropTagRequest.cs new file mode 100644 index 000000000..061aa937a --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateCropTagRequest.cs @@ -0,0 +1,100 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +/// +/// 添加企业客户标签请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkCreateCropTagRequest : WeChatWorkRequest +{ + /// + /// 标签组id + /// + [CanBeNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string? GroupId { get; set; } + + private string? _groupName; + /// + /// 标签组名称,最长为30个字符 + /// + [CanBeNull] + [JsonProperty("group_name")] + [JsonPropertyName("group_name")] + public string? GroupName { + get => _groupName; + set { + + Check.Length(value, nameof(GroupName), 30); + _groupName = value; + } + } + /// + /// 标签组排序的次序值,order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [CanBeNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int? Order { get; set; } + /// + /// 授权方安装的应用agentid。仅旧的第三方多应用套件需要填此参数 + /// + [CanBeNull] + [JsonProperty("agentid")] + [JsonPropertyName("agentid")] + public string? AgentId { get; set; } + /// + /// 添加的标签组 + /// + [CanBeNull] + [JsonProperty("tag")] + [JsonPropertyName("tag")] + public List Tag { get; } + + public WeChatWorkCreateCropTagRequest() + { + Tag = new List(); + } + + protected override void Validate() + { + if (GroupName.IsNullOrWhiteSpace() && + Tag.IsNullOrEmpty()) + { + throw new ArgumentException("The name of the tag group or the tag list cannot be empty at the same time!"); + } + } +} + +public class NewCropTag +{ + /// + /// 添加的标签名称,最长为30个字符 + /// + [NotNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string Name { get; } + /// + /// 标签次序值。order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [CanBeNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int? Order { get; set; } + public NewCropTag(string name, int? order = null) + { + Check.NotNullOrWhiteSpace(name, nameof(name), 30); + + Name = name; + Order = order; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateStrategyTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateStrategyTagRequest.cs new file mode 100644 index 000000000..a1e7a1bb1 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkCreateStrategyTagRequest.cs @@ -0,0 +1,88 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +public class WeChatWorkCreateStrategyTagRequest : WeChatWorkRequest +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; } + /// + /// 标签组id + /// + [CanBeNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string? GroupId { get; set; } + + private string? _groupName; + /// + /// 标签组名称,最长为30个字符 + /// + [CanBeNull] + [JsonProperty("group_name")] + [JsonPropertyName("group_name")] + public string? GroupName { + get => _groupName; + set { + + Check.Length(value, nameof(GroupName), 30); + _groupName = value; + } + } + /// + /// 标签组排序的次序值,order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [CanBeNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int? Order { get; set; } + /// + /// 添加的标签组 + /// + [CanBeNull] + [JsonProperty("tag")] + [JsonPropertyName("tag")] + public List Tag { get; } + + public WeChatWorkCreateStrategyTagRequest(int strategyId) + { + Check.NotDefaultOrNull(strategyId, nameof(strategyId)); + + StrategyId = strategyId; + + Tag = new List(); + } +} + +public class NewStrategyTag +{ + /// + /// 添加的标签名称,最长为30个字符 + /// + [NotNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string Name { get; } + /// + /// 标签次序值。order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [CanBeNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int? Order { get; set; } + public NewStrategyTag(string name, int? order = null) + { + Check.NotNullOrWhiteSpace(name, nameof(name), 30); + + Name = name; + Order = order; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteCropTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteCropTagRequest.cs new file mode 100644 index 000000000..c5b86b07e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteCropTagRequest.cs @@ -0,0 +1,53 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +/// +/// 删除企业客户标签请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkDeleteCropTagRequest : WeChatWorkRequest +{ + /// + /// 标签组的id列表 + /// + [CanBeNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string[]? GroupId { get; } + /// + /// 标签组的id列表 + /// + [CanBeNull] + [JsonProperty("tag_id")] + [JsonPropertyName("tag_id")] + public string[]? TagId { get; } + /// + /// 授权方安装的应用agentid。仅旧的第三方多应用套件需要填此参数 + /// + [CanBeNull] + [JsonProperty("agentid")] + [JsonPropertyName("agentid")] + public string? AgentId { get; set; } + + private WeChatWorkDeleteCropTagRequest( + string[]? groupId = null, + string[]? tagId = null) + { + GroupId = groupId; + TagId = tagId; + } + + public static WeChatWorkDeleteCropTagRequest Tag(string[] tagId) + { + return new WeChatWorkDeleteCropTagRequest(tagId: tagId); + } + + public static WeChatWorkDeleteCropTagRequest Group(string[] groupId) + { + return new WeChatWorkDeleteCropTagRequest(groupId); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteStrategyTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteStrategyTagRequest.cs new file mode 100644 index 000000000..018ed9505 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkDeleteStrategyTagRequest.cs @@ -0,0 +1,40 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +public class WeChatWorkDeleteStrategyTagRequest : WeChatWorkRequest +{ + /// + /// 标签组的id列表 + /// + [CanBeNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string[]? GroupId { get; } + /// + /// 标签组的id列表 + /// + [CanBeNull] + [JsonProperty("tag_id")] + [JsonPropertyName("tag_id")] + public string[]? TagId { get; } + + private WeChatWorkDeleteStrategyTagRequest( + string[]? groupId = null, + string[]? tagId = null) + { + GroupId = groupId; + TagId = tagId; + } + + public static WeChatWorkDeleteStrategyTagRequest Tag(string[] tagId) + { + return new WeChatWorkDeleteStrategyTagRequest(tagId: tagId); + } + + public static WeChatWorkDeleteStrategyTagRequest Group(string[] groupId) + { + return new WeChatWorkDeleteStrategyTagRequest(groupId); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetCropTagListRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetCropTagListRequest.cs new file mode 100644 index 000000000..051a09701 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetCropTagListRequest.cs @@ -0,0 +1,33 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +/// +/// 获取企业标签库请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCropTagListRequest : WeChatWorkRequest +{ + /// + /// 要查询的标签id + /// + [CanBeNull] + [JsonProperty("tag_id")] + [JsonPropertyName("tag_id")] + public string[]? TagId { get; } + /// + /// 要查询的标签组id,返回该标签组以及其下的所有标签信息 + /// + [CanBeNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string[]? GroupId { get; } + public WeChatWorkGetCropTagListRequest(string[]? tagId = null, string[]? groupId = null) + { + TagId = tagId; + GroupId = groupId; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetStrategyTagListRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetStrategyTagListRequest.cs new file mode 100644 index 000000000..e17cc35d0 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkGetStrategyTagListRequest.cs @@ -0,0 +1,41 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +public class WeChatWorkGetStrategyTagListRequest : WeChatWorkRequest +{ + /// + /// 规则组id + /// + [NotNull] + [JsonProperty("strategy_id")] + [JsonPropertyName("strategy_id")] + public int StrategyId { get; } + /// + /// 要查询的标签id + /// + [CanBeNull] + [JsonProperty("tag_id")] + [JsonPropertyName("tag_id")] + public string[]? TagId { get; } + /// + /// 要查询的标签组id,返回该标签组以及其下的所有标签信息 + /// + [CanBeNull] + [JsonProperty("group_id")] + [JsonPropertyName("group_id")] + public string[]? GroupId { get; } + public WeChatWorkGetStrategyTagListRequest( + int strategyId, + string[]? tagId = null, + string[]? groupId = null) + { + Check.NotDefaultOrNull(strategyId, nameof(strategyId)); + + StrategyId = strategyId; + TagId = tagId; + GroupId = groupId; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkMarkCropTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkMarkCropTagRequest.cs new file mode 100644 index 000000000..fc90029c3 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkMarkCropTagRequest.cs @@ -0,0 +1,65 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +/// +/// 编辑客户企业标签请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkMarkCropTagRequest : WeChatWorkRequest +{ + /// + /// 添加外部联系人的userid + /// + [NotNull] + [JsonProperty("userid")] + [JsonPropertyName("userid")] + public string UserId { get; } + /// + /// 外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserId { get; } + /// + /// 要标记的标签列表 + /// + [NotNull] + [JsonProperty("add_tag")] + [JsonPropertyName("add_tag")] + public List CreateTag { get; } + /// + /// 要移除的标签列表 + /// + [NotNull] + [JsonProperty("remove_tag")] + [JsonPropertyName("remove_tag")] + public List RemoveTag { get; } + public WeChatWorkMarkCropTagRequest(string userId, string externalUserId) + { + Check.NotNullOrWhiteSpace(userId, nameof(userId)); + Check.NotNullOrWhiteSpace(externalUserId, nameof(externalUserId)); + + UserId = userId; + ExternalUserId = externalUserId; + + CreateTag = new List(); + RemoveTag = new List(); + } + + protected override void Validate() + { + if (CreateTag.IsNullOrEmpty() && + RemoveTag.IsNullOrEmpty()) + { + throw new ArgumentException("CreateTag and RemoveTag cannot be empty simultaneously!"); + } + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateCropTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateCropTagRequest.cs new file mode 100644 index 000000000..b79ec152c --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateCropTagRequest.cs @@ -0,0 +1,52 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +/// +/// 编辑企业客户标签请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkUpdateCropTagRequest : WeChatWorkRequest +{ + /// + /// 标签或标签组的id + /// + [NotNull] + [JsonProperty("id")] + [JsonPropertyName("id")] + public string Id { get; } + /// + /// 新的标签或标签组名称,最长为30个字符 + /// + [CanBeNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string? Name { get; } + /// + /// 标签/标签组的次序值。order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [CanBeNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int? Order { get; set; } + /// + /// 授权方安装的应用agentid。仅旧的第三方多应用套件需要填此参数 + /// + [CanBeNull] + [JsonProperty("agentid")] + [JsonPropertyName("agentid")] + public string? AgentId { get; set; } + + public WeChatWorkUpdateCropTagRequest(string id, string? name = null) + { + Check.NotNullOrWhiteSpace(id, nameof(id)); + Check.Length(name, nameof(name), 30); + + Id = id; + Name = name; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateStrategyTagRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateStrategyTagRequest.cs new file mode 100644 index 000000000..b8f1f1a84 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Request/WeChatWorkUpdateStrategyTagRequest.cs @@ -0,0 +1,39 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +public class WeChatWorkUpdateStrategyTagRequest : WeChatWorkRequest +{ + /// + /// 标签或标签组的id + /// + [NotNull] + [JsonProperty("id")] + [JsonPropertyName("id")] + public string Id { get; } + /// + /// 新的标签或标签组名称,最长为30个字符 + /// + [CanBeNull] + [JsonProperty("name")] + [JsonPropertyName("name")] + public string? Name { get; } + /// + /// 标签/标签组的次序值。order值大的排序靠前。有效的值范围是[0, 2^32) + /// + [CanBeNull] + [JsonProperty("order")] + [JsonPropertyName("order")] + public int? Order { get; set; } + + public WeChatWorkUpdateStrategyTagRequest(string id, string? name = null) + { + Check.NotNullOrWhiteSpace(id, nameof(id)); + Check.Length(name, nameof(name), 30); + + Id = id; + Name = name; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateCropTagResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateCropTagResponse.cs new file mode 100644 index 000000000..d10cb037d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateCropTagResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +/// +/// 添加企业客户标签响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkCreateCropTagResponse : WeChatWorkResponse +{ + /// + /// 标签组 + /// + [NotNull] + [JsonProperty("tag_group")] + [JsonPropertyName("tag_group")] + public CropTagGroup TagGroup { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateStrategyTagResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateStrategyTagResponse.cs new file mode 100644 index 000000000..6f40217d5 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkCreateStrategyTagResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +/// +/// 为指定规则组创建企业客户标签 +/// +/// +/// 详情见: https://developer.work.weixin.qq.com/document/path/94882#%E4%B8%BA%E6%8C%87%E5%AE%9A%E8%A7%84%E5%88%99%E7%BB%84%E5%88%9B%E5%BB%BA%E4%BC%81%E4%B8%9A%E5%AE%A2%E6%88%B7%E6%A0%87%E7%AD%BE +/// +public class WeChatWorkCreateStrategyTagResponse : WeChatWorkResponse +{ + /// + /// 标签组 + /// + [NotNull] + [JsonProperty("tag_group")] + [JsonPropertyName("tag_group")] + public StrategyTagGroup TagGroup { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetCropTagListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetCropTagListResponse.cs new file mode 100644 index 000000000..b71bcb1a1 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetCropTagListResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +/// +/// 获取企业标签库响应参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetCropTagListResponse : WeChatWorkResponse +{ + /// + /// 标签组列表 + /// + [NotNull] + [JsonProperty("tag_group")] + [JsonPropertyName("tag_group")] + public StrategyTagGroup[] TagGroup { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetStrategyTagListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetStrategyTagListResponse.cs new file mode 100644 index 000000000..1a77eaa69 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/Response/WeChatWorkGetStrategyTagListResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +/// +/// 获取指定规则组下的企业客户标签响应参数 +/// +/// +/// 详情见: https://developer.work.weixin.qq.com/document/path/94882#%E8%8E%B7%E5%8F%96%E6%8C%87%E5%AE%9A%E8%A7%84%E5%88%99%E7%BB%84%E4%B8%8B%E7%9A%84%E4%BC%81%E4%B8%9A%E5%AE%A2%E6%88%B7%E6%A0%87%E7%AD%BE +/// +public class WeChatWorkGetStrategyTagListResponse : WeChatWorkResponse +{ + /// + /// 标签组列表 + /// + [NotNull] + [JsonProperty("tag_group")] + [JsonPropertyName("tag_group")] + public StrategyTagGroup[] TagGroup { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider.cs new file mode 100644 index 000000000..b73400b14 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider.cs @@ -0,0 +1,108 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkCropTagProvider : IWeChatWorkCropTagProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkCropTagProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetCropTagListAsync( + WeChatWorkGetCropTagListRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetCropTagListAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task CreateCropTagAsync( + WeChatWorkCreateCropTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.CreateCropTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task UpdateCropTagAsync( + WeChatWorkUpdateCropTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.UpdateCropTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task DeleteCropTagAsync( + WeChatWorkDeleteCropTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.DeleteCropTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task MarkCropTagAsync( + WeChatWorkMarkCropTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.MarkCropTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkStrategyTagProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkStrategyTagProvider.cs new file mode 100644 index 000000000..49fe5189e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkStrategyTagProvider.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Response; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkStrategyTagProvider : IWeChatWorkStrategyTagProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkStrategyTagProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetStrategyTagListAsync( + WeChatWorkGetStrategyTagListRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetStrategyTagListAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task CreateStrategyTagAsync( + WeChatWorkCreateStrategyTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.CreateStrategyTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task UpdateStrategyTagAsync( + WeChatWorkUpdateStrategyTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.UpdateStrategyTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task DeleteStrategyTagAsync( + WeChatWorkDeleteStrategyTagRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.DeleteStrategyTagAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkEmployExtendProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkEmployExtendProvider.cs new file mode 100644 index 000000000..9622d4e54 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkEmployExtendProvider.cs @@ -0,0 +1,48 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers; +/// +/// 在职继承接口 +/// +public interface IWeChatWorkEmployExtendProvider +{ + /// + /// 分配在职成员的客户 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task TransferCustomerAsync( + WeChatWorkTransferCustomerRequest request, + CancellationToken cancellationToken = default); + /// + /// 查询客户接替状态 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetTransferResultAsync( + WeChatWorkGetTransferResultRequest request, + CancellationToken cancellationToken = default); + /// + /// 分配在职成员的客户群 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GroupChatOnjobTransferAsync( + WeChatWorkGroupChatOnjobTransferRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkResignExtendProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkResignExtendProvider.cs new file mode 100644 index 000000000..3a837d768 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/IWeChatWorkResignExtendProvider.cs @@ -0,0 +1,60 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers; +/// +/// 离职继承接口 +/// +public interface IWeChatWorkResignExtendProvider +{ + /// + /// 获取待分配的离职成员列表 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetUnassignedListAsync( + WeChatWorkGetUnassignedListRequest request, + CancellationToken cancellationToken = default); + /// + /// 分配离职成员的客户 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task ResignedTransferCustomerAsync( + WeChatWorkResignedTransferCustomerRequest request, + CancellationToken cancellationToken = default); + /// + /// 查询客户接替状态 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GetResignedTransferResultAsync( + WeChatWorkGetResignedTransferResultRequest request, + CancellationToken cancellationToken = default); + /// + /// 分配离职成员的客户群 + /// + /// + /// 详情见: + /// + /// 请求参数 + /// + /// + Task GroupChatTransferAsync( + WeChatWorkGroupChatTransferRequest request, + CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/GroupChatTransferFailed.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/GroupChatTransferFailed.cs new file mode 100644 index 000000000..a39fb70d4 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/GroupChatTransferFailed.cs @@ -0,0 +1,32 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +/// +/// 没能成功继承的群详情 +/// +public class GroupChatTransferFailed +{ + /// + /// 没能成功继承的群ID + /// + [NotNull] + [JsonProperty("chat_id")] + [JsonPropertyName("chat_id")] + public string ChatId { get; set; } + /// + /// 没能成功继承的群,错误码 + /// + [NotNull] + [JsonProperty("errcode")] + [JsonPropertyName("errcode")] + public int ErrCode { get; set; } + /// + /// 没能成功继承的群,错误描述 + /// + [NotNull] + [JsonProperty("errmsg")] + [JsonPropertyName("errmsg")] + public string ErrMsg { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomer.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomer.cs new file mode 100644 index 000000000..3402836b0 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomer.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +public class TransferCustomer +{ + /// + /// 客户的外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserid { get; set; } + /// + /// 对此客户进行分配的结果, 具体可参考全局错误码, 0表示成功发起接替,待24小时后自动接替,并不代表最终接替成功 + /// + [NotNull] + [JsonProperty("errcode")] + [JsonPropertyName("errcode")] + public int ErrCode { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomerResult.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomerResult.cs new file mode 100644 index 000000000..c76f89df7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferCustomerResult.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +public class TransferCustomerResult +{ + /// + /// 客户的外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserid { get; set; } + /// + /// 接替状态 + /// + [NotNull] + [JsonProperty("status")] + [JsonPropertyName("status")] + public TransferStatus Status { get; set; } + /// + /// 接替客户的时间,如果是等待接替状态,则为未来的自动接替时间 + /// + [NotNull] + [JsonProperty("takeover_time")] + [JsonPropertyName("takeover_time")] + public long TakeoverTime { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferStatus.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferStatus.cs new file mode 100644 index 000000000..acab61ff8 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/TransferStatus.cs @@ -0,0 +1,30 @@ +using System.ComponentModel; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +/// +/// 接替状态 +/// +[Description("接替状态")] +public enum TransferStatus +{ + /// + /// 接替完毕 + /// + [Description("接替完毕")] + Completed = 1, + /// + /// 等待接替 + /// + [Description("等待接替")] + Pending = 2, + /// + /// 客户拒绝 + /// + [Description("客户拒绝")] + CustomerReject = 3, + /// + /// 接替成员客户达到上限 + /// + [Description("接替成员客户达到上限")] + ReachesLimit = 4 +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedCustomerInfo.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedCustomerInfo.cs new file mode 100644 index 000000000..f4767e63e --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedCustomerInfo.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +public class UnassignedCustomerInfo +{ + /// + /// 离职成员的userid + /// + [NotNull] + [JsonProperty("handover_userid")] + [JsonPropertyName("handover_userid")] + public string HandoverUserid { get; set; } + /// + /// 外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserid { get; set; } + /// + /// 成员离职时间 + /// + [NotNull] + [JsonProperty("dimission_time")] + [JsonPropertyName("dimission_time")] + public long DimissionTime { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomer.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomer.cs new file mode 100644 index 000000000..f8942edf9 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomer.cs @@ -0,0 +1,25 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +/// +/// 分配离职成员客户详情 +/// +public class UnassignedTransferCustomer +{ + /// + /// 客户的外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserid { get; set; } + /// + /// 对此客户进行分配的结果,0表示开始分配流程,待24小时后自动接替,并不代表最终分配成功 + /// + [NotNull] + [JsonProperty("errcode")] + [JsonPropertyName("errcode")] + public int ErrCode { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomerResult.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomerResult.cs new file mode 100644 index 000000000..8379d2f65 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Models/UnassignedTransferCustomerResult.cs @@ -0,0 +1,32 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +/// +/// 分配离职成员客户接替状态结果 +/// +public class UnassignedTransferCustomerResult +{ + /// + /// 转接客户的外部联系人userid + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string ExternalUserid { get; set; } + /// + /// 接替状态 + /// + [NotNull] + [JsonProperty("status")] + [JsonPropertyName("status")] + public TransferStatus Status { get; set; } + /// + /// 接替客户的时间,如果是等待接替状态,则为未来的自动接替时间 + /// + [NotNull] + [JsonProperty("takeover_time")] + [JsonPropertyName("takeover_time")] + public long TakeoverTime { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetResignedTransferResultRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetResignedTransferResultRequest.cs new file mode 100644 index 000000000..64960ea47 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetResignedTransferResultRequest.cs @@ -0,0 +1,48 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +/// +/// 查询离职成员的客户接替状态请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetResignedTransferResultRequest : WeChatWorkRequest +{ + /// + /// 原添加成员的userid + /// + [NotNull] + [JsonProperty("handover_userid")] + [JsonPropertyName("handover_userid")] + public string HandOverUserId { get; } + /// + /// 接替成员的userid + /// + [NotNull] + [JsonProperty("takeover_userid")] + [JsonPropertyName("takeover_userid")] + public string TakeOverUserId { get; } + /// + /// 分页查询的cursor,每个分页返回的数据不会超过1000条;不填或为空表示获取第一个分页 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; } + public WeChatWorkGetResignedTransferResultRequest( + string handOverUserId, + string takeOverUserId, + string? cursor = null) + { + Check.NotNullOrWhiteSpace(handOverUserId, nameof(handOverUserId)); + Check.NotNullOrWhiteSpace(takeOverUserId, nameof(takeOverUserId)); + + HandOverUserId = handOverUserId; + TakeOverUserId = takeOverUserId; + Cursor = cursor; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetTransferResultRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetTransferResultRequest.cs new file mode 100644 index 000000000..2ea1f6298 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetTransferResultRequest.cs @@ -0,0 +1,48 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +/// +/// 查询客户接替状态请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetTransferResultRequest : WeChatWorkRequest +{ + /// + /// 原跟进成员的userid + /// + [NotNull] + [JsonProperty("handover_userid")] + [JsonPropertyName("handover_userid")] + public string HandOverUserId { get; } + /// + /// 接替成员的userid + /// + [NotNull] + [JsonProperty("takeover_userid")] + [JsonPropertyName("takeover_userid")] + public string TakeOverUserId { get; } + /// + /// 分页查询的cursor,每个分页返回的数据不会超过1000条;不填或为空表示获取第一个分页 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; } + public WeChatWorkGetTransferResultRequest( + string handOverUserId, + string takeOverUserId, + string? cursor = null) + { + Check.NotNullOrWhiteSpace(handOverUserId, nameof(handOverUserId)); + Check.NotNullOrWhiteSpace(takeOverUserId, nameof(takeOverUserId)); + + HandOverUserId = handOverUserId; + TakeOverUserId = takeOverUserId; + Cursor = cursor; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetUnassignedListRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetUnassignedListRequest.cs new file mode 100644 index 000000000..75c102ad9 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGetUnassignedListRequest.cs @@ -0,0 +1,27 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +public class WeChatWorkGetUnassignedListRequest : WeChatWorkRequest +{ + /// + /// 分页查询游标,字符串类型,适用于数据量较大的情况,如果使用该参数则无需填写page_id,该参数由上一次调用返回 + /// + [CanBeNull] + [JsonProperty("cursor")] + [JsonPropertyName("cursor")] + public string? Cursor { get; set; } + /// + /// 每次返回的最大记录数,默认为1000,最大值为1000 + /// + [CanBeNull] + [JsonProperty("page_size")] + [JsonPropertyName("page_size")] + public int? PageSize { get; set; } + public WeChatWorkGetUnassignedListRequest(string? cursor = null, int? pageSize = 1000) + { + Cursor = cursor; + PageSize = pageSize; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatOnjobTransferRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatOnjobTransferRequest.cs new file mode 100644 index 000000000..dda7a5ed2 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatOnjobTransferRequest.cs @@ -0,0 +1,43 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +/// +/// 分配在职成员的客户群请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGroupChatOnjobTransferRequest : WeChatWorkRequest +{ + /// + /// 新群主ID + /// + [NotNull] + [JsonProperty("new_owner")] + [JsonPropertyName("new_owner")] + public string NewOwner { get; } + /// + /// 需要转群主的客户群ID列表。取值范围: 1 ~ 100 + /// + [NotNull] + [JsonProperty("chat_id_list")] + [JsonPropertyName("chat_id_list")] + public string[] ChatIdList { get; } + public WeChatWorkGroupChatOnjobTransferRequest(string newOwner, string[] chatIdList) + { + Check.NotNullOrWhiteSpace(newOwner, nameof(newOwner)); + Check.NotNullOrEmpty(chatIdList, nameof(chatIdList)); + + if (chatIdList.Length < 1 || chatIdList.Length > 100) + { + throw new ArgumentException("The list of customer group ids that need to be transferred to the group owner must have more than 1 item or less than 100 items"); + } + + NewOwner = newOwner; + ChatIdList = chatIdList; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatTransferRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatTransferRequest.cs new file mode 100644 index 000000000..364427048 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkGroupChatTransferRequest.cs @@ -0,0 +1,43 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +/// +/// 分配离职成员的客户群请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkGroupChatTransferRequest : WeChatWorkRequest +{ + /// + /// 新群主ID + /// + [NotNull] + [JsonProperty("new_owner")] + [JsonPropertyName("new_owner")] + public string NewOwner { get; } + /// + /// 需要转群主的客户群ID列表。取值范围: 1 ~ 100 + /// + [NotNull] + [JsonProperty("chat_id_list")] + [JsonPropertyName("chat_id_list")] + public string[] ChatIdList { get; } + public WeChatWorkGroupChatTransferRequest(string newOwner, string[] chatIdList) + { + Check.NotNullOrWhiteSpace(newOwner, nameof(newOwner)); + Check.NotNullOrEmpty(chatIdList, nameof(chatIdList)); + + if (chatIdList.Length < 1 || chatIdList.Length > 100) + { + throw new ArgumentException("The list of customer group ids that need to be transferred to the group owner must have more than 1 item or less than 100 items"); + } + + NewOwner = newOwner; + ChatIdList = chatIdList; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkResignedTransferCustomerRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkResignedTransferCustomerRequest.cs new file mode 100644 index 000000000..60ed2712d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkResignedTransferCustomerRequest.cs @@ -0,0 +1,52 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +/// +/// 分配离职成员的客户请求参数 +/// +public class WeChatWorkResignedTransferCustomerRequest : WeChatWorkRequest +{ + /// + /// 原跟进成员的userid + /// + [NotNull] + [JsonProperty("handover_userid")] + [JsonPropertyName("handover_userid")] + public string HandoverUserId { get; } + /// + /// 接替成员的userid + /// + [NotNull] + [JsonProperty("takeover_userid")] + [JsonPropertyName("takeover_userid")] + public string TakeoverUserId { get; } + /// + /// 客户的external_userid列表,每次最多分配100个客户 + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string[] ExternalUserId { get; } + public WeChatWorkResignedTransferCustomerRequest(string handoverUserId, string takeoverUserId, string[] externalUserId) + { + Check.NotNullOrWhiteSpace(handoverUserId, nameof(handoverUserId)); + Check.NotNullOrWhiteSpace(takeoverUserId, nameof(takeoverUserId)); + Check.NotNullOrEmpty(externalUserId, nameof(externalUserId)); + + HandoverUserId = handoverUserId; + TakeoverUserId = takeoverUserId; + ExternalUserId = externalUserId; + } + + protected override void Validate() + { + if (ExternalUserId.Length > 100) + { + throw new ArgumentException("Transfer a maximum of 100 customers at a time!"); + } + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkTransferCustomerRequest.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkTransferCustomerRequest.cs new file mode 100644 index 000000000..61fee48e4 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Request/WeChatWorkTransferCustomerRequest.cs @@ -0,0 +1,60 @@ +using JetBrains.Annotations; +using Newtonsoft.Json; +using System.Text.Json.Serialization; +using Volo.Abp; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +/// +/// 分配在职成员的客户请求参数 +/// +/// +/// 详情见: +/// +public class WeChatWorkTransferCustomerRequest : WeChatWorkRequest +{ + /// + /// 原跟进成员的userid + /// + [NotNull] + [JsonProperty("handover_userid")] + [JsonPropertyName("handover_userid")] + public string HandoverUserId { get; } + /// + /// 接替成员的userid + /// + [NotNull] + [JsonProperty("takeover_userid")] + [JsonPropertyName("takeover_userid")] + public string TakeoverUserId { get; } + /// + /// 客户的external_userid列表,每次最多分配100个客户 + /// + [NotNull] + [JsonProperty("external_userid")] + [JsonPropertyName("external_userid")] + public string[] ExternalUserId { get; } + /// + /// 转移成功后发给客户的消息,最多200个字符,不填则使用默认文案 + /// + [CanBeNull] + [JsonProperty("transfer_success_msg")] + [JsonPropertyName("transfer_success_msg")] + public string? TransferSuccessMsg { get; set; } + public WeChatWorkTransferCustomerRequest(string handoverUserId, string takeoverUserId, string[] externalUserId, string? transferSuccessMsg = null) + { + Check.NotNullOrWhiteSpace(handoverUserId, nameof(handoverUserId)); + Check.NotNullOrWhiteSpace(takeoverUserId, nameof(takeoverUserId)); + Check.NotNullOrEmpty(externalUserId, nameof(externalUserId)); + Check.Length(transferSuccessMsg, nameof(transferSuccessMsg), 200); + + HandoverUserId = handoverUserId; + TakeoverUserId = takeoverUserId; + ExternalUserId = externalUserId; + TransferSuccessMsg = transferSuccessMsg; + } + + protected override void Validate() + { + Check.Length(TransferSuccessMsg, nameof(TransferSuccessMsg), 200); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetResignedTransferResultResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetResignedTransferResultResponse.cs new file mode 100644 index 000000000..256950e43 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetResignedTransferResultResponse.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 查询离职人员客户接替状态响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetResignedTransferResultResponse : WeChatWorkResponse +{ + /// + /// 转接客户 + /// + [NotNull] + [JsonProperty("customer")] + [JsonPropertyName("customer")] + public UnassignedTransferCustomerResult[] Customer { get; set; } + /// + /// 下个分页的起始cursor + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetTransferResultResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetTransferResultResponse.cs new file mode 100644 index 000000000..7aed70bf7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetTransferResultResponse.cs @@ -0,0 +1,29 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 查询客户接替状态响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetTransferResultResponse : WeChatWorkResponse +{ + /// + /// 分配客户 + /// + [NotNull] + [JsonProperty("customer")] + [JsonPropertyName("customer")] + public TransferCustomerResult[] Customer { get; set; } + /// + /// 下个分页的起始cursor + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetUnassignedListResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetUnassignedListResponse.cs new file mode 100644 index 000000000..66e42c82b --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGetUnassignedListResponse.cs @@ -0,0 +1,36 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 获取待分配的离职成员列表响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGetUnassignedListResponse : WeChatWorkResponse +{ + /// + /// 待分配离职成员的客户 + /// + [NotNull] + [JsonProperty("info")] + [JsonPropertyName("info")] + public UnassignedCustomerInfo[] Info { get; set; } + /// + /// 是否是最后一条记录 + /// + [NotNull] + [JsonProperty("is_last")] + [JsonPropertyName("is_last")] + public bool IsLast { get; set; } + /// + /// 分页查询游标,已经查完则返回空(""),使用page_id作为查询参数时不返回 + /// + [CanBeNull] + [JsonProperty("next_cursor")] + [JsonPropertyName("next_cursor")] + public string? NextCursor { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatOnjobTransferResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatOnjobTransferResponse.cs new file mode 100644 index 000000000..7f05c077d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatOnjobTransferResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 分配在职成员的客户群响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGroupChatOnjobTransferResponse : WeChatWorkResponse +{ + /// + /// 没能成功继承的群 + /// + [NotNull] + [JsonProperty("failed_chat_list")] + [JsonPropertyName("failed_chat_list")] + public GroupChatTransferFailed[] FailedChatList { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatTransferResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatTransferResponse.cs new file mode 100644 index 000000000..ad0112bf4 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkGroupChatTransferResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 分配离职成员的客户群响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkGroupChatTransferResponse : WeChatWorkResponse +{ + /// + /// 没能成功继承的群 + /// + [NotNull] + [JsonProperty("failed_chat_list")] + [JsonPropertyName("failed_chat_list")] + public GroupChatTransferFailed[] FailedChatList { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkResignedTransferCustomerResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkResignedTransferCustomerResponse.cs new file mode 100644 index 000000000..255fdab7d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkResignedTransferCustomerResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 分配离职成员的客户响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkResignedTransferCustomerResponse : WeChatWorkResponse +{ + /// + /// 分配离职成员客户结果 + /// + [NotNull] + [JsonProperty("customer")] + [JsonPropertyName("customer")] + public UnassignedTransferCustomer[] Customer { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkTransferCustomerResponse.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkTransferCustomerResponse.cs new file mode 100644 index 000000000..638d3b4ef --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/Response/WeChatWorkTransferCustomerResponse.cs @@ -0,0 +1,22 @@ +using JetBrains.Annotations; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Models; +using Newtonsoft.Json; +using System.Text.Json.Serialization; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +/// +/// 分配在职成员的客户响应结果 +/// +/// +/// 详情见: +/// +public class WeChatWorkTransferCustomerResponse : WeChatWorkResponse +{ + /// + /// 分配客户 + /// + [NotNull] + [JsonProperty("customer")] + [JsonPropertyName("customer")] + public TransferCustomer[] Customer { get; set; } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkEmployExtendProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkEmployExtendProvider.cs new file mode 100644 index 000000000..63baaeeb1 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkEmployExtendProvider.cs @@ -0,0 +1,76 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkEmployExtendProvider : IWeChatWorkEmployExtendProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkEmployExtendProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task TransferCustomerAsync( + WeChatWorkTransferCustomerRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.AssignCustomerAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GetTransferResultAsync( + WeChatWorkGetTransferResultRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetTransferResultAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GroupChatOnjobTransferAsync( + WeChatWorkGroupChatOnjobTransferRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.OnjobTransferAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkResignExtendProvider.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkResignExtendProvider.cs new file mode 100644 index 000000000..3ff4fae55 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/LINGYUN/Abp/WeChat/Work/ExternalContact/Transfers/WeChatWorkResignExtendProvider.cs @@ -0,0 +1,92 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Response; +using LINGYUN.Abp.WeChat.Work.Token; +using Microsoft.Extensions.DependencyInjection; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Features; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers; + +[RequiresFeature(WeChatWorkExternalContactFeatureNames.Enable)] +public class WeChatWorkResignExtendProvider : IWeChatWorkResignExtendProvider, ISingletonDependency +{ + protected IHttpClientFactory HttpClientFactory { get; } + protected IWeChatWorkTokenProvider WeChatWorkTokenProvider { get; } + + public WeChatWorkResignExtendProvider( + IHttpClientFactory httpClientFactory, + IWeChatWorkTokenProvider weChatWorkTokenProvider) + { + HttpClientFactory = httpClientFactory; + WeChatWorkTokenProvider = weChatWorkTokenProvider; + } + + public async virtual Task GetUnassignedListAsync( + WeChatWorkGetUnassignedListRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetUnassignedListAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task ResignedTransferCustomerAsync( + WeChatWorkResignedTransferCustomerRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.ResignedTransferCustomerAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GetResignedTransferResultAsync( + WeChatWorkGetResignedTransferResultRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GetResignedTransferResultAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } + + public async virtual Task GroupChatTransferAsync( + WeChatWorkGroupChatTransferRequest request, + CancellationToken cancellationToken = default) + { + Check.NotNull(request, nameof(request)); + + var token = await WeChatWorkTokenProvider.GetTokenAsync(cancellationToken); + var client = HttpClientFactory.CreateWeChatWorkApiClient(); + + using var response = await client.GroupChatTransferAsync(token.AccessToken, request, cancellationToken); + + var wechatResponse = await response.DeserializeObjectAsync(); + wechatResponse.ThrowIfNotSuccess(); + return wechatResponse; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/Newtonsoft/Json/ExternalProfileNewtonsoftJsonConverter.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/Newtonsoft/Json/ExternalProfileNewtonsoftJsonConverter.cs new file mode 100644 index 000000000..e3521bde5 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/Newtonsoft/Json/ExternalProfileNewtonsoftJsonConverter.cs @@ -0,0 +1,70 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; + +namespace Newtonsoft.Json; +internal class ExternalProfileNewtonsoftJsonConverter : JsonConverter +{ + public override bool CanWrite => true; + + public override void WriteJson(JsonWriter writer, ExternalProfile? value, JsonSerializer serializer) + { + writer.WriteStartObject(); + + if (value?.ExternalCorpName != null) + { + writer.WritePropertyName("external_corp_name"); + serializer.Serialize(writer, value.ExternalCorpName); + } + + if (value?.WechatChannels != null) + { + writer.WritePropertyName("wechat_channels"); + serializer.Serialize(writer, value.WechatChannels, value.WechatChannels.GetType()); + } + + if (value?.ExternalAttributes != null) + { + writer.WritePropertyName("external_attr"); + serializer.Serialize(writer, value.ExternalAttributes, value.ExternalAttributes.GetType()); + } + + writer.WriteEndObject(); + } + + public override ExternalProfile? ReadJson(JsonReader reader, Type objectType, ExternalProfile? existingValue, bool hasExistingValue, JsonSerializer serializer) + { + var jObject = JObject.Load(reader); + + var externalProfile = new ExternalProfile + { + WechatChannels = new List(), + ExternalAttributes = new List() + }; + + if (jObject.TryGetValue("external_corp_name", out var externalCorpNameToken)) + { + externalProfile.ExternalCorpName = externalCorpNameToken.ToString(); + } + if (jObject.TryGetValue("wechat_channels", out var wechatChannelsToken) && wechatChannelsToken.Type == JTokenType.Array) + { + externalProfile.WechatChannels = wechatChannelsToken.ToObject>(serializer)!; + } + if (jObject.TryGetValue("external_attr", out var externalAttrsToken) && externalAttrsToken.Type == JTokenType.Array) + { + foreach ( var externalAttrToken in externalAttrsToken) + { + var typeToken = externalAttrToken.SelectToken("type"); + if (typeToken != null) + { + var type = typeToken.Value(); + externalProfile.ExternalAttributes.Add( + ExternalAttributeDeserializeFactory.CreateExternalAttribute(type, externalAttrToken)); + } + } + } + + return externalProfile; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/README.md b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/README.md new file mode 100644 index 000000000..1ff6cd2c2 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/README.md @@ -0,0 +1,29 @@ +# LINGYUN.Abp.WeChat.Work.ExternalContact + +企业微信客户联系模块,提供企业微信应用开发的客户联系功能实现。 + +## 功能特性 + + +## 模块引用 + +```csharp +[DependsOn(typeof(AbpWeChatWorkExternalContactModule))] +public class YouProjectModule : AbpModule +{ + // other +} +``` + +## 配置项 + + +## 消息处理 + + +## 事件处理 + + +## 更多文档 + +* [企业微信客户联系文档](https://developer.work.weixin.qq.com/document/path/92109) diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Attachments.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Attachments.cs new file mode 100644 index 000000000..43d71ccc7 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Attachments.cs @@ -0,0 +1,33 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Attachments.Request; +using LINGYUN.Abp.WeChat.Work.Utils; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task UploadAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkUploadAttachmentRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/media/upload_attachment"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + urlBuilder.AppendFormat("&media_type={0}", request.MediaType.ToString().ToLowerInvariant()); + urlBuilder.AppendFormat("&attachment_type={0}", request.AttachmentType); + + var fileBytes = await request.Content.GetStream().GetAllBytesAsync(); + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = WeChatWorkHttpContentBuildHelper.BuildUploadMediaContent("media", fileBytes, request.Content.FileName) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Contacts.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Contacts.cs new file mode 100644 index 000000000..fde7c64cf --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Contacts.cs @@ -0,0 +1,28 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Request; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task GetExternalContactListAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetExternalContactListRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/contact_list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Customers.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Customers.cs new file mode 100644 index 000000000..2a3ce8111 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Customers.cs @@ -0,0 +1,89 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task GetCustomerListAsync( + this HttpMessageInvoker client, + string accessToken, + string userId, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + urlBuilder.AppendFormat("&userid={0}", userId); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Get, + urlBuilder.ToString()); + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task BulkGetCustomerAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkBulkGetCustomerRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/batch/get_by_user"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetCustomerAsync( + this HttpMessageInvoker client, + string accessToken, + string externalUserid, + string? cursor = null, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/get"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + urlBuilder.AppendFormat("&external_userid={0}", externalUserid); + if (!cursor.IsNullOrWhiteSpace()) + { + urlBuilder.AppendFormat("&cursor={0}", cursor); + } + + var httpRequest = new HttpRequestMessage( + HttpMethod.Get, + urlBuilder.ToString()); + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task UpdateCustomerRemarkAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkUpdateCustomerRemarkRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/remark"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Follows.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Follows.cs new file mode 100644 index 000000000..868b0e865 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Follows.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task GetFollowUserListAsync( + this HttpMessageInvoker client, + string accessToken, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/get_follow_user_list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Get, + urlBuilder.ToString()); + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.GroupChats.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.GroupChats.cs new file mode 100644 index 000000000..c8a2d3e80 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.GroupChats.cs @@ -0,0 +1,69 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task GetGroupChatListAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetGroupChatListRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/groupchat/list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetGroupChatAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetGroupChatRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/groupchat/get"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task OpengIdToChatIdAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkOpengIdToChatIdRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/opengid_to_chatid"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()) + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Strategies.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Strategies.cs new file mode 100644 index 000000000..833baac6b --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Strategies.cs @@ -0,0 +1,128 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task GetCustomerStrategyListAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetCustomerStrategyListRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/customer_strategy/list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetCustomerStrategyAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/customer_strategy/get"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetCustomerStrategyRangeAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetCustomerStrategyRangeRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/customer_strategy/get_range"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task CreateCustomerStrategyAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkCreateCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/customer_strategy/create"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task UpdateCustomerStrategyAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkUpdateCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/customer_strategy/edit"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task DeleteCustomerStrategyAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkDeleteCustomerStrategyRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/customer_strategy/del"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Tags.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Tags.cs new file mode 100644 index 000000000..8f6fb24b0 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Tags.cs @@ -0,0 +1,188 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task GetCropTagListAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetCropTagListRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/get_corp_tag_list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task CreateCropTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkCreateCropTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/add_corp_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task UpdateCropTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkUpdateCropTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/edit_corp_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task DeleteCropTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkDeleteCropTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/del_corp_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task MarkCropTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkMarkCropTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/mark_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetStrategyTagListAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetStrategyTagListRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/get_strategy_tag_list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task CreateStrategyTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkCreateStrategyTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/add_strategy_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task UpdateStrategyTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkUpdateStrategyTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/edit_strategy_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task DeleteStrategyTagAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkDeleteStrategyTagRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/del_strategy_tag"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Transfers.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Transfers.cs new file mode 100644 index 000000000..3b32435bb --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Transfers.cs @@ -0,0 +1,148 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Transfers.Request; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + public async static Task AssignCustomerAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkTransferCustomerRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/transfer_customer"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetTransferResultAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetTransferResultRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/transfer_result"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task OnjobTransferAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGroupChatOnjobTransferRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/groupchat/onjob_transfer"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetUnassignedListAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetUnassignedListRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/get_unassigned_list"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task ResignedTransferCustomerAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkResignedTransferCustomerRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/resigned/transfer_customer"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GetResignedTransferResultAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGetResignedTransferResultRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/resigned/transfer_result"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } + + public async static Task GroupChatTransferAsync( + this HttpMessageInvoker client, + string accessToken, + WeChatWorkGroupChatTransferRequest request, + CancellationToken cancellationToken = default) + { + var urlBuilder = new StringBuilder(); + urlBuilder.Append("/cgi-bin/externalcontact/groupchat/transfer"); + urlBuilder.AppendFormat("?access_token={0}", accessToken); + + var httpRequest = new HttpRequestMessage( + HttpMethod.Post, + urlBuilder.ToString()) + { + Content = new StringContent(request.SerializeToJson()), + }; + + return await client.SendAsync(httpRequest, cancellationToken); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.cs new file mode 100644 index 000000000..072b15046 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpClientWeChatWorkRequestExtensions.cs @@ -0,0 +1,5 @@ +namespace System.Net.Http; +internal static partial class HttpClientWeChatWorkRequestExtensions +{ + +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpResponseDeserializeExtensions.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpResponseDeserializeExtensions.cs new file mode 100644 index 000000000..f3abd415d --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Net/Http/HttpResponseDeserializeExtensions.cs @@ -0,0 +1,19 @@ +using LINGYUN.Abp.WeChat.Work; +using Newtonsoft.Json; +using System.Threading.Tasks; +using Volo.Abp.Http.Client; + +namespace System.Net.Http; +internal static class HttpResponseDeserializeExtensions +{ + public async static Task DeserializeObjectAsync(this HttpResponseMessage response) where T : WeChatWorkResponse + { + if (!response.IsSuccessStatusCode) + { + throw new AbpRemoteCallException($"Wechat work request error: {response.StatusCode} - {response.ReasonPhrase}"); + } + var responseContent = await response.Content.ReadAsStringAsync(); + + return JsonConvert.DeserializeObject(responseContent)!; + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Text/Json/Serialization/ExternalProfileSystemTextJsonConverter.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Text/Json/Serialization/ExternalProfileSystemTextJsonConverter.cs new file mode 100644 index 000000000..ec532e9f1 --- /dev/null +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work.ExternalContact/System/Text/Json/Serialization/ExternalProfileSystemTextJsonConverter.cs @@ -0,0 +1,63 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Models; +using System.Collections.Generic; + +namespace System.Text.Json.Serialization; +internal class ExternalProfileSystemTextJsonConverter : JsonConverter +{ + public override ExternalProfile Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + var root = doc.RootElement; + + var externalProfile = new ExternalProfile + { + WechatChannels = new List(), + ExternalAttributes = new List() + }; + + if (root.TryGetProperty("external_corp_name", out var corpNameElement)) + { + externalProfile.ExternalCorpName = corpNameElement.GetRawText(); + } + if (root.TryGetProperty("wechat_channels", out var wechatChannelsElement) && wechatChannelsElement.ValueKind == JsonValueKind.Array) + { + externalProfile.WechatChannels = JsonSerializer.Deserialize>(wechatChannelsElement.GetRawText(), options)!; + } + if (root.TryGetProperty("external_attr", out var externalAttrsElement) && externalAttrsElement.ValueKind == JsonValueKind.Array) + { + foreach ( var externalAttrElement in externalAttrsElement.EnumerateArray()) + { + if (externalAttrElement.TryGetProperty("type", out var typeElement) && typeElement.ValueKind != JsonValueKind.Null) + { + var type = typeElement.Deserialize(); + + externalProfile.ExternalAttributes.Add( + ExternalAttributeDeserializeFactory.CreateExternalAttribute(type, externalAttrElement)); + } + } + } + + return externalProfile; + } + + public override void Write(Utf8JsonWriter writer, ExternalProfile value, JsonSerializerOptions options) + { + writer.WriteStartObject(); + + writer.WritePropertyName("external_corp_name"); + JsonSerializer.Serialize(writer, value.ExternalCorpName, options); + + if (value.WechatChannels != null) + { + writer.WritePropertyName("wechat_channels"); + JsonSerializer.Serialize(writer, value.WechatChannels, value.WechatChannels.GetType(), options); + } + if (value.ExternalAttributes != null) + { + writer.WritePropertyName("external_attr"); + JsonSerializer.Serialize(writer, value.ExternalAttributes, value.ExternalAttributes.GetType(), options); + } + + writer.WriteEndObject(); + } +} diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/HttpContentBuildHelper.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/WeChatWorkHttpContentBuildHelper.cs similarity index 96% rename from aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/HttpContentBuildHelper.cs rename to aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/WeChatWorkHttpContentBuildHelper.cs index 190a1ff89..1542c47da 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/HttpContentBuildHelper.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/LINGYUN/Abp/WeChat/Work/Utils/WeChatWorkHttpContentBuildHelper.cs @@ -5,7 +5,7 @@ using System.Text; namespace LINGYUN.Abp.WeChat.Work.Utils; -internal static class HttpContentBuildHelper +public static class WeChatWorkHttpContentBuildHelper { public static HttpContent BuildUploadMediaContent( string mediaName, diff --git a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Media.cs b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Media.cs index fb4c2e77e..8ab66dcdc 100644 --- a/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Media.cs +++ b/aspnet-core/framework/wechat/LINGYUN.Abp.WeChat.Work/System/Net/Http/HttpClientWeChatWorkRequestExtensions.Media.cs @@ -41,7 +41,7 @@ internal static partial class HttpClientWeChatWorkRequestExtensions HttpMethod.Post, urlBuilder.ToString()) { - Content = HttpContentBuildHelper.BuildUploadMediaContent("media", fileBytes, request.Content.FileName) + Content = WeChatWorkHttpContentBuildHelper.BuildUploadMediaContent("media", fileBytes, request.Content.FileName) }; return await client.SendAsync(httpRequest, cancellationToken); @@ -61,7 +61,7 @@ internal static partial class HttpClientWeChatWorkRequestExtensions HttpMethod.Post, urlBuilder.ToString()) { - Content = HttpContentBuildHelper.BuildUploadMediaContent("file", fileBytes, request.Content.FileName) + Content = WeChatWorkHttpContentBuildHelper.BuildUploadMediaContent("file", fileBytes, request.Content.FileName) }; return await client.SendAsync(httpRequest, cancellationToken); diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/GlobalUsings.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/GlobalUsings.cs new file mode 100644 index 000000000..bd8299f6f --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/GlobalUsings.cs @@ -0,0 +1,2 @@ +global using Xunit; +global using Shouldly; \ No newline at end of file diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests.csproj new file mode 100644 index 000000000..e65ecd7cd --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests.csproj @@ -0,0 +1,20 @@ + + + + net9.0 + + false + Debug;Release;PostgreSQL + AnyCPU + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestBase.cs new file mode 100644 index 000000000..e78c65e39 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestBase.cs @@ -0,0 +1,6 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact; +public abstract class AbpWeChatWorkExternalContactTestBase : AbpTestsBase +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestModule.cs new file mode 100644 index 000000000..ab8d15e07 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/AbpWeChatWorkExternalContactTestModule.cs @@ -0,0 +1,22 @@ +using LINGYUN.Abp.Tests.Features; +using LINGYUN.Abp.WeChat.Work.ExternalContact.Features; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact; + +[DependsOn( + typeof(AbpWeChatWorkExternalContactModule), + typeof(AbpWeChatWorkTestModule))] +public class AbpWeChatWorkExternalContactTestModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.Map(WeChatWorkExternalContactFeatureNames.Enable, (feature) => + { + return true.ToString(); + }); + }); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider_Tests.cs new file mode 100644 index 000000000..d5ed50793 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Contacts/WeChatWorkExternalContactProvider_Tests.cs @@ -0,0 +1,22 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts.Request; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Contacts; + +public class WeChatWorkExternalContactProvider_Tests : AbpWeChatWorkExternalContactTestBase +{ + public readonly IWeChatWorkExternalContactProvider _provider; + public WeChatWorkExternalContactProvider_Tests() + { + _provider = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Get_External_Contact_List() + { + var res = await _provider.GetExternalContactListAsync(new WeChatWorkGetExternalContactListRequest()); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider_Tests.cs new file mode 100644 index 000000000..7d96f6ade --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerProvider_Tests.cs @@ -0,0 +1,62 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using Microsoft.Extensions.Configuration; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers; +public class WeChatWorkCustomerProvider_Tests : AbpWeChatWorkExternalContactTestBase +{ + public readonly IWeChatWorkCustomerProvider _provider; + public readonly IConfiguration _configuration; + public WeChatWorkCustomerProvider_Tests() + { + _provider = GetRequiredService(); + _configuration = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Get_Customer_List() + { + var userId = _configuration["WeChat:Work:ExternalContact:Customers:GetCustomerList:UserId"]; + var res = await _provider.GetCustomerListAsync(userId); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Bulk_Get_Customer() + { + var userId = _configuration["WeChat:Work:ExternalContact:Customers:BulkGetCustomer:UserId"]; + var res = await _provider.BulkGetCustomerAsync( + new WeChatWorkBulkGetCustomerRequest( + new List { userId })); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Get_Customer() + { + var externalUserid = _configuration["WeChat:Work:ExternalContact:Customers:GetCustomer:ExternalUserid"]; + var res = await _provider.GetCustomerAsync(externalUserid); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Update_Customer_Remark() + { + var userId = _configuration["WeChat:Work:ExternalContact:Customers:UpdateCustomerRemark:UserId"]; + var externalUserid = _configuration["WeChat:Work:ExternalContact:Customers:UpdateCustomerRemark:ExternalUserid"]; + var res = await _provider.UpdateCustomerRemarkAsync( + new WeChatWorkUpdateCustomerRemarkRequest( + userId, + externalUserid)); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider_Tests.cs new file mode 100644 index 000000000..56eeac713 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Customers/WeChatWorkCustomerStrategyProvider_Tests.cs @@ -0,0 +1,49 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Customers.Request; +using Microsoft.Extensions.Configuration; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Customers; +public class WeChatWorkCustomerStrategyProvider_Tests : AbpWeChatWorkExternalContactTestBase +{ + public readonly IWeChatWorkCustomerStrategyProvider _provider; + public readonly IConfiguration _configuration; + public WeChatWorkCustomerStrategyProvider_Tests() + { + _provider = GetRequiredService(); + _configuration = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Get_Customer_Strategy_List() + { + var res = await _provider.GetCustomerStrategyListAsync( + new WeChatWorkGetCustomerStrategyListRequest()); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Get_Customer_Strategy() + { + var exception = await Assert.ThrowsAsync(async () => + await _provider.GetCustomerStrategyAsync( + new WeChatWorkGetCustomerStrategyRequest(0))); + + exception.Code.ShouldBe($"WeChatWork:40058"); + exception.Message.ShouldContain($"invalid strategy_id:0"); + } + + [Fact] + public async virtual Task Should_Get_Customer_Strategy_Range() + { + var exception = await Assert.ThrowsAsync(async () => + await _provider.GetCustomerStrategyRangeAsync( + new WeChatWorkGetCustomerStrategyRangeRequest(0))); + + exception.Code.ShouldBe($"WeChatWork:40058"); + exception.Message.ShouldContain($"invalid strategy_id:0"); + } + + // TODO: 其他敏感接口自行实现测试 +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider_Tests.cs new file mode 100644 index 000000000..37ebc3653 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Follows/WeChatWorkFollowUserProvider_Tests.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Follows; +public class WeChatWorkFollowUserProvider_Tests : AbpWeChatWorkExternalContactTestBase +{ + public readonly IWeChatWorkFollowUserProvider _provider; + public WeChatWorkFollowUserProvider_Tests() + { + _provider = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Get_Follow_User_List() + { + var res = await _provider.GetFollowUserListAsync(); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider_Tests.cs new file mode 100644 index 000000000..5a10debdd --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/GroupChats/WeChatWorkGroupChatProvider_Tests.cs @@ -0,0 +1,47 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats.Request; +using Microsoft.Extensions.Configuration; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.GroupChats; +public class WeChatWorkGroupChatProvider_Tests : AbpWeChatWorkExternalContactTestBase +{ + public readonly IWeChatWorkGroupChatProvider _provider; + public readonly IConfiguration _configuration; + public WeChatWorkGroupChatProvider_Tests() + { + _provider = GetRequiredService(); + _configuration = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Get_Group_Chat_List() + { + var res = await _provider.GetGroupChatListAsync( + new WeChatWorkGetGroupChatListRequest()); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Get_Group_Chat() + { + var chatId = _configuration["WeChat:Work:ExternalContact:GroupChats:GetGroupChat:ChatId"]; + var res = await _provider.GetGroupChatAsync( + new WeChatWorkGetGroupChatRequest(chatId, true)); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_OpengId_To_ChatId() + { + var opengId = _configuration["WeChat:Work:ExternalContact:GroupChats:GetGroupChat:OpengIdToChatId"]; + var res = await _provider.OpengIdToChatIdAsync( + new WeChatWorkOpengIdToChatIdRequest(opengId)); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider_Tests.cs new file mode 100644 index 000000000..a9b702fc0 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.ExternalContact.Tests/LINGYUN/Abp/WeChat/Work/ExternalContact/Tags/WeChatWorkCropTagProvider_Tests.cs @@ -0,0 +1,90 @@ +using LINGYUN.Abp.WeChat.Work.ExternalContact.Tags.Request; +using Microsoft.Extensions.Configuration; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.WeChat.Work.ExternalContact.Tags; +public class WeChatWorkCropTagProvider_Tests : AbpWeChatWorkExternalContactTestBase +{ + public readonly IWeChatWorkCropTagProvider _provider; + public readonly IConfiguration _configuration; + public WeChatWorkCropTagProvider_Tests() + { + _provider = GetRequiredService(); + _configuration = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Get_Crop_Tag_List() + { + var res = await _provider.GetCropTagListAsync( + new WeChatWorkGetCropTagListRequest()); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Create_Crop_Tag() + { + var res = await _provider.CreateCropTagAsync( + new WeChatWorkCreateCropTagRequest() + { + GroupName = "test", + }); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + + await _provider.DeleteCropTagAsync( + WeChatWorkDeleteCropTagRequest.Group(new string[1] { res.TagGroup.GroupId })); + } + + [Fact] + public async virtual Task Should_Update_Crop_Tag() + { + var createRes = await _provider.CreateCropTagAsync( + new WeChatWorkCreateCropTagRequest() + { + GroupName = "test", + }); + + var updateRes = await _provider.UpdateCropTagAsync( + new WeChatWorkUpdateCropTagRequest(createRes.TagGroup.GroupId, "test_update")); + + updateRes.ErrorCode.ShouldBe(0); + updateRes.ErrorMessage.ShouldBe("ok"); + + await _provider.DeleteCropTagAsync( + WeChatWorkDeleteCropTagRequest.Group(new string[1] { createRes.TagGroup.GroupId })); + } + + [Fact] + public async virtual Task Should_Delete_Crop_Tag() + { + var createRes = await _provider.CreateCropTagAsync( + new WeChatWorkCreateCropTagRequest() + { + GroupName = "test", + }); + + var deleteRes = await _provider.DeleteCropTagAsync( + WeChatWorkDeleteCropTagRequest.Group(new string[1] { createRes.TagGroup.GroupId })); + + deleteRes.ErrorCode.ShouldBe(0); + deleteRes.ErrorMessage.ShouldBe("ok"); + } + + [Fact] + public async virtual Task Should_Mark_Crop_Tag() + { + var userId = _configuration["WeChat:Work:ExternalContact:Tags:MarkCropTag:UserId"]; + var externalUserId = _configuration["WeChat:Work:ExternalContact:Tags:MarkCropTag:ExternalUserId"]; + + var req = new WeChatWorkMarkCropTagRequest(userId, externalUserId); + req.CreateTag.Add("test_tag"); + var res = await _provider.MarkCropTagAsync(req); + + res.ErrorCode.ShouldBe(0); + res.ErrorMessage.ShouldBe("ok"); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkTestModule.cs b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkTestModule.cs index bb888cb1f..a95eb64f5 100644 --- a/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkTestModule.cs +++ b/aspnet-core/tests/LINGYUN.Abp.WeChat.Work.Tests/LINGYUN/Abp/WeChat/Work/AbpWeChatWorkTestModule.cs @@ -17,15 +17,14 @@ namespace LINGYUN.Abp.WeChat.Work; typeof(AbpTestsBaseModule))] public class AbpWeChatWorkTestModule : AbpModule { + private const string UserSecretsId = "5709C35E-27FF-4F5A-BBFD-F451285AA012"; + public override void PreConfigureServices(ServiceConfigurationContext context) { - var configurationOptions = new AbpConfigurationBuilderOptions + context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(builderAction: builder => { - BasePath = @"D:\Projects\Development\Abp\WeChat\Work", - EnvironmentName = "Test" - }; - - context.Services.ReplaceConfiguration(ConfigurationHelper.BuildConfiguration(configurationOptions)); + builder.AddUserSecrets(UserSecretsId); + })); } public override void ConfigureServices(ServiceConfigurationContext context) From 7bfb235de54f3254d55358371b5c2dbf4d93877d Mon Sep 17 00:00:00 2001 From: colin Date: Tue, 11 Nov 2025 08:51:37 +0800 Subject: [PATCH 2/2] feat(wechat): Add the missing module references --- .../LINGYUN.MicroService.WechatManagement.sln | 51 +++++++++++++++++++ ...rvice.WechatManagement.HttpApi.Host.csproj | 6 ++- ...atManagementHttpApiHostModule.Configure.cs | 18 +++++++ .../WechatManagementHttpApiHostModule.cs | 13 ++++- 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/aspnet-core/LINGYUN.MicroService.WechatManagement.sln b/aspnet-core/LINGYUN.MicroService.WechatManagement.sln index aeee78091..22ef88c5e 100644 --- a/aspnet-core/LINGYUN.MicroService.WechatManagement.sln +++ b/aspnet-core/LINGYUN.MicroService.WechatManagement.sln @@ -111,6 +111,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Identity.Sessio EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.SkyWalking", "framework\telemetry\LINGYUN.Abp.Telemetry.SkyWalking\LINGYUN.Abp.Telemetry.SkyWalking.csproj", "{7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Telemetry.OpenTelemetry", "framework\telemetry\LINGYUN.Abp.Telemetry.OpenTelemetry\LINGYUN.Abp.Telemetry.OpenTelemetry.csproj", "{164E4514-4E84-F13A-E24E-2A743753CDB3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Identity.WeChat.Work", "framework\wechat\LINGYUN.Abp.Identity.WeChat.Work\LINGYUN.Abp.Identity.WeChat.Work.csproj", "{CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.ExternalContact", "framework\wechat\LINGYUN.Abp.WeChat.Work.ExternalContact\LINGYUN.Abp.WeChat.Work.ExternalContact.csproj", "{3A6D0EA9-FA3F-4252-87D9-31845D57180D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.TestsBase", "tests\LINGYUN.Abp.TestBase\LINGYUN.Abp.TestsBase.csproj", "{757279EC-708D-D1AD-5E9E-7B757F3F7785}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.Tests", "tests\LINGYUN.Abp.WeChat.Work.Tests\LINGYUN.Abp.WeChat.Work.Tests.csproj", "{9DC2A982-8FA2-93BE-5FE1-3D7F7C105C39}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.ExternalContact.Tests", "tests\LINGYUN.Abp.WeChat.Work.ExternalContact.Tests\LINGYUN.Abp.WeChat.Work.ExternalContact.Tests.csproj", "{6628FB84-66C0-4023-9AA0-AAC4C0CC5917}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WeChat.Work.Handlers", "framework\wechat\LINGYUN.Abp.WeChat.Work.Handlers\LINGYUN.Abp.WeChat.Work.Handlers.csproj", "{E0DFCAD9-8AFE-A816-10F7-B4CA6691E910}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -281,6 +297,34 @@ Global {7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.ActiveCfg = Release|Any CPU {7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE}.Release|Any CPU.Build.0 = Release|Any CPU + {164E4514-4E84-F13A-E24E-2A743753CDB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {164E4514-4E84-F13A-E24E-2A743753CDB3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {164E4514-4E84-F13A-E24E-2A743753CDB3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {164E4514-4E84-F13A-E24E-2A743753CDB3}.Release|Any CPU.Build.0 = Release|Any CPU + {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5}.Release|Any CPU.Build.0 = Release|Any CPU + {3A6D0EA9-FA3F-4252-87D9-31845D57180D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A6D0EA9-FA3F-4252-87D9-31845D57180D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A6D0EA9-FA3F-4252-87D9-31845D57180D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A6D0EA9-FA3F-4252-87D9-31845D57180D}.Release|Any CPU.Build.0 = Release|Any CPU + {757279EC-708D-D1AD-5E9E-7B757F3F7785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {757279EC-708D-D1AD-5E9E-7B757F3F7785}.Debug|Any CPU.Build.0 = Debug|Any CPU + {757279EC-708D-D1AD-5E9E-7B757F3F7785}.Release|Any CPU.ActiveCfg = Release|Any CPU + {757279EC-708D-D1AD-5E9E-7B757F3F7785}.Release|Any CPU.Build.0 = Release|Any CPU + {9DC2A982-8FA2-93BE-5FE1-3D7F7C105C39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DC2A982-8FA2-93BE-5FE1-3D7F7C105C39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DC2A982-8FA2-93BE-5FE1-3D7F7C105C39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DC2A982-8FA2-93BE-5FE1-3D7F7C105C39}.Release|Any CPU.Build.0 = Release|Any CPU + {6628FB84-66C0-4023-9AA0-AAC4C0CC5917}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6628FB84-66C0-4023-9AA0-AAC4C0CC5917}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6628FB84-66C0-4023-9AA0-AAC4C0CC5917}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6628FB84-66C0-4023-9AA0-AAC4C0CC5917}.Release|Any CPU.Build.0 = Release|Any CPU + {E0DFCAD9-8AFE-A816-10F7-B4CA6691E910}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0DFCAD9-8AFE-A816-10F7-B4CA6691E910}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0DFCAD9-8AFE-A816-10F7-B4CA6691E910}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0DFCAD9-8AFE-A816-10F7-B4CA6691E910}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -337,6 +381,13 @@ Global {CC8DDC8C-CC0C-4534-8D9F-2C345E065869} = {52701ECE-3EBD-45EC-AD2C-0AAB15322311} {80EBBECC-EF11-4E5E-91DA-EEECED832F21} = {73ED64BB-7C39-42EA-B821-3DD697B9C36A} {7CF83493-6AF5-9C6D-01A7-AC7FC11BC2CE} = {FFACB4F0-33E0-4F8B-A97E-8FFFA10C12E6} + {164E4514-4E84-F13A-E24E-2A743753CDB3} = {FFACB4F0-33E0-4F8B-A97E-8FFFA10C12E6} + {CCC8A29C-1FC1-044F-895A-EC6894CDC8E5} = {EDBB7BC1-46F0-4803-A572-7F8FEF433BE2} + {3A6D0EA9-FA3F-4252-87D9-31845D57180D} = {EDBB7BC1-46F0-4803-A572-7F8FEF433BE2} + {757279EC-708D-D1AD-5E9E-7B757F3F7785} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {9DC2A982-8FA2-93BE-5FE1-3D7F7C105C39} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {6628FB84-66C0-4023-9AA0-AAC4C0CC5917} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {E0DFCAD9-8AFE-A816-10F7-B4CA6691E910} = {EDBB7BC1-46F0-4803-A572-7F8FEF433BE2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {EC9D01C1-EA3C-48C7-A279-4D35C8AD312E} diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/LY.MicroService.WechatManagement.HttpApi.Host.csproj b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/LY.MicroService.WechatManagement.HttpApi.Host.csproj index 18da14edf..7a608dcd2 100644 --- a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/LY.MicroService.WechatManagement.HttpApi.Host.csproj +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/LY.MicroService.WechatManagement.HttpApi.Host.csproj @@ -33,6 +33,7 @@ + @@ -52,13 +53,16 @@ - + + + + diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.Configure.cs b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.Configure.cs index e73992052..7fcfb0a18 100644 --- a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.Configure.cs +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.Configure.cs @@ -42,6 +42,7 @@ using Volo.Abp.Security.Claims; using Volo.Abp.SettingManagement; using Volo.Abp.Threading; using Volo.Abp.Timing; +using Volo.Abp.UI.Navigation.Urls; using Volo.Abp.VirtualFileSystem; namespace LY.MicroService.WechatManagement; @@ -177,6 +178,23 @@ public partial class WechatManagementHttpApiHostModule } }); } + + private void ConfigureUrls(IConfiguration configuration) + { + Configure(options => + { + var applicationConfiguration = configuration.GetSection("App:Urls:Applications"); + foreach (var appConfig in applicationConfiguration.GetChildren()) + { + options.Applications[appConfig.Key].RootUrl = appConfig["RootUrl"]; + foreach (var urlsConfig in appConfig.GetSection("Urls").GetChildren()) + { + options.Applications[appConfig.Key].Urls[urlsConfig.Key] = urlsConfig.Value; + } + } + }); + } + private void ConfigureTiming(IConfiguration configuration) { Configure(options => diff --git a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.cs b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.cs index 63b5c767d..97486d47c 100644 --- a/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.cs +++ b/aspnet-core/services/LY.MicroService.WechatManagement.HttpApi.Host/WechatManagementHttpApiHostModule.cs @@ -8,15 +8,18 @@ using LINGYUN.Abp.EventBus.CAP; using LINGYUN.Abp.ExceptionHandling.Emailing; using LINGYUN.Abp.Http.Client.Wrapper; using LINGYUN.Abp.Identity.Session.AspNetCore; +using LINGYUN.Abp.Identity.WeChat.Work; using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore; using LINGYUN.Abp.Saas.EntityFrameworkCore; using LINGYUN.Abp.Serilog.Enrichers.Application; using LINGYUN.Abp.Serilog.Enrichers.UniqueId; -using LINGYUN.Abp.Telemetry.SkyWalking; +using LINGYUN.Abp.Telemetry.OpenTelemetry; using LINGYUN.Abp.WeChat.MiniProgram; using LINGYUN.Abp.WeChat.Official; using LINGYUN.Abp.WeChat.SettingManagement; using LINGYUN.Abp.WeChat.Work; +using LINGYUN.Abp.WeChat.Work.ExternalContact; +using LINGYUN.Abp.WeChat.Work.Handlers; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -30,6 +33,7 @@ using Volo.Abp.DistributedLocking; using Volo.Abp.EntityFrameworkCore.MySQL; using Volo.Abp.FeatureManagement.EntityFrameworkCore; using Volo.Abp.Http.Client.IdentityModel.Web; +using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.MailKit; using Volo.Abp.Modularity; using Volo.Abp.PermissionManagement.EntityFrameworkCore; @@ -45,11 +49,15 @@ namespace LY.MicroService.WechatManagement; typeof(AbpAspNetCoreSerilogModule), typeof(AbpWeChatWorkApplicationModule), typeof(AbpWeChatWorkHttpApiModule), + typeof(AbpWeChatWorkExternalContactModule), + typeof(AbpWeChatWorkHandlersModule), typeof(AbpWeChatOfficialApplicationModule), typeof(AbpWeChatOfficialHttpApiModule), typeof(AbpWeChatMiniProgramModule), + typeof(AbpIdentityWeChatWorkModule), typeof(AbpWeChatSettingManagementModule), typeof(AbpSaasEntityFrameworkCoreModule), + typeof(AbpIdentityEntityFrameworkCoreModule), typeof(AbpFeatureManagementEntityFrameworkCoreModule), typeof(AbpPermissionManagementEntityFrameworkCoreModule), typeof(AbpSettingManagementEntityFrameworkCoreModule), @@ -68,7 +76,7 @@ namespace LY.MicroService.WechatManagement; typeof(AbpHttpClientWrapperModule), typeof(AbpMailKitModule), typeof(AbpClaimsMappingModule), - typeof(AbpTelemetrySkyWalkingModule), + typeof(AbpTelemetryOpenTelemetryModule), typeof(AbpAspNetCoreMvcWrapperModule), typeof(AbpAspNetCoreHttpOverridesModule), typeof(AbpIdentitySessionAspNetCoreModule), @@ -100,6 +108,7 @@ public partial class WechatManagementHttpApiHostModule : AbpModule ConfigureFeatureManagement(); ConfigureSettingManagement(); ConfigurePermissionManagement(); + ConfigureUrls(configuration); ConfigureTiming(configuration); ConfigureCaching(configuration); ConfigureAuditing(configuration);