Wechat applet + php to realize instant messaging chat function

1, PHP7 installing the spool extension

PHP swoole extension download address

Github: https://github.com/swoole/swoole-src/tags

PHP official extension library: http://pecl.php.net/package/swoole

Open source China: http://git.oschina.net/swoole/swoole/tags

1. Custom installation

#Download wget https://pecl.php.net/get/swoole-4.3.3.tgz #Unzip tar zxf swoole-4.3.3 Tgz # compile and install extension # enter the directory cd swoole-4.3.3 # execute phpize command to generate the configure executable # if you don't know where the phpize path is, you can use which phpize to view the corresponding path / usr/bin/phpize # for configuration. If you don't know where the PHP config path is, you can use which PHP config to view the corresponding path/ Configure -- with PHP config = / usr / bin / PHP config # compile and install make & & make install VI / etc / PHP Ini copy the following code: extension = swoole So can be put into the file you opened or created without restarting any service # to check whether the extension is successfully installed PHP - m|grep spool

2. Install PHP spoole extension on pagoda panel

If you feel that the above installation is complex, you can use the pagoda panel to realize one click installation

2, Configure nginx reverse proxy

1. Connect to a remote alicloud server using xshell

2. Use the command (find / -name nginx.conf) to find nginx Configuration file where conf is located

3. Use the command (vim /etc/nginx/nginx.conf) to find and enter the vim editor

View the configuration file information that can be imported under / etc/nginx/conf.d /

4. Use the command (cd /etc/nginx/conf.d /) to enter the path and create a new configuration file: study lishuo. net. conf

5. Configure nginx reverse proxy to access study lishuo. Net domain name forwarding port number to 127.0.0.1:9511, that is, the port number forwarded to websocket

# The name of study, the rule of reverse proxy, can be used casually
upstream study{
  server 127.0.0.1:9511;
}
server {
        listen       80;
        server_name  study.lishuo.net;
        error_page 404 /404.html;
        location = /404.html {
        }
        location / {
          index index.php index.html index.htm;
          if (!-e $request_filename) {
                rewrite  ^(.*)$  /index.php?s=/$1  last;
          }
        #wss configuration
        client_max_body_size 100m;
        proxy_redirect off;
        proxy_set_header Host $host;# http requested host domain name
        proxy_set_header X-Real-IP $remote_addr;# Remote real IP address
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#IP address before forwarding after reverse proxy
        proxy_read_timeout 604800s;#The heartbeat time of websocket is 60s by default
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_pass http://study;
       }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
         #Add the following information to configure Nginx to process your PHP requests through fastcgi.
        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9001;   #Forward PHP requests to the native FPM through php-9000.
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;   #Nginx calls the fastcgi interface to process PHP requests.
        }
    }
copy

3, Wechat applet socket legal domain name configuration

1. Log in to wechat open platform https://mp.weixin.qq.com/

2. Development = > development management = > development settings, complete legal domain name settings

3. Now that the configuration has been completed, the next step is to realize the function, wechat applet + PHP code

4, Effect demonstration and code

1. Applet side code

Path of applet page code / pages / contact / contact wxml

<!--pages/contact/contact.wxml-->

<view>

<scroll-view scroll-y scroll-into-view='{{toView}}' style='height: {{scrollHeight}};'>
  <!-- <view class='scrollMsg'> -->
  <block wx:key wx:for='{{msgList}}' wx:for-index="index">

    <!-- Single message 1 sent by customer service (left) -->
    <view wx:if='{{item.speaker=="server"}}' id='msg-{{index}}' style='display: flex; padding: 2vw 11vw 2vw 2vw;'>
      <view style='width: 11vw; height: 11vw;'>
        <image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='https://cdn.pixabay.com/photo/2020/02/10/12/47/girl-4836394__340.jpg'></image>
      </view>
      <view style='width: 4vw; height: 11vw; margin-left: 0.5vw; display: flex; align-items: center; z-index: 9;'>
        <view class="triangle_border_left"></view>
      </view>
      <view class='leftMsg'>{{item.content}}</view>
    </view>

    <!-- Single message 2 sent by user (right) -->
    <view wx:else id='msg-{{index}}' style='display: flex; justify-content: flex-end; padding: 2vw 2vw 2vw 11vw;'>
      <view class='rightMsg'>{{item.content}}</view>
      <view style='width: 4vw; height: 11vw; margin-right: 0.5vw; display: flex; align-items: center; z-index: 9;'>
        <view class="triangle_border_right"></view>
      </view>
      <view style='width: 11vw; height: 11vw;'>
        <image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='https://cdn.pixabay.com/photo/2021/09/24/10/00/chick-6652163__340.jpg'></image>
      </view>
    </view>

  </block>
  <!-- </view> -->

  <!-- seize a seat -->
  <view style='width: 100%; height: 18vw;'></view>
</scroll-view>

<view class='inputRoom' style='bottom: {{inputBottom}}'>
  <image style='width: 7vw; margin-left: 3.2vw;' src='https://img95.699pic.com/element/40030/6429.png_300.png' mode='widthFix'></image>
  <input bindconfirm='sendClick' adjust-position='{{false}}' value='{{inputVal}}' confirm-type='send' bindfocus='focus' bindblur='blur'></input>
</view>
</view>
copy

2. Path of applet page style code / pages / contact / contact wxss

/* pages/contact/contact.wxss */

page {
  background-color: #f1f1f1;
}

.inputRoom {
  width: 100vw;
  height: 16vw;
  border-top: 1px solid #cdcdcd;
  background-color: #f1f1f1;
  position: fixed;
  bottom: 0;
  display: flex;
  align-items: center;
  z-index: 20;
}

input {
  width: 76vw;
  height: 9.33vw;
  background-color: #fff;
  border-radius: 40rpx;
  margin-left: 2vw;
  padding: 0 3vw;
  font-size: 28rpx;
  color: #444;
}

.leftMsg {
  font-size: 35rpx;
  color: #444;
  line-height: 7vw;
  padding: 2vw 2.5vw;
  background-color: #fff;
  margin-left: -1.6vw;
  border-radius: 10rpx;
  z-index: 10;
}

.rightMsg {
  font-size: 35rpx;
  color: #444;
  line-height: 7vw;
  padding: 2vw 2.5vw;
  background-color: #96EB6A;
  margin-right: -1.6vw;
  border-radius: 10rpx;
  z-index: 10;
}

 /*towards the left*/
 .triangle_border_left {
  width: 0;
  height: 0;
  border-width: 10px 30px 30px 0;
  border-style: solid;
  border-color: transparent #fff transparent transparent;
          /*Transparent yellow transparent */
  margin: 40px auto;
  position: relative;
}


        /*towards the right*/
        .triangle_border_right {
          width: 0;
          height: 0;
          border-width: 0px 30px 20px 13px;
          border-style: solid;
          border-color: transparent transparent transparent #96EB6A;
                  /*Transparent yellow*/
          margin: 40px auto;
          position: relative;
      }
copy

Path of applet configuration file code / pages / contact / contact json

{
  "navigationBarTitleText":"Ke Zuo customer service",
  "usingComponents": {
  
  }
}
copy

Path of applet business logic code / pages / contact / contact js

// pages/contact/contact.js
const app = getApp();
var inputVal = '';
var msgList = [];
var windowWidth = wx.getSystemInfoSync().windowWidth;
var windowHeight = wx.getSystemInfoSync().windowHeight;
var keyHeight = 0;

/**
 * Initialization data
 */
function initData(that) {
  //Contents of input box
  inputVal = '';
  //Message list, including chat content between customer service and users
  msgList = [{
      speaker: 'server',
      contentType: 'text',
      content: 'Hiļ¼ŒDear little Lord, I finally wait for you! Welcome to Kezuo store. It's my pleasure to serve you.'
    },
    {
      speaker: 'customer',
      contentType: 'text',
      content: 'It's too early for you to be happy'
    }
  ]
  that.setData({
    msgList,
    inputVal
  })
}

Page({
  /**
   * Initial data of the page
   */
  data: {
    scrollHeight: '100vh',
    inputBottom: 0
  },

  /**
   * Life cycle function -- listening for page loading
   */
  onLoad: function(options) {
    //Initialize websocket connection
    this.chat();
    //Method of monitoring heartbeat
    this.webSocketXin();
    //Chat method
    initData(this);

    //Listen for messages
    wx.onSocketMessage(res=>{
         //Append to message list
        msgList.push(JSON.parse(res.data))
        inputVal = '';
        this.setData({
          msgList,
          inputVal
        });
    })


  },
  //Page unload time
  onUnload(){
    wx.closeSocket();
  },
  /**
   * Get focus
   */
  focus: function(e) {
    keyHeight = e.detail.height;
    this.setData({
      scrollHeight: (windowHeight - keyHeight) + 'px'
    });
    this.setData({
      toView: 'msg-' + (msgList.length - 1),
      inputBottom: keyHeight + 'px'
    })
    //Calculate msg height
    // calScrollHeight(this, keyHeight);

  },

  //Lose focus (soft keyboard disappears)
  blur: function(e) {
    this.setData({
      scrollHeight: '100vh',
      inputBottom: 0
    })
    this.setData({
      toView: 'msg-' + (msgList.length - 1)
    })
  },

  /**
   * Send click monitor
   */
  sendClick: function(e) {
    //Information sent by customers
    let customerMsg = {
      uid: 10,
      speaker: 'customer',
      contentType: 'text',
      content: e.detail.value
    };

     //Turn off heartbeat packet
     this.webSocketXin(60000, false)
    //Send to websocket
    wx.sendSocketMessage({
      data: JSON.stringify(customerMsg),
      success:res=>{
        //Restart heartbeat packet
        this.webSocketXin(40000, true)
      }  
    })

    //Append to message list
    msgList.push(customerMsg)
    inputVal = '';
    this.setData({
      msgList,
      inputVal
    });
  },
  /**
   * Back to previous page
   */
  toBackClick: function() {
    wx.navigateBack({})
  },
  /**
   * websocket
   */
  chat(){
     //socket for connecting php
     wx.connectSocket({
       //wss protocol is equivalent to having an ssl certificate, https
       //ws is equivalent to http, which is not a practical certificate
      url: 'ws://study.lishuo.net',
      success: function () {
        console.log('websocket Connection successful~')
      },
      fail: function () {
        console.log('websocket connection failed~')
      }
    })
  },


  /**
   * Method for monitoring websocket heartbeat connection
   */
  webSocketXin(time=60000,status=true){
    var timing;
    if(status == true){
      timing = setInterval(function () {
        console.log("The current heartbeat has been reconnected");
        //Loop execution code
        wx.sendSocketMessage({
          data: JSON.stringify({
            type: 'active'
          }),
          fail(res) {
            //Close connection
            wx.closeSocket();
            //Tips
            wx.showToast({
              title: 'The current chat has been disconnected',
              icon:'none'
            })
            clearInterval(timing);
            console.log("Current heartbeat is off");
          }
        });
      }, time) //The cycle time should not exceed 1 minute  
    } else {
      //off timer 
      clearInterval(timing);
      console.log("Current heartbeat is off");
    }
  

  }



})
copy

2. Server code (PHP code)

wechat_websocket.php

<?php

//Create a WebSocket Server object and listen on port 0.0.0.0:9502
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9511);

//Listen for WebSocket connection opening events
$ws->on('Open', function ($ws, $request) {
    echo $request->fd . 'I'm connected';
});

//Listening for WebSocket message events
$ws->on('Message', function ($ws, $frame) {
    //Convert the json string passed from the foreground into an array
    $params = json_decode($frame->data, true);
    //Judge whether it is a heartbeat message. If it is a heartbeat message
    if (isset($params['type']) && isset($params['type'])=='active'){
        echo 'This is a heartbeat monitoring message';
    }else{
        //First judge whether the current user is connecting
        if (isset($params['uid']) && !empty($params['uid'] == 666)) {
            //Go to the user table to query the current user fd
            $fd = 2;
        } else {
            $fd = 1;
        }
        //Customer service id
        $ws->push($fd, json_encode($params, JSON_UNESCAPED_UNICODE));
    }
});

//Listen for WebSocket connection closing events
$ws->on('Close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();
copy

5, The code has been written

1. Upload the server code to the Linux operating system

2. Then switch to this directory and run php wechat_websocket.php

Posted by vbzoom.com on Tue, 10 May 2022 06:13:51 +0300