Creating card on file from a successful payment not working with verification_token

Hi

Trying to implement this from api docs

I use verifyBuyer in the JS SDK to get a verification_token that is send to the createPayment API request (PHP), and the intent is set as ‘CHARGE’

$bofy->setVerificationToken($post_data[‘verification_token’]);

Payment is taken successfully, I then create the customer using CreateCustomerRequest, which again all works fine.

Then I try and create a card on file using the payment_id as the source_id , but no matter what I do it always throws an error:

{
“errors”: [
{
“category”: “PAYMENT_METHOD_ERROR”,
“code”: “CARD_DECLINED_VERIFICATION_REQUIRED”,
“detail”: “Card declined. A verification is required to process this payment. See https://developer.squareup.com/docs/sca-overview for more information.”
}
]
}

I tried sending the same verification_token used for the payment, but same error.

Am I missing something? Can you not use 3DS / verifyBuyer on initial payment if you want to create a card on file from that payment?

You’ll need to call verifyBuyer() a second time with the payment_id and have the intent set as CHARGE. Once you get the new verification_token you’ll use that as the verification_token in the CreateCard request. :slightly_smiling_face:

Hi Bryan

Thanks for quick response. But verifyBuyer() is a javascript call, how would I call this again once I am in the API routine… Throwing the user back to enter their card details again would be pretty confusing UI for them to understand?

If I switched my logic around and changed Web SDK intent to STORE (still calling verifyBuyer) then the api calls created a customer then a card on file then took a payment using the returned card id would this get around having to call vedrifyBuyer twice?

None of the card on file docs describe how to use verification_token in a CreateCard request.

Hi Bryan

Before I get too much more into my code. Can I just check that card on file is actually going to work for my clients situation.

They sell hotel stays. The customer pays a deposit (online with 3DS) and we want to create a card on file from this initial interaction so we can automatically take the balance 4 weeks before they travel via a cron (so card holder not present). The deposit page informed them of the amount and date of future payment.

Will square up card on file work for this situation or am I barking up the wrong tree?

Yes, the card on file option will work for your use case. As for calling verifyBuyer() when the customer isn’t present it would be similar to our card on file with verification example. :slightly_smiling_face:

I am confused now. Surely you can’t expect a cron job to run js and submit an html web form as in the example you sent?

So are you saying that this set of api calls from your docs won’t work for any card details collected using verifyBuyer ?

I am now pulling my hair out - I can create a customer, create a card card, but then when I try CreatePayment using the newly created card on file all I get is error:

Array
(
[0] => Square\Models\Error Object
(
[category:Square\Models\Error:private] => PAYMENT_METHOD_ERROR
[code:Square\Models\Error:private] => CARD_DECLINED_VERIFICATION_REQUIRED
[detail:Square\Models\Error:private] => Authorization error: ‘CARD_DECLINED_VERIFICATION_REQUIRED’
[field:Square\Models\Error:private] =>
)

)

Should I store card using the Web SDK and not the API? How would I then take a payment from that stored card immediately after it has been created?

Yes, that is an html web form however you can configure your cron to call the verifyBuyer() function to get the verification_token. It’s just a function call that your server can make to get the token. Once you have the token you can complete the payment. :slightly_smiling_face:

Hi Bryan

I really appreciate your help, but I don’t know how I can call a javascript function (verifyBuyer) in the middle of a php cron job, or even why I would need to for a card on file already created with a valid verification_code? Are card holder not presents not supported by squareup?

Also, as far as I can work out, verifyBuyer js call initiates the 3DS popup for the user to complete the verification codes/steps, which in an unattended cron with card holder not present makes no sense?

Are there any examples of card payments created using the php/curl API where the card on file was created with a verification_code?

Even when I try and create a payment via the API explorer using a customer_id and card_id I get the same error

"errors": [
    {
      "code": "CARD_DECLINED_VERIFICATION_REQUIRED",
      "detail": "Authorization error: 'CARD_DECLINED_VERIFICATION_REQUIRED'",
      "category": "PAYMENT_METHOD_ERROR"
    }

From digging around I guess what I need to know is does squareup support Merchant Initiated Transactions for cards on file created initially created with SCA enabled

Card payments with the card holder not present is supported. With SCA a verification_token has to be created for every payment. Just saving the card on file with the initial verification_token and charging the card won’t work. The verifyBuyer() JS call does initiate 3DS but with card on file, the information that passed in is the information from the customer profile that you get from the Customers API. Like in our example it asks for a customer_id and the card_id.

From what I’ve found from searching around is that you’ll need to run this in a browser to call verifyBuyer(). :slightly_smiling_face:

From what I’ve found from searching around is that you’ll need to run this in a browser to call verifyBuyer().

So from what you are saying squareup in UK/EU (where SCA in mandatory) is not capable of doing MIT (Merchant Initiated Transactions) as a cron can’t open a browser. Maybe with node.js you could call the function, but we don’t use node, and if verifyBuyer() opened some sort of popup for user to interact with, there is no user in a cron!

I am now talking to Mousa Khan from your dev team as my clients account manager put me in touch with him. He seems to think there is some sort of issue with the sandbox environment with SCA and card on file transactions that is the issue.

A Merchant Initiated Transaction is available with Square. We take care of this under the hood. The only problem today is that its not supported in our sandbox. It’s only supported in production. If you want to test in sandbox you’ll need to call verifyBuyer(). We’re constantly working to improve our features based on feedback like this, so I’ll be sure to share your request to the API product team. :slightly_smiling_face:

I found this post after hitting the same CARD_DECLINED_VERIFICATION_REQUIRED issue as the OP. I have found a solution so adding it here for anyone else experiencing the same problem.

I had wanted the process to be:

Find Or Create a Customer
Take Payment
IF successful THEN
Store Card On File
ENDIF

and then later via cron or a server-side trigger, use the Card On File to take another payment.

However, it doesn’t appear to be possible to store a Card On File after taking payment (where SCA is required), without a second verification token via verifyBuyer() in the browser, which would be terrible UX.

So, storing the Card On File needs to happen before the payment is taken (and deleted if the payment fails).

Taking the payment from the Card On File with the customer not present, thus avoiding the need for a verification token can be achieved by adding customer details to the Create Payment Request Body and setting customer_initiated to false.

$customer_details = new \Square\Models\CustomerDetails();
$customer_details->setCustomerInitiated(false);

$body = new CreatePaymentRequest($card_id, $order_id);
$body->setCustomerDetails($customer_details);

Hi Nystag

As you can see from squareup last posts, the main issue is the sandbox system you use to develop and test on is broken - or it was. I only found this out from one of squareup dev team after I wasted hours of time from trying to solve the problem and getting lttile to no help on these forums.

Hi mkcostello,

I’m currently in an R&D phase with Square and only working in the sandbox, so I assume setting customer_initiated to false was not available before. It’s not ideal having to use the verification token to store the card and then process a cardholder not present transaction, from experience they sometimes fail… but it should be workable for us. Being able to create a payment and store the card in one step, with a single verification token would be much better.

It’s recommended that you first store the card on file and then charge the customer. You can store the card with a payment_id however we still recommend that you store it first prior to charging. :slightly_smiling_face:

Hi Bryan.

Thanks for the reply. Could you log a feature request to make it possible to create a payment and store the card, customer-initiated with SCA, with a single verification token?

Using the verification token to store the card and then charge the card (merchant initiated) will work, but it means having to pay the increased fee of a card-not-present transaction, even though the card is technically present and the customer initiated the payment.

I agree with Nystag.

It seems odd that the API doesn’t do this already as it’s pretty normal functionality to collect a deposit, store/tokenize card details and take automated balance payment later. Stripe allows you to do this, but squareup penalizes merchants with higher card fees and risk score.

I now tend to steer my clients away from squareup if I can because of this, and various other issues with the API - including the awful documentation

The fee of the charge won’t change if these are API payments. If you charge and store or store and charge the card with seller_keyed_in the fee is the same when processed by our API. Here is our pricing documentation. :slightly_smiling_face:

Thanks, Bryan.

I was under the impression from our Account Executive, and the fee schedule at Fee Schedule that Card On File transactions would attract an increased fee. However, the sandbox is showing the standard Square Online fee for those transactions :slight_smile: