Last active
May 30, 2025 23:12
-
-
Save abc123me/76e4f8eeab24e2de6ed86130b22be1c3 to your computer and use it in GitHub Desktop.
PHP wrapper for Digikey API with OAUTH 3-legged process and refresh token handling
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 | |
| class DigikeyAPI { | |
| private $clientID; | |
| private $clientSecret; | |
| private $tokenFile; | |
| private $barcodeURL; | |
| private $tokenURL; | |
| private $partSearchURL; | |
| private $mediaURL; | |
| public function __construct( | |
| string $clientID, | |
| string $clientSecret, | |
| string $tokenFile = __DIR__ . '/dk_token.json', | |
| string $tokenURL = 'https://api.digikey.com/v1/oauth2/token', | |
| string $barcodeURL = 'https://api.digikey.com/Barcoding/v3/ProductBarcodes/__REPLACE__', | |
| string $searchURL = 'https://api.digikey.com/products/v4/search/__REPLACE__' | |
| ) { | |
| $this->clientID = $clientID; | |
| $this->clientSecret = $clientSecret; | |
| $this->tokenFile = $tokenFile; | |
| $this->tokenURL = $tokenURL; | |
| $this->searchURL = $searchURL; | |
| $this->barcodeURL = $barcodeURL; | |
| /* catch these errors early */ | |
| $this->checkTokenFile(); | |
| } | |
| public function lookupPartPricing(string $value): array { | |
| return $this->lookupGeneric($value, $this->searchURL . "/pricing"); | |
| } | |
| public function lookupPartMedia(string $value): array { | |
| return $this->lookupGeneric($value, $this->searchURL . "/media"); | |
| } | |
| public function lookupPartNumber(string $value): array { | |
| return $this->lookupGeneric($value, $this->searchURL . "/productdetails"); | |
| } | |
| public function lookupPartByBarcode(string $value): array { | |
| return $this->lookupGeneric($value, $this->barcodeURL); | |
| } | |
| private function lookupGeneric(string $value, string $base_url) { | |
| $url = str_replace("__REPLACE__", $value, $base_url); | |
| return $this->makeRequest('GET', $url, $this->tokenHeaders()); | |
| } | |
| private function tokenHeaders(): array { | |
| return [ | |
| "Authorization: Bearer " . $this->getAccessToken(), | |
| "X-DIGIKEY-Client-Id: " . $this->clientID, | |
| "Accept: application/json" | |
| ]; | |
| } | |
| private function getAccessToken(): string { | |
| $this->checkTokenFile(); | |
| $tokenDat = json_decode(file_get_contents($this->tokenFile), true); | |
| if ($tokenDat && $tokenDat['access_expires'] > time()) { | |
| /* An access token already exists, don't refresh it */ | |
| return $tokenDat['access_token']; | |
| } | |
| /* Time to get the access token since it's went bad */ | |
| if ($tokenDat && $tokenDat['refresh_expires'] > time()) { | |
| /* Generate a new access token from the refresh token */ | |
| return $this->useRefreshToken($tokenDat['refresh_token']); | |
| } else { | |
| /* Generate and store a new refresh/access tokens */ | |
| return $this->generateNewTokens(); | |
| } | |
| } | |
| private function generateNewTokens() { | |
| throw new Exception("Not yet implemented!"); | |
| } | |
| private function useRefreshToken($oldToken) { | |
| $postData = http_build_query([ | |
| 'client_id' => $this->clientID, | |
| 'client_secret' => $this->clientSecret, | |
| 'refresh_token' => $oldToken, | |
| 'grant_type' => 'refresh_token' | |
| ]); | |
| $headers = [ 'Content-Type: application/x-www-form-urlencoded' ]; | |
| $response = $this->makeRequest('POST', $this->tokenURL, $headers, $postData); | |
| if (!isset($response['access_token'], $response['expires_in'])) | |
| throw new Exception('Access token/expiry not found in response'); | |
| if (!isset($response['refresh_token'], $response['refresh_token_expires_in'])) | |
| throw new Exception('Refresh token/expiry not found in response'); | |
| $cacheData = [ | |
| 'access_token' => $response['access_token'], | |
| 'refresh_token' => $response['refresh_token'], | |
| 'access_expires' => time() + $response['expires_in'] - 60, | |
| 'refresh_expires' => time() + $response['refresh_token_expires_in'] - 60 | |
| ]; | |
| file_put_contents($this->tokenFile, json_encode($cacheData)); | |
| return $response['access_token']; | |
| } | |
| private function makeRequest(string $method, string $url, array $headers = [], $body = null): array { | |
| $ch = curl_init(); | |
| curl_setopt($ch, CURLOPT_URL, $url); | |
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
| if ($method === 'POST') { | |
| curl_setopt($ch, CURLOPT_POST, true); | |
| if ($body !== null) | |
| curl_setopt($ch, CURLOPT_POSTFIELDS, $body); | |
| } | |
| curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); | |
| $result = curl_exec($ch); | |
| if (curl_errno($ch)) { | |
| throw new Exception('cURL error: ' . curl_error($ch)); | |
| } | |
| $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); | |
| curl_close($ch); | |
| $response = json_decode($result, true); | |
| if ($status >= 400) { | |
| throw new Exception("API Error (HTTP $status): " . json_encode($response)); | |
| } | |
| return $response; | |
| } | |
| private function checkTokenFile() { | |
| if (!file_exists($this->tokenFile)) | |
| throw new Exception("Token file does not exist!"); | |
| if (!is_readable($this->tokenFile)) | |
| throw new Exception("Token file is not readable!"); | |
| if (!is_writeable($this->tokenFile)) | |
| throw new Exception("Token file is not writeable!"); | |
| } | |
| } | |
| ?> |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This may or may not be secure and should be treated as MIT Licensed code, Use this at YOUR OWN RISK and distribute however you wish. It requires php and php-curl to be installed.