Skip to content

二维码

为了满足用户渠道推广分析和用户账号绑定等场景的需要,公众平台提供了生成带参数二维码的接口。使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送,详细内容可以访问微信二维码文档。

类型:

1、临时二维码,是有过期时间的,最长可以设置为在二维码生成后的30天(即2592000秒)后过期,但能够生成较多数量。临时二维码主要用于账号绑定等不要求二维码永久保存的业务场景

2、永久二维码,是无过期时间的,但数量较少(目前为最多10万个)。永久二维码主要用于适用于账号绑定、用户来源统计等场景。

获取 Ticket

ticket 是微信管理二维码的凭证,生成二维码首先需要获取 ticket。

下面使用 getQrTicket 获取 ticket

$data = [
    "expire_seconds" => 3600,
    "action_name" => "QR_STR_SCENE",
    "action_info" => [
        "scene" => [
            "scene_str" => "houdunren_login"
        ]
    ]
];
$res = (new QrCode())->getQrTicket($data)

返回的$res 结果如下

{
  "ticket": "gQHS7zwAAAAAGpxLXBrUmtjSkcxZDk3b2hEY1kAAgQ5uRhnAwQQDgAA",
  "expire_seconds": 3600,
  "url": "http://weixin.qq.com/q/02Xjq-pkRkcJG1d97ohDcY"
}

获取图片

生成二维码图片有两种方式

使用 Ticket

第一种方式是使用上面获取的 ticket 来获取二维码图片

(new QrCode())->getQrImageByTicket($ticket)

也可以传递第二个参数获取 base64位的二维码

(new QrCode())->getQrImageByTicket($ticket,true)

使用扩展包

第二种方式是使用 getQrTicket 方法返回的 url 借助 endroid/qr-code 包来生成二维码图片,这种方式可以自定义二维码的样式和内容。

$res = $qr->getQrImage($data);
$builder = new Builder(
    writer: new PngWriter(),
    writerOptions: [],
    validateResult: false,
    data: $res['url'],
    encoding: new Encoding('UTF-8'),
    errorCorrectionLevel: ErrorCorrectionLevel::High,
    size: 300,
    margin: 0,
    roundBlockSizeMode: RoundBlockSizeMode::Margin,
    //二维码中显示的logo,在二维码中间显示
    // logoPath: url('/images/xj.jpeg'),
    logoResizeToWidth: 50,
    logoPunchoutBackground: true,
    //二维码下面显示的文字内容,如果使用中文,需要配置中文字体
    //labelText: '后盾人登录',
    //labelFont: new OpenSans(20),
    //labelAlignment: LabelAlignment::Center
);
header("Content-Type:image/png");
return $builder->build()->getString();

一次操作

后盾人微信也支持一次获取 ticket 与 base64图片数据

$data = [
    "expire_seconds" => 3600,
    "action_name" => "QR_STR_SCENE",
    "action_info" => [
        "scene" => [
            "scene_str" => "houdunren_login"
        ]
    ]
];

$res = (new QrCode())->getQrTicketAndBase64Image($data)

返回的变量 $res 内容如下

{
  "ticket": "gQG77zwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyWmJVOG9zUmtjSkcxY3k2b2hEY2oAAgQSuBhnAwQQDgAA",
  "expire_seconds": 3600,
  "url": "http://weixin.qq.com/q/02ZbU8osRkcJG1cy6ohDcj",
  "image": "data:image/png;base64,..."
}

完整示例

下面是一个完整的二维码生成示例。

控制器

下面定义 WechatQrLoginController 用于生成二维码图片。

<?php

namespace App\Http\Controllers\Wechat;

use App\Http\Controllers\Controller;
use Houdunren\Wechat\Qrcode\QrCode;
use Houdunren\Wechat\WeChat;

//微信扫码登录
class WechatQrLoginController extends Controller
{
    public function __invoke()
    {
        WeChat::init(config('hd.admin'));
        $qr = new QrCode();
        $data = [
            "expire_seconds" => 3600,
            "action_name" => "QR_STR_SCENE",
            "action_info" => [
                "scene" => [
                    "scene_str" => "houdunren_login"
                ]
            ]
        ];
        return $qr->getQrTicketAndBase64Image($data, true);
    }
}

路由定义

下面来定义路由,前端请求该接口就可以显示二维码图片了。

Route::get('wechat/qrLogin', WechatQrLoginController::class);

前端显示

现在前端请求这个接口,就可以显示二维码图片了,以下是 react 代码,不同前端技术请自行调整。

import { useAxios } from '@/hooks/useAxios'
import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'

export const WechatLoginQr = () => {
  const { axiosInstance } = useAxios()
  const { isPending, isError, data } = useQuery({
    queryKey: ['wechatLoginQr'],
    queryFn: async () => {
      return (await axiosInstance.get('/api/wechat/qrLogin')).data
    },
  })
  if (isPending || isError) return <></>

  return (
    <div>
      <img src={data.image} alt='' />
    </div>
  )
}