hyperf使用easywechat指南

发表:2年前 更新:2年前
开发 |
2048
| 0

注意:以下操作经过本人在生产环境不完全验证,因为我本身仅仅是一个业务人员,所以涉及到专业的知识性错误欢迎大家补充指正!!!
环境:
1、如果使用的是 hyperf2.x 则 PHP 必须是 8.0.x,因为 hyperf2.x 不支持 8.1 以上,easywechat6.x 不支持 8.0 以下
2、swoole 截止到我测试通过,最新的发布版本 4.8.x 是不支持的,原因是 curl 函数在 swoole 携程化下有 bug,具体的报错可以自行编译测试,总之就是与 easywechat6.x 使用的 symfony/http-client 包中的某些 curl 不兼容,实际上 hyperf 提供了携程的 Guzzle HTTP 客户端但是 easywechat6.x 在调研之初就否定了,参考#2328,然后 6.x 实际上也只封装了核心部分功能,具体业务接口还是需要自己手动写请求,所以如果你 hyperf 非常牛,guzzle 用得也非常 6 完全可以把 6.x 的功能抄过来直接用就好了,这个不在本文的讨论范围。
但是 swoole 的 master 分支编译后可以无缝支持,原因是这些 bug 已经修复了,可以看一下最新的提交记录

已经测试通过的功能:
公众号、开放平台、支付,小程序、企业微信因为业务暂时没有用到暂未测试

原理:跟 5.x 在 hyperf 下使用类似,因为实际上这样的 API 相互调用的 sdk 就是发请求处理响应,而优秀的 easywechat6.x 提供了完全自定义的能力,包括核心的 http 请求客户端,所以你完全可以根据自己的实际需求来替换,当前全都换了她就不是那个她了,哈哈 ~
客户端:es6.x 要求是实现了 Symfony\Contracts\HttpClient\HttpClientInterface 接口的,所以如果你无法升级 swoole 的版本,可以通过替换客户端的方式实现,写一个实现这个接口的类,奈何我不会,幸好 swoole5.x 已经兼容了所以本步骤跳过
请求:hyperf 的请求类跟 es6.x 要求的请求类是实现了同一套接口的,可以直接替换使用且必须替换,否则 es6.x 拿不到请求参数
缓存:hyperf 的缓存同样跟 es6.x 要求的缓存类是实现同一套接口的,可直接使用,建议替换,默认的文件缓存根据 5.x 的经验隔一段时间或者并发较大的情况下或造成缓存错误的问题。

开放平台:

<?php

// $platformModel 是开放平台模型类,简单来说是从数据库中取出来的,如果用配置文件也可以
public function initApplication(PlatformModel $platformModel)
    {
        // 实例化应用
        $application = make(Application::class, [[
            'app_id' => $platformModel->app_id,
            'secret' => $platformModel->app_secret,
            'token' => $platformModel->app_token,
            'aes_key' => $platformModel->app_key
        ]]);

        // region 替换请求[必须替换] +++++
        $request = ApplicationContext::getContainer()->get(RequestInterface::class);
        $application->setRequest($request);
        // endregion

        // region 替换缓存[可选,建议替换] +++++
        $cache = ApplicationContext::getContainer()->get(CacheInterface::class);
        $application->setCache($cache);
        // endregion

        return $application;
    }

开放平台代公众号实现业务,这步操作必须要有,原因是开放平台也需要去兑换公众号的应用实例,所以兑换出来的实例也需要替换响应的请求,以下可供参考,需要根据自己的业务修改。

<?php 

public function getOfficialApplication(AuthorizeModel $authorizeModel): \EasyWeChat\OfficialAccount\Application
    {
        $platformModel = $authorizeModel->platform;
        $platformApplication = $this->initApplication($platformModel);
        $cache = ApplicationContext::getContainer()->get(CacheInterface::class);
        $cacheName = md5($platformModel->id.'_'.$authorizeModel->app_id.'_authorizer_access_token');
        $authorizerAccessToken = $cache->get($cacheName, '');
        if (!$authorizerAccessToken) {
            $refreshAuthorizerToken = $platformApplication->refreshAuthorizerToken($authorizeModel->app_id, $authorizeModel->refresh_token);
            $authorizerAccessToken = $refreshAuthorizerToken['authorizer_access_token'];
            // 写入缓存
            $cache->set($cacheName, $authorizerAccessToken, $refreshAuthorizerToken['expires_in']);
        }
        $officialAccessToken = make(AuthorizerAccessToken::class, [$authorizeModel->app_id, $authorizerAccessToken]);
        // 公众号应用
        $officialApplication = $platformApplication->getOfficialAccount($officialAccessToken);
        // region 替换请求 +++++
        $request = ApplicationContext::getContainer()->get(RequestInterface::class);
        $officialApplication->setRequest($request);
        // endregion
        // region 替换缓存 +++++
        $officialApplication->setCache($cache);
        // endregion
        // 设置客户端
        $officialApplication->setClient($platformApplication->getClient());
        // var_dump($officialApplication->getAccessToken());
        // $client = $officialApplication->createClient();
        // $officialApplication->setClient($client);
        return $officialApplication;
    }

公众号:这是直接使用公众号后台配置接口的情况,为了兼容,写了开放平台的东西,如果你完全没用开放平台可以直接替换请求合缓存就能用。

<?php

public function initApplication(OfficialModel $officialModel, PlatformModel $platformModel = null)
    {
        $authorizeModel = null;
        // 如指定开放平台或公众号自身缺少必要属性则尝试开放平台实例
        if ($platformModel || !$officialModel->app_secret || !$officialModel->app_token) {
            if ($platformModel) {
                $authorizeModel = $this->authorizeService->model->where([
                    ['platform_id', '=', $platformModel->id],
                    ['app_id', '=', $officialModel->app_id]
                ])->firstOrFail();
            } else {
                $authorizeModel = $this->authorizeService->model->where([
                    ['app_id', '=', $officialModel->app_id]
                ])->firstOrFail();
            }
        }
        if ($authorizeModel instanceof AuthorizeModel) {
            return $this->platformService->getOfficialApplication($authorizeModel);
        }
        // 实例化应用
        $application = make(Application::class, [[
            'app_id' => $officialModel->app_id,
            'secret' => $officialModel->app_secret,
            'token' => $officialModel->app_token,
            'aes_key' => $officialModel->app_key,
        ]]);

        // region 替换请求[必须替换] +++++
        $request = ApplicationContext::getContainer()->get(RequestInterface::class);
        $application->setRequest($request);
        // endregion

        // region 替换缓存[可选,建议替换] +++++
        $cache = ApplicationContext::getContainer()->get(CacheInterface::class);
        $application->setCache($cache);
        // endregion

        return $application;
    }

支付:支付仅测试通过 v2,暂未测试 v3,如有问题我会补充

<?php
public function initApplication(MerchantModel $merchantModel)
    {
        $application = make(Application::class, [[
            // 商户号
            'mch_id' => $merchantModel->mch_id,
            // 商户证书
            'certificate' => BASE_PATH.'/cert/'.$merchantModel->mch_id.'/apiclient_cert.pem',
            'private_key' => BASE_PATH.'/cert/'.$merchantModel->mch_id.'/apiclient_key.pem',
            // v2 API 密钥
            'v2_secret_key' => $merchantModel->pay_key,
            // v3 API 密钥
            'secret_key' => $merchantModel->v3_pay_key,

        ]]);

        // region 替换请求 +++++
        $request = ApplicationContext::getContainer()->get(RequestInterface::class);
        $server = make(Server::class, [
            $application->getMerchant(),
            $request
        ]);
        $application->setServer($server);
        // endregion

        return $application;
    }

转:https://github.com/w7corp/easywechat/issues/2328

signature
保持理智
评论

无权限

请登录后评论

RunPod公众号

赞助商

联系我们

QQ群:798695907

邮箱:laravel@88.com