Tp生成小程序二维码(带参数),前端解析
注:小程序要进行上线,然后微信开发工具的appid和上线后的appid要一致,否则无法解析出来参参数。
需要 小程序appid 然后小程序秘钥 可以自设头像也可以不设置中间的图像
官方给的三个链接,链接不同获取的二维码不同,含义也不同,先看一遍链接 在敲代码吧!!!
https://www.php.cn/php-weizijiaocheng-389348.html
通过后台接口可以获取小程序任意页面的二维码,扫描该二维码可以直接进入小程序对应的页面。官方推荐生成并使用小程序码,它具有更好的辨识度。目前有3个接口可以生成小程序码,开发者可以根据自己的需要选择合适的接口。
接口A: 适用于需要的码数量较少的业务场景 接口地址:
https://api.weixin.qq.com/wxa/getwxacode?access_token=ACCESS_TOKEN
参数如下:
注意:通过该接口生成的小程序码,永久有效,数量限制见文末说明,请谨慎使用。用户扫描该码进入小程序后,将直接进入 path 对应的页面。
接口B:适用于需要的码数量极多,或仅临时使用的业务场景:
https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
参数如下:
注意:通过该接口生成的小程序码,永久有效,数量暂无限制。用户扫描该码进入小程序后,开发者需在对应页面获取的码中 scene 字段的值,再做处理逻辑。使用如下代码可以获取到二维码中的 scene 字段的值。调试阶段可以使用开发工具的条件编译自定义参数 scene=xxxx 进行模拟,开发工具模拟时的 scene 的参数值需要进行 urlencode
接口C:适用于需要的码数量较少的业务场景:
https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN
参数如下:
注意:通过该接口生成的小程序二维码,永久有效,数量限制见文末说明,请谨慎使用。用户扫描该码进入小程序后,将直接进入 path 对应的页面。
这几个接口POST 参数需要转成 json 字符串,不支持 form 表单提交。接口A加上接口C,总共生成的码数量限制为100,000,请谨慎调用。这里以接口B为例,讲一下生成二维码图片并保存本地服务器:
1. 获取 access_token
access_token 是全局唯一接口调用凭据,开发者调用各接口时都需使用 access_token,需妥善保存。做过微信开发和公众号开发,这都是最基本的,这里获取方法跟公众号获取 access_token 一模一样,方法见: 获取微信基础接口凭证Access_token
小程序前端
参考地址:
https://blog.csdn.net/mossbaoo/article/details/84143453
https://blog.csdn.net/u013184970/article/details/105357121
https://blog.csdn.net/qq_35713752/article/details/79794342
如果是扫码进去的就自动解析啦
onLoad(options) {
if(options.scene) {
let scene = decodeURIComponent(options.scene);
console.log(scene)
// 后续处理scene
}
},
Js扫码事件
/**
* 扫码事件
*/
scanCodeEvent: function(){
var that = this;
wx.scanCode({
// onlyFromCamera: true,// 只允许从相机扫码
success(res){
console.log(res.scene);
console.log("扫码成功:"+JSON.stringify(res))
// 扫码成功后 在此处理接下来的逻辑
that.setData({
scanCode: res.result
})
}
})
},
Tp后台代码(无中间头像 默认的头像):
public function qrcode()
{
$request = Request::instance();
//拿到openid 查找用户表内是否有该用户 没有则拒绝生成二维码 有则查看是否已生成二维码 有生成则发送数据 没有则生成
// $openid = input( 'post.openid' );
//得到用户openid
// $dealer = Db::name( 'users' )->where( ['openid' => $openid] )->value( 'tuiguangimg' );
// if ( $dealer == NULL ) {
// if ( $dealer['qrcode'] == '' ) {
$dealer = 'nihaowoshiweiyibiaoshideluanma';
$appid = 'wx11****3d3f6';
$secret = '320c*****3a57348';
//AppSecret( 小程序密钥 )
$url_access_token = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$secret;
$json_access_token = $this -> sendCmd( $url_access_token, array() );
$arr_access_token = json_decode( $json_access_token, true );
$access_token = $arr_access_token['access_token'];
// dump( $access_token );
// exit;
if ( !empty( $access_token ) ) {
//https://api.weixin.qq.com/wxa/getwxacode //花瓣的
//https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode //方图的
$url = 'https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token='.$access_token;
$data = '{"path": "pages/index/index?uid='.$dealer.'", "width": 430}';
$result = $this -> sendCmd( $url, $data );
$name = "woshiceshi".time();
//保存图片
$user = "MERCHANT_UNIQUE_IDENTIFICATIO999995";
//用户的唯一标识
$pathname = '../public/static/eq/' . $user . '/' . date( 'Ymd' );
if ( !is_dir( $pathname ) ) {
//若目录不存在则创建之
mkdir( $pathname, 0777, true );
}
//这个应该用不到
$name = time();
file_put_contents( '../public/static/eq/' . $user . '/' . date( 'Ymd' ) . '/'. $name . '.jpg', $result );
return $request->domain() . '/static/eq/' . $user . '/' . date( 'Ymd' ) .'/' . $name . '.jpg';
} else {
$arr = array( 'code'=>0, 'msg'=>'ACCESS TOKEN为空!' );
return GYReturn( '1', '暂无数据', $arr );
}
// } else {
// echo '获取二维码';
// }
// } else {
// $arr['tuiguangimg'] = $dealer;
// //echo "<img src=/youchis$dealer>";
// return GYReturn( '1', '暂无数据', $arr );
// }
}
/**
* 发起请求
* @param string $url 请求地址
* @param string $data 请求数据包
* @return string 请求返回数据
*/
function sendCmd( $url, $data )
{
$curl = curl_init();
// 启动一个CURL会话
curl_setopt( $curl, CURLOPT_URL, $url );
// 要访问的地址
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, 0 );
// 对认证证书来源的检测
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, 2 );
// 从证书中检查SSL加密算法是否存在
curl_setopt( $curl, CURLOPT_HTTPHEADER, array( 'Expect:' ) );
//解决数据包大不能提交
curl_setopt( $curl, CURLOPT_FOLLOWLOCATION, 1 );
// 使用自动跳转
curl_setopt( $curl, CURLOPT_AUTOREFERER, 1 );
// 自动设置Referer
curl_setopt( $curl, CURLOPT_POST, 1 );
// 发送一个常规的Post请求
curl_setopt( $curl, CURLOPT_POSTFIELDS, $data );
// Post提交的数据包
curl_setopt( $curl, CURLOPT_TIMEOUT, 30 );
// 设置超时限制防止死循
curl_setopt( $curl, CURLOPT_HEADER, 0 );
// 显示返回的Header区域内容
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
// 获取的信息以文件流的形式返回
$tmpInfo = curl_exec( $curl );
// 执行操作
if ( curl_errno( $curl ) ) {
echo 'Errno'.curl_error( $curl );
}
curl_close( $curl );
// 关键CURL会话
return $tmpInfo;
// 返回数据
}
Tp后台有头像的(不是文件名加参数):
<?php
namespace app\api\controller;
use app\common\controller\IndexBase;
use think\Request;
use think\Log;
use think\Db;
//小程序基本配置
header( 'Access-Control-Allow-Origin: *' );
//解决跨域 /测试
class Wxt extends IndexBase {
//生成二维码功能/ajax上传
public function Image_eq()
{
$request = Request::instance();
$file = request()->file( 'file' );
//tp5写法获取图片信息
$user = session( 'admin_auth.MERCHANT_UNIQUE_IDENTIFICATION' );
// $pathname = '../public/static/eq/' . $user . '/' . date( 'Ymd' );
// if ( !is_dir( $pathname ) ) {
// //若目录不存在则创建之
// mkdir( $pathname, 0777, true );
// }
$info = $file->move( ROOT_PATH . '/public/static/eq/'. $user );
if ( $info ) {
$Nmae = $info->getSaveName();
//获取临时名字
$site = str_replace( '\\', '/', $Nmae );
$avatarUrl = $request->domain() . '/static/eq/' . $user .'/'. $site;
}
// Log::record( $avatarUrl );
$avatar = $this->eq( $avatarUrl );
$img = [$avatar,$avatarUrl];
if ( $img ) {
return ['code' => 1, 'url' => $img ];
} else {
return ['code' => 0, 'msg' => '上传文件错误'];
}
// return json( $img );
}
/**
* 生成微信二维码
*/
// public function eq( $avatarUrl )
public function eq()
{
$request = Request::instance();
/**
* 步骤:
* 1.获得微信返回的二维码图片数据流
* 2.把用户头像变成圆形,覆盖到小程序中间的空白部分
* 3.把二维码与圆形头像结合
* 3.返回客户端,或者输出显示
*/
$user_sole = "100";//传递的参数
$appid = 'wx11******d3f6';
//appid
$appsecret = '327284********5d2ea57348';
//app secret
$send = array( 'scene'=>$user_sole, 'path'=>'pages/index/index', 'width' => '100' );
//'scene' => 123 这里必须为123不能去掉 width可能是小程序码的宽度
//传给微信的参数
$avatarUrl = 'http://www.aiabte-tp5.con/upload/img/2019092510504711.png';//地址链接,要用本域名的链接地址 否则上传不成功
//用户头像url
//请求微信,获取小程序二维码
$resWxQrCode = $this->getWxQrcode( $send, $appid, $appsecret );
//不报错
//用户头像图片变圆形
$avatar = file_get_contents( $avatarUrl );
$logo = $this->yuanImg( $avatar );
// Log::record( $logo );
//返回的是图片数据流
//二维码与头像结合
$sharePic = $this->qrcodeWithLogo( $resWxQrCode, $logo );
// Log::record( "<image src='data:image/png;base64," . base64_encode( $sharePic ) . "'>" );
// return $sharePic;
//这里为了看效果,直接输出图片了
// $img = "<image src='data:image/png;base64," . base64_encode( $sharePic ) . "'>";
// return $img;
//保存图片
$user = "100";//用户名文件夹
//用户的唯一标识
$pathname = '../public/static/eq/' . $user . '/' . date( 'Ymd' );
if ( !is_dir( $pathname ) ) {
//若目录不存在则创建之
mkdir( $pathname, 0777, true );
}
//这个应该用不到
$name = time();
file_put_contents( '../public/static/eq/' . $user . '/' . date( 'Ymd' ) . '/'. $name . '.jpg', $sharePic );
return $request->domain() . '/static/eq/' . $user . '/' . date( 'Ymd' ) .'/' . $name . '.jpg';
}
/******************************* 下面是功能函数 **********************************/
/**
* curl方法
* @param $url 请求url
* @param $data 传送数据,有数据时使用post传递
* @param type 为2时, 设置json传递
*/
public function curlRequest( $url, $data = null, $type = 1 )
{
$curl = curl_init();
curl_setopt( $curl, CURLOPT_URL, $url );
curl_setopt( $curl, CURLOPT_SSL_VERIFYPEER, FALSE );
curl_setopt( $curl, CURLOPT_SSL_VERIFYHOST, FALSE );
if ( !empty( $data ) ) {
curl_setopt( $curl, CURLOPT_POST, 1 );
curl_setopt( $curl, CURLOPT_POSTFIELDS, $data );
if ( $type == 2 ) {
curl_setopt( $curl, CURLOPT_HTTPHEADER,
array( 'Content-Type: application/json', 'Content-Length: ' . strlen( $data ) ) );
}
}
curl_setopt( $curl, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $curl, CURLOPT_CONNECTTIMEOUT, 10 );
$output = curl_exec( $curl );
curl_close( $curl );
return $output;
}
/**
* 请求微信服务器, 生成二维码
* @param $data array( 'scene'=>$setid, 'path' =>'pages/question/question', 'width'=>'100' );
*/
public function getWxQrcode( $data, $appid, $appsecret )
{
//get access_token
$wxTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;
$access_token = $this->curlRequest( $wxTokenUrl );
//报错
$access_token = json_decode( $access_token, true );
// dump( $access_token );
// exit;
// Log::record( $access_token );
//get qrcode 微信B接口
$wxQrcodeUrl = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $access_token['access_token'];
$data = json_encode( $data, JSON_UNESCAPED_UNICODE );
return $this->curlRequest( $wxQrcodeUrl, $data );
}
/**
* 在二维码的中间区域镶嵌图片
* @param $QR 二维码数据流。比如file_get_contents( imageurl )返回的东东, 或者微信给返回的东东
* @param $logo 中间显示图片的数据流。比如file_get_contents( imageurl )返回的东东
* @return 返回图片数据流
*/
public function qrcodeWithLogo( $QR, $logo )
{
$QR = imagecreatefromstring( $QR );
$logo = imagecreatefromstring( $logo );
$QR_width = imagesx( $QR );
//二维码图片宽度
$QR_height = imagesy( $QR );
//二维码图片高度
$logo_width = imagesx( $logo );
//logo图片宽度
$logo_height = imagesy( $logo );
//logo图片高度
$logo_qr_width = $QR_width / 2.2;
//组合之后logo的宽度( 占二维码的1/2.2 )
$scale = $logo_width / $logo_qr_width;
//logo的宽度缩放比( 本身宽度/组合后的宽度 )
$logo_qr_height = $logo_height / $scale;
//组合之后logo的高度
$from_width = ( $QR_width - $logo_qr_width ) / 2;
//组合之后logo左上角所在坐标点
/**
* 重新组合图片并调整大小
* imagecopyresampled() 将一幅图像( 源图象 )中的一块正方形区域拷贝到另一个图像中
*/
imagecopyresampled( $QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, $logo_qr_height, $logo_width, $logo_height );
/**
* 如果想要直接输出图片,应该先设header。header( 'Content-Type: image/png; charset=utf-8' );
* 并且去掉缓存区函数
*/
//获取输出缓存,否则imagepng会把图片输出到浏览器
ob_start();
imagepng( $QR );
imagedestroy( $QR );
imagedestroy( $logo );
$contents = ob_get_contents();
ob_end_clean();
// Log::record( $contents );
return $contents;
}
/**
* 剪切图片为圆形
* @param $picture 图片数据流 比如file_get_contents( imageurl )返回的东东
* @return 图片数据流
*/
public function yuanImg( $picture )
{
$src_img = imagecreatefromstring( $picture );
$w = imagesx( $src_img );
$h = imagesy( $src_img );
$w = min( $w, $h );
$h = $w;
$img = imagecreatetruecolor( $w, $h );
//这一句一定要有
imagesavealpha( $img, true );
//拾取一个完全透明的颜色, 最后一个参数127为全透明
$bg = imagecolorallocatealpha( $img, 255, 255, 255, 127 );
imagefill( $img, 0, 0, $bg );
$r = $w / 2;
//圆半径
$y_x = $r;
//圆心X坐标
$y_y = $r;
//圆心Y坐标
for ( $x = 0; $x < $w; $x++ ) {
for ( $y = 0; $y < $h; $y++ ) {
$rgbColor = imagecolorat( $src_img, $x, $y );
if ( ( ( ( $x - $r ) * ( $x - $r ) + ( $y - $r ) * ( $y - $r ) ) < ( $r * $r ) ) ) {
imagesetpixel( $img, $x, $y, $rgbColor );
}
}
}
/**
* 如果想要直接输出图片,应该先设header。header( 'Content-Type: image/png; charset=utf-8' );
* 并且去掉缓存区函数
*/
//获取输出缓存,否则imagepng会把图片输出到浏览器
ob_start();
imagepng( $img );
imagedestroy( $img );
$contents = ob_get_contents();
ob_end_clean();
return $contents;
}
/**
* 生成微信二维码结束
*/
}