1

Im using stymiee/authnetjson library to consume and verify an authorize.net webhook in the sandbox environment.

I can verify my headers include

X-ANET-Signature: sha512=C3CC15F7801AA304C0840C85E4F0222A15338827EE3D922DC13A6BB99DF4BFE7D8E235A623480C0EAF3151F7B008E4DFBFDC6E9F493A6901961C5CFC10143289

And my json body is

{"notificationId":"c5933ec1-2ef6-4962-a667-10552d19c481","eventType":"net.authorize.payment.authcapture.created","eventDate":"2018-01-20T20:36:54.9163559Z","webhookId":"66cf7109-f42f-45b9-bf36-f1ade83eac48","payload":{"responseCode":1,"authCode":"37ATT8","avsResponse":"Y","authAmount":550.00,"entityName":"transaction","id":"60038744863"}}

I have a signature key set up and it all seems correct and similar to the one in the tests for the library

My code looks like this:

$signature_key = "...";
$headers = getallheaders();
$payload = file_get_contents("php://input");

$webhook = new JohnConde\Authnet\AuthnetWebhook($signature_key, $payload, $headers);

if ( ! $webhook->isValid() ) {
    error_log("Payload not valid");
}

I have also tried removing the $headers argument from the constructor args

When I execute a test transaction, it is not valid so I get 'Payload not valid' in the logs. How can I debug this problem?

Thanks! NFV

John Conde
  • 217,595
  • 99
  • 455
  • 496
nfvindaloo
  • 948
  • 2
  • 11
  • 24
  • What version of the library are you using? There was a release a few weeks ago to version 3.1.3 which addressed a case sensitivity issue that would cause this to happen. – John Conde Jan 20 '18 at 22:10
  • Hi John my composer.lock says version 3.1.3 – nfvindaloo Jan 21 '18 at 11:17
  • Now that I am looking into your question I see what the issue is. The library is expecting `X-Anet-Signature` and not `X-ANET-Signature`. Ironically this was the change I made in 3.1.3 as another user was seeing `X-Anet-Signature` and not `X-ANET-Signature` and I validated that in my tests. Looks like Authorize.Net is not consistent in the case sensitivity of their headers. I'll update the library to be case agnostic and post here once it's available for download. That should be in less than 24 hours. – John Conde Jan 21 '18 at 14:35
  • A quick workaround is to version 3.1.2 which is expecting the header in that exact format. – John Conde Jan 21 '18 at 14:40
  • Ah ok makes sense, although strange that the headers are not being set consistently, thanks John! – nfvindaloo Jan 21 '18 at 18:15

1 Answers1

1

This issue was caused by the X-ANET-Signature being case sensitive. I orinigally was looking for it exactly as you see it but another user reached to me with the same issue but they were getting X-Anet-Signature instead which the code was not expecting. When I was doing my debugging I saw the same issue and figured either I somehow made an error when I first coded this or Authnet made a change and I needed to adapt.

Apparently that is not the issue. I am unsure why we are seeing inconsistent cases for this header but I will reach out to Authorize.Net to see if I can find out what the story is.

But the fix is easy: Update the library to use version 3.1.4 which is case agnostic when checking this header's value.

For the sake of answering the literal title of this question, here's a sample script for dubugging this issue:

<?php

namespace myapplication;

use JohnConde\Authnet\AuthnetWebhook;

// Include a configuration file with the Authorize.Net API credentials
require('./config.inc.php');

// Include my application autoloader
require('./vendor/autoload.php');

$errorCode = null;
$errorText = null;
$isValid   = null;

try {
    $headers = getallheaders();
    $payload = file_get_contents("php://input");
    $webhook = new AuthnetWebhook(AUTHNET_SIGNATURE, $payload, $headers);
    $isValid = 'false';
    if ($webhook->isValid()) {
        $isValid = 'true';
    }
    $hashedBody = strtoupper(hash_hmac('sha512', $payload, AUTHNET_SIGNATURE));
    $hash = explode('=', $headers['X-Anet-Signature'])[1];
    $valid = strtoupper(explode('=', $headers['X-Anet-Signature'])[1]) === $hashedBody;
}
catch (\Exception $e) {
    $errorCode = $e->getCode();
    $errorText = $e->getMessage();
}
finally {
    ob_start(); 
    var_dump([
        'errorCode'  => $errorCode,
        'errorText'  => $errorText,
        'isValid'    => $isValid,
        'headers'    => $headers,
        'payload'    => $payload,
        'hashedBody' => $hashedBody,
        'hash'       => $hash,
        'valid'      => $valid
    ]);
    $dump = ob_get_clean();
    file_put_contents('webhooks.txt', $dump, FILE_APPEND | LOCK_EX);
}
John Conde
  • 217,595
  • 99
  • 455
  • 496