HTTPS via curl_init() versus HTTPS via -X POST

Hi everyone,

I now have the Quick Pay Checkout working correctly via the following code…

$access_token="My_Access_Token";
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://connect.squareupsandbox.com/v2/online-checkout/payment-links");
curl_setopt($curl, CURLOPT_POST, "true");
curl_setopt($curl, CURLOPT_HTTPHEADER, array('authorization: Bearer ' . $access_token, 'content-type: application/json', 'Square-Version: 2025-06-18'));

$body = array(
	"idempotency_key" => "603ae3ba-d189-45c1-8498-fb8f74a5abb7",			
	"quick_pay" => array(
	"name" => "Test Order", "price_money" => array(
	"amount" => 9524, "currency" => "GBP"),
	"location_id" => "My_Location_ID")
);
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($body));

$response = curl_exec($curl);
curl_close($curl);
echo "$response";

It’s working perfectly, i.e. the $response contains the relevant data including the URL, which when copy/pasted into the browser and clicking “Preview Link”, the payment link appears as expected, so all is great!

However, the above code isn’t the same as shown in the Quick Pay Checkout example as follows…

curl https://connect.squareupsandbox.com/v2/online-checkout/payment-links \
-X POST \
-H 'Square-Version: 2025-06-18' \
-H 'Authorization: Bearer My_Access_Token' \
-H 'Content-Type: application/json' \
-d '{
	"idempotency_key": "55dbdb70-e84e-4c9c-a6cb-6f267c7d90c2",
	"quick_pay": {
		"location_id": "L2A4E9BGPYY1R",
		"name": "Another test 1",
		"price_money": {
			"amount": 4579,
			"currency": "GBP"
		}
	}
}'

Now, I realise I’m looking at two different methods for requesting a payment link, i.e. the one I have working initialises via the curl_init() function, and the Quick Pay Checkout example via -X POST.

Presumably I can continue on with what I have working and simply not bother worrying about the -X POST method… but even so, it’s really bugging me that I’m getting the following error…

Parse error : syntax error, unexpected identifier “https”

I’m using PHP Version 8.4.8 and from checking via calling phpinfo(), I can see “cURL support enabled”, “cURL Information 7.76.1”, “Age 8”, “HTTPS_PROXY Yes”, and many other settings.

  1. Any ideas why I’m getting the Parse error?
  2. Even if I wasn’t getting the parse error, is there an equivalent way to access the response when working with headers via -X POST in this way, i.e. equivalent to the returned “$response = curl_exec($curl)”? Or is -X POST intended to just create the payment link for me to then access in my account, but not to handle the response in my code?

Cheers, Gary.

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

Make your First API Call
Square PHP SDK Quickstart
Checkout API

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.

That’s exactly the resource I needed actually, so thank you Square Dev AI.

However, I’ve been reading that the REST API isn’t something that needs to be included within my code like a library is included, or initiated by a function such as curl_init()

Therefore, to any humans, please if you have any ideas why I’m getting… Parse error : syntax error, unexpected identifier “https”?

P.S. I’d really like to have that method of coding as an option for the longer term!

Cheers, Gary.

I have another site hosted with another provider, and so I tested the -X POST code, and I was getting exactly the same parsing error…

Well, this is embarrassing for me I guess, but I’ve been using opening and closing php tags for my -X POST code, simply because my file has a .php extension and my curl_init() code is of course php code inside php tags.

Ironically, whenever I’ve tried to post opening and closing php tags here on this forum when showing my code, it wouldn’t post, giving me a 403 error, and sometimes a 422 error which I won’t go into because it’s very strange. So if I’d been able to show you the php tags in my code, then I guess someone would have pointed out my mistake.

Anyway, I’ve simply removed the php tags and it now works :slight_smile:

Update: No it didn’t… see post 8

Your your first example is php code, using php functions. Your second example is bash code, to be run on a server.
Use backticks to run it in your php environment:

Add backticks at the start and end of this code, and PHP will execute it.
I do this all the time; copy working bash code from Square’s API explorer, fix variables, add backticks, run. SO MUCH EASIER than PHP curl functions.

That’s very useful to know, thank you!

Inside php tags, after enclosing my entire -X POST script in backticks, I get " Warning : shell_exec() has been disabled for security reasons in /home/luxedisp/public_html/quick_pay_test.php on line 3"

Can this be expected?

Ah, I’m getting somewhere… I recently migrated my website to another host, and so now having just tried to run it via my old hosting, it definitely works…

:slightly_smiling_face:

{"payment_link":{"id":"BBW6GTDCJYVLJDE5","version":1,"order_id":"MCTtcVKkXg5tCBlc1IeyiqWgc8AZY","url":"https://sandbox.square.link/u/QLTFQXwz","long_url":"https://connect.squareupsandbox.com/v2/online-checkout/sandbox-testing-panel/MLDG30YCETDVF/BBW6GTDCJYVLJDE5","created_at":"2025-07-14T17:33:19Z"},"related_resources":{"orders":[{"id":"MCTtcVKkXg5tCBlc1IeyiqWgc8AZY","location_id":"My_Location_ID","source":{"name":"Sandbox for sq0idp-X4Ft22ezemttn_0RiEKKaw"},"line_items":[{"uid":"8VX8wQl3ppG2hqDDtiFLR","name":"Auto Detailing","quantity":"1","item_type":"ITEM","base_price_money":{"amount":6543,"currency":"GBP"},"variation_total_price_money":{"amount":6543,"currency":"GBP"},"gross_sales_money":{"amount":6543,"currency":"GBP"},"total_tax_money":{"amount":0,"currency":"GBP"},"total_discount_money":{"amount":0,"currency":"GBP"},"total_money":{"amount":6543,"currency":"GBP"},"total_service_charge_money":{"amount":0,"currency":"GBP"}}],"fulfillments":[{"uid":"LvkGT98DgGVw3e0ugLAMWC","type":"DIGITAL","state":"PROPOSED"}],"net_amounts":{"total_money":{"amount":6543,"currency":"GBP"},"tax_money":{"amount":0,"currency":"GBP"},"discount_money":{"amount":0,"currency":"GBP"},"tip_money":{"amount":0,"currency":"GBP"},"service_charge_money":{"amount":0,"currency":"GBP"}},"created_at":"2025-07-14T17:33:19.187Z","updated_at":"2025-07-14T17:33:19.187Z","state":"DRAFT","version":1,"total_money":{"amount":6543,"currency":"GBP"},"total_tax_money":{"amount":0,"currency":"GBP"},"total_discount_money":{"amount":0,"currency":"GBP"},"total_tip_money":{"amount":0,"currency":"GBP"},"total_service_charge_money":{"amount":0,"currency":"GBP"},"net_amount_due_money":{"amount":6543,"currency":"GBP"}}]}}

So my new provider has shell_exec() disabled!

I’ll look at my cPanel MultiPHP INI Editor tomorrow to see if I can figure it out, and if I can’t, I’ll contact my new provider to ask if it can be enabled.

Also notice the post I deleted just above. Well, that’s because I felt like an idiot when I realised it wasn’t actually working, i.e. I’d mistaken my own code exactly as is in plain text for what I thought was JSON being returned :grinning_face:

Anyway, as is explained in that link you kindly posted… and thank you again NemoNoman… the whole code block between backticks can simply be assigned to a variable, which is awesome if all I need to do now is handle it pretty much like I have been doing already via the response from the curl functions.

My final update I guess for this topic, but my new provider doesn’t offer shell_exec() for shared hosting :frowning: They provide SSH access, it’s just that shell_exec() is disabled.

They have options as quoted… just not for shared hosting…

“You would be able to run this on a VPS or using the dedicated cloud hosting options where you can then manage the disabled_functions on the server to meet your own needs but that would be a more expensive hosting option

I’ve checked and it’s a bit expensive for all I’m needing to do with Square, so I guess I’m gonna do without Square’s bash code option, at least for now.

P.S. I have curl functions working anyway, so I’m happy enough… Quick Pay Checkout works with Sandbox Credentials… But Not Production Credentials - Questions - Square Developer Forums

It turns out that we can use the bash code by copy/pasting without needing shell_exec(), well the most beneficial part of it anyway, i.e. the JSON body data…

As shown in my opening post, I was using PHP arrays, but json_encode($body), although expects arrays, doesn’t produce them.

For example if using Order instead of QuickPay, and so you might call json_encode() for…

$body = array(
    "idempotency_key" => $unique_value,

    "order" => array(
       "location_id" => "location_id",
       "line_items" => array(
          "quantity" => 1,
          "base_price_money" => array(
             "amount" => 473,
             "currency" => "GBP"
          ),
       "name" => "Item 1 (Method 1)"
       )
    )
 );

But the JSON returned by json_encode() is…

$body = '{"idempotency_key":"' . $unique_value . '","order":{"location_id":"location_id","line_items":
   
{"quantity":"1","base_price_money":{"amount":1473,"currency":"GBP"},"name":"Item 1 (Method 1)"},
{"quantity":"2","base_price_money":{"amount":7834,"currency":"GBP"},"name":"Item 2 (Method 1)"}
}}';

That’s a problem because Checkout API expects the square brackets, i.e. an array…

$body = '{"idempotency_key":"' . $unique_value . '","order":{"location_id":"location_id","line_items":
[
  {"quantity":"1","base_price_money":{"amount":1473,"currency":"GBP"},"name":"Item 1 (Method 2)"},
  {"quantity":"2","base_price_money":{"amount":7834,"currency":"GBP"},"name":"Item 2 (Method 2)"}
]
}}';

And that code :roll_eyes: is exactly the same JSON as is autogenerated by Square Explorer, i.e. rearranged it looks like…

$body = '{
  "idempotency_key": "' . $unique_value . '",
  "order": {
     "location_id": "location_id",
     "line_items": [
        {
           "quantity": "1",
           "base_price_money": {
              "amount": 1473 ,
              "currency": "GBP"
           },
           "name": "Item 1 (Method 2)"
        },
        {
           "quantity": "2",
           "base_price_money": {
              "amount": 7834,
              "currency": "GBP"
           },
           "name": "Item 2 (Method 2)"
        }
     ]
  }
}';

So, the most beneficial part, i.e. the body data, we can still simply copy/paste directly from Explorer, although of course curl functions are still required for setting up the HTTPS request, but it’s the potential for the body data to become long and complex that I’ve found copy/pasting the bash code to be the most beneficial.

Finally, for anyone interested, this is what I ended up doing for my shopping cart so that it dynamically injects my various PHP session variables…

$body = '{
  "idempotency_key": "' . $unique_value . '",
  "order": {
     "location_id": "location_id",
     "line_items": [';  

Then after setting up those first few lines, loop through the shopping cart basket…

$basket_length = count($_SESSION['my_basket']);  
$index = 0;

foreach ($_SESSION['my_basket'] as $value)
{
  $item_cost = number_format($value->price, 2, '.', ''); // making sure there are no more than 2 decimal places
  // round() is required because somehow I had an example whereby the * 100 must have been resulting in fractionally less than the expected integer result, thereby resulting in £0.01 too cheap!
  $item_cost_as_integer = (int)(round($item_cost * 100));

  $body .=
  '{
     "quantity": "' . $value->quantity . '",
     "base_price_money": {
        "amount": ' . $item_cost_as_integer . ',
        "currency": "GBP"
     },
     "name": "' . $value->title . '"
  }';
  if ($index < $basket_length - 1)
     $body .= ',';
  ++$index;
}

And then add the delivery cost as a service charge… (although I have just noticed that there is now shipping_fee)

$shipping_cost_as_integer = (int)(round($_SESSION['checkout_costs']->delivery_cost * 100));

$body .= '],
"service_charges": [
  {
     "amount_money": {
        "amount": ' . $shipping_cost_as_integer . ',
        "currency": "GBP"
     },
     "name": "Shipping ",
     "calculation_phase": "SUBTOTAL_PHASE",
     "taxable": true
  }
]';
$body .= ',
"taxes": [
     {
        "percentage": "20",
        "type": "ADDITIVE",
        "name": "VAT",
        "scope": "ORDER"
     }
]}}';