PHP Create order and Sale notification

In my current PHP process-card file I have:

use Square\SquareClient;
use Square\LocationsApi;
use Square\Exceptions\ApiException;
use Square\Http\ApiResponse;
use Square\Models\ListLocationsResponse;
use Square\Environment;

use Square\Models\Money;
use Square\Models\CreatePaymentRequest;


$client = new SquareClient([
    'accessToken' => $access_token,
    'environment' => Environment::PRODUCTION,
]);


$nonce = $_POST['nonce'];
$payments_api = $client->getPaymentsApi();

$money = new Money();
$money->setAmount(501);
$money->setCurrency('USD');

$create_payment_request = new CreatePaymentRequest($nonce, uniqid(), $money);

try {

    $apiResponse = $payments_api->createOrder($location_id, $create_payment_request);

And this works fine. But I want to convert the transaction to an order.
I want to be able to assign a tracking number within my square account to the transaction (order). (All my square transactions will be for my ecommerce store)

QUESTION 1:
Is it even possible to sign in to square, view a transaction/order and assign a tracking number to it? This has to be added DAYS after the transaction has been made.
The only reason I Want to do this, is because I know with paypal when a customer files a dispute for a transaction that does not have any tracking number assigned to it, they tend to favor customer more.

QUESTION 2:
When it comes to converting the transaction to an order, I’m stuck with what to remove/change from the code above. What I found from online was:

$apiInstance = new SquareConnect\Api\OrdersApi();
$location_id = "location_id_example"; 
$order_id = "order_id_example"; 
$create_payment_request = new \SquareConnect\Model\UpdateOrderRequest(); 

try {
    $apiResponse = $apiInstance->updateOrder($location_id, $order_id, $create_payment_request);

The problem is, this code above, conflicts with my CURRENT code at the top of this page.
Am I supposed to have them together? Or just one of them?
I mean the new code above does not even have a money AMOUNT in it :S
Also it says "update order. I’m trying to create a NEW one and add a custom amount and an order_id.

QUESTION 3:
When a sale has been made, I want to be notified. I do have a PHP file on my website that sends me an e-mail. I’m assuming where I should put this link in " Point of Sale API - Web Callback URLs" ?
So when ever somebody uses a browser regardless on PC or smartphone and buys something on my website, it should call that url ?

Thanks in advance!! =)

Regarding your last error, it looks like we do not document the constructor very well in the README; I’m escalating that to our SDK team to get those updated. For now, it looks like the OrderLineItem requires a quantity in the object initialization.

As for your first questions:

  1. If the order hasn’t been paid for, you can update it for as long as you like via the API (not the dashboard).
  2. It sounds like you’re on the right track with your second post, so let me know if something more specific comes up about this one.
  3. It’s actually not the POS API callback url; that’s for the POS API specifically which is an in-person mobile solution. If you want to be notified, your best bet would be using webhooks. There are specific payment webhooks that will be sent when a payment is created. However, if you need cash/other (for like POS payments), then you’d need to rely on V1 PAYMENT_UPDATED webhook unfortunately.
1 Like

When it comes to "payment webhooks, I just feel like both me and you been spending several daaays on getting accepting payment to work. It’s been so mentally exhausting don’t have the energy to go on another complicated project lol.

QUESTION 1:
So there is NO way (via dashboard or php), I can apply a tracking number to an order/transaction, at LEAST 24 hours after payment has been received ?

QUESTION 2:
In the code I have below (Bottom of this reply), where do I add the $order_id ?
Can I do this?
$apiResponse = $payments_api->createOrder($location_id, $request, $order_id);

QUESTION 3:
Ok what I’m trying to make the PHP process-card do is:

  1. Add Title of the product(s) to it
  2. Add Quantity for each product
  3. Add an ID for each product (if possible)
  4. Add an order ID for the whole order/transaction
  5. Submit payment as an ORDER

Here is the error message I get from the code I use below:

  • PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function Square\Models\OrderLineItem::__construct(), 0 passed in /square/process-card.php on line 37 and exactly 1 expected in /square/vendorsrc/src/Models/OrderLineItem.php:106

  • Stack trace: #0 /square/process-card.php(37): Square\Models\OrderLineItem->__construct()

  • #1 {main} thrown in /square/vendorsrc/src/Models/OrderLineItem.php on line 106

I checked the file OrderLineItem.php, on around row 106:

public function __construct(string $quantity) // this is row 106
{
$this->quantity = $quantity;
}

No idea what the problem is. Here is my PHP:

require ‘vendorsrc/autoload.php’;

use Square\SquareClient;
use Square\LocationsApi;
use Square\Exceptions\ApiException;
use Square\Http\ApiResponse;
use Square\Models\ListLocationsResponse;
use Square\Environment;

use Square\Models\Money;
use Square\Models\CreatePaymentRequest;

use Square\Models\OrderLineItem;

$client = new SquareClient([
‘accessToken’ => $access_token,
‘environment’ => Environment::PRODUCTION,
]);

nonce = _POST[‘nonce’];
$payments_api = $client->getPaymentsApi();
$money = new Money();
$money->setAmount(5);
$money->setCurrency(‘USD’);

$book = new Square\Models\OrderLineItem();
$book->setName(‘Name of the product TEST’);
$book->setQuantity(‘1’);
$book->setBasePriceMoney($money);
$order_id = “Test Order ID”;

$lineItems = array();
array_push($lineItems, $book);

$order = new Square\Models\Order();
$order->setLineItems($lineItems);

$request = new Square\Models\CreateOrderRequest();

$request->setIdempotencyKey(uniqid()); //uniqid() generates a random string.
$request->setOrder($order);

try {

$apiResponse = $payments_api->createOrder($location_id, $request);

By the way, I tried changing:
$book = new Square\Models\OrderLineItem();
to:
$book = new Square\Models\OrderLineItem(“1”);

Just to test it out, not sure if I’m even supposed to do that. Considering the QTY should be based on each product in the sale and not an overall QTY. Anyway, now I’m getting this error code instead:
Uncaught ArgumentCountError: Too few arguments to function Square\Models\Order::__construct(),
/square/vendorsrc/src/Models/Order.php:165

And row 165 in order.php is:

public function __construct(string $locationId) // this is row 165
{
$this->locationId = $locationId;
}

  1. Not as far as I know. Once an order has been completely paid for, it can no longer be updated by the API. A payment can never be updated by anything currently.
  2. No; the Payments API does not have an endpoint called CreateOrder, you would need to create a new variable for the Orders API. Then, you would need to add the order_id to your Payments API CreatePaymentRequest. So basically, you need to create both a payment request, and an order request. First, call CreateOrder, and then finally call CreatePayment after you’ve set the order_id of the payment request.
  3. As mentioned in 2 above, it will need to be two different requests (one for creating the order, one for creating the payment).

As for the OrderLineItem, you do need to set the quantity as I mentioned in my previous comment. So your line: $book = new Square\Models\OrderLineItem(“1”);, is correct. This means this “book” line item, will have a quantity of 1. You can add as many line items you like, each with their own quantity.

The same issue with the Order, except here you need to add the locationId in the constructor (as you provided in the last bit of code). So change this $order = new Square\Models\Order(); to this $order = new Square\Models\Order("location_id_here");

1 Like

I guess it makes sense the last stage of what I’m trying to accomplish is the hardest.

QUESTION 1:
Is the steps below possible in same php file and exact order below?

  1. createOrder (put the name of products and quantities)
  2. updateOrder (only used to add order_id)
  3. CreatePayment (to finalize it and make the order visible in my dashboard and actually take payment)

QUESTION 2:
I don’t need to use “payOrder” if I’m trying to accomplish what I wrote in question 1, correct?

QUESTION 3:
If my goal is to only do what I wrote in question 1, do I need to set “setIdempotencyKey” ?

Any PHP links to an existing (not deprecated) Createorder sample by any chance?
I been spending over 5 hours just today codes I look at are so different and the ones that looks like might work are missing OrderLineItem info :confused:

  1. Doesn’t seem like you need UpdatedOrder here. You would add the order_id to the CreatePayment request; the order would already have the order_id.
  2. Nope, PayOrder is mainly used with either completing $0 orders, or attaching multiple tenders to a single order.
  3. I believe idempotency_key is required with payments. If done correctly, it would prevent duplicate payments from occurring, but it also would allow you to make the same request if for whatever reason you didn’t get the response.

The API Explorer will allow you to create an order, and you can choose the drop down on the right-side to choose “PHP” instead of “cURL” (default language). It will show you the exact code to create a particular order, in PHP SDK.

1 Like

Wow…this link…truly made it 1000 times easier. Thank you!!
I think there’s just 1 question left :slight_smile:

QUESTION 1:
So I create an order with final line:

$apiResponse = $client->getOrdersApi()->createOrder($body);

When that row above has run, it creates an order successfully. But when it’s time to create payment, how do I link the order and payment together?
This is the final row to create payment:

$api_response = $client->getPaymentsApi()->createPayment($body);

I read somewhere you wrote: “You can use CreatePayment and pass the order_id in the request.
But, when creating an order, there is no order_id being generated that I can pass along in Createpayment.

Am I supposed to get a variable after creating an order and putting that in the createpayment?
Or am I supposed to put in a value in createorder, and put the same value in when doing a createpayment?


QUESTION 2:
I’m assuming the “$base_price_money->setAmount(” in the Createorder doesn’t really matter, because it’s really the price in the Payment that will be the amount charged correct? I’m referring to “$amount_money->setAmount(” in the “createPayment” process.

The CreateOrder response does have an id. The response is CreateOrderResponse, which has an order, and inside there, has an id. So with the above you could do:

$apiResponse = $client->getOrdersApi()->createOrder($body);
$order = $apiResponse->getOrder();
$order_id = $order->getId();

Further, the body of a CreatePayment request, is CreatePaymentRequest, which has an orderId field. So you would need to pass the above $order_id into this field, before calling CreatePayment (ie in the $body).

For your second question: the amounts actually must match, or else the CreatePayment would fail with an error.

1 Like

When trying to get the order_id it seems that function does not work.
I get:
PHP Fatal error: Uncaught Error: Call to undefined method Square\Http\ApiResponse::getOrder()

Here’s my code:

$apiResponse = $client->getOrdersApi()->createOrder($body);
$order = $apiResponse->getOrder();
$order_id = $order->getId();

I looked online and removed the last 2 rows above and replaced with:
$order = $apiResponse->getCheckout()->getId();

Results:
PHP Fatal error: Uncaught Error: Call to undefined method Square\Http\ApiResponse::getCheckout()

I do have this at the top of my page:
use Square\Http\ApiResponse;

So no idea why this is not working.
The file “ApiResponse.php” does actually also exist in my HTTP folder in square\SRC.

Ah, sorry about that, I was looking at our older PHP SDK. With the newer one, all responses are actually ApiResponse, and then they have a result. So the above should actually be:

$apiResponse = $client->getOrdersApi()->createOrder($body);
$order = $apiResponse->getResult()->getOrder();
$order_id = $order->getId();

I believe. Although, errors could happen, so you probably want to be a bit more robust than this, like:

$apiResponse = $client->getOrdersApi()->createOrder($body);

if ($apiResponse->isSuccess()) {
    $createOrderResponse = $apiResponse->getResult();
    $order = $createOrderResponse->getOrder();
    $order_id = $order->getId();
    // create your payment next etc...
} else {
    $errors = $apiResponse->getErrors();
    // do something with errors? printing them out:
   for ($errors as $error) {
      error_log($error->getDetail());
   }
}
1 Like

You’re a genius!

Question 1:
When clicking on “Orders” in my dashboard, it’s empty. Is it not supposed to be there? (Receipt #Zo0B)

I got the payment to go through but have no idea why it’s missing information.
When viewing the transaction/order in my dashboard, I must be able to identify it.
I used these codes when creating payment:

$body->setReferenceId(“22356”);
$body->setCustomerId(“6126”);

Question 2:
When I click on the transaction, or view the full receipt, the entire page does not contain ANY of the 2 numbers above :S

Question 3:
I even entered shipping address when creating payment. None of the shipping address is in the transaction or receipt.

$shipping_address = new \Square\Models\Address();
$shipping_address->setAddressLine1(‘addresen’);
$shipping_address->setAddressLine2(‘address 222’);
$shipping_address->setLocality(‘Los Angeles’);
$shipping_address->setSublocality(‘California’);
$shipping_address->setPostalCode(‘90025’);
$shipping_address->setCountry(‘US’);
$shipping_address->setFirstName(‘First name’);
$shipping_address->setLastName(‘last name’);
$body->setShippingAddress($shipping_address);

Question 4:
Also, I put
$order_line_item->setUid(‘17’);
When creating the order. The number 17 does not show up anywhere :confused:
(this is supposed to be the ID (database) of my product.

  1. Orders will only show up in the Dashboard if they have fulfillments and have been paid for. In your previous code, you weren’t supplying fulfillments, so they will not show up there. The Orders Dashboard is meant to interact with the Orders (like “preparing” order), so if you don’t need that, then it won’t show up there unfortunately.
  2. Customer id is meant to be an actual customer id, ie one created by Square (like the order_id). First, you would either create a customer or retrieve a customer using the Customers API. The id wouldn’t be very visible, but it would show the customer’s name on who paid for it, and then you could click it to go to their profile. As for the reference id, I think that id is only visible in the API, and not in the UI of the dashboard.
  3. The shipping address would be visible in the Payment’s API object. If you added in the fulfillments for the Order as a SHIPPING type, then I believe the order would show the shipping address supplied there.
  4. The uid is meant to be a unique identifier for that particular order, so you can reference those objects inside the order (ie if another object needs to refer to it, it would use the uid). It, too, would show up in the API, but not anywhere else. Most ids will not be visible in the Dashboard’s UI, to be clear, as they do not mean anything to a merchant/seller.
1 Like

Ah lord…
Q 1:
if I supply fulfillment, does that mean I must provide a tracking number as well ?

Q 2:
Adding fulfillment does this mean it’s just variables I can add? or is this an entirely by it self an api I have to create ?

Q 3:
I really don’t want to spend days longer figuring out the customers api.
I need to provide an ID for each product, and a customer ID for my own reference for EACH payment. I must be able to see this in dashboard or I will have no idea what the product purchased and who.
Are there any fields I can send with the order or payment that I can see in my dashboard? Like a custom string? obviously I would prefer multiple custom strings but if I only get 1 I can embed customer ID and all product ID’s in there.

I’m sorry for the trouble!!

  1. Tracking number is not a required field, no, but it is an optional field. You do not need to provide it. You can see more info about fulfillments (“ordering ahead”) here.
  2. It’s an additional field in the CreateOrder request, see link above for more info.
  3. No way to see product IDs as far as I know, unless you want to add it as a “note” (which exists in each line item, or the overall order). Same thing with the customer; the recommendation would be to create customers so you can see them in the dashboard, but it still wouldn’t show IDs (except, possibly in the URL to access them). It sounds like if you have your own database, you would be better off creating a linking table in your database, where you would put the catalog object ids from Square, with your internal database ids (and the same with customer ids).
1 Like

Ok it seems I have to create a customer. Thanks to you, I understand the whole structure now of doing all of it.
Can I just ask you how to retrieve customer id? After I use:
$api_response = $client->getCustomersApi()->createCustomer($body);

I get:

Square\Models\CreateCustomerResponse Object
(
    [errors:Square\Models\CreateCustomerResponse:private] => 
    [customer:Square\Models\CreateCustomerResponse:private] => Square\Models\Customer Object
        (
            [id:Square\Models\Customer:private] => This is the code I need

Can you please provide me the php codes that can get me that customer ID generated there so I can pass this on when creating an order? :slight_smile:

QUESTION 2:
For example when creating a payment and you want to add customer ID to it (connecting customer ID to the payment), it seems none of these 2 rows below do it. Do you know what actually connects a payment to an existing customer id?

  • $body->setCustomerId($square_customer_id);
  • $body->setReferenceId($square_customer_id);

Regardless of the 2 even both used, it still gives me the option in dashboard to “Add customer” to the payment, when it should say “Edit customer” if you know what I mean

  1. It should be fairly similar to the Order one above:
$api_response = $client->getCustomersApi()->createCustomer($body);
$customer = $api_response->getResult()->getCustomer();
$customer->getId();

I think…
2. If $body is a CreatePaymentRequest then the first line should work. ie:

$body = new Models\CreatePaymentRequest(
    $body_sourceId,
    $body_idempotencyKey,
    $body_amountMoney
);
$body->setCustomerId("customer_id_here");
...

should work.

1 Like

I’m sorry, but it does not add the customer to the payment.
I know that because when viewing the payment in dashboard, it gives me the option to “Add to customer”.
My code looks just like yours and I tried both of the rows below and none of them adds the customer to the payment :confused: Here is my code:

$idempotency_key = uniqid();
$body = new \Square\Models\CreatePaymentRequest(
    $nonce,
    $idempotency_key,
    $amount_money
);
$body->setAutocomplete(true);
$body->setOrderId($square_order_id);
$body->setCustomerId($square_customer_id);
$body->setLocationId($location_id);

So, have you actually created a customer? What id are you passing? If it’s not a valid id, it probably will be ignored and nothing will show up in the dashboard. Feel free to share a payment_id and I can take a look on my side to see what we’re receiving in the logs.

1 Like

Yes the first thing I do in PHP is create a customer. I get the ID and then pass it in createpayment.
It’s a 26 digit long customer id and I’m 100% It’s a valid customer id.

Wait, do I have to do something like this for it to work?

$body->setSourceId($customerCardId);

Anyway, here is the payment id:
ZveeGvWmZTukjuXDGQ6YLwzHWPWZY
dk9LvrYoh1ss0FQTCeZdoxw4dlKZY
it’s one of these 2

Do you need customer id as well?


Please…please is there anyway I can extract the payment Id by any chance ?
I tried this below, didn’t work

$payment = $api_response->getResult()->getPayment();
$payment_id = $payment->getId();

Hmm, interesting, I do see a customer on it in the API, not on the dashboard. Not sure what actually happened there, I’m escalating this to our Customers API team to investigate. I’ll follow up once I hear back from them.

As for the the payment, that looks right. Is it possible you’re getting errors instead of a payment object? Or does the first line work?

1 Like