Xero - beautiful accounting software

Xero Developer Help Center

Xero Developer Community

Community > Getting Started >

Webhook failing with "Response contained a body"

Started by Gimhana Gagana -   in Getting Started

Hi,
During setup webhook, I have completed signature validation part. It correctly return 200, 401 for relevant situations. But it fails to "Intent To Receive". It shows in the Xero webhook set up page "Response contained a body".
Hi there,

You'll only see that message if your responses to the "Intent To Receive" webhook requests contained information in the body. You need to remove everything being sent in the body of your responses to pass that part of the validation.

Thanks,

Russell
 

Russell Dear (Xero Staff)  

I am having the same issue. How specifically can I remove everything from the body of the response. As far as I can see there's an empty JSON object and a 200 response code in the header. Example below is in php. I am really having trouble here.

$responsePayLoad = '{}';
header('HTTP/1.1 200');
echo $responsePayLoad;

Thanks!
 

benjamin waters  

I think it's not possible from php get webhook validation, I try every combination for response body and always got "Response contained a body"
 

jack Everard  

It sure is, we just had to move the touch point outside project root (not web root). This is partly because Xero coders (or more than likely their business analysts) have no idea what they are doing.

If you'd like an example of this, see their php API (which used to force us to create our own XML) and compare it with this.

 

Ben Waters  

I'm having this problem as well.
My code is shown below. There's nothing being sent after the headers, but I'm getting that error regardless of what I do. Any suggestions would be greatly appreciated.

One thing I found in some of their documentation is a link to Github's site for webhook Testing. Github has a tool for their webhook integrations that will allow you to see the request/response while troubleshooting issues with webhook creation. If we could see the actual response that Xero is getting back on ITR attempts, it might help to solve the problem.
 

César Castañeda  

$secret = 'cWp15d4e78JcqRfrLxsaz7Zvp6xc4JuuUKt01N+Pa5nAYJTVijl9FWVJPKKHpK/pL+eZNPxtAbjkwBSMxNZpQA==';
$headers = getallheaders();
$timestamp = time();
$payload = file_get_contents('php://input');
$signature = '';
$hash = base64_encode(hash_hmac('sha256', $payload, $secret, true));
$response = 200;
 

César Castañeda  

We use multiple WebHooks in our project and for some stupid reason Xero is the only one for which we need to use a separate file -outside our web root on it's own.

It doesn't matter if the headers values are empty, if it sees a key of any kind it will fail.

I hope this helps.
 

Ben Waters  

I'm trying to post the rest of my code and it won't let me :(
 

César Castañeda  

I don't want to see your code. Just move the endpoint somewhere away from your project where things like $_SESSION etc. won't interfere.
 

Ben Waters  

Ben, I actually saw your previous comment about having to have a file outside of your project root in order for it to work, but I've tested that as well. I'm still getting the error with ITr pointing to a file in my webroot.
 

César Castañeda  

http_response_code($response);
//header("Content-Length: 0");

ob_flush();
flush();
ob_end_clean();

exit;
 

César Castañeda  

I guess that's the problem. I wanted to share my code because my endpoint is completely standalone, and not affected by and project settiings/files/variables.

20 lines of code, no includes, sending an http response, and exiting.
 

César Castañeda  

The only bit of code it won't let me post here is two if statements that actually figure the correct response code.

Ben can you give an example of what you have that is working correctly for you?
 

César Castañeda  

My webhook is pointing to a file in webroot, and I actually stripped everything out except these few lines:

header_remove ();
http_response_code(200);
ob_flush();
flush();
ob_end_clean();
exit;

And I'm still getting that same error, 'Response contained a body'.
 

César Castañeda  

At the end of the day we're talking about accounting software that reuses invoice numbers. Who knows why things happen the way they do.
 

Ben Waters  

Lol, that may be true, but at the end of the day, I gotta eat and to do that I need to finish my current project :)

I found the answer. There's a defect in PHP 5.6 that will throw a deprecation error when you use:
file_get_contents('php://input');
 

César Castañeda  

The only solution is to edit p h p . i n i and set:
always_populate_raw_post_data = -1

You can't turn it off by setting error_reporting(0) or by using ini_set() to change that setting.

I discovered this when watching this helpful video, https://devblog.xero.com/lets-play-web-hooky-with-php-34a141dcac0a, and figuring out that it's the same method that I was using and it failed on my system as well.

In the process I also learned something new. I've been a huge fan of ngrok for awhile, but I didn't know until tonight that it has a response/request viewer built-in. (localhost:4040).

 

César Castañeda  

Really?!? I can't type p h p . i n i without the spaces in a post, what year is this?
 

César Castañeda