вступление

Когда я впервые начал этот проект, я столкнулся с проблемой, заключающейся в том, что не было столько руководств по аутентификации пользователей Spotify, как я ожидал. Поэтому я решил опубликовать свой подход к этой проблеме.

Это будет цикл из двух статей. В первом я собираюсь пройти процесс аутентификации с помощью Spotify, ReactNative и expo-auth-session. Вторая часть будет посвящена отображению и воспроизведению ваших личных текущих лучших 20 песен в виде трутоподобных мечей. Для быстрой демонстрации посмотрите это видео.

Весь проект можно найти здесь.

Настраивать

Прежде чем мы сможем погрузиться в код, нам сначала нужно настроить некоторые вещи, касающиеся Spotify. Перейдите на этот сайт и войдите в свою учетную запись Spotify. После этого создайте приложение. На следующем экране позже вам понадобится идентификатор клиента.

Затем вам нужно перейти на экран «Изменить настройки». Там вам нужно вставить URI перенаправления. В моем случае это «exp: //127.0.0.1: 19000 /», поскольку я работаю с expo на своем локальном компьютере.

Вот и все, что касалось установки! Давайте теперь погрузимся в код!

Экран входа в систему

import { StatusBar } from "expo-status-bar";
import React from "react";
import { View, StyleSheet, KeyboardAvoidingView, Text } from "react-native";
import { Button, Image } from "react-native-elements";
import { useEffect, useState } from "react";
import { ResponseType, useAuthRequest } from "expo-auth-session";
import { useSelector, useDispatch } from "react-redux";
import * as tokenAction from "../store/actions/token";
import axios from "axios";
import * as songAction from "../store/actions/topSongs";
const discovery = {
  authorizationEndpoint: 
  "https://accounts.spotify.com/authorize",
  tokenEndpoint: 
  "https://accounts.spotify.com/api/token",
};
const LoginScreen = ({ navigation }) => {
  const dispatch = useDispatch();
  const [token, setToken] = useState("");
  const [request, response, promptAsync] = 
  useAuthRequest(
    {
      responseType: ResponseType.Token,
      clientId: "YOUR_CLIENT_ID",
      scopes: [
        "user-read-currently-playing",
        "user-read-recently-played",
        "user-read-playback-state",
        "user-top-read",
        "user-modify-playback-state",
        "streaming",
        "user-read-email",
        "user-read-private",
      ],
      // In order to follow the "Authorization Code Flow" 
      // to fetch token after authorizationEndpoint
      // this must be set to false
      usePKCE: false,
      redirectUri: "exp://127.0.0.1:19000/",
    },
    discovery
  );
  useEffect(() => {
    if (response?.type === "success") {
      const { access_token } = response.params;
      setToken(access_token);
    }
  }, [response]);
  useEffect(() => {
    if (token) {
      axios(
        "https://api.spotify.com/v1/me/top/
        tracks?time_range=short_term", {
        method: "GET",
        headers: {
          Accept: "application/json",
          "Content-Type": "application/json",
          Authorization: "Bearer " + token,
        },
      })
        .then((response) => {
          dispatch(songAction.addTopSongs(response));
        })
        .catch((error) => {
          console.log("error", error.message);
        });
      setTimeout(
        () =>
          navigation.replace("Home", {
            token: token,
            
          }),
        500
      );
      dispatch(tokenAction.addToken(token));
    }
  });
  return (
    <KeyboardAvoidingView behavior="padding" 
    style={styles.container}>
      <StatusBar style="light" />
      <Text
        style={{
          fontSize: 30,
          fontWeight: "bold",
          color: "white",
          marginBottom: "20%",
        }}
      >
        top song player
      </Text>
      <Button
        title="Login with Spotify"
        style={styles.button}
        onPress={() => {
          promptAsync();
        }}
      />
      <View style={{ height: 100 }} />
    </KeyboardAvoidingView>
  );
};
export default LoginScreen;
const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    justifyContent: "center",
    backgroundColor: "black",
  },
  button: {
    width: 200,
    marginTop: 50,
  },
});

Если вы посмотрите на импорт, то увидите, что я использую redux для управления состоянием, axios для выборки данных и expo-auth-session для фактической аутентификации. Остальной импорт довольно стандартный.

Как правило, мы используем неявный поток аутентификации.

const discovery = {
  authorizationEndpoint: 
  "https://accounts.spotify.com/authorize",
  tokenEndpoint: 
  "https://accounts.spotify.com/api/token",
};

Первая константа обнаружение содержит две ссылки, которые необходимы для процесса аутентификации. authorizationEndpoint будет ссылкой, на которую вы будете перенаправлены после нажатия кнопки входа в систему. Второй, tokenEndpoint, вызовет API Spotify, чтобы создать уникальный токен Spotify для текущего сеанса.

const [request, response, promptAsync] = 
useAuthRequest(
    {
      responseType: ResponseType.Token,
      clientId: "YOUR_CLIENT_ID",
      scopes: [
        "user-read-currently-playing",
        "user-read-recently-played",
        "user-read-playback-state",
        "user-top-read",
        "user-modify-playback-state",
        "streaming",
        "user-read-email",
        "user-read-private",
      ],
      // In order to follow the "Authorization Code Flow" to 
      // fetch token after authorizationEndpoint
      // this must be set to false
      usePKCE: false,
      redirectUri: "exp://127.0.0.1:19000/",
    },
    discovery
  );

Подробное описание ловушки useAuthRequest смотрите здесь. Самое важное, что нужно изменить в этом фрагменте кода, - это сначала clientId. Вы должны ввести свой идентификатор клиента на этапе настройки. Во-вторых, вам нужно определить области. Это влияет на то, какую конечную точку spotify api вы можете успешно использовать. Взгляните на документацию по API Spotify. Последняя важная вещь здесь - это redirectUri, где вам нужно вставить URL-адрес, по которому вы хотите, чтобы ваши пользователи перенаправлялись после успешного подключения к Spotify. В моем случае это exp: //127.0.0.1: 19000 /. Этот ДОЛЖЕН быть тем же URL-адресом, что и в ваших настройках!

useEffect(() => {
    if (response?.type === "success") {
      const { access_token } = response.params;
      setToken(access_token);
    }
  }, [response]);

В этом разделе мы проверяем, был ли процесс аутентификации успешным. Если это так, мы извлекаем токен доступа из ответа, полученного ранее из фрагмента кода, и сохраняем его.

После этого мы готовы использовать токен доступа для извлечения данных из spotify api!

useEffect(() => {
  if (token) {
    axios(
      "https://api.spotify.com/v1/me/top/tracks?time_range=short_term",
       {
      method: "GET",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
        Authorization: "Bearer " + token,
      },
    })
      .then((response) => {
        dispatch(songAction.addTopSongs(response));
      })
      .catch((error) => {
        console.log("error", error.message);
      });
    setTimeout(
      () =>
        navigation.replace("Home", {
          token: token,
         
        }),
      500
    );
    dispatch(tokenAction.addToken(token));
  }
});

На этом этапе мы вызываем конечную точку лучших треков, чтобы получить текущие популярные песни. В заголовках мы используем токен доступа, чтобы получить доступ к этой конечной точке. Кроме того, я отправляю лучшие песни и токен доступа в магазины redux. Поскольку у нас только два экрана, в этом нет необходимости, и вы также можете передавать данные через свои компоненты. Тем не менее, если приложение станет более сложным, это может стать очень полезным. На последнем этапе мы заменяем экран входа в систему на главный экран.

Остальной код действительно является довольно стандартным кодом ReactNative!

Как я уже упоминал во вступлении, не стесняйтесь проверить репозиторий github

Заключение

Во второй части этой серии мы рассмотрим отображение и воспроизведение ваших текущих лучших песен. Как всегда, спасибо, что прочитали мой рассказ!

Больше контента на plainenglish.io