package weChat import ( "bytes" "context" "encoding/json" "errors" "fmt" "github.com/leeqvip/gophp" "hospital-open-api/config" "hospital-open-api/global" "io" "net/http" "time" ) // CommonError 微信返回的通用错误 json type CommonError struct { ErrCode int64 `json:"errcode"` ErrMsg string `json:"errmsg"` } type GetAccessTokenResponse struct { AccessToken string `json:"access_token"` ExpiresIn int64 `json:"expires_in"` CommonError } type WeChatConfig struct { AppId string `json:"app_id"` AppSecret string `json:"app_secret"` } // GetConfig 初始化配置 func GetConfig(userType int) *WeChatConfig { weChatConfig := &WeChatConfig{} if userType == 1 { // 患者 weChatConfig.AppId = config.C.Wechat.PatientAppId weChatConfig.AppSecret = config.C.Wechat.PatientAppSecret } else if userType == 2 { // 医生/药师 weChatConfig.AppId = config.C.Wechat.DoctorAppId weChatConfig.AppSecret = config.C.Wechat.DoctorAppSecret } return weChatConfig } // GetAccessToken 获取access_token func (c WeChatConfig) GetAccessToken() (string, error) { // 检测缓存是否存在access_token redisKey := "c:official_account.access_token." + c.AppId + "." + c.AppSecret accessToken, _ := global.Redis.Get(context.Background(), redisKey).Result() if accessToken != "" { // 存在缓存,反序列化 result, err := gophp.Unserialize([]byte(accessToken)) if err != nil { return "", err } var ok bool accessToken, ok = result.(string) if !ok { return "", errors.New("失败") } } else { // 不存在缓存,重新获取 var body []byte grantType := "client_credential" // 构建 URL url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=%s&appid=%s&secret=%s", grantType, c.AppId, c.AppSecret) body, err := GetRequest(url) if err != nil { return "", errors.New(err.Error()) } var GetAccessTokenResponse GetAccessTokenResponse err = json.Unmarshal(body, &GetAccessTokenResponse) if err != nil { return "", errors.New(err.Error()) } if GetAccessTokenResponse.ErrCode != 0 { return "", errors.New(GetAccessTokenResponse.ErrMsg) } accessToken = GetAccessTokenResponse.AccessToken expiresIn := GetAccessTokenResponse.ExpiresIn // 序列化 redisValue, _ := gophp.Serialize(accessToken) // 增加缓存 global.Redis.Set(context.Background(), redisKey, string(redisValue), time.Duration(expiresIn-1500)*time.Second) } if accessToken == "" { return "", errors.New("失败") } return accessToken, nil } // GetRequest 发送 GET 请求并返回响应内容和错误(如果有) func GetRequest(url string) ([]byte, error) { // 发送 GET 请求 resp, err := http.Get(url) if err != nil { return nil, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) // 读取响应内容 body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } return body, nil } // PostRequest 统一请求 func PostRequest(url string, requestBody []byte) ([]byte, error) { // 发起 POST 请求 resp, err := http.Post(url, "application/json", bytes.NewBuffer(requestBody)) if err != nil { return nil, err } defer func(Body io.ReadCloser) { _ = Body.Close() }(resp.Body) body, err := io.ReadAll(resp.Body) if err != nil { return nil, err } return body, nil }