尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

三合一收款码生成器PHP源码:UA分流路由与二维码部署全解析

三合一收款码生成器PHP源码:UA分流路由与二维码部署全解析 简介生成QQ、微信、支付宝三合一收款二维码的PHP源码定位轻量实用适合个人站长、中小商户或需要聚合收款码的开发者直接部署使用不依赖任何第三方接口即可自行搭建在线收款码生成系统。压缩包内共4个文件包含PHP主程序与二维码生成组件、一个HTML辅助说明页和一个CSS样式文件整体仅33KB结构精简、便于二次修改和快速上线。已有443人浏览学习。通过简单修改index.php中的解码地址即可替换为自己的收款码并可按需调整页面样式与配色生成可同时识别QQ、微信、支付宝扫码支付的三合一收款码。源码内置phpqrcode二维码生成库无需额外安装扩展同时附带404跳转页面对熟悉PHP虚拟主机部署的用户十分友好适合作为轻量级收款码工具用于博客、官网或线下展示场景。1. 收款码生成器三合一不是拼图是扫码路由把微信、支付宝、QQ 三个收款码合并成一张二维码最容易踩的坑是直接在图片层面做“拼接”。实际扫一下就会发现系统要么只识别出叠在最上面那张要么直接报错——二维码的纠错机制会优先解出离摄像头最近的码后续内容全被截断。三合一收款码生成器真正要解决的是把三个支付链接收敛成一个跳转地址再对这个地址做二维码生成。用户扫到的永远是同一个 URL服务端拿到请求特征后再分流到对应收银台。这个思路也解释了为什么市面上的收款码生成器基本都是“在线工具”形态它需要一个能跑脚本的服务端单靠静态图片做不到。本文按最常见的 PHP 源码方案来拆解从识别原理、路由源码、二维码渲染到部署排错给出能直接落地用的代码和参数。2. 三合一收款码识别原理UA 分流与二维码落地页设计2.1 为什么三合一必须走跳转页而不是把三个链接塞进一张图支付宝收款链接形如https://qr.alipay.com/xxxx微信支付链接是https://wpay.weixin.qq.com/xxxxQQ 钱包链接则指向i.qianbao.qq.com。有人曾尝试把三个 URL 直接拼接成一个字符串再用二维码生成器编码这个做法有两层隐患。先不说支付平台会不会效验链接格式单看二维码本身QR Code 的数据容量上限虽然接近 3KB但内容越长编码版本就越高模块越密。三个长链接拼起来通常超过 600 字符版本会升到 15 以上打印在小票、名片上以后超市灯光、手机镜头畸变、纸张折痕都会让识别率断崖式下跌。所以成熟的三合一收款码生成器二维码里只放一个带路由参数的短地址比如https://pay.yourdomain.com/pay.php?m10086。三个原始收款链接存到服务端配置里二维码只负责把用户带到路由页由路由决定下一步跳去哪。这个设计把“码的容量问题”转换成了“服务端路由问题”也是后面所有源码实现的基础。2.2 微信、支付宝、QQ 的 UA 特征与分流判断路由页拿到请求后靠什么判断当前环境最可靠、也最省资源的办法是读User-Agent。微信内置浏览器的 UA 里固定带MicroMessenger支付宝客户端带AlipayClient手机 QQ 带QQ/和MQQBrowser这几个特征串从移动端到 PC 端都相对稳定用字符串匹配就够了。扫码环境UA 特征串路由目标典型触发场景微信MicroMessenger微信支付链接微信扫一扫、聊天内长按识别支付宝AlipayClient支付宝收款链接支付宝扫一扫、生活号内打开QQQQ/或MQQBrowserQQ 钱包收款链接QQ 扫一扫、QQ 内置浏览器其它浏览器无上述特征展示支付方式选择页抖音、钉钉、系统相机扫码用 PHP 实现这个判断只需要一个strpos循环代码写出来大约 20 行。下面这段是路由判断的核心逻辑实际项目里可以直接抄进pay.php?php // pay.php 三合一收款路由入口 $ua $_SERVER[HTTP_USER_AGENT] ?? ; $routes [ MicroMessenger wechat, AlipayClient alipay, MQQBrowser qq, QQ/ qq, ]; foreach ($routes as $keyword $platform) { if (strpos($ua, $keyword) ! false) { header(Location: . getPayUrl($platform), true, 302); exit; } } // 未命中则加载选择页见 2.3 include select_page.html;这段代码的匹配顺序有讲究MQQBrowser要写在QQ/前面因为手机 QQ 的 UA 里两个特征可能同时出现但MQQBrowser更精确。header()的第二个参数302表示临时重定向避免浏览器缓存跳转结果万一以后要换链接还能立即生效。getPayUrl()是从配置文件读链接的封装函数下一章会给出完整实现。2.3 落地页还要做好“未知 App”兜底UA 判断并不是万能的。抖音、钉钉、企业微信的 UA 不包含上面任何特征串系统相机扫码也可能直接调用默认浏览器访问这时候路由必须回退到一个“选择页”。选择页上展示微信、支付宝、QQ 三个按钮每个按钮都是一个a标签href直接指向对应的支付链接。用户点击某个按钮后当前浏览器会尝试拉起对应 App拉不起来也能复制链接到浏览器打开。这层兜底不是可选项。很多收款码生成器源码把 UA 匹配做得很好却忽略了“未识别环境”结果用户扫出来是一张纯白页面。选择页还可以加一个navigator.userAgent的实时显示方便排查扫码环境这个调试信息上线后可以隐藏。3. 收款码生成器源码PHP 版路由、配置与二维码生成3.1 源码目录结构与收款码参数配置表一套能直接部署的三合一收款码源码至少需要四个文件配置文件存三个支付链接、路由文件做 UA 分流、生成器页面提供表单输入、二维码库负责渲染。常见的目录结构是这样paycode/ ├── config.php # 收款链接和商户配置 ├── pay.php # 扫码落地路由UA 分流 ├── index.php # 收款码生成器页面前端表单 ├── qrcode.min.js # 二维码渲染库 ├── select_page.html # 未识别环境时的兜底选择页 └── self_check.php # 自检脚本第 6 章用到config.php里配置三个支付链接字段设计成关联数组便于后续从数据库读取扩展。参数说明如下表配置键示例值说明merchant张三的小店商户名称显示在选择页wechat_pay_urlhttps://wpay.weixin.qq.com/xxxx微信支付/收款链接alipay_pay_urlhttps://qr.alipay.com/xxxx支付宝收款码链接qq_pay_urlhttps://i.qianbao.qq.com/xxxxQQ 钱包收款链接配置文件的写法不复杂重点是要把三个链接单独拎出来不要让它们散落在业务代码里。下面这段可以直接用?php // config.php 收款链接配置 return [ merchant 张三的小店, wechat_pay_url https://wpay.weixin.qq.com/xxxx, alipay_pay_url https://qr.alipay.com/xxxx, qq_pay_url https://i.qianbao.qq.com/xxxx, ];把配置做成return数组而不是普通变量是为了配合require的返回值赋值调用处写$config require config.php;就能直接拿到数组不用关心全局变量污染。后续如果要做多商户版本把这份配置改成数据库表行即可路由代码不用动。3.2 用 PHP 写 UA 跳转路由核心 30 行路由文件把配置和跳转逻辑串起来完整实现如下。这个文件同时承担“生成”和“落地”两个职责生成时它接收参数生成跳转链接扫码时它根据 UA 做重定向。两份代码并不冲突合并写在一个入口里反而省去额外路由规则。?php // pay.php 三合一收款码统一入口 $config require config.php; // 1. 从生成器传来的参数中读取商户标识 // 用 base64_decode 而不是明文传链接避免 URL 过长 $payload $_GET[m] ?? ; $payload base64_decode($payload); // 2. 从配置中取出当前商户的三个支付链接 $payUrls [ wechat $config[wechat_pay_url], alipay $config[alipay_pay_url], qq $config[qq_pay_url], ]; // 3. 根据 UA 特征串分流 $ua $_SERVER[HTTP_USER_AGENT] ?? ; $uaRules [ MicroMessenger wechat, AlipayClient alipay, MQQBrowser qq, QQ/ qq, ]; foreach ($uaRules as $keyword $platform) { if (strpos($ua, $keyword) ! false) { header(Location: . $payUrls[$platform], true, 302); exit; } } // 4. 未识别环境时展示选择页 $merchantName $config[merchant]; include select_page.html;这里我做了一个取舍用base64_decode从m参数还原链接而不是直接把支付链接拼进 URL。因为支付宝和微信的收款链接本身就有 60 到 100 个字符三个拼一起会使最终二维码长度超标。改进后可把链接存到数据库m参数只传自增 ID这样二维码内容能控制在 80 字符以内识别率最高。参数说明上$_GET[m]是生成器在创建二维码时写入的如果没传或解码失败代码会走进include select_page.html这其实也是一种容错。生产环境建议把include后面加一个exit和日志记录方便追踪哪些场景反复落到兜底页。3.3 二维码生成端与路由端如何共用一份源码生成器页面index.php和路由pay.php是同一份 PHP 源码里的两个角色。生成端的职责是把用户填写的三个链接拼成跳转链接路由端再把链接解开。中间传递的数据结构必须约定好常见做法是生成端输出一个完整跳转 URL 给二维码库而路由端只负责消费这个 URL。?php // 生成端核心逻辑index.php 内联代码 // 用户提交三个链接后拼成 pay.php 可识别的参数 $wx $_POST[wechat_pay_url] ?? ; $ali $_POST[alipay_pay_url] ?? ; $qq $_POST[qq_pay_url] ?? ; $payload base64_encode(json_encode([ wx $wx, ali $ali, qq $qq, ])); $finalUrl // . $_SERVER[HTTP_HOST] . /pay.php?m . urlencode($payload);这里把三个链接放进一个 JSON 再 base64严格说容量压力转移到了 JSON 本身。如果商户数量多还是推荐用数据库短 ID。判断一份收款码源码成不成熟就看它有没有把“链接入库”做成可选模块。短码方案下生成端生成的二维码内容短、模板少扫码解析速度快排错也容易。4. 在线三合一收款码生成器前端表单交互与二维码渲染4.1 用 qrcode.js 在前端直接出码不依赖后端图片接口二维码渲染有两种路径后端用 PHP GD 库生成图片前端用 JavaScript 库直接画 canvas。做收款码生成器时我一般推荐后者。qrcode.js 是一个无依赖的纯前端库不需要后端安装任何图像扩展生成速度也快。更重要的是二维码内容本来就是前端拼好的跳转链接在前端直接生成省掉一次 AJAX 请求部署时只需静态文件。下面是index.php里的完整表单和渲染逻辑!-- index.php 收款码生成器页面 -- script srcqrcode.min.js/script div classform-row label微信收款链接/label input idpayWx typeurl placeholderhttps://wpay.weixin.qq.com/... /div div classform-row label支付宝收款链接/label input idpayAli typeurl placeholderhttps://qr.alipay.com/... /div div classform-row labelQQ钱包收款链接/label input idpayQq typeurl placeholderhttps://i.qianbao.qq.com/... /div div idqrcode/div button onclickrenderQrcode()生成三合一收款码/button script let qr null; function buildPayUrl() { const wx document.getElementById(payWx).value.trim(); const ali document.getElementById(payAli).value.trim(); const qq document.getElementById(payQq).value.trim(); // 参数顺序固定与 pay.php 解包顺序保持一致 const payload btoa(unescape(encodeURIComponent( JSON.stringify({ wx: wx, ali: ali, qq: qq }) ))); return location.origin /pay.php?m encodeURIComponent(payload); } function renderQrcode() { const url buildPayUrl(); const box document.getElementById(qrcode); box.innerHTML ; qr new QRCode(box, { text: url, width: 320, height: 320, correctLevel: QRCode.CorrectLevel.H }); } /scriptbtoa在遇到中文时会报错所以先用encodeURIComponent编码一遍再用unescape还原成 UTF-8 字节序列最后btoa。这个过程和 PHP 的base64_encode是互逆的注意前后端必须使用同一套字符编码否则 base64 解码出来是乱码。correctLevel: H把容错率调到最高一档这样后面加 Logo 仍有冗余纠错空间。4.2 表单参数与二维码内容的一致性校验用户从支付宝后台复制的链接可能带换行或空格某些浏览器还会自动补齐https://。生成器前端至少要做一个基础校验避免生成一个扫不开的二维码// 生成前校验返回错误信息 function validatePayUrl(input) { const val input.value.trim(); if (val ) return 收款链接不能为空; if (!/^https?:\/\//i.test(val)) return 链接必须以 http(s):// 开头; if (val.length 500) return 链接长度超过 500 字符请改用短链; // 简单域名白名单防止复制错 if (!/(wpay\.weixin\.qq\.com|qr\.alipay\.com|qianbao\.qq\.com)/.test(val)) { return 链接域名不在微信/支付宝/QQ 钱包白名单内; } return ; }白名单校验值得多说一句。它不能真正验证链接是否属于当前商户但能拦截 90% 的复制错误比如把微信码填到支付宝栏里。要拿到更严格的校验得在服务端请求一次支付链接看返回状态码和重定向目标这部分放到第 6 章自检脚本里做。4.3 加 Logo、调容错率、留白边扫描率的关键参数生成器给二维码加 Logo 是常见需求但 Logo 会遮挡数据模块。QR 码有四级容错L(7%)、M(15%)、Q(25%)、H(30%)加 Logo 必须用 H 级。日常常见的做法是 Logo 占码面不超过四分之一并且放在三个定位角以外的中心区域。使用场景建议容错级Logo 大小白边模块数屏幕展示M无 Logo2打印小票Q无 Logo4带 Logo 的收款码H边长 ≤ 码的 25%4布料/陶瓷印刷H边长 ≤ 码的 15%6白边quiet zone是二维码四周的空白区域很多生成器默认不画导致扫码器无法定位。qrcode.js 在 canvas 模式下可以通过 CSS 给容器加 padding 来模拟白边更稳妥的做法是让后端在输出 PNG 时把白边画进图片这样无论用户怎么存图都不会丢边距。5. 部署在线收款码生成器Nginx、域名与“无法识别二维码”排错5.1 最小可用的 Nginx PHP-FPM 站点配置把源码传上服务器后需要让pay.php和index.php都能被访问。以 Nginx 为例配置一个站点的核心片段如下server { listen 80; server_name pay.example.com; root /var/www/paycode; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.1-fpm.sock; } location ~* \.(png|jpg|js|css)$ { expires 7d; access_log off; } }try_files那一行保证 SEO 友好的路由入口.php$的 location 把 PHP 请求交给 fastcgi静态资源单独缓存 7 天二维码库和 Logo 图片都能被浏览器缓存。部署时如果只有 HTTP 没有 HTTPS微信和支付宝内置浏览器会拦截重定向所以上线前务必配好 HTTPS 证书腾讯云和阿里云的免费证书都够用。5.2 微信扫码后“无法识别二维码格式”的排查路径这个问题在收款码生成场景里出现频率最高。二维码本身是一张图片微信扫码后提示“无法识别”九成原因不是二维码坏了而是解析出来的内容有问题。现象常见原因检查方法扫码提示“无法识别二维码”二维码内容过长版本过高用短 ID 替代完整跳转链接扫码出来一长串字母不跳转Payload 未做 URL 编码检查urlencode($payload)扫码后提示“网页无法打开”域名未备案或未配 HTTPS浏览器直接访问跳转链接微信内打开后白屏UA 没命中选择页路径写错查看select_page.html相对路径能打开但跳错平台UA 规则顺序配置错误用 curl 模拟三种 UA 逐一验证这里最容易忽略的是 URL 编码。生成器前端拼的?m参数如果是 base64其中会包含、/、放进 URL 前必须做 encodeURIComponent。漏掉这一步扫码后 PHP 拿到的$_GET[m]会被截断。5.3 使用 curl 模拟 UA 验证跳转结果代码改完别急着上线先在命令行验证三种环境的跳转是否符合预期。curl 支持-A参数伪造 UA用-I只取响应头重点看Locationcurl -sI -A MicroMessenger/8.0 \ https://pay.example.com/pay.php?mxxxx | grep -E HTTP|Location curl -sI -A AlipayClient/10.1 \ https://pay.example.com/pay.php?mxxxx | grep -E HTTP|Location curl -sI -A QQ/8.9 MQQBrowser/6.2 \ https://pay.example.com/pay.php?mxxxx | grep -E HTTP|Location预期结果应该是三个请求分别返回302且Location指向各自平台的收款链接。如果三个Location都一样说明 UA 规则没写对或者请求参数m解析出来是空的。注意不能加-L跟随重定向否则 curl 会直接按跳转执行请求输出会被污染。6. 收款码生成器进阶批量自检二维码内容与路由可达性6.1 用 zbarimg 批量校验生成的二维码图片二维码生成器上线后用户可能一次性生成上百张码人工一张张扫码不现实。Linux 上装好 zbar-tools 后可以用脚本批量读取模板里的.png并检查解码出来的文本是不是正确的跳转链接#!/bin/bash # check_qrcodes.sh 批量校验二维码图片内容 for png in ./qrcodes/*.png; do raw$(zbarimg --raw $png 2/dev/null) if [[ $raw *pay.php?m* ]]; then echo [OK] $png else echo [FAIL] $png - $raw fi donezbarimg --raw会跳过图形界面直接输出解码文本脚本里的条件判断检查文本是否包含pay.php?m防止生成器把空 URL 或配置环境变量当成有效内容。这个自检对“印刷前”的码尤其重要因为印刷后没法快速改。6.2 自动化模拟三端跳转校验路由可达性除了二维码内容路由本身也可能出问题比如支付链接失效或者配置项被误改动。把第 5.3 节的 curl 验证写成脚本并加进 crontab就能做到每日巡检。下面这段脚本用 UA 特征串做关键字匹配输出每个环境的实际落点#!/bin/bash # check_routes.sh 模拟三种扫码环境验证跳转目标 PAY_URLhttps://pay.example.com/pay.php?mdGVzdA check_redirect() { local ua$1 local task$2 local location location$(curl -sI -A $ua $PAY_URL | grep -i ^Location: | tr -d \r) if [ -n $location ]; then echo $task - $location else echo $task - [NO REDIRECT] fi } check_redirect MicroMessenger/8.0 wechat check_redirect AlipayClient/10.1 alipay check_redirect QQ/8.9 MQQBrowser qq脚本里用tr -d \r把 Windows 换行符去掉避免 Location 后面跟一个回程符导致后续判断不准。这里故意不检查 Location 的具体值只检查有没有返回因为支付链接可能因商户平台调整而变化。要更严格的话可以把$location再和 config.php 里的期望值比对发现不一致时直接告警。配合 CI 里的定时任务这套自检能在用户扫到失效码之前先发现问题。本文还有配套的精品资源点击获取
返回列表