Laravel 使用 EasyWechat 管理多公众号

第一次写专栏文章,如代码规范有错误或者不周全的地方,请社区朋友们指正。如果有更好的方法,请留言给我,谢谢各位大神。

这篇文章旨在Laravel使用EasyWechat扩展进行多公众号管理,具体步骤如下:

  1. 创建公众号参数表
  2. 创建微信控制器
  3. 创建辅助函数
  4. 配置路由
  5. 设置路由忽略

首先我们新建一个Laravel项目,配置好数据库参数,引入Easywechat扩展(在此感谢安正超)

然后创建数据表:

php artisan make:model Wechat -m

来在生成的wechats的migration文件里写入微信相关数据字段:

public function up()
    {
        Schema::create('wechats', function (Blueprint $table) {
            $table->increments('id');
            $table->string('aid')->nullable();

            $table->string('wechat_app_id')->nullable(); //微信公众号设置参数
            $table->string('wechat_secret')->nullable();
            $table->string('wechat_token')->nullable();
            $table->string('wechat_aes_key')->nullable();

            $table->string('pay_mch_id')->nullable();  //微信支付设置参数
            $table->string('pay_api_key')->nullable();
            $table->string('pay_cert_path')->nullable();
            $table->string('pay_key_path')->nullable();

            $table->string('op_app_id')->nullable();  //微信开放平台设置参数
            $table->string('op_secret')->nullable();
            $table->string('op_token')->nullable();
            $table->string('op_aes_key')->nullable();

            $table->string('work_corp_id')->nullable();  //微信企业号设置参数
            $table->string('work_agent_id')->nullable();
            $table->string('work_secret')->nullable();
            $table->timestamps();
        });
    }

接下来在App\Handlers创建一个辅助函数WechatConfigHandler.php文件,代码如下:

<?php

namespace App\Handlers;

use App\Wechat;
use EasyWeChat\Factory;

class WechatConfigHandler
{
    //[1-1]微信公众号设置
    public function app_config($account)
    {
        $wechat = Wechat::where('aid',$account)->first();
        if (!$wechat) {
            return $config = [];
        }
        $config = [
            'app_id'  => $wechat->wechat_app_id,      // AppID
            'secret'  => $wechat->wechat_secret,      // AppSecret
            'token'   => $wechat->wechat_token,       // Token
            'aes_key' => $wechat->wechat_aes_key,     // EncodingAESKey,兼容与安全模式下请一定要填写!!!
            'response_type' => 'array',
            'oauth'   => [
                //'scopes'   => array_map('trim', explode(',', env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_SCOPES', 'snsapi_userinfo'))),
                'scopes'   => 'snsapi_userinfo',
                //'callback' => env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_CALLBACK', '/oauth_callback'),
                'callback' => '/oauth_callback/'.$account,
                ],
            'log' => [
                'level' => 'debug',
                'file' => storage_path('logs/wechat.log'),  //这个必须要有,要不调试有问题,你都会找不到原因
            ],
        ];
        return $config;
    }

    //[1-2]生成微信公众号相关
    public function app($account)
    {
        $app = Factory::officialAccount($this->app_config($account));
        return $app;
    }

    //[2-1]微信支付设置
    public function pay_config($account)
    {
        $wechat = Wechat::where('aid',$account)->first();
        if (!$wechat) {
            return $config = [];
        }
        $config = [
            'app_id'      => $wechat->wechat_app_id,      // AppID
            'secret'      => $wechat->wechat_secret,      // AppSecret
            'mch_id'      => $wechat->pay_mch_id,
            'key'         => $wechat->pay_api_key,   // API 密钥
            // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path'   => $wechat->pay_api_key, // XXX: 绝对路径!!!!
            'key_path'    => $wechat->pay_api_key,      // XXX: 绝对路径!!!!
            'notify_url'  => '默认的订单回调地址',     // 你也可以在下单时单独设置来想覆盖它
        ];
        return $config;
    }

    //[2-2]生成微信支付相关
    public function pay($account)
    {
        $pay = Factory::payment($this->pay_config($account));
        return $pay;
    }

    //[3-1]微信小程序设置
    public function mini_config($account)
    {
        $wechat = Wechat::where('aid',$account)->first();
        if (!$wechat) {
            return $config = [];
        }
        $config = [
            'app_id'  => $wechat->wechat_app_id,         // AppID
            'secret'  => $wechat->wechat_secret,     // AppSecret
            'response_type' => 'array',
        ];
        return $config;
    }

    //[3-2]微信小程序相关
    public function miniProgram($account)
    {
        $miniProgram = Factory::miniProgram($this->mini_config($account));
        return $miniProgram;
    }

    //[4-1]微信开放平台设置参数
    public function opconfig($account)
    {
        $wechat = Wechat::where('aid',$account)->first();
        if (!$wechat) {
            return $config = [];
        }
        $config = [
            'app_id'   => $wechat->op_app_id,
            'secret'   => $wechat->op_secret,
            'token'    => $wechat->op_token,
            'aes_key'  => $wechat->op_aes_key
        ];
        return $config;
    }

    //[4-2]微信开放平台相关
    public function openPlatform($account)
    {
        $openPlatform = Factory::openPlatform($this->opconfig($account));
        return $openPlatform;
    }

    //[5-1]微信企业号设置参数
    public function workconfig($account)
    {
        $wechat = Wechat::where('aid',$account)->first();
        if (!$wechat) {
            return $config = [];
        }
        $config = [
            'corp_id'   => $wechat->work_corp_id,
            'agent_id'   => $wechat->work_agent_id,
            'secret'    => $wechat->work_secret,

            'response_type' => 'array',
        ];
        return $config;

    }

    //[5-2]微信企业号相关
    public function work($account)
    {
        $work = Factory::work($this->workconfig($account));
        return $work;
    }
}

创建一个微信控制器,进行微信公众平台对接:

php artisan make:controller WechatController

写入方法以下方法:

    protected $wechat;

    public function __construct(WechatConfigHandler $wechat)
    {
        $this->wechat = $wechat;
    }

        public function serve($account)
    {
        $app = $this->wechat->app($account);
        $app->server->push(function($message){
            switch ($message['MsgType']) {
                case 'event':
                    if ($message['Event'] == 'subscribe') {
                        return '欢迎关注 Johnson!';
                    }
                    break;
                case 'text':
                    return '收到文字消息';
                    break;
                case 'image':
                    return '收到图片消息';
                    break;
                case 'voice':
                    return '收到语音消息';
                    break;
                case 'video':
                    return '收到视频消息';
                    break;
                case 'location':
                    return '收到坐标消息';
                    break;
                case 'link':
                    return '收到链接消息';
                    break;
                // ... 其它消息
                default:
                    return '收到其它消息';
                    break;
            }
        });
        $response = $app->server->serve();
        return $response;
    }

    public function oauth_callback($account)
    {
        $app = $this->wechat->app($account);
        $user = $app->oauth->user();
        session(['wechat.oauth_user' => $user->toArray()]);
        //不管在哪个页面检测用户登录状态,都要写入session值:target_url
        $targetUrl = session()->has('target_url') ? session('target_url') : '/' ;
        //header('location:'. $targetUrl);
        return redirect()->to($targetUrl);
    }

写到这里,千万别忘了,中间键Middleware文件夹里VerifyCsrfToken.php修改路由忽略:

protected $except = [
        'wechat/*'
    ];

然后在使用的时候,可以这样写:

$app = $this->wechat->app($account);  //公众号
$app = $this->wechat->pay($account);  //微信支付
$app = $this->wechat->miniProgram($account);  //微信小程序
$app = $this->wechat->work($account);  //企业号应用

微信公众平台开发者选项里要设置为:

http://www.xxx.com/wechat/1

其他内容自己配置吧,到这里就结束了。
哦,别忘了配置路由:

Route::any('wechat/{account}','WechatController@serve');
Route::any('/oauth_callback/{account}','WechatController@oauth_callback');

这里wechat/1就是数据库里,aid为1的公众号接入,其他的功能大家可以自行测试,也不知道这样实现是否符合逻辑,再次感谢安正超。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer 于 6年前 加精
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 14
ThinkQ

很好,很实用。

5年前 评论

有个问题哈,由于是不同的公众号,所以在 oAuth 验证的时候,存入 session 的 key 是否也需要进行区分?理论上来说,key应该再加个参数 比如 wechat.oauth_user_1 然后再取 session 的时候就可以区分到底是哪个公众号的那个用户在登录了?

5年前 评论

@VAGH 你的意思是在后台管理公众号的时候,还是前端微信用户登录的时候?

5年前 评论

感谢分享,正好现在需要

5年前 评论

感谢超哥! 还有这篇文章的作者

4年前 评论

路由问题,是不是nginx要做修改

4年前 评论

@时俊 有个细节问题,就是要路由忽略。

file

4年前 评论

csrf 忽略 wechat/* 这么写是可以的?试了不行。
是 wechat 才可以

4年前 评论

@BboyFate 我就是这么写的,测试过了

4年前 评论
hankin

获取用户信息时报错 {"errcode":41008,"errmsg":"missing code, hints: [ req_id: ziKdojwgE-4zLVAA ]"}
是什么参数没填?

4年前 评论
panluo888 4年前
sethhu 3年前

@hankin 是小程序还是公众号!

4年前 评论
hankin

@Johnson16 公众号

4年前 评论

还有这篇文章的作者,感谢超哥!解决我的问题

3年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!