ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

基于laravel+workerman+easywechat的公众号客服系统

2021-11-19 09:31:31  阅读:346  来源: 互联网

标签:laravel res easywechat workerman content messageId message data id


1、流程:用户在公众号发送文本消息,通过公众号消息模板推送通知给客服,客服点击通知,跳转小程序与用户对话。用户可以直接在公众号内与客服对话。

2、所用技术栈:                 

"php": "^7.3|^8.0",
"laravel/framework": "^8.54",
"overtrue/laravel-wechat": "^6.0",
"overtrue/wechat": "~5.0",
"workerman/gateway-worker": "^3.0",
"workerman/workerman": "^4.0",

3、首先截获用户在公众号发送的消息(workerman搭建不再赘述,详情可查看官方文档)

WechatController.php

    public function wechetCheck()
    {
        $app = Factory::officialAccount($this->config);
        $app->server->push(function ($message) use ($app) {
            switch ($message['MsgType']) {
                case 'event' :
                    {
                        // do something
                    }
                    break;
                case 'text':
                {
                    //检查用户是否咨询过,咨询过则用原message_id
                    $openId = $message['FromUserName'];
                    $LogServerMessage = new LogServerMessage();
                    $checkMessage = $LogServerMessage->getIdByOpenId($openId);
                    if (!$checkMessage) {
                        $messageId = $LogServerMessage->newMessage($openId)->id;
                    } else {
                        $messageId = $checkMessage->id;
                    }
                    $LogServer = new LogServer();
                    $serverRes = $LogServer->addLog($messageId, $openId, 0, $message['Content']);
                    // 发送消息模板,按自己的实际情况编写
                    // do something
                    }
                    //由于我的服务器同时运行了多个workerman,需要指定registerAddress发送消息
                    Gateway::$registerAddress = '127.0.0.1:1237';
                    Gateway::sendToGroup("server_{$messageId}", json_encode([
                        'type' => 'message',
                        'content' => $message['Content'],
                        'id' => $serverRes->id
                    ]));
                    return "消息提示";
                }
            }
        });
        return $app->server->serve();
    }

    //发送消息给用户,配置路由为 /server-message-list
    public function sendServerMsgToUser(Request $request)
    {
        $messageId = $request->input('message_id');
        $content = $request->input('content');
        $toUserOpenId = $request->input('to_user_open_id');
        $fromUserOpenId = $request->input('from_user_open_id');
        $app = Factory::officialAccount($this->config);
        $app->customer_service->message($content)->to($toUserOpenId)->send();
        $LogServer = new LogServer();
        $server = $LogServer->addLog($messageId, $fromUserOpenId, 1, $content);
        $data['status'] = 'success';
        $data['content'] = $server->id;
        return $data;
    }

 LogServerMessage.php(表结构很简单,就只保存open_id)

    public function newMessage($openId)
    {
        return $this->create([
            'open_id' => $openId
        ]);
    }

    public function getIdByOpenId($openId)
    {
        return $this->where('open_id', $openId)->first(['id']);
    }

 LogServer.php(记录消息详情)

    /***
    *$userType 0:用户;1:客服;
    ***/
    public function addLog($messageId, $openId, $userType, $content)
    {
        return $this->create([
            'message_id' => $messageId,
            'open_id' => $openId,
            'user_type' => $userType,
            'content' => $content
        ]);
    }

    public function getListByMessageId($messageId)
    {
        return $this->where('message_id', $messageId)->orderBy('id', 'asc')->get(['id', 'user_type', 'content', 'open_id']);
    }

4、前端连接websocket,我这里使用的是uniapp

<template>
    <view class="h-100 w-100 p-1">
        <scroll-view class="content-wrap bg p-1" :scroll-y="true"  :scroll-into-view="scrollViewItem">
            <view v-for="(item, index) in list" :key="index" class="w-90p"
                  :class="[parseInt(item.user_type) === 0 ? '' : 'msg-server-flex']">
                <view class="msg border-round border p-05 m-b-05" :id="`msg_${item.id}`"
                      :class="[parseInt(item.user_type) === 0 ? 'msg-customer' : 'msg-server']">
                <span>
                    {{ item.content }}
                </span>
                </view>
            </view>
        </scroll-view>
        <view class="flex flex-center flex-col footer w-90p">
            <u-input :border="true" style="width: 100%" type="textarea" v-model="content"/>
            <u-button :custom-style="longPop" size="mini" type="primary-color" :hair-line="false" @click="sendMessage">
                发送
            </u-button>
        </view>
    </view>
</template>

<script>
export default {
    name: "index",
    data() {
        return {
            messageId: '',
            list: [],
            user: this.$common.getUserInfo(),
            content: '',
            longPop: {
                width: '100%',
                margin: '0.5rem auto'
            },
            toUserOpenId: '',
            fromUserOpenId: '',
            scrollViewItem: ''
        }
    },
    methods: {
        getMessage() {
            const data = {
                uid: this.user.uid,
                token: this.user.token,
                message_id: this.messageId
            }
            this.$ajax.post(`${this.$url}/server-message-list`, data).then(res => {
                this.list = []
                if (res.data.status === 'success') {
                    this.list = res.data.content.list
                    this.toUserOpenId = res.data.content.open_id
                    this.fromUserOpenId = res.data.content.server_open_id
                    this.scrollToBottom(this.list[this.list.length - 1].id)
                }
            })
        },
        sendMessage() {
            const data = {
                uid: this.user.uid,
                token: this.user.token,
                content: this.content,
                to_user_open_id: this.toUserOpenId,
                from_user_open_id: this.fromUserOpenId,
                message_id: this.messageId
            }
            this.$ajax.post(`${this.$url}/send-server-msg-to-user`, data).then(res => {
                this.list.push({
                    content: this.content,
                    user_type: 1,
                    id: res.data.content
                })
                this.content = ''
                this.scrollToBottom(res.data.content)
            })
        },
        scrollToBottom(id){
            this.scrollViewItem = `msg_${id}`
        }
    },
    onl oad(option) {
        this.messageId = option.message_id
        this.getMessage()
        uni.connectSocket({
            url: `wss://your-wesocket?message_id=${this.messageId}`,
            success: res => console.log('success:', res),
            error: res => console.log('error:', res),
            complete: res => console.log('complete:', res),
        })
        const _this = this
        uni.onSocketMessage(function (res) {
            const data = JSON.parse(res.data)
            if (data.type === 'message') {
                _this.list.push({
                    content: data.content,
                    user_type: 0,
                    id: data.id
                })
                _this.scrollToBottom(data.id)
            }
        });
    }
}
</script>


<style scoped lang="scss">
@import "src/static/style/common.scss";

.bg {
    background-color: #fcfcfc;
}

.p-1 {
    padding: 25rpx;
}


.h-100 {
    height: 100vh;
}

.w-100 {
    width: 100vw;
}


.w-90p {
    width: 90%;
}


.p-05 {
    padding: 15rpx;
}


.m-b-05 {
    margin-bottom: 15rpx;
}

.border-round {
    border-radius: 5px;
}

.border{
    border: 1px solid #efefef;
}


.flex {
    display: flex;
}

.flex-center {
    justify-content: center;
    align-items: center;
}

.flex-col {
    flex-direction: column;
}

.content-wrap {
    height: calc(100vh - 300rpx);
    overflow-y: auto;
}

.footer {
    position: fixed;
    left: 5%;
    bottom: 30rpx;
    background-color: white;
}

.msg {
    max-width: 45%;
    display: inline-block;
}

.msg-customer {
    background-color: white;
}

.msg-server {
    background-color: $green;
    color: white;
}

.msg-server-flex {
    display: flex;
    justify-content: flex-end;
}
</style>

标签:laravel,res,easywechat,workerman,content,messageId,message,data,id
来源: https://blog.csdn.net/b2894lxlx/article/details/121414552

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有