Integrasi Spotify API di Next.js

Roti dan selai, bunga dan kumbang, romeo dan juliet, beberapa hal dalam hidup memang ditakdirkan selalu bersama.

~ Dapatkan Premium, Spotify

Hhhmmm… Spotify.. saya paling suka Discover Weekly-nya, karena rekomendasinya berdasarkan musik yang sering kita mainkan jadi banyak musik yang cocok di telinga.

Di Spotify juga ada fitur Friend activity, kita bisa lihat musik apa yang sedang didengarkan teman kita. Karena saya ngga punya teman suka berbagi maka saya buat widget status playback Spotify di Next.js, siapa tau pengunjung website ini punya selera musik seperti saya,.. weirdo.

NB: Widgetnya sudah terpasang di footer website ini, scroll kebawah poll.

Tulisan kali ini hanya meliputi integrasi Spotify API saja, untuk React component akan saya tulis di lain kesempatan.

Authorization

Ada beberapa flow yang bisa kita pakai, karena kita akan memakai API tidak dari client namun dari sisi server Next.js maka kita pakai flow Authorization Code Flow.

Alasannya karena kita dapat menyimpan refresh_token dengan aman tanpa ter-ekspose ke client. Kita akan hit endpoint dari serverlessnya Vercel.

Sebelum melakukan flow tersebut kita diharuskan memiliki sebuah Spotify App

Buat Spotify App

  • Kunjungi Dashboard Developer Spotify
  • Buat App baru, klik “Create An App”
  • Di halaman App yang baru saja dibuat klik “Edit Settings”
  • Isi “Redirect URIs” dengan alamat development local, misal http://localhost:3000/callback
  • Simpan Client ID dan Client Secret ke Env Next.js

Mendapatkan code Authorization

Silahkan buka URI berikut di browser:

https://accounts.spotify.com/authorize?response_type=code&client_id=CLIENT_ID&scope=user-read-currently-playing&redirect_uri=REDIRECT_URI

*Sesuaikan CLIENT_ID dan REDIRECT_URI dengan milik kalian, untuk scope selengkapnya dapat dilihat disini

Setelah terauthentikasi browser akan redirect dengan query code:

REDIRECT_URI?code=AQC5peqvEd-xxx

code authorization tersebut akan kita gunakan untuk mendapatkan refresh_token.

Mendapatkan refresh_token

Kita akan membutuhkan basic_token berupa base64 dengan format CLIENT_ID:CLIENT_SECRET.

Basic Token

Bisa menggunakan tools seperti base64encode.org, atau bisa menggunakan command dibawah:

# shell

BASIC_TOKEN=$(echo "$CLIENT_ID:$CLIENT_SECRET" | base64)
// javascript

const basicToken = Buffer.from(`${clientId}:${clientSecret}`).toString('base64')

Refresh Token

Lakukan POST Request ke URI https://accounts.spotify.com/api/token:

# curl

curl -X POST "https://accounts.spotify.com/api/token" \
     -H "Content-Type" "application/x-www-form-urlencoded" \
     -H "Authorization" "Basic $BASIC_TOKEN" \
     -d "grant_type=authorization_code&code=$CODE&redirect_uri=$REDIRECT_URI"
// javascript

const response = await fetch('https://accounts.spotify.com/api/token', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
    Authorization: 'Basic ' + basicToken
  },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: code,
    redirect_uri: redirectUri
  }).toString()
})

console.log(response.json())

*Sesuaikan variable dengan milik kalian

Kita akan mendapatkan response berisi access_token dan refresh_token, silahkan simpan hanya refresh_token ke Env aplikasi Next.js

Membuat API di Next.js

Karena API kita akan berjalan pada platform serverless, maka kita tidak bisa menyimpan access_token yang telah kita dapatkan pada request sebelumnya, jadi setiap ada request ke API Next.js kita harus mendapatkan access_token baru untuk kemudian melakukan request data ke API Spotify

Mendapatkan access_token

const clientId = process.env.SPOTIFY_CLIENT_ID
const clientSecret = process.env.SPOTIFY_CLIENT_SECRET
const refreshToken = process.env.SPOTIFY_REFRESH_TOKEN || ''

const basicToken = Buffer.from(`${clientId}:${clientSecret}`).toString('base64')

const getAccessToken = async () => {
  const url = 'https://accounts.spotify.com/api/token'
  const headers = {
    'Content-Type': 'application/x-www-form-urlencoded',
    Authorization: 'Basic ' + basicToken
  }

  const formData = new URLSearchParams({
    grant_type: 'refresh_token',
    refresh_token: refreshToken
  })

  const response = await fetch(url, {
    method: 'POST',
    body: formData.toString(),
    headers
  })

  return response.json()
}

Mendapatkan Status Playback Spotify

const getCurrentlyPlaying = async () => {
  const { access_token } = await getAccessToken()
  const url = 'https://api.spotify.com/v1/me/player/currently-playing'
  const headers = {
    'Content-Type': 'application/json',
    Authorization: 'Bearer ' + access_token
  }

  const response = await fetch(url, { headers })

  return response.status === 200 ? response.json() : null
}

Endpoint Next.js

Silahkan sesuaikan dengan kebutuhan frontend kalian

// pages/api/now-playing.js

import { getCurrentlyPlaying } from '~/lib/spotify'

export default async (req, res) => {
  const music = await getCurrentlyPlaying()

  // Jika tidak ada musik yang sedang dimainkan
  if (!music || !music.item || !music.is_playing) {
    return res.status(200).json({ isPlaying: false })
  }

  // silahkan sesuaikan kebutuhan frontend kalian
  res.status(200).json({
    isPlaying: true,
    title: music.item.name,
    artists: music.item.artists.map(({ name }: any) => name).join(', '),
    spotifyUrl: music.item.external_urls.spotify,
    cover: music.item.album.images.find(({ height }: any) => height === 64)?.url
  })
}

Kesimpulan

Dengan Next.js kita dapat mudah integrasi ke platform apapun karena platform serverless dan fitur API pages-nya.

Sepertinya goal tulisan ini sudah tercapai, untuk React component akan saya tulis di lain waktu. Jika ada yang penasaran source website ini saya open di repository github saya.

Terimakasih.