Пример интеграции Go (Golang)
В этой статье мы рассмотрим пример реализации авторизации через внешний API с использованием Go (Golang). Клиент отправляет номер телефона, получает код для авторизации через прокси-сервер, а затем проверяет результат авторизации с регулярными запросами. В конце, после успешной авторизации, пользователь получает токен.
Шаг 1: Настройка маршрутов в Go
Для начала нам нужно настроить маршруты, которые будут обрабатывать запросы от клиента. Мы создадим три маршрута:
- /proxy/auth/code — для запроса кода авторизации на основе номера телефона.
- /proxy/auth/result — для проверки статуса авторизации через
code_id
. - /proxy/auth/complete — для завершения авторизации и выдачи токена после успешного завершения процесса.
Настройка маршрутов производится с использованием пакета net/http
:
// main.go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
)
const apiURL = "https://api.auth4app.com"
const apiKey = "your_api_key" // Замените на ваш реальный API-ключ
func main() {
http.HandleFunc("/proxy/auth/code", getCode)
http.HandleFunc("/proxy/auth/result", getResult)
http.HandleFunc("/proxy/auth/complete", completeAuth)
fmt.Println("Server is running on port 8080")
http.ListenAndServe(":8080", nil)
}
func getCode(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
phone := r.FormValue("phone")
reqBody := fmt.Sprintf(`{"api_key": "%s", "phone": "%s"}`, apiKey, phone)
resp, err := http.Post(apiURL+"/code/get", "application/json", strings.NewReader(reqBody))
if err != nil {
http.Error(w, "Failed to request auth code", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
w.Header().Set("Content-Type", "application/json")
w.Write(body)
}
func getResult(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
codeID := r.FormValue("code_id")
reqBody := fmt.Sprintf(`{"api_key": "%s", "code_id": "%s"}`, apiKey, codeID)
resp, err := http.Post(apiURL+"/code/result", "application/json", strings.NewReader(reqBody))
if err != nil {
http.Error(w, "Failed to check auth result", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
w.Header().Set("Content-Type", "application/json")
w.Write(body)
}
func completeAuth(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
return
}
codeID := r.FormValue("code_id")
reqBody := fmt.Sprintf(`{"api_key": "%s", "code_id": "%s"}`, apiKey, codeID)
// 1. Получаем результат авторизации
resp, err := http.Post(apiURL+"/code/result", "application/json", strings.NewReader(reqBody))
if err != nil {
http.Error(w, "Failed to complete auth", http.StatusInternalServerError)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var authData map[string]interface{}
json.Unmarshal(body, &authData)
if authData["auth"] == true {
phone, ok := authData["phone"].(string)
if !ok {
http.Error(w, "Phone number not found in the response", http.StatusBadRequest)
return
}
// 2. Поиск пользователя по номеру телефона или его создание
user := findUserByPhone(phone)
if user == nil {
user = createUser(phone)
}
// 3. Здесь можно сгенерировать токен для пользователя
token := "ТУТ ВАШ ТОКЕН" // На этом этапе можно создать токен
// Возвращаем ответ с токеном и информацией о пользователе
response := map[string]interface{}{
"token": token,
"user": map[string]interface{}{
"id": user["id"],
"phone": user["phone"],
},
}
jsonResponse, _ := json.Marshal(response)
w.Header().Set("Content-Type", "application/json")
w.Write(jsonResponse)
} else {
http.Error(w, "Authorization failed or not completed", http.StatusBadRequest)
}
}
// Пример функций для поиска и создания пользователей
func findUserByPhone(phone string) map[string]interface{} {
// Здесь логика поиска пользователя в базе данных по номеру телефона
return nil // Если не найден
}
func createUser(phone string) map[string]interface{} {
// Здесь логика создания нового пользователя
return map[string]interface{}{
"id": 1,
"phone": phone,
}
}
Шаг 3: Логика клиентской стороны
На клиентской стороне необходимо реализовать логику для выполнения последовательных шагов:
- Отправка номера телефона для получения кода авторизации.
- Параллельное отправление запросов для проверки результата авторизации с интервалом в 3 секунды.
- Как только в ответе появится
auth: true
, запрос завершения авторизации с передачейcode_id
.
1. Отправка номера телефона для запроса кода
Клиент отправляет POST-запрос на /proxy/auth/code
, передавая номер телефона:
fetch('/proxy/auth/code', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ phone: '+1234567890' }) // Замените на реальный номер телефона
})
.then(response => response.json())
.then(data => {
if (data.code_id) {
// Начинаем проверку статуса авторизации каждые 3 секунды
const codeId = data.code_id;
const intervalId = setInterval(() => {
checkAuthStatus(codeId, intervalId);
}, 3000);
}
});
2. Периодическая проверка статуса авторизации
Клиент начинает проверять статус авторизации, отправляя запросы на /proxy/auth/result
:
function checkAuthStatus(codeId, intervalId) {
fetch('/proxy/auth/result', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ code_id: codeId })
})
.then(response => response.json())
.then(data => {
if (data.auth === true) {
// Останавливаем проверку
clearInterval(intervalId);
// Завершаем авторизацию
completeAuth(codeId);
}
});
}
3. Завершение авторизации и получение токена
Как только авторизация будет успешной, клиент отправляет запрос на /proxy/auth/complete
:
function completeAuth(codeId) {
fetch('/proxy/auth/complete', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ code_id: codeId })
})
.then(response => response.json())
.then(data => {
if (data.token) {
// Токен получен, можно использовать для дальнейшей работы
console.log('Authorization successful, token:', data.token);
}
});
}
Заключение
Мы рассмотрели пример интеграции Go (Golang) с внешним API для авторизации. В процессе клиент отправляет номер телефона, получает код для авторизации и затем проверяет результат с использованием code_id
. Когда авторизация завершается успешно, клиент получает токен для дальнейшей работы.
Порядок действий:
- Клиент отправляет номер телефона через прокси-метод
/proxy/auth/code
. - Клиент запрашивает результат авторизации через
/proxy/auth/result
, передаваяcode_id
. - Как только авторизация завершена (
auth: true
), клиент вызывает метод завершения авторизации/proxy/auth/complete
. - Сервер выдает клиенту токен для дальнейшей работы.