diff --git a/app/controller/api/PayManageController.php b/app/controller/api/PayManageController.php index 08f11bf..5e60a06 100644 --- a/app/controller/api/PayManageController.php +++ b/app/controller/api/PayManageController.php @@ -159,6 +159,42 @@ class PayManageController extends BaseController return json(backMsg(1, '上传失败')); } } + // 获取账号交易流水 + public function getAccountTrade() + { + $req_info = $this->request->get(); + $req_pid = $req_info['pid']; + $req_aid = $req_info['aid']; + // 加载配置文件 + $config = \think\facade\Config::load("payconfig/{$req_pid}_{$req_aid}", 'payconfig'); + // 收款平台账号配置 + $pay_config = isset($config['pay']) ? $config['pay'] : []; + // 配置检查 + if ($pay_config) { + // 账号配置信息 + $aid = $pay_config['aid']; + if ($req_aid != $aid) return '监听收款配置不一致'; + } else { + return '监听收款配置文件名错误'; + } + // 登陆账号 + $config = ['username' => $pay_config['account'], 'password' => $pay_config['password']]; + // 收款查询 + $query = $pay_config['query']; + // 实例监听客户端 + $payclient_name = $pay_config['payclass']; + $payclient_path = "\\payclient\\{$payclient_name}"; + $Payclient = new $payclient_path($config); + // 获取支付明细 + $records = $Payclient->getOrderInfo($query); + if ($records) { + // 收款流水 + return json(backMsg(0, '查询成功', $records)); + } else { + return json(backMsg(1, '查询空订单')); + } + } + // 生成账号配置 private function createAccountConfig($acc) { diff --git a/public/static/js/helper.js b/public/static/js/helper.js new file mode 100644 index 0000000..8a44c99 --- /dev/null +++ b/public/static/js/helper.js @@ -0,0 +1,112 @@ +// 插件配置 +const plugins = [ + { + name: '收钱吧', + host: 'web-platforms-msp.shouqianba.com', + method: 'POST', + orderQuery: '/api/transaction/findTransactions', + channelKey: 'terminal_device_fingerprint', + moneyKey: 'original_amount', + listPath: 'data.records' + } +]; + +// 登陆配置 +const logins = [ + { + name: '新商城', + host: 'localhost', + method: 'GET', + orderQuery: '/api/Order/getOrders', + accPath: 'order_id', + pswPath: 'money', + } +]; + +// 提取订单信息 +function extractOrderInfo(response, plugins) { + plugins.forEach((plugin) => { + const urlObj = new URL(response.url); + if (plugin.host === urlObj.hostname + && plugin.orderQuery === urlObj.pathname + && plugin.method === response.method) { + const jsonDatas = JSON.parse(response.response); + const orderDatas = eval(`jsonDatas.${plugin.listPath}`); + let lists = []; + orderDatas.forEach((orderData) => { + const data = { + '终端编号': orderData[plugin.channelKey], + '订单金额': orderData[plugin.moneyKey] + }; + lists.push(data); + }) + console.log(plugin.name); + console.table(lists); + } + }) +} + +// 提取登陆信息 +function extractLoginInfo(request, logins) { + logins.forEach((login) => { + const urlObj = new URL(request.url); + if (login.host === urlObj.hostname + && login.orderQuery === urlObj.pathname + && login.method === request.method) { + const jsonData = JSON.parse(request.request); + const acc = eval(`jsonData.${login.accPath}`); + const psw = eval(`jsonData.${login.pswPath}`); + const data = { + '账号': acc, + '密码': psw + }; + console.log(login.name); + console.table(data); + } + }) +} + +// XHR 重写 +var oldOpen = XMLHttpRequest.prototype.open; +var oldSend = XMLHttpRequest.prototype.send; +XMLHttpRequest.prototype.open = function (method, url) { + this._url = url; + this._method = method; + const res = { + url: this.responseURL, + method: this._method, + response: this._body + } + extractLoginInfo(res, logins); + return oldOpen.apply(this, arguments); +}; +XMLHttpRequest.prototype.send = function (body) { + this._body = body; + this.addEventListener('load', function () { + const res = { + url: this.responseURL, + method: this._method, + response: this.responseText + } + console.log(res); + + extractOrderInfo(res, plugins); + }); + return oldSend.apply(this, arguments); +}; + +// fetch 重写 +window.au_fetch = window.fetch; +window.fetch = function (url, options) { + // console.log('Fetch URL:', url); + // console.log('Fetch Options:', options); + return window.au_fetch.apply(window, [url, options]).then((response) => { + const res = { + url: url, + method: options.method, + response: response.text() + } + extractOrderInfo(res, plugins); + return response; + }); +}; \ No newline at end of file diff --git a/view/pay_manage/add_channel.html b/view/pay_manage/add_channel.html index cb5ef4f..c9f60bb 100644 --- a/view/pay_manage/add_channel.html +++ b/view/pay_manage/add_channel.html @@ -40,6 +40,11 @@ +
+
+

终端编号如何填写,请查看文档

+
+
diff --git a/view/pay_manage/index.html b/view/pay_manage/index.html index b892c9e..48f79b4 100644 --- a/view/pay_manage/index.html +++ b/view/pay_manage/index.html @@ -5,6 +5,11 @@ 收款管理 + @@ -119,6 +124,7 @@ { title: '启用状态', field: 'state', align: 'center', templet: '#account-state' }, { title: '监听模式', field: 'pattern', align: 'center' }, { title: '监听地址 / 自定义模版', field: 'checkUrl', align: 'center', minWidth: 300, event: 'copy', templet: '#account-checkUrl' }, + { title: '收款平台流水', field: 'trade', align: 'center', templet: '
查询
' }, { title: '收款码数量', field: 'channel', align: 'center', templet: '
{{= d.channel }}
' }, { title: '操作', align: 'center', fixed: 'right', templet: '
编辑
' } ]] @@ -147,18 +153,21 @@ account.editAccount(id); } else if (obj.event === 'channelList') { account.channelList(id); + } else if (obj.event === 'queryTrade') { + const url = this.getAttribute('data-url'); + account.getAccountTrade(url); } }); table.on('toolDouble(account-table)', function (obj) { if (obj.event === 'copy') { const text = obj.tr[0].querySelector('td[data-field="checkUrl"]>div').innerText; if (navigator.clipboard) { - navigator.clipboard.writeText(text).then(() => { - layer.msg('复制成功'); - }); - } else { - layer.msg('复制失败,请手动复制'); - } + navigator.clipboard.writeText(text).then(() => { + layer.msg('复制成功'); + }); + } else { + layer.msg('复制失败,请手动复制'); + } } }); // 表格头部按钮事件 @@ -274,6 +283,32 @@ content: `/Order/testPay`, }); } + + // 查询平台收银流水 + account.getAccountTrade = async function (url) { + const res = await fetch(url); + if (res.status !== 200) { + layer.msg('请求失败,请重试!', { tips: 2, time: 1200 }); + return false; + } + const rec_info = await res.json(); + if (rec_info.code === 0) { + const data = rec_info.data; + let html = ''; + data.forEach(order => { + html += `${order.order_no}${order.channel}${order.price}${order.payway}`; + }); + layer.open({ + type: 1, + title: '收银流水(近3分钟)', + area: ['720px', '480px'], + content: `` + }); + } else { + layer.msg(rec_info.msg, { icon: 2, time: 1200 }); + } + } + // 请求封装 async function httpJSON(url, info) { const res = await fetch(url, { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(info) });