我正在尝试为ASP.NET C#中的WordPress WooCommerce创建Webhooks发送的WebHookHandler。
我开始创建ASP.NET C#Azure API应用程序WebApplication项目并添加相关引用(Microsoft.AspNet.WebHooks.Common,Microsoft.AspNet.WebHooks.Receivers,Microsoft.AspNet.WebHooks.Receivers.WordPress)。添加了WebHookConfig,WordPressWebHookHandler并在GlobalAsax中注册了WebHookConfig。
然后我将该应用程序发布为Azure App Service。
我的WordPressWebHookHandler仍然是示例的默认设置,如下所示:
public class WordPressWebHookHandler : WebHookHandler
{
public override Task ExecuteAsync(string receiver, WebHookHandlerContext context)
{
// make sure we're only processing the intended type of hook
if("WordPress".Equals(receiver, System.StringComparison.CurrentCultureIgnoreCase))
{
// todo: replace this placeholder functionality with your own code
string action = context.Actions.First();
JObject incoming = context.GetDataOrDefault<JObject>();
}
return Task.FromResult(true);
}
}
在WooCommerce中测试用户创建WebHook时,我可以在日志中看到请求,如下所示。
但不幸的是,在调试时从未收到它,我看到下面的错误。
我想也许我需要一个自定义WebHook而不是WordPress特定的一个,因为这是一个WooCommerce Webhook。或者可能在路由中处理错误并最终在另一个控制器中。
非常感谢任何帮助。
答案 0 :(得分:5)
期望HTML表单数据不匹配,实际上它应该是期待JSON。
WordPressWebHookHandler仍然是默认
这是导致错误的原因。如果您查看WordPressWebHookReceiver
方法实施ReceiveAsync()
,请调用ReadAsFormDataAsync()
方法,即不您想要的内容,因为Content-Type
是json
。所以,你想做ReadAsJsonAsync()
。
解决方案:请勿使用WordPressWebHookReceiver
并将其切换为另一个将调用ReadAsJsonAsync()
的人。
我想也许我需要一个自定义WebHook而不是WordPress特定的一个,因为这是一个WooCommerce Webhook。
你有正确的想法,所以我挖出了一些代码来解释为什么会发生这种情况。
下面的代码块是在WordPressWebHookReceiver中覆盖的ReceiveAsync()
方法。你可以看到它正在调用ReadAsFormDataAsync()
而不是你想要的......
public override async Task<HttpResponseMessage> ReceiveAsync(
string id, HttpRequestContext context, HttpRequestMessage request)
{
...
if (request.Method == HttpMethod.Post)
{
// here is what you don't want to be called
// you want ReadAsJsonAsync(), In short, USE A DIFFERENT RECEIVER.
NameValueCollection data = await ReadAsFormDataAsync(request);
...
}
else
{
return CreateBadMethodResponse(request);
}
}
通过存储库快速搜索调用ReadAsJsonAsync()
方法的类,可以显示以下接收方实现它:
我认为CustomWebHookReceiver符合您的要求,因此可以抓住NuGet here。否则你可以实现自己的,或者从这个类等派生出来。
Microsoft.AspNet.WebHooks.Receivers.Custom提供支持 接收ASP.NET WebHooks生成的WebHooks
开箱即用,你可以找到对Dropbox,GitHub,MailChimp的支持, PayPal,Pusher,Salesforce,Slack,Stripe,Trello和WordPress但是 可以支持任意数量的其他提供者
WebHook接收器通过注册来初始化,通常是在
WebApiConfig
静态类,例如:public static class WebApiConfig { public static void Register(HttpConfiguration config) { ... // Load receivers config.InitializeReceiveGitHubWebHooks(); } }
答案 1 :(得分:1)
您在请求中发送的数据格式存在问题。您必须使用HTML表单的格式作为错误消息说明。
此处描述了正确的POST数据格式:How are parameters sent in an HTTP POST request?
如果您的库不这样做,请不要忘记设置Content-Length标头并更正Content-Type。通常内容类型为application/x-www-form-urlencoded
。
答案 2 :(得分:1)
我想对Svek的答案做一些补充,因为我现在已经完成了我的概念验证,并对接收器有了更多了解。
他的回答指出了我正确的方向,但需要一点点补充。
<强> WordpressWebHookReceiver 强> 可以接受类型为HttpPost的Wordpress Webhooks。这不适用于Woocommerce,因为Woocommerce发送Json Webhook消息,并且将无法通过构建到WordpressWebHookReceiver类中的HttpPost验证。
<强> CustomWebHookReceiver 强> 可以采用自定义ASP.NET Webhooks。自定义ASP.NET webhooks具有特定的验证合作伙伴,包括但不限于“ms-signature”。即使添加标题也是不够的,因为签名也以与开箱即用的Woocommerce不同的方式用于加密消息。基本上没有改变Wohommerce的Webhook类,你无法将Woocommerce与CustomWebHookReceiver集成。
<强> GenericWebHookReceiver 强> 这是你想要的接收器,它基本上接受一组通用的Json数据,并且能够使用“code”查询参数来验证你可以在你的asp.net api应用程序的web.config中添加的秘密。我使用这个接收器来完成概念验证,同时获得了签名验证以及解密蝙蝠工作的消息。
我将开始构建一个真正的解决方案的基本类可以在下面查看,并将JObject更改为我从类调用的方法中的动态对象。如您所见,我目前添加了两种方法,一种用于客户创建,另一种用于订单创建,以调用插入Dynamics 365(以前的CRM)的相应方法。
public class GenericJsonWebHookHandler : WebHookHandler
{
public GenericJsonWebHookHandler()
{
this.Receiver = "genericjson";
}
public override Task ExecuteAsync(string generator, WebHookHandlerContext context)
{
var result = false;
try
{
// Get JSON from WebHook
var data = context.GetDataOrDefault<JObject>();
if(context.Id != "crcu" && context.Id != "cror")
return Task.FromResult(true);
if (context.Id == "crcu")
{
result = WoocommerceCRMIntegrations.Entities.Contact.CreateContactInCRM(data);
}
else if (context.Id == "cror")
{
result = WoocommerceCRMIntegrations.Entities.Order.CreateOrderInCRM(data);
}
}
catch (Exception ex)
{
result = false;
}
return Task.FromResult(result);
}
}