Skip to content

Commit

Permalink
improve comment ,参考:https://github.com/huacnlee/autocorrect
Browse files Browse the repository at this point in the history
  • Loading branch information
houseme committed Jul 19, 2024
1 parent ba0a147 commit d8fde54
Show file tree
Hide file tree
Showing 118 changed files with 974 additions and 867 deletions.
65 changes: 65 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,68 @@ linters-settings:
lines: 66
statements: 50

errcheck:
# Report about not checking of errors in type assertions: `a := b.(MyStruct)`.
# Such cases aren't reported by default.
# Default: false
check-type-assertions: true
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`.
# Such cases aren't reported by default.
# Default: false
check-blank: true
# To disable the errcheck built-in exclude list.
# See `-excludeonly` option in https://github.com/kisielk/errcheck#excluding-functions for details.
# Default: false
disable-default-exclusions: true
# List of functions to exclude from checking, where each entry is a single function to exclude.
# See https://github.com/kisielk/errcheck#excluding-functions for details.
exclude-functions:
- io/ioutil.ReadFile
- io.Copy(*bytes.Buffer)
- io.Copy(os.Stdout)
- (*bytes.Buffer).WriteString
- (*bytes.Buffer).Write
- url.Parse
- (*strings.Builder).WriteString
- io.WriteString
- (*bytes.Buffer).WriteByte
- (*hmac.New).Write
- (*int)
- (*string)
- (hash.Hash).Write

depguard:
# Rules to apply.
#
# Variables:
# - File Variables
# you can still use and exclamation mark ! in front of a variable to say not to use it.
# Example !$test will match any file that is not a go test file.
#
# `$all` - matches all go files
# `$test` - matches all go test files
#
# - Package Variables
#
# `$gostd` - matches all of go's standard library (Pulled from `GOROOT`)
#
# Default: Only allow $gostd in all files.
rules:
# Name of a rule.
main:
# Used to determine the package matching priority.
# There are three different modes: `original`, `strict`, and `lax`.
# Default: "original"
list-mode: lax
# List of file globs that will match this list of settings to compare against.
# Default: $all
files:
- "!**/*_a _file.go"
# List of allowed packages.
allow:
- $gostd
- github.com/OpenPeeDeeP
# Packages that are not allowed where the value is a suggestion.
deny:
- pkg: "github.com/pkg/errors"
desc: Should be replaced by standard lib errors package
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
[![pkg](https://img.shields.io/badge/dev-reference-007d9c?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/silenceper/wechat/v2?tab=doc)
![version](https://img.shields.io/badge/version-v2-green)

使用Golang开发的微信SDK,简单、易用。
> 注意:当前版本为v2版本,v1版本已废弃
使用 Golang 开发的微信 SDK,简单、易用。
> 注意:当前版本为 v2 版本,v1 版本已废弃
## 文档 && 例子

[API列表](https://github.com/silenceper/wechat/tree/v2/doc/api)
[API 列表](https://github.com/silenceper/wechat/tree/v2/doc/api)

[Wechat SDK 2.0 文档](https://silenceper.com/wechat)

Expand All @@ -25,7 +25,7 @@ import "github.com/silenceper/wechat/v2"
以下是一个微信公众号处理消息接收以及回复的例子:

```go
// 使用memcache保存access_token,也可选择redis或自定义cache
// 使用 memcache 保存 access_token,也可选择 redis 或自定义 cache
wc := wechat.NewWechat()
memory := cache.NewMemory()
cfg := &offConfig.Config{
Expand All @@ -37,7 +37,7 @@ cfg := &offConfig.Config{
}
officialAccount := wc.GetOfficialAccount(cfg)

// 传入request和responseWriter
// 传入 request 和 responseWriter
server := officialAccount.GetServer(req, rw)
// 设置接收消息的处理方法
server.SetMessageHandler(func(msg *message.MixMessage) *message.Reply {
Expand All @@ -60,20 +60,20 @@ server.Send()

## 目录说明

- officialaccount: 微信公众号API
- miniprogram: 小程序API
- minigame:小游戏API
- pay:微信支付API
- openplatform:开放平台API
- officialaccount: 微信公众号 API
- miniprogram: 小程序 API
- minigame:小游戏 API
- pay:微信支付 API
- openplatform:开放平台 API
- work:企业微信
- aispeech:智能对话
- doc: api文档
- doc: api 文档

## 贡献

-[API列表](https://github.com/silenceper/wechat/tree/v2/doc/api)中查看哪些API未实现
- 提交issue,描述需要贡献的内容
- 完成更改后,提交PR
-[API 列表](https://github.com/silenceper/wechat/tree/v2/doc/api)中查看哪些 API 未实现
- 提交 issue,描述需要贡献的内容
- 完成更改后,提交 PR

## 公众号

Expand Down
6 changes: 5 additions & 1 deletion cache/memcache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,16 @@ func TestMemcache(t *testing.T) {
exists := mem.IsExist("unknown-key")
assert.Equal(t, false, exists)

name := mem.Get("username").(string)
name, ok := mem.Get("username").(string)
if !ok {
t.Error("get Error")
}
if name != "" {
if name != "silenceper" {
t.Error("get Error")
}
}

data := mem.Get("unknown-key")
assert.Nil(t, data)

Expand Down
14 changes: 8 additions & 6 deletions cache/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ func NewRedis(ctx context.Context, opts *RedisOpts) *Redis {
return &Redis{ctx: ctx, conn: conn}
}

// SetConn 设置conn
// SetConn 设置 conn
func (r *Redis) SetConn(conn redis.UniversalClient) {
r.conn = conn
}

// SetRedisCtx 设置redis ctx 参数
// SetRedisCtx 设置 redis ctx 参数
func (r *Redis) SetRedisCtx(ctx context.Context) {
r.ctx = ctx
}
Expand Down Expand Up @@ -69,15 +69,17 @@ func (r *Redis) SetContext(ctx context.Context, key string, val interface{}, tim
return r.conn.SetEX(ctx, key, val, timeout).Err()
}

// IsExist 判断key是否存在
// IsExist 判断 key 是否存在
func (r *Redis) IsExist(key string) bool {
return r.IsExistContext(r.ctx, key)
}

// IsExistContext 判断key是否存在
// IsExistContext 判断 key 是否存在
func (r *Redis) IsExistContext(ctx context.Context, key string) bool {
result, _ := r.conn.Exists(ctx, key).Result()

result, err := r.conn.Exists(ctx, key).Result()
if err != nil {
return false
}
return result > 0
}

Expand Down
5 changes: 4 additions & 1 deletion cache/redis_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ func TestRedis(t *testing.T) {
t.Error("IsExist Error")
}

name := redis.Get(key).(string)
name, ok := redis.Get(key).(string)
if !ok {
t.Error("get Error")
}
if name != val {
t.Error("get Error")
}
Expand Down
63 changes: 34 additions & 29 deletions credential/default_access_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ import (
)

const (
// accessTokenURL 获取access_token的接口
// accessTokenURL 获取 access_token 的接口
accessTokenURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
// stableAccessTokenURL 获取稳定版access_token的接口
// stableAccessTokenURL 获取稳定版 access_token 的接口
stableAccessTokenURL = "https://api.weixin.qq.com/cgi-bin/stable_token"
// workAccessTokenURL 企业微信获取access_token的接口
// workAccessTokenURL 企业微信获取 access_token 的接口
workAccessTokenURL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"
// CacheKeyOfficialAccountPrefix 微信公众号cache key前缀
// CacheKeyOfficialAccountPrefix 微信公众号 cache key 前缀
CacheKeyOfficialAccountPrefix = "gowechat_officialaccount_"
// CacheKeyMiniProgramPrefix 小程序cache key前缀
// CacheKeyMiniProgramPrefix 小程序 cache key 前缀
CacheKeyMiniProgramPrefix = "gowechat_miniprogram_"
// CacheKeyWorkPrefix 企业微信cache key前缀
// CacheKeyWorkPrefix 企业微信 cache key 前缀
CacheKeyWorkPrefix = "gowechat_work_"
)

// DefaultAccessToken 默认AccessToken 获取
// DefaultAccessToken 默认 AccessToken 获取
type DefaultAccessToken struct {
appID string
appSecret string
Expand Down Expand Up @@ -57,34 +57,36 @@ type ResAccessToken struct {
ExpiresIn int64 `json:"expires_in"`
}

// GetAccessToken 获取access_token,先从cache中获取,没有则从服务端获取
// GetAccessToken 获取 access_token,先从 cache 中获取,没有则从服务端获取
func (ak *DefaultAccessToken) GetAccessToken() (accessToken string, err error) {
return ak.GetAccessTokenContext(context.Background())
}

// GetAccessTokenContext 获取access_token,先从cache中获取,没有则从服务端获取
// GetAccessTokenContext 获取 access_token,先从 cache 中获取,没有则从服务端获取
func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
// 先从cache中取
// 先从 cache 中取
accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.appID)

if val := ak.cache.Get(accessTokenCacheKey); val != nil {
if accessToken = val.(string); accessToken != "" {
var ok bool
if accessToken, ok = val.(string); ok && accessToken != "" {
return
}
}

// 加上lock,是为了防止在并发获取token时,cache刚好失效,导致从微信服务器上获取到不同token
// 加上 lock,是为了防止在并发获取 token 时,cache 刚好失效,导致从微信服务器上获取到不同 token
ak.accessTokenLock.Lock()
defer ak.accessTokenLock.Unlock()

// 双检,防止重复从微信服务器获取
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
if accessToken = val.(string); accessToken != "" {
var ok bool
if accessToken, ok = val.(string); ok && accessToken != "" {
return
}
}

// cache失效,从微信服务器获取
// cache 失效,从微信服务器获取
var resAccessToken ResAccessToken
if resAccessToken, err = GetTokenFromServerContext(ctx, fmt.Sprintf(accessTokenURL, ak.appID, ak.appSecret)); err != nil {
return
Expand All @@ -97,8 +99,8 @@ func (ak *DefaultAccessToken) GetAccessTokenContext(ctx context.Context) (access
return
}

// StableAccessToken 获取稳定版接口调用凭据(与getAccessToken获取的调用凭证完全隔离,互不影响)
// 不强制更新access_token,可用于不同环境不同服务而不需要分布式锁以及公用缓存,避免access_token争抢
// StableAccessToken 获取稳定版接口调用凭据 (与 getAccessToken 获取的调用凭证完全隔离,互不影响)
// 不强制更新 access_token,可用于不同环境不同服务而不需要分布式锁以及公用缓存,避免 access_token 争抢
// https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getStableAccessToken.html
type StableAccessToken struct {
appID string
Expand All @@ -120,20 +122,20 @@ func NewStableAccessToken(appID, appSecret, cacheKeyPrefix string, cache cache.C
}
}

// GetAccessToken 获取access_token,先从cache中获取,没有则从服务端获取
// GetAccessToken 获取 access_token,先从 cache 中获取,没有则从服务端获取
func (ak *StableAccessToken) GetAccessToken() (accessToken string, err error) {
return ak.GetAccessTokenContext(context.Background())
}

// GetAccessTokenContext 获取access_token,先从cache中获取,没有则从服务端获取
// GetAccessTokenContext 获取 access_token,先从 cache 中获取,没有则从服务端获取
func (ak *StableAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
// 先从cache中取
// 先从 cache 中取
accessTokenCacheKey := fmt.Sprintf("%s_stable_access_token_%s", ak.cacheKeyPrefix, ak.appID)
if val := ak.cache.Get(accessTokenCacheKey); val != nil {
return val.(string), nil
}

// cache失效,从微信服务器获取
// cache 失效,从微信服务器获取
var resAccessToken ResAccessToken
resAccessToken, err = ak.GetAccessTokenDirectly(ctx, false)
if err != nil {
Expand All @@ -147,7 +149,7 @@ func (ak *StableAccessToken) GetAccessTokenContext(ctx context.Context) (accessT
return
}

// GetAccessTokenDirectly 从微信获取access_token
// GetAccessTokenDirectly 从微信获取 access_token
func (ak *StableAccessToken) GetAccessTokenDirectly(ctx context.Context, forceRefresh bool) (resAccessToken ResAccessToken, err error) {
b, err := util.PostJSONContext(ctx, stableAccessTokenURL, map[string]interface{}{
"grant_type": "client_credential",
Expand All @@ -170,7 +172,7 @@ func (ak *StableAccessToken) GetAccessTokenDirectly(ctx context.Context, forceRe
return
}

// WorkAccessToken 企业微信AccessToken 获取
// WorkAccessToken 企业微信 AccessToken 获取
type WorkAccessToken struct {
CorpID string
CorpSecret string
Expand All @@ -193,24 +195,27 @@ func NewWorkAccessToken(corpID, corpSecret, cacheKeyPrefix string, cache cache.C
}
}

// GetAccessToken 企业微信获取access_token,先从cache中获取,没有则从服务端获取
// GetAccessToken 企业微信获取 access_token,先从 cache 中获取,没有则从服务端获取
func (ak *WorkAccessToken) GetAccessToken() (accessToken string, err error) {
return ak.GetAccessTokenContext(context.Background())
}

// GetAccessTokenContext 企业微信获取access_token,先从cache中获取,没有则从服务端获取
// GetAccessTokenContext 企业微信获取 access_token,先从 cache 中获取,没有则从服务端获取
func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessToken string, err error) {
// 加上lock,是为了防止在并发获取token时,cache刚好失效,导致从微信服务器上获取到不同token
// 加上 lock,是为了防止在并发获取 token 时,cache 刚好失效,导致从微信服务器上获取到不同 token
ak.accessTokenLock.Lock()
defer ak.accessTokenLock.Unlock()
accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.CorpID)
val := ak.cache.Get(accessTokenCacheKey)
if val != nil {
accessToken = val.(string)
var ok bool
if accessToken, ok = val.(string); !ok {
accessToken = ""
}
return
}

// cache失效,从微信服务器获取
// cache 失效,从微信服务器获取
var resAccessToken ResAccessToken
resAccessToken, err = GetTokenFromServerContext(ctx, fmt.Sprintf(workAccessTokenURL, ak.CorpID, ak.CorpSecret))
if err != nil {
Expand All @@ -224,12 +229,12 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
return
}

// GetTokenFromServer 强制从微信服务器获取token
// GetTokenFromServer 强制从微信服务器获取 token
func GetTokenFromServer(url string) (resAccessToken ResAccessToken, err error) {
return GetTokenFromServerContext(context.Background(), url)
}

// GetTokenFromServerContext 强制从微信服务器获取token
// GetTokenFromServerContext 强制从微信服务器获取 token
func GetTokenFromServerContext(ctx context.Context, url string) (resAccessToken ResAccessToken, err error) {
var body []byte
body, err = util.HTTPGetContext(ctx, url)
Expand Down
Loading

0 comments on commit d8fde54

Please sign in to comment.