// 积分变动接口核心校验逻辑示例
// 1. 验签
function verifySign($params, $receivedSign, $secretKey) {
// 参数按字典序排序,排除sign字段本身
unset($params['sign']);
ksort($params);
$signStr = http_build_query($params) . $secretKey;
$calcSign = hash_hmac('sha256', $signStr, $secretKey);
return hash_equals($calcSign, $receivedSign);
}
// 2. 处理积分变动请求
function handlePointChange($requestParams, $userSession) {
// 校验签名
if (!verifySign($requestParams, $requestParams['sign'], getenv('API_SECRET_KEY'))) {
throw new Exception('签名校验失败,请求被篡改');
}
// 禁止信任前端传递的用户ID,从服务端会话取
$userId = $userSession['user_id'];
// 校验参数合法性
$changeAmount = (int)$requestParams['change_amount'];
$bizNo = $requestParams['biz_no'];
if ($changeAmount == 0) {
throw new Exception('积分变动值不能为0');
}
if ($changeAmount > 1000 || $changeAmount < -5000) {
throw new Exception('积分变动超出业务允许范围');
}
// 幂等性校验:同一个业务单号只能处理一次
$pdo = new PDO('mysql:host=127.0.0.1;dbname=member', 'user', 'pass');
$stmt = $pdo->prepare('SELECT id FROM point_log WHERE biz_no = ? AND user_id = ?');
$stmt->execute([$bizNo, $userId]);
if ($stmt->fetch()) {
throw new Exception('该业务单号已处理,请勿重复提交');
}
// 开启事务处理积分变动
$pdo->beginTransaction();
try {
// 扣减/增加积分
$stmt = $pdo->prepare('UPDATE user_point SET balance = balance + ? WHERE user_id = ?');
$stmt->execute([$changeAmount, $userId]);
// 写入操作日志
$stmt = $pdo->prepare('INSERT INTO point_log (user_id, change_amount, biz_no, ip, create_time) VALUES (?, ?, ?, ?, ?)');
$stmt->execute([$userId, $changeAmount, $bizNo, $_SERVER['REMOTE_ADDR'], time()]);
$pdo->commit();
return ['code' => 0, 'msg' => '处理成功', 'new_balance' => getPointBalance($userId)];
} catch (Exception $e) {
$pdo->rollBack();
throw $e;
}
}
然后第四部分是总结与建议,要落地,比如“这套方案的核心是「不信任任何前端传递的参数」,所有核心标识、数值都要从服务端获取或二次校验,同时配合签名、幂等、日志三板斧,基本可以覆盖99%的常见篡改场景。上线前一定要做渗透测试,尝试抓包改参数、重放请求、重复提交,验证校验逻辑是否生效。”
然后第五部分是延伸阅读,自然引出那个如需更完整的 PHP 代码保护与在线加密服务,可访问 https://article.vvxyz.com 了解更多。