更新了get_user_id和get_openid
This commit is contained in:
244
src/main.rs
244
src/main.rs
@@ -1,46 +1,219 @@
|
||||
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
|
||||
use models::User;
|
||||
use actix_web::{App, HttpResponse, HttpServer, Responder, post, web};
|
||||
use db::create_pool;
|
||||
use reqwest::Client;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::postgres::PgPool;
|
||||
|
||||
mod models;
|
||||
mod db;
|
||||
mod models;
|
||||
|
||||
#[get("/users")]
|
||||
async fn get_users(pool: web::Data<PgPool>) -> impl Responder {
|
||||
// 定义请求体结构
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct OpenIdRequest {
|
||||
openid: String,
|
||||
}
|
||||
|
||||
// 定义成功响应结构
|
||||
#[derive(Debug, Serialize)]
|
||||
struct UserIdResponse {
|
||||
user_id: i32,
|
||||
}
|
||||
|
||||
// 微信登录请求结构
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct WeChatLoginRequest {
|
||||
code: String,
|
||||
}
|
||||
|
||||
// 微信API响应结构
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct WeChatApiResponse {
|
||||
openid: Option<String>,
|
||||
errcode: Option<i32>,
|
||||
errmsg: Option<String>,
|
||||
}
|
||||
|
||||
// 我们的API响应结构
|
||||
#[derive(Debug, Serialize)]
|
||||
struct OpenIdResponse {
|
||||
openid: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct ErrorResponse {
|
||||
error: String,
|
||||
errcode: Option<i32>,
|
||||
errmsg: Option<String>,
|
||||
}
|
||||
|
||||
// 新增:根据openid获取用户ID的端点
|
||||
#[post("/getmyid")]
|
||||
async fn get_user_id(pool: web::Data<PgPool>, request: web::Json<OpenIdRequest>) -> impl Responder {
|
||||
let openid = &request.openid;
|
||||
|
||||
// 查询用户ID
|
||||
let query = r#"
|
||||
SELECT id, "name", openid, phone, "type", "desc"
|
||||
FROM users
|
||||
LIMIT 10
|
||||
SELECT id FROM users WHERE openid = $1
|
||||
"#;
|
||||
|
||||
let result = sqlx::query_as::<_, User>(query)
|
||||
.fetch_all(pool.get_ref())
|
||||
|
||||
let result: Result<Option<(i32,)>, sqlx::Error> = sqlx::query_as::<_, (i32,)>(query)
|
||||
.bind(openid)
|
||||
.fetch_optional(pool.get_ref())
|
||||
.await;
|
||||
|
||||
match result {
|
||||
Ok(users) => {
|
||||
println!("Successfully fetched {} users", users.len());
|
||||
HttpResponse::Ok().json(users)
|
||||
},
|
||||
Ok(Some(user_id)) => {
|
||||
println!("Found user ID {} for openid {}", user_id.0, openid);
|
||||
HttpResponse::Ok().json(UserIdResponse { user_id: user_id.0 })
|
||||
}
|
||||
Ok(None) => {
|
||||
println!("No user found with openid: {}", openid);
|
||||
HttpResponse::NotFound().json(ErrorResponse {
|
||||
error: format!("未找到openid为 {} 的用户", openid),
|
||||
errcode: Some(404), // 添加错误码
|
||||
errmsg: Some("用户不存在".to_string()), // 添加错误消息
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Database error: {}", e);
|
||||
HttpResponse::InternalServerError().body(format!("Database error: {}", e))
|
||||
HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: format!("数据库查询错误: {}", e),
|
||||
errcode: Some(500), // 添加错误码
|
||||
errmsg: Some(e.to_string()), // 添加错误消息
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取openid的API端点
|
||||
#[post("/getopenid")]
|
||||
async fn get_openid(
|
||||
pool: web::Data<PgPool>,
|
||||
req: web::Json<WeChatLoginRequest>,
|
||||
http_client: web::Data<Client>,
|
||||
) -> impl Responder {
|
||||
// 从环境变量获取微信小程序配置
|
||||
let appid = match std::env::var("WECHAT_APPID") {
|
||||
Ok(id) => id,
|
||||
Err(_) => {
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: "服务器配置错误:缺少微信小程序appid".to_string(),
|
||||
errcode: None,
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
let secret = match std::env::var("WECHAT_SECRET") {
|
||||
Ok(secret) => secret,
|
||||
Err(_) => {
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: "服务器配置错误:缺少微信小程序secret".to_string(),
|
||||
errcode: None,
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 构建微信API请求URL
|
||||
let url = format!(
|
||||
"https://api.weixin.qq.com/sns/jscode2session?appid={}&secret={}&js_code={}&grant_type=authorization_code",
|
||||
appid, secret, req.code
|
||||
);
|
||||
|
||||
// 调用微信API
|
||||
let wechat_response = match http_client.get(&url).send().await {
|
||||
Ok(response) => response,
|
||||
Err(e) => {
|
||||
eprintln!("请求微信API失败: {}", e);
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: "请求微信服务失败".to_string(),
|
||||
errcode: None,
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 解析微信API响应
|
||||
let wechat_data: WeChatApiResponse = match wechat_response.json().await {
|
||||
Ok(data) => data,
|
||||
Err(e) => {
|
||||
eprintln!("解析微信API响应失败: {}", e);
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: "解析微信响应失败".to_string(),
|
||||
errcode: None,
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 检查微信API响应中的错误
|
||||
if let Some(errcode) = wechat_data.errcode {
|
||||
return HttpResponse::BadRequest().json(ErrorResponse {
|
||||
error: "微信登录失败".to_string(),
|
||||
errcode: Some(errcode),
|
||||
errmsg: wechat_data.errmsg,
|
||||
});
|
||||
}
|
||||
// 获取openid
|
||||
let openid = match wechat_data.openid {
|
||||
Some(id) => id,
|
||||
None => {
|
||||
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||
error: "微信API未返回openid".to_string(),
|
||||
errcode: None,
|
||||
errmsg: None,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 检查用户是否已存在,不存在则创建
|
||||
let query = r#"
|
||||
INSERT INTO users (openid)
|
||||
VALUES ($1)
|
||||
ON CONFLICT (openid) DO NOTHING
|
||||
RETURNING id
|
||||
"#;
|
||||
|
||||
let result = sqlx::query_as::<_, (i32,)>(query)
|
||||
.bind(&openid)
|
||||
.fetch_optional(pool.get_ref())
|
||||
.await;
|
||||
match result {
|
||||
Ok(Some(user_id)) => {
|
||||
println!("用户已存在,ID: {}", user_id.0);
|
||||
}
|
||||
Ok(None) => {
|
||||
println!("新用户已创建,openid: {}", openid);
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("数据库操作失败: {}", e);
|
||||
// 即使数据库操作失败,我们仍然返回openid,因为微信登录已经成功
|
||||
}
|
||||
}
|
||||
|
||||
// 返回openid给前端
|
||||
HttpResponse::Ok().json(OpenIdResponse { openid })
|
||||
}
|
||||
|
||||
// 创建服务器配置的函数
|
||||
fn create_server_config(pool: PgPool) -> App<impl actix_web::dev::ServiceFactory<
|
||||
actix_web::dev::ServiceRequest,
|
||||
Config = (),
|
||||
Response = actix_web::dev::ServiceResponse,
|
||||
Error = actix_web::Error,
|
||||
InitError = (),
|
||||
>> {
|
||||
fn create_server_config(
|
||||
pool: PgPool,
|
||||
http_client: Client,
|
||||
) -> App<
|
||||
impl actix_web::dev::ServiceFactory<
|
||||
actix_web::dev::ServiceRequest,
|
||||
Config = (),
|
||||
Response = actix_web::dev::ServiceResponse,
|
||||
Error = actix_web::Error,
|
||||
InitError = (),
|
||||
>,
|
||||
> {
|
||||
App::new()
|
||||
.app_data(web::Data::new(pool))
|
||||
.service(get_users)
|
||||
.app_data(web::Data::new(http_client))
|
||||
.service(get_user_id)
|
||||
.service(get_openid)
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
@@ -55,21 +228,26 @@ async fn main() -> std::io::Result<()> {
|
||||
}
|
||||
};
|
||||
|
||||
println!("Attempting to start server...");
|
||||
// 初始化HTTP客户端
|
||||
let http_client = Client::new();
|
||||
|
||||
println!("Attempting to start server...");
|
||||
// 尝试多个端口
|
||||
let ports = vec![8080, 3000, 8000, 8888];
|
||||
let mut server = None;
|
||||
|
||||
|
||||
for port in ports {
|
||||
let addr = format!("0.0.0.0:{}", port);
|
||||
println!("Trying to bind to {}", addr);
|
||||
|
||||
// 为每个服务器创建克隆的连接池
|
||||
// 为每个服务器创建克隆的连接池和HTTP客户端
|
||||
let pool_clone = pool.clone();
|
||||
|
||||
match HttpServer::new(move || create_server_config(pool_clone.clone()))
|
||||
.bind(&addr) {
|
||||
let http_client_clone = http_client.clone();
|
||||
|
||||
match HttpServer::new(move || {
|
||||
create_server_config(pool_clone.clone(), http_client_clone.clone())
|
||||
})
|
||||
.bind(&addr)
|
||||
{
|
||||
Ok(s) => {
|
||||
println!("Successfully bound to {}", addr);
|
||||
server = Some(s);
|
||||
@@ -84,7 +262,7 @@ async fn main() -> std::io::Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
match server {
|
||||
Some(s) => {
|
||||
println!("Server started successfully");
|
||||
@@ -95,4 +273,4 @@ async fn main() -> std::io::Result<()> {
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user