1033 lines
30 KiB
Go
1033 lines
30 KiB
Go
|
package controller
|
|||
|
|
|||
|
import (
|
|||
|
"encoding/json"
|
|||
|
"encoding/xml"
|
|||
|
"errors"
|
|||
|
"fmt"
|
|||
|
"github.com/gin-gonic/gin"
|
|||
|
"github.com/silenceper/wechat/v2/officialaccount/basic"
|
|||
|
"github.com/tidwall/gjson"
|
|||
|
"io/ioutil"
|
|||
|
"kefu/common"
|
|||
|
"kefu/lib"
|
|||
|
"kefu/lib/wxbizjsonmsgcrypt"
|
|||
|
"kefu/models"
|
|||
|
"kefu/tools"
|
|||
|
"kefu/types"
|
|||
|
"kefu/ws"
|
|||
|
"log"
|
|||
|
"net/http"
|
|||
|
"net/url"
|
|||
|
"os"
|
|||
|
"strings"
|
|||
|
"time"
|
|||
|
|
|||
|
wechat "github.com/silenceper/wechat/v2"
|
|||
|
offConfigMini "github.com/silenceper/wechat/v2/miniprogram/config"
|
|||
|
miniMsg "github.com/silenceper/wechat/v2/miniprogram/message"
|
|||
|
offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
|
|||
|
"github.com/silenceper/wechat/v2/officialaccount/message"
|
|||
|
workConfig "github.com/silenceper/wechat/v2/work/config"
|
|||
|
toolsWechat "kefu/tools/wechat"
|
|||
|
)
|
|||
|
|
|||
|
func GetCheckWeixinSign(c *gin.Context) {
|
|||
|
token := models.FindConfig("WeixinToken")
|
|||
|
signature := c.Query("signature")
|
|||
|
timestamp := c.Query("timestamp")
|
|||
|
nonce := c.Query("nonce")
|
|||
|
echostr := c.Query("echostr")
|
|||
|
wechat := &lib.Wechat{
|
|||
|
AppId: "",
|
|||
|
AppSecret: "",
|
|||
|
Token: token,
|
|||
|
}
|
|||
|
res, err := wechat.CheckWechatSign(signature, timestamp, nonce, echostr)
|
|||
|
if err == nil {
|
|||
|
c.Writer.Write([]byte(res))
|
|||
|
} else {
|
|||
|
log.Println("微信API验证失败")
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 处理微信消息
|
|||
|
func PostWechatServer(c *gin.Context) {
|
|||
|
kefuName := c.Param("kefuName")
|
|||
|
entId := c.Param("entId")
|
|||
|
|
|||
|
serveWechat(c.Writer, c.Request, entId, kefuName)
|
|||
|
}
|
|||
|
func serveWechat(rw http.ResponseWriter, req *http.Request, entId, kefuName string) {
|
|||
|
//这里本地内存保存access_token,也可选择redis,memcache或者自定cache
|
|||
|
wechatConfig, _ := lib.NewWechatLib(entId)
|
|||
|
if wechatConfig == nil {
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
cfg := &offConfig.Config{
|
|||
|
AppID: wechatConfig.AppId,
|
|||
|
AppSecret: wechatConfig.AppSecret,
|
|||
|
Token: wechatConfig.Token,
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
officialAccount := wc.GetOfficialAccount(cfg)
|
|||
|
|
|||
|
// 传入request和responseWriter
|
|||
|
server := officialAccount.GetServer(req, rw)
|
|||
|
//设置接收消息的处理方法
|
|||
|
server.SetMessageHandler(func(msg *message.MixMessage) *message.Reply {
|
|||
|
//TODO
|
|||
|
|
|||
|
visitorId := fmt.Sprintf("wx|%s|%s", entId, string(msg.CommonToken.FromUserName))
|
|||
|
avator := "/static/images/we-chat-wx.png"
|
|||
|
visitorName := "微信公众号用户"
|
|||
|
vistorInfo := models.FindVisitorByVistorId(visitorId)
|
|||
|
kefuInfo := models.FindUser(kefuName)
|
|||
|
isExist := true
|
|||
|
if vistorInfo.ID == 0 {
|
|||
|
isExist = false
|
|||
|
vistorInfo = *models.CreateVisitor(visitorName, avator, "", kefuName, visitorId, "微信对话框", "", "", entId, "")
|
|||
|
} else {
|
|||
|
avator = vistorInfo.Avator
|
|||
|
visitorName = vistorInfo.Name
|
|||
|
}
|
|||
|
|
|||
|
log.Println("微信公众号回调消息体:", msg)
|
|||
|
|
|||
|
if msg.MsgType == "text" {
|
|||
|
//访客上线
|
|||
|
go ws.VisitorOnline(kefuName, vistorInfo)
|
|||
|
//访客发给客服
|
|||
|
ws.VisitorSendToKefu(kefuInfo.Name, vistorInfo, msg.Content)
|
|||
|
if isExist {
|
|||
|
go models.UpdateVisitorStatus(visitorId, 3)
|
|||
|
}
|
|||
|
if !models.CheckVisitorRobotReply(vistorInfo.State) {
|
|||
|
return nil
|
|||
|
}
|
|||
|
//自动回复消息
|
|||
|
go func() {
|
|||
|
replyContent, isGPT := ws.VisitorAutoReply(vistorInfo, kefuInfo, msg.Content)
|
|||
|
//reply := models.FindArticleRow("ent_id = ? and title like ?", vistorInfo.EntId, "%"+msg.Content+"%")
|
|||
|
replyContent, _ = tools.ReplaceStringByRegex(replyContent, `<[^a>]+>|target="[^"]+"`, "")
|
|||
|
if replyContent != "" {
|
|||
|
SendWechatVisitorMessage(vistorInfo.VisitorId, replyContent, entId)
|
|||
|
if isGPT {
|
|||
|
models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, replyContent, "kefu", vistorInfo.EntId, "read")
|
|||
|
ws.KefuMessage(vistorInfo.VisitorId, replyContent, kefuInfo)
|
|||
|
}
|
|||
|
}
|
|||
|
}()
|
|||
|
//go models.ReadMessageByVisitorId(vistorInfo.VisitorId, "kefu")
|
|||
|
//go models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, reply.Content, "kefu", vistorInfo.EntId, "read")
|
|||
|
//text := message.NewText(replyContent)
|
|||
|
return nil
|
|||
|
|
|||
|
} else if msg.MsgType == "event" {
|
|||
|
msg.Content = string(msg.Event)
|
|||
|
if string(msg.Event) == "subscribe" {
|
|||
|
subResult := HandleScanSubscribe(msg, wechatConfig, visitorId)
|
|||
|
if subResult == "kefu" {
|
|||
|
url := wechatConfig.WechatHost + "/wechatKefuTransfer?ent_id=" + entId + "&kefu_name=" + kefuName
|
|||
|
text := message.NewText(fmt.Sprintf("绑定客服账户成功!<a href='%s'>前往客服助手H5</a>", url))
|
|||
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: text}
|
|||
|
}
|
|||
|
}
|
|||
|
//取关事件
|
|||
|
if string(msg.Event) == "unsubscribe" {
|
|||
|
go models.UpdateVisitorStatus(visitorId, 2)
|
|||
|
go models.DelOauth(string(msg.CommonToken.FromUserName))
|
|||
|
}
|
|||
|
if string(msg.Event) == "SCAN" {
|
|||
|
subResult := HandleScanSubscribe(msg, wechatConfig, visitorId)
|
|||
|
if subResult == "kefu" {
|
|||
|
url := wechatConfig.WechatHost + "/wechatKefuTransfer?ent_id=" + entId + "&kefu_name=" + kefuName
|
|||
|
text := message.NewText(fmt.Sprintf("绑定客服账户成功!<a href='%s'>前往客服助手H5</a>", url))
|
|||
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: text}
|
|||
|
}
|
|||
|
}
|
|||
|
//模板事件
|
|||
|
if msg.Content == "TEMPLATESENDJOBFINISH" || msg.Content == "VIEW" {
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
} else if msg.MsgType == "image" {
|
|||
|
if isExist {
|
|||
|
go models.UpdateVisitorVisitorId(visitorId, visitorId)
|
|||
|
}
|
|||
|
fildDir := fmt.Sprintf("%s%d%s/", common.Upload, time.Now().Year(), time.Now().Month().String())
|
|||
|
mediaId := msg.MediaID
|
|||
|
fileName := mediaId + ".jpg"
|
|||
|
isExist, _ := tools.IsFileExist(fildDir)
|
|||
|
if !isExist {
|
|||
|
os.Mkdir(fildDir, os.ModePerm)
|
|||
|
}
|
|||
|
filepath := fmt.Sprintf("%s%s", fildDir, fileName)
|
|||
|
tools.HttpDown(msg.PicURL, filepath)
|
|||
|
msg.Content = fmt.Sprintf("img[/%s]", filepath)
|
|||
|
//访客上线
|
|||
|
go ws.VisitorOnline(kefuName, vistorInfo)
|
|||
|
//访客发给客服
|
|||
|
ws.VisitorSendToKefu(kefuInfo.Name, vistorInfo, msg.Content)
|
|||
|
if isExist {
|
|||
|
go models.UpdateVisitorStatus(visitorId, 3)
|
|||
|
}
|
|||
|
return nil
|
|||
|
} else {
|
|||
|
text := message.NewText("仅支持图片和文本")
|
|||
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: text}
|
|||
|
}
|
|||
|
|
|||
|
//欢迎
|
|||
|
replyContent := ""
|
|||
|
welcomes := models.FindWelcomesByKeyword(kefuName, "wechat")
|
|||
|
if len(welcomes) > 0 {
|
|||
|
for _, welcome := range welcomes {
|
|||
|
welcome.Content, _ = tools.ReplaceStringByRegex(welcome.Content, `<[^a>]+>|target="[^"]+"`, "")
|
|||
|
replyContent += welcome.Content + "\r\n"
|
|||
|
}
|
|||
|
}
|
|||
|
//发送热门问题
|
|||
|
questions := models.FindTopArticles("ent_id = ? and is_top = 1 ", entId)
|
|||
|
if len(questions) > 0 {
|
|||
|
for _, item := range questions {
|
|||
|
replyContent += fmt.Sprintf("\r\n<a href='weixin://bizmsgmenu?msgmenucontent=%s&msgmenuid=%d'>%s</a>", item.Title, item.Id, item.Title)
|
|||
|
}
|
|||
|
}
|
|||
|
text := message.NewText(replyContent)
|
|||
|
return &message.Reply{MsgType: message.MsgTypeText, MsgData: text}
|
|||
|
})
|
|||
|
|
|||
|
//处理消息接收以及回复
|
|||
|
err := server.Serve()
|
|||
|
if err != nil {
|
|||
|
log.Println(err)
|
|||
|
return
|
|||
|
}
|
|||
|
if server.ResponseMsg != nil {
|
|||
|
//发送回复的消息
|
|||
|
server.Send()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//处理关注或扫码事件
|
|||
|
/*
|
|||
|
返回解释:
|
|||
|
kefu:客服扫码带场景
|
|||
|
visitor:访客扫码带场景
|
|||
|
customer:营销会员扫码
|
|||
|
empty:扫码不带场景
|
|||
|
*/
|
|||
|
func HandleScanSubscribe(msg *message.MixMessage, wechatConfig *lib.Wechat, visitorId string) string {
|
|||
|
openId := string(msg.CommonToken.FromUserName)
|
|||
|
//带场景扫码
|
|||
|
if msg.EventKey != "" {
|
|||
|
qrSenceTxt := strings.Replace(msg.EventKey, "qrscene_", "", -1)
|
|||
|
//客服扫码带场景
|
|||
|
if strings.HasPrefix(qrSenceTxt, "kf_") {
|
|||
|
qrSenceTxt := strings.Replace(qrSenceTxt, "kf_", "", -1)
|
|||
|
go models.CreateOauth(qrSenceTxt, string(msg.CommonToken.FromUserName))
|
|||
|
return "kefu"
|
|||
|
}
|
|||
|
//客服扫码登录场景
|
|||
|
if strings.HasPrefix(qrSenceTxt, "wechatLogin_") {
|
|||
|
qrSenceTxt := strings.Replace(qrSenceTxt, "wechatLogin_", "", -1)
|
|||
|
oauth := models.FindOauthsByOpenId(openId)
|
|||
|
if oauth.UserId == "" {
|
|||
|
oauth.UserId = openId
|
|||
|
models.CreateOauth(openId, openId)
|
|||
|
}
|
|||
|
user := models.FindUser(openId)
|
|||
|
if user.ID == 0 {
|
|||
|
dd, _ := time.ParseDuration("180h")
|
|||
|
dd1 := time.Now().Add(dd)
|
|||
|
kefuInfo := models.User{
|
|||
|
Name: openId,
|
|||
|
Password: tools.Md5("123456"),
|
|||
|
Nickname: "在线客服",
|
|||
|
Avator: "/static/images/4.jpg",
|
|||
|
Pid: 1,
|
|||
|
RecNum: 0,
|
|||
|
AgentNum: 0,
|
|||
|
Status: 0,
|
|||
|
OnlineStatus: 1,
|
|||
|
ExpiredAt: types.Time{dd1},
|
|||
|
}
|
|||
|
uid, _ := kefuInfo.AddUser()
|
|||
|
models.CreateUserRole(uid, 2)
|
|||
|
}
|
|||
|
wechatLogin := &models.Wechat_login{
|
|||
|
KefuName: oauth.UserId,
|
|||
|
OpenId: openId,
|
|||
|
TempKefuId: qrSenceTxt,
|
|||
|
Status: "SUCCESS",
|
|||
|
}
|
|||
|
go wechatLogin.SaveWechatLogin("temp_kefu_id = ?", qrSenceTxt)
|
|||
|
return "kefu"
|
|||
|
}
|
|||
|
//访客扫码带场景
|
|||
|
if strings.HasPrefix(qrSenceTxt, "vs_") {
|
|||
|
qrSenceTxt := strings.Replace(qrSenceTxt, "vs_", "", -1)
|
|||
|
go models.UpdateVisitorVisitorId(qrSenceTxt, visitorId)
|
|||
|
go models.UpdateMessageVisitorId(qrSenceTxt, visitorId)
|
|||
|
go ws.VisitorChangeId(qrSenceTxt, visitorId)
|
|||
|
return "visitor"
|
|||
|
}
|
|||
|
|
|||
|
//营销会员
|
|||
|
if strings.HasPrefix(qrSenceTxt, "cu_") {
|
|||
|
qrSenceTxts := strings.Split(qrSenceTxt, "_")
|
|||
|
entId := qrSenceTxts[1]
|
|||
|
kefuName := qrSenceTxts[2]
|
|||
|
companyName := qrSenceTxts[3]
|
|||
|
|
|||
|
customer := models.FindCustomerWhere("ent_id = ? and acount_openid = ?", entId, openId)
|
|||
|
|
|||
|
msgData := make(map[string]*message.TemplateDataItem)
|
|||
|
var msg *message.TemplateMessage
|
|||
|
customerName := "待授权"
|
|||
|
msgData["first"] = &message.TemplateDataItem{
|
|||
|
Value: "感谢您关注,欢迎点击注册成为会员",
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
//提示注册成为会员
|
|||
|
if customer.ID == 0 {
|
|||
|
go models.CreateCustomer(openId, entId, kefuName)
|
|||
|
msgData["remark"] = &message.TemplateDataItem{
|
|||
|
Value: "点击此处授权成为会员",
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
} else {
|
|||
|
//展示会员积分
|
|||
|
msgData["remark"] = &message.TemplateDataItem{
|
|||
|
Value: fmt.Sprintf("您的积分为:%d", customer.Score),
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
if customer.Name != "" {
|
|||
|
customerName = customer.Name
|
|||
|
}
|
|||
|
if customer.Tel != "" {
|
|||
|
msgData["first"] = &message.TemplateDataItem{
|
|||
|
Value: "感谢您关注,您的会员信息",
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
customerName = customer.Name + customer.Tel
|
|||
|
} else {
|
|||
|
msgData["remark"] = &message.TemplateDataItem{
|
|||
|
Value: "点击此处授权完善手机号",
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
msgData["keyword1"] = &message.TemplateDataItem{
|
|||
|
Value: companyName,
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
msgData["keyword2"] = &message.TemplateDataItem{
|
|||
|
Value: customerName,
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
msgData["keyword3"] = &message.TemplateDataItem{
|
|||
|
Value: time.Now().Format("2006-01-02 15:04:05"),
|
|||
|
Color: "",
|
|||
|
}
|
|||
|
msg = &message.TemplateMessage{
|
|||
|
ToUser: openId,
|
|||
|
Data: msgData,
|
|||
|
TemplateID: wechatConfig.WechatCustomerTemplateId,
|
|||
|
URL: "",
|
|||
|
MiniProgram: struct {
|
|||
|
AppID string `json:"appid"`
|
|||
|
PagePath string `json:"pagepath"`
|
|||
|
}{
|
|||
|
AppID: wechatConfig.WechatMiniAppId,
|
|||
|
PagePath: fmt.Sprintf("/pages/index/index?kefu_name=%s&ent_id=%s&acount_openid=%s", kefuName, entId, openId),
|
|||
|
},
|
|||
|
}
|
|||
|
_, err := SendWechatTemplate(wechatConfig, msg)
|
|||
|
if err != nil {
|
|||
|
log.Println("发送营销会员模板消息失败:", err.Error(), openId, wechatConfig.AppId, wechatConfig.WechatCustomerTemplateId)
|
|||
|
}
|
|||
|
return "customer"
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
//扫码不带场景
|
|||
|
go models.CreateOauth(visitorId, openId)
|
|||
|
}
|
|||
|
return "empty"
|
|||
|
}
|
|||
|
|
|||
|
func sendWeixinToKefu(kefuName, visitorName, avator, entId, visitorId, content string) {
|
|||
|
|
|||
|
msgId := models.CreateMessage(kefuName, visitorId, content, "visitor", entId, "read")
|
|||
|
msg := ws.TypeMessage{
|
|||
|
Type: "message",
|
|||
|
Data: ws.ClientMessage{
|
|||
|
MsgId: msgId,
|
|||
|
Avator: avator,
|
|||
|
Id: visitorId,
|
|||
|
VisitorId: visitorId,
|
|||
|
Name: visitorName,
|
|||
|
ToId: kefuName,
|
|||
|
Content: content,
|
|||
|
Time: time.Now().Format("2006-01-02 15:04:05"),
|
|||
|
IsKefu: "no",
|
|||
|
},
|
|||
|
}
|
|||
|
str, _ := json.Marshal(msg)
|
|||
|
ws.OneKefuMessage(kefuName, str)
|
|||
|
go SendAppGetuiPush(kefuName, "[信息]"+visitorName, content)
|
|||
|
}
|
|||
|
|
|||
|
// 查询绑定的oauth
|
|||
|
func GetWechatOauth(c *gin.Context) {
|
|||
|
visitorId := c.Query("visitor_id")
|
|||
|
visitorIdArr := strings.Split(visitorId, "|")
|
|||
|
var oauth models.Oauth
|
|||
|
if len(visitorIdArr) >= 3 && visitorIdArr[0] == "wx" {
|
|||
|
args := []interface{}{
|
|||
|
visitorIdArr[2],
|
|||
|
}
|
|||
|
oauth = models.FindOauthsQuery("oauth_id = ? ", args)
|
|||
|
} else {
|
|||
|
oauth = models.FindOauthById(visitorId)
|
|||
|
}
|
|||
|
if oauth.OauthId == "" {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "未绑定公众号",
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": oauth.OauthId,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 展示带参二维码
|
|||
|
func GetShowQrCode(c *gin.Context) {
|
|||
|
|
|||
|
entId := c.Query("entId")
|
|||
|
sceneName := c.Query("sceneName")
|
|||
|
configs := models.GetEntConfigsMap(entId, "WechatAppId",
|
|||
|
"WechatAppSecret", "WechatAppToken")
|
|||
|
AppID := configs["WechatAppId"]
|
|||
|
AppSecret := configs["WechatAppSecret"]
|
|||
|
Token := configs["WechatAppToken"]
|
|||
|
|
|||
|
if AppID == "" || AppSecret == "" || Token == "" {
|
|||
|
systemBussinesId := models.FindConfig("SystemBussinesId")
|
|||
|
if systemBussinesId == "" {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "AppID,AppSecret,Token不能为空",
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
entId = systemBussinesId
|
|||
|
configs := models.GetEntConfigsMap(entId, "WechatAppId",
|
|||
|
"WechatAppSecret", "WechatAppToken")
|
|||
|
AppID = configs["WechatAppId"]
|
|||
|
AppSecret = configs["WechatAppSecret"]
|
|||
|
Token = configs["WechatAppToken"]
|
|||
|
}
|
|||
|
|
|||
|
offical := lib.NewWechatOffical(AppID, AppSecret, Token, memory)
|
|||
|
url, err := offical.TmpQrCode(sceneName)
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": gin.H{
|
|||
|
"url": url,
|
|||
|
},
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 获取永久带参二维码
|
|||
|
func GetLimitQrcode(c *gin.Context) {
|
|||
|
|
|||
|
entId := c.Query("entId")
|
|||
|
sceneName := c.Query("sceneName")
|
|||
|
url, err := MakeQrcode(entId, sceneName, true)
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": gin.H{
|
|||
|
"url": url,
|
|||
|
},
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 获取系统永久带参二维码
|
|||
|
func PostUserMarketingQrcode(c *gin.Context) {
|
|||
|
kefuName := c.PostForm("kefu_name")
|
|||
|
kefuInfo := models.FindUser(kefuName)
|
|||
|
if kefuInfo.ID == 0 {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "账号不存在",
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
entId := models.FindConfig("SystemBussinesId")
|
|||
|
sceneName := fmt.Sprintf("%s_%d_%s_%s", "cu", kefuInfo.ID, kefuName, kefuInfo.Nickname)
|
|||
|
url, err := MakeQrcode(entId, sceneName, true)
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": gin.H{
|
|||
|
"url": url,
|
|||
|
"logo": kefuInfo.Avator,
|
|||
|
},
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 生成带参二维码
|
|||
|
func MakeQrcode(entId, sceneName string, isLimit bool) (string, error) {
|
|||
|
configs := models.GetEntConfigsMap(entId, "WechatAppId",
|
|||
|
"WechatAppSecret", "WechatAppToken")
|
|||
|
AppID := configs["WechatAppId"]
|
|||
|
AppSecret := configs["WechatAppSecret"]
|
|||
|
Token := configs["WechatAppToken"]
|
|||
|
|
|||
|
if AppID == "" || AppSecret == "" || Token == "" {
|
|||
|
return "", errors.New("AppID,AppSecret,Token不能为空")
|
|||
|
}
|
|||
|
cfg := &offConfig.Config{
|
|||
|
AppID: AppID,
|
|||
|
AppSecret: AppSecret,
|
|||
|
Token: Token,
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
officialAccount := wc.GetOfficialAccount(cfg)
|
|||
|
basicObj := officialAccount.GetBasic()
|
|||
|
var tq *basic.Request
|
|||
|
if isLimit {
|
|||
|
tq = basic.NewLimitQrRequest(sceneName)
|
|||
|
} else {
|
|||
|
tq = basic.NewTmpQrRequest(time.Duration(24*3600), sceneName)
|
|||
|
}
|
|||
|
ticket, err := basicObj.GetQRTicket(tq)
|
|||
|
if err != nil {
|
|||
|
return "", err
|
|||
|
}
|
|||
|
url := basic.ShowQRCode(ticket)
|
|||
|
return url, nil
|
|||
|
}
|
|||
|
|
|||
|
// 带参二维码直接输出图片
|
|||
|
func GetVisitorQrCode(c *gin.Context) {
|
|||
|
|
|||
|
entId := c.Query("ent_id")
|
|||
|
if models.FindConfig("SystemBussinesId") != "" {
|
|||
|
entId = models.FindConfig("SystemBussinesId")
|
|||
|
}
|
|||
|
sceneName := c.Query("visitor_id")
|
|||
|
configs := models.GetEntConfigsMap(entId, "WechatAppId",
|
|||
|
"WechatAppSecret", "WechatAppToken")
|
|||
|
AppID := configs["WechatAppId"]
|
|||
|
AppSecret := configs["WechatAppSecret"]
|
|||
|
Token := configs["WechatAppToken"]
|
|||
|
|
|||
|
if AppID == "" || AppSecret == "" || Token == "" {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "AppID,AppSecret,Token不能为空",
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
cfg := &offConfig.Config{
|
|||
|
AppID: AppID,
|
|||
|
AppSecret: AppSecret,
|
|||
|
Token: Token,
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
officialAccount := wc.GetOfficialAccount(cfg)
|
|||
|
basicObj := officialAccount.GetBasic()
|
|||
|
tq := basic.NewTmpQrRequest(time.Duration(24*3600), "vs_"+sceneName)
|
|||
|
ticket, err := basicObj.GetQRTicket(tq)
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
url := basic.ShowQRCode(ticket)
|
|||
|
content, _ := tools.HTTPGet(url)
|
|||
|
c.Writer.Header().Set("Content-Type", "image/png")
|
|||
|
c.Writer.Write(content)
|
|||
|
}
|
|||
|
|
|||
|
// 获取小程序用户信息
|
|||
|
func GetMiniUserTel(c *gin.Context) {
|
|||
|
code := c.Query("code")
|
|||
|
entId := c.Query("entId")
|
|||
|
systemId := models.FindConfig("SystemBussinesId")
|
|||
|
if systemId == "" {
|
|||
|
systemId = entId
|
|||
|
}
|
|||
|
configs := models.FindEntConfigs(systemId)
|
|||
|
AppID := ""
|
|||
|
AppSecret := ""
|
|||
|
for _, config := range configs {
|
|||
|
if config.ConfKey == "WechatMiniAppId" {
|
|||
|
AppID = config.ConfValue
|
|||
|
}
|
|||
|
if config.ConfKey == "WechatMiniAppSecret" {
|
|||
|
AppSecret = config.ConfValue
|
|||
|
}
|
|||
|
}
|
|||
|
if AppID == "" || AppSecret == "" {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "AppID,AppSecret不能为空",
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
cfg := &offConfigMini.Config{
|
|||
|
AppID: AppID,
|
|||
|
AppSecret: AppSecret,
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
mini := wc.GetMiniProgram(cfg)
|
|||
|
accessToken, err := mini.GetAuth().GetAccessToken()
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
data := fmt.Sprintf("{\"code\":\"%s\"}", code)
|
|||
|
result, _ := tools.Post("https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+accessToken, "application/json;charset=utf-8", []byte(data))
|
|||
|
log.Println(result)
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": result,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 获取小程序手机号
|
|||
|
func GetMiniUserInfo(c *gin.Context) {
|
|||
|
code := c.Query("code")
|
|||
|
entId := c.Query("entId")
|
|||
|
systemId := models.FindConfig("SystemBussinesId")
|
|||
|
if systemId == "" {
|
|||
|
systemId = entId
|
|||
|
}
|
|||
|
configs := models.FindEntConfigs(systemId)
|
|||
|
AppID := ""
|
|||
|
AppSecret := ""
|
|||
|
for _, config := range configs {
|
|||
|
if config.ConfKey == "WechatMiniAppId" {
|
|||
|
AppID = config.ConfValue
|
|||
|
}
|
|||
|
if config.ConfKey == "WechatMiniAppSecret" {
|
|||
|
AppSecret = config.ConfValue
|
|||
|
}
|
|||
|
}
|
|||
|
if AppID == "" || AppSecret == "" {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "AppID,AppSecret不能为空",
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
cfg := &offConfigMini.Config{
|
|||
|
AppID: AppID,
|
|||
|
AppSecret: AppSecret,
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
mini := wc.GetMiniProgram(cfg)
|
|||
|
res, err := mini.GetAuth().Code2Session(code)
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
openId := res.OpenID
|
|||
|
customer := models.FindCustomerWhere("ent_id = ? and openid = ?", entId, openId)
|
|||
|
kefuInfo := models.FindUserByUid(entId)
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": gin.H{
|
|||
|
"open_id": openId,
|
|||
|
"avatar": customer.Avatar,
|
|||
|
"nickname": customer.Name,
|
|||
|
"tel": customer.Tel,
|
|||
|
"score": customer.Score,
|
|||
|
"kefu_nickname": kefuInfo.Nickname,
|
|||
|
"company_pic": kefuInfo.CompanyPic,
|
|||
|
},
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
// 发送应用消息
|
|||
|
func SendWorkAppMsg(c *gin.Context) {
|
|||
|
//SendWorkWechatMesage("2", "xxx", "kefu2", "你好")
|
|||
|
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
const token = "taoshihan"
|
|||
|
const receiverId = "wwa4266261c4ea2c08"
|
|||
|
const encodingAeskey = "aoazdxwpDKjOKM6T04YINN9HpAowEOVl6VDGMUJKn54"
|
|||
|
|
|||
|
// 接收应用消息
|
|||
|
func ReceiveWorkAppMsg(c *gin.Context) {
|
|||
|
httpstr := c.Request.URL.RawQuery
|
|||
|
echo := strings.Index(httpstr, "echostr")
|
|||
|
entId := c.Param("entId")
|
|||
|
|
|||
|
wechatConfig, _ := lib.NewWechatLib(entId)
|
|||
|
if wechatConfig.WorkWechatCorpid == "" ||
|
|||
|
wechatConfig.WorkWechatAppToken == "" ||
|
|||
|
wechatConfig.WorkWechatAppEncodingAESKey == "" {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": "配置错误",
|
|||
|
})
|
|||
|
}
|
|||
|
if echo != -1 {
|
|||
|
VerifyURL(c.Writer, c.Request,
|
|||
|
wechatConfig.WorkWechatAppToken,
|
|||
|
wechatConfig.WorkWechatAppEncodingAESKey,
|
|||
|
wechatConfig.WorkWechatCorpid)
|
|||
|
} else {
|
|||
|
MsgHandler(c.Writer, c.Request,
|
|||
|
wechatConfig.WorkWechatAppToken,
|
|||
|
wechatConfig.WorkWechatAppEncodingAESKey,
|
|||
|
wechatConfig.WorkWechatCorpid,
|
|||
|
entId)
|
|||
|
}
|
|||
|
//c.JSON(200, gin.H{
|
|||
|
// "code": 200,
|
|||
|
// "msg": "ok",
|
|||
|
//})
|
|||
|
}
|
|||
|
func VerifyURL(w http.ResponseWriter, r *http.Request, token, encodingAeskey, receiverId string) {
|
|||
|
//httpstr := `&{GET /?msg_signature=825075c093249d5a60967fe4a613cae93146636b×tamp=1597998748&nonce=1597483820&echostr=neLB8CftccHiz19tluVb%2BUBnUVMT3xpUMZU8qvDdD17eH8XfEsbPYC%2FkJyPsZOOc6GdsCeu8jSIa2noSJ%2Fez2w%3D%3D HTTP/1.1 1 1 map[Cache-Control:[no-cache] Accept:[*/*] Pragma:[no-cache] User-Agent:[Mozilla/4.0]] 0x86c180 0 [] false 100.108.211.112:8893 map[] map[] <nil> map[] 100.108.79.233:59663 /?msg_signature=825075c093249d5a60967fe4a613cae93146636b×tamp=1597998748&nonce=1597483820&echostr=neLB8CftccHiz19tluVb%2BUBnUVMT3xpUMZU8qvDdD17eH8XfEsbPYC%2FkJyPsZOOc6GdsCeu8jSIa2noSJ%2Fez2w%3D%3D <nil>}`
|
|||
|
fmt.Println(r, r.Body)
|
|||
|
httpstr := r.URL.RawQuery
|
|||
|
start := strings.Index(httpstr, "msg_signature=")
|
|||
|
start += len("msg_signature=")
|
|||
|
|
|||
|
var msg_signature string
|
|||
|
next := getString(httpstr, "×tamp=", start, &msg_signature)
|
|||
|
|
|||
|
var timestamp string
|
|||
|
next = getString(httpstr, "&nonce=", next, ×tamp)
|
|||
|
|
|||
|
var nonce string
|
|||
|
next = getString(httpstr, "&echostr=", next, &nonce)
|
|||
|
|
|||
|
echostr := httpstr[next:len(httpstr)]
|
|||
|
|
|||
|
echostr, _ = url.QueryUnescape(echostr)
|
|||
|
fmt.Println(msg_signature, timestamp, nonce, echostr, next)
|
|||
|
|
|||
|
wxcpt := wxbizjsonmsgcrypt.NewWXBizMsgCrypt(token, encodingAeskey, receiverId, wxbizjsonmsgcrypt.JsonType)
|
|||
|
echoStr, cryptErr := wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr)
|
|||
|
if nil != cryptErr {
|
|||
|
fmt.Println("verifyUrl fail", cryptErr)
|
|||
|
}
|
|||
|
fmt.Println("verifyUrl success echoStr", string(echoStr))
|
|||
|
fmt.Fprintf(w, string(echoStr))
|
|||
|
}
|
|||
|
func getString(str, endstr string, start int, msg *string) int {
|
|||
|
end := strings.Index(str, endstr)
|
|||
|
*msg = str[start:end]
|
|||
|
return end + len(endstr)
|
|||
|
}
|
|||
|
|
|||
|
type MsgContent struct {
|
|||
|
ToUsername string `json:"ToUserName"`
|
|||
|
FromUsername string `json:"FromUserName"`
|
|||
|
CreateTime uint32 `json:"CreateTime"`
|
|||
|
MsgType string `json:"MsgType"`
|
|||
|
Content string `json:"Content"`
|
|||
|
Msgid uint64 `json:"MsgId"`
|
|||
|
Agentid uint32 `json:"AgentId"`
|
|||
|
}
|
|||
|
|
|||
|
func MsgHandler(w http.ResponseWriter, r *http.Request, token, encodingAeskey, receiverId, entId string) {
|
|||
|
httpstr := r.URL.RawQuery
|
|||
|
start := strings.Index(httpstr, "msg_signature=")
|
|||
|
start += len("msg_signature=")
|
|||
|
|
|||
|
var msg_signature string
|
|||
|
next := getString(httpstr, "×tamp=", start, &msg_signature)
|
|||
|
|
|||
|
var timestamp string
|
|||
|
next = getString(httpstr, "&nonce=", next, ×tamp)
|
|||
|
|
|||
|
nonce := httpstr[next:len(httpstr)]
|
|||
|
fmt.Println(msg_signature, timestamp, nonce)
|
|||
|
|
|||
|
body, err := ioutil.ReadAll(r.Body)
|
|||
|
fmt.Println(string(body), err)
|
|||
|
wxcpt := lib.NewWXBizMsgCrypt(token, encodingAeskey, receiverId, lib.XmlType)
|
|||
|
|
|||
|
msg, err_ := wxcpt.DecryptMsg(msg_signature, timestamp, nonce, body)
|
|||
|
fmt.Println(string(msg), err_)
|
|||
|
var msgContent MsgContent
|
|||
|
err = xml.Unmarshal(msg, &msgContent)
|
|||
|
if nil != err {
|
|||
|
fmt.Println("Unmarshal fail")
|
|||
|
} else {
|
|||
|
fmt.Println("struct", msgContent)
|
|||
|
}
|
|||
|
|
|||
|
fmt.Println(msgContent, err)
|
|||
|
if msgContent.Content == "" {
|
|||
|
return
|
|||
|
}
|
|||
|
result := ""
|
|||
|
kefuInfo := models.FindUserByUid(entId)
|
|||
|
config := models.GetEntConfigsMap(entId, "QdrantAIStatus")
|
|||
|
if config["QdrantAIStatus"] == "true" {
|
|||
|
//调用GPT3.5
|
|||
|
result = ws.Gpt3Knowledge(entId, "", kefuInfo, msgContent.Content)
|
|||
|
} else {
|
|||
|
//调用自动回复
|
|||
|
result = GetLearnReplyContent(entId, msgContent.Content)
|
|||
|
}
|
|||
|
timeStr := tools.Int2Str(tools.Now())
|
|||
|
respXml := fmt.Sprintf(`
|
|||
|
<xml>
|
|||
|
<ToUserName><![CDATA[%s]]></ToUserName>
|
|||
|
<FromUserName><![CDATA[%s]]></FromUserName>
|
|||
|
<CreateTime>%s</CreateTime>
|
|||
|
<MsgType><![CDATA[text]]></MsgType>
|
|||
|
<Content><![CDATA[%s]]></Content>
|
|||
|
</xml>
|
|||
|
`, msgContent.FromUsername, msgContent.ToUsername, timeStr, result)
|
|||
|
resp, _ := wxcpt.EncryptMsg(respXml, timeStr, "1372623149")
|
|||
|
w.Write(resp)
|
|||
|
//id, _ := tools.GetOneStringByRegex(msgContent.Content, "@(\\d+)")
|
|||
|
//if id == "" {
|
|||
|
// return
|
|||
|
//}
|
|||
|
//content := strings.Trim(strings.ReplaceAll(msgContent.Content, "@"+id, ""), " ")
|
|||
|
//if content == "" {
|
|||
|
// return
|
|||
|
//}
|
|||
|
//vistorInfo := models.FindVisitorByCondition("id = ? and ent_id = ?", id, entId)
|
|||
|
//if vistorInfo.ID != 0 {
|
|||
|
// kefuInfo := models.FindUserByUid(entId)
|
|||
|
// isRead := "unread"
|
|||
|
// models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, content, "kefu", entId, isRead)
|
|||
|
// go ws.VisitorMessage(vistorInfo.VisitorId, content, kefuInfo)
|
|||
|
//}
|
|||
|
}
|
|||
|
|
|||
|
// 获取企业微信客服列表
|
|||
|
func GetWorkAccountList(c *gin.Context) {
|
|||
|
wc := wechat.NewWechat()
|
|||
|
cfg := &workConfig.Config{
|
|||
|
CorpID: "wwa4266261c4ea2c08",
|
|||
|
CorpSecret: "jdYozJmgcmsfUNfmGgHPgE--7iGyEIc2UZ8IkBJW-AA",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
work := wc.GetWork(cfg)
|
|||
|
kfClient, err := work.GetKF()
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
accountList, err := kfClient.AccountList()
|
|||
|
if err != nil {
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 400,
|
|||
|
"msg": err.Error(),
|
|||
|
})
|
|||
|
return
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"code": 200,
|
|||
|
"msg": "ok",
|
|||
|
"result": accountList.AccountList,
|
|||
|
})
|
|||
|
}
|
|||
|
func GetMiniMessage(c *gin.Context) {
|
|||
|
entId := c.Param("entId")
|
|||
|
configs := models.GetEntConfigsMap(entId, "WechatMiniToken", "WechatMiniAppId", "WechatMiniAppSecret")
|
|||
|
token := configs["WechatMiniToken"]
|
|||
|
|
|||
|
signature := c.Query("signature")
|
|||
|
timestamp := c.Query("timestamp")
|
|||
|
nonce := c.Query("nonce")
|
|||
|
echostr := c.Query("echostr")
|
|||
|
|
|||
|
rawData, _ := c.GetRawData()
|
|||
|
jsonMsg := string(rawData)
|
|||
|
log.Println("微信小程序:", jsonMsg)
|
|||
|
|
|||
|
fromUsername := gjson.Get(jsonMsg, "FromUserName").String()
|
|||
|
toUsername := gjson.Get(jsonMsg, "ToUserName").String()
|
|||
|
event := gjson.Get(jsonMsg, "Event").String()
|
|||
|
msgType := gjson.Get(jsonMsg, "MsgType").String()
|
|||
|
content := gjson.Get(jsonMsg, "Content").String()
|
|||
|
|
|||
|
//首次提交接口的时候需要验证
|
|||
|
if msgType == "" {
|
|||
|
res, err := toolsWechat.CheckWechatSign(token, signature, timestamp, nonce, echostr)
|
|||
|
if err == nil {
|
|||
|
c.Writer.Write([]byte(res))
|
|||
|
} else {
|
|||
|
log.Println("微信API验证失败", res)
|
|||
|
}
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
cfg := &offConfigMini.Config{
|
|||
|
AppID: configs["WechatMiniAppId"],
|
|||
|
AppSecret: configs["WechatMiniAppSecret"],
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: memory,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
mini := wc.GetMiniProgram(cfg).GetCustomerMessage()
|
|||
|
|
|||
|
visitorId := fmt.Sprintf("mini|%s|%s", entId, fromUsername)
|
|||
|
avator := "/static/images/we-chat-wx.png"
|
|||
|
visitorName := "微信小程序用户"
|
|||
|
vistorInfo := models.FindVisitorByVistorId(visitorId)
|
|||
|
kefuInfo := models.FindUserByUid(entId)
|
|||
|
go ws.VisitorOnline(kefuInfo.Name, vistorInfo)
|
|||
|
|
|||
|
if msgType == "text" {
|
|||
|
go models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, content, "visitor", vistorInfo.EntId, "unread")
|
|||
|
ws.VisitorToKefuMessage(vistorInfo, kefuInfo.Name, content)
|
|||
|
go SendWechatVisitorMessageTemplate(kefuInfo.Name, vistorInfo.Name, vistorInfo.VisitorId, content, vistorInfo.EntId)
|
|||
|
|
|||
|
if vistorInfo.ID != 0 {
|
|||
|
go models.UpdateVisitorVisitorId(visitorId, visitorId)
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"MsgType": "transfer_customer_service",
|
|||
|
"FromUserName": toUsername,
|
|||
|
"ToUserName": fromUsername,
|
|||
|
"CreateTime": timestamp,
|
|||
|
})
|
|||
|
//自动回复
|
|||
|
reply := models.FindArticleRow("ent_id = ? and title like ?", vistorInfo.EntId, "%"+content+"%")
|
|||
|
reply.Content, _ = tools.ReplaceStringByRegex(reply.Content, `<[^a>]+>|target="[^"]+"`, "")
|
|||
|
if reply.Content != "" {
|
|||
|
go ws.KefuMessage(vistorInfo.VisitorId, reply.Content, kefuInfo)
|
|||
|
go models.ReadMessageByVisitorId(vistorInfo.VisitorId, "kefu")
|
|||
|
go models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, reply.Content, "kefu", vistorInfo.EntId, "read")
|
|||
|
msg := miniMsg.NewCustomerTextMessage(fromUsername, reply.Content)
|
|||
|
go mini.Send(msg)
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
if msgType == "image" {
|
|||
|
mediaId := gjson.Get(jsonMsg, "MediaId").String()
|
|||
|
accessToken, _ := mini.GetAccessToken()
|
|||
|
imgUrl := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s", accessToken, mediaId)
|
|||
|
content = fmt.Sprintf("<a href='%s' target='_blank'><img class='chatImagePic' src='%s' data-src='%s'/></a>", imgUrl, imgUrl, imgUrl)
|
|||
|
models.CreateMessage(kefuInfo.Name, vistorInfo.VisitorId, content, "visitor", vistorInfo.EntId, "unread")
|
|||
|
go ws.VisitorToKefuMessage(vistorInfo, kefuInfo.Name, content)
|
|||
|
go SendWechatVisitorMessageTemplate(kefuInfo.Name, vistorInfo.Name, vistorInfo.VisitorId, content, vistorInfo.EntId)
|
|||
|
|
|||
|
if vistorInfo.ID != 0 {
|
|||
|
go models.UpdateVisitorVisitorId(visitorId, visitorId)
|
|||
|
}
|
|||
|
c.JSON(200, gin.H{
|
|||
|
"MsgType": "transfer_customer_service",
|
|||
|
"FromUserName": toUsername,
|
|||
|
"ToUserName": fromUsername,
|
|||
|
"CreateTime": timestamp,
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
if event == "user_enter_tempsession" {
|
|||
|
//发送欢迎
|
|||
|
welcomes := models.FindWelcomesByKeyword(kefuInfo.Name, "wechat")
|
|||
|
if len(welcomes) > 0 {
|
|||
|
for _, welcome := range welcomes {
|
|||
|
welcome.Content, _ = tools.ReplaceStringByRegex(welcome.Content, `<[^a>]+>|target="[^"]+"`, "")
|
|||
|
msg := miniMsg.NewCustomerTextMessage(fromUsername, welcome.Content)
|
|||
|
mini.Send(msg)
|
|||
|
}
|
|||
|
}
|
|||
|
//发送热门问题
|
|||
|
questions := models.FindTopArticles("ent_id = ? and is_top = 1 ", entId)
|
|||
|
if len(questions) > 0 {
|
|||
|
num := time.Now().Unix()
|
|||
|
questionStr := "热门问题导航"
|
|||
|
for _, item := range questions {
|
|||
|
questionStr += fmt.Sprintf("\r\n<a href='weixin://bizmsgmenu?msgmenucontent=%s&msgmenuid=%d'>%s</a>", item.Title, item.Id, item.Title)
|
|||
|
num++
|
|||
|
}
|
|||
|
msg := miniMsg.NewCustomerTextMessage(fromUsername, questionStr)
|
|||
|
mini.Send(msg)
|
|||
|
}
|
|||
|
|
|||
|
if vistorInfo.ID == 0 {
|
|||
|
vistorInfo = *models.CreateVisitor(visitorName, avator, c.ClientIP(), kefuInfo.Name, visitorId, "微信小程序客服界面", "未知", c.ClientIP(), entId, "")
|
|||
|
} else {
|
|||
|
vistorInfo.VisitNum = vistorInfo.VisitNum + 1
|
|||
|
models.UpdateVisitor(entId, vistorInfo.Name, avator, visitorId, kefuInfo.Name, vistorInfo.Status, c.ClientIP(), c.ClientIP(),
|
|||
|
"微信小程序客服界面",
|
|||
|
"",
|
|||
|
vistorInfo.City,
|
|||
|
vistorInfo.VisitNum,
|
|||
|
)
|
|||
|
}
|
|||
|
noticeContent := fmt.Sprintf("%s访问%d次", vistorInfo.Name, vistorInfo.VisitNum)
|
|||
|
go SendVisitorLoginNotice(kefuInfo.Name, vistorInfo.Name, vistorInfo.Avator, noticeContent, vistorInfo.VisitorId)
|
|||
|
}
|
|||
|
|
|||
|
}
|