在 Linux 配置基于 Laravel 的小程序开发环境

在 Linux 配置基于 Laravel 的小程序开发环境

安装环境

任务时间:5min ~ 10min

更新操作系统

首先,我们需要更新我们的操作系统,让我们的云主机处在最新的状态。执行如下命令

yum update -y

安装 Apache 、 PHP 、 MySQL

完成了系统的更新后,我们来配置服务器端的 LAMP(Linux、Apache、MySQL、PHP)环境,让我们的 Laravel 可以在云端运行。

安装 Apache

首先,我们来安装 Apache ,执行如下命令:

yum -y install httpd

稍等片刻后,安装完成,执行如下命令来启动 Apache 服务,并配置开机自启动

systemctl start httpd.service
systemctl enable httpd.service

这时,你可以执行如下命令来检测你的 Apache 是否正常工作

curl <您的 CVM IP 地址>

安装 MySQL

接下来,来执行命令配置 MySQL 环境

yum -y install mariadb-server mariadb

稍等片刻后,安装完成,执行如下命令启动 Mariadb

systemctl start mariadb

然后执行如下命令来进行数据库的初始化

mysql_secure_installation

执行命令后,会让你输入默认的用户名,这里默认为空,直接回车即可,

提示设置 Root 密码时,选择 Y ,并输入 Root 密码,确认。

提示移除匿名用户时,选择 Y

提示关闭远程的 root 登录时,选择 Y

提示删除测试数据库时,选择 Y

提示刷新权限数据库时,选择 Y

这样,我们就完成了 MySQL 数据库的安全初始化了。

然后,执行如下命令,让 MySQL 开机自启动

systemctl start mariadb

安装 PHP 7

接下来,我们来安装 PHP 7 ,这里我们需要借助 webtatic 库编译的源码。

执行如下命令,来安装 webtatic 库

yum -y install epel-release
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

稍等片刻,安装完成后,我们可以执行命令来安装 PHP7

yum install -y php70w php70w-opcache php70w-mysql  php70w-mcrypt php70w-dom php70w-mbstring unzip

稍等片刻,模块就安装完成了,我们重启一下 Apache

systemctl restart httpd

安装 Composer

Laravel 使用 Composer 来管理依赖,所以,我们需要在我们的服务端配置上 Composer .执行如下命令,来安装 Composer

curl -k -sS https://getcomposer.org/installer | php
echo $PATH
mv composer.phar /usr/local/bin/composer

安装完成后,执行如下命令,切换为国内镜像,加速后续依赖的下载

composer config -g repo.packagist composer https://packagist.laravel-china.org

安装 Laravel

任务时间:5min ~ 10min

初始化项目

接下来,我们在 Apache 的根目录中创建一个 Laravel 项目

cd /var/www/html
composer create-project --prefer-dist laravel/laravel ./
chown apache:apache -R /var/www/html

执行完成命令后,会自动在当前目录的根目录中看到各文件。此时,可以访问 http://<您的 CVM IP 地址>/public 查看默认首页。

移除默认的 /public

我们在访问时,有一个 public 的前缀,非常不好看,我们希望可以去除这个前缀。

参考下面的配置文件,创建你的虚拟主机配置文件(/etc/httpd/conf.d/laravel.conf)

示例代码:/etc/httpd/conf.d/laravel.conf
<VirtualHost *:80>
    DocumentRoot /var/www/html/public
    ServerName <您的 CVM IP 地址>

    <Directory /var/www/html/>
        AllowOverride All
    </Directory>
</VirtualHost>

保存完成后,重启 Apache .

systemctl restart httpd

然后,就可以访问 http://<您的 CVM IP 地址> 查看 Laravel 的默认页面了。

链接微信

任务时间:15min ~ 20min

引入 EasyWeChat

这里,我们使用 EasyWeChat 作为我们的微信框架,进入到我们的项目根目录,执行如下命令来安装 EasyWeChat

cd /var/www/html/
composer require "overtrue/laravel-wechat:~4.0"

稍等片刻,执行完成后,执行如下命令

php artisan vendor:publish --provider="OvertrueLaravelWeChatServiceProvider"

会自动生成 config/wechat.php ,接下来,我们来编辑这个文件,将其中代码改为如下所示(取消小程序部分和微信支付部分的注释)。

<?php

/*
 * This file is part of the overtrue/laravel-wechat.
 *
 * (c) overtrue <i@overtrue.me>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

return [
    /*
     * 默认配置,将会合并到各模块中
     */
    'defaults' => [
        /*
         * 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
         */
        'response_type' => 'array',

        /*
         * 使用 Laravel 的缓存系统
         */
        'use_laravel_cache' => true,

        /*
         * 日志配置
         *
         * level: 日志级别,可选为:
         *                 debug/info/notice/warning/error/critical/alert/emergency
         * file:日志文件位置(绝对路径!!!),要求可写权限
         */
        'log' => [
            'level' => env('WECHAT_LOG_LEVEL', 'debug'),
            'file' => env('WECHAT_LOG_FILE', storage_path('logs/wechat.log')),
        ],
    ],

    /*
     * 路由配置
     */
    'route' => [
        /*
         * 开放平台第三方平台路由配置
         */
        // 'open_platform' => [
        //     'uri' => 'serve',
        //     'action' => OvertrueLaravelWeChatControllersOpenPlatformController::class,
        //     'attributes' => [
        //         'prefix' => 'open-platform',
        //         'middleware' => null,
        //     ],
        // ],
    ],

    /*
     * 公众号
     */
    'official_account' => [
        'default' => [
            'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', 'your-app-id'),         // AppID
            'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', 'your-app-secret'),    // AppSecret
            'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', 'your-token'),           // Token
            'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', ''),                 // EncodingAESKey

            /*
             * OAuth 配置
             *
             * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
             * callback:OAuth授权完成后的回调页地址(如果使用中间件,则随便填写。。。)
             */
            // 'oauth' => [
            //     'scopes'   => array_map('trim', explode(',', env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_SCOPES', 'snsapi_userinfo'))),
            //     'callback' => env('WECHAT_OFFICIAL_ACCOUNT_OAUTH_CALLBACK', '/examples/oauth_callback.php'),
            // ],
        ],
    ],

    /*
     * 开放平台第三方平台
     */
    // 'open_platform' => [
    //     'default' => [
    //         'app_id'  => env('WECHAT_OPEN_PLATFORM_APPID', ''),
    //         'secret'  => env('WECHAT_OPEN_PLATFORM_SECRET', ''),
    //         'token'   => env('WECHAT_OPEN_PLATFORM_TOKEN', ''),
    //         'aes_key' => env('WECHAT_OPEN_PLATFORM_AES_KEY', ''),
    //     ],
    // ],

    /*
     * 小程序
     */
    'mini_program' => [
        'default' => [
            'app_id'  => env('WECHAT_MINI_PROGRAM_APPID', ''),
            'secret'  => env('WECHAT_MINI_PROGRAM_SECRET', ''),
            'token'   => env('WECHAT_MINI_PROGRAM_TOKEN', ''),
            'aes_key' => env('WECHAT_MINI_PROGRAM_AES_KEY', ''),
        ],
    ],

    /*
     * 微信支付
     */
    'payment' => [
        'default' => [
            'sandbox'            => env('WECHAT_PAYMENT_SANDBOX', false),
            'app_id'             => env('WECHAT_PAYMENT_APPID', ''),
            'mch_id'             => env('WECHAT_PAYMENT_MCH_ID', 'your-mch-id'),
            'key'                => env('WECHAT_PAYMENT_KEY', 'key-for-signature'),
            'cert_path'          => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'),    // XXX: 绝对路径!!!!
            'key_path'           => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'),      // XXX: 绝对路径!!!!
            'notify_url'         => 'http://example.com/payments/wechat-notify',                           // 默认支付结果通知地址
        ],
        // ...
    ],

    /*
     * 企业微信
     */
    // 'work' => [
    //     'default' => [
    //         'corp_id' => 'xxxxxxxxxxxxxxxxx',
    ///        'agent_id' => 100020,
    //         'secret'   => env('WECHAT_WORK_AGENT_CONTACTS_SECRET', ''),
    //          //...
    //      ],
    // ],
];

然后,我们在 /var/www/html/.env 文件中添加如下代码

WECHAT_MINI_PROGRAM_APPID=
WECHAT_MINI_PROGRAM_SECRET=
WECHAT_MINI_PROGRAM_TOKEN=
WECHAT_MINI_PROGRAM_AES_KEY=

WECHAT_PAYMENT_SANDBOX=false
WECHAT_PAYMENT_APPID=
WECHAT_PAYMENT_MCH_ID=
WECHAT_PAYMENT_KEY=
WECHAT_PAYMENT_CERT_PATH=
WECHAT_PAYMENT_KEY_PATH=

并将各项目设置成为我们自己的值,后续,我们将使用 .env 文件中的值来创建小程序实例,并使用这个小程序实例来进行微信登录等后续的代码。

引入 JWT Auth

接下来,我们在项目内引入 JWT Auth

cd /var/www/html
composer require tymon/jwt-auth 1.0.0-rc.2

然后执行如下命令生成配置文件

php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider"

并生成 Secret

php artisan jwt:secret

然后,修改一下我们的配置文件(config/auth.php),你可以点击下面的对比查看具体的修改内容。

示例代码:/var/www/html/config/auth.php
<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Authentication Defaults
    |--------------------------------------------------------------------------
    |
    | This option controls the default authentication "guard" and password
    | reset options for your application. You may change these defaults
    | as required, but they're a perfect start for most applications.
    |
    */

    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Authentication Guards
    |--------------------------------------------------------------------------
    |
    | Next, you may define every authentication guard for your application.
    | Of course, a great default configuration has been defined for you
    | here which uses session storage and the Eloquent user provider.
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | Supported: "session", "token"
    |
    */

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | User Providers
    |--------------------------------------------------------------------------
    |
    | All authentication drivers have a user provider. This defines how the
    | users are actually retrieved out of your database or other storage
    | mechanisms used by this application to persist your user's data.
    |
    | If you have multiple user tables or models you may configure multiple
    | sources which represent each model / table. These sources may then
    | be assigned to any extra authentication guards you have defined.
    |
    | Supported: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Resetting Passwords
    |--------------------------------------------------------------------------
    |
    | You may specify multiple password reset configurations if you have more
    | than one user table or model in the application and you want to have
    | separate password reset settings based on the specific user types.
    |
    | The expire time is the number of minutes that the reset token should be
    | considered valid. This security feature keeps tokens short-lived so
    | they have less time to be guessed. You may change this as needed.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
        ],
    ],

];

并修改我们的 app/User.php 文件

示例代码:/var/www/html/app/User.php
<?php

namespace App;

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements JWTSubject
{
    use Notifiable;

      /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}

这样我们就完成了 JWT Auth 的引入,后续,我们将返回 JWT 的 Token 给小程序,用于后续的登录。

创建 Auth 控制器,并实现微信登录

引入 Auth Controller

接下来,我们来生成一个 Auth 控制器,用于我们的微信登录

cd /var/www/html
php artisan make:controller AuthController
示例代码:/var/www/html/app/Http/Controllers/AuthController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;

class AuthController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth:api', ['except' => ['login']]);
    }
    public function login()
    {
        $credentials = request(['email', 'password']);

        if (! $token = auth()->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $this->respondWithToken($token);
    }
    public function me()
    {
        return response()->json(auth()->user());
    }
    public function logout()
    {
        auth()->logout();

        return response()->json(['message' => 'Successfully logged out']);
    }
    public function refresh()
    {
        return $this->respondWithToken(auth()->refresh());
    }
    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60
        ]);
    }
}

并且,在 routes/api.php 中添加如下代码

Route::group([

    'middleware' => 'api',
    'prefix' => 'auth'

], function ($router) {

    Route::post('login', 'AuthController@login');
    Route::post('logout', 'AuthController@logout');
    Route::post('refresh', 'AuthController@refresh');
    Route::post('me', 'AuthController@me');

});

改造微信登录

接下来,我们将 AuthController 中的 Login 方法修改为 微信登录的机制。

首先,在文件顶部添加如下代码(点我编辑文件

use EasyWeChat;
use IlluminateHttpRequest;

然后替换 Login 方法为如下代码

public function login(Request $request)
{

    $miniProgram = EasyWeChat::miniProgram();
    /**
    * 换取 Session Key
    */
    $session_data = $miniProgram->auth->session($request->code);
    $username = $session_data['openId']."@cloud.tencent.com";
    $password = $session_data['openId'];
    $credentials = [
        'email' => $username,
        'password' => $password
    ];
    /**
    * 检测用户信息是否可以登录
    * 如果可以登录,则说明已经有相关用户
    * 如果不可以登录,则跳转到创建用户的逻辑
    */
    if (! $token = auth()->attempt($credentials)) {
        /**
            * 使用微信数据来创建一个新的用户
            */
        $user = User::create([
            "email" => $username,
            "password" => bcrypt($password),
            "openId" => $session_data['openId'],
        ]);
        /**
            * 使用新的用户来登录,用于返回token
            */
        $token = auth()->attempt($credentials);
        /**
            * 返回token给用户
            */
        return $this->respondWithToken($token);
    }
    return $this->respondWithToken($token);
}

这样,我们就实现了微信的自动登录。我们使用 wx.login 登录获得的 code 换取 session_key 以及 openId,并使用不变的 openId 拼接邮箱作为用户名,使用 openId 作为密码,来确保用户无需输入账号密码自动登录。

获取小程序码

我们如何获取小程序码?也非常简单,只需要添加如下代码即可

use EasyWeChat;
public function getCode(){
    $miniProgram = EasyWeChat::miniProgram();
    $reponse = $miniProgram->app_code->get("/pages/index/index");
    return $response;
}

这样,我们就完成了基于 Laravel 的小程序后台的开发!后续的更多内容,你可以到 EasyWeChat 的官网去查看各 API 的调用方式。

點閱: 41

發表迴響

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料