feat(payment): 实现网页端登录码流程(无需微信登录)
- 新增 GET /payment/generate-code:网页端生成 ASD-XXXXXX 登录码 - 新增 GET /payment/login-status:网页轮询查询登录码确认状态 - web_generate_login_code 和 web_login_confirm 增加 JWT 保护 - payment_index JS 改为真实调用 generate-code 并轮询 - 添加 rand crate 依赖
This commit is contained in:
@@ -8,6 +8,7 @@ use tracing::{debug, error, info, warn};
|
||||
use crate::auth::{generate_token, generate_refresh_token, verify_refresh_token};
|
||||
use crate::db;
|
||||
use crate::error::ErrorResponse;
|
||||
use crate::models::Claims;
|
||||
use crate::models::{
|
||||
AppState, LoginResponse, RefreshTokenRequest, TokenRefreshResponse,
|
||||
WeChatApiResponse, WeChatLoginRequest,
|
||||
@@ -345,10 +346,12 @@ pub struct WebLoginCodeResponse {
|
||||
pub async fn web_generate_login_code(
|
||||
pool: web::Data<PgPool>,
|
||||
req: web::Json<WebLoginCodeRequest>,
|
||||
claims: web::ReqData<Claims>,
|
||||
http_client: web::Data<Client>,
|
||||
app_state: web::Data<AppState>,
|
||||
) -> impl Responder {
|
||||
let code = req.code.trim();
|
||||
let user_id = claims.user_id; // 从 JWT 获取当前用户
|
||||
|
||||
// 1. 用 code 换取 openid(和登录流程一样)
|
||||
let url = format!(
|
||||
@@ -401,12 +404,12 @@ pub async fn web_generate_login_code(
|
||||
// 3. 生成随机登录码
|
||||
let random_part: String = (0..6)
|
||||
.map(|_| {
|
||||
let chars = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
let idx = (Utc::now().timestamp_millis() % 36) as u8;
|
||||
let ch = if idx < 10 { b'0' + idx } else { b'A' + idx - 10 };
|
||||
ch as char
|
||||
let ch = chars[(idx % 36) as usize] as char;
|
||||
ch
|
||||
})
|
||||
.collect();
|
||||
// 避免前面几位太规律,多取几位时间戳混合
|
||||
let ts = Utc::now().timestamp();
|
||||
let short_code = format!(
|
||||
"{:X}{}",
|
||||
@@ -416,13 +419,14 @@ pub async fn web_generate_login_code(
|
||||
let display_code = format!("ASD-{}", &short_code[..7].to_uppercase());
|
||||
let code_for_db = display_code.clone();
|
||||
|
||||
// 4. 存入临时表(user_id 稍后确认时写入)
|
||||
// 4. 存入临时表(关联 user_id)
|
||||
let expires_at = Utc::now() + chrono::Duration::minutes(10);
|
||||
if let Err(e) = sqlx::query(
|
||||
"INSERT INTO web_login_codes (code, openid, expires_at) VALUES ($1, $2, $3)",
|
||||
"INSERT INTO web_login_codes (code, openid, user_id, expires_at) VALUES ($1, $2, $3, $4)",
|
||||
)
|
||||
.bind(&code_for_db)
|
||||
.bind(&openid)
|
||||
.bind(user_id)
|
||||
.bind(expires_at)
|
||||
.execute(pool.get_ref())
|
||||
.await
|
||||
@@ -432,7 +436,7 @@ pub async fn web_generate_login_code(
|
||||
.json(ErrorResponse::<()>::error("生成登录码失败"));
|
||||
}
|
||||
|
||||
info!("[WEB LOGIN CODE] openid={} code={}", openid, display_code);
|
||||
info!("[WEB LOGIN CODE] user_id={} openid={} code={}", user_id, openid, display_code);
|
||||
HttpResponse::Ok().json(WebLoginCodeResponse {
|
||||
success: true,
|
||||
display_code,
|
||||
|
||||
Reference in New Issue
Block a user