'支付宝官方', 'description' => '支付宝官方 API 直连,PC + 当面付', 'icon' => 'mdi-alpha-a-circle', ]); // ============================================================ // 配置读取辅助 // ============================================================ function alipay_official_get_config() { return [ 'app_id' => trim((string)mnbt_plugin_option_get('alipay_official', 'app_id', '')), 'private_key' => trim((string)mnbt_plugin_option_get('alipay_official', 'private_key', '')), 'public_key' => trim((string)mnbt_plugin_option_get('alipay_official', 'public_key', '')), 'gateway' => trim((string)mnbt_plugin_option_get('alipay_official', 'gateway', '')), ]; } function alipay_official_is_configured() { $c = alipay_official_get_config(); return $c['app_id'] !== '' && $c['private_key'] !== '' && $c['public_key'] !== ''; } function alipay_official_get_service() { if (!alipay_official_is_configured()) { return null; } return new Alipay_Official_Service(alipay_official_get_config()); } // ============================================================ // 注册支付插件 // ============================================================ mnbt_register_payment('alipay_official', [ 'name' => '支付宝官方', 'description' => '支付宝官方 API 直连(RSA2)', 'icon' => 'mdi-alpha-a-circle', 'methods' => [ 'pc' => ['name' => '支付宝(电脑网站)', 'icon' => 'mdi-desktop-mac'], 'qrcode' => ['name' => '支付宝(扫码)', 'icon' => 'mdi-qrcode-scan'], ], 'build' => function ($method, $order, $plugin_config) { $svc = alipay_official_get_service(); if (!$svc) { error_log('[MNBT alipay_official] 未配置 app_id/private_key/public_key,无法发起支付'); return false; } $siteurl = isset($order['siteurl']) ? $order['siteurl'] : ''; $siteurl = rtrim((string)$siteurl, '/') . '/'; // 回调地址统一用 index.php?_r= 兼容路由:不依赖服务器伪静态重写(同 epay) $notifyUrl = $siteurl . 'index.php?_r=/pay/alipay_official/notify'; $returnUrl = $siteurl . 'index.php?_r=/pay/alipay_official/return'; $params = [ 'out_trade_no' => $order['out_trade_no'], 'total_amount' => $order['money'], 'subject' => $order['name'], 'notify_url' => $notifyUrl, ]; if ($method === 'pc') { $params['return_url'] = $returnUrl; return $svc->buildPagePay($params); } if ($method === 'qrcode') { $result = $svc->buildPrecreate($params); if (empty($result['ok']) || empty($result['qr_code'])) { error_log('[MNBT alipay_official] precreate 失败: ' . json_encode($result['raw'], JSON_UNESCAPED_UNICODE)); return alipay_official_render_qr_error($result); } return alipay_official_render_qr_page($order, $result['qr_code'], $returnUrl); } return false; }, ]); /** * 渲染扫码支付页面(HTML)。 */ function alipay_official_render_qr_page($order, $qrCode, $returnUrl) { $amount = htmlspecialchars((string)$order['money'], ENT_QUOTES, 'UTF-8'); $subject = htmlspecialchars((string)$order['name'], ENT_QUOTES, 'UTF-8'); $orderno = htmlspecialchars((string)$order['out_trade_no'], ENT_QUOTES, 'UTF-8'); $qrEscape = htmlspecialchars($qrCode, ENT_QUOTES, 'UTF-8'); $qrImg = 'https://api.qrserver.com/v1/create-qr-code/?size=240x240&data=' . rawurlencode($qrCode); $returnEsc = htmlspecialchars($returnUrl, ENT_QUOTES, 'UTF-8'); return << 支付宝扫码支付

支付宝扫码支付

{$subject}
¥{$amount}
支付二维码
请使用 支付宝 扫描上方二维码完成支付
支付完成后请点击下方按钮返回
我已完成支付
订单号:{$orderno}
HTML; } /** * 渲染扫码失败页面(HTML)。 */ function alipay_official_render_qr_error($result) { $raw = is_array($result['raw'] ?? null) ? $result['raw'] : []; $msg = $raw['msg'] ?? ($raw['error'] ?? '未知错误'); $sub = $raw['sub_msg'] ?? ''; $msgEsc = htmlspecialchars((string)$msg, ENT_QUOTES, 'UTF-8'); $subEsc = htmlspecialchars((string)$sub, ENT_QUOTES, 'UTF-8'); // 预先计算子消息行,避免在 heredoc 中使用嵌套 {$} 三元表达式(部分 PHP 版本解析异常) $subLine = $subEsc !== '' ? '

' . $subEsc . '

' : ''; return << 支付发起失败

支付发起失败

{$msgEsc}

{$subLine} 返回上一页
HTML; } // ============================================================ // 回调路由:/pay/alipay_official/notify(异步通知) // ============================================================ mnbt_register_route('POST', '/pay/alipay_official/notify', function ($params, $ctx) { @header('Content-Type: text/plain; charset=UTF-8'); $svc = alipay_official_get_service(); if (!$svc) { echo 'fail'; return; } $post = $_POST; if (empty($post)) { mnbt_pay_log('支付宝官方异步通知无数据', '回调异常', ''); echo 'fail'; return; } if (!$svc->verifyNotify($post)) { mnbt_pay_log('支付宝官方异步通知验签失败', '验签失败', $post['out_trade_no'] ?? ''); echo 'fail'; return; } $outTradeNo = isset($post['out_trade_no']) ? (string)$post['out_trade_no'] : ''; $tradeStatus = isset($post['trade_status']) ? (string)$post['trade_status'] : ''; $totalAmount = isset($post['total_amount']) ? (string)$post['total_amount'] : ''; if ($outTradeNo === '') { echo 'fail'; return; } $result = mnbt_pay_settle_order($outTradeNo, $tradeStatus, $totalAmount); if (!empty($result['ok'])) { echo 'success'; } else { echo 'fail'; } }, 10, null, true); // ============================================================ // 回调路由:/pay/alipay_official/return(同步返回) // ============================================================ mnbt_register_route('GET', '/pay/alipay_official/return', function ($params, $ctx) { $base = isset($ctx['base']) ? $ctx['base'] : ''; // 同步返回仅作展示,订单最终状态以异步通知为准 @header('Location: ' . $base . '/user'); }); // ============================================================ // 后台设置页 // ============================================================ mnbt_register_page('admin', 'settings', 'admin/settings.php', '支付宝官方设置'); mnbt_register_settings_tab([ 'title' => '支付宝官方设置', 'page' => 'settings', 'order' => 20, ]); mnbt_register_menu('admin', [ 'title' => '支付宝官方设置', 'page' => 'settings', 'icon' => 'mdi-alpha-a-circle', 'order' => 61, 'multitabs' => true, ]); // ============================================================ // AJAX:保存配置 // ============================================================ mnbt_register_ajax('admin', 'alipay_official_save', function () { mnbt_plugin_require_admin(); $appId = isset($_POST['app_id']) ? trim((string)$_POST['app_id']) : ''; $privateKey = isset($_POST['private_key']) ? trim((string)$_POST['private_key']) : ''; $publicKey = isset($_POST['public_key']) ? trim((string)$_POST['public_key']) : ''; $gateway = isset($_POST['gateway']) ? trim((string)$_POST['gateway']) : ''; if (mb_strlen($appId) > 60) json_exit('APPID 过长'); if (mb_strlen($gateway) > 200) json_exit('网关地址过长'); if (mb_strlen($privateKey) > 4000) json_exit('私钥过长'); if (mb_strlen($publicKey) > 4000) json_exit('公钥过长'); mnbt_plugin_option_set('alipay_official', 'app_id', $appId); mnbt_plugin_option_set('alipay_official', 'private_key', $privateKey); mnbt_plugin_option_set('alipay_official', 'public_key', $publicKey); mnbt_plugin_option_set('alipay_official', 'gateway', $gateway); json_exit('保存成功'); });