Created
February 9, 2026 11:43
-
-
Save anova/6545da90d69db918dc87b87c7caf6615 to your computer and use it in GitHub Desktop.
Shopify access token retriever. Needs .env file on same folder.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Shopify OAuth Access Token Handler | |
| * This script verifies the HMAC from Shopify and exchanges the authorization code for an access token. | |
| */ | |
| // 1. Load environment variables from .env | |
| function loadEnv($path) { | |
| if (!file_exists($path)) { | |
| return false; | |
| } | |
| $lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); | |
| foreach ($lines as $line) { | |
| if (strpos(trim($line), '#') === 0) continue; | |
| $parts = explode('=', $line, 2); | |
| if (count($parts) === 2) { | |
| $key = trim($parts[0]); | |
| $value = trim($parts[1]); | |
| putenv("$key=$value"); | |
| $_ENV[$key] = $value; | |
| } | |
| } | |
| return true; | |
| } | |
| loadEnv(__DIR__ . '/.env'); | |
| $apiKey = getenv('CLIENT_ID'); | |
| $apiSecret = getenv('SECRET'); | |
| // 2. Capture parameters from Shopify | |
| $params = $_GET; | |
| $hmac = $params['hmac'] ?? ''; | |
| // Note: In this context, Shopify sends hmac, host, shop, and timestamp | |
| if (empty($hmac) || empty($params['shop']) || empty($params['timestamp'])) { | |
| http_response_code(400); | |
| die("Missing required parameters (hmac, shop, or timestamp)."); | |
| } | |
| // 3. Verify HMAC | |
| // Remove hmac from the params to verify | |
| unset($params['hmac']); | |
| ksort($params); | |
| // Reconstruct the query string using key=value pairs joined by & | |
| $pairs = []; | |
| foreach ($params as $key => $value) { | |
| $pairs[] = "$key=$value"; | |
| } | |
| $computedString = implode('&', $pairs); | |
| $calculatedHmac = hash_hmac('sha256', $computedString, $apiSecret); | |
| if (!hash_equals($hmac, $calculatedHmac)) { | |
| http_response_code(401); | |
| die("HMAC verification failed. The request is not authentic."); | |
| } | |
| // 4. Get Access Token via client_credentials | |
| // Since we don't have a 'code', we use client_credentials as seen in your Node.js script. | |
| $query = [ | |
| "grant_type" => "client_credentials", | |
| "client_id" => $apiKey, | |
| "client_secret" => $apiSecret | |
| ]; | |
| $accessTokenUrl = "https://" . $params['shop'] . "/admin/oauth/access_token"; | |
| $ch = curl_init(); | |
| curl_setopt($ch, CURLOPT_URL, $accessTokenUrl); | |
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
| curl_setopt($ch, CURLOPT_POST, true); | |
| curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($query)); | |
| curl_setopt($ch, CURLOPT_HTTPHEADER, ["Accept: application/json"]); | |
| $response = curl_exec($ch); | |
| $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
| $error = curl_error($ch); | |
| curl_close($ch); | |
| if ($error) { | |
| http_response_code(500); | |
| die("CURL Error: " . $error); | |
| } | |
| $result = json_decode($response, true); | |
| if ($httpCode === 200 && isset($result['access_token'])) { | |
| header('Content-Type: application/json'); | |
| echo json_encode([ | |
| "status" => "success", | |
| "access_token" => $result['access_token'], | |
| "shop" => $params['shop'] | |
| ], JSON_PRETTY_PRINT); | |
| } else { | |
| http_response_code($httpCode); | |
| header('Content-Type: application/json'); | |
| echo json_encode([ | |
| "status" => "error", | |
| "message" => "Failed to retrieve access token using client_credentials", | |
| "details" => $result | |
| ], JSON_PRETTY_PRINT); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment