Files
HotLunches/square/seed_test_connection.php
T
2026-10-19 15:22:52 -07:00

123 lines
6.1 KiB
PHP

<?php
/**
* Seed a Square connection for LOCAL TESTING — bypasses OAuth onboarding so you
* can test the "Pay with Square" widget + charge (Phase 3/4) without a public
* URL or the host app.
*
* It VALIDATES the access token against Square (GET /v2/locations) and
* auto-resolves the location + currency + merchant id, so you only need the
* token. Pass --location to override the auto-pick.
*
* Get the token from: Developer Dashboard → open your app → toggle to SANDBOX →
* Credentials → "Sandbox Access Token" (the EAAA… value). Use the SAME
* application whose Sandbox Application ID is your client_id in config.php.
*
* USAGE (CLI only):
* php seed_test_connection.php --school="Test School" --token=EAAA...
* php seed_test_connection.php --school="Test School" --token=EAAA... --location=L123 --currency=CAD
*
* Then: php -S 127.0.0.1:8000 and open the URL it prints.
*
* ⚠️ Sandbox only. Stored ENCRYPTED with your config token_encryption_key (set
* one first, or the token is stored in plaintext).
*/
if (PHP_SAPI !== 'cli') { http_response_code(403); echo "CLI only.\n"; exit(1); }
require_once __DIR__ . '/lib/SquareClient.php';
require_once __DIR__ . '/lib/MerchantStore.php';
$config = require __DIR__ . '/config.php';
$opts = getopt('', ['school:', 'token:', 'location::', 'merchant::', 'currency::', 'help']);
if (isset($opts['help']) || empty($opts['school']) || empty($opts['token'])) {
fwrite(STDOUT, "Usage: php seed_test_connection.php --school=\"Name\" --token=EAAA... [--location=L123] [--currency=CAD]\n");
exit(isset($opts['help']) ? 0 : 1);
}
if (($config['env'] ?? 'sandbox') !== 'sandbox') {
fwrite(STDERR, "Refusing to run: config env is not 'sandbox'. This helper is for sandbox testing only.\n");
exit(1);
}
if (empty($config['token_encryption_key'])) {
fwrite(STDERR, "WARNING: token_encryption_key is not set in config.php — the token will be stored in PLAINTEXT.\n");
}
$school = (string)$opts['school'];
$token = trim((string)$opts['token']);
$client = new SquareClient($config);
// ── Validate the token + discover locations. ────────────────────────────────
fwrite(STDOUT, "Checking token against " . $client->getConnectBase() . " …\n");
$resp = $client->api('GET', '/v2/locations', $token);
if ($resp['status'] === 401) {
fwrite(STDERR, "\n❌ HTTP 401 Unauthorized — Square rejected this access token.\n"
. " Fix: Developer Dashboard → open your app → toggle to SANDBOX → Credentials →\n"
. " copy the \"Sandbox Access Token\" (starts with EAAA…). Make sure:\n"
. " • you copied the SANDBOX token (not Production), and the whole string,\n"
. " • it's from the SAME app as your client_id (" . $config['client_id'] . "),\n"
. " • the token hasn't been rotated since you copied it.\n");
exit(1);
}
if ($resp['status'] < 200 || $resp['status'] >= 300) {
fwrite(STDERR, "\n❌ GET /v2/locations failed (HTTP " . $resp['status'] . "): "
. json_encode($resp['body']['errors'] ?? $resp['body']) . "\n");
exit(1);
}
$locations = $resp['body']['locations'] ?? [];
if (empty($locations)) {
fwrite(STDERR, "\n❌ Token is valid but the seller has no locations. Create one in the sandbox seller dashboard.\n");
exit(1);
}
// ── Pick a location. ─────────────────────────────────────────────────────────
$wanted = isset($opts['location']) ? (string)$opts['location'] : '';
$chosen = null;
foreach ($locations as $l) {
if ($wanted !== '') { if (($l['id'] ?? '') === $wanted) { $chosen = $l; break; } continue; }
$active = ($l['status'] ?? '') === 'ACTIVE';
$card = in_array('CREDIT_CARD_PROCESSING', $l['capabilities'] ?? [], true);
if ($active && $card) { $chosen = $l; break; } // best: active + can take cards
if ($active && $chosen === null) { $chosen = $l; } // fallback: any active
}
if ($chosen === null) $chosen = $locations[0];
if ($wanted !== '' && ($chosen['id'] ?? '') !== $wanted) {
fwrite(STDERR, "\n❌ Location '$wanted' not found for this token. Available: "
. implode(', ', array_map(fn($l) => $l['id'] ?? '?', $locations)) . "\n");
exit(1);
}
$locationId = $chosen['id'];
$currency = strtoupper((string)($opts['currency'] ?? ($chosen['currency'] ?? 'CAD')));
$canCards = in_array('CREDIT_CARD_PROCESSING', $chosen['capabilities'] ?? [], true);
// merchant id: --merchant, else GET /v2/merchants, else a placeholder.
$merchantId = (string)($opts['merchant'] ?? '');
if ($merchantId === '') {
$m = $client->api('GET', '/v2/merchants', $token);
$merchantId = $m['body']['merchant'][0]['id'] ?? 'SANDBOX_TEST_MERCHANT';
}
// ── Store it. ────────────────────────────────────────────────────────────────
$store = new MerchantStore($config);
$store->saveConnection($school, $merchantId, $token, '', gmdate('Y-m-d\TH:i:s\Z', time() + 365 * 86400));
$store->mergeMeta($school, [
'active_location_id' => $locationId,
'square_ready' => true,
'currency' => $currency,
'seeded_for_testing' => true,
'status_checked_at' => time(),
]);
fwrite(STDOUT, "\n✅ Seeded connection for \"$school\"\n");
fwrite(STDOUT, " merchant_id : $merchantId\n");
fwrite(STDOUT, " location_id : $locationId (" . ($chosen['status'] ?? '?') . ($canCards ? ", card-capable" : ", NO card capability") . ")\n");
fwrite(STDOUT, " currency : $currency\n");
fwrite(STDOUT, " token : stored " . (empty($config['token_encryption_key']) ? "(PLAINTEXT)" : "encrypted") . "\n");
if (!$canCards) {
fwrite(STDOUT, "\n⚠️ This location has no CREDIT_CARD_PROCESSING capability — card charges may fail.\n");
}
fwrite(STDOUT, "\nNext: php -S 127.0.0.1:8000 then open\n");
fwrite(STDOUT, " http://127.0.0.1:8000/demo-checkout.php?school=" . rawurlencode($school) . "\n");
exit(0);