- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
public class AppWebhookDefinitionProvider : WebhookDefinitionProvider
{
public override void SetWebhooks(IWebhookDefinitionContext context)
{
//物料档案 - 全部可见
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T11071001_Created));
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T11071001_Updated));
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T11071001_Deleted));
//生产订单 - 生产管理可见
var featureC = new SimpleFeatureDependency("SCM.C");
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T13041001_Created, featureDependency: featureC));
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T13041001_Updated, featureDependency: featureC));
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T13041001_Deleted, featureDependency: featureC));
context.Manager.Add(new WebhookDefinition(name: AppWebHookNames.T13041001_MRP_Data, featureDependency: featureC));
//...
}
}
public class SCMCoreModule : AbpModule
{
public override void PreInitialize()
{
Configuration.Webhooks.Providers.Add<AppWebhookDefinitionProvider>();
Configuration.Webhooks.TimeoutDuration = TimeSpan.FromMinutes(1);
Configuration.Webhooks.IsAutomaticSubscriptionDeactivationEnabled = true;
Configuration.Webhooks.MaxSendAttemptCount = 3;
Configuration.Webhooks.MaxConsecutiveFailCountBeforeDeactivateSubscription = 10;
//...
}
//...
}
[AbpAuthorize(AppPermissions.Pages_Administration_WebhookSubscription)]
public class WebhookSubscriptionAppService : SCMAppServiceBase, IWebhookSubscriptionAppService
{
//...
[AbpAuthorize(AppPermissions.Pages_Administration_WebhookSubscription_Create)]
public async Task AddSubscription(WebhookSubscription subscription)
{
subscription.TenantId = AbpSession.TenantId;
await _webHookSubscriptionManager.AddOrUpdateSubscriptionAsync(subscription);
}
//...
}
public class T11071001Syncronizer :
IEventHandler<EntityCreatedEventData<T11071001>>,
IEventHandler<EntityUpdatedEventData<T11071001>>,
IEventHandler<EntityDeletedEventData<T11071001>>,
ITransientDependency
{
private readonly IAppWebhookPublisher _appWebhookPublisher;
public T11071001Syncronizer(IAppWebhookPublisher appWebhookPublisher)
{
_appWebhookPublisher = appWebhookPublisher;
}
public void HandleEvent(EntityCreatedEventData<T11071001> eventData)
{
DoWebhook("N", eventData.Entity);
}
public void HandleEvent(EntityUpdatedEventData<T11071001> eventData)
{
DoWebhook("U", eventData.Entity);
}
public void HandleEvent(EntityDeletedEventData<T11071001> eventData)
{
int? tenantId = eventData.Entity.TenantId;
string whName = AppWebHookNames.T11071001_Deleted;
var subscriptions = _appWebhookPublisher.GetSubscriptions(tenantId, whName);
if (subscriptions == null) { return; }
_appWebhookPublisher.PublishWebhookUOW(whName, eventData.Entity, tenantId, subscriptions);
}
}
private void DoWebhook(string nu, T11071001 entity)
{
int? tenantId = entity.TenantId;
var whCache = _appWebhookPublisher.GetWebhookCache(tenantId); if (whCache.Count == 0) { return; }
string whName = nu == "N" ? AppWebHookNames.T11071001_Created : AppWebHookNames.T11071001_Updated;
string whNameWX = AppWebHookNames.WX_T11071001_Created;
string whNameDD = AppWebHookNames.DD_T11071001_Created;
bool isWH = whCache.Names.ContainsKey(whName);
bool isWX = whCache.Names.ContainsKey(whNameWX);
bool isDD = whCache.Names.ContainsKey(whNameDD);
if (!(isWH || isWX || isDD)) { return; }
var data = ObjectMapper.Map<T11071001WebhookDto>(entity);
//内部接口
if (isWH)
{
_appWebhookPublisher.PublishWebhookUOW(whName, data, tenantId, whCache.Names[whName], false);
}
//企业微信内部群
if (isWX)
{
var wxData = new WxTCardWebhookDto { template_card = GetWxTCard(data, tenantId, nu) };
_appWebhookPublisher.PublishWebhookUOW(whNameWX, wxData, tenantId, whCache.Names[whNameWX], true);
}
//钉钉内部群
if (isDD)
{
var title = GetNUTitle(nu, L(T));
var mdText = GetNewMarkdown(data, title);
var ddData = new DdMarkdownWebhookDto { markdown = new DdMarkdownContentDto { title = title, text = mdText } };
_appWebhookPublisher.PublishWebhookUOW(whNameDD, ddData, tenantId, whCache.Names[whNameDD], true);
}
}
public SCMWebhookCacheItem GetWebhookCache(int? tenantId)
{
return SetAndGetCache(tenantId);
}
private SCMWebhookCacheItem SetAndGetCache(int? tenantId, string keyName = "SubscriptionCount")
{
int tid = tenantId ?? 0; var cacheKey = $"{keyName}-{tid}";
return _cacheManager.GetSCMWebhookCache().Get(cacheKey, () =>
{
int count = 0;
var names = new Dictionary<string, List<WebhookSubscription>>();
UnitOfWorkManager.WithUnitOfWork(() =>
{
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
if (_featureChecker.IsEnabled(tid, "SCM.H")) //Feature核查
{
var items = _webhookSubscriptionRepository.GetAllList(e => e.TenantId == tenantId && e.IsActive == true);
count = items.Count;
foreach (var item in items)
{
if (string.IsNullOrWhiteSpace(item.Webhooks)) { continue; }
var whNames = JsonHelper.DeserializeObject<string[]>(item.Webhooks); if (whNames == null) { continue; }
foreach (string whName in whNames)
{
if (names.ContainsKey(whName))
{
names[whName].Add(item.ToWebhookSubscription());
}
else
{
names.Add(whName, new List<WebhookSubscription> { item.ToWebhookSubscription() });
}
}
}
}
}
});
return new SCMWebhookCacheItem(count, names);
});
}
public void PublishWebhookUOW(string webHookName, object data, int? tenantId, List<WebhookSubscription> webhookSubscriptions = null, bool sendExactSameData = false)
{
UnitOfWorkManager.WithUnitOfWork(() =>
{
using (UnitOfWorkManager.Current.SetTenantId(tenantId))
{
Publish(webHookName, data, tenantId, webhookSubscriptions, sendExactSameData);
}
});
}
private void Publish(string webhookName, object data, int? tenantId, List<WebhookSubscription> webhookSubscriptions, bool sendExactSameData = false)
{
if (string.IsNullOrWhiteSpace(webhookName)) { return; }
//若无直接传入订阅则按webhookName查询
webhookSubscriptions ??= _webhookSubscriptionRepository.GetAllList(subscriptionInfo =>
subscriptionInfo.TenantId == tenantId &&
subscriptionInfo.IsActive &&
subscriptionInfo.Webhooks.Contains("\"" + webhookName + "\"")
).Select(subscriptionInfo => subscriptionInfo.ToWebhookSubscription()).ToList();
if (webhookSubscriptions.IsNullOrEmpty()) { return; }
var webhookInfo = SaveAndGetWebhookEvent(tenantId, webhookName, data);
foreach (var webhookSubscription in webhookSubscriptions)
{
var jobArgs = new WebhookSenderArgs
{
TenantId = webhookSubscription.TenantId,
WebhookEventId = webhookInfo.Id,
Data = webhookInfo.Data,
WebhookName = webhookInfo.WebhookName,
WebhookSubscriptionId = webhookSubscription.Id,
Headers = webhookSubscription.Headers,
Secret = webhookSubscription.Secret,
WebhookUri = webhookSubscription.WebhookUri,
SendExactSameData = sendExactSameData
};
//指定队列执行任务,由触发事件的server执行
IBackgroundJobClient hangFireClient = new BackgroundJobClient();
hangFireClient.Create<WebhookSenderJob>(x => x.ExecuteAsync(jobArgs), new EnqueuedState(AppVersionHelper.MachineName));
}
}
public override void SignWebhookRequest(HttpRequestMessage request, string serializedBody, string secret)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}
//第三方接口,不添加签名Header
if (IsThirdAPI(request))
{
return;
}
if (string.IsNullOrWhiteSpace(serializedBody))
{
throw new ArgumentNullException(nameof(serializedBody));
}
var secretBytes = Encoding.UTF8.GetBytes(secret);
using (var hasher = new HMACSHA256(secretBytes))
{
request.Content = new StringContent(serializedBody, Encoding.UTF8, "application/json");
var data = Encoding.UTF8.GetBytes(serializedBody);
var sha256 = hasher.ComputeHash(data);
var headerValue = string.Format(CultureInfo.InvariantCulture, SignatureHeaderValueTemplate, BitConverter.ToString(sha256));
request.Headers.Add(SignatureHeaderName, headerValue);
}
}
protected override HttpRequestMessage CreateWebhookRequestMessage(WebhookSenderArgs webhookSenderArgs)
{
return webhookSenderArgs.WebhookName switch
{
AppWebHookNames.JST_supplier_upload => JSTHttpRequestMessage(webhookSenderArgs), //聚水潭 - 供应商上传
//...
_ => new HttpRequestMessage(HttpMethod.Post, webhookSenderArgs.WebhookUri)
};
}
protected override void AddAdditionalHeaders(HttpRequestMessage request, WebhookSenderArgs webhookSenderArgs)
{
//第三方接口,不添加Header
if (IsThirdAPI(request))
{
return;
}
foreach (var header in webhookSenderArgs.Headers)
{
if (request.Headers.TryAddWithoutValidation(header.Key, header.Value))
{
continue;
}
if (request.Content.Headers.TryAddWithoutValidation(header.Key, header.Value))
{
continue;
}
throw new Exception($"Invalid Header. SubscriptionId:{webhookSenderArgs.WebhookSubscriptionId},Header: {header.Key}:{header.Value}");
}
}
protected override async Task<(bool isSucceed, HttpStatusCode statusCode, string content)> SendHttpRequest(HttpRequestMessage request)
{
using var client = _httpClientFactory.CreateClient(); //避免使用 new HttpClient()方式
client.Timeout = _webhooksConfiguration.TimeoutDuration;
var response = await client.SendAsync(request);
var isSucceed = response.IsSuccessStatusCode;
var statusCode = response.StatusCode;
var content = await response.Content.ReadAsStringAsync();
//第三方接口,需要处理回传的数据
if (IsThirdAPI(request))
{
string method = TryGetHeader(request.Headers, "ThirdAPI1");
int tenantId = Convert.ToInt32(TryGetHeader(request.Headers, "ThirdAPI2"));
switch (method)
{
case AppWebHookNames.JST_supplier_upload: await JSTSupplierUploadResponse(method, content, tenantId); break;
//...
default: break;
}
}
return (isSucceed, statusCode, content);
}
基于ABP/ZERO的Webhook功能实现,进行一些扩展改造,可以实现业务数据按用户订阅进行推送,包括推送到第三方接口(企业微信群、钉钉等),在很大程度上提升了业务系统的灵活性与实用性.
最后此篇关于扩展ABP的Webhook功能,推送数据到第三方接口(企业微信群、钉钉群等)的文章就讲到这里了,如果你想了解更多关于扩展ABP的Webhook功能,推送数据到第三方接口(企业微信群、钉钉群等)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我想知道是否有任何方法可以为所有意图激活 webhook(除了一个一个激活它)。谢谢! 最佳答案 目前还没有这样的功能,但我遇到了类似的问题,这就是我解决它的方法: 下载所有意图的zip文件 写一个程
谁能在最基本的层面上解释一下 Incoming webhook、Outgoing webhook 和 O365 webhook 之间的区别 最佳答案 Webhooks 是一种轻型 HTTP 模式,用于
好吧,这可能 super 简单,但我只是没有足够的背景知识来确定: 如果我定义了一个 webhook 回调(例如,OpenAPI 中的回调):我可以从常规网页使用该回调吗? 我会假设是的,否则有什么意
我正在尝试设置 Grafana 以将 webhook 发送到 Microsoft Teams。我可以通过终端 curl 到地址,但不能通过 Grafanas 界面。 我将 URL 添加到 Grafan
我正在玩Paypal REST(php)环境,我喜欢玩沙盒webhooks。 是否可以将Paypal沙箱Webhooks与本地设置一起使用? http://localhost/test 是无效的网址
使用 slack webhooks,我可以使用消息中的简码发送表情符号: curl -X POST --data-urlencode "payload={\"channel\": \"#my_noti
我们想将Slack Webhook(传出Webhook)与内部Web服务一起使用。 我们公司位于防火墙后面,因此必须将外部连接列入白名单。 Slack似乎有多个地址,它将从中发送API请求,并且似乎没
我们目前正在实现 Mailgun 的 Webhook,以将电子邮件回复转换为应用程序中评论线程中的回复。我们设置一条路由来匹配收件人,并将操作设置为 store(notify="https://exa
我可以通过应用程序脚本通过 webhook 将消息发送到聊天室,但是我如何发送回复该消息。这是一种单向聊天。我如何才能通过 webhook 将其作为对话流. 最佳答案 您可以提供一个threadKey
我正在尝试注册一个 evernote webhook。但似乎注册表不起作用。 Evernote webhook 注册表格: 我填写了表格,点击“提交”,但总是得到以下错误响应: {"error":"R
我可以通过应用程序脚本通过 webhook 将消息发送到聊天室,但是我如何发送回复该消息。这是一种单向聊天。我如何才能通过 webhook 将其作为对话流. 最佳答案 您可以提供一个threadKey
我有一个订阅页面提要事件的 webhook。 我希望它告诉我何时在页面或用户管理的页面上创建了公共(public)事件。 应用仪表板告诉我这是将发送给我的 JSON 对象: { "field": "
当我在 google 项目和 API.AI 代理上创建操作时,我使用自己的服务作为 API.AI 实现 webhook。我希望 API.AI 会调用我的 webhook。但是当我通过谷歌上的 Acti
我正在按照本教程在 App Inventor 中发送电子邮件:https://www.hackster.io/taifun/trigger-ifttt-to-send-an-email-using-a
我正在尝试将消息发布到松弛团队中的任何 channel 。 我的 webhook 已正确创建并安装到我的测试团队中。作为安装过程的一部分,我选择了“发布到#channel1” 当我查看权限时,我看到我
我快速浏览了与 Bluesnap webhooks 相关的 IPN 类型和参数 - https://support.bluesnap.com/v2.2.7/docs/ipn-parameter-ref
我有一个 HTML 表格,我正在尝试通过 webhook 将其发布到 Slack。 有没有办法将 HTML 表格发布到 Slack? 这是 HTML 代码: HTML Tabl
我在我的 Slack 工作区中创建了一个传入 Webhook。我正在使用第三方工具将 JSON 对象发布到 Hook url。我想向@user_1 发送通知 我的问题是通知发送到我和该用户@user_
我正在开发一个与 Trello 紧密集成的应用程序,并使用 Trello webhooks 做很多事情。但是,我在 Trello 的开发人员文档中找不到任何地方可能触发 webhook 的“操作”是什
当我创建这篇文章时,我只是在stackoverflow上找到了没有任何回复的帖子...... TelegramBot. "Webhook can be set up only on ports 80,
我是一名优秀的程序员,十分优秀!