150 lines
3.3 KiB
Go

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
}