Skip to content

Commit

Permalink
Able to generate & handle verification code now
Browse files Browse the repository at this point in the history
  • Loading branch information
songquanpeng committed Nov 5, 2022
1 parent f59a659 commit a988285
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 11 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
## 功能
+ [x] Access Token 自动刷新 & 提供外部访问接口
+ [ ] 自定义菜单
+ [ ] 登录验证
+ [x] 自定义菜单
+ [x] 登录验证
+ [ ] 自定义回复

## 配置
Expand All @@ -22,7 +22,7 @@
4. 初始账户用户名为 `root`,密码为 `123456`,记得登录后立刻修改密码。
5. 前往[微信公众号配置页面 -> 设置与开发 -> 基本配置](https://mp.weixin.qq.com/)获取 AppID 和 AppSecret,并在我们的配置页面填入上述信息,另外还需要配置 IP 白名单,按照页面上的提示完成即可。
6. 前往[微信公众号配置页面 -> 设置与开发 -> 基本配置](https://mp.weixin.qq.com/)填写以下配置:
1. `URL` 填:`https://<your.domain>/api/wechat_verification`
1. `URL` 填:`https://<your.domain>/api/wechat`
2. `Token` 首先在我们的配置页面随便填写一个 Token,然后在微信公众号的配置页面填入同一个 Token 即可。
3. `EncodingAESKey` 点随机生成,然后在我们的配置页面填入该值。
4. 消息加解密方式选择明文模式。
Expand All @@ -31,5 +31,13 @@
## API
### 获取 Access Token
1. 请求方法:`GET`
2. URL:`/api/access_token`
3. 无参数,但是需要设置 HTTP 头部:`Authorization: your token`
2. URL:`/api/wechat/access_token`
3. 无参数,但是需要设置 HTTP 头部:`Authorization: <token>`

### 通过验证码查询用户 ID
1. 请求方法:`GET`
2. URL:`/api/wechat/user?code=<code>`
3. 需要设置 HTTP 头部:`Authorization: <token>`

### 注意
需要将 `<token>``<code>` 替换为实际的内容。
33 changes: 29 additions & 4 deletions common/verification.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package common

import (
"github.com/google/uuid"
"math"
"math/rand"
"strconv"
"strings"
"sync"
"time"
Expand All @@ -13,14 +16,15 @@ type verificationValue struct {
}

const (
EmailVerificationPurpose = "v"
PasswordResetPurpose = "r"
EmailVerificationPurpose = "v"
PasswordResetPurpose = "r"
WeChatVerificationPurpose = "w"
)

var verificationMutex sync.Mutex
var verificationMap map[string]verificationValue
var verificationMapMaxSize = 10
var VerificationValidMinutes = 10
var verificationMapMaxSize = 20
var VerificationValidMinutes = 3

func GenerateVerificationCode(length int) string {
code := uuid.New().String()
Expand All @@ -31,6 +35,27 @@ func GenerateVerificationCode(length int) string {
return code[:length]
}

func GenerateAllNumberVerificationCode(length int) string {
min := math.Pow10(length)
max := math.Pow10(length+1) - 1
return strconv.Itoa(rand.Intn(int(max-min)) + int(min))
}

func RegisterWeChatCodeAndID(code string, id string) {
RegisterVerificationCodeWithKey(code, id, WeChatVerificationPurpose)
}

func GetWeChatIDByCode(code string) string {
verificationMutex.Lock()
defer verificationMutex.Unlock()
value, okay := verificationMap[WeChatVerificationPurpose+code]
now := time.Now()
if !okay || int(now.Sub(value.time).Seconds()) >= VerificationValidMinutes*60 {
return ""
}
return value.code
}

func RegisterVerificationCodeWithKey(key string, code string, purpose string) {
verificationMutex.Lock()
defer verificationMutex.Unlock()
Expand Down
33 changes: 33 additions & 0 deletions common/wechat-message.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package common

import "encoding/xml"

type WeChatMessageRequest struct {
XMLName xml.Name `xml:"xml"`
ToUserName string `xml:"ToUserName"`
FromUserName string `xml:"FromUserName"`
CreateTime int64 `xml:"CreateTime"`
MsgType string `xml:"MsgType"`
Content string `xml:"Content"`
MsgId int64 `xml:"MsgId"`
MsgDataId int64 `xml:"MsgDataId"`
Idx int64 `xml:"Idx"`
}

type WeChatMessageResponse struct {
XMLName xml.Name `xml:"xml"`
ToUserName string `xml:"ToUserName"`
FromUserName string `xml:"FromUserName"`
CreateTime int64 `xml:"CreateTime"`
MsgType string `xml:"MsgType"`
Content string `xml:"Content"`
}

func ProcessWeChatMessage(req *WeChatMessageRequest, res *WeChatMessageResponse) {
switch req.Content {
case "验证码":
code := GenerateAllNumberVerificationCode(6)
RegisterWeChatCodeAndID(code, req.FromUserName)
res.Content = code
}
}
43 changes: 43 additions & 0 deletions controller/wechat.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package controller
import (
"crypto/sha1"
"encoding/hex"
"encoding/xml"
"github.com/gin-gonic/gin"
"net/http"
"sort"
"strings"
"time"
"wechat-server/common"
)

Expand All @@ -33,6 +35,47 @@ func WeChatVerification(c *gin.Context) {
}
}

func ProcessWeChatMessage(c *gin.Context) {
var req common.WeChatMessageRequest
err := xml.NewDecoder(c.Request.Body).Decode(&req)
if err != nil {
common.SysError(err.Error())
c.Abort()
return
}
res := common.WeChatMessageResponse{
ToUserName: req.FromUserName,
FromUserName: req.ToUserName,
CreateTime: time.Now().Unix(),
MsgType: "text",
Content: "",
}
common.ProcessWeChatMessage(&req, &res)
if res.Content == "" {
c.String(http.StatusOK, "")
return
}
c.XML(http.StatusOK, &res)
}

func GetUserIDByCode(c *gin.Context) {
code := c.Query("code")
if code == "" {
c.JSON(http.StatusOK, gin.H{
"message": "无效的参数",
"success": false,
})
return
}
id := common.GetWeChatIDByCode(code)
c.JSON(http.StatusOK, gin.H{
"message": "",
"success": true,
"data": id,
})
return
}

func GetAccessToken(c *gin.Context) {
accessToken, expiration := common.GetAccessTokenAndExpirationSeconds()
c.JSON(http.StatusOK, gin.H{
Expand Down
10 changes: 8 additions & 2 deletions router/api-router.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ func SetApiRouter(router *gin.Engine) {
{
apiRouter.GET("/status", controller.GetStatus)
apiRouter.GET("/notice", controller.GetNotice)
apiRouter.GET("/wechat_verification", controller.WeChatVerification)
apiRouter.GET("/wechat", controller.WeChatVerification)
apiRouter.POST("/wechat", controller.ProcessWeChatMessage)
apiRouter.GET("/verification", middleware.CriticalRateLimit(), controller.SendEmailVerification)
apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), controller.SendPasswordResetEmail)
apiRouter.GET("/user/reset", controller.SendNewPasswordEmail)
apiRouter.GET("/oauth/github", controller.GitHubOAuth)
apiRouter.GET("/access_token", middleware.AdminAuth(), middleware.TokenOnlyAuth(), controller.GetAccessToken)

userRoute := apiRouter.Group("/user")
{
Expand Down Expand Up @@ -57,5 +57,11 @@ func SetApiRouter(router *gin.Engine) {
fileRoute.POST("/", middleware.UserAuth(), middleware.UploadRateLimit(), controller.UploadFile)
fileRoute.DELETE("/:id", middleware.UserAuth(), controller.DeleteFile)
}
wechatRoute := apiRouter.Group("/wechat")
wechatRoute.Use(middleware.AdminAuth(), middleware.TokenOnlyAuth())
{
wechatRoute.GET("/access_token", controller.GetAccessToken)
wechatRoute.GET("/user", controller.GetUserIDByCode)
}
}
}

0 comments on commit a988285

Please sign in to comment.