Spotify API を使って開発をしてみた！Reactでaccess tokenの取得編


## はじめに
SpotifyAPIを使用したポートフォリオ 作成しました。
APIを叩きtokenを取得するのに苦戦したので、アウトプットとして記事を投稿します。

参考になれば幸いです:bow:



## ステップ①
<h4>デベロッパーに登録</h4>

https://developer.spotify.com/documentation/web-api/
こちらのURLから登録できます。

まず、登録するためにログインします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/2824b841-a156-b389-c6d4-598758487a99.png)


ログインをしましたら、開発するアプリ用のダッシュボードを作成します。
__CREATE AN APP__をクリックして先へ進みます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/757715a4-babb-a8d4-4e61-c1f9a0eb3b38.png)

続いて、以下の様開発アプリの名前と説明を書きます。
今回は、Qiita用に作成しますので、名前はQiita、説明はtestにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/ef474686-a5c6-83c8-b3db-0e2f7d24509e.png)



ここまできたら、リダイレクトする際のURLアドレスを定義します。
SpotifyAPIではユーザーの認証に成功、あるいは認証に失敗した際に、リダイレクトするURLを定義する必要があります。
今回は、開発段階として考え、リダイレクトURLをhttp://localhost:3000/ とします。
補足：デプロイしたアプリであれば、IPアドレスなどを定義する必要があります。

EDIT SETTINGSをクリックし、画像の様にリダイレクトURLを定義しADDで追加します。
できましたら、Saveをクリックし保存します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/4f608382-4372-5ebf-4572-b33d337c4eff.png)

## ステップ②

では、でアプリを立ち上げてコードを書いていきます。

```
% npx create-react-app myapp
```
SpotifyAPIを使用するには、使用するユーザーがSpotifyのアカウント持っている必要があります。
また本番環境でも、もし他者がSpotifyAPIを使用したサービスを使用する場合も本人がSpotifyアカウントを持っている必要があります。
したがって、開発側はSpotifyAPIからユーザーが任意のデータを取得できる様にプログラムを組む前にアカウントを持っているか検証するプログラムを組む必要があります。

簡単にまとめると、__SpotifyAPIは[OAuth](https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be)を利用するため、ユーザにログインを促す必要がある__ということです。

流れのイメージは以下の感じです。

+ ログインボタンをクリック
+  Spotifyのログインページへリダイレクト
+  ログイン後のページへリダイレクト(Spotifyのデータを取得できる様になる)

<h5>ログインコンポーネントを作成</h5>
まずは、Spotifyアカウントへログインしていない状態の時のコンポーネントを作成します。
あまり深く考えず記述はこんな感じです。

```react
import React from 'react'
import { accessUrl } from "./Spotify";

function Login() {
  return (
    <div className="Login">
      <h2>ログイン前です</h2>
      <a href={accessUrl}>spotifyへログイン</a>
    </div>
  )
}

export default Login

```
accessURLの中身は、次に解説しますがspotifyがアクセスを承認する先のURLです。



<h5>ユーザーのアクセスを承認する</h5>

まずは、Spotifyコンポーネントを作成しアクセスを承認する先のURLを組み立てます。

以下を定義する必要があります。
・https://accounts.spotify.com/authorize
(上記URLは、承認ページへアクセスするためのURLです。[詳しくはこちら](https://developer.spotify.com/documentation/general/guides/authorization-guide/))
・clientId
(ダッシュボードへログインした際に確認できます！)
・scopes
(対応する範囲を決めます)
・SpotifyのログインページのURL

先に記述以下です。

```react:Spotify.js
export const  authEndpoint = "https://accounts.spotify.com/authorize";


const redirectUri = "http://localhost:3000/";

const clientId = "22b595ba74a041a493fe4eb9472cdb51";

// 対応する範囲を決める
const scopes = [
  "user-read-currently-playing",
  "user-read-recently-played",
  "user-read-playback-state",
  "user-top-read",
  "user-modify-playback-state",
];

export const getTokenFromUrl = () => {
  return window.location.hash
    .substring(1)
    .split('&')
    .reduce((initial, item) => {
      let parts = item.split('=');
      initial[parts[0]] = decodeURIComponent(parts[1]);
      return initial
    }, {});
}


// SpotifyのログインページのURL
export const accessUrl = `${authEndpoint}?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scopes.join(
  "%20"
)}&response_type=token&show_dialog=true`;
```

ここでやっている事を簡単に説明すると、
https://accounts.spotify.com/authorize にアクセスする事でSpotifyのアクセスページへ移動ができます。
しかし、このままだとユーザーの情報がないためclientId等を定義し、新たにアクセスURLを組み立てます。

下の画像の様に、先ほどLoginコンポーネントのaタグ内に書いたURLは、ここで組み立てたアクセスURLです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/44bafb55-1e32-8c7a-cd8f-04b6df2e2730.png)

__Spotifyへログイン__を押すと以下のアクセスページへ移動し、先ほど組み立てたURLになっている事を確認できます。





![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/da479a56-b810-01cf-39ba-f6ab017ebe27.png)

<h5>access tokenの確認</h5>
ここまま、同意するボタンを押すと元の画面に戻ります。
しかし、先ほどURLが変わっています。
URLを見てみるとaccess tokenが組み込まれていることがわかります。

とりあえずは、access tokenの取得ができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/96009f4f-60c1-4a67-9801-bebd6c4a2168.png)

## ステップ③
<h5>spotifyへログインした状態とそうでない状態を分ける</h5>

現時点では、access tokenの確認はできましたが画面が変わっていません。
なので、別のコンポーネントを作成し、ログインできた時のページへ行く様にする必要があります。


ここでは、__JSX内でtokenを取得できたならばぺージへ移動する__という条件分岐をする必要があります。


```react:loggedIn.js
import React from 'react'

function LoggedIn() {
  return (
    <div>
      <h1>spotifyへログインしました</h1>
    </div>
  )
}

export default LoggedIn

```

```react:App.js
import React,{ useState, useEffect } from 'react';
import './App.css';
import Login from './Login';
import LoggedIn from './LoggedIn';
import { getTokenFromUrl } from './Spotify';



function App() {

  const [token, setToken] = useState(null);

  useEffect(() => {
    const hash = getTokenFromUrl();
    console.log(hash )
    window.location.hash = "";
    const token = hash.access_token;

    if (token) {
      setToken(token)
    }

  }, [])

  return (
    <div className="App">
      { token ? <LoggedIn/> : <Login/> } 
    </div>
  );
}

export default App;

```

条件分岐を定義するために、Spotify.jsからaccess tokenを持ってくる必要があります。
 console.log(hash)の中身を確認すると、access tokenが取得できています。
無事に取れていたら、 __const token = hash.access_token;__と、tokenを定義し
JSX内の__{ tokeno ? : }__とする事で、ユーザーがログインしている時とそうでない時を定義することができます。

実際に、試す以下のページに移動できるかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/622835/6205d230-2fef-270d-c657-d7d048df1fd1.png)



## 最後に

SpotifyAPIのを使用した開発は、他のAPIと比べても難しく感じ、特にaccess tokenの取得がなかなか上手くいかなかったので記事にしました。
[SpotifyAPIのデベロッパーサイトでクイックスタート](https://developer.spotify.com/documentation/web-api/quick-start/)を参考にしてみたものの、?????続きでした。
今回のポイントは、OAuthを利用するためのアクセス先のURLをどう組み立てるかです。
APIによっては、OAuthを利用する必要がないものもあるのでケースバイケースですが、OAuthを利用する際のロジックは同じですので、別のAPIで開発をするにも応用できるかなと思います。

最後に今回書いた記述をした書いておきますので、参考なれば幸いです。

```react:App.js
import React,{ useState, useEffect } from 'react';
import './App.css';
import Login from './Login';
import LoggedIn from './LoggedIn';
import { getTokenFromUrl } from './Spotify';



function App() {

  const [token, setToken] = useState(null);

  useEffect(() => {
    const hash = getTokenFromUrl();
    console.log(hash )
    window.location.hash = "";
    const token = hash.access_token;

    if (token) {
      setToken(token)
    }

  }, [])

  return (
    <div className="App">
      { token ?
      <LoggedIn/>
      :
      <Login/>
      } 
    </div>
  );
}

export default App;

```

```react:loggedIn.js
import React from 'react'

function LoggedIn() {
  return (
    <div>
      <h1>spotifyへログインしました</h1>
    </div>
  )
}

export default LoggedIn

```

```react:login.js
import React from 'react'
import { accessUrl } from "./Spotify";

function Login() {
  return (
    <div className="Login">
      <h2>ログイン前です</h2>
      <a href={accessUrl}>spotifyへログイン</a>
    </div>
  )
}

export default Login


```

```react:Spotify.js
export const  authEndpoint = "https://accounts.spotify.com/authorize";


const redirectUri = "http://localhost:3000/";

const clientId = "22b595ba74a041a493fe4eb9472cdb51";

// 対応する範囲を決める
const scopes = [
  "user-read-currently-playing",
  "user-read-recently-played",
  "user-read-playback-state",
  "user-top-read",
  "user-modify-playback-state",
];

export const getTokenFromUrl = () => {
  return window.location.hash
    .substring(1)
    .split('&')
    .reduce((initial, item) => {
      let parts = item.split('=');
      initial[parts[0]] = decodeURIComponent(parts[1]);
      return initial
    }, {});
}


// SpotifyのログインページのURL
export const accessUrl = `${authEndpoint}?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scopes.join(
  "%20"
)}&response_type=token&show_dialog=true`;


```