前期,写过一个帖子,为了解决微信支付成功之后,异步回调问题,使用了workerman的web-sender,其中需要引入大量文件开启三个端口,现阶段改进一下,原理利用swoole的websocket继承了Swoole\Http\Server,可以使用后者的onrequest接收其他页面后端页面的主动推送,原理大概如下,首先是start.php,主要作用是开启守护进程,并且执行调用thinkphp5的test.php中的方法
include_once('/www/wwwroot/tp5/extend/sw/Test.php');
$serv = new sw\Test("0.0.0.0", 9501);
$serv->set(array(
'daemonize' => 0,
'worker_num' => 2,
'task_worker_num' => 2
));
$redis= '';
$serv->on('WorkerStart', function ($serv, $worker_id) {
global $redis;
$redis = new \Redis();
$redis->connect("127.0.0.1", 6379) || die("redis 连接失败");
echo "redis 连接成功!\n";
});
$serv->on('Open', function($serv, $frame) {
echo "链接成功";
});
//当收到用户的消息时 触发事件
$serv->on('Message', function($serv, $frame) {
global $redis;
var_dump($frame);
$serv->messaging($redis,$frame);
});
$serv->on('request', function(\Swoole\Http\Request $request, \Swoole\Http\Response $response) {
global $serv;
if ($request->server['path_info'] == '/favicon.ico' || $request->server['request_uri'] == '/favicon.ico') {
$response->end();
return;
}
$serv->push($request->get['a'],$request->get['b']);
return;
});
$serv->on('Task',function(){
});
$serv->on('finish',function(){
});
$serv->start();
?>
linux服务器下,切到start.php目录,执行 php start.php &
以守护进程方式执行,出现如下,即表示开启9501端口成功
其次是Test.php,路径在extend文件夹下,代码如下
namespace sw;
class Test extends \Swoole\WebSocket\Server
{
public function messaging(\Redis $redis,$frame){
var_dump($frame->data);
$redis->setex($frame->data,1000,$frame->fd);
echo 'sucess-setredis';
}
}
redis存储订单号作为redis的string键值,frame的fd作为值
其次,在微信异步回调结尾处,写上如下方法即可,
$orderid = input('a'); //订单号
$redis = new \Redis();
$redis->connect("127.0.0.1", 6379);
$a = $redis->get($orderid); //此时a为客户端id,可以推送到指定用户
file_get_contents('http://121.37.158.*:9501?a='.$a.'&b='.$orderid);//换成自己的ip,会失败,但是不用理会
其中file_get_contents可以换成自己的curl,更好一点,直接执行会失败,不用管,其实已经推送成功了,
前端js中加入如下方法
var wsObj = new WebSocket("ws://*.*.*.*:9501"); //换成自己的ip
wsObj.onopen = function(){ //发送请求
alert("open");
wsObj.send("a123");
};
wsObj.onmessage = function(ev){ //获取后端响应
//获取到推送的数据,处理业务逻辑,可以进行跳转到成功页面
alert(ev.data);
};
wsObj.onclose = function(ev){
alert("close");
};
wsObj.onerror = function(ev){
alert("error");
};
其中onmessage 处理接收数据。
end:至于为何使用redis,是因为我想用tp5的Db方法,却不知道该如何在Test.php中使用,在Test.php中使用会报错方法不存在,如果你有好的方法可以使用数据库操作,敬请指点。
PS:: 2020-07-01,生活不易,可能说不准哪天就失业了,但是a za a za fighting。