Square API

Contributor ,
Jan 17, 2021 Jan 17, 2021

Copy link to clipboard

Copied

I am having an issue with the square API and want to make sure I'm not doing something stupid. Here's my code:

 

<cfset stFields = {
    "order": {
      "idempotency_key": "xxxxxx-215d-4dce-b92a-90c306eb5eba",
      "location_id": "xxxxxx",
      "total_money": {
      "amount": 99999,
      "currency_code": "USD"
      },
      "order": {
        "location_id": "xxxxx",
        "customer_id": "asdasd"
      }
    },
    "idempotency_key": "xxxxxx-215d-4dce-b92a-90c306eb5eba",
    "ask_for_shipping_address": false,
    "merchant_support_email": "consectetur@loremipsum.com",
    "redirect_url": "https://abc.com"
  }
> 

 

I keep getting the error: 

{"errors":[{"category":"INVALID_REQUEST_ERROR","code":"VALUE_TOO_LOW","detail":"`order.total_money.amount` must be greater than 1.","field":"order.total_money.amount"}]}

Yet... It looks to me like there's a value...  Any ideas???

Screen Shot 2021-01-17 at 5.56.54 PM.png

 

Views

125

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct Answer

Adobe Community Professional , Jan 21, 2021 Jan 21, 2021
To reiterate, the error does not originate from the struct stFields. It originates from squareupdata, the output of a cfhttp post. But we don't know the contents of squareupdata. So the original question is moot. In any case, since CF2016 Update 2, you can specify the data type of a struct's key-value pair as follows: <cfset metadata = {someKey: {type:"int"}}> <cfset myStruct.setMetadata(metadata)>

Likes

Translate

Translate
Contributor ,
Jan 18, 2021 Jan 18, 2021

Copy link to clipboard

Copied

It seems the issue was how CF2016 processes the JSON. The exact same code works in CF2021.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 19, 2021 Jan 19, 2021

Copy link to clipboard

Copied

Could it be that the error message is justified? That is, could it be that order.total_money.amount must be in currency format? Hence 99999.00 instead of  99999.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jan 19, 2021 Jan 19, 2021

Copy link to clipboard

Copied

Square uses the lowest common denominator of any currency. So in the US, that's a penny. Sending 1 equals $0.01 where sending 100 equals $1.00.

The issue was in CF 2016 when serializing the JSON CF wasn't sending the amounts as integers even if you wrapped it as INT(#value#).  In CF2018 and CF2021 serializing the JSON created the value as an integer and Square was happy. We tested the exact same code in 2016, 2018, and 2021. It failed in 2016 and worked perfectly in the newer versions.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 20, 2021 Jan 20, 2021

Copy link to clipboard

Copied

I tested your exact code on trycf.com. It worked without any problems.

 

trycf.png

 
 

 

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 20, 2021 Jan 20, 2021

Copy link to clipboard

Copied

Suggestions:

1) Ensure you have the latest CF2016 update.

2) Add the following fix just before the serializeJson(stFields) call: 

<cfset metadata = {"amount": {type:"int"}}>
<cfset stFields.setMetadata(metadata)>
<!--- Try the following line instead, if the last line doesn't solve the problem.--->
<!---<cfset stFields.order.total_money.setMetadata(metadata)>--->

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 20, 2021 Jan 20, 2021

Copy link to clipboard

Copied

Hang on. I just noticed something. Apparently, you're looking at the wrong struct.

 

The error does not occur when you serialize the struct stFields. It occurs with the struct named SquareUpData.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jan 20, 2021 Jan 20, 2021

Copy link to clipboard

Copied

I have updated to 2021.  I appreciate your help though. For the next person reading this...

1) The field order.total_money_amount is actually a read-only field that Square calculates in the response. It is based on you sending order.amount and order.quantity. You don't send total_money in the request.

2) SquareUpData is the response data, not the data you send.

Here's an example of working code:

<cfset REQUEST.location_id = "YourLocationID">
<cfset REQUEST.Access_Token = "YourToken">
<cfset REQUEST.Square_Server = "connect.squareup.com">
<cfset REQUEST.Square_Version = "2020-12-16">
<cfif StructKeyExists(Session, "total") AND StructKeyExists(Session, "CustomerID")>
<cfset session.total = session.total * 100 />
<cfset REQUEST.Amount = #session.total#>
<cfif isDefined("URL.transactionId")>
<cfset rtFields = {
          "order_ids": [
              "#URL.orderID#"
          ]
}>
<cfhttp method="post" result="objGet" url="https://#REQUEST.Square_Server#/v2/locations/#REQUEST.location_id#/orders/batch-retrieve">

<cfhttpparam type="header" name="Accept" value="application/json">
<cfhttpparam type="header" name="Authorization" value="Bearer #REQUEST.Access_Token#">
<cfhttpparam type="header" name="Cache-Control" value="no-cache">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="body" value="#serializeJSON(rtFields)#">

</cfhttp>

<cfelse>

<cfset REQUEST.Base_Price_Money_Amount = #session.total#>
<cfset REQUEST.idempotency_key = #CreateUUID()#>
<cfset REQUEST.order_idempotency_key = #CreateUUID()#>


<cfset stFields = {
	"idempotency_key": "#REQUEST.idempotency_key#",
	"order": {
	  "idempotency_key": "REQUEST.order_idempotency_key",
	  "order": {
		"location_id": "#session.REQUEST_LocationID",
		"customer_id": "C-#session.CustomerID#",
		"line_items": [
		  {
			"quantity": '1',
			"name": "Item Name",
			"note": "Any Item Note",
			"uid": "uid",
			"base_price_money": {
			  "amount": int(#REQUEST.Base_Price_Money_Amount#),
			  "currency": "USD"
			}
		  }
		]
	  }
	},
	"ask_for_shipping_address": false,
	"merchant_support_email": "CustomerService@example.com",
	"redirect_url": "https://someURL.com/SquareOrderComplete.cfm"
  }>

<cfhttp method="post" result="objGet" url="https://#REQUEST.Square_Server#/v2/locations/#REQUEST.location_id#/checkouts">



<cfhttpparam type="header" name="Square-Version" value="#REQUEST.Square_Version#">
<cfhttpparam type="header" name="Authorization" value="Bearer #REQUEST.Access_Token#">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="body" value="#serializeJSON(stFields)#">

</cfhttp>

</cfif>

<cfscript>
squareupdata = deserializeJSON(#objGet.FileContent#);
</cfscript>

3) If using CF2016 you need to add the metadata above in BKBK's post. You don't need it in 2018 and 2021.

4) Square checkout (unlike Stripe) after the customer completes the checkout does not return JSON. The customer can't get to the order complete page until the card has been approved. You get ID's for reference in the order complete URL.

 

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Jan 21, 2021 Jan 21, 2021

Copy link to clipboard

Copied

To reiterate, the error does not originate from the struct stFields. It originates from squareupdata, the output of a cfhttp post.

 

But we don't know the contents of squareupdata. So the original question is moot.

 

In any case, since CF2016 Update 2, you can specify the data type of a struct's key-value pair as follows:

 

<cfset metadata = {someKey: {type:"int"}}>
<cfset myStruct.setMetadata(metadata)>

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Jan 21, 2021 Jan 21, 2021

Copy link to clipboard

Copied

LATEST

BKBK, I appreciate your response. You are always helpful. In this case, however, you are partially correct. Yes, metadata would have fixed the issue in 2016 but is not needed in 2018 or 2021.

 

"To reiterate, the error does not originate from the struct stFields. It originates from squareupdata, the output of a cfhttp post. But we don't know the contents of squareupdata. So the original question is moot."

 

As I said above the issue is in stFields, not SquareUpData. SquareUpData is the response data from Square. You do not post SquareUpData it is a read only response. You post stFields and Square responds with a check_out URL in SquareUpData unless there is an error and then Square responds with the error in SquareUpData. The field order.Total_Money_Amount is a read-only field calculated by Square based on the fields in order.line_items.quantity and order.line_items.amount. Quantity and amount need to be integers. If Square can't read quantity and amount then the total order amount is less than 1 and Square responds in SquareUpData what the error is.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines