When using SCA how can I both charge a card and also store it?

I am implementing SCA into my app. The app has a subscription model and so the users cards are stored and then charged monthly. When implementing SCA though I have hit upon a problem. I can either charge a card, or I can store a card, but not both.

My initial plan was to first of all store the card, and then charge it. The problem is that when I do that the SCA screen appears and when the intent is set to ‘STORE’ I cannot add a cash value to it and so it appears with 0.00 as the amount no matter what I do. So, when a user buys a subscription and they see the SCA screen, they are told that the amount is 0, which is unacceptable when they are in fact being charged money.

After doing some research I came across this video here https://youtu.be/v-8w8IujsJs where it is mentioned that you can take a paymentID and use that to store a card, so I thought great I will do it that way instead. So I set intent to ‘CHARGE’ and the SCA screen shows the value correctly. Then I take the payment using the card nonce and the SCA token and it takes the payment ok. But then when I try to add the card using the payment ID it throws an exception with the error ‘Card declined. A verification is required to process this payment.’. So it seem it will not allow me to use a PaymentId created using a CHARGE SCA token to store a card unless I also supply a second STORE SCA token as well.

I saw another post from someone who had the same problem and he ended up calling the verifyBuyer function twice; once to get a STORE token and once to get a CHARGE token. But this is not an acceptable solution. There is no other website in the entire world that makes you type in your verification ID twice in a row like that. All that is going to do is confuse the user and make them think its not working properly or make them suspicious.

So how do I do this?

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

https://developer.squareup.com/docs/sca-overview-iap

Additional Documentation

https://developer.squareup.com/docs/sca-overview-web
https://developer.squareup.com/docs/sca-overview
https://developer.squareup.com/docs/reader-sdk/quick-start/step-3

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.

To make this as seem less as possible you can call verifyBuyer with the intent to STORE with the amount that your going to charge the sellers. This way there not confused when they see the $0 amount. Once you’ve saved the card on file you can call CreatePayment and set customer_details to seller_keyed_in. This indicates that your programmatically handling the payment for the seller when they’re not present. :slightly_smiling_face:

Hi Bryan,

Thank you for the quick response!

I tried again to call the verifyBuyer function with intent to ‘STORE’, however when I do that it always ignores the money value I send to it and it always shows 0.00 in the amount.

If it’s supposed to show the amount either way, then I think this is possible a bug in the verifyBuyer function.

Are you passing it as a float?

async function verifyBuyer(payments, sourceId) {
  const verificationDetails = {
    amount: '1.00',
    billingContact: {
      addressLines: ['123 Main Street', 'Apartment 1'],
      familyName: 'Doe',
      givenName: 'John',
      email: '[email protected]',
      country: 'GB',
      phone: '3214563987',
      region: 'LND',
      city: 'London',
    },
    currencyCode: 'GBP',
    intent: 'STORE',
  };

:slightly_smiling_face:

Yes I am. I will show you my code and the result.

This is with CHARGE:

        const result = await card.tokenize();
        if (result.status === 'OK') {
            var postcode = result.details.billing.postalCode;

            const verificationDetails = {
                intent: 'CHARGE',
                amount: '10.00',
                currencyCode: 'GBP',
                billingContact: {
                    addressLines: ['123 Fake Street'],
                    countryCode: 'GB',
                    city: 'Leeds',
                    postalCode: postcode
                },
            };


            try {
                // Attempt to verify the buyer
                const verificationResults = await payments.verifyBuyer(
                    result.token,
                    verificationDetails
                );

This is with STORE (it is the only difference):

        const result = await card.tokenize();
        if (result.status === 'OK') {
            var postcode = result.details.billing.postalCode;

            const verificationDetails = {
                intent: 'STORE',
                amount: '10.00',
                currencyCode: 'GBP',
                billingContact: {
                    addressLines: ['123 Fake Street'],
                    countryCode: 'GB',
                    city: 'Leeds',
                    postalCode: postcode
                },
            };


            try {
                // Attempt to verify the buyer
                const verificationResults = await payments.verifyBuyer(
                    result.token,
                    verificationDetails
                );

I’ve managed to find a solution. STORE and CHARGE are not the only intent options. I was having a nosy in the payment javascript and I found mention of CHARGE_AND_STORE, so I gave it a try and it literally works exactly how it sounds :slight_smile:

Oh and I also needed to set seller_keyed_in in the customer details just as you said, in order to take repeat payments, so thank you for that because I dont think I would have guessed it.

Amazingly though I cannot find any mention of CHARGE_AND_STORE on the Square Developer site. Only STORE and CHARGE are mentioned on there. I would highly recommend adding something about it!

1 Like