eBay oauth token and refresh tokens

前端 未结 4 510
耶瑟儿~
耶瑟儿~ 2020-12-14 02:46

been struggling for couple of days with eBay token authentication. I am finding it hard to understand how to fetch new tokens, after signing up for a developer program accou

4条回答
  •  夕颜
    夕颜 (楼主)
    2020-12-14 03:27

    I found @FullStackFool's post above very helpful. Based on that, I've built a class that gets the current token from the local DB, refreshes the token if required, displays instructions for getting a new refresh token, or processes the code to generate the new refresh token.

    Class is written in PHP 5.6 (apologies - old internal order management system), but could easily be upgraded to PHP 7 / Laravel etc.

    The constructor only takes one optional value - this is the URL string that's generated by ebay when you authenticate / signin to get a new token. If you feed this into the constructor it will parse it, get the 'code' part and then go and get a new token and refresh token.

    Hopefully the code is self explanatory - i've tried to comment it well. Hope someone else finds this useful.

    Database table (EbayTokens):

    CREATE TABLE IF NOT EXISTS `EbayTokens` (
      `TokenID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `TokenValue` text,
      `TokenCreated` datetime DEFAULT NULL,
      `TokenLifetime` int(11) unsigned DEFAULT NULL,
      `RefreshTokenValue` text,
      `RefreshTokenCreated` datetime DEFAULT NULL,
      `RefreshTokenLifetime` int(11) unsigned DEFAULT NULL,
      `TokenType` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`TokenID`),
      UNIQUE KEY `TokenID` (`TokenID`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
    

    The PHP Class (ebaytoken.php):

    string = $string;
    
        //Ininitalise the credentials.
        $this->base64_encoded_credentials = base64_encode($this->client_id . ':' . $this->secret);
    
        //Get any existing token from db.
        $this->get_token_from_db();
    
        //Check if it's expired - or almost expired. If there is no token this will not do anything.
        $this->check_db_token();
    
        //Has the current token expired??
        if(($this->access_token_expired == true) && ($this->refresh_token_expired == true)) {
          //Uh oh. Gonna have to get a new token - or display instructions on how to. Has the user entered the URL string to parse?
          if((isset($this->string)) && ($this->string != '')) {
            $this->get_new_tokens($this->string);
          } else {
            $this->get_new_tokens_instructions();
          }
        } else if($this->access_token_expired == true) {
          //Just the access token. Get a fresh one. If the refresh token has almost expired, display the instuctions.
          if($this->refresh_token_almost_expired == true) {
            $this->need_new_tokens_almost_instructions();
          }
          $this->refresh_token(); //Just the access token expired - go and refresh it using the refresh token.
        } else {
          //All fine. If the refresh token has almost expired, display the instructions.
          if($this->refresh_token_almost_expired == true) {
            $this->need_new_tokens_almost_instructions();
          }
    
        }
      }
    
      //Get the current token information from the DB. Should only be 1.
      private function get_token_from_db() {
        //Get token(s). Should only be 1. But loop anyhow.
        $sql = "SELECT * FROM EbayTokens";
        $res = @mysql_query($sql);
        $count = 0;
        if($res) {
          $count = mysql_num_rows($res);
          while ($rec = mysql_fetch_assoc($res)) {
             $this->db_token = $rec;
          }
          $this->messages[] = 'Access token loaded from database...';
        } else {
          $this->messages[] = 'No token found in database!';
        }
    
        return null;
      }
    
      //Has the access token expired?
      private function check_db_token() {
        //Do we even have a token from the db?
        if($this->db_token != null) {
    
          //Access token expired?
          $now = new DateTime();
          $now_plus_30_days = new DateTime();
          $now_plus_30_days->add(DateInterval::createFromDateString('30 days'));
    
          $date_created = DateTime::createFromFormat('Y-m-d H:i:s', $this->db_token['TokenCreated']);
          $date_expires = DateTime::createFromFormat('Y-m-d H:i:s', $this->db_token['TokenCreated']); //Make a new object.
          $date_expires->add(DateInterval::createFromDateString($this->db_token['TokenLifetime'] . ' seconds'));
    
          //Refresh token expired?
          $refresh_date_created = DateTime::createFromFormat('Y-m-d H:i:s', $this->db_token['RefreshTokenCreated']);
          $refresh_date_expires = DateTime::createFromFormat('Y-m-d H:i:s', $this->db_token['RefreshTokenCreated']); //Make a new object.
          $refresh_date_expires->add(DateInterval::createFromDateString($this->db_token['RefreshTokenLifetime'] . ' seconds'));
    
          //Check access token.
          $this->messages[] = 'Access token created on: ' . $date_created->format('d/m/Y H:i:s') . ', expires: ' . $date_expires->format('d/m/Y H:i:s');
          if($date_expires < $now) {
            $this->messages[] = ' Access token expired!';
          } else {
            $this->messages[] = ' Access token valid!';
            $this->access_token_expired = false;
          }
    
          //Check refresh token.
          $this->messages[] = 'Refresh token created on: ' . $refresh_date_created->format('d/m/Y H:i:s') . ', expires: ' . $refresh_date_expires->format('d/m/Y H:i:s');
          if($refresh_date_expires < $now) {
            $this->messages[] = 'Refresh token expired!';
          } else if($refresh_date_expires < $now_plus_30_days) {
            $this->messages[] = ' Refresh token valid! But expires within 30 days. INFORM ADMIN TO GENERATE A NEW REFRESH TOKEN.';
            $this->refresh_token_expired = false;
          } else {
            $this->messages[] = 'Refresh token valid!';
            $this->refresh_token_almost_expired = false;
            $this->refresh_token_expired = false;
          }
    
          //Was it all ok?
          if(($this->refresh_token_expired == false) && ($this->access_token_expired == false)) {
            $this->messages[] = 'All tokens valid!';
            $this->success = true;
          }
    
        }
    
        return null;
      }
    
      //Go and get a new token using the refresh token. Save it to the db.
      private function refresh_token() {
        $this->messages[] = 'OAUTH token expired - refreshing token...';
        // $this->messages[] = 'Using refresh token: ' . $this->db_token['RefreshTokenValue'];
    
        //Connect to Ebay API and refresh the existing oauth token.
        $url_get_token = 'https://api.ebay.com/identity/v1/oauth2/token';
        $port = 443;
    
        $headers = array(
          'Content-Type: application/x-www-form-urlencoded',
          'Authorization: Basic ' . $this->base64_encoded_credentials
        );
    
        $payload = array(
            'grant_type' => 'refresh_token',
            'refresh_token' => $this->db_token['RefreshTokenValue'],
            'scope=' . urlencode($this->scope),
        );
        $payload_string = http_build_query($payload);
    
        //Setting the curl parameters.
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_PORT, $port);
        curl_setopt($ch, CURLOPT_URL, $url_get_token);
        curl_setopt($ch, CURLOPT_POST, true);
        // curl_setopt($ch, CURLOPT_SSLVERSION, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload_string);
    
        $data = curl_exec($ch);
        curl_close($ch);
    
        //Convert the JSON result into array
        $array_data = json_decode($data, true);
    
        //Did we get an access token?
        $access_token = null;
        if((is_array($array_data)) && (isset($array_data['access_token']))) {
    
          //Save the tokens to the database. Set variables.
          $access_token = mysql_real_escape_string($array_data['access_token']);
          $expires_in = mysql_real_escape_string($array_data['expires_in']);
          $token_type = mysql_real_escape_string($array_data['token_type']);
    
          //Update. This will only be run if there is already a token in the DB. So no need to truncate.
          $now = new DateTime();
          $now_mysql = $now->format('Y-m-d H:i:s');
          $existing_token_id = $this->db_token['TokenID'];
    
          $sql = sprintf("UPDATE EbayTokens SET TokenValue = '%s', TokenCreated = '%s', TokenLifetime = %s, TokenType = '%s' WHERE TokenID = %d", $access_token, $now_mysql, $expires_in, $token_type, $existing_token_id);
    
          // $this->messages[] = 'SQL: ' . $sql;
          if (@executeSQL($sql)) {
            $this->messages[] = 'Success! Token refreshed and saved to database.';
          }
    
          //Update the token in this object from the freshly saved data.
          $this->get_token_from_db();
          $this->check_db_token(); //Re-check - this will mark the success flag in this object.
    
        } else {
          $this->messages[] = 'Failed to get OAUTH token! Aborting.';
          $this->messages[] =  'Reply was:' . '
    ' . print_r($array_data) . '
    '; } return null; } //Get new tokens using the string supplied. private function get_new_tokens($string) { //Parse the URL string supplied and get the 'code'. $auth_code = null; $parameters = parse_url($string); $query_array = explode('&', $parameters['query']); //Loop through and get code. Just in case the 'code' moves to another position. foreach ($query_array as $parameter) { $parameter_array = explode('=', $parameter); if($parameter_array[0] == 'code') { $auth_code = $parameter_array[1]; break; //Got what we want. } } /***********************************************************************/ $this->messages[] = "Getting eBay Oauth token using URL string..."; $this->messages[] = 'Using auth code: ' . $auth_code; //Connect to Ebay API and get an oath using authorisation code. $url_get_token = 'https://api.ebay.com/identity/v1/oauth2/token'; $port = 443; $headers = array( 'Content-Type: application/x-www-form-urlencoded', 'Authorization: Basic ' . $this->base64_encoded_credentials ); $payload = array( 'grant_type' => 'authorization_code', 'code' => urldecode($auth_code), //Get from step one. 'redirect_uri' => $this->ru_name_value, //Same as used in part one. ); $payload_string = http_build_query($payload); //Setting the curl parameters. $ch = curl_init(); curl_setopt($ch, CURLOPT_PORT, $port); curl_setopt($ch, CURLOPT_URL, $url_get_token); curl_setopt($ch, CURLOPT_POST, true); // curl_setopt($ch, CURLOPT_SSLVERSION, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload_string); $data = curl_exec($ch); curl_close($ch); //Convert the JSON result into array $array_data = json_decode($data, true); //Did we get an access token? $access_token = null; if((is_array($array_data)) && (isset($array_data['access_token']))) { //Save the tokens to the database. Set variables. $access_token = mysql_real_escape_string($array_data['access_token']); $expires_in = mysql_real_escape_string($array_data['expires_in']); $refresh_token = mysql_real_escape_string($array_data['refresh_token']); $refresh_token_expires_in = mysql_real_escape_string($array_data['refresh_token_expires_in']); $token_type = mysql_real_escape_string($array_data['token_type']); //Truncate and then insert. There may or may not be an existing token in the db. $this->truncate_db(); $now = new DateTime(); $now_mysql = $now->format('Y-m-d H:i:s'); $sql = sprintf("INSERT INTO EbayTokens SET TokenValue = '%s', TokenCreated = '%s', TokenLifetime = %d, RefreshTokenValue = '%s', RefreshTokenCreated = '%s', RefreshTokenLifetime = %d, TokenType = '%s' ", $access_token, $now_mysql, $expires_in, $refresh_token, $now_mysql, $refresh_token_expires_in, $token_type); if (@executeSQL($sql)) { $this->messages[] = 'Success! New token aquired and saved to database.'; } else { $this->messages[] = 'Error saving new token to database!'; } //Update the token in the object from the freshly saved data. $this->get_token_from_db(); $this->check_db_token(); //Re-check - this will mark the success flag. } else { $this->messages[] = 'Failed to get OAUTH token! Aborting.'; $this->messages[] = 'Reply was:' . '
    ' . print_r($array_data) . '
    '; } return null; } //Instructions to get a new refresh token. private function get_new_tokens_instructions() { $this->messages[] = 'Tokens expired! Admin action required'; $this->messages[] = "In order to get a fresh oauth token (and more importantly a refresh token), click on the URL below (it will open in a new window) and login as."; //Connect to Ebay API and get consent. The authorization code grant flow. https://developer.ebay.com/api-docs/static/oauth-authorization-code-grant.html $url_get_consent = 'https://auth.ebay.com/oauth2/authorize'; $payload = array( 'client_id=' . $this->client_id, 'redirect_uri=' . $this->ru_name_value, 'response_type=code', 'scope=' . urlencode($this->scope), ); $payload_string = implode('&', $payload); $url_get_consent_full = $url_get_consent . '?' . $payload_string; $this->messages[] = 'URL: ' . $url_get_consent_full . '
    '; $this->messages[] = "Once you have completed the login and see the window saying you can close the page, copy the URL. It will contain a 'code' parameter."; $this->messages[] = "Insert the coppied URL in the form below and click submit. The new code will be used and a new oauth and refresh token will be obtained and stored in the database."; $this->messages[] = '
    URL string:
    '; return null; } //Instructions to get a new refresh token - refresh token has ALMOST expired. private function need_new_tokens_almost_instructions() { $this->messages[] = 'Tokens ALMOST expired! Admin action required'; $this->messages[] = "In order to get a fresh oauth token (and more importantly a refresh token), click on the URL below (it will open in a new window) and login."; //Connect to Ebay API and get consent. The authorization code grant flow. https://developer.ebay.com/api-docs/static/oauth-authorization-code-grant.html $url_get_consent = 'https://auth.ebay.com/oauth2/authorize'; $payload = array( 'client_id=' . $this->client_id, 'redirect_uri=' . $this->ru_name_value, 'response_type=code', 'scope=' . urlencode($this->scope), ); $payload_string = implode('&', $payload); $url_get_consent_full = $url_get_consent . '?' . $payload_string; $this->messages[] = 'URL: ' . $url_get_consent_full . '
    '; $this->messages[] = "Once you have completed the login and see the window saying you can close the page, copy the URL. It will contain a 'code' parameter."; $this->messages[] = "Insert the coppied URL in the form below and click submit. The new code will be used and a new oauth and refresh token will be obtained and stored in the database."; $this->messages[] = '
    URL string:
    '; return null; } //Delete any tokens from the database. Use cautiously. private function truncate_db() { $sql = "TRUNCATE TABLE EbayTokens"; if (@executeSQL($sql)) { $this->messages[] = 'Existing tokens deleted from database.'; } return null; } } ?>

    And a little script to test / use:

    Current eBay Tokens";
    
    $messages = $token->messages;
    if(count($messages) > 0) {
        echo '
      '; foreach ($messages as $message) { echo '
        ' . $message . '
      '; } echo '
    '; } //Is the token valid? if($token->success == true) { get_orders($token->db_token); } //Get ebay orders. function get_orders($token_data) { echo "

    Getting Ebay Orders

    "; //Start the main request now we have the token. https://developer.ebay.com/api-docs/sell/static/orders/discovering-unfulfilled-orders.html $url_get_orders = 'https://api.ebay.com/sell/fulfillment/v1/order'; $port = 443; $headers = array( 'Authorization: Bearer ' . $token_data['TokenValue'], 'X-EBAY-C-MARKETPLACE-ID: EBAY_GB', ); $payload = array( 'filter=orderfulfillmentstatus:' . urlencode('{NOT_STARTED|IN_PROGRESS}'), 'limit=100', 'offset=0', ); $payload_string = implode('&', $payload); $url_get_orders_full = $url_get_orders . '?' . $payload_string; //Setting the curl parameters. $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url_get_orders_full); //For 'get', add query string to end of URL. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 300); $data = curl_exec($ch); curl_close($ch); //Convert the JSON result into array $array_data = json_decode($data, true); print_r('
    ');
        print_r($array_data);
        print_r('
    '); return null; } ?>

提交回复
热议问题