本文目录导读:

使用PHP实现用户自定义风险评估系统,建议采用规则引擎 + 权重计算的模式,以下是完整的实现方案,包含数据结构、算法和代码示例。
系统架构设计
用户自定义规则 → 规则解析器 → 权重引擎 → 风险评分 → 等级判定
数据库表结构
1 规则配置表 (risk_rules)
CREATE TABLE risk_rules (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
rule_name VARCHAR(100) NOT NULL,
rule_description TEXT,
risk_level ENUM('low', 'medium', 'high', 'critical') NOT NULL,
base_score DECIMAL(5,2) DEFAULT 0.00,
weight DECIMAL(3,2) DEFAULT 1.00,
is_active TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
2 条件配置表 (risk_conditions)
CREATE TABLE risk_conditions (
id INT AUTO_INCREMENT PRIMARY KEY,
rule_id INT NOT NULL,
field_name VARCHAR(50) NOT NULL, -- 评估字段如amount, age, ip等
operator ENUM('=', '!=', '>', '<', '>=', '<=', 'IN', 'BETWEEN', 'LIKE') NOT NULL,
value1 VARCHAR(255) NOT NULL,
value2 VARCHAR(255) DEFAULT NULL, -- 用于BETWEEN等操作符
logic_operator ENUM('AND', 'OR') DEFAULT 'AND',
priority INT DEFAULT 0,
FOREIGN KEY (rule_id) REFERENCES risk_rules(id) ON DELETE CASCADE
);
3 评估记录表 (risk_assessments)
CREATE TABLE risk_assessments (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
rule_id INT,
entity_id VARCHAR(50), -- 被评估对象ID
input_data JSON,
total_score DECIMAL(5,2),
risk_level ENUM('low', 'medium', 'high', 'critical'),
matched_rules JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
PHP核心实现
1 规则引擎类
<?php
namespace App\RiskEngine;
class RiskEngine {
private $db;
private $rules = [];
public function __construct(\PDO $db) {
$this->db = $db;
}
/**
* 加载用户的自定义规则
*/
public function loadUserRules(int $userId): void {
$stmt = $this->db->prepare("
SELECT r.*, c.field_name, c.operator, c.value1, c.value2,
c.logic_operator, c.priority
FROM risk_rules r
LEFT JOIN risk_conditions c ON r.id = c.rule_id
WHERE r.user_id = ? AND r.is_active = 1
ORDER BY r.id, c.priority
");
$stmt->execute([$userId]);
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
$this->rules[$row['rule_id']]['rule'] = [
'id' => $row['rule_id'],
'name' => $row['rule_name'],
'level' => $row['risk_level'],
'base_score' => $row['base_score'],
'weight' => $row['weight']
];
if ($row['field_name']) {
$this->rules[$row['rule_id']]['conditions'][] = [
'field' => $row['field_name'],
'operator' => $row['operator'],
'value1' => $row['value1'],
'value2' => $row['value2'],
'logic' => $row['logic_operator']
];
}
}
}
/**
* 执行风险评估
*/
public function evaluate(array $inputData): array {
$matchedRules = [];
$totalScore = 0;
foreach ($this->rules as $ruleId => $ruleData) {
$conditionResults = [];
foreach ($ruleData['conditions'] as $condition) {
$fieldValue = $inputData[$condition['field']] ?? null;
$result = $this->evaluateCondition($fieldValue, $condition);
$conditionResults[] = [
'condition' => $condition,
'result' => $result
];
}
if ($this->evaluateLogic($conditionResults, $ruleData['rule'])) {
$matchedRules[] = $ruleData['rule'];
$score = $ruleData['rule']['base_score'] * $ruleData['rule']['weight'];
$totalScore += $score;
}
}
return [
'total_score' => $totalScore,
'matched_rules' => $matchedRules,
'risk_level' => $this->determineRiskLevel($totalScore),
'details' => $conditionResults
];
}
/**
* 评估单个条件
*/
private function evaluateCondition($fieldValue, array $condition): bool {
$operator = $condition['operator'];
$value1 = $condition['value1'];
$value2 = $condition['value2'] ?? null;
switch ($operator) {
case '=':
return $fieldValue == $value1;
case '!=':
return $fieldValue != $value1;
case '>':
return floatval($fieldValue) > floatval($value1);
case '<':
return floatval($fieldValue) < floatval($value1);
case '>=':
return floatval($fieldValue) >= floatval($value1);
case '<=':
return floatval($fieldValue) <= floatval($value1);
case 'IN':
$values = explode(',', $value1);
return in_array($fieldValue, $values);
case 'BETWEEN':
return floatval($fieldValue) >= floatval($value1) &&
floatval($fieldValue) <= floatval($value2);
case 'LIKE':
return preg_match('/' . preg_quote($value1, '/') . '/i', $fieldValue);
default:
return false;
}
}
/**
* 执行逻辑运算
*/
private function evaluateLogic(array $results, array $rule): bool {
if (empty($results)) {
return false;
}
$finalResult = $results[0]['result'];
for ($i = 1; $i < count($results); $i++) {
$logic = $results[$i]['condition']['logic'];
$result = $results[$i]['result'];
if ($logic === 'AND') {
$finalResult = $finalResult && $result;
} else {
$finalResult = $finalResult || $result;
}
// 短路优化
if (!$finalResult) {
return false;
}
}
return $finalResult;
}
/**
* 确定风险等级
*/
private function determineRiskLevel(float $score): string {
if ($score >= 80) return 'critical';
if ($score >= 60) return 'high';
if ($score >= 30) return 'medium';
return 'low';
}
}
2 用户规则管理控制器
<?php
namespace App\Controllers;
class RiskRuleController {
private $db;
public function __construct(\PDO $db) {
$this->db = $db;
}
/**
* 创建自定义规则
*/
public function createRule(array $data): int {
$this->db->beginTransaction();
try {
// 插入规则主表
$stmt = $this->db->prepare("
INSERT INTO risk_rules (user_id, rule_name, rule_description, risk_level, base_score, weight)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$data['user_id'],
$data['rule_name'],
$data['rule_description'] ?? '',
$data['risk_level'],
$data['base_score'],
$data['weight'] ?? 1.00
]);
$ruleId = $this->db->lastInsertId();
// 插入条件
if (!empty($data['conditions'])) {
$stmt = $this->db->prepare("
INSERT INTO risk_conditions (rule_id, field_name, operator, value1, value2, logic_operator, priority)
VALUES (?, ?, ?, ?, ?, ?, ?)
");
foreach ($data['conditions'] as $priority => $condition) {
$stmt->execute([
$ruleId,
$condition['field_name'],
$condition['operator'],
$condition['value1'],
$condition['value2'] ?? null,
$condition['logic_operator'] ?? 'AND',
$priority
]);
}
}
$this->db->commit();
return $ruleId;
} catch (\Exception $e) {
$this->db->rollBack();
throw $e;
}
}
/**
* 更新规则
*/
public function updateRule(int $ruleId, array $data): void {
$this->db->beginTransaction();
try {
// 更新规则主表
$stmt = $this->db->prepare("
UPDATE risk_rules SET
rule_name = ?, rule_description = ?, risk_level = ?,
base_score = ?, weight = ?, updated_at = NOW()
WHERE id = ?
");
$stmt->execute([
$data['rule_name'],
$data['rule_description'],
$data['risk_level'],
$data['base_score'],
$data['weight'],
$ruleId
]);
// 删除旧条件
$this->db->prepare("DELETE FROM risk_conditions WHERE rule_id = ?")
->execute([$ruleId]);
// 插入新条件
if (!empty($data['conditions'])) {
$stmt = $this->db->prepare("
INSERT INTO risk_conditions (rule_id, field_name, operator, value1, value2, logic_operator, priority)
VALUES (?, ?, ?, ?, ?, ?, ?)
");
foreach ($data['conditions'] as $priority => $condition) {
$stmt->execute([
$ruleId,
$condition['field_name'],
$condition['operator'],
$condition['value1'],
$condition['value2'],
$condition['logic_operator'],
$priority
]);
}
}
$this->db->commit();
} catch (\Exception $e) {
$this->db->rollBack();
throw $e;
}
}
}
使用示例
<?php
// 示例:创建用户自定义规则
$controller = new RiskRuleController($db);
$ruleData = [
'user_id' => 1,
'rule_name' => '大额交易风控',
'rule_description' => '检测异常大额交易',
'risk_level' => 'high',
'base_score' => 50,
'weight' => 1.5,
'conditions' => [
[
'field_name' => 'amount',
'operator' => '>',
'value1' => '10000',
'logic_operator' => 'AND'
],
[
'field_name' => 'frequency',
'operator' => '>',
'value1' => '5',
'logic_operator' => 'AND'
]
]
];
$ruleId = $controller->createRule($ruleData);
// 执行评估
$engine = new RiskEngine($db);
$engine->loadUserRules(1);
$inputData = [
'amount' => 15000,
'frequency' => 10,
'user_age' => 35,
'ip_address' => '192.168.1.1'
];
$result = $engine->evaluate($inputData);
echo "风险评分: " . $result['total_score'] . "\n";
echo "风险等级: " . $result['risk_level'] . "\n";
echo "匹配规则: " . json_encode($result['matched_rules']) . "\n";
前端配置界面(Vue.js 示例)
<template>
<div class="risk-rule-form">
<h3>创建自定义风控规则</h3>
<div class="form-group">
<label>规则名称</label>
<input v-model="rule.rule_name" />
</div>
<div v-for="(condition, index) in rule.conditions" :key="index">
<div class="condition-row">
<select v-model="condition.field_name">
<option value="amount">交易金额</option>
<option value="frequency">交易频率</option>
<option value="age">用户年龄</option>
<option value="ip">IP地址</option>
</select>
<select v-model="condition.operator">
<option value=">">大于</option>
<option value="<">小于</option>
<option value="=">等于</option>
<option value="IN">包含</option>
</select>
<input v-model="condition.value1" placeholder="值" />
<select v-model="condition.logic_operator">
<option value="AND">lt;/option>
<option value="OR">或者</option>
</select>
<button @click="removeCondition(index)">删除</button>
</div>
</div>
<button @click="addCondition">添加条件</button>
<button @click="submitRule">保存规则</button>
</div>
</template>
<script>
export default {
data() {
return {
rule: {
rule_name: '',
risk_level: 'medium',
base_score: 30,
weight: 1,
conditions: [{
field_name: 'amount',
operator: '>',
value1: '',
logic_operator: 'AND'
}]
}
}
},
methods: {
addCondition() {
this.rule.conditions.push({
field_name: '',
operator: '>',
value1: '',
logic_operator: 'AND'
});
},
removeCondition(index) {
this.rule.conditions.splice(index, 1);
},
async submitRule() {
// 调用API保存规则
const response = await fetch('/api/risk-rules', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(this.rule)
});
if (response.ok) {
alert('规则创建成功');
}
}
}
}
</script>
高级功能建议
1 规则模板
// 预定义规则模板
$templates = [
'high_amount' => [
'name' => '大额交易',
'conditions' => [
['field' => 'amount', 'operator' => '>', 'value' => 10000]
],
'base_score' => 40
],
'frequent_trading' => [
'name' => '频繁交易',
'conditions' => [
['field' => 'frequency', 'operator' => '>', 'value' => 10]
],
'base_score' => 30
]
];
2 规则优先级和冲突处理
// 规则优先级排序
usort($this->rules, function($a, $b) {
return $b['rule']['weight'] - $a['rule']['weight'];
});
// 冲突处理:取最高评分
if ($override) {
$finalScore = max($scores);
} else {
$finalScore = array_sum($scores);
}
性能优化建议
- 缓存规则:使用Redis缓存用户规则
- 批量评估:支持批量数据评估
- 异步执行:使用消息队列处理大批量评估
- 规则索引:为常用字段创建索引
这个方案完全支持用户自定义规则,包括条件组合、权重调整、等级配置,适合大多数风控场景。