快速开始

在我们已经成功安装完成 EasySwoole WeChat SDK 组件后,就可以很快地开始使用它了,当然你还是有必要明白 PHP 的基本知识,如命名空间等,我这里就不赘述了。

接下来我们以完成 服务器端验证接收响应用户发送的消息 为例来演示,首先我们有必要先了解一下微信交互的运行流程:

具体交互流程如下:

                                 +-----------------+                       +---------------+
+----------+                     |                 |    POST/GET/PUT       |               |
|          | ------------------> |                 | ------------------->  |               |
|   user   |                     |  wechat server  |                       |  your server  |
|          | < - - - - - - - - - |                 |                       |               |
+----------+                     |                 | <- - - - - - - - - -  |               |
                                 +-----------------+                       +---------------+

其实我们要做的就是图中 微信服务器把用户消息转到我们的自有服务器(虚线返回部分) 后的处理过程。

服务端验证

在微信接入开始有一个 "服务器验证" 的过程,这一步其实就是 微信服务器我们服务器 发起一个请求(上图实线部分),传了一个名称为 echostr 的字符串过来,我们只需要原样返回就好了。

作为开发者,你应该知道,微信后台只能填写一个服务器地址,所以 服务器验证消息的接收与回复,都在这一个链接内完成交互。

考虑到这些,我们已经把验证这一步给封装到 SDK 里了,你可以完全忽略这一步。

下面我们来配置一个基本的服务端,这里假设我们自己的服务器域名叫 easyswoolewechat.com,并且我们在服务端已经安装好了一个 EasySwoole 框架,或者我们在服务器上准备一个文件 server.php(使用原生 Swoole 实现,下文只提供伪代码)。

使用 EasySwoole 框架配置服务端验证

以下为了演示,我们只在 App\HttpController\Index 控制器类下进行编码实现配置服务端验证,用户可自行选择其他控制器类进行编码实现。

在服务器的 EasySwoole 框架的 HTTP 服务的 控制器 中来配置一个基本的服务端:

配置主服务为 HTTP 服务,然后我们可以在 App\HttpController\Index 控制器类下编写 server 方法,编写如下代码实现服务端验证:

<?php

namespace App\HttpController;

use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\WeChat\Factory;

class Index extends Controller
{
    public function server()
    {
        $config = [
            // 微信公众平台后台的 appid
            'appId' => 'wxefe41fdeexxxxxx',

            // 微信公众平台后台配置的 Token
            'token' => 'dczmnau31ea9nzcnxxxxxxxxx',

            // 微信公众平台后台配置的 EncodingAESKey
            'aesKey' => 'easyswoole'
        ];

        $officialAccount = Factory::officialAccount($config);

        $server = $officialAccount->server;

        /** @var \Psr\Http\Message\ServerRequestInterface $psr7Request */
        $psr7Request = $this->request();

        /**
         * @var \Psr\Http\Message\ResponseInterface $replyResponse
         * forceValidate() 表示启用请求验证,以确保请求来自微信发送。默认不启用验证
         * serve() 会解析本次请求后回调之前注册的事件(包括 AES 解密和解析 XML)
         * serve() 接受一个显式实现了 \Psr\Http\Message\ServerRequestInterface 的 request 对象
         */
        $replyResponse = $server->forceValidate()->serve($psr7Request);

        /**
         * $replyResponse 是一个显式实现了 PSR-7 的对象,用户只需要处理该对象即可正确响应给微信
         * 下面是一个原生swoole的响应方法
         */
        $this->response()->withStatus($replyResponse->getStatusCode());

        /**
         * PSR-7 的 Header 并不是单纯的 k => v 结构
         */
        foreach ($replyResponse->getHeaders() as $name => $values) {
            $this->response()->withHeader($name, implode(", ", $values));
        }

        $this->response()->write($replyResponse->getBody()->__toString());
    }
}

使用原生 Swoole 配置服务端验证

server.php 的实现形式我就以原生 Swoolehttp_server 来启动一个服务,伪代码内容如下:

<?php

use EasySwoole\WeChat\Factory;

require_once __DIR__ . '/vendor/autoload.php';

$http = new Swoole\Http\Server('0.0.0.0', 9501);

$http->on('request', function (\Swoole\Http\Request $request, \Swoole\Http\Response $response) {

    $config = [
        // 微信公众平台后台的 appid
        'appId' => 'wxefe41fdeexxxxxx',

        // 微信公众平台后台配置的 Token
        'token' => 'dczmnau31ea9nzcnxxxxxxxxx',

        // 微信公众平台后台配置的 EncodingAESKey
        'aesKey' => 'easyswoole'
    ];

    $officialAccount = Factory::officialAccount($config);

    $server = $officialAccount->server;

    // 此处为实现了 \Psr\Http\Message\ServerRequestInterface 的 request 对象
    /** @var \Psr\Http\Message\ServerRequestInterface $psr7Request  */
    $psr7Request = new XxxReuest($request); // 伪代码

    /**
     * @var \Psr\Http\Message\ResponseInterface $replyResponse
     * forceValidate() 表示启用请求验证,以确保请求来自微信发送。默认不启用验证
     * serve() 会解析本次请求后回调之前注册的事件(包括 AES 解密和解析 XML)
     * serve() 接受一个显式实现了 \Psr\Http\Message\ServerRequestInterface 的 request 对象
     */
    $replyResponse = $server->forceValidate()->serve($psr7Request);

    /**
     * $replyResponse 是一个显式实现了 PSR-7 的对象,用户只需要处理该对象即可正确响应给微信
     * 下面是一个原生 swoole 的响应方法
     */
    $response->status($replyResponse->getStatusCode());

    /**
     * PSR-7 的 Header 并不是单纯的 k => v 结构
     */
    foreach ($replyResponse->getHeaders() as $name => $values) {
        $response->header($name, implode(", ", $values));
    }

    // 将响应输出到客户端
    $response->write($replyResponse->getBody()->__toString());
});

$http->start();

上述 $psr7Request 请用户参考 PSR-7 标准自行实现 Psr\Http\Message\ServerRequestInterface 接口。

注意:安全模式下请一定要配置 aesKey

很简单,一个服务端带验证功能的代码已经完成,当然我们没有对消息做处理,别着急,后面我们再讲。

我们先来分析上面的代码:

<?php

// 引入我们的主项目工厂类
use EasySwoole\WeChat\Factory;

// 一些配置
$config = [...];

// 使用配置来初始化一个公众号应用实例
$officialAccount = Factory::officialAccount($config);

// 得到一个 Server\Guard $server 实例
$server = $officialAccount->server;

// 构造 实现了 \Psr\Http\Message\ServerRequestInterface 的 request 对象
// 此处为实现了 \Psr\Http\Message\ServerRequestInterface 的 request 对象
/** @var \Psr\Http\Message\ServerRequestInterface $psr7Request  */
$psr7Request = new XxxReuest($request); // 伪代码

// 得到一个实现了 `Psr\Http\Message\ResponseInterface` 接口的 response 响应实例对象
$replyReponse = $server->forceValidate()->serve($psr7Request);

### 构建 Swoole 响应给到客户端
// 设置响应 HTTP 状态码
$response->status($replyResponse->getStatusCode());
// 设置响应头 Header
foreach ($replyResponse->getHeaders() as $name => $values) {
    $response->header($name, implode(", ", $values));
}
// 将响应输出到客户端
$response->write($replyResponse->getBody()->__toString());

最后这一行我有必要详细讲一下:

  • 我们的 $server->forceValidate()->serve($psr7Request); 就是执行服务端业务了,那么它的返回值是一个实现了 Psr\Http\Message\ResponseInterface 接口的实例对象。
  • 我这里是直接调用了 Swoole 原生的响应方法 write()。在一些的 Swoole 相关的框架中,你可以直接拿到 $replyResponse 实例对象进行相关的操作,然后输出到客户端即可。在 EasySwoole 中,可以直接使用上文示例的方法操作即可输出到客户端。

OK,有了上面的代码,那么请你按 微信官方的接入指引 在公众号后台完成配置并启用,并相应修改上面的 $config 的相关配置。

URL 就是我们的 http://easyswoolewechat.com/server,这里我是举例哦,你可不要填写我的域名。由于我使用的是 Swoole9501 端口提供服务,请用户自行进行反向代理配置,具体如何配置反向代理请看 EasySwoole 反向代理

请一定要将微信后台的开发者模式 ”启用” !!!!!!看到红色 “停用” 才真正的是启用了。最后,请不要用浏览器访问这个地址,它是给微信服务器访问的,不是给人访问的。

接收 & 回复用户消息

上述完成服务端验证通过后,接下来我们就来试一下接收消息吧。

在刚刚上文代码最后一行使用 $this->response()->write($replyResponse->getBody()->__toString()); (在 EasySwoole 框架中响应) 或 使用 $response->write($replyResponse->getBody()->__toString()); (原生 Swoole 响应); 在前面,现在我们调用 $officialAccount->serverpush() 方法来注册一个消息处理器,这里用到了 PHP 闭包 的知识,如果你不熟悉赶紧补课去。

EasySwooleApp\HttpController\Index.php 实现:

<?php

namespace App\HttpController;

use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\WeChat\Factory;

class Index extends Controller
{

    public function server()
    {
        // 这里省略 

        $server = $officialAccount->server;

        /** 注册消息事件回调 */
        $server->push(function (\EasySwoole\WeChat\Kernel\Contracts\MessageInterface $message) {
            return new \EasySwoole\WeChat\Kernel\Messages\Text("您好!欢迎使用 EasySwoole WeChat!");
        });

        $psr7Request = $this->request();
        /** @var \Psr\Http\Message\ResponseInterface $replyResponse */
        $replyResponse = $server->forceValidate()->serve($psr7Request);

        $this->response()->withStatus($replyResponse->getStatusCode());
        foreach ($replyResponse->getHeaders() as $name => $values) {
            $this->response()->withHeader($name, implode(", ", $values));
        }

        // 将响应输出到客户端
        $this->response()->write($replyResponse->getBody()->__toString());
    }
}

原生 Swoole 中单独实现 server.php

<?php

use EasySwoole\WeChat\Factory;

require_once __DIR__ . '/vendor/autoload.php';

// 这里省略

$http->on('request', function (\Swoole\Http\Request $request, \Swoole\Http\Response $response) {

    // 这里省略

    $server = $officialAccount->server;

    /** 注册消息事件回调 */
    $server->push(function (\EasySwoole\WeChat\Kernel\Contracts\MessageInterface $message) {
        return new \EasySwoole\WeChat\Kernel\Messages\Text("您好!欢迎使用 EasySwoole WeChat!");
    });

    /** @var \Psr\Http\Message\ServerRequestInterface $psr7Request  */
    $psr7Request = new XxxReuest($request); // 伪代码

    $replyResponse = $server->forceValidate()->serve($psr7Request);
    $response->status($replyResponse->getStatusCode());
    foreach ($replyResponse->getHeaders() as $name => $values) {
        $response->header($name, implode(", ", $values));
    }

    // 将响应输出
    $response->write($replyResponse->getBody()->__toString());
});

// 这里省略

OK,打开你的微信客户端,向你的公众号发送任意一条消息,你应该会收到回复:您好!欢迎使用 EasySwoole WeChat!

如果您没有收到回复,但是看到了 “你的公众号暂时无法提供服务”,好,那检查一下你的日志吧,日志在哪儿?我们的配置里写了日志路径了(sys_get_temp_dir() . '/wechat.log')。没有这个文件?看看权限。

一个基本的服务端验证就完成了。

总结

所有的应用服务都通过主入口 EasySwoole\WeChat\Factory 类来创建:

<?php

use EasySwoole\WeChat\Factory;

// 公众号
$officialAccount = Factory::officialAccount($config);

// 小程序
$miniProgram = Factory::miniProgram($config);

// 开放平台
$openPlatform = Factory::openPlatform($config);

// 企业微信
$work = Factory::work($config);

最后

希望您在使用本 SDK 的时候如果您发现 SDK 的不足,欢迎提交 PR 或者给我们 提建议 & 报告问题