如何用PHP项目实现用户自定义风险评估?

wen java案例 11

本文目录导读:

如何用PHP项目实现用户自定义风险评估?

  1. 系统架构设计
  2. 数据库表结构
  3. PHP核心实现
  4. 使用示例
  5. 前端配置界面(Vue.js 示例)
  6. 高级功能建议
  7. 性能优化建议

使用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);
}

性能优化建议

  1. 缓存规则:使用Redis缓存用户规则
  2. 批量评估:支持批量数据评估
  3. 异步执行:使用消息队列处理大批量评估
  4. 规则索引:为常用字段创建索引

这个方案完全支持用户自定义规则,包括条件组合、权重调整、等级配置,适合大多数风控场景。

抱歉,评论功能暂时关闭!