Create_Payment_Link and LocationID of seller

SCENARIO
theleedz.com brokers the payment of a digital asset from Buyer → Seller with the app taking a small fee. In the scenario provided the seller is ‘scott.gross’ and the buyer is ‘theleedz’ – an admin accounts up just like any other user. I have two Square accounts – two white cards one for scott.gross and one for theleedz. I have tested it both ways - with either party being buyer/seller.

SANDBOX
In the sandbox I was able authorize both accounts and generate access/refresh tokens. In the sandbox I can create a payment link and proceed through to the sample payment dialog with the caveat that to proceed further, to test app fee etc., I would need to switch to production.

I switched to production – create_payment_link is broke.

TESTING

SELLER
scott.gross
ACCESS TOKEN:

BUYER
theleedz
ACCESS TOKEN:

AWS

APP: My app is sending the following request – this is taken right from AWS logs:
URL: POST /v2/online-checkout/payment-links - Square API Explorer

HEADER
{‘Accept’: ‘application/json’, ‘Square-Version’: ‘2023-12-13’, ‘Authorization’: ‘Bearer ACCESS_TOKEN’, ‘Content-Type’: ‘application/json’}

BODY
{“checkout_options”: {“app_fee_money”: {“currency”: “USD”, “amount”: 18}, “redirect_url”: “https://theleedz.com/hustle.html”, “merchant_support_email”: “[email protected]”, “ask_for_shipping_address”: “false”}, “quick_pay”: {“location_id”: “L40JHVTYW8QZW”, “name”: “scott’s airbrush 2/20”, “price_money”: {“currency”: “USD”, “amount”: 200}}, “description”: “[airbrush] scott’s airbrush 2/20 (90034)”, “payment_note”: “151882451|airbrush|theleedz”}’

The result is HTTP ERROR 400 Bad Request

WEB CLIENT

curl https://connect.squareup.com/v2/online-checkout/payment-links
-X POST
-H ‘Square-Version: 2024-01-18’
-H ‘Authorization: Bearer ACCESS TOKEN’
-H ‘Content-Type: application/json’
-d ‘{
“quick_pay”: {
“location_id”: “L40JHVTYW8QZW”,
“name”: “Sample Caricature Party Sample”,
“price_money”: {
“amount”: 200,
“currency”: “USD”
}
},
“payment_note”: “62732928|caricatures|scott.gross”,
“description”: “[caricatures] Sample Caricature Party Sample (90034)”,
“checkout_options”: {
“app_fee_money”: {
“amount”: 18,
“currency”: “USD”
},
“redirect_url”: “https://theleedz.com/hustle.html”,
“merchant_support_email”: “[email protected]”,
“ask_for_shipping_address”: false
}
}’

------ RESPONSE ------

cache-control: no-cache
content-length: 119
content-type: application/json
date: Tue, 06 Feb 2024 23:18:06 GMT
square-version: 2024-01-18

{
“errors”: [
{
“category”: “INVALID_REQUEST_ERROR”,
“code”: “INVALID_VALUE”,
“detail”: “Invalid location id: L40JHVTYW8QZW.”
}
]
}

********** IF I replace the seller’s token with the buyer’s token – it works!**

curl https://connect.squareup.com/v2/online-checkout/payment-links
-X POST
-H ‘Square-Version: 2024-01-18’
-H ‘Authorization: Bearer ACCESS_TOKEN’
-H ‘Content-Type: application/json’
-d ‘{
“quick_pay”: {
“location_id”: “L40JHVTYW8QZW”,
“name”: “Sample Caricature Party Sample”,
“price_money”: {
“amount”: 200,
“currency”: “USD”
}
},
“payment_note”: “62732928|caricatures|scott.gross”,
“description”: “[caricatures] Sample Caricature Party Sample (90034)”,
“checkout_options”: {
“app_fee_money”: {
“amount”: 18,
“currency”: “USD”
},
“redirect_url”: “https://theleedz.com/hustle.html”,
“merchant_support_email”: “[email protected]”,
“ask_for_shipping_address”: false
}
}’

PRODUCES

{
“payment_link”: {
“id”: “6OROXAQUJYERW2BJ”,
“version”: 1,
“description”: “[caricatures] Sample Caricature Party Sample (90034)”,
“order_id”: “HNUwrZ6MP9snpqzE8FSH8B6QYxCZY”,
“checkout_options”: {
“redirect_url”: “https://theleedz.com/hustle.html”,
“merchant_support_email”: “[email protected]”,
“ask_for_shipping_address”: false,
“app_fee_money”: {
“amount”: 18,
“currency”: “USD”
}
},
“url”: “https://square.link/u/oVcvJNDO”,
“long_url”: “https://checkout.square.site/merchant/MLT52FZYSY9GD/order/HNUwrZ6MP9snpqzE8FSH8B6QYxCZY”,
“created_at”: “2024-02-06T23:19:32Z”,
“payment_note”: “62732928|caricatures|scott.gross”
},
“related_resources”: {
“orders”: [
{
“id”: “HNUwrZ6MP9snpqzE8FSH8B6QYxCZY”,
“location_id”: “L40JHVTYW8QZW”,
“source”: {
“name”: “The Leedz”
},
“line_items”: [
{
“uid”: “EZqSNyEeMVyTOP1NlS4Lb”,
“name”: “Sample Caricature Party Sample”,
“quantity”: “1”,
“item_type”: “ITEM”,
“base_price_money”: {
“amount”: 200,
“currency”: “USD”
},
“variation_total_price_money”: {
“amount”: 200,
“currency”: “USD”
},
“gross_sales_money”: {
“amount”: 200,
“currency”: “USD”
},
“total_tax_money”: {
“amount”: 0,
“currency”: “USD”
},
“total_discount_money”: {
“amount”: 0,
“currency”: “USD”
},
“total_money”: {
“amount”: 200,
“currency”: “USD”
},
“total_service_charge_money”: {
“amount”: 0,
“currency”: “USD”
}
}
],
“fulfillments”: [
{
“uid”: “yr1vvNP6Ml2qJtU06QFZn”,
“type”: “DIGITAL”,
“state”: “PROPOSED”
}
],
“net_amounts”: {
“total_money”: {
“amount”: 200,
“currency”: “USD”
},
“tax_money”: {
“amount”: 0,
“currency”: “USD”
},
“discount_money”: {
“amount”: 0,
“currency”: “USD”
},
“tip_money”: {
“amount”: 0,
“currency”: “USD”
},
“service_charge_money”: {
“amount”: 0,
“currency”: “USD”
}
},
“created_at”: “2024-02-06T23:19:32.662Z”,
“updated_at”: “2024-02-06T23:19:32.662Z”,
“state”: “DRAFT”,
“version”: 1,
“total_money”: {
“amount”: 200,
“currency”: “USD”
},
“total_tax_money”: {
“amount”: 0,
“currency”: “USD”
},
“total_discount_money”: {
“amount”: 0,
“currency”: “USD”
},
“total_tip_money”: {
“amount”: 0,
“currency”: “USD”
},
“total_service_charge_money”: {
“amount”: 0,
“currency”: “USD”
},
“net_amount_due_money”: {
“amount”: 200,
“currency”: “USD”
}
}
]
}
}

ANALYSIS

The Leedz (Main)

L40JHVTYW8QZW

Location ID comes from the application developer console. It is associated with ‘theleedz’ because theleedz is a character in the scenario – but it would have no connection to two random users of the system. The checkout link ONLY works when the access token of the application – matching the LocationID – is encoded into the link.

This is a problem for me. The checkout link must be encoded with the seller’s info – not the buyer’s info. And not the app info. The seller is giving permission to the app to deposit the sale money into their Square account (and subtract the app fee). The buyer is brand new to the system and just paying for a digital asset with a credit card. They are providing all the required ‘authorization’ in the checkout dialog when they authorize payment. Although I store access/refresh tokens for the buyer when they sign up – that is only so they can then sell and collect money. It should be possible to use the system just by coming to the page and seeing a list of checkout links and buying one. There is no way to determine the locationID of a random buyer.

+Scott

theleedz.com

The create_payment_link API wants the LocationID of the seller matching the authorization token. I thought I might use the Location API

– I have the seller’s authorization token – just exchange it for the Location ID
`GET /v2/locations/{location_id} - Square API Explorer
https://connect.squareup.com/v2/locations/main

This generates the error

category": “AUTHENTICATION_ERROR”,
“code”: “INSUFFICIENT_SCOPES”,
“detail”: “The merchant has not given your application sufficient permissions to do that. The merchant must authorize your application for the following scopes: MERCHANT_PROFILE_READ”
}

!! HOWEVER !! those permissions ARE granted during oauth – see Developer Dashboard Log:

REQUEST
{
“client_id”: “sq0idp-fGPn-QZvqEnvGeWHA9sHMw”,
“client_secret”: “[redacted]”,
“code”: “[redacted]”,
“redirect_uri”: “User Editor”,
“grant_type”: “authorization_code”,
“scopes”: [
“ORDERS_WRITE”,
“ORDERS_READ”,
“PAYMENTS_WRITE”,
“PAYMENTS_READ”,
“PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS”,
“MERCHANT_PROFILE_READ”
]
}

RESPONSE

200 – OK

{
“access_token”: “[redacted]”,
“token_type”: “bearer”,
“expires_at”: “2024-03-08T01:15:21Z”,
“merchant_id”: “516FB1QR33PFH”,
“refresh_token”: “[redacted]”,
“short_lived”: false
}

The location_id your passing in is L40JHVTYW8QZW which is for the Leedz account. The merchant_id for the permissions your showing is for 516FB1QR33PFH which is the scott.gross account. If your going to use that token you have to use a scott.gross location_id since that’s the OAuth’d account. :slightly_smiling_face:

How do I obtain the Location ID for ‘scottgross.works’ ?
I have the authorization token.
When the oauth was granted I asked for and received MERCHANT_PROFILE_READ

{
“client_id”: “sq0idp-fGPn-QZvqEnvGeWHA9sHMw”,
“client_secret”: “[redacted]”,
“code”: “[redacted]”,
“redirect_uri”: “User Editor”,
“grant_type”: “authorization_code”,
“scopes”: [
“ORDERS_WRITE”,
“ORDERS_READ”,
“PAYMENTS_WRITE”,
“PAYMENTS_READ”,
“PAYMENTS_WRITE_ADDITIONAL_RECIPIENTS”,
“MERCHANT_PROFILE_READ”
]
}

I went to
-developer.squareup.com/explorer/square_2024-01-18/locations-api/retrieve-location

I tried exchanging the auth token for the location ID but still got this ERROR
“category”: “AUTHENTICATION_ERROR”,
“code”: “INSUFFICIENT_SCOPES”,
“detail”: “The merchant has not given your application sufficient permissions to do that. The merchant must authorize your application for the following scopes: MERCHANT_PROFILE_READ”

With the access token for merchant_id: 516FB1QR33PFH you’ll call ListLocations. :slightly_smiling_face: