经过确认,发送图文消息,到用户触达,是1秒以内,很快的。 也就是说,用户发送的消息,通过微信官方的推送,到达我们服务器经过了很久。
发送图文消息,用户接收的时间为什么有3-5秒的延迟?我们微信小程序的消息推送模块里,对用户进入客服窗口后发送消息,会推送一条介绍内容的图文消息。从技术那边的日志来看,在调用了发送图文消息接口并返回 成功后,用户在3-4秒后才会收到消息。我们对比了别人的应用小程序,这个间隔都是1秒内,为什么我们的会慢这么多。发送图文消息的接口,我们使用的是: https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESSTOKEN 发送消息参考的文档,选择的是: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/kf-mgnt/kf-message/sendCustomMessage.html 这里面的耗时,有可能体现在两点: 用户发送消息,到消息通过微信官方推送,到达我们的服务器,经过了很长时间。用户消息进来以后,发送图文消息,到用户触达很慢, 请问,这个怎么排查,有没有思路。
2023-07-27同求答案,我的请求样式和参数是: [代码]url = https:[代码][代码]//api.weixin.qq.com/cgi-bin/midas/sandbox/getbalance?access_token=24_7Da1uJzyrsN3iSWXZnHOsYYLvvUMJuGBK21823Jwet4rgP38ghyysSEKJkyjjV4cVqioeMCR6bZoJeLLxIQXYzrQa0DLnUxT5x0PUojwpAvw2zo6HcqhP35EzyMbMQM6FGP1J0fFTGiLilXhNYKiAGAWHT[代码][代码]{[代码][代码] [代码][代码]"openid"[代码][代码]: [代码][代码]"oz6H-4xORMoVNqV9tQoWd5KkBvjw"[代码][代码],[代码][代码] [代码][代码]"appid"[代码][代码]: [代码][代码]"wx9a07c5856f3999e1"[代码][代码],[代码][代码] [代码][代码]"offer_id"[代码][代码]: [代码][代码]"1450021954"[代码][代码],[代码][代码] [代码][代码]"ts"[代码][代码]: [代码][代码]1566371448[代码][代码],[代码][代码] [代码][代码]"zone_id"[代码][代码]: [代码][代码]"1"[代码][代码],[代码][代码] [代码][代码]"pf"[代码][代码]: [代码][代码]"android"[代码][代码],[代码][代码] [代码][代码]"sig"[代码][代码]: [代码][代码]"f377a5d919e61dc1ec78a98ae74268c0c38419de042c6f310e5d4f397b62ea02"[代码][代码],[代码][代码] [代码][代码]"mp_sig"[代码][代码]: [代码][代码]"114344cc3fef85fb3613fb07fc44760754140aed7683040a0218ddb5f1db7c4e"[代码][代码] [代码][代码]}[代码]返回结果 [代码]{[代码][代码] [代码][代码]"errmsg"[代码][代码]:[代码][代码]"对不起,系统繁忙"[代码][代码],[代码][代码] [代码][代码]"errcode"[代码][代码]:-[代码][代码]1[代码][代码]}[代码]
1002-213-0 对不起,系统繁忙?{"errcode":-1,"errmsg":"1002-213-0 对不起,系统繁忙"} 小程序 沙箱环境 米大师查询余额接口返回提示 ? 是什么原因呢?
2019-08-21发现问题了,原来是测试的账户,和一个公众号后台的客服对聊了,这两个结束以前,不会被转发进服务器!
微信客服功能接入自己的服务器后,服务器接受不到消息,但公众号后台有消息- 当前 Bug 的表现(可附上截图) app_id: wxbec7aebf80022eb2 - 预期表现 服务器接收用户在客服里发送的各类消息 - 复现路径 该app_id对应的服务器URL配置 POST /vx-pub/bridge-in/ 昨天调试的时候,是正常的,可以接受消息。 今天来试,就所有消息都接受不到了,已测: 服务器配置URL/vx-pub/bridge-in/ 接口完好 公众号已认证 消息推送已启用 公众号后台,可接收用户消息 服务器日志结果: 服务器仅在昨日调试时,接入成功了 GET URL/vx-pub/bridge-in/, 并且能通过POST URL/vx-pub/bridge-in/ 收到用户消息,设置好transfer_customer_service后,服务器和公众号后台都可以收到消息。正常 今日再来用时,服务端代码没变,收不到任何消息,偶尔收到几条事件,比如: ``` {"ToUserName":"gh_043fa918d149","FromUserName":"oZKx35IzemCgIIkQr2Bq7sRz0iho","CreateTime":1560909204,"MsgType":"event","Event":"kf_close_session","KfAccount":"kf2001@gh_043fa918d149","CloseType":"TIMEOUT"} [GIN] 2019/06/19 - 09:53:24 | 200 | 156.653µs | 223.166.222.112 | POST /vx-pub/bridge-in/?signature=72aa026743513ff410f4a496afab0c24cef827dc×tamp=1560909204&nonce=1022030466 ``` **但是,公众号后台的消息还是能收到的** - 提供一个最简复现 Demo ```go package main import ( "crypto/sha1" "encoding/hex" "encoding/json" "fmt" "github.com/fwhezfwhez/errorx" "github.com/gin-gonic/gin" "github.com/rs/cors" "io/ioutil" "log" "net/http" "shangraomajiang/util/dependent-services/vx-pub/config" "sort" "strings" "time" ) func main() { r := gin.Default() r.GET("/vx-pub/bridge-in/", BridgeIn) r.POST("/vx-pub/bridge-in/", service) s := &http.Server{ // dev-8301 pro-8300 Addr: config.Port, Handler: cors.AllowAll().Handler(r), ReadTimeout: 60 * time.Second, WriteTimeout: 60 * time.Second, MaxHeaderBytes: 1 << 21, } s.ListenAndServe() } func BridgeIn(c *gin.Context) { signature := c.DefaultQuery("signature", "") timestamp := c.DefaultQuery("timestamp", "") nonce := c.DefaultQuery("nonce", "") echostr := c.DefaultQuery("echostr", "") log.Println(fmt.Sprintf("receive: signature=%s, timestamp=%s, nonce=%s, echostr=%s", signature, timestamp, nonce, echostr)) log.Println(fmt.Sprintf("token=%s", config.Cfg.GetString("token"))) arr := []string{timestamp, nonce, config.Cfg.GetString("token")} sort.Strings(arr) sha1Hash := Sha1(strings.Join(arr, "")) log.Println("sha1Hash=", sha1Hash) if sha1Hash != signature { log.Println("invalid source sha1Hash != signature") } c.String(200, echostr) } func service(c *gin.Context) { type Message struct { // 公有的 ToUserName string FromUserName string CreateTime int64 MsgType string // text,image,miniprogrampage, event MsgId int64 // 文本消息,text Content string // 图片消息, image PicUrl string MediaId string // 小卡片消息,miniprogrampage Title string AppId string PagePath string ThumbUrl string ThumbMediaId string // event // do nothing } type Result struct { ToUserName string FromUserName string CreateTime int64 MsgType string } var message Message defer func() { var in = func(str string, arr []string) bool { for _, v := range arr { if v == str { return true } } return false } if in(message.MsgType, []string{"text", "image", "miniprogrampage"}) { c.JSON(200, Result{ ToUserName: message.FromUserName, FromUserName: message.ToUserName, CreateTime: time.Now().Unix(), MsgType: "transfer_customer_service", }) } else { c.String(200, "success") } }() buf, e := ioutil.ReadAll(c.Request.Body) if e != nil { log.Println(errorx.Wrap(e).Error()) return } if e := json.Unmarshal(buf, &message); e != nil { log.Println(errorx.Wrap(e).Error()) return } fmt.Println(string(buf)) } func Sha1(data string) string { sha := sha1.New() sha.Write([]byte(data)) return hex.EncodeToString(sha.Sum([]byte(nil))) } ```
2019-06-19😔,原来所有参数都要参与签名,而不是像文档里的balance一样,只有这几个参数
小游戏midasPay联调不成功mp_sig错误地址:https://developers.weixin.qq.com/minigame/dev/api-backend/midasPay.html 官方给的测试示例:https://developers.weixin.qq.com/minigame/dev/tutorial/open-ability/midas-signature.html 服务端使用的是go 测试结果: [代码]/[代码][代码]/[代码] [代码]测试sig和mp_sig的生成[代码][代码]func TestGenerateSigAndMpSig(t [代码][代码]*[代码][代码]testing.T) {[代码][代码] [代码][代码]sig, mpSig, e:[代码][代码]=[代码] [代码]GenerateSigAndMpSig(SigParam{[代码][代码] [代码][代码]Openid: [代码][代码]"odkx20ENSNa2w5y3g_qOkOvBNM1g"[代码][代码],[代码][代码] [代码][代码]Appid:[代码][代码]"wx1234567"[代码][代码],[代码][代码] [代码][代码]OfferId: [代码][代码]"12345678"[代码][代码],[代码][代码] [代码][代码]Ts:[代码][代码]1507530737[代码][代码],[代码][代码] [代码][代码]ZoneId:[代码][代码]"1"[代码][代码],[代码][代码] [代码][代码]Pf:[代码][代码]"android"[代码][代码],[代码][代码] [代码][代码]AccessToken: [代码][代码]"ACCESSTOKEN"[代码][代码],[代码][代码] [代码][代码]},[代码][代码]"zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u"[代码][代码], [代码][代码]"V7Q38/i2KXaqrQyl2Yx9Hg=="[代码][代码],[代码][代码]"/cgi-bin/midas/getbalance"[代码][代码])[代码] [代码] [代码][代码]if[代码] [代码]e![代码][代码]=[代码][代码]nil {[代码][代码] [代码][代码]t.Fail()[代码][代码] [代码][代码]fmt.Println(e.Error())[代码][代码] [代码][代码]}[代码][代码] [代码][代码]fmt.Println([代码][代码]"sig:"[代码][代码], sig)[代码][代码] [代码][代码]fmt.Println([代码][代码]"mp_sig"[代码][代码], mpSig)[代码][代码]}[代码] [代码]sig: 1ad64e8dcb2ec1dc486b7fdf01f4a15159fc623dc3422470e51cf6870734726b[代码] [代码]mp_sig ff4c5bb39dea1002a8f03be0438724e1a8bcea5ebce8f221f9b9fea3bcf3bf76[代码] 与官方的签名达成了一致,用同样的方法,成功获取了游戏币余额。 但是 midasPay 无论怎么调,都是mp_sig 错误 已经确认了很多遍,midasPay的环境全是sandbox,参数都是正确,然而mp_sig始终错误。 想问一下,bill_no 和amt 难道也参与mp_sig签名吗? 附上一段请求的示例: (请求是按照文档说明请求的,该段示例仅仅是打日志的注解,而不是body里的实际样子) [代码]{[代码][代码] [代码][代码]"param"[代码][代码]: {[代码][代码] [代码][代码]"openid"[代码][代码]: [代码][代码]"oZKx35Nm5ztxziIKxmf6jMTmeOpY"[代码][代码],[代码][代码] [代码][代码]"appid"[代码][代码]: [代码][代码]"wxbec7aebf80022eb2"[代码][代码],[代码][代码] [代码][代码]"offer_id"[代码][代码]: [代码][代码]"1450019844"[代码][代码],[代码][代码] [代码][代码]"ts"[代码][代码]: 1553764538,[代码][代码] [代码][代码]"zone_id"[代码][代码]: [代码][代码]"1"[代码][代码],[代码][代码] [代码][代码]"pf"[代码][代码]: [代码][代码]"android"[代码][代码],[代码][代码] [代码][代码]"amt"[代码][代码]: 1,[代码][代码] [代码][代码]"bill_no"[代码][代码]: [代码][代码]"20190328171538-33586765-exchange_by_shop-diamond-1"[代码][代码],[代码][代码] [代码][代码]"sig"[代码][代码]: [代码][代码]"2f6c54d1061b8bcbc0b4b9fd06ec246a011105d14cf23bbe3a18ffef1978d3f2"[代码][代码],[代码][代码] [代码][代码]"mp_sig"[代码][代码]: [代码][代码]"00ff4bc5b1ae448a987a5de554fa1257b9e57e4b98f143872f815f388a6cb687"[代码][代码] [代码][代码]},[代码][代码] [代码][代码]"url"[代码][代码]: [代码][代码]"https://api.weixin.qq.com/cgi-bin/midas/sandbox/pay?access_token=20_iGmI6zIL98BFi1Aa7MR6VsxMkfRDvwaULTMUFkFOevD_J-a1y02GJG26aLFNDz44LkOuILV2gG5oU1qqa4OF3D_kEfAuct1RFny8OAEOHdvz8T5rNnotUou9VATkIjXYYrZA5MPy-1k3WqarRNAeAIAFBO"[代码][代码]}[代码] 谢指导!!! 下面附上了sig和mp_sig的生成方法 主方法(golang 1.9) [代码]/[代码][代码]/[代码] [代码]获取sig与mp_sig[代码][代码]/[代码][代码]/[代码] [代码]使用实例:[代码][代码]/[代码][代码]*[代码][代码] [代码][代码]sig, mpSig, e:[代码][代码]=[代码] [代码]GenerateSigAndMpSig(SigParam{[代码][代码] [代码][代码]Openid: [代码][代码]"odkx20ENSNa2w5y3g_qOkOvBNM1g"[代码][代码],[代码][代码] [代码][代码]Appid:[代码][代码]"wx1234567"[代码][代码],[代码][代码] [代码][代码]OfferId: [代码][代码]"12345678"[代码][代码],[代码][代码] [代码][代码]Ts:[代码][代码]1507530737[代码][代码],[代码][代码] [代码][代码]ZoneId:[代码][代码]"1"[代码][代码],[代码][代码] [代码][代码]Pf:[代码][代码]"android"[代码][代码],[代码][代码] [代码][代码]AccessToken: [代码][代码]"ACCESSTOKEN"[代码][代码],[代码][代码] [代码][代码]},[代码][代码]"zNLgAGgqsEWJOg1nFVaO5r7fAlIQxr1u"[代码][代码], [代码][代码]"V7Q38/i2KXaqrQyl2Yx9Hg=="[代码][代码],[代码][代码]"/cgi-bin/midas/getbalance"[代码][代码])[代码][代码] [代码][代码]*[代码][代码]/[代码][代码]func GenerateSigAndMpSig(param SigParam, offerSecret string, sessionKey string, orgLoc string) (string, string, error) {[代码][代码] [代码][代码]if[代码] [代码]offerSecret [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]offerSecret [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]sessionKey [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]sessionKey [代码][代码]is[代码] [代码]empty")[代码] [代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]orgLoc [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]orgLoc [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.AccessToken [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.AccessToken [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.ZoneId [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.ZoneId [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.OfferId [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.OfferId [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.Openid [代码][代码]=[代码][代码]=[代码][代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.OpenId [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.Appid [代码][代码]=[代码][代码]=[代码] [代码]"" {[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.Appid [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.Ts [代码][代码]=[代码][代码]=[代码] [代码]0[代码] [代码]{[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.Ts [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码][代码] [代码][代码]if[代码] [代码]param.Pf [代码][代码]=[代码][代码]=[代码] [代码]""{[代码][代码] [代码][代码]return[代码] [代码]"[代码][代码]", "[代码][代码]", errorx.NewFromString("[代码][代码]param.Pf [代码][代码]is[代码] [代码]empty")[代码][代码] [代码][代码]}[代码] [代码] [代码][代码]stringA :[代码][代码]=[代码] [代码]common.ToParam(param, [代码][代码]"json"[代码][代码], []string{[代码][代码]"sig"[代码][代码], [代码][代码]"access_token"[代码][代码], [代码][代码]"mp_sig"[代码][代码]}...)[代码][代码] [代码][代码]stringSignTemp :[代码][代码]=[代码] [代码]stringA [代码][代码]+[代码] [代码]fmt.Sprintf([代码][代码]"&org_loc=%s&method=POST&secret=%s"[代码][代码], orgLoc, offerSecret)[代码] [代码] [代码][代码]param.Sig [代码][代码]=[代码] [代码]common.HmacHs256(stringSignTemp, offerSecret)[代码] [代码] [代码][代码]/[代码][代码]/[代码] [代码]获取mp_sig[代码][代码] [代码][代码]stringB :[代码][代码]=[代码] [代码]common.ToParam(param, [代码][代码]"json"[代码][代码], []string{[代码][代码]"mp_sig"[代码][代码]}...)[代码][代码] [代码][代码]stringSignTempB :[代码][代码]=[代码] [代码]stringB [代码][代码]+[代码] [代码]fmt.Sprintf([代码][代码]"&org_loc=%s&method=POST&session_key=%s"[代码][代码], orgLoc, sessionKey)[代码] [代码] [代码][代码]param.MpSig [代码][代码]=[代码] [代码]hmacHs256(stringSignTempB, sessionKey)[代码][代码] [代码][代码]return[代码] [代码]param.Sig, param.MpSig, nil[代码][代码]}[代码] [代码]/[代码][代码]/[代码] [代码]获取hmac[代码][代码]-[代码][代码]hs256 签名[代码][代码]func hmacHs256(message string, secret string) string {[代码][代码] [代码][代码]h :[代码][代码]=[代码] [代码]hmac.New(sha256.New, []byte(secret))[代码][代码] [代码][代码]io.WriteString(h, message)[代码][代码] [代码][代码]return[代码] [代码]fmt.Sprintf([代码][代码]"%x"[代码][代码], h.[代码][代码]Sum[代码][代码](nil))[代码][代码]}[代码] 为什么midasGetBalance成功了,midasPay却 mp_sig异常
2019-03-29