hyperf中使用w7corp/easywechat

本文介绍如何在Swoole框架下集成EasyWeChat SDK,并提供具体步骤来解决协程环境下出现的问题。包括更换HTTP客户端、适配Request对象及使用特定包简化集成流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


EasyWeChat 是一个开源的微信非官方 SDK。安装非常简单,因为它是一个标准的Composer包,这意味着任何满足下列安装条件的 PHP 项目支持Composer都可以使用它。在php-fpm模式下使用是没有任何问题的,但是在swoole框架(例如:hyperf等)的项目中使用就会存在一些问题。

问题:

Swoole框架每个请求都是协程处理的,所以在使用Request对象的使用就会出错。例如Hyperf就有重写的过的Request对象,而EasyWechat4、5版本所用的请求组件为GuzzleHttp包,hyperf官方文档给出了解决方案:
第一步,替换Handler。

<?php

use Hyperf\Utils\ApplicationContext;
use EasyWeChat\Factory;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Hyperf\Guzzle\CoroutineHandler;

$container = ApplicationContext::getContainer();

$app = Factory::officialAccount($config);
$handler = new CoroutineHandler();

// 设置 HttpClient,部分接口直接使用了 http_client。
$config = $app['config']->get('http', []);
$config['handler'] = $stack = HandlerStack::create($handler);
$app->rebind('http_client', new Client($config));

// 部分接口在请求数据时,会根据 guzzle_handler 重置 Handler
$app['guzzle_handler'] = $handler;

// 如果使用的是 OfficialAccount,则还需要设置以下参数
$app->oauth->setGuzzleOptions([
    'http_errors' => false,
    'handler' => $stack,
]);

第二步,将 XML 数据放到 EasyWeChat 的 Request 中。

<?php
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\Request;

$get = $this->request->getQueryParams();
$post = $this->request->getParsedBody();
$cookie = $this->request->getCookieParams();
$uploadFiles = $this->request->getUploadedFiles() ?? [];
$server = $this->request->getServerParams();
$xml = $this->request->getBody()->getContents();
$files = [];
/** @var \Hyperf\HttpMessage\Upload\UploadedFile $v */
foreach ($uploadFiles as $k => $v) {
    $files[$k] = $v->toArray();
}
$request = new Request($get, $post, [], $cookie, $files, $server, $xml);
$request->headers = new HeaderBag($this->request->getHeaders());
$app->rebind('request', $request);
// Do something...

当我们使用easywechat6时,该SDK进行全新的重构,easywechat6用symfony/http-client相关组件,替换了之前4、5版本的GuzzleHttp/Client请求组件,Symfony Http Client在常驻内存的服务中使用时,HttpClient会因为多个协程共用而报错,而pengxuxu/hyperf-easywechat6包使用hyperf的ClassMap替换了InteractWithHttpClient中的HttpClient对象实例,使得不同协程为不同的请求实例,同一协程上下文中获取到的为同一请求实例。而且pengxuxu/hyperf-easywechat6包用hyperf的容器获得Hyperf\HttpServer\Contract\RequestInterface对应的Hyperf\HttpServer\Request,替换了easywechat6中的同样基于PSR-7规范request;获得Psr\SimpleCache\CacheInterface对应的缓存类,替换easywechat6中同样基于PSR-16规范的cache。并且做了兼容处理同时支持hyperf2和hyperf3版本,让用户像在php-fpm模式下一样使用easywechat包进行微信开发。

第一步,安装composer包。

composer require pengxuxu/hyperf-easywechat6 

第二步,注册路由。(注意:一定是 Router::addRoute, 因为微信服务端认证的时候是 GET, 接收用户消息时是 POST !)

Router::addRoute(['GET', 'POST', 'HEAD'], '/wechat', 'App\Controller\WeChatController@serve');

第三步,使用外观,以公众号为例。

<?php
declare(strict_types=1);
namespace App\Controller;
use EasyWeChat\Kernel\Exceptions\BadRequestException;
use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use Pengxuxu\HyperfWechat\EasyWechat;
use Pengxuxu\HyperfWechat\Helper;
use ReflectionException;
class WeChatController
{
    /**
     * 处理微信的请求消息
     *
     * @return string
     * @throws BadRequestException
     * @throws InvalidArgumentException
     * @throws InvalidConfigException
     * @throws ReflectionException
     */
    public function serve()
    {
        $app = EasyWechat::officialAccount();
        
        $server = $app->getServer();
        
        $server->with(function ($message, \Closure $next) {
            return '谢谢关注!';
            
            // 你的自定义逻辑
            // return $next($message);
        });
        // 一定要用Helper::Response去转换
        return Helper::Response($server->serve());
    }
}
### 使用 EasyWechat 实现微信小程序登录 为了实现微信小程序通过 EasyWechat 登录,需先完成必要的准备工作并编写相应的代码逻辑。 #### 准备工作 确保 PHP 版本不低于 8.0 并安装 EasyWechat 库[^2]: ```bash composer require w7corp/easywechat:^6.7 ``` 配置应用参数以便后续调用接口。创建一个包含 `app_id` 和 `secret` 的数组作为配置项,并指定响应类型以及日志级别和文件路径[^3]: ```php $config = [ 'app_id' => 'your_app_id', 'secret' => 'your_secret', 'response_type' => 'array', 'log' => [ 'level' => 'debug', 'file' => __DIR__ . '/wechat.log', ], ]; $app = \EasyWeChat\Factory::miniProgram($config); ``` #### 获取 session_key 及 openid 前端部分采用 Uni-app 开发框架,在页面加载完成后执行 `uni.login()` 方法获取临时登录凭证 `code`,再将其发送给服务器端验证换取 `session_key` 和 `openid`[^5]: ```javascript // 前端uniapp getSessionKey() { var that = this; uni.login({ success(info) { const postData = { code: info.code }; getApp().posturl('Wechat/getSessionKey', postData).then((res) => { that.session_key = res.data.session_key; }); } }); } ``` 服务器接收到请求后利用 EasyWechat 提供的方法解析传入的数据包,从而得到用户的唯一标识符 `openid` 和加密数据解密所需的 `session_key`。 #### 后台处理流程 后台接收来自客户端传递过来的 `code` 参数,之后调用微信开放平台提供的 API 接口来交换获得上述提到的重要信息。具体来说就是使用之前实例化的 `$app` 对象中的 auth 属性下的方法来进行身份认证操作[^4]: ```php $auth = $app->auth; $result = $auth->session($request->input('code')); if ($result instanceof \Symfony\Component\HttpFoundation\Response && !$result->isSuccessful()) { throw new \Exception('Failed to get session key'); } return response()->json([ 'session_key' => $result['session_key'], ]); ``` 以上即为整个基于 EasyWechat SDK 完成的小程序用户登录过程概述。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值