轻论坛

xiuno 虎皮椒v3在线充值插件lite_pay V1.2

森屿00

启用后会在用户个人中心显示充值选项,输入金额后,会自动生成微信扫码支付二维码,付款后会直接充值到账户余额。余额与积分的兑换比例为1:100,也就是充值1元,可以兑换成100积分。相关文案可以自行查找替换。

后台能够看到充值记录,包括充值用户的用户名、充值金额、充值时间和订单号,方便与虎皮椒后台的订单号核验,本插件仅作技术交流使用,请勿用于非法用途。

使用效果:

LiteBBS旧版本 (2).png

注意:本插件对接的是虎皮椒 V3微信官方支付接口,无需挂机,但需要在虎皮椒 V3侧开通相关渠道并取得APPID和APPSECRET,在插件设置中填入对应的密钥。由于回调接口的限制,需要在网站根目录放置notify.php文件,可以新建该文件后,填入以下内容,否则插件回调会出现异常:

<?php
ini_set('display_errors', '0');
error_reporting(E_ALL & ~E_NOTICE);
set_time_limit(0);

// 仅允许POST方法
if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
    header('Content-Type: text/plain; charset=utf-8');
    echo 'failed';
    exit;
}

// 读取POST数据
$data = $_POST ?: array();
foreach ($data as $k => $v) { $data[$k] = stripslashes($v); }

// 加载配置与支付SDK
define('APP_PATH', rtrim(__DIR__, '/').'/');
define('DEBUG', 0);
$conf_file = APP_PATH . 'conf/conf.php';
if (!file_exists($conf_file)) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
$conf = include $conf_file;
if (!is_array($conf)) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}

$api_file = APP_PATH.'plugin/lite_pay/lib/api.php';
if (!file_exists($api_file)) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
require_once $api_file;

// 数据库配置解析
function xiuno_db_conf_normalize($conf) {
    $host='127.0.0.1'; $user=''; $password=''; $name=''; $port=3306; $charset='utf8mb4'; $tablepre='';
    if (isset($conf['db'])) {
        $db = $conf['db'];
        if (isset($db['mysql'])) {
            $mysql = $db['mysql'];
            $m = isset($mysql['master']) && is_array($mysql['master']) ? $mysql['master'] : (is_array($mysql) ? $mysql : array());
        } else {
            $m = is_array($db) ? $db : array();
        }
        $tablepre = $m['tablepre'] ?? ($db['tablepre'] ?? '');
    } elseif (isset($conf['mysql'])) {
        $m = isset($conf['mysql']['master']) ? $conf['mysql']['master'] : $conf['mysql'];
        $tablepre = $m['tablepre'] ?? '';
    } else {
        $m = array();
    }
    $host     = $m['host']     ?? $host;
    $user     = $m['user']     ?? ($m['username'] ?? $user);
    $password = $m['password'] ?? ($m['passwd']   ?? $password);
    $name     = $m['name']     ?? ($m['dbname']   ?? $name);
    $port     = intval($m['port'] ?? $port);
    $charset  = $m['charset']  ?? $charset;
    return compact('host','user','password','name','port','charset','tablepre');
}
$dbc = xiuno_db_conf_normalize($conf);
if (empty($dbc['user']) || empty($dbc['name'])) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}

// 连接数据库
$mysqli = @mysqli_connect($dbc['host'], $dbc['user'], $dbc['password'], $dbc['name'], $dbc['port']);
if (!$mysqli) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
@mysqli_set_charset($mysqli, $dbc['charset'] ?: 'utf8mb4');

// 判断表是否存在
function table_exists($mysqli, $name) {
    $name_esc = mysqli_real_escape_string($mysqli, $name);
    $sql = "SHOW TABLES LIKE '{$name_esc}'";
    if ($res = mysqli_query($mysqli, $sql)) {
        $ok = mysqli_num_rows($res) > 0;
        mysqli_free_result($res);
        return $ok;
    }
    return false;
}
function resolve_table($base) {
    global $dbc, $mysqli;
    $cands = array();
    if (!empty($dbc['tablepre'])) $cands[] = $dbc['tablepre'].$base;
    if ($dbc['tablepre'] !== 'bbs_') $cands[] = 'bbs_'.$base;
    $cands[] = $base;
    foreach ($cands as $t) {
        if (table_exists($mysqli, $t)) return $t;
    }
    return (!empty($dbc['tablepre']) ? $dbc['tablepre'].$base : $base);
}
$tbl_recharge = resolve_table('recharge_log');
$tbl_user     = resolve_table('user');
$tbl_kv       = resolve_table('kv');

// 从数据库获取支付配置
function kv_get_db($mysqli, $tbl_kv, $key) {
    $sql = "SELECT `v` FROM `{$tbl_kv}` WHERE `k` = ? LIMIT 1";
    $stmt = mysqli_prepare($mysqli, $sql);
    if (!$stmt) return null;
    mysqli_stmt_bind_param($stmt, 's', $key);
    mysqli_stmt_execute($stmt);
    mysqli_stmt_bind_result($stmt, $val);
    $ret = null;
    if (mysqli_stmt_fetch($stmt)) $ret = $val;
    mysqli_stmt_close($stmt);
    if ($ret === null) return null;

    $arr = json_decode($ret, true);
    if (json_last_error() === JSON_ERROR_NONE && is_array($arr)) return $arr;
    $arr = @unserialize($ret);
    if (is_array($arr)) return $arr;
    return $ret;
}
$pay_setting = kv_get_db($mysqli, $tbl_kv, 'pay_setting');
if (!is_array($pay_setting)) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
$conf_appid = trim($pay_setting['appid'] ?? '');
$appsecret  = trim($pay_setting['appsecret'] ?? '');
if (!$appsecret) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}

// 验证参数与签名
if (empty($data['hash']) || empty($data['trade_order_id'])) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
$recv_appid = trim($data['appid'] ?? '');
if ($conf_appid && $recv_appid && $recv_appid !== $conf_appid) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
if (!class_exists('XH_Payment_Api') || !method_exists('XH_Payment_Api','generate_xh_hash')) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}
$sign_data = $data; unset($sign_data['hash']);
$calc_hash = XH_Payment_Api::generate_xh_hash($sign_data, $appsecret);
if (!hash_equals($data['hash'], $calc_hash)) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}

// 只有 status == 'OD' 时才入账(amount单位为分,余额也是分)
$trade_order_id = $data['trade_order_id'];
$status         = $data['status'] ?? '';
$transaction_id = $data['transaction_id'] ?? '';
$total_fee_str  = $data['total_fee'] ?? '';

try {
    if ($status === 'OD') {
        // 查询订单
        $sql = "SELECT `uid`,`status`,`amount` FROM `{$tbl_recharge}` WHERE `out_order_id`=? LIMIT 1";
        $stmt = mysqli_prepare($mysqli, $sql);
        mysqli_stmt_bind_param($stmt, 's', $trade_order_id);
        mysqli_stmt_execute($stmt);
        mysqli_stmt_bind_result($stmt, $uid, $order_status, $order_amount_fen);
        $found = mysqli_stmt_fetch($stmt);
        mysqli_stmt_close($stmt);

        if ($found) {
            if (intval($order_status) === 0) {
                // 开始事务
                if (function_exists('mysqli_begin_transaction')) {
                    mysqli_begin_transaction($mysqli);
                } else {
                    mysqli_query($mysqli, 'START TRANSACTION');
                }

                // 1)更新订单:status=1, plat_order_id, pay_date
                $sql1 = "UPDATE `{$tbl_recharge}` SET `status`=1, `plat_order_id`=?, `pay_date`=? WHERE `out_order_id`=? AND `status`=0";
                $stmt1 = mysqli_prepare($mysqli, $sql1);
                $now = time();
                mysqli_stmt_bind_param($stmt1, 'sis', $transaction_id, $now, $trade_order_id);
                mysqli_stmt_execute($stmt1);
                $aff1 = mysqli_stmt_affected_rows($stmt1);
                mysqli_stmt_close($stmt1);

                if ($aff1 > 0) {
                    // 2)增加用户余额(user.rmbs 单位为分)
                    $add_fen = intval($order_amount_fen);
                    $sql2 = "UPDATE `{$tbl_user}` SET `rmbs` = `rmbs` + ? WHERE `uid` = ?";
                    $stmt2 = mysqli_prepare($mysqli, $sql2);
                    mysqli_stmt_bind_param($stmt2, 'ii', $add_fen, $uid);
                    mysqli_stmt_execute($stmt2);
                    $aff2 = mysqli_stmt_affected_rows($stmt2);
                    mysqli_stmt_close($stmt2);

                    if ($aff2 > 0) {
                        mysqli_commit($mysqli);

                        // 金额一致性检查:平台 total_fee(元)与 amount(分)/100
                        if ($total_fee_str !== '') {
                            $recv_fen = (int) round(floatval($total_fee_str) * 100);
                            if (abs($recv_fen - $add_fen) > 0) {
                                // 金额不一致,仅忽略处理
                            }
                        }
                    } else {
                        mysqli_rollback($mysqli);
                        header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
                    }
                } else {
                    // 并发或失败,复查
                    mysqli_rollback($mysqli);
                    $sqlc = "SELECT `status` FROM `{$tbl_recharge}` WHERE `out_order_id`=? LIMIT 1";
                    $stmtc = mysqli_prepare($mysqli, $sqlc);
                    mysqli_stmt_bind_param($stmtc, 's', $trade_order_id);
                    mysqli_stmt_execute($stmtc);
                    mysqli_stmt_bind_result($stmtc, $stc);
                    $ok = (mysqli_stmt_fetch($stmtc) && intval($stc) === 1);
                    mysqli_stmt_close($stmtc);
                    if (!$ok) {
                        header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
                    }
                }
            }
        } else {
            header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
        }
    }
} catch (Throwable $e) {
    header('Content-Type: text/plain; charset=utf-8'); echo 'failed'; exit;
}

// 返回成功
header('Content-Type: text/plain; charset=utf-8');
echo 'success';
exit;
?>

评论

0
提示: 您必须 登录 后才能查看此内容

推广

推广广告推广广告推广广告