Card API "Source was used before"

I am using the Cards SDK, and I have wrapped the results in my own PHP, including a wrapper around the SDK interface.
I discoved user problems in the real world, and began some intensive testing.
The problem involves a ‘source used before’ API error result.
My testing method involved

  1. Creating TEST customers
  2. Using the SDK inside my wrapper to do a pretty “Enter your card here” for customers with no saved card, then
  3. For customers, Using the SDK inside my wrapper with a pretty “Update your card info here”
  4. The wrapper checks the save card results and shows “card saved successfully” or “Could not save, please recheck your info” after the card has an error.
  5. I used my 7 personal cards to test.

Here’s my situation.
My code always successfully saves a card on the first try with a new customer. Correctly shows “saved”, or “recheck info” if I deliberately alter the CVV, etc. When I make corrections, the card is saved as it should be.

If I try to change the customer’s saved card with another of my cards, however, I now always get the following result:


            [category] => 'INVALID_REQUEST_ERROR'
            [code] => 'SOURCE_USED'
            [detail] => 'Source was used before.'
            [field] => 'source_id'

This generates the “Could not save, please recheck your info” in the wrapper.

I have checked the nonces, and they are different even if the same card is being submitted.

YOU SHOULD BE AWARE that i have used all of my cards numerous times in these tests. The “source was used before”-- but not with new customers.
But I don’t get this error on the initial save with a new customer, only on the update.

Any ideas?
Thanks for the help.

:wave: 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

Save a Card on File
Create a Card on File from a Payment ID
Charge a Card on File

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.

I can’t find any results when searching for this specific situation.

The error message “Source was used before” indicates that the payment token (nonce) you’re trying to use to save a card on file has already been used in a previous request. In the Square payment flow, a nonce is single-use and cannot be used multiple times.

When you’re updating a customer’s card on file, you need to generate a new payment token using the Web Payments SDK or In-App Payments SDK. This new token should be used in the CreateCard request to update the card on file for the customer.

Remember, each time a customer enters their card information, a new unique payment token is generated. So, even if the customer is entering the same card details, a new payment token should be generated for the update.

If you’re seeing the “Source was used before” error, it’s likely that your application is reusing a payment token that was already used in a previous CreateCard request. Ensure that your application is correctly generating and using a new payment token each time you’re updating a card on file.

This answer was reviewed by @Bryan-Square.

UPDATE:
I’m having the problem consistently now, even on intial saves.

I have checked the nonces and they are apparently unique, even for the same card, Examples:

cnon:CA4SEGg9x9cxt7XC1VJH6u4-0JcYAigB
cnon:CA4SECvnIdecAG0sZ1f0V3yKn4gYAigB

I going to guess that Square looks at the actual card related to the nonces? Not just the unique nonce?

Do I have to get a new card? Is there any way to clear existing Square database records?

What’s your application ID and are you using In-App Payments SDK? If so what version of the SDK are you using? :slight_smile:

App ID: sq0idp-XX6UWAX013YgL8UN-wNg8w

I don’t use any SDKs except the “create nonce” card SDK, and have had no problem with it (except i didn’t find it user friendly, and made some cosmetic adjustments. My changes have had no effect on nonce creation, and the nonce results work OK (until it starred burping about my 7 cards).

This isn’t a payment problem. It’s a Card problem only. And it appears to be specifically related to MY 7 CARDs. Customers are using my system and so far no complaints. I don’t know that any have tried a card update with this specific code, however.

My previous code wrapper (online yoga livestream subscriptions) was not liked by customers – not friendly enough, but it worked.

This new wrapper is in place for “Single class purchases” only, and it’s just gone live, and the wrapper working, and 4 customers who used it successfully today like it OK. But I noticed a non-square bug, and started retesting with my own cards, which is when I encountered the problem.

For cards I use my handwritten PHP curl code:

<?
	$json= "{'customer':'$customerid','nonce':'$nonce'}";
	$json=str_replace("'",'"',$json);
	$rawpost = array();
	$rawpost['card']['customer_id']="$customerid";
	$rawpost['source_id']=$nonce;
	$rawpost['idempotency_key']=$cardkey;
	$headers = array();
	$headers[] = "Content-Type: application/json";
	$headers[] = "Square-Version: 2021-06-16";
	$headers[] = "Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxx";
	$cardurl='https://connect.squareup.com/v2/cards';

	$postRequest = json_encode($rawpost);

	$ch = curl_init($cardurl);
	curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, $postRequest);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
	$result = curl_exec($ch);
	curl_close($ch);
	print_r($final_result);
?>

Which works just fine unless your using one of my 7 cards.

Is your site publicly hosted? If so what’s the link to get to it? :slight_smile:

Bryan: Thanks for your concern.

Naturally, the problem was with my code.
In some instances, the same nonce was being submitted 2x, not one time.
My curl code had succeeded on the first try, but was showing ‘Source was used before’ on the second instance.

I use jquery to initiate the curls, and use the returned jquery internal variable ‘data’ and use ‘console.log’ to view the curl processes that were done, and the result code.

What I did not know is that my console.log was only showing the results of the second attempt . jquery overwrote the ‘data’ variable, before the console.log results were displayed. So I was only seeing the failed process and results of the second attempt (essentially re-using the same info).

So the ‘data’ variable I was viewing always (CORRECTLY) said ‘source was used before’

I have removed the spurious second attempts, and all is good now.

Your request to see the live site helped; the implied suggestion that this was not a square problem or a card problem, but actually a coding problem helped a lot, forcing to make me refocus on what might be going on in my code. Also chatgpt helped me understand that how jquery handles its ‘data’ variable was a likely location for my spurious errors.

I have over-explained in hopes that this example might provide guidance to others, particularly about the use of jquery’s ‘data’ variable.

Thanks.

Glad to hear that you found the problem and it’s working as expected now. :slight_smile: