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

Но, к сожалению, он никогда не получен во время отладки, и я вижу ошибку ниже.

Ошибка журнала запроса Webook

Я думаю, может быть, мне нужен собственный WebHook вместо конкретного WordPress, так как это WooCommerce Webhook. Или, возможно, он неправильно обрабатывается в маршрутизации и заканчивается в другом контроллере.

Буду признателен за любую оказанную помощь.

11

Решение

Ваш 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() метод, показывает, что следующие приемники реализуют его:

  1. DynamicsCrmWebHookReceiver
  2. ZendeskWebHookReceiver
  3. AzureAlertWebHookReceiver
  4. KuduWebHookReceiver
  5. MyGetWebHookReceiver
  6. VstsWebHookReceiver
  7. BitbucketWebHookReceiver
  8. CustomWebHookReceiver
  9. DropboxWebHookReceiver
  10. GitHubWebHookReceiver
  11. PaypalWebHookReceiver
  12. StripeWebHookReceiver
  13. PusherWebHookReceiver

Я предположил, что CustomWebHookReceiver будет соответствовать вашим требованиям, так что можете взять NuGet здесь. В противном случае вы можете реализовать свой собственный, или извлечь его из этого класса и т. Д.


Настройка получателя WebHook

(Скопировано из Документация Microsoft)

Microsoft.AspNet.WebHooks.Receivers.Custom обеспечивает поддержку
получение WebHooks, сгенерированных ASP.NET WebHooks

Из коробки вы можете найти поддержку 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();
}
}
5

Другие решения

Существует проблема с форматом данных, который вы отправляете в своем запросе. Вы должны использовать формат HTML-формы, как сказано в сообщении об ошибке.

Правильный формат данных POST описан здесь: Как параметры отправляются в запросе HTTP POST?

Не забудьте установить заголовок Content-Length и исправить Content-Type, если ваша библиотека этого не делает. Обычно тип контента application/x-www-form-urlencoded,

1

Я хотел бы сделать некоторые дополнения к ответу Свека, так как теперь я завершил свою проверку концепции и немного разбираюсь в приемниках.

Его ответ указал мне правильное направление, но нуждается в небольшом дополнении.

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);
}
}
1
По вопросам рекламы [email protected]