WordPress WooCommerce ASP.net API WebHookHandler: Die WebHook-Anforderung muss einen als HTML-Formulardaten formatierten Entitätstext enthalten

Lesezeit: 6 Minuten

Benutzeravatar von Kevin Hendricks
Kevin Hendricks

Ich versuche, einen WebHookHandler für Webhooks zu erstellen, die von WordPress WooCommerce in ASP.NET C # gesendet werden.

Ich begann mit der Erstellung eines ASP.NET C# Azure API App WebApplication Project und dem Hinzufügen der relevanten Referenzen (Microsoft.AspNet.WebHooks.Common, Microsoft.AspNet.WebHooks.Receivers, Microsoft.AspNet.WebHooks.Receivers.WordPress). WebHookConfig, WordPressWebHookHandler hinzugefügt und WebHookConfig in GlobalAsax registriert.

Anschließend habe ich die Anwendung als Azure App Service veröffentlicht.

Mein WordPressWebHookHandler ist immer noch der Standard der Beispiele und sieht so aus:

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);
    }
}

Beim Testen eines Webhook zur Benutzererstellung in WooCommerce kann ich die Anfrage im Protokoll wie unten sehen.

Webhook-Anforderungsprotokoll

Aber leider wird es beim Debuggen nie empfangen und ich sehe den folgenden Fehler.

Fehler im Webbook-Anforderungsprotokoll

Ich denke, vielleicht brauche ich einen benutzerdefinierten WebHook anstelle des WordPress-spezifischen, da dies ein WooCommerce-Webhook ist. Oder es wird im Routing falsch behandelt und landet in einem anderen Controller.

Jede Hilfe wird sehr geschätzt.

Benutzeravatar von Svek
Schwek

Ihr WebHookReceiver ist falsch

Es gibt eine Diskrepanz bei der Erwartung von HTML-Formulardaten, obwohl eigentlich JSON erwartet werden sollte.

WordPressWebHookHandler ist immer noch der Standard

Dies ist die Ursache Ihres Fehlers. Schaut man sich die an WordPressWebHookReceiverdas ReceiveAsync() Methodenimplementierung, ruft auf ReadAsFormDataAsync() Methode, die ist nicht was Sie wollen, als Ihre Content-Type ist json. Sie wollen also tun ReadAsJsonAsync().

Lösung: Verwenden Sie nicht die WordPressWebHookReceiver und schalte es auf ein anderes um, das anruft ReadAsJsonAsync().


Blick auf den Code

Ich denke, vielleicht brauche ich einen benutzerdefinierten WebHook anstelle des WordPress-spezifischen, da dies ein WooCommerce-Webhook ist.

Sie hatten die richtige Idee, also habe ich einen Teil des Codes ausgegraben, um genau zu erklären, warum dies geschah.

Der folgende Codeblock ist die ReceiveAsync() Methode, die in der überschrieben wird WordPressWebHookReceiver. Sie können sehen, dass es anruft ReadAsFormDataAsync() was du nicht willst…

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);
    }
}

Eine schnelle Suche im Repository nach Klassen, die die aufrufen ReadAsJsonAsync() -Methode, zeigt, dass die folgenden Empfänger sie implementieren:

  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

Ich bin davon ausgegangen, dass die CustomWebHookReceiver würde zu deinen anforderungen passen, also kannst die greifen NuGet hier. Andernfalls können Sie Ihre eigene implementieren oder von dieser Klasse ableiten usw.


Konfigurieren eines WebHook-Empfängers

(Kopiert aus der Microsoft-Dokumentation)

Microsoft.AspNet.WebHooks.Receivers.Custom bietet Unterstützung für den Empfang von WebHooks, die von ASP.NET-WebHooks generiert wurden

Out of the Box finden Sie Unterstützung für Dropbox, GitHub, MailChimp, PayPal, Pusher, Salesforce, Slack, Stripe, Trello und WordPress, aber es ist möglich, eine beliebige Anzahl anderer Anbieter zu unterstützen

Initialisieren eines WebHook-Empfängers

WebHook-Empfänger werden initialisiert, indem sie registriert werden, normalerweise in der WebApiConfig Statische Klasse, zum Beispiel:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...

        // Load receivers
        config.InitializeReceiveGitHubWebHooks();
    }
}

  • Da verstehe ich eins nicht. Ich implementiere dies in meinem Web-API-Projekt für Zendesk? muss ich einen controller mit route api/webhooks/incoming erstellen. und wie rufe ich die WebHookHandler-Klasse auf?

    – coder771

    16. Oktober 2018 um 8:20 Uhr

  • @coder771 Vielleicht möchten Sie ein wenig online suchen, da es viele verschiedene Möglichkeiten gibt, wie Sie WebHooks in Ihrem Projekt implementieren können. Ich würde damit beginnen, zu verstehen, wie die Request-Pipeline-Mechanik in Asp Net Core funktioniert, bevor ich zu dem Schluss komme, dass Sie einen Controller benötigen.

    – Schwek

    16. Oktober 2018 um 9:59 Uhr

Benutzeravatar von Alexander Ushakov
Alexander Uschakow

Es gibt ein Problem mit dem Datenformat, das Sie in Ihrer Anfrage senden. Sie müssen das Format des HTML-Formulars verwenden, wie in Ihrer Fehlermeldung angegeben.

Das richtige POST-Datenformat wird hier beschrieben: Wie werden Parameter in einer HTTP-POST-Anforderung gesendet?

Vergessen Sie nicht, den Content-Length-Header festzulegen und den Content-Type zu korrigieren, wenn Ihre Bibliothek dies nicht tut. Normalerweise ist der Inhaltstyp application/x-www-form-urlencoded.

  • Hallo Alexander, danke für deine Antwort. Leider sendet Woocommerce / WordPress die Inhalte standardmäßig in Json, was auch mein bevorzugter Standard ist. Ich sehe viele Beiträge zum Empfangen von Json mit ASP.NET-Webhooks im Allgemeinen, aber es scheint bei mir nicht zu funktionieren.

    – Kevin Hendriks

    20. Februar 2017 um 8:43 Uhr

Ich würde gerne einige Ergänzungen zu Sveks Antwort vornehmen, da ich jetzt meinen Proof-of-Concept abgeschlossen habe und etwas mehr über die Empfänger verstehe.

Seine Antwort wies mich in die richtige Richtung, bedarf aber einer kleinen Ergänzung.

WordPressWebHookReceiver
Kann WordPress Webhooks vom Typ HttpPost aufnehmen. Dies funktioniert nicht mit Woocommerce, da Woocommerce Json-Webhook-Nachrichten sendet und die HttpPost-Validierung fehlschlägt, die in die WordPressWebHookReceiver-Klasse integriert ist.

CustomWebHookReceiver
Kann benutzerdefinierte ASP.NET-Webhooks aufnehmen. Die benutzerdefinierten ASP.NET-Webhooks haben einen bestimmten Partner für die Validierung, der die „MS-Signatur“ umfasst, aber nicht darauf beschränkt ist. Selbst das Hinzufügen des Headers reicht nicht aus, da die Signatur auch auf andere Weise als bei Woocommerce verwendet wird, um die Nachricht zu verschlüsseln. Grundsätzlich kommt man an einen Punkt, an dem man Woocommerce nicht mit dem CustomWebHookReceiver integrieren kann, ohne die Webhook-Klassen von Woocommerce zu ändern.

GenericWebHookReceiver
Dies ist der gewünschte Empfänger, der im Grunde genommen einen generischen Satz von Json-Daten akzeptiert und den Abfrageparameter “Code” verwenden kann, um das Geheimnis zu überprüfen, das Sie in der web.config Ihrer asp.net-API-Anwendung hinzufügen können. Ich habe diesen Empfänger verwendet, um den Proof-of-Concept abzuschließen, und sowohl die Signaturvalidierung als auch die Entschlüsselung der Nachricht funktionierten direkt von der Fledermaus.

Meine grundlegende Klasse, die ich in eine echte Lösung einbauen werde, kann unten angezeigt werden und ändert das JObject in ein dynamisches Objekt in den Methoden, die ich von der Klasse aus aufrufe. Wie Sie sehen können, habe ich derzeit zwei Methoden hinzugefügt, eine für die Kundenerstellung und eine für die Auftragserstellung, um die jeweiligen Methoden aufzurufen, die eine Einfügung in Dynamics 365 (ehemals CRM) vornehmen.

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);
    }
}

  • Kein Problem, ich dachte, Sie verdienen die Anerkennung für die ausführliche Antwort, die mich in die richtige Richtung gewiesen hat. Danke nochmal

    – Kevin Hendriks

    28. Februar 2017 um 15:14 Uhr

  • Hallo. Ich verwende WooComm 4.0.1 und habe unseren Ansatz ausprobiert, aber er funktioniert bei mir überhaupt nicht. “Error: Delivery URL hat Antwortcode zurückgegeben: 415” Wenn ich den Hook trotzdem auslöse, sehe ich, dass er in den WordPress-Protokollen durchgegangen ist. Aber auf der .net-Seite steht im Protokoll: w3wp.exe Information: 0: Verarbeitung eingehender WebHook-Anfrage mit Empfänger „genericjson“ und ID „crcpn“. w3wp.exe Information: 0 : Die WebHook-Anforderung muss einen als JSON formatierten Entitätstext enthalten. Nicht sicher, wo ich falsch liege. Hilfe bitte!

    – Mudasser Mian

    12. Mai 2020 um 15:45 Uhr

1397450cookie-checkWordPress WooCommerce ASP.net API WebHookHandler: Die WebHook-Anforderung muss einen als HTML-Formulardaten formatierten Entitätstext enthalten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy