API › Примеры клиента

Примеры клиента

Bash · полный цикл

EMAIL="user@example.com"
PASS="secret"

# 1. Получить bearer-токен.
TOKEN=$(curl -sS -X POST https://beon.vip/api.php?act=auth_token_issue \
    -d "email=$EMAIL" -d "password=$PASS" \
  | jq -r .result.token)

# 2. Проверить авторизацию.
curl -sS https://beon.vip/api.php?act=auth_me \
  -H "Authorization: Bearer $TOKEN" | jq .

# 3. Создать пост.
curl -sS -X POST https://beon.vip/api.php?act=post_create \
  -H "Authorization: Bearer $TOKEN" \
  -d "title=Hello" -d "body=Hello world" | jq .

# 4. Послать сообщение.
curl -sS -X POST https://beon.vip/api.php?act=im_send \
  -H "Authorization: Bearer $TOKEN" \
  -d "convo_id=123" -d "text=hi" | jq .

# 5. Выйти.
curl -sS -X POST https://beon.vip/api.php?act=auth_token_revoke \
  -H "Authorization: Bearer $TOKEN"

Android · Kotlin + OkHttp + Retrofit

build.gradle.kts

implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.retrofit2:retrofit:2.11.0")
implementation("com.squareup.retrofit2:converter-moshi:2.11.0")
implementation("androidx.security:security-crypto:1.1.0-alpha06")

Хранение токена и interceptor

object TokenStore {
    @Volatile var value: String? = null
    fun save(ctx: Context, t: String) {
        EncryptedSharedPreferences.create(
            ctx, "auth",
            MasterKey.Builder(ctx).setKeyScheme(AES256_GCM).build(),
            AES256_SIV, AES256_GCM
        ).edit().putString("token", t).apply()
        value = t
    }
}

val authInterceptor = Interceptor { chain ->
    val req = chain.request().newBuilder().apply {
        TokenStore.value?.let { header("Authorization", "Bearer $it") }
    }.build()
    chain.proceed(req)
}

val client = OkHttpClient.Builder()
    .addInterceptor(authInterceptor)
    .build()

API-интерфейс

data class Resp<T>(val ok: Boolean, val result: T?, val error: String?)
data class User(val user_id: Int, val username: String, val displayname: String)
data class TokenRes(val token: String, val token_type: String, val user: User)

interface BeonApi {
    @FormUrlEncoded
    @POST("api.php?act=auth_token_issue")
    suspend fun login(
        @Field("email") email: String,
        @Field("password") password: String
    ): Resp<TokenRes>

    @GET("api.php?act=auth_me")
    suspend fun me(): Resp<User?>

    @FormUrlEncoded
    @POST("api.php?act=im_send")
    suspend fun imSend(
        @Field("convo_id") convoId: Int,
        @Field("text") text: String
    ): Resp<Any>
}

val api: BeonApi = Retrofit.Builder()
    .baseUrl("https://beon.vip/")
    .client(client)
    .addConverterFactory(MoshiConverterFactory.create())
    .build()
    .create(BeonApi::class.java)

Логин

suspend fun login(ctx: Context, email: String, pass: String) {
    val r = api.login(email, pass)
    if (!r.ok) throw IOException(r.error)
    TokenStore.save(ctx, r.result!!.token)
}

JavaScript · fetch

const BASE = 'https://beon.vip/api.php';
let token = localStorage.getItem('beon_token');

async function call(act, params = null) {
    const opts = { headers: {} };
    if (token) opts.headers['Authorization'] = 'Bearer ' + token;
    if (params) {
        opts.method = 'POST';
        opts.body = new URLSearchParams(params);
    }
    const r = await fetch(`${BASE}?act=${act}`, opts);
    return r.json();
}

// логин
const login = await call('auth_token_issue', { email, password });
token = login.result.token;
localStorage.setItem('beon_token', token);

// дальше любой call() уже с авторизацией
const me = await call('auth_me');
console.log(me.result);