Files
nepiedg 1c48fbdeaf Integrate WeChat Official Account support and update configuration
- Added WeChat Official Account configuration options to .env.example and config.go for OAuth2 integration.
- Updated main.go to initialize WeChat OAuth handler and register routes for handling OAuth requests.
- Enhanced documentation to include references for WeChat Official Account functionality.
- Updated route registration to accommodate the new OAuth handler for improved API structure.
2025-12-31 03:55:30 +00:00

81 lines
2.4 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package handler
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"wx_service/internal/common/wechat_official/service"
"wx_service/internal/model"
)
type OAuthHandler struct {
oaService *service.WeChatOAService
}
func NewOAuthHandler(oaService *service.WeChatOAService) *OAuthHandler {
return &OAuthHandler{oaService: oaService}
}
type codeToUserRequest struct {
Code string `json:"code" binding:"required"`
WithUserInfo *bool `json:"with_userinfo"`
}
// CodeToUser 使用微信公众号网页授权 code 换取 openid,并可选拉取用户信息(需要 snsapi_userinfo 授权)。
func (h *OAuthHandler) CodeToUser(c *gin.Context) {
var req codeToUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "请求参数错误"))
return
}
withUserInfo := true
if req.WithUserInfo != nil {
withUserInfo = *req.WithUserInfo
}
token, err := h.oaService.ExchangeCode(c.Request.Context(), req.Code)
if err != nil {
switch {
case errors.Is(err, service.ErrWeChatOANotConfigured):
c.JSON(http.StatusServiceUnavailable, model.Error(http.StatusServiceUnavailable, "未配置公众号服务,请联系管理员"))
case errors.Is(err, service.ErrWeChatOACodeRequired):
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "code 不能为空"))
default:
var apiErr *service.WeChatOAError
if errors.As(err, &apiErr) {
c.JSON(http.StatusBadGateway, model.Error(http.StatusBadGateway, "微信接口异常,请稍后重试"))
return
}
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "获取 openid 失败,请稍后重试"))
}
return
}
payload := gin.H{
"openid": token.OpenID,
"unionid": token.UnionID,
"scope": token.Scope,
"expires_in": token.ExpiresIn,
}
if withUserInfo {
info, err := h.oaService.FetchUserInfo(c.Request.Context(), token.AccessToken, token.OpenID)
if err != nil {
// 可能是 scope 不够(snsapi_base),此时仍返回 openid,并给出提示。
payload["userinfo_error"] = "未获取到用户信息(可能未授权 snsapi_userinfo"
} else {
// 统一从 userinfo 里回填 unionid(如果有)
if info.UnionID != "" {
payload["unionid"] = info.UnionID
}
payload["userinfo"] = info
}
}
// 为安全起见,这里不向前端返回 access_token/refresh_token。
c.JSON(http.StatusOK, model.Success(payload))
}