Skip to content

Commit

Permalink
增加发送模版消息、jsapi签名接口,把常用的工具接口分离到不同文件
Browse files Browse the repository at this point in the history
  • Loading branch information
rosbit committed Nov 9, 2020
1 parent 1bb5fe6 commit 29768d7
Show file tree
Hide file tree
Showing 14 changed files with 445 additions and 234 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,12 @@
"sns-auth2": "/sns-auth2 -- 这是可选的路由配置,如果网页授权由其它服务接收,可以通过网页授权参数code获取用户信息",
"sns-auth2参数说明": "s=<服务名,对应services中的name>&code=<网页授权得到的code>&[scope=userinfo|base|snsapi_userinfo|snsn_api_base]",
"short-url": "/short-url -- 这是可选的路由配置,用于把长url生成短链接",
"short-url参数说明": "访问方法POST, POST body: s=<服务名,对应services中的name>&u=<url编码的长URL>"
"short-url参数说明": "访问方法POST, POST body: s=<服务名,对应services中的name>&u=<url编码的长URL>",
"tmpl-msg": "/tmpl-msg -- 这是可选的路由配置,用于发送模版消息",
"tmpl-msg参数说明": "访问方法POST, POST body是JSON",
"tmpl-msg body例子": {"s":"服务名,对应services中的name","to":"用户openid","tid":"模版id","url":"可选,跳转url","mp":{"说明":"可选的小程序参数","appid":"小程序appid","pagepath":"页面路径"}, "data":{"模版数据key":"数据","数据key2":"..."}},
"sign-jsapi": "/sign-jsapi -- 这是可选的路由配置,用于生产jsapi签名",
"sign-jsapi参数说明": "访问方法POST, POST body: s=<service-name-in-conf>&u=<url-calling-jsapi-in-urlencoding>,结果会返回noncestr, timestamp, signature等结果"
},
"dont-append-userinfo": "true|false, 各种消息事件是否不增加用户信息,缺省是false,表示追加"
}
Expand Down
77 changes: 77 additions & 0 deletions common-endpoints/create-qr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ce

import (
"github.com/rosbit/go-wx-api/auth"
"github.com/rosbit/go-wx-api/tools"
"strconv"
"fmt"
"net/http"
)

// GET ${commonEndpoints.WxQr}?s=<service-name-in-conf>&t=<type-name,temp|forever>[&sceneid=xx][&e=<expire-secs-for-type-temp>]
func CreateWxQr(w http.ResponseWriter, r *http.Request) {
service := r.FormValue("s")
if service == "" {
writeError(w, http.StatusBadRequest, "s(ervice) parameter expected")
return
}

wxParams, ok := wxParamsCache[service]
if !ok {
writeError(w, http.StatusBadRequest, fmt.Sprintf("unknown service name %s", service))
return
}

qrType := r.FormValue("t")
if qrType == "" {
writeError(w, http.StatusBadRequest, "t(type) parameter expected")
return
}
switch qrType {
case "temp", "forever":
default:
writeError(w, http.StatusBadRequest, `t(ype) value must be "temp" or "forever"`)
return
}

sceneid := r.FormValue("sceneid")
if sceneid == "" {
sceneid = "0"
}

accessToken, err := wxauth.NewAccessTokenWithParams(wxParams).Get()
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}

var ticketURL2ShowQrCode, urlIncluedInQrcode string
switch qrType {
case "temp":
expireSecs := 30
e := r.FormValue("e")
if e == "" {
expireSecs, _ := strconv.Atoi(e)
if expireSecs <= 0 {
expireSecs = 30
}
}
ticketURL2ShowQrCode, urlIncluedInQrcode, err = wxtools.CreateTempQrStrScene(accessToken, sceneid, expireSecs)
case "forever":
ticketURL2ShowQrCode, urlIncluedInQrcode, err = wxtools.CreateQrStrScene(accessToken, sceneid)
}

if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}

writeJson(w, http.StatusOK, map[string]interface{}{
"code": http.StatusOK,
"msg": "OK",
"result": map[string]string {
"ticketURL2ShowQrCode": ticketURL2ShowQrCode,
"urlIncluedInQrcode": urlIncluedInQrcode,
},
})
}
40 changes: 40 additions & 0 deletions common-endpoints/get-user-info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package ce

import (
"wx-gateway/handlers"
"fmt"
"net/http"
)

// GET ${commonEndpoints.WxUser}?s=<service-name-in-conf>&o=<openId>
func GetWxUserInfo(w http.ResponseWriter, r *http.Request) {
service := r.FormValue("s")
if service == "" {
writeError(w, http.StatusBadRequest, "s(ervice) parameter expected")
return
}

wxParams, ok := wxParamsCache[service]
if !ok {
writeError(w, http.StatusBadRequest, fmt.Sprintf("unknown service name %s", service))
return
}

openId := r.FormValue("o")
if openId == "" {
writeError(w, http.StatusBadRequest, "o(penId) parameter expected")
return
}

userInfo, err := gwhandlers.GetUserInfo(wxParams, openId)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJson(w, http.StatusOK, map[string]interface{}{
"code": http.StatusOK,
"msg": "OK",
"userInfo": userInfo,
})
}

35 changes: 35 additions & 0 deletions common-endpoints/http-common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ce

import (
"encoding/json"
"fmt"
"net/http"
)

func writeJson(w http.ResponseWriter, code int, data interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
switch data.(type) {
case []byte:
w.Write(data.([]byte))
default:
enc := json.NewEncoder(w)
enc.Encode(data)
}
}

func writeError(w http.ResponseWriter, code int, msg string) {
writeJson(w, code, map[string]interface{}{"code": code, "msg": msg})
}

func readJson(r *http.Request, res interface{}) (status int, err error) {
if r.Body == nil {
return http.StatusBadRequest, fmt.Errorf("bad request")
}
defer r.Body.Close()

if err = json.NewDecoder(r.Body).Decode(res); err != nil {
return http.StatusBadRequest, err
}
return http.StatusOK, nil
}
11 changes: 11 additions & 0 deletions common-endpoints/params-cache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ce

import (
"github.com/rosbit/go-wx-api/conf"
)

var wxParamsCache = map[string]*wxconf.WxParamsT{}

func CacheWxParams(service string, wxParams *wxconf.WxParamsT) {
wxParamsCache[service] = wxParams
}
77 changes: 77 additions & 0 deletions common-endpoints/send-tmpl-msg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ce

import (
"github.com/rosbit/go-wx-api/auth"
"github.com/rosbit/go-wx-api/tools"
"fmt"
"net/http"
)

// POST ${commonEndpoints.TmplMsg}
// {
// "s": "service-name-in-conf",
// "to": "to-user-id",
// "tid": "template-id",
// "url": "optional url to jump",
// "mp": {
// "appid": "mini program appid",
// "pagepath": "pagepath",
// },
// "data": {
// "k1": "v1",
// "k2": "v2",
// "....": "..."
// }
// }
func SendTmplMsg(w http.ResponseWriter, r *http.Request) {
var params struct {
Service string `json:"s"`
ToUserId string `json:"to"`
TmplId string `json:"tid"`
Url string `json:"url"`
MiniProg struct {
AppId string `json:"appid"`
PagePath string `json:"pagepath"`
} `json:"mp"`
Data map[string]interface{} `json:"data"`
}
if status, err := readJson(r, &params); err != nil {
writeError(w, status, err.Error())
return
}
if params.Service == "" {
writeError(w, http.StatusBadRequest, "s(ervice) parameter expected")
return
}

wxParams, ok := wxParamsCache[params.Service]
if !ok {
writeError(w, http.StatusBadRequest, fmt.Sprintf("unknown service name %s", params.Service))
return
}
if params.ToUserId == "" {
writeError(w, http.StatusBadRequest, "to(user id) parameter expected")
return
}
if params.TmplId == "" {
writeError(w, http.StatusBadRequest, "tid(template id) parameter expected")
return
}
if len(params.Data) == 0 {
writeError(w, http.StatusBadRequest, "data parameter as a map expected")
return
}

accessToken, err := wxauth.NewAccessTokenWithParams(wxParams).Get()
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
res, err := wxtools.SendTemplateMessage(accessToken, params.ToUserId, params.TmplId, params.Data, params.Url, params.MiniProg.AppId, params.MiniProg.PagePath)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJson(w, http.StatusOK, res)
}

48 changes: 48 additions & 0 deletions common-endpoints/short-url.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ce

import (
"github.com/rosbit/go-wx-api/auth"
"github.com/rosbit/go-wx-api/tools"
"fmt"
"net/http"
)

// POST ${commonEndpoints.ShortUrl}
// s=<service-name-in-conf>&u=<long-url>
func CreateShorturl(w http.ResponseWriter, r *http.Request) {
service := r.FormValue("s")
if service == "" {
writeError(w, http.StatusBadRequest, "s(ervice) parameter expected")
return
}

wxParams, ok := wxParamsCache[service]
if !ok {
writeError(w, http.StatusBadRequest, fmt.Sprintf("unknown service name %s", service))
return
}

longUrl := r.FormValue("u")
if longUrl == "" {
writeError(w, http.StatusBadRequest, "u(rl) parameter expected")
return
}

accessToken, err := wxauth.NewAccessTokenWithParams(wxParams).Get()
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}

shortUrl, err := wxtools.MakeShorturl(accessToken, longUrl)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJson(w, http.StatusOK, map[string]interface{}{
"code": http.StatusOK,
"msg": "OK",
"short-url": shortUrl,
})
}

52 changes: 52 additions & 0 deletions common-endpoints/sign-jsapi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ce

import (
"github.com/rosbit/go-wx-api/auth"
"github.com/rosbit/go-wx-api/tools"
"fmt"
"net/http"
)

// POST ${commonEndpoints.SignJSAPI}
// s=<service-name-in-conf>&u=<url-calling-jsapi-in-urlencoding>
func SignJSAPI(w http.ResponseWriter, r *http.Request) {
service := r.FormValue("s")
if service == "" {
writeError(w, http.StatusBadRequest, "s(ervice) parameter expected")
return
}

wxParams, ok := wxParamsCache[service]
if !ok {
writeError(w, http.StatusBadRequest, fmt.Sprintf("unknown service name %s", service))
return
}

url := r.FormValue("u")
if url == "" {
writeError(w, http.StatusBadRequest, "u(rl) parameter expected")
return
}

accessToken, err := wxauth.NewAccessTokenWithParams(wxParams).Get()
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}

nonce, timestamp, signature, err := wxtools.SignJSAPI(accessToken, url)
if err != nil {
writeError(w, http.StatusInternalServerError, err.Error())
return
}
writeJson(w, http.StatusOK, map[string]interface{}{
"code": http.StatusOK,
"msg": "OK",
"params": map[string]interface{}{
"nonce": nonce,
"timestamp": timestamp,
"signature": signature,
},
})
}

Loading

0 comments on commit 29768d7

Please sign in to comment.