golang 后端验证码 模拟接口 post get ,postman测试
package main
import (
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"sync"
"time"
)
// 定义结构体
type SMSRequest struct {
UID string `json:"uid"`
}
type SMSResponse struct {
Code int `json:"code"`
Message string `json:"message"`
VerifyCode string `json:"verifyCode"`
}
type EmailResponse struct {
Code int `json:"code"`
Data struct {
Email string `json:"email"`
} `json:"data"`
}
type ExportDataRequest struct {
UID string `json:"uid"`
ChannelID string `json:"channelId"`
Month int `json:"month"`
Nick string `json:"nick"`
Receiver string `json:"receiver"`
VerifyCode string `json:"verifyCode"`
}
type TableData struct {
Key int `json:"key"`
Month int `json:"month"`
HostUid int `json:"hostUid"`
Nick string `json:"nick"`
HuyaId string `json:"huyaId"`
LiveDayCnt int `json:"liveDayCnt"`
LiveDayStatus int `json:"liveDayStatus"`
HostGain int `json:"hostGain"`
}
type ExportDataResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data struct {
Status string `json:"status"`
DataList []TableData `json:"dataList"`
} `json:"data"`
}
// 全局变量用于保存验证码
var (
verificationCodes = make(map[string]string)
mutex sync.Mutex
)
func generateCode() string {
rand.Seed(time.Now().UnixNano())
return fmt.Sprintf("%06d", rand.Intn(1000000))
}
func main() {
fmt.Println("Registering route /api/getSmsCode")
http.HandleFunc("/api/getSmsCode", getSmsCodeHandler)
fmt.Println("Registering route /api/getLastEmail")
http.HandleFunc("/api/getLastEmail", getLastEmailHandler)
fmt.Println("Registering route /api/exportData")
http.HandleFunc("/api/exportData", exportDataHandler)
log.Println("Server starting on port 8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatalf("Server failed to start: %v", err)
}
}
// 处理获取短信验证码请求
func getSmsCodeHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for /api/getSmsCode")
if r.Method != http.MethodPost {
log.Println("Invalid method. Only POST is allowed.")
httpResponse(w, http.StatusMethodNotAllowed, "Method Not Allowed")
return
}
var req SMSRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
log.Printf("Error decoding SMSRequest: %v\n", err)
httpResponse(w, http.StatusBadRequest, "Invalid request")
return
}
if req.UID == "" {
log.Println("UID is missing in the SMSRequest")
httpResponse(w, http.StatusBadRequest, "UID is required")
return
}
verifyCode := generateCode()
mutex.Lock()
verificationCodes[req.UID] = verifyCode
mutex.Unlock()
log.Printf("Sending SMS to user %s with VerifyCode %s...\n", req.UID, verifyCode)
response := SMSResponse{
Code: 200,
Message: "SMS Sent Successfully",
VerifyCode: verifyCode,
}
jsonResponse(w, response)
}
// 处理获取最后一次邮箱请求
func getLastEmailHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for /api/getLastEmail")
response := EmailResponse{
Code: 200,
}
response.Data.Email = "user@example.com"
jsonResponse(w, response)
}
// 处理导出数据请求
func exportDataHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for /api/exportData")
if r.Method != http.MethodPost {
log.Println("Invalid method. Only POST is allowed.")
httpResponse(w, http.StatusMethodNotAllowed, "Method Not Allowed")
return
}
var req ExportDataRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
log.Printf("Error decoding ExportDataRequest: %v\n", err)
httpResponse(w, http.StatusBadRequest, "Invalid request")
return
}
log.Printf("Request received: %+v\n", req)
if req.UID == "" || req.ChannelID == "" || req.Month == 0 || req.Nick == "" || req.Receiver == "" || req.VerifyCode == "" {
log.Println("Missing fields in ExportDataRequest")
httpResponse(w, http.StatusBadRequest, "All fields are required")
return
}
mutex.Lock()
storedVerifyCode, exists := verificationCodes[req.UID]
mutex.Unlock()
log.Printf("Stored code: %s, Input code: %s\n", storedVerifyCode, req.VerifyCode)
if !exists || storedVerifyCode != req.VerifyCode {
log.Printf("Invalid VerifyCode for user %s\n", req.UID)
httpResponse(w, http.StatusUnauthorized, "Invalid or expired VerifyCode")
return
}
log.Printf("Exporting data for ChannelID: %s, Month: %d, Nick: %s, Receiver: %s, VerifyCode: %s\n",
req.ChannelID, req.Month, req.Nick, req.Receiver, req.VerifyCode)
// 添加返回的表格数据
tableData := []TableData{
{Key: 0, Month: 202410, HostUid: 2344, Nick: "PlayerOne0", HuyaId: "huya1234560", LiveDayCnt: 20, LiveDayStatus: 0, HostGain: 1000},
{Key: 1, Month: 202410, HostUid: 2344, Nick: "PlayerOne1", HuyaId: "huya1234561", LiveDayCnt: 21, LiveDayStatus: 1, HostGain: 1001},
{Key: 2, Month: 202410, HostUid: 2344, Nick: "PlayerOne2", HuyaId: "huya1234562", LiveDayCnt: 22, LiveDayStatus: 0, HostGain: 1002},
{Key: 3, Month: 202410, HostUid: 2344, Nick: "PlayerOne3", HuyaId: "huya1234563", LiveDayCnt: 23, LiveDayStatus: 1, HostGain: 1003},
{Key: 4, Month: 202410, HostUid: 2344, Nick: "PlayerOne4", HuyaId: "huya1234564", LiveDayCnt: 24, LiveDayStatus: 0, HostGain: 1004},
{Key: 5, Month: 202410, HostUid: 2344, Nick: "PlayerOne5", HuyaId: "huya1234565", LiveDayCnt: 25, LiveDayStatus: 1, HostGain: 1005},
{Key: 6, Month: 202410, HostUid: 2344, Nick: "PlayerOne6", HuyaId: "huya1234566", LiveDayCnt: 26, LiveDayStatus: 0, HostGain: 1006},
{Key: 7, Month: 202410, HostUid: 2344, Nick: "PlayerOne7", HuyaId: "huya1234567", LiveDayCnt: 27, LiveDayStatus: 1, HostGain: 1007},
{Key: 8, Month: 202410, HostUid: 2344, Nick: "PlayerOne8", HuyaId: "huya1234568", LiveDayCnt: 28, LiveDayStatus: 0, HostGain: 1008},
{Key: 9, Month: 202410, HostUid: 2344, Nick: "PlayerOne9", HuyaId: "huya1234569", LiveDayCnt: 29, LiveDayStatus: 1, HostGain: 1009},
}
var response ExportDataResponse
response.Code = 200
response.Message = "Export successful"
response.Data.Status = "Exported"
response.Data.DataList = tableData
jsonResponse(w, response)
}
// 发送JSON响应
func jsonResponse(w http.ResponseWriter, data interface{}) {
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(data); err != nil {
log.Printf("Error encoding response: %v\n", err)
httpResponse(w, http.StatusInternalServerError, "Internal Server Error")
}
}
// 发送HTTP错误响应
func httpResponse(w http.ResponseWriter, code int, message string) {
w.WriteHeader(code)
w.Write([]byte(message))
}
测试请求体示例
确保在 Postman 中设置 Content-Type
为 application/json
,并使用以下 JSON 请求体。
获取短信验证码请求 (POST):
- URL:
http://localhost:8080/api/getSmsCode
- 请求体:
{
"uid": "123456789"
}
获取最后一次邮箱请求 (GET):
- URL:
http://localhost:8080/api/getLastEmail
- 无需请求体。
导出数据请求 (POST):
- URL:
http://localhost:8080/api/exportData
- 请求体:
{
"uid": "123456789",
"channelId": "channel123",
"month": 8,
"nick": "SampleNick",
"receiver": "user@example.com",
"verifyCode": "从getSmsCode返回的verifyCode"
}
详细的注释代码的每一行:
package main // 定义包名称
import ( // 导入必要的包
"encoding/json" // JSON编码和解码
"fmt" // 格式化输入输出
"log" // 日志记录
"math/rand" // 生成随机数
"net/http" // HTTP协议实现
"sync" // 同步原语(如互斥锁)
"time" // 时间操作
)
// SMSRequest 定义请求短信验证码时的数据结构
type SMSRequest struct {
UID string `json:"uid"` // 用户唯一标识
}
// SMSResponse 定义发送短信后的响应数据结构
type SMSResponse struct {
Code int `json:"code"` // 响应状态码
Message string `json:"message"` // 响应消息
VerifyCode string `json:"verifyCode"` // 发送的验证码
}
// EmailResponse 定义请求最后一封邮件信息的响应数据结构
type EmailResponse struct {
Code int `json:"code"` // 响应状态码
Data struct {
Email string `json:"email"` // 邮件地址
} `json:"data"` // 数据包装对象
}
// ExportDataRequest 定义导出数据请求的数据结构
type ExportDataRequest struct {
UID string `json:"uid"` // 用户唯一标识
ChannelID string `json:"channelId"` // 频道ID
Month int `json:"month"` // 月份
Nick string `json:"nick"` // 用户昵称
Receiver string `json:"receiver"` // 接收者
VerifyCode string `json:"verifyCode"` // 验证码
}
// TableData 定义返回的表格数据结构
type TableData struct {
Key int `json:"key"` // 表格的键
Month int `json:"month"` // 月份
HostUid int `json:"hostUid"` // 主播用户ID
Nick string `json:"nick"` // 昵称
HuyaId string `json:"huyaId"` // 虎牙ID
LiveDayCnt int `json:"liveDayCnt"` // 直播天数
LiveDayStatus int `json:"liveDayStatus"` // 直播天数状态
HostGain int `json:"hostGain"` // 主播收益
}
// ExportDataResponse 定义导出数据响应的数据结构
type ExportDataResponse struct {
Code int `json:"code"` // 响应状态码
Message string `json:"message"` // 响应消息
Data struct {
Status string `json:"status"` // 导出状态
DataList []TableData `json:"dataList"` // 导出的数据列表
} `json:"data"` // 数据包装对象
}
// 全局变量,用于储存验证码
var (
verificationCodes = make(map[string]string) // 存储用户ID和对应的验证码
mutex sync.Mutex // 互斥锁,确保验证码的存取安全
)
// 生成验证码的函数
func generateCode() string {
rand.Seed(time.Now().UnixNano()) // 初始化随机数种子
return fmt.Sprintf("%06d", rand.Intn(1000000)) // 生成六位随机数作为验证码
}
// main函数,程序入口
func main() {
fmt.Println("Registering route /api/getSmsCode") // 注册获取短信验证码的路由
http.HandleFunc("/api/getSmsCode", getSmsCodeHandler) // 设置处理函数
fmt.Println("Registering route /api/getLastEmail") // 注册获取最后一封邮件的路由
http.HandleFunc("/api/getLastEmail", getLastEmailHandler) // 设置处理函数
fmt.Println("Registering route /api/exportData") // 注册导出数据的路由
http.HandleFunc("/api/exportData", exportDataHandler) // 设置处理函数
log.Println("Server starting on port 8080...") // 日志记录,服务器开始在8080端口监听
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatalf("Server failed to start: %v", err) // 日志记录,服务器启动失败
}
}
// 处理短信验证码请求的函数
func getSmsCodeHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for /api/getSmsCode") // 日志记录,接收到请求
if r.Method != http.MethodPost { // 检查请求方法是否为POST
log.Println("Invalid method. Only POST is allowed.") // 日志记录,请求方法不合法
httpResponse(w, http.StatusMethodNotAllowed, "Method Not Allowed") // 响应405状态码
return
}
var req SMSRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { // 解析请求体
log.Printf("Error decoding SMSRequest: %v", err) // 日志记录,解析错误
httpResponse(w, http.StatusBadRequest, "Invalid request") // 响应400状态码
return
}
if req.UID == "" { // 检查UID是否为空
log.Println("UID is missing in the SMSRequest") // 日志记录,UID缺失
httpResponse(w, http.StatusBadRequest, "UID is required") // 响应400状态码
return
}
verifyCode := generateCode() // 生成验证码
mutex.Lock() // 加锁
verificationCodes[req.UID] = verifyCode // 存储验证码
mutex.Unlock() // 解锁
log.Printf("Sending SMS to user %s with VerifyCode %s...", req.UID, verifyCode) // 日志记录,发送短信
response := SMSResponse{ // 构造响应对象
Code: 200,
Message: "SMS Sent Successfully", // 响应成功信息
VerifyCode: verifyCode, // 包含验证码
}
jsonResponse(w, response) // 发送JSON响应
}
// 处理获取最后一封电子邮件的函数
func getLastEmailHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for /api/getLastEmail") // 日志记录,接收到请求
response := EmailResponse{ // 构造响应对象
Code: 200,
}
response.Data.Email = "user@example.com" // 设置电子邮件地址
jsonResponse(w, response) // 发送JSON响应
}
// 处理导出数据请求的函数
func exportDataHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Received request for /api/exportData") // 日志记录,接收到请求
if r.Method != http.MethodPost { // 检查请求方法是否为POST
log.Println("Invalid method. Only POST is allowed.") // 日志记录,请求方法不合法
httpResponse(w, http.StatusMethodNotAllowed, "Method Not Allowed") // 响应405状态码
return
}
var req ExportDataRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil { // 解析请求体
log.Printf("Error decoding ExportDataRequest: %v", err) // 日志记录,解析错误
httpResponse(w, http.StatusBadRequest, "Invalid request") // 响应400状态码
return
}
log.Printf("Request received: %+v", req) // 日志记录,显示请求内容
if req.UID == "" || req.ChannelID == "" || req.Month == 0 || req.Nick == "" || req.Receiver == "" || req.VerifyCode == "" { // 检查字段完整性
log.Println("Missing fields in ExportDataRequest") // 日志记录,缺少字段
httpResponse(w, http.StatusBadRequest, "All fields are required") // 响应400状态码
return
}
mutex.Lock() // 加锁
storedVerifyCode, exists := verificationCodes[req.UID] // 获取存储的验证码
mutex.Unlock() // 解锁
log.Printf("Stored code: %s, Input code: %s", storedVerifyCode, req.VerifyCode) // 日志记录,显示验证码比对信息
if !exists || storedVerifyCode != req.VerifyCode { // 验证验证码
log.Printf("Invalid VerifyCode for user %s", req.UID) // 日志记录,验证码无效
httpResponse(w, http.StatusUnauthorized, "Invalid or expired VerifyCode") // 响应401状态码
return
}
log.Printf("Exporting data for ChannelID: %s, Month: %d, Nick: %s, Receiver: %s, VerifyCode: %s", req.ChannelID, req.Month, req.Nick, req.Receiver, req.VerifyCode) // 日志记录,导出数据详情
// 模拟的数据,实际应用中应从数据库或其他存储中获取
tableData := []TableData{ // 构造表数据
{Key: 0, Month: 202410, HostUid: 2344, Nick: "PlayerOne0", HuyaId: "huya1234560", LiveDayCnt: 20, LiveDayStatus: 0, HostGain: 1000},
{Key: 1, Month: 202410, HostUid: 2344, Nick: "PlayerOne1", HuyaId: "huya1234561", LiveDayCnt: 21, LiveDayStatus: 1, HostGain: 1001},
{Key: 2, Month: 202410, HostUid: 2344, Nick: "PlayerOne2", HuyaId: "huya1234562", LiveDayCnt: 22, LiveDayStatus: 0, HostGain: 1002},
{Key: 3, Month: 202410, HostUid: 2344, Nick: "PlayerOne3", HuyaId: "huya1234563", LiveDayCnt: 23, LiveDayStatus: 1, HostGain: 1003},
{Key: 4, Month: 202410, HostUid: 2344, Nick: "PlayerOne4", HuyaId: "huya1234564", LiveDayCnt: 24, LiveDayStatus: 0, HostGain: 1004},
{Key: 5, Month: 202410, HostUid: 2344, Nick: "PlayerOne5", HuyaId: "huya1234565", LiveDayCnt: 25, LiveDayStatus: 1, HostGain: 1005},
{Key: 6, Month: 202410, HostUid: 2344, Nick: "PlayerOne6", HuyaId: "huya1234566", LiveDayCnt: 26, LiveDayStatus: 0, HostGain: 1006},
{Key: 7, Month: 202410, HostUid: 2344, Nick: "PlayerOne7", HuyaId: "huya1234567", LiveDayCnt: 27, LiveDayStatus: 1, HostGain: 1007},
{Key: 8, Month: 202410, HostUid: 2344, Nick: "PlayerOne8", HuyaId: "huya1234568", LiveDayCnt: 28, LiveDayStatus: 0, HostGain: 1008},
{Key: 9, Month: 202410, HostUid: 2344, Nick: "PlayerOne9", HuyaId: "huya1234569", LiveDayCnt: 29, LiveDayStatus: 1, HostGain: 1009},
}
var response ExportDataResponse // 构造响应对象
response.Code = 200
response.Message = "Export successful" // 设置成功消息
response.Data.Status = "Exported"
response.Data.DataList = tableData // 设置数据列表
jsonResponse(w, response) // 发送JSON响应
}
// 发送JSON格式响应的函数
func jsonResponse(w http.ResponseWriter, data interface{}) {
w.Header().Set("Content-Type", "application/json") // 设置响应头
if err := json.NewEncoder(w).Encode(data); err != nil { // 编码并发送JSON
log.Printf("Error encoding response: %v", err) // 日志记录,编码错误
httpResponse(w, http.StatusInternalServerError, "Internal Server Error") // 响应500状态码
}
}
// 发送HTTP状态响应的函数
func httpResponse(w http.ResponseWriter, code int, message string) {
w.WriteHeader(code) // 设置状态码
w.Write([]byte(message)) // 发送响应消息
}