| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- package customerservice
- import (
- "fmt"
- "github.com/silenceper/wechat/v2/officialaccount/context"
- "github.com/silenceper/wechat/v2/util"
- )
- // TypingStatus 输入状态类型
- type TypingStatus string
- const (
- customerServiceListURL = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist"
- customerServiceOnlineListURL = "https://api.weixin.qq.com/cgi-bin/customservice/getonlinekflist"
- customerServiceAddURL = "https://api.weixin.qq.com/customservice/kfaccount/add"
- customerServiceUpdateURL = "https://api.weixin.qq.com/customservice/kfaccount/update"
- customerServiceDeleteURL = "https://api.weixin.qq.com/customservice/kfaccount/del"
- customerServiceInviteURL = "https://api.weixin.qq.com/customservice/kfaccount/inviteworker"
- customerServiceUploadHeadImg = "https://api.weixin.qq.com/customservice/kfaccount/uploadheadimg"
- customerServiceTypingURL = "https://api.weixin.qq.com/cgi-bin/message/custom/typing"
- )
- const (
- // Typing 表示正在输入状态
- Typing TypingStatus = "Typing"
- // CancelTyping 表示取消正在输入状态
- CancelTyping TypingStatus = "CancelTyping"
- )
- // Manager 客服管理者,可以管理客服
- type Manager struct {
- *context.Context
- }
- // NewCustomerServiceManager 实例化客服管理
- func NewCustomerServiceManager(ctx *context.Context) *Manager {
- csm := new(Manager)
- csm.Context = ctx
- return csm
- }
- // KeFuInfo 客服基本信息
- type KeFuInfo struct {
- KfAccount string `json:"kf_account"` // 完整客服帐号,格式为:帐号前缀@公众号微信号
- KfNick string `json:"kf_nick"` // 客服昵称
- KfID int `json:"kf_id"` // 客服编号
- KfHeadImgURL string `json:"kf_headimgurl"` // 客服头像
- KfWX string `json:"kf_wx"` // 如果客服帐号已绑定了客服人员微信号, 则此处显示微信号
- InviteWX string `json:"invite_wx"` // 如果客服帐号尚未绑定微信号,但是已经发起了一个绑定邀请, 则此处显示绑定邀请的微信号
- InviteExpTime int `json:"invite_expire_time"` // 如果客服帐号尚未绑定微信号,但是已经发起过一个绑定邀请, 邀请的过期时间,为unix 时间戳
- InviteStatus string `json:"invite_status"` // 邀请的状态,有等待确认“waiting”,被拒绝“rejected”, 过期“expired”
- }
- type resKeFuList struct {
- util.CommonError
- KfList []*KeFuInfo `json:"kf_list"`
- }
- // List 获取所有客服基本信息
- func (csm *Manager) List() (customerServiceList []*KeFuInfo, err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceListURL, accessToken)
- var response []byte
- response, err = util.HTTPGet(uri)
- if err != nil {
- return
- }
- var res resKeFuList
- err = util.DecodeWithError(response, &res, "ListCustomerService")
- return res.KfList, err
- }
- // KeFuOnlineInfo 客服在线信息
- type KeFuOnlineInfo struct {
- KfAccount string `json:"kf_account"`
- Status int `json:"status"`
- KfID int `json:"kf_id"`
- AcceptedCase int `json:"accepted_case"`
- }
- type resKeFuOnlineList struct {
- util.CommonError
- KfOnlineList []*KeFuOnlineInfo `json:"kf_online_list"`
- }
- // OnlineList 获取在线客服列表
- func (csm *Manager) OnlineList() (customerServiceOnlineList []*KeFuOnlineInfo, err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceOnlineListURL, accessToken)
- var response []byte
- response, err = util.HTTPGet(uri)
- if err != nil {
- return
- }
- var res resKeFuOnlineList
- err = util.DecodeWithError(response, &res, "ListOnlineCustomerService")
- return res.KfOnlineList, err
- }
- // Add 添加客服账号
- func (csm *Manager) Add(kfAccount, nickName string) (err error) {
- // kfAccount:完整客服帐号,格式为:帐号前缀@公众号微信号,帐号前缀最多10个字符,必须是英文、数字字符或者下划线,后缀为公众号微信号,长度不超过30个字符
- // nickName:客服昵称,最长16个字
- // 参数此处均不做校验
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceAddURL, accessToken)
- data := struct {
- KfAccount string `json:"kf_account"`
- NickName string `json:"nickname"`
- }{
- KfAccount: kfAccount,
- NickName: nickName,
- }
- var response []byte
- response, err = util.PostJSON(uri, data)
- if err != nil {
- return
- }
- err = util.DecodeWithCommonError(response, "AddCustomerService")
- return
- }
- // Update 修改客服账号
- func (csm *Manager) Update(kfAccount, nickName string) (err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceUpdateURL, accessToken)
- data := struct {
- KfAccount string `json:"kf_account"`
- NickName string `json:"nickname"`
- }{
- KfAccount: kfAccount,
- NickName: nickName,
- }
- var response []byte
- response, err = util.PostJSON(uri, data)
- if err != nil {
- return
- }
- err = util.DecodeWithCommonError(response, "UpdateCustomerService")
- return
- }
- // Delete 删除客服帐号
- func (csm *Manager) Delete(kfAccount string) (err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceDeleteURL, accessToken)
- data := struct {
- KfAccount string `json:"kf_account"`
- }{
- KfAccount: kfAccount,
- }
- var response []byte
- response, err = util.PostJSON(uri, data)
- if err != nil {
- return
- }
- err = util.DecodeWithCommonError(response, "DeleteCustomerService")
- return
- }
- // InviteBind 邀请绑定客服帐号和微信号
- func (csm *Manager) InviteBind(kfAccount, inviteWX string) (err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceInviteURL, accessToken)
- data := struct {
- KfAccount string `json:"kf_account"`
- InviteWX string `json:"invite_wx"`
- }{
- KfAccount: kfAccount,
- InviteWX: inviteWX,
- }
- var response []byte
- response, err = util.PostJSON(uri, data)
- if err != nil {
- return
- }
- err = util.DecodeWithCommonError(response, "InviteBindCustomerService")
- return
- }
- // UploadHeadImg 上传客服头像
- func (csm *Manager) UploadHeadImg(kfAccount, fileName string) (err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s&kf_account=%s", customerServiceUploadHeadImg, accessToken, kfAccount)
- var response []byte
- response, err = util.PostFile("media", fileName, uri)
- if err != nil {
- return
- }
- err = util.DecodeWithCommonError(response, "UploadCustomerServiceHeadImg")
- return
- }
- // SendTypingStatus 下发客服输入状态给用户
- func (csm *Manager) SendTypingStatus(openid string, cmd TypingStatus) (err error) {
- var accessToken string
- accessToken, err = csm.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", customerServiceTypingURL, accessToken)
- data := struct {
- ToUser string `json:"touser"`
- Command string `json:"command"`
- }{
- ToUser: openid,
- Command: string(cmd),
- }
- var response []byte
- response, err = util.PostJSON(uri, data)
- if err != nil {
- return
- }
- err = util.DecodeWithCommonError(response, "SendTypingStatus")
- return
- }
|