We are using the PHP SDK and have been successfully cancelling payments that aren’t captured yet for a while. Recently, we’ve noticed that we are getting a 400 Bad Request from cloudflare. Did something change that I’m unaware or or is there something going on with that endpoint?
I’m Square Dev AI, here to help answer your question!
Based on the information you’ve provided, the following documentation will help answer your question:
Additional Documentation
If this documentation helped you find a solution, please check the box indicating that this reply solves the problem.
Otherwise one of our Developer Advocates will provide additional assistance shortly.
What’s your application ID?
I’m not seeing any errors in the API Logs. Do you have the error message that Cloudflare provided?
This is part of the log.
[headers:Core\Types\Sdk\CoreApiResponse:private] => Array
(
[0] => HTTP/1.1 400 Bad Request
[Server] => cloudflare
[Date] => Fri, 20 Sep 2024 12:54:57 GMT
[Content-Type] => text/html
[Content-Length] => 155
[Connection] => close
[CF-RAY] => -
)
[result:Core\Types\Sdk\CoreApiResponse:private] => <html>
400 Bad Request
400 Bad Request
cloudflare
[body:Core\Types\Sdk\CoreApiResponse:private] => <html>
400 Bad Request
400 Bad Request
cloudflare
[errors:Square\Http\ApiResponse:private] => Array
(
[0] => Square\Models\Error Object
(
[category:Square\Models\Error:private] => V1_ERROR
[code:Square\Models\Error:private] => Unknown
[detail:Square\Models\Error:private] =>
[field:Square\Models\Error:private] =>
)
)
When you retry the request does it succeed? Also do you have the snippet of code that calls the endpoint? Also do you have a payment_id
that this happened with?
No. It doesn’t work if I retry. The client and I have both tried many times. This was the payment id: pSnkog4JHE09iJ8Xr6T2mdvEDHBZY.
I tested on sandbox to see if I got the same result and it was. That payment id was rVoM08bI80V6I803ZCOjLkGmXuJZY.
$this->init_api();
$payments_api = new PaymentsApi($this->api_client);
try {
//if token is expired refresh it
$this->refresh_token();
$this->response = $payments_api->cancelPayment($transaction_id);
$this->log_message(print_r($this->response,true) . PHP_EOL, false, 'void_transaction');
} catch (\SquareConnect\ApiException $e) {
$this->api_error = true;
$this->response = $e->getResponseBody();
$this->log_message(print_r($e,true) . PHP_EOL, true, 'void_transaction');
}
In the case of the above code transaction_id is the payment_id that I sent. I also want to re-iterate I am using the PHP SDK. I am on version [2024-06-04]
Oh, your using the transaction_id
. If the payment was take with the Payments API you’ll need to use the payment_id
. You should not be using anything related to the Transactions API unless your using Readers SDK or Point of Sale API.
If you read the bottom of my reply, you’ll see that I stated that the $transaction_id in the case you see is the actual payment_id. I should rename it.
I have confirmed from the logs returned that we are using the payment_id.
Okay, thank you! How was the payment created? Was it with our API or was it with an SDK? What are the steps to reproduce this.
The payment was created with the SDK to your API. We use the create payment call to start a delay capture payment. We store the response with the order. Then we can extract the payment id to use in the admin of our system, where the client can either capture the transaction or cancel it. It seems the cancelling no longer returns a good response.
I haven’t been able to replicate this with the SDK. I see from your API logs that you haven’t actually called CancelPayment which means the request is being blocked by Cloudflare. Is there anything that could be malforming the requests?
Ok. Thank you. I was looking for a response like that. Recently, we’ve implemented some new WAF rules and other bot protection. Maybe, something is breaking the request. I’ll talk with the team.
Hi again. I had to put this down, but I’m back to testing.
I was able to do normal curl request from our server with our sandbox access token. The cancel request went through no issue. The differences are the headers passed by the Square SDK. Looks like instead of passing the header ‘Content-Type’, the SDK uses ‘Accept’. The SDK also passes along the user-agent string ‘Square-PHP-SDK/37.1.0.20240604 (2024-06-04) PHP/8.1.30 (Linux-3.10.0-1160.92.1.el7.x86_64)’.
Would any of this cause us to get blocked by Cloudflare. I feel like the user-agent string might be an issue, but I don’t know what rules y’all have setup.
Thanks again for your time on this matter.
Hi, helping out Bryan here.
Odd that the SDK would set Content-Type
of Accept
. Could you try seeing if you can set the Content-Type
to application/json
?
It is not setting Content-Type as Accept. It is not even passing Content-Type. It is passing what should be the content type as the header ‘Accept’. So ‘Accept: application/json’
Here is the SDK Request before it’s being passed, so you can get an idea of what I’m saying.
[request:protected] => Square\Http\HttpRequest Object
(
[httpMethod:Core\Types\Sdk\CoreRequest:private] => Post
[headers:Core\Types\Sdk\CoreRequest:private] => Array
(
[Square-Version] => 2024-06-04
[user-agent] => Square-PHP-SDK/37.1.0.20240604 (2024-06-04) PHP/8.1.30 (Linux-3.10.0-1160.92.1.el7.x86_64)
[Authorization] => Bearer xxxxxxxxxxxx
[Accept] => application/json
)
[queryUrl:Core\Types\Sdk\CoreRequest:private] => https://connect.squareupsandbox.com/v2/payments/rV2pfyaGRhwopqEggOc5t3e3WWdZY/cancel
[parameters:Core\Types\Sdk\CoreRequest:private] => Array
(
)
)
Hey @bibdev! Based on that user-agent string, it looks like you’re using an older version of the SDK. Do you mind trying to update to 38.1.0.20240919 (Square API version 2024-09-19
) and seeing if this issue persists?
I upgraded to latest version and did a couple tests with our system to make sure everything was working. Checking out with our system worked fine. Capturing a payment worked as well. Cancelling by a payment_id did not work. Here is the request being sent by the SDK.
[request:protected] => Square\Http\HttpRequest Object
(
[httpMethod:Core\Types\Sdk\CoreRequest:private] => Post
[headers:Core\Types\Sdk\CoreRequest:private] => Array
(
[Square-Version] => 2024-09-19
[user-agent] => Square-PHP-SDK/38.1.0.20240919 (2024-09-19) PHP/8.1.30 (Linux-3.10.0-1160.92.1.el7.x86_64)
[Authorization] => Bearer xxxxxxxxxxxxx
[Accept] => application/json
)
[queryUrl:Core\Types\Sdk\CoreRequest:private] => https://connect.squareupsandbox.com/v2/payments/vpb7DlZ71UbMutwH5rxvnbgsbuSZY/cancel
[parameters:Core\Types\Sdk\CoreRequest:private] => Array
(
)
)
I found that other API calls from the SDK do have the header ‘Content-Type’. I believe somewhere you are explicitly setting it for other calls, but not for this cancel call. Just my hunch. Being more familiar with the code base, you might be able to prove this faster than I can.