From f76831fbb36f628c12641fb5dcb1154ec91a3630 Mon Sep 17 00:00:00 2001 From: riba2534 Date: Wed, 7 Jul 2021 00:10:22 +0800 Subject: [PATCH 1/2] =?UTF-8?q?AccessToken=E6=94=B9=E4=B8=BA=E5=8D=8A?= =?UTF-8?q?=E5=B0=8F=E6=97=B6=E8=8E=B7=E5=8F=96=E4=B8=80=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go-scf/README.md | 11 +++++--- go-scf/dal/dal.go | 50 +++++++++++++++++++++++++++++++++++++ go-scf/go.sum | 11 ++++++-- go-scf/main.go | 9 ++++++- go-scf/service/wecomchan.go | 33 +++--------------------- 5 files changed, 77 insertions(+), 37 deletions(-) create mode 100644 go-scf/dal/dal.go diff --git a/go-scf/README.md b/go-scf/README.md index 546ffbd..cca0685 100644 --- a/go-scf/README.md +++ b/go-scf/README.md @@ -1,12 +1,15 @@ # 腾讯云云函数部署Server酱 -本项目是对 [Wecom酱](https://github.com/easychen/wecomchan) 进行的扩展。 +本项目是对 [Wecom酱](https://github.com/easychen/wecomchan) 进行的扩展,可以通过企业微信 OpenAPI 向微信推送消息,实现微信消息提醒。 -利用 [腾讯云云函数](https://cloud.tencent.com/product/scf) ServerLess 的能力,以极低的费用(按量付费,且有大量免费额度)来完成部署,优点: +利用 [腾讯云云函数](https://cloud.tencent.com/product/scf) ServerLess 的能力,以极低的费用(按量付费,且有大量免费额度)来完成部署 + +优点: - 便宜:说是免费也不过分 +- 简单:不需要购买vps, 也不需要备案, 腾讯云速度有保障. - 易搭建:一个可执行二进制文件加一个配置文件,直接上传至腾讯云函数控制面板即可,虽然使用 Golang 编写,但是搭建无需 Golang 环境 -- Serverless:无服务器,不用自己购买VPS +- Serverless:无服务器,函数调用完资源会释放 ## 简单介绍 @@ -88,5 +91,5 @@ config: --- -如果发现bug,或者对本文档有任何建议,欢迎联系 `riba2534@qq.com` +如果发现bug,或者对本项目有任何建议,欢迎联系 `riba2534@qq.com` 或者直接提 [Issue](https://github.com/riba2534/wecomchan/issues). diff --git a/go-scf/dal/dal.go b/go-scf/dal/dal.go new file mode 100644 index 0000000..ff86f3e --- /dev/null +++ b/go-scf/dal/dal.go @@ -0,0 +1,50 @@ +package dal + +import ( + "fmt" + "io/ioutil" + "net/http" + "time" + + jsoniter "github.com/json-iterator/go" + "github.com/riba2534/wecomchan/go-scf/consts" + "github.com/riba2534/wecomchan/go-scf/model" +) + +var AccessToken string + +func loadAccessToken() { + client := http.Client{Timeout: 10 * time.Second} + req, _ := http.NewRequest("GET", fmt.Sprintf(consts.WeComAccessTokenURL, consts.WECOM_CID, consts.WECOM_SECRET), nil) + resp, err := client.Do(req) + if err != nil { + fmt.Println("getAccessToken err=", err) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + fmt.Println("getAccessToken statusCode is not 200") + } + respBodyBytes, _ := ioutil.ReadAll(resp.Body) + assesTokenResp := &model.AssesTokenResp{} + if err := jsoniter.Unmarshal(respBodyBytes, assesTokenResp); err != nil { + fmt.Println("getAccessToken json Unmarshal failed, err=", err) + panic(err) + } + if assesTokenResp.Errcode != 0 { + fmt.Println("getAccessToken assesTokenResp.Errcode != 0, err=", assesTokenResp.Errmsg) + panic(err) + } + AccessToken = assesTokenResp.AccessToken +} + +func Init() { + loadAccessToken() + fmt.Printf("[Init] accessToken load success, time=%s, token=%s\n", time.Now().Format("2006-01-02 15:04:05"), AccessToken) + go func() { + for { + time.Sleep(30 * time.Minute) + loadAccessToken() + fmt.Printf("[Goroutine] accessToken load success, time=%s, token=%s\n", time.Now().Format("2006-01-02 15:04:05"), AccessToken) + } + }() +} diff --git a/go-scf/go.sum b/go-scf/go.sum index 1b74d1e..469a8f9 100644 --- a/go-scf/go.sum +++ b/go-scf/go.sum @@ -135,6 +135,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= @@ -164,12 +165,15 @@ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMW github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= @@ -187,7 +191,6 @@ github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxd github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -204,7 +207,9 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= @@ -218,11 +223,11 @@ github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -559,6 +564,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= @@ -569,6 +575,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/go-scf/main.go b/go-scf/main.go index 6f89939..3022449 100644 --- a/go-scf/main.go +++ b/go-scf/main.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/riba2534/wecomchan/go-scf/consts" + "github.com/riba2534/wecomchan/go-scf/dal" "github.com/riba2534/wecomchan/go-scf/service" "github.com/riba2534/wecomchan/go-scf/utils" "github.com/spf13/cast" @@ -28,12 +29,17 @@ func init() { consts.WECOM_SECRET = cast.ToString(config.Get("config.WECOM_SECRET")) consts.WECOM_AID = cast.ToString(config.Get("config.WECOM_AID")) consts.WECOM_TOUID = cast.ToString(config.Get("config.WECOM_TOUID")) + if consts.FUNC_NAME == "" || consts.SEND_KEY == "" || consts.WECOM_CID == "" || + consts.WECOM_SECRET == "" || consts.WECOM_AID == "" || consts.WECOM_TOUID == "" { + fmt.Println("config.yaml is None, please check") + panic("config.yaml param error") + } fmt.Println("config.yaml load success!") } func HTTPHandler(ctx context.Context, event events.APIGatewayRequest) (events.APIGatewayResponse, error) { path := event.Path - fmt.Println("req:", utils.MarshalToStringParam(event)) + fmt.Println("req->", utils.MarshalToStringParam(event)) var result interface{} if strings.HasPrefix(path, "/"+consts.FUNC_NAME) { result = service.WeComChanService(ctx, event) @@ -50,5 +56,6 @@ func HTTPHandler(ctx context.Context, event events.APIGatewayRequest) (events.AP } func main() { + dal.Init() cloudfunction.Start(HTTPHandler) } diff --git a/go-scf/service/wecomchan.go b/go-scf/service/wecomchan.go index 6f91fc2..7db7a37 100644 --- a/go-scf/service/wecomchan.go +++ b/go-scf/service/wecomchan.go @@ -11,12 +11,13 @@ import ( jsoniter "github.com/json-iterator/go" "github.com/riba2534/wecomchan/go-scf/consts" + "github.com/riba2534/wecomchan/go-scf/dal" "github.com/riba2534/wecomchan/go-scf/model" "github.com/riba2534/wecomchan/go-scf/utils" "github.com/tencentyun/scf-go-lib/events" ) -func WeComChanService(ctx context.Context, event events.APIGatewayRequest) interface{} { +func WeComChanService(ctx context.Context, event events.APIGatewayRequest) map[string]interface{} { sendKey := getQuery("sendkey", event.QueryString) msgType := getQuery("msg_type", event.QueryString) msg := getQuery("msg", event.QueryString) @@ -26,40 +27,12 @@ func WeComChanService(ctx context.Context, event events.APIGatewayRequest) inter if sendKey != consts.SEND_KEY { return utils.MakeResp(-1, "sendkey error") } - accessToken, err := getAccessToken() - if err != nil { - return utils.MakeResp(-1, "get accessToken error") - } - if err := postWechatMsg(accessToken, msg, msgType); err != nil { + if err := postWechatMsg(dal.AccessToken, msg, msgType); err != nil { return utils.MakeResp(0, err.Error()) } return utils.MakeResp(0, "success") } -func getAccessToken() (string, error) { - client := http.Client{Timeout: 10 * time.Second} - req, _ := http.NewRequest("GET", fmt.Sprintf(consts.WeComAccessTokenURL, consts.WECOM_CID, consts.WECOM_SECRET), nil) - resp, err := client.Do(req) - if err != nil { - fmt.Println("getAccessToken err=", err) - } - defer resp.Body.Close() - if resp.StatusCode != 200 { - fmt.Println("getAccessToken statusCode is not 200") - } - respBodyBytes, _ := ioutil.ReadAll(resp.Body) - assesTokenResp := &model.AssesTokenResp{} - if err := jsoniter.Unmarshal(respBodyBytes, assesTokenResp); err != nil { - fmt.Println("getAccessToken json Unmarshal failed, err=", err) - return "", err - } - if assesTokenResp.Errcode != 0 { - fmt.Println("getAccessToken assesTokenResp.Errcode != 0, err=", assesTokenResp.Errmsg) - return "", errors.New(assesTokenResp.Errmsg) - } - return assesTokenResp.AccessToken, nil -} - func postWechatMsg(accessToken, msg, msgType string) error { content := &model.WechatMsg{ ToUser: consts.WECOM_TOUID, From 302b1fda6a881173e961652c5ab0efa142069979 Mon Sep 17 00:00:00 2001 From: riba2534 Date: Wed, 7 Jul 2021 00:27:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?go-scf=E5=8F=91=E5=B8=831.1=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go-scf/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/go-scf/README.md b/go-scf/README.md index cca0685..94dd174 100644 --- a/go-scf/README.md +++ b/go-scf/README.md @@ -25,12 +25,12 @@ ### 2. 下载编译好的二进制文件,填写配置 -下载文件: +下载文件 [历史版本链接](https://github.com/riba2534/wecomchan/releases): -- [main](https://github.com/riba2534/wecomchan/releases/download/1.0/main) :腾讯云云函数,可执行二进制文件 +- [main](https://github.com/riba2534/wecomchan/releases/download/1.1/main) :腾讯云云函数,可执行二进制文件 - [config.yaml.example](https://github.com/riba2534/wecomchan/releases/download/1.0/config.yaml.example) : 示例的配置文件 -修改 `config.yaml.example` 中的内容,先把文件名改为 `config.yaml`,在对应位置填入相关配置,企业微信相关配置,请参考项目主页获取。 +修改 `config.yaml.example` 中的内容,**先把文件名改为 `config.yaml`**,在对应位置填入相关配置,企业微信相关配置,请参考项目主页获取。 配置中的 `FUNC_NAME` 指下一步在腾讯云创建云函数时的函数名称,推荐填 `wecomchan` @@ -79,6 +79,8 @@ config: 在你刚才获得的路径之后拼几个GET参数,在后面加上:`?sendkey=你配置的sendkey&msg_type=text&msg=hello` +> 当发送的文本中存在有换行符或其他字符时,请把 msg 参数进行 url 编码 + ![image-20210705015727720](https://image-1252109614.cos.ap-beijing.myqcloud.com/img/image-20210705015727720.png) 可以看见返回 success 字样。