Ai
1 Star 0 Fork 0

vibly/wechat-sdk

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
server.go 6.38 KB
一键复制 编辑 原始数据 按行查看 历史
夏雨天 提交于 2023-05-12 08:37 +08:00 . init
package core
import (
"bytes"
"crypto/hmac"
"crypto/md5"
"crypto/sha256"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"github.com/chanxuehong/util"
"github.com/chanxuehong/util/security"
"gitee.com/vibly/wechat-sdk/internal/debug/mch/callback"
)
type Server struct {
appId string
mchId string
apiKey string
subAppId string
subMchId string
handler Handler
errorHandler ErrorHandler
}
// NewServer 创建一个新的 Server.
// appId: 可选; 公众号的 appid, 如果设置了值则该 Server 只能处理 appid 为该值的消息(事件)
// mchId: 可选; 商户号 mch_id, 如果设置了值则该 Server 只能处理 mch_id 为该值的消息(事件)
// apiKey: 必选; 商户的签名 key
// handler: 必选; 处理微信服务器推送过来的消息(事件)的 Handler
// errorHandler: 可选; 用于处理 Server 在处理消息(事件)过程中产生的错误, 如果没有设置则默认使用 DefaultErrorHandler
func NewServer(appId, mchId, apiKey string, handler Handler, errorHandler ErrorHandler) *Server {
if apiKey == "" {
panic("empty apiKey")
}
if handler == nil {
panic("nil Handler")
}
if errorHandler == nil {
errorHandler = DefaultErrorHandler
}
return &Server{
appId: appId,
mchId: mchId,
apiKey: apiKey,
handler: handler,
errorHandler: errorHandler,
}
}
// NewSubMchServer 创建一个新的 Server.
// appId: 可选; 公众号的 appid, 如果设置了值则该 Server 只能处理 appid 为该值的消息(事件)
// mchId: 可选; 商户号 mch_id, 如果设置了值则该 Server 只能处理 mch_id 为该值的消息(事件)
// apiKey: 必选; 商户的签名 key
// subAppId: 可选; 公众号的 sub_appid, 如果设置了值则该 Server 只能处理 sub_appid 为该值的消息(事件)
// subMchId: 可选; 商户号 sub_mch_id, 如果设置了值则该 Server 只能处理 sub_mch_id 为该值的消息(事件)
// handler: 必选; 处理微信服务器推送过来的消息(事件)的 Handler
// errorHandler: 可选; 用于处理 Server 在处理消息(事件)过程中产生的错误, 如果没有设置则默认使用 DefaultErrorHandler
func NewSubMchServer(appId, mchId, apiKey string, subAppId, subMchId string, handler Handler, errorHandler ErrorHandler) *Server {
if apiKey == "" {
panic("empty apiKey")
}
if handler == nil {
panic("nil Handler")
}
if errorHandler == nil {
errorHandler = DefaultErrorHandler
}
return &Server{
appId: appId,
mchId: mchId,
apiKey: apiKey,
subAppId: subAppId,
subMchId: subMchId,
handler: handler,
errorHandler: errorHandler,
}
}
func (srv *Server) AppId() string {
return srv.appId
}
func (srv *Server) MchId() string {
return srv.mchId
}
func (srv *Server) ApiKey() string {
return srv.apiKey
}
func (srv *Server) SubAppId() string {
return srv.subAppId
}
func (srv *Server) SubMchId() string {
return srv.subMchId
}
// ServeHTTP 处理微信服务器的回调请求, query 参数可以为 nil.
func (srv *Server) ServeHTTP(w http.ResponseWriter, r *http.Request, query url.Values) {
callback.DebugPrintRequest(r)
errorHandler := srv.errorHandler
switch r.Method {
case "POST":
requestBody, err := ioutil.ReadAll(r.Body)
if err != nil {
errorHandler.ServeError(w, r, err)
return
}
callback.DebugPrintRequestMessage(requestBody)
msg, err := util.DecodeXMLToMap(bytes.NewReader(requestBody))
if err != nil {
errorHandler.ServeError(w, r, err)
return
}
returnCode := msg["return_code"]
if returnCode != "" && returnCode != ReturnCodeSuccess {
err = &Error{
ReturnCode: returnCode,
ReturnMsg: msg["return_msg"],
}
errorHandler.ServeError(w, r, err)
return
}
resultCode := msg["result_code"]
if resultCode != "" && resultCode != ResultCodeSuccess {
err = &BizError{
ResultCode: resultCode,
ErrCode: msg["err_code"],
ErrCodeDesc: msg["err_code_des"],
}
errorHandler.ServeError(w, r, err)
return
}
if srv.appId != "" {
wantAppId := srv.appId
haveAppId := msg["appid"]
if haveAppId != "" && !security.SecureCompareString(haveAppId, wantAppId) {
err = fmt.Errorf("appid mismatch, have: %s, want: %s", haveAppId, wantAppId)
errorHandler.ServeError(w, r, err)
return
}
}
if srv.mchId != "" {
wantMchId := srv.mchId
haveMchId := msg["mch_id"]
if haveMchId != "" && !security.SecureCompareString(haveMchId, wantMchId) {
err = fmt.Errorf("mch_id mismatch, have: %s, want: %s", haveMchId, wantMchId)
errorHandler.ServeError(w, r, err)
return
}
}
if srv.subAppId != "" {
wantSubAppId := srv.subAppId
haveSubAppId := msg["sub_appid"]
if haveSubAppId != "" && !security.SecureCompareString(haveSubAppId, wantSubAppId) {
err = fmt.Errorf("sub_appid mismatch, have: %s, want: %s", haveSubAppId, wantSubAppId)
errorHandler.ServeError(w, r, err)
return
}
}
if srv.subMchId != "" {
wantSubMchId := srv.subMchId
haveSubMchId := msg["sub_mch_id"]
if haveSubMchId != "" && !security.SecureCompareString(haveSubMchId, wantSubMchId) {
err = fmt.Errorf("sub_mch_id mismatch, have: %s, want: %s", haveSubMchId, wantSubMchId)
errorHandler.ServeError(w, r, err)
return
}
}
// 认证签名
if haveSignature := msg["sign"]; haveSignature != "" {
var wantSignature string
switch signType := msg["sign_type"]; signType {
case "", SignType_MD5:
wantSignature = Sign2(msg, srv.apiKey, md5.New())
case SignType_HMAC_SHA256:
wantSignature = Sign2(msg, srv.apiKey, hmac.New(sha256.New, []byte(srv.apiKey)))
default:
err = fmt.Errorf("unsupported notification sign_type: %s", signType)
errorHandler.ServeError(w, r, err)
return
}
if !security.SecureCompareString(haveSignature, wantSignature) {
err = fmt.Errorf("sign mismatch,\nhave: %s,\nwant: %s", haveSignature, wantSignature)
errorHandler.ServeError(w, r, err)
return
}
} else {
if _, ok := msg["req_info"]; !ok { // 退款结果通知没有 sign 字段
err = ErrNotFoundSign
errorHandler.ServeError(w, r, err)
return
}
}
ctx := &Context{
Server: srv,
ResponseWriter: w,
Request: r,
RequestBody: requestBody,
Msg: msg,
handlerIndex: initHandlerIndex,
}
srv.handler.ServeMsg(ctx)
default:
errorHandler.ServeError(w, r, errors.New("Unexpected HTTP Method: "+r.Method))
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/vibly/wechat-sdk.git
git@gitee.com:vibly/wechat-sdk.git
vibly
wechat-sdk
wechat-sdk
v1.0.0

搜索帮助