diff --git a/README.md b/README.md index 2792ad9..f933e55 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- mpay + mpay
@@ -25,7 +25,7 @@ |

gitee

|

github

| | :----------: | :------------: | -| mpay|mpay| +| mpay|mpay| ## ⚙️ 工具特性 @@ -77,17 +77,17 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理 ### 🎯 服务商聚合码 - + 码支付说到底就是通过二维码来进行收款,日常使用的除了微信支付宝生成的二维码外,还有一类二维码是由收款服务商提供的,它能通过一张收款二维码,同时支持**微信**、**支付宝**、**云闪付**等多渠道付款,一般称为**聚合收款码**。 - + 这类收款码扫码之后需要用户自己输入指定金额来进行付款,然后查看收款通知,确认是否到账,最后确认订单支付成功。 就像你去店子里买一瓶水,你扫二维码进去付款界面,就生成了一个订单,你付款成功之后,商店老板会去查看一下商户后台流水,确认订单是否支付成功,这是一个人工审核的过程。 - + 那么码支付的作用,就是让人工审核变成自动审核的,当用户通过网站购买商品的时候,码支付会生成一个订单并展示收银台界面,用户再扫码进入聚合码付款页面。 @@ -97,7 +97,7 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理 同一时间,**码支付后台会自动通过账号密码登陆聚合码服务平台的管理后台**,并通过API接口,循环查询最近的收款明细,通过比对金额和时间,确认是否付款到账,最后确认成功收款。 - + 当用户付款成功,并且后台检测到收款成功消息后,收钱台就会提示收款成功,并最终确认收款。 @@ -107,7 +107,7 @@ V免签是一款开源免费适用于个人收款使用的收款程序,原理 ### 🪁 微信、支付宝收款码 - + 普通的个人收款码,大多使用微信/支付宝来进行收款,依赖于微信/支付宝平台的推送服务和系统通知机制,就可以获取到收款金额的通知信息,从而可以实现支付回调,自动确认收款。 目前主流的方式也是这种,来实现自动收款,简单方便,不过有一些小问题: diff --git a/app/controller/api/PluginController.php b/app/controller/api/PluginController.php index bb5c826..be52126 100644 --- a/app/controller/api/PluginController.php +++ b/app/controller/api/PluginController.php @@ -44,7 +44,7 @@ class PluginController extends BaseController // 添加插件 public function addPlugin(array $option = []) { - $keys = ['platform', 'name', 'class_name', 'price', 'describe', 'website', 'state', 'query']; + $keys = ['platform', 'name', 'class_name', 'price', 'describe', 'website', 'state']; $config = []; foreach ($option as $key => $value) { if (in_array($key, $keys)) { @@ -117,9 +117,7 @@ class PluginController extends BaseController public function pluginEnable() { $info = $this->request->post(); - if ($this->isPluginInstall($info['platform']) == false) { - return json(backMsg(1, '插件未安装')); - } + if (!$this->isPluginInstall($info['platform'])) return json(backMsg(1, '插件未安装')); $up_res = $this->setPlugin($info['platform'], ['state' => $info['state']]); if ($up_res) { return json(backMsg(1, '失败')); @@ -172,9 +170,7 @@ class PluginController extends BaseController private static function getPluginConfig(): array { $payplugin_path = config_path() . '/extend/payplugin.php'; - if (!file_exists($payplugin_path)) { - return []; - } + if (!file_exists($payplugin_path)) return []; // 加载插件配置 $payplugin_config = require $payplugin_path; return $payplugin_config; diff --git a/config/extend/payplugin.php b/config/extend/payplugin.php index aea09ca..bbaaf3b 100644 --- a/config/extend/payplugin.php +++ b/config/extend/payplugin.php @@ -3,45 +3,4 @@ // | 支付插件列表 // +---------------------------------------------------------------------- -return array( - 0 => - array( - 'platform' => 'wxpay', - 'name' => '微信支付', - 'class_name' => 'WxPay', - 'price' => '0.00', - 'describe' => '支持微信个人收款码、赞赏码、经营码、商家码收款,监听回调', - 'website' => 'https://weixin.qq.com/', - 'state' => 1, - ), - 1 => - array( - 'platform' => 'alipay', - 'name' => '支付宝', - 'class_name' => 'AliPay', - 'price' => '0.00', - 'describe' => '支持支付宝个人收款码、经营码收款,监听回调', - 'website' => 'https://www.alipay.com/', - 'state' => 1, - ), - 2 => - array( - 'platform' => 'sqbpay', - 'name' => '收钱吧', - 'class_name' => 'ShouQianBa', - 'price' => '0.00', - 'describe' => '主流移动支付全能收 信用卡,花呗都能用,生意帮手收钱吧,移动收款就用它!', - 'website' => 'https://www.shouqianba.com/', - 'state' => 1, - ), - 3 => - array( - 'platform' => 'alipayb', - 'name' => '支付宝账单', - 'class_name' => 'AliPayb', - 'price' => '99.00', - 'describe' => '支付宝账单查询回调,免挂机,稳定不掉线', - 'website' => 'https://open.alipay.com/', - 'state' => 1, - ), -); +return array(); diff --git a/extend/Plugin.php b/extend/Plugin.php index 7d13e1e..d26dcbf 100644 --- a/extend/Plugin.php +++ b/extend/Plugin.php @@ -4,7 +4,7 @@ declare(strict_types=1); class Plugin { - private static $siteUrl = 'https://api.zhaidashi.cn'; + private static $siteUrl = 'http://localhost:60'; // 获取全部插件(含本地) public static function getAllPlugins(array $local_plugin = []): array { @@ -23,6 +23,7 @@ class Plugin // 获取已安装插件 public static function getInstall(array $local_plugin = []): array { + if (empty($local_plugin)) return []; foreach ($local_plugin as $key => $value) { $local_plugin[$key]['install'] = true; } @@ -33,8 +34,10 @@ class Plugin { $uninstall_plugin = []; $install = []; - foreach ($local_plugin as $e_val) { - $install[] = $e_val['platform']; + if (!empty($local_plugin)) { + foreach ($local_plugin as $e_val) { + $install[] = $e_val['platform']; + } } foreach ($app_plugin as $i_val) { if (in_array($i_val['platform'], $install)) { @@ -50,12 +53,11 @@ class Plugin public static function getAllPlugin(): array { $app_plugin = cache('app_plugin'); - if ($app_plugin) { - return json_decode($app_plugin, true); - } - $app_plugin = self::getHttpResponse(self::$siteUrl . '/mpay/getplugins'); - cache('app_plugin', $app_plugin, 36000); - return json_decode($app_plugin, true); + if ($app_plugin) return $app_plugin; + $app_plugin = self::getHttpResponse(self::$siteUrl . '/mpayapi', ['action' => 'getPluginList']); + $info = json_decode($app_plugin, true); + if ($info['code'] === 0) cache('app_plugin', $info['data'], 36000); + return $info['data']; } // 获取通知消息 public static function getNotifyMessage(): array @@ -69,27 +71,36 @@ class Plugin return json_decode($message, true); } // 请求外部资源 - private static function getHttpResponse($url, $header = [], $post = null, $timeout = 10) + private static function getHttpResponse($url, $post = null, $header = [], $timeout = 10) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); - if ($header) { - curl_setopt($ch, CURLOPT_HTTPHEADER, $header); - } else { - $httpheader[] = "Accept: */*"; - $httpheader[] = "Accept-Language: zh-CN,zh;q=0.9"; - $httpheader[] = "Connection: close"; - curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader); - } - curl_setopt($ch, CURLOPT_HEADER, false); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + $httpheader = [ + "Accept: application/json", + "Accept-Language: zh-CN,zh;q=0.9", + "Connection: close", + "mpayAgent: your_mpay_agent_identifier" + ]; + $httpheader = array_merge($httpheader, $header); if ($post) { + if (!is_string($post)) $post = json_encode($post); + $httpheader[] = "Content-Type: application/json"; + $httpheader[] = "Content-Length: " . strlen($post); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); } + curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($ch); + // 检查 cURL 请求是否出错 + if ($response === false) { + $error = curl_error($ch); + curl_close($ch); + throw new \RuntimeException("cURL error: $error"); + } curl_close($ch); return $response; } diff --git a/view/plugin/index.html b/view/plugin/index.html index 3b8e89f..0f375bf 100644 --- a/view/plugin/index.html +++ b/view/plugin/index.html @@ -71,9 +71,10 @@ { title: '收款平台名称', field: 'name', align: 'center', maxWidth: 180 }, { title: '官网', field: 'name', align: 'left', maxWidth: 220, templet: `
{{= d.website }}
` }, { title: '说明', field: 'describe', align: 'left' }, - { title: '价格', field: 'price', align: 'center', maxWidth: 180, templet: `
{{= d.price==0 ? '免费' : d.price }}
` }, - { title: '状态', field: 'state', align: 'center', maxWidth: 180, templet: `#plugin-state` }, - { title: '操作', align: 'center', maxWidth: 180, fixed: 'right', templet: `#plugin-action` }, + { title: '价格', field: 'price', align: 'center', width: 120, templet: `
{{= d.price==0 ? '免费' : d.price }}
` }, + { title: '状态', field: 'state', align: 'center', width: 120, templet: `#plugin-state` }, + { title: '教程', field: 'helplink', align: 'center', width: 120, templet: `
使用文档
` }, + { title: '操作', align: 'center', width: 180, fixed: 'right', templet: `#plugin-action` }, ]] table.render({ @@ -167,6 +168,25 @@ layer.msg(rec_info.msg, { icon: 2, time: 1200 }); } } + // 安装插件 + plugin.install = async (config) => { + const res = await fetch('/api/Plugin/installPlugin', { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); + if (res.status !== 200) { + layer.msg('请求失败,请重试!', { tips: 2, time: 1200 }); + return false; + } + const rec_info = await res.json(); + + } + // 更新插件 + plugin.update = async (config) => { + const res = await fetch('/api/Plugin/updatePlugin', { method: 'post', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(config) }); + if (res.status!== 200) { + layer.msg('请求失败,请重试!', { tips: 2, time: 1200 }); + return false; + } + const rec_info = await res.json(); + } });