简介:这是一套面向新能源充电桩行业的H5多语言PHP源码,适用于搭建充电桩推广、会员钱包与充值提现一体化平台,兼顾5G浪潮下移动端引流与上下级分销绑定场景。包内共2000个文件,以png图片、PHP业务逻辑、gif/jpg素材、JavaScript交互、HTML页面及CSS样式为主,少量sql安装文件与配置文件辅助部署,整体仅29.67MB,便于快速迁移与打包成APP。前端支持中英日泰韩等多语言一键切换,钱包充值、提现流程完整,并已接入免签微信、支付宝接口,省去签约门槛。目前已有303人学习下载,适合有PHP基础、希望快速搭建新能源充电桩或同类型多语言推广站点的开发者参考使用。源码附带较完整的目录结构和安装文件,能帮助读者直接部署体验,并作为二次开发或功能改造的起点。
1. 充电桩H5多语言系统:不只是换个语言包那么简单
做推广类H5项目最怕两件事:一是UI粗糙,用户打开就关;二是语言单一,尤其在东南亚和日韩市场,用户一看不是母语直接流失。这套基于PHP的H5新能源超级充电桩多语言版本,恰好把这两点都覆盖了——前端UI做得像正规运营产品,语言包一次配齐中英日泰韩,而且前端切换不用刷新页面。推广上下级绑定是完整的,钱包充提也已跑通,充值走的免签微信支付宝接口,省去申请签约的周期。
对PHP开发者来说,这套源码的价值不只是“能跑”,更在于多语言架构、推广链绑定、支付回调三个模块是完整解耦的,可以直接拆出来复用到其他项目。后端还有xxtea相关源码,说明接口参数做了对称加密,不是裸奔的明文传输。文章后面会按“多语言实现 → 推广绑定与钱包 → XXTEA加密封装 → 部署排错”这个顺序拆开讲,新手能照着部署,老手能参考设计取舍。
2. 多语言切换机制:前端i18n与PHP后端语言栈的配合
2.1 语言包目录结构:把文案和逻辑分开
打开源码先看config目录和语言相关文件夹。这个版本不是用FastAdmin那种后端多语言插件硬怼出来的,而是自己维护了一套语言映射文件。常见做法是在lang/下按语言代码分目录,比如:
lang/ ├── zh-cn/ │ └── common.php ├── en/ │ └── common.php ├── ja/ │ └── common.php ├── th/ │ └── common.php └── ko/ └── common.php每个common.php返回一个关联数组,键名统一,值就是对应语言文案。例如:
<?php // lang/en/common.php return [ 'charge_now' => 'Charge Now', 'recharge' => 'Recharge', 'invite' => 'Invite Friends', 'balance' => 'Balance', ];注意键名的命名规范:全部小写加下划线,不要用中文做键。原因有两点,一是后续如果要接第三方翻译API,下划线命名可以直接转成JSON;二是PHP数组键如果是中文,在某些老版本PHP下会触发编码问题,排查起来很麻烦。
2.2 后端语言切换:Session存语言码,模板动态取词
这套系统的切换逻辑是:前端把语言码(如en)通过AJAX提交到后端,后端存入Session,之后所有模板输出都从当前语言包里取词。后端入口代码大致这样:
<?php // set_lang.php session_start(); $allowed = ['zh-cn', 'en', 'ja', 'th', 'ko']; $lang = $_POST['lang'] ?? 'zh-cn'; if (!in_array($lang, $allowed, true)) { $lang = 'zh-cn'; } $_SESSION['lang'] = $lang; echo json_encode(['code' => 0, 'lang' => $lang]);逻辑说明:这里做了白名单校验,不允许直接传任意字符串,避免语言包文件名被恶意拼接。后一个参数true表示严格比较类型,防止传0这种绕过。
取词时,可以封装一个全局函数:
<?php function L($key) { static $langPack = null; $lang = $_SESSION['lang'] ?? 'zh-cn'; if ($langPack === null) { $langPack = require __DIR__ . "/lang/{$lang}/common.php"; } return $langPack[$key] ?? $key; }这里用静态变量缓存语言包,避免每次取词都include一次文件。如果你用的是ThinkPHP或Laravel,可以直接对接到框架的lang()助手函数,但核心思想一样:当前语言码决定读取哪个文件。
2.3 前端一键切换:AJAX + 刷新关键区块
前端切换按钮不放Form表单,而是用JavaScript发送AJAX请求,成功后刷新页面或者更新局部文本。示例:
function switchLang(lang) { fetch('set_lang.php', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: 'lang=' + encodeURIComponent(lang) }) .then(res => res.json()) .then(data => { if (data.code === 0) { location.reload(); } }); }参数说明:lang直接取按钮上的>CREATE TABLE `user` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL, `invite_code` VARCHAR(20) NOT NULL, `parent_id` INT UNSIGNED DEFAULT NULL, `register_time` INT UNSIGNED NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `idx_invite_code` (`invite_code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
注册时绑定逻辑:
<?php $inviteCode = $_GET['invite_code'] ?? $_COOKIE['invite_code'] ?? ''; $parentId = null; if ($inviteCode) { $stmt = $pdo->prepare("SELECT id FROM user WHERE invite_code = ?"); $stmt->execute([$inviteCode]); $parent = $stmt->fetch(); $parentId = $parent ? $parent['id'] : null; } // 插入用户时带上 $parentId这里有个细节:邀请码通过Cookie也存一份,而不是只靠URL参数。因为用户从推广链接跳转后可能先浏览一会儿再注册,URL中间的广告跳转可能会丢掉参数。Cookie有效期建议设7天,过期后新注册就不再绑定了。
3.2 佣金计算:只算一级,还是多级?
这套源码默认做成二级分销。也就是A邀请B,B消费A拿一级佣金;B邀请C,C消费时A拿二级佣金。佣金比例在后台配置,比如一级10%、二级5%。计算时最忌讳递归查库,用户量上去后性能会崩。正确做法是在下单或充值时,直接累加对应的父级、祖父级钱包余额,并写入佣金流水表。
核心处理:
<?php // 假设 $orderUserId 是消费用户ID,$orderAmount 是消费金额 function grantCommission($pdo, $orderUserId, $orderAmount) { $level1Percent = 0.10; $level2Percent = 0.05; // 查出上级链 $stmt = $pdo->prepare("SELECT id, parent_id FROM user WHERE id = ?"); $stmt->execute([$orderUserId]); $user = $stmt->fetch(); $parentId = $user['parent_id'] ?? null; if (!$parentId) return; // 一级佣金 $l1Money = round($orderAmount * $level1Percent, 2); $pdo->beginTransaction(); try { $pdo->exec("UPDATE user SET balance = balance + {$l1Money} WHERE id = {$parentId}"); // 写佣金流水... $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); } // 二级同理,查 parentId 的 parent }注意:浮点运算一定要用round(..., 2)或者直接用分存储。订单金额10.55元,按百分比计算可能得到3.335,直接加进余额会导致总额偏差。更稳妥的做法是全部以“分”为单位存储,输出时再除以100。
3.3 钱包充值提现:免签支付的回调处理
钱包功能包含充值和提现。充值接入的是免签微信支付宝接口,这类接口的好处是无需企业资质签约,但回调验签逻辑必须自己处理。充值时先生成订单,拿到支付二维码,用户扫码支付后,第三方回调通知PHP服务器,验证通过后把订单标记为已支付并给余额加钱。
支付回调伪代码:
<?php $rawBody = file_get_contents('php://input'); $data = json_decode($rawBody, true); // 免签支付一般会有签名,这里做验签 $sign = $data['sign']; unset($data['sign']); ksort($data); $str = http_build_query($data) . $secretKey; if (md5($str) !== $sign) { exit('sign error'); } // 判断订单状态 $orderNo = $data['order_no']; if ($data['status'] === 'success') { $pdo->beginTransaction(); $stmt = $pdo->prepare("SELECT * FROM recharge_order WHERE order_no = ? FOR UPDATE"); $stmt->execute([$orderNo]); $order = $stmt->fetch(); if ($order && $order['status'] === 'pending') { $pdo->exec("UPDATE recharge_order SET status = 'paid' WHERE order_no = '{$orderNo}'"); $pdo->exec("UPDATE user SET balance = balance + {$order['amount']} WHERE id = {$order['user_id']}"); } $pdo->commit(); echo 'success'; }这里用了FOR UPDATE行锁,防止并发回调导致同一笔订单重复入账。免签接口的坑在于回调可能延迟、重复、甚至丢失,所以必须做幂等处理:订单状态从pending到paid只允许更新一次。
提现流程相对简单:用户提交提现申请,后台人工审核,审核后通过打款接口处理。源码中提现表会记录用户ID、金额、支付账户、状态。
4. XXTEA加密封装:接口参数防篡改的实现细节
4.1 为什么用XXTEA而不是AES?
源码里出现了php_xxtea.c和xxtea.c,说明这是一个PHP扩展或源码级移植的XXTEA算法。XXTEA(Corrected Block TEA)是TEA加密算法的改进版,特点是简单、快速、无需额外安装SQLCipher之类的配件,适合在H5前后端接口通信中做参数加密。
选XXTEA的另一个原因是很多老PHP项目还在用PHP 5.6甚至更早版本,OpenSSL扩展虽然可用,但配置AES的IV、padding等参数复杂,容易踩坑。XXTEA只需要一个密钥,加密后输出Base64字符串,解包逻辑清晰。
代码实现(纯PHP版,完整可运行):
<?php class XXTEA { public static function encrypt($str, $key) { if ($str == '') return ''; $v = self::str2long($str, true); $k = self::str2long($key, false); $n = count($v); $z = $v[$n - 1]; $y = $v[0]; $delta = 0x9E3779B9; $sum = 0; $q = floor(6 + 52 / $n); $p = 0; while ($q-- > 0) { $sum = ($sum + $delta) & 0xFFFFFFFF; $e = ($sum >> 2) & 3; for ($i = 0; $i < $n; $i++) { $y = $v[($i + 1) % $n]; $z = $v[$i] + (($z >> 5 ^ $y << 2) + ($y >> 3 ^ $z << 4) ^ ($sum ^ $y) + ($k[($i & 3) ^ $e] ^ $z)); $v[$i] = $z & 0xFFFFFFFF; } } return self::long2str($v, false); } // 解密切不可省略,否则改一个字符全乱 }参数说明:密钥建议32位随机字符串,前后端保持一致。加密后的数据通常再Base64编码,否则二进制会破坏JSON传输。
4.2 接口参数加签应用场景
在这个充电桩项目里,XXTEA主要用于两个地方:
- 用户ID和邀请码拼接成推广链接时,对参数字符串加密,防止用户在URL中篡改邀请关系。
- 支付回调时对订单号和时间戳加密,防止第三方伪造回调数据。
举例,生成推广链接:
<?php $userId = 1024; $inviteCode = 'ABC123'; $data = json_encode(['uid' => $userId, 'code' => $inviteCode, 'ts' => time()]); $encryptData = base64_encode(XXTEA::encrypt($data, $secretKey)); $url = "https://yourdomain.com/index.php?p=" . urlencode($encryptData);接收方解析:
<?php $p = $_GET['p']; $decryptData = XXTEA::decrypt(base64_decode(urldecode($p)), $secretKey); $info = json_decode($decryptData, true); if (time() - $info['ts'] > 3600) { // 过期链接,拒绝绑定 }这里的时间戳就算防重放攻击。有效期设为1小时,超过则拒绝处理。
4.3 H5打包APP时的加密注意事项
源码支持打包成APP,一般用HBuilder之类的H5打包工具。打包后前端代码是本地文件,HTTP请求还是照常发。如果加密算法只放在PHP后端,前端只是传参数,那没问题。但如果前端也参与解密,切记不要把密钥明文写在JS里。JS是明文可见的,任何人解包都能提取密钥。
解决办法:
- 密钥存放在后端配置文件中,前端只负责传递加密后的密文。
- 如果一定要前端加密,至少混淆JS代码,并且定期更换密钥。
- 接口请求增加设备指纹参数,服务端验证设备ID,发现异常请求直接拒绝。
5. 部署与验证:从上传到多语言切换成功的四个关键检查
部署这套系统建议直接用LNMP环境。PHP版本低于7.0的,先检查加密和语法兼容性。把源码放入站点目录后,第一步先保证config目录下的数据库连接配置正确,第二步开启伪静态。
Nginx伪静态规则参考:
location / { try_files $uri $uri/ /index.php?$query_string; }前端资源里的wdatepicker.js.bak文件是日期插件的备份文件,不是核心依赖。如果打包APP后日期选择器失效,检查是不是缺少了日历插件的中文语言包。
上线最优先验证三件事:
- 多语言切换:访问首页,切换日文、韩文,确认不白屏、文案不缺失。
- 推广链绑定:用两个手机号注册,A邀请B,B充值后看A的余额是否增加。
- 支付回调:用一笔小额充值测试,确认回调后订单状态变为已支付,金额入账。
常见错误处理:如果切换语言后页面CSS乱了,多半是因为语言包文案里包含单引号,导致JS变量被截断。排查时先打开浏览器控制台看SyntaxError,再去语言包对应位置加转义符。
要注意打包APP后location.href和location.reload()在WebView中的行为差异。部分安卓WebView下,location.reload()会丢失Referer,如果前端的免签支付依赖来源判断,就会充值成功但回调校验失败。这时改用window.location.href = currentUrl手动刷新,能绕过这个兼容问题。
本文还有配套的精品资源,点击获取