Hi @hollymcr,
> The idempotency_key that was failing was 50 chars long. Looking at the Square API info 128 chars should be accepted
Thanks for bring this to our attention! Can you please share a link to the Square API docs that mention 128 characters?
Here’s a link to the Square API library we use in our extension and is says the idempotency_key
has to be MAX 45 characters (screenshot: https://d.pr/i/mD8UTF)
In our Square extension we set the idempotency key on payment requests to have the value: {32-char-hash}
+ :
+ Order number + -
+ number of failed attempts.
With a 45 character limit, that leaves 12 characters after the {hash}:
for the order ID and number of failed attempts, which I believe will only become a problem after the order ID gets larger than 999,999,999.
In the examples you shared, you had XXXXX-ORDER-1234
in the Failed case: 77c03b5942fa2784e3304b45a4a164d5:XXXXX-ORDER-1234
.
What is adding the XXXXX-ORDER-
to the idempotency key value??
Do you have some other plugin that customises the value returned by get_order_number
to include the xxxx-order- at the front?
Thanks for reporting this.
OK, I hadn’t realised I was using an order number plugin – it’s been there since I started using Woo – but I have this installed:
woo-custom-and-sequential-order-number.
(I have no idea what order numbers look like by default any more!)
As to the API docs: looking again I can’t see a specific figure documented and did find at least one place where 45 was mentioned just now, but here’s a reference to it being 192 (I can’t now find 128)
Clearly the problem I have is a clash between two extensions but as far as I can tell neither are doing anything wrong. Not sure what a sensible solution would be…
Question: You say idemopotency_key is set to {hash}:{order number}-{attempts}, but what is {hash} generated from?
From a glance at the code, {hash} seems to be based on the site URL, so should stay the same for all my site transactions. But is there any reason for it to be so?
Thought: What would be the implication of having idemopotency_key set to md5(“$site:$order_number”) so that, regardless of order number structure, the result was always 32 chars? You could then set idempotency_key to {hash}-{attempts} and (for any reasonable number of attempts!) always remain below 45 chars. That would make it compatible with any plugin which changed the order number structure.
I can see an advantage of the current structure when looking at the logs but as far as I can see the actual order number is always present within the data structure that contains the idempotency_key.
Or maybe a better fix: if idempotency_key ever exceeds 45 chars, do something to make force it under 45 chars, eg (untested):
public function get_idempotency_key( $key_input = '' ) {
if ( '' === $key_input ) {
$key_input = uniqid( '', false );
}
$hash_source = get_option( 'siteurl' );
if ( strlen( $key_input ) > 12 ) {
// As things stand, idempotency_key will exceed 45 chars
// Therefore include $key_input in the md5 hash (to ensure uniqueness)
// and shorten $key_input to make everything fit
$hash_source .= ':' . $key_input;
$key_input = substr( $key_input, -12 );
}
return apply_filters( 'wc_square_idempotency_key', md5( $hash_source ) . ':' . $key_input );
}
That should result in no changes to idempotency_key for sites where it already works, but fix any that don’t because of a long order number. (Can you see any problems with it?)
Still don’t understand why it used to work then stopped though, as I have always had this order number structure. Maybe something was letting >45 char idempotency_key values work, then started to enforce the limit?
Hi there @hollymcr,
Thanks for getting back to us!
The issue has already been reported to our developers and they’re working on a permanent fix so idemopotency_key
value stays under 45 symbols even with customer order numbers.
Meanwhile, please use add the following code snippet to your site and check if the issue is resolved now:
function custom_square_idempotency_key( $key ) {
if ( strlen( $key ) > 45 ) {
$hash_split = explode( ':', $string );
$short_hash = substr( $hash_split[0], 0, 10 );
$key = $short_hash . substr( $string, strlen( $hash_split[0] ) );
}
return $key;
}
add_filter( 'wc_square_idempotency_key', 'custom_square_idempotency_key', 10, 1);
Still don’t understand why it used to work then stopped though, as I have always had this order number structure.
Since Square 2.2.0 we upgraded from the Transactions API to the Payments API which is having this limitation.
Enjoy the rest of your day and stay safe!
Hi there @hollymcr,
I wanted to let you know that the error you were seeing has been fixed in Square 2.2.1
so you don’t need a code snippet anymore.
Please let us know if you’re still seeing issues after an update!
Cheers!
Plugin Support
AW a11n
(@slash1andy)
Automattic Happiness Engineer
Hey there!
We haven’t heard back from you in a while, so I’m going to mark this as resolved – if you have any further questions, you can start a new thread.
Sorry for not getting back to you, for some reason I didn’t see the email notifications of updates.
I agree that this is likely resolved now but in the meantime I had changed my order number structure to ensure it never exceeded the character limit so it no longer affects me and the fix won’t therefore affect me either.
This is a busy time for my store but when things get quiet I’ll return to a custom order format that challenges the character limit and report back if there are issues. But having looked at the code I’m confident your fix is fine.
Many thanks for your investigation and fix for this.