150 lines
3.3 KiB
Go
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
|
|
}
|