快速開始
在我們已經(jīng)成功安裝完成 EasySwoole WeChat SDK
組件后,就可以很快地開始使用它了,當(dāng)然你還是有必要明白 PHP
的基本知識,如命名空間等,我這里就不贅述了。
接下來我們以完成 服務(wù)器端驗(yàn)證
與 接收響應(yīng)用戶發(fā)送的消息
為例來演示,首先我們有必要先了解一下微信交互的運(yùn)行流程:
具體交互流程如下:
+-----------------+ +---------------+
+----------+ | | POST/GET/PUT | |
| | ------------------> | | -------------------> | |
| user | | wechat server | | your server |
| | < - - - - - - - - - | | | |
+----------+ | | <- - - - - - - - - - | |
+-----------------+ +---------------+
其實(shí)我們要做的就是圖中 微信服務(wù)器把用戶消息轉(zhuǎn)到我們的自有服務(wù)器(虛線返回部分) 后的處理過程。
服務(wù)端驗(yàn)證
在微信接入開始有一個 "服務(wù)器驗(yàn)證" 的過程,這一步其實(shí)就是 微信服務(wù)器 向 我們服務(wù)器 發(fā)起一個請求(上圖實(shí)線部分),傳了一個名稱為 echostr
的字符串過來,我們只需要原樣返回就好了。
作為開發(fā)者,你應(yīng)該知道,微信后臺只能填寫一個服務(wù)器地址,所以 服務(wù)器驗(yàn)證 與 消息的接收與回復(fù),都在這一個鏈接內(nèi)完成交互。
考慮到這些,我們已經(jīng)把驗(yàn)證這一步給封裝到 SDK
里了,你可以完全忽略這一步。
下面我們來配置一個基本的服務(wù)端,這里假設(shè)我們自己的服務(wù)器域名叫 easyswoolewechat.com
,并且我們在服務(wù)端已經(jīng)安裝好了一個 EasySwoole
框架,或者我們在服務(wù)器上準(zhǔn)備一個文件 server.php
(使用原生 Swoole
實(shí)現(xiàn),下文只提供偽代碼)。
使用 EasySwoole
框架配置服務(wù)端驗(yàn)證
以下為了演示,我們只在 App\HttpController\Index
控制器類下進(jìn)行編碼實(shí)現(xiàn)配置服務(wù)端驗(yàn)證,用戶可自行選擇其他控制器類進(jìn)行編碼實(shí)現(xiàn)。
在服務(wù)器的 EasySwoole
框架的 HTTP
服務(wù)的 控制器
中來配置一個基本的服務(wù)端:
配置主服務(wù)為 HTTP
服務(wù),然后我們可以在 App\HttpController\Index
控制器類下編寫 server
方法,編寫如下代碼實(shí)現(xiàn)服務(wù)端驗(yàn)證:
<?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() 表示啟用請求驗(yàn)證,以確保請求來自微信發(fā)送。默認(rèn)不啟用驗(yàn)證
* serve() 會解析本次請求后回調(diào)之前注冊的事件(包括 AES 解密和解析 XML)
* serve() 接受一個顯式實(shí)現(xiàn)了 \Psr\Http\Message\ServerRequestInterface 的 request 對象
*/
$replyResponse = $server->forceValidate()->serve($psr7Request);
/**
* $replyResponse 是一個顯式實(shí)現(xiàn)了 PSR-7 的對象,用戶只需要處理該對象即可正確響應(yīng)給微信
* 下面是一個使用 EasySwoole 的響應(yīng)方法
*/
$this->response()->withStatus($replyResponse->getStatusCode());
/**
* PSR-7 的 Header 并不是單純的 k => v 結(jié)構(gòu)
*/
foreach ($replyResponse->getHeaders() as $name => $values) {
$this->response()->withHeader($name, implode(", ", $values));
}
$this->response()->write($replyResponse->getBody()->__toString());
}
}
使用原生 Swoole
配置服務(wù)端驗(yàn)證
server.php
的實(shí)現(xiàn)形式我就以原生 Swoole
的 http_server
來啟動一個服務(wù),偽代碼內(nèi)容如下:
<?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;
// 此處為實(shí)現(xiàn)了 \Psr\Http\Message\ServerRequestInterface 的 request 對象
/** @var \Psr\Http\Message\ServerRequestInterface $psr7Request */
$psr7Request = new XxxReuest($request); // 偽代碼
/**
* @var \Psr\Http\Message\ResponseInterface $replyResponse
* forceValidate() 表示啟用請求驗(yàn)證,以確保請求來自微信發(fā)送。默認(rèn)不啟用驗(yàn)證
* serve() 會解析本次請求后回調(diào)之前注冊的事件(包括 AES 解密和解析 XML)
* serve() 接受一個顯式實(shí)現(xiàn)了 \Psr\Http\Message\ServerRequestInterface 的 request 對象
*/
$replyResponse = $server->forceValidate()->serve($psr7Request);
/**
* $replyResponse 是一個顯式實(shí)現(xiàn)了 PSR-7 的對象,用戶只需要處理該對象即可正確響應(yīng)給微信
* 下面是一個原生 swoole 的響應(yīng)方法
*/
$response->status($replyResponse->getStatusCode());
/**
* PSR-7 的 Header 并不是單純的 k => v 結(jié)構(gòu)
*/
foreach ($replyResponse->getHeaders() as $name => $values) {
$response->header($name, implode(", ", $values));
}
// 將響應(yīng)輸出到客戶端
$response->write($replyResponse->getBody()->__toString());
});
$http->start();
上述
$psr7Request
請用戶參考 PSR-7 標(biāo)準(zhǔn)自行實(shí)現(xiàn)Psr\Http\Message\ServerRequestInterface
接口。
注意:安全模式下請一定要配置 aesKey
。
很簡單,一個服務(wù)端帶驗(yàn)證功能的代碼已經(jīng)完成,當(dāng)然我們沒有對消息做處理,別著急,后面我們再講。
我們先來分析上面的代碼:
<?php
// 引入我們的主項目工廠類
use EasySwoole\WeChat\Factory;
// 一些配置
$config = [...];
// 使用配置來初始化一個公眾號應(yīng)用實(shí)例
$officialAccount = Factory::officialAccount($config);
// 得到一個 Server\Guard $server 實(shí)例
$server = $officialAccount->server;
// 構(gòu)造 實(shí)現(xiàn)了 \Psr\Http\Message\ServerRequestInterface 的 request 對象
// 此處為實(shí)現(xiàn)了 \Psr\Http\Message\ServerRequestInterface 的 request 對象
/** @var \Psr\Http\Message\ServerRequestInterface $psr7Request */
$psr7Request = new XxxReuest($request); // 偽代碼
// 得到一個實(shí)現(xiàn)了 `Psr\Http\Message\ResponseInterface` 接口的 response 響應(yīng)實(shí)例對象
$replyReponse = $server->forceValidate()->serve($psr7Request);
### 構(gòu)建 Swoole 響應(yīng)給到客戶端
// 設(shè)置響應(yīng) HTTP 狀態(tài)碼
$response->status($replyResponse->getStatusCode());
// 設(shè)置響應(yīng)頭 Header
foreach ($replyResponse->getHeaders() as $name => $values) {
$response->header($name, implode(", ", $values));
}
// 將響應(yīng)輸出到客戶端
$response->write($replyResponse->getBody()->__toString());
最后這一行我有必要詳細(xì)講一下:
- 我們的
$server->forceValidate()->serve($psr7Request);
就是執(zhí)行服務(wù)端業(yè)務(wù)了,那么它的返回值是一個實(shí)現(xiàn)了Psr\Http\Message\ResponseInterface
接口的實(shí)例對象。 - 我這里是直接調(diào)用了
Swoole
原生的響應(yīng)方法write()
。在一些的Swoole
相關(guān)的框架中,你可以直接拿到$replyResponse
實(shí)例對象進(jìn)行相關(guān)的操作,然后輸出到客戶端即可。在EasySwoole
中,可以直接使用上文示例的方法操作即可輸出到客戶端。
OK,有了上面的代碼,那么請你按 微信官方的接入指引 在公眾號后臺完成配置并啟用,并相應(yīng)修改上面的 $config
的相關(guān)配置。
URL
就是我們的 http://easyswoolewechat.com/server
,這里我是舉例哦,你可不要填寫我的域名。由于我使用的是 Swoole
的 9501
端口提供服務(wù),請用戶自行進(jìn)行反向代理配置,具體如何配置反向代理請看 EasySwoole 反向代理。
請一定要將微信后臺的開發(fā)者模式 ”啟用” !!!!!!看到紅色 “停用” 才真正的是啟用了。最后,請不要用瀏覽器訪問這個地址,它是給微信服務(wù)器訪問的,不是給人訪問的。
接收 & 回復(fù)用戶消息
上述完成服務(wù)端驗(yàn)證通過后,接下來我們就來試一下接收消息吧。
在剛剛上文代碼最后一行使用 $this->response()->write($replyResponse->getBody()->__toString());
(在 EasySwoole
框架中響應(yīng)) 或 使用 $response->write($replyResponse->getBody()->__toString());
(原生 Swoole
響應(yīng)); 在前面,現(xiàn)在我們調(diào)用 $officialAccount->server
的 push()
方法來注冊一個消息處理器,這里用到了 PHP 閉包
的知識,如果你不熟悉趕緊補(bǔ)課去。
EasySwoole
中App\HttpController\Index.php
實(shí)現(xiàn):
<?php
namespace App\HttpController;
use EasySwoole\Http\AbstractInterface\Controller;
use EasySwoole\WeChat\Factory;
class Index extends Controller
{
public function server()
{
// 這里省略
$server = $officialAccount->server;
/** 注冊消息事件回調(diào) */
$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));
}
// 將響應(yīng)輸出到客戶端
$this->response()->write($replyResponse->getBody()->__toString());
}
}
原生
Swoole
中單獨(dú)實(shí)現(xiàn)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;
/** 注冊消息事件回調(diào) */
$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));
}
// 將響應(yīng)輸出
$response->write($replyResponse->getBody()->__toString());
});
// 這里省略
OK,打開你的微信客戶端,向你的公眾號發(fā)送任意一條消息,你應(yīng)該會收到回復(fù):您好!歡迎使用 EasySwoole WeChat!
。
如果您沒有收到回復(fù),但是看到了 “你的公眾號暫時無法提供服務(wù)”,好,那檢查一下你的日志吧,日志在哪兒?我們的配置里寫了日志路徑了(sys_get_temp_dir() . '/wechat.log'
)。沒有這個文件?看看權(quán)限。
一個基本的服務(wù)端驗(yàn)證就完成了。
總結(jié)
所有的應(yīng)用服務(wù)都通過主入口 EasySwoole\WeChat\Factory
類來創(chuàng)建:
<?php
use EasySwoole\WeChat\Factory;
// 公眾號
$officialAccount = Factory::officialAccount($config);
// 小程序
$miniProgram = Factory::miniProgram($config);
// 開放平臺
$openPlatform = Factory::openPlatform($config);
// 企業(yè)微信
$work = Factory::work($config);
最后
希望您在使用本 SDK
的時候如果您發(fā)現(xiàn) SDK
的不足,歡迎提交 PR
或者給我們 提建議 & 報告問題。