实现微信小程序手机号一键登录的流程涉及到前端(uni-app)和后端(Gin框架)的配合,主要用于简化用户登录过程,通过微信提供的接口获取用户授权的手机号,然后在后端验证并完成用户登录或注册。下面是一个简化的步骤说明及前后端代码示例。
前提条件
- 微信小程序已注册并获取AppID。
- 后端服务器已配置好HTTPS,因为微信要求相关API请求必须在HTTPS环境下进行。
- uni-app项目与Gin后端服务已经搭建好。
流程概览
- 小程序端请求微信登录接口,获取code。
- 使用code换取微信登录session_key和用户的openId。
- 通过openId请求微信的“获取用户手机号”接口。
- 将手机号发送到后端进行登录逻辑处理。
- 后端验证手机号并返回登录状态或新用户注册信息。
前端(uni-app)代码示例
获取code
// pages/login/index.vue
onLoad() {
uni.login({
provider: 'weixin',
success: (loginRes) => {
console.log('微信登录成功', loginRes.code);
// 保存code用于后续换取session_key和openId
this.code = loginRes.code;
this.fetchSessionKeyAndOpenId();
},
fail: (err) => {
console.error('微信登录失败', err);
}
});
},
fetchSessionKeyAndOpenId() {
// 这里应调用后端接口,传入code,后端处理换取session_key和openId的逻辑
// 假设有一个后端接口 /api/auth/wechat/code2session
uni.request({
url: `${this.baseUrl}/api/auth/wechat/code2session`,
method: 'POST',
data: { code: this.code },
success: (res) => {
if (res.data.success) {
this.openId = res.data.openId;
this.fetchPhoneNumber();
} else {
console.error('获取session_key和openId失败');
}
},
fail: (err) => {
console.error('请求失败', err);
}
});
},
获取手机号并发送至后端
fetchPhoneNumber() {
uni.getPhoneNumber({
success: (res) => {
console.log('获取手机号成功', res);
// 发送手机号和openId到后端进行登录处理
// 假设有一个后端接口 /api/auth/phone-login
uni.request({
url: `${this.baseUrl}/api/auth/phone-login`,
method: 'POST',
data: {
encryptedData: res.encryptedData,
iv: res.iv,
openId: this.openId
},
success: (loginRes) => {
if (loginRes.data.success) {
console.log('登录成功', loginRes.data);
// 处理登录成功后的逻辑
} else {
console.error('登录失败', loginRes.data.message);
}
},
fail: (err) => {
console.error('登录请求失败', err);
}
});
},
fail: (err) => {
console.error('获取手机号失败', err);
}
});
}
后端(Gin)代码示例
首先,确保你的Gin项目中已经引入了必要的库,并且配置好了路由。
交换Code为SessionKey和OpenId
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"fmt"
"io/ioutil"
"encoding/json"
)
func code2Session(c *gin.Context) {
code := c.PostForm("code")
url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=YOUR_APPID&secret=YOUR_SECRET&js_code=%s&grant_type=authorization_code", code)
resp, err := http.Get(url)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch session key and openId"})
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
var result map[string]interface{}
json.Unmarshal(body, &result)
if result["errcode"] != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": result["errmsg"].(string)})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"openId": result["openid"],
})
}
手机号登录处理
这部分需要解密手机号,验证用户,创建或查找用户记录等逻辑。这里只提供一个简单的示例逻辑框架:
func phoneLogin(c *gin.Context) {
encryptedData := c.PostForm("encryptedData")
iv := c.PostForm("iv")
openId := c.PostForm("openId")
// 注意:此处需要使用微信提供的解密方法解密encryptedData得到手机号
// 并根据openId在数据库中查找或创建用户,具体逻辑较为复杂,需结合实际业务实现
// 假设解密并验证逻辑已完成,此处直接返回示例成功响应
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "登录成功",
"data": map[string]string{"token": "your_token_here"}, // 实际应生成有效Token
})
}
func main() {
router := gin.Default()
router.POST("/api/auth/wechat/code2session", code2Session)
router.POST("/api/auth/phone-login", phoneLogin)
router.Run(":8080")
}
注意事项
- 上述示例代码仅为简化流程,实际应用中需要处理更多细节,如错误处理、安全性校验、数据加密解密等。
- 微信提供的手机号解密方法需要在服务器端实现,具体可以参考微信官方文档和微信小程序获取用户手机号文档。
- 确保在处理用户数据时遵守相关法律法规,保护用户隐私。