|  | 
  Joel Fischer - 2021-07-10 23:43:26Thank you for developing this library. It has been immensely useful for me. I do have one question going forward.
 Since Etsy is moving to its v3/Oauth2 API and discontinuing v2/Oauth1 in 2022, according to their timeline, I was wondering if you are planning on including Etsy v3/Oauth2 access as a built in function?
 
 If not, could you provide some guidance or a tutorial on how to access their Oauth2 v3 API with this library?
 
 I have the current API v2 working with the built in Etsy function but I do not know enough about Oauth2 to successfully connect to their v3 with this library.
 
 Any help would be appreciated.
  Manuel Lemos - 2021-07-11 00:51:08 - In reply to message 1 from Joel FischerHello Joel, 
Adding support to make the class work with OAuth 2 is relatively easy.
 
It may be a matter of adding a few lines of configuration to the oauth_configuration.json file .
 
Take a look at this tutorial article to get the guidance that you need:
 phpclasses.org/blog/package/7700/po ...
 
Would you like to try adding Etsy API V3 OAuth support doing that and then share the lines that you will add to the oauth_configuration.json file?
  Joel Fischer - 2021-07-11 03:08:28 - In reply to message 2 from Manuel LemosFollowing the link you provided I added the following to the oauth_configuration.json file.
 "Etsy2":
 {
 "oauth_version": "2.0",
 "dialog_url": "https://www.etsy.com/oauth/connect?response_type=code&scope={SCOPE}&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&state={STATE}",
 "access_token_url": "https://api.etsy.com/v3/public/oauth/token"
 },
 
 I get an error in my redirect url: ../login_with_etsy.php?error=invalid_request&error_description=code_challenge+is+required&state=1625970501-a03889
 
 Etsy v3 API is requiring a PKCE code challenge.
 How would I implement that?
  Joel Fischer - 2021-07-13 21:10:40 - In reply to message 1 from Joel FischerOk finally got it to work.
 Here are the changes I made:
 
 (1) Added to oauth_configuration.json
 
 "Etsy2":
 {
 "oauth_version": "2.0",
 "dialog_url": "https://www.etsy.com/oauth/connect?response_type=code&scope={SCOPE}&client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}&state={STATE}&code_challenge={CODE_CHALLENGE}&code_challenge_method=S256",
 "access_token_url": "https://api.etsy.com/v3/public/oauth/token"
 },
 
 (2) Changed oauth_client.php at line 1284
 
 from:
 '{REALM}', UrlEncode($this->realm),
 $url)))))));
 to:
 '{REALM}', UrlEncode($this->realm), str_replace(
 '{CODE_CHALLENGE}',UrlEncode($this->code_challenge),
 $url))))))));
 
 (3) Modified login_with_etsy.php
 
 <?php
 /*
 * login_with_etsy2.php
 *
 *
 *
 */
 
 /*
 *  Get the http.php file from http://www.phpclasses.org/httpclient
 */
 require('./http.php');
 require('oauth_client.php');
 session_start();
 
 function base64url_encode($plainText)
 {
 $base64 = base64_encode($plainText);
 $base64 = trim($base64, "=");
 $base64url = strtr($base64, '+/', '-_');
 return ($base64url);
 }
 
 $random = bin2hex(openssl_random_pseudo_bytes(64));
 
 if(!isset($_SESSION['verifier'])){
 $verifier = base64url_encode(pack('H*', $random));
 $_SESSION['verifier'] = $verifier;
 } else {
 $verifier = $_SESSION['verifier'];
 }
 
 if(!isset($_SESSION['challenge'])){
 $challenge = base64url_encode(pack('H*', hash('sha256', $verifier)));
 $_SESSION['challenge'] = $challenge;
 } else {
 $challenge = $_SESSION['challenge'];
 }
 
 $client = new oauth_client_class;
 $client->debug = false;
 $client->debug_http = true;
 $client->server = 'Etsy2';
 $client->redirect_uri = 'https://'.$_SERVER['HTTP_HOST'].
 dirname(strtok($_SERVER['REQUEST_URI'],'?')).'/login_with_etsy.php';
 $client->client_id = ''; $application_line = __LINE__;
 $client->client_secret = '';
 $client->authorization_header = true;
 $client->scope = 'email_r';
 $client->code_challenge = $challenge;
 $client->code_verifier = $verifier;
 
 if(strlen($client->client_id) == 0
 || strlen($client->client_secret) == 0)
 die('Please go to Etsy Developers page https://www.etsy.com/developers/register , '.
 'create an application, and in the line '.$application_line.
 ' set the client_id to key string and client_secret with shared secret. '.
 'The Callback URL must be '.$client->redirect_uri);
 
 if(($success = $client->Initialize()))
 {
 if(($success = $client->Process()))
 {
 if(strlen($client->access_token))
 {
 $user_id = explode(".", $client->access_token)[0];
 $success = $client->CallAPI(
 'https://openapi.etsy.com/v3/application/users/'.$user_id,
 'GET', array(), array('FailOnAccessError'=>true,'RequestHeaders'=>array('Authorization'=>'Bearer '.$client->access_token,'x-api-key'=>$client->client_id)), $user);
 
 }
 }
 $success = $client->Finalize($success);
 }
 if($client->exit)
 exit;
 if($success)
 {
 
 
 
 ?>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <title>Etsy OAuth client results</title>
 </head>
 <body>
 <?php
 echo '<h1> you have logged in successfully with Etsy!</h1>';
 echo '<pre>', HtmlSpecialChars(print_r($user, 1)), '</pre>';
 ?>
 </body>
 </html>
 <?php
 }
 else
 {
 ?>
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <title>OAuth client error</title>
 </head>
 <body>
 <h1>OAuth client error</h1>
 <pre>Error: <?php echo HtmlSpecialChars($client->error); ?></pre>
 
 </body>
 </html>
 <?php
 }
 
 ?>
 
 
  Joel Fischer - 2021-07-14 10:04:48 - In reply to message 4 from Joel FischerForgot 
 add to oauth_client.php around line 2055
 
 from:
 case 'authorization_code':
 $values = array(
 'code'=>$code,
 'redirect_uri'=>$redirect_uri,
 'grant_type'=>'authorization_code'
 );
 
 to:
 
 case 'authorization_code':
 $values = array(
 'code'=>$code,
 'redirect_uri'=>$redirect_uri,
 'grant_type'=>'authorization_code',
 'code_verifier'=>$this->code_verifier
 );
 
 
  Manuel Lemos - 2021-07-18 23:43:11 - In reply to message 4 from Joel FischerGreat. Is that code challenge feature that you added is based on a standard aspect of the OAuth specification?
  Joel Fischer - 2021-07-21 02:15:08 - In reply to message 6 from Manuel Lemos
  Manuel Lemos - 2021-07-21 07:03:24 - In reply to message 7 from Joel FischerHello Joel,
 Thanks for sharing that documentation. I am very busy this week but I will try to update the class into this in the upcoming weekend to support better that part of the standard. Can you please reply here if I do not reply until next Monday?
 
 
  Joel Fischer - 2021-07-27 02:52:09 - In reply to message 8 from Manuel LemosHey Manuel, Just a friendly check in for the update status for this class.
  Andrew Leonard - 2023-01-07 20:52:56 - In reply to message 9 from Joel FischerJoel, thanks for posting this.
 
 I have implemented your code, however, once the initial token expires I get the following error:
 
 Error: it was not possible to access the OAuth refresh token: it was returned an unexpected response status 401 Response: {"error":"invalid_token","error_description":"access token is expired"}
 
 Do you know how to get the refresh token?
 
 Andrew
 |