Square Online Checkout -> APIs with Card on File

hi there.

i’m building out some recurring order features for a customer’s shop. they use Square Online with the Checkout form/feature. is there a way to configure how the Checkout works so we can attach the card to a user instead of just creating a thin Instant Profile? if not, are there ways to intercept the payment event and do some behind the scenes API magic to wire API objects up properly?

thanks for any thoughts

Currently with the Square Online Store there isn’t any way to programmatically change or configure the checkout. Nor is there a way to get the payment prior to being processed to adjust it in any way. You would have to build a custom site with our SDKs and APIs to have full control of the checkout process. :slightly_smiling_face:

Thanks for the confirmation Bryan. Followup: we don’t/can’t forgo the ease of the website setup, is there a way you can think of where when a user has looked at an item of ours and configured it they could click a button/link to then take them to a custom checkout form that would read all the item, variation, modifier, etc data based on the URI or something (I can figure out the “catching” part of it, but currently unsure what we can do in the website builder to help facilitate this :face_with_diagonal_mouth:)

Thanks!

So you want the customer to be redirected to another site for processing the payment? If that’s the cases you’ll have to put a link to the other site on the page. Not sure if that’s possible with the online store or how you’d easily direct customers to click on the redirect.

Is this to use another payment processor other then Square or are you looking to do something with the order? :slightly_smiling_face:

definitely not trying to use another processor. just trying to get around Square’s restrictions as i see them (or learn that i’m wrong :slight_smile: )

use case: customer wants to purchase Item A. they love to get it every monday for the office, either delivered or ready for pickup. instead of ordering every sunday in advance, they’d like to “subscribe” to a recurring weekly order. not of some generic Item A though, it’s the variant and modified one that they specifically get (and the same fulfillment as last time, i.e. delivered to Acme Corp at 10a).

what i had hoped to do was get an order created or paid webhook, see that they chose a Weekly modifier, and then stash that into our system to be cloned and paid according to whatever schedule they chose, in this case every week.

the cloning would, ideally, carry the customer, their payment source, and order fulfillment info forward into the next one and voila!

since i can’t do anything programmatically w the Checkout form it sounds like i’ll have to create our own checkout form via the SDK to facilitate this. is that right?

if so, then my thoughts go to:

  1. after their one-off order, when we see there was the Weekly modifier, we send them an email saying they have to confirm their recurring order. the link would take them to a new SDK-based checkout form that does all the above work i’d mentioned, except it’d have the original orderId stashed in the URI or something so that it would know to a) not charge them now bc they just paid, b) associate these recurring orders w that original one
  2. from the Square Online Checkout form pop them over to this SDK form so that they only have to enter their information once instead of in a follow up process.

either way introduces friction of some sort unfortunately :\

does that make sense overall?

You can do this. The information is available in with webhooks. If the customer_id isn’t in the order then it’s in the payment. You can call GetPayment with the payment_id in the order.

With the payment you’ll get the customer_id which you can use to create future orders for and you can ListCards with the customer_id. If they have a stored card on file that matches the data from the card_details you can programmatically create and pay for the orders on the customers desired cadence.

If there isn’t a card on file or it doesn’t match the card_details you can create a card on file with the payment_id and customer_id. Once the card is created then you can programmatically create and pay for orders on the customers desired cadence. :slightly_smiling_face:

Interesting. I’d tried it in the api explorer and wasn’t able to get any cards listed when send over the customer info. Maybe I hadn’t included the payment id as well :thinking: will try again this evening and hope for the best :crossed_fingers: otherwise will be back w questions lol

There may be no cards on file for a customer. We don’t automatically store one of file. You’ll most likely be creating the cards on file. :slightly_smiling_face:

wowee, this may be the ticket. had a quick minute to pull out the laptop and it looks promising, but i don’t want to create a card for an unknowing production user :sweat_smile: and don’t have time to recreate a payment and customer in sandbox right now. will do it as soon as i can tomorrow and report back. :crossed_fingers:

thanks!

Great! If you don’t create the card on file for a customer that doesn’t have a card on file then you won’t be able to take the payment for the next cadence. Also if the customer chose the cadence for example weekly they opted in to it. :slightly_smiling_face:

maybe i’m missing something still. i ran a test in production w my own email + card. caught the webhook for the payment.created. double checked that i got nothing ( {} ) from the listCards API w my customer_id. used the payment’s id + the customer_id from the related order and in the API explorer made a request that would’ve been this code:

const response = await client.cardsApi.createCard({
    idempotencyKey: '6f6da687-9be6-4413-9252-ea862bf9546f',
    sourceId: 'xxx',
    card: {
      customerId: 'xxx'
    }
  });

and got:

cache-control: no-cache
content-length: 126
content-type: application/json
date: Fri, 06 Oct 2023 12:51:21 GMT
square-version: 2023-09-25


{
  "errors": [
    {
      "category": "INVALID_REQUEST_ERROR",
      "code": "INVALID_CARD_DATA",
      "detail": "Invalid card data.",
      "field": "source_id"
    }
  ]
}```

did i misunderstand how to get this working?

No, that should work. Did you use a digital wallet to make the initial payment? What’s your application ID? :slightly_smiling_face:

sq0idp-Sl2vwyEjfeaykXZ-ydTlOQ

nope, i used the square checkout. even put in a new card instead of the one associated w my email.

I just tested with my account and it worked. Is the customer_id the same from the payment? :slightly_smiling_face:

:confused:

i was using the payment id from the creation event: jffuztfumrVLqnZCdltvEdA4njSZY

i used that to retrieve the payment via api explorer bc the customer_id was not in the original payload. i got: 8ZE7FH29YD1GZDPK0WMAJ3XB04

code would be:

const response = await client.cardsApi.createCard({
    idempotencyKey: '5303bfbf-c0e2-4423-9f74-9d239473592c',
    sourceId: 'jffuztfumrVLqnZCdltvEdA4njSZY',
    card: {
      customerId: '8ZE7FH29YD1GZDPK0WMAJ3XB04'
    }
  });

same error:

{
  "errors": [
    {
      "category": "INVALID_REQUEST_ERROR",
      "code": "INVALID_CARD_DATA",
      "detail": "Invalid card data.",
      "field": "source_id"
    }
  ]
}

Hmm, the team is taking a look. :slightly_smiling_face:

Ok, thanks. What typically is the turnaround on that? I can start stubbing out our application’s code assuming this will all work but also want to be able to confirm with a real case in order to know we’re moving in the right direction or, worst case, figure out the pivot and communicate w the client.

Thanks for the help so far

We can’t really say what the turnaround time is cause we first need to understand the issue and why it failed to figure out what a fix will be if were able to fix the issue. :slightly_smiling_face:

Sure. If it worked for you but not me then I’d guess it’s some sort of account / token / access type of issue?

Looks like the payment jffuztfumrVLqnZCdltvEdA4njSZY method you use to process the payment was card_on_file. You can’t create a card on file with a payment that’s card on file. You’ll need to key the card in. :slightly_smiling_face: