API WordPress WooCommerce ASP.net WebHookHandler: запрос WebHook должен содержать тело объекта, отформатированное как данные формы HTML
Я пытаюсь создать WebHookHandler для веб-крючков, отправленных из WordPress WooCommerce в ASP.NET C#.
Я начал с создания проекта веб-приложения API ASP.NET C# Azure и добавления соответствующих ссылок (Microsoft.AspNet.WebHooks.Common, Microsoft.AspNet.WebHooks.Receivers, Microsoft.AspNet.WebHooks.Receivers.WordPress). Добавил WebHookConfig, WordPressWebHookHandler и зарегистрировал WebHookConfig в GlobalAsax.
Затем я опубликовал приложение в качестве службы приложений Azure.
Мой 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);
}
}
При тестировании WebHook Создание пользователя в WooCommerce я вижу запрос в журнале, как показано ниже.
Но, к сожалению, он никогда не получен во время отладки, и я вижу ошибку ниже.
Я думаю, может быть, мне нужен собственный WebHook вместо конкретного WordPress, так как это WooCommerce Webhook. Или, возможно, он неправильно обрабатывается в маршрутизации и заканчивается в другом контроллере.
Буду признателен за любую оказанную помощь.
3 ответа
Я хотел бы внести некоторые дополнения в ответ Свека, так как теперь я получил законченное доказательство концепции и немного разбираюсь в приемниках.
Его ответ указал мне правильное направление, но нуждается в небольшом дополнении.
WordpressWebHookReceiver Может принимать в Wordpress Webhooks типа HttpPost. Это не работает с Woocommerce, так как Woocommerce отправляет сообщения Json Webhook и не проходит проверку HttpPost, встроенную в класс WordpressWebHookReceiver.
CustomWebHookReceiver Может принимать пользовательские ASP.NET Webhooks. У пользовательских веб-зацепок ASP.NET есть специальный партнер для проверки, который включает, но не ограничивается "ms-signature". Даже добавления заголовка будет недостаточно, поскольку подпись также используется не по умолчанию, а из Woocommerce для шифрования сообщения. По сути, доходит до того, что вы не можете интегрировать WooCommerce с CustomWebHookReceiver без изменения классов Webhook WooCommerce.
GenericWebHookReceiver Это требуемый приемник, который принимает в основном общий набор данных Json и сможет использовать параметр запроса "code" для проверки секрета, который вы можете добавить в web.config вашего API-приложения asp.net. Я использовал этот приемник для завершения проверки концепции и получил как проверку подписи, так и расшифровку сообщения, работающего прямо на летучей мыши.
Мой базовый класс, который я начну встраивать в реальное решение, можно посмотреть ниже и изменить 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);
}
}
Ваш WebHookReceiver неправильный
Существует несоответствие ожидания данных формы HTML, тогда как на самом деле это ожидание JSON.
WordPressWebHookHandler по-прежнему по умолчанию
Это то, что вызывает вашу ошибку. Если вы посмотрите на WordPressWebHookReceiver
, ReceiveAsync()
реализация метода, призывает к ReadAsFormDataAsync()
метод, который не то, что вы хотите, как ваш Content-Type
является json
, Итак, вы хотите делать ReadAsJsonAsync()
,
Решение: не используйте WordPressWebHookReceiver
и переключите его на другой, который будет вызывать ReadAsJsonAsync()
,
Глядя на код
Я думаю, может быть, мне нужен собственный WebHook вместо конкретного WordPress, так как это WooCommerce Webhook.
У вас была правильная идея, поэтому я выкопал часть кода, чтобы точно объяснить, почему это происходит.
Блок кода ниже является ReceiveAsync()
метод, который переопределяется в WordPressWebHookReceiver. Вы можете видеть, что это вызывает 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()
метод, показывает, что следующие приемники реализуют его:
- DynamicsCrmWebHookReceiver
- ZendeskWebHookReceiver
- AzureAlertWebHookReceiver
- KuduWebHookReceiver
- MyGetWebHookReceiver
- VstsWebHookReceiver
- BitbucketWebHookReceiver
- CustomWebHookReceiver
- DropboxWebHookReceiver
- GitHubWebHookReceiver
- PaypalWebHookReceiver
- StripeWebHookReceiver
- PusherWebHookReceiver
Я предположил, что CustomWebHookReceiver будет соответствовать вашим требованиям, поэтому можете взять NuGet здесь. В противном случае вы можете реализовать свой собственный, или извлечь его из этого класса и т. Д.
Настройка получателя WebHook
(Скопировано из документации Microsoft)
https://www.nuget.org/packages?q=Microsoft.AspNet.WebHooks.Receivers.Custom обеспечивает поддержку для получения веб-книг, сгенерированных ASP.NET веб-книг
Из коробки вы можете найти поддержку Dropbox, GitHub, MailChimp, PayPal, Pusher, Salesforce, Slack, Stripe, Trello и WordPress, но можно поддерживать любое количество других провайдеров.
Инициализация Приемника WebHook
Приемники WebHook инициализируются путем их регистрации, как правило, в
WebApiConfig
статический класс, например:public static class WebApiConfig { public static void Register(HttpConfiguration config) { ... // Load receivers config.InitializeReceiveGitHubWebHooks(); } }
Существует проблема с форматом данных, который вы отправляете в своем запросе. Вы должны использовать формат формы HTML, как указано в сообщении об ошибке.
Правильный формат данных POST описан здесь: Как параметры отправляются в запросе HTTP POST?
Не забудьте установить заголовок Content-Length и исправить Content-Type, если ваша библиотека этого не делает. Обычно тип контента application/x-www-form-urlencoded
,