package wechat import ( "crypto/sha1" "encoding/json" "fmt" "io" "io/ioutil" "rtzh_elec_temperature/conf" "rtzh_elec_temperature/logger" "rtzh_elec_temperature/tools" "os" "strconv" "sort" "strings" "time" "github.com/astaxie/beego/context" "github.com/silenceper/wechat/v2" "github.com/silenceper/wechat/v2/cache" "github.com/silenceper/wechat/v2/officialaccount" offConfig "github.com/silenceper/wechat/v2/officialaccount/config" "github.com/silenceper/wechat/v2/officialaccount/message" "github.com/silenceper/wechat/v2/officialaccount/oauth" //wechatuser "github.com/silenceper/wechat/v2/officialaccount/user" "github.com/astaxie/beego/orm" //wechatMenu "github.com/silenceper/wechat/v2/officialaccount/menu" ) type WeThird struct { Id int `orm:pk,auto` UserId int Platform string `orm:default:"wechat"` Appid string Apptype string Unionid string Openid string Openname string Sex string Headimgurl string AccessToken string RefreshToken string ExpiresIn int Createtime int Updatetime int Logintime int Expiretime int } type Wechat struct { Token string officialAccount *officialaccount.OfficialAccount Cfg *offConfig.Config } func init() { fmt.Println("=======wechat init") orm.RegisterModel(new(WeThird)) go func() { time.Sleep(3 * time.Second) dbo := orm.NewOrm() var h []orm.Params sql := "select 1 from we_third" _, err := dbo.Raw(sql).Values(&h) if err != nil { if strings.Index(err.Error(), "doesn't exist") > -1 { logger.Logger.Error("未初始化Wechat数据表,脚本:db/db_wechat_init.sql") } } }() } func (t *Wechat) Init() { cfgpath := "conf/wechat-" + conf.GlobalConfig["runmode"] + ".cnf" fileHanlder, err := os.Open(cfgpath) if err != nil { fmt.Println(tools.NowTime()+" 配置文件"+cfgpath+":", err) tools.Log(err) return } txt, readerr := ioutil.ReadAll(fileHanlder) if readerr != nil { fmt.Println(tools.NowTime() + " " + readerr.Error()) tools.Log(readerr) return } fileHanlder.Close() cfgJson := map[string]string{} err = json.Unmarshal(txt, &cfgJson) if err != nil { fmt.Println(tools.NowTime()+" 无效的配置文件"+cfgpath, err) tools.Log(err) return } wx := wechat.NewWechat() cfg := &offConfig.Config{ AppID: cfgJson["AppID"], AppSecret: cfgJson["AppSecret"], Token: cfgJson["Token"], EncodingAESKey: cfgJson["EncodingAESKey"], Cache: cache.NewMemory(), } t.Cfg = cfg t.officialAccount = wx.GetOfficialAccount(cfg) } func (t *Wechat) UpdateToken(tokeninfo oauth.ResAccessToken) { dbc := orm.NewOrm() sql := "update we_third set access_token=?,expires_in=? where appid=? and openid=?" _, err := dbc.Raw(sql, tokeninfo.AccessToken, tokeninfo.ExpiresIn, t.Cfg.AppID, tokeninfo.OpenID).Exec() if err != nil { tools.Log(err) } } func (t *Wechat) PushMsg(to string, txt string) { msg := message.NewCustomerTextMessage(to, txt) mm := t.officialAccount.GetCustomerMessageManager().Send(msg) if mm != nil { tools.Log(mm) } } func (t *Wechat) Message(ctx *context.Context) { // 传入request和responseWriter server := t.officialAccount.GetServer(ctx.Request, ctx.ResponseWriter) //设置接收消息的处理方法 server.SetMessageHandler(func(msg *message.MixMessage) *message.Reply { //fmt.Println(msg.FromUserName) //fmt.Println(msg.Event) //回复消息:演示回复用户发送的消息 /* return nil*/ //text := message.NewText(msg.Content) //return &message.Reply{MsgType: message.MsgTypeText, MsgData: text} return &message.Reply{MsgType: message.MsgTypeText, MsgData: message.NewText("感谢您的支持和信任")} }) //处理消息接收以及回复 err := server.Serve() if err != nil { fmt.Println(err) return } reqmessage := server.RequestMsg if reqmessage.Event == "subscribe" { t.Subscribe(reqmessage) } else if reqmessage.Event == "unsubscribe" { t.UnSubscribe(reqmessage) } if reqmessage.Content == "111" { tpl := message.TemplateMessage{ ToUser: string(reqmessage.FromUserName), TemplateID: "y-7BIRqRKI6Mg8lTp4U2W5hkdR9N_jNNpShpojIvx2Y", URL: "", Data: map[string]*message.TemplateDataItem{ "first": {Value: "有新的客户预约,请及时查看"}, "cardNumber": {Value: "13762", Color: "red"}, "address": {Value: "x路x号"}, "VIPName": {Value: "高级VIP"}, "VIPPhone": {Value: "1868127287"}, "expDate": {Value: "永久"}, "remark": {Value: "点击进入会员中心"}, }, } t.officialAccount.GetTemplate().Send(&tpl) } //发送回复的消息 server.Send() } func (t *Wechat) Subscribe(msg *message.MixMessage) { appid := t.Cfg.AppID userid := string(msg.FromUserName) u := t.officialAccount.GetUser() uinfo, err := u.GetUserInfo(userid) if err != nil { tools.Log(err) return } dbobj := orm.NewOrm() uobj := WeThird{Appid: appid, Openid: userid, Openname: uinfo.Nickname, Logintime: int(time.Now().Unix())} uobj.Sex = strconv.Itoa(int(uinfo.Sex)) uobj.Headimgurl = uinfo.Headimgurl uobj.Unionid = uinfo.UnionID _, err = dbobj.Insert(&uobj) if err != nil { tools.Log(err) return } //创建菜单 menuObj := t.officialAccount.GetMenu() menujson := `{ "button":[ { "type":"view", "name":"店铺", "key":"MENU_JUJUTONG_CASE", "url":"https://www.jujutong.cloud/mobile/furniture/case/index.html" },{ "type":"view", "name":"预约", "key":"MENU_JUJUTONG_MALL", "url":"https://www.jujutong.cloud/mobile/furniture/mall/index.html" }, { "type":"view", "name":"我的", "url":"", "sub_button":[ { "type":"view", "name":"沟通", "url":"https://www.jujutong.cloud/api/wechat/r/chat" } ] }] }` err = menuObj.SetMenuByJSON(menujson) if err != nil { tools.Log(err) return } } func (t *Wechat) UnSubscribe(msg *message.MixMessage) { menuObj := t.officialAccount.GetMenu() menuObj.DeleteMenu() appid := t.Cfg.AppID userid := string(msg.FromUserName) dbc := orm.NewOrm() _, err := dbc.Raw("delete from we_third where appid=? and openid=?", appid, userid).Exec() if err != nil { tools.Log(err) } } func (t *Wechat) makeSignature(timestamp, nonce string) string { //1. 将 plat_token、timestamp、nonce三个参数进行字典序排序 sl := []string{t.Token, timestamp, nonce} sort.Strings(sl) //2. 将三个参数字符串拼接成一个字符串进行sha1加密 s := sha1.New() io.WriteString(s, strings.Join(sl, "")) return fmt.Sprintf("%x", s.Sum(nil)) }