Config.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <?php
  2. /**
  3. * 支付配置控制器 - 字段单独存储版
  4. */
  5. namespace app\admin\controller\pay;
  6. use app\common\controller\Backend;
  7. use think\facade\Db;
  8. class Config extends Backend
  9. {
  10. protected array $noNeedLogin = ['*'];
  11. /**
  12. * 支付配置列表
  13. * @return void
  14. */
  15. public function index(): void
  16. {
  17. $where = [];
  18. // 配置名称搜索
  19. if (!empty($this->request->get('name'))) {
  20. $where[] = ['name', 'like', '%' . $this->request->get('name') . '%'];
  21. }
  22. // 支付类型筛选
  23. if (!empty($this->request->get('type'))) {
  24. $where['type'] = $this->request->get('type');
  25. }
  26. // 状态筛选
  27. if ($this->request->get('status') !== '' && $this->request->get('status') !== null) {
  28. $where['status'] = $this->request->get('status');
  29. }
  30. // 排序
  31. $order = ['id' => 'desc'];
  32. // 分页
  33. $page = $this->request->get('page', 1);
  34. $limit = $this->request->get('limit', 20);
  35. $configList = Db::name('pay_config')
  36. ->where($where)
  37. ->order($order)
  38. ->paginate([
  39. 'list_rows' => $limit,
  40. 'page' => $page
  41. ]);
  42. $list = $configList->items();
  43. foreach ($list as &$item) {
  44. // 添加类型文本
  45. $item['type_text'] = $this->getTypeText($item['type']);
  46. $item['status_text'] = $item['status'] ? '启用' : '禁用';
  47. }
  48. $this->success('查询成功', [
  49. 'list' => $list,
  50. 'total' => $configList->total()
  51. ]);
  52. }
  53. /**
  54. * 获取支付配置详情
  55. * @return void
  56. */
  57. public function detail(): void
  58. {
  59. $id = $this->request->get('id');
  60. if (empty($id)) {
  61. $this->error(__('参数错误'));
  62. }
  63. $config = Db::name('pay_config')
  64. ->where('id', $id)
  65. ->find();
  66. if (!$config) {
  67. $this->error(__('配置不存在'));
  68. }
  69. // 添加类型文本
  70. $config['type_text'] = $this->getTypeText($config['type']);
  71. $this->success('查询成功', $config);
  72. }
  73. /**
  74. * 新增/编辑支付配置
  75. * @return void
  76. */
  77. public function edit(): void
  78. {
  79. $id = $this->request->post('id');
  80. $name = $this->request->post('name');
  81. $type = $this->request->post('type', 1);
  82. $status = $this->request->post('status', 0);
  83. // 通用字段
  84. $appId = $this->request->post('app_id', '');
  85. $mchId = $this->request->post('mch_id', '');
  86. $key = $this->request->post('key', '');
  87. $notifyUrl = $this->request->post('notify_url', '');
  88. $h5NotifyUrl = $this->request->post('h5_notify_url', '');
  89. // 支付宝专用字段
  90. $publicKeyPath = $this->request->post('public_key_path', '');
  91. $privateKeyPath = $this->request->post('private_key_path', '');
  92. if (empty($name)) {
  93. $this->error(__('配置名称不能为空'));
  94. }
  95. if (empty($type)) {
  96. $this->error(__('请选择支付类型'));
  97. }
  98. // 验证配置名称是否已存在(编辑时排除自己)
  99. $checkName = Db::name('pay_config')
  100. ->where('name', $name);
  101. if (!empty($id)) {
  102. $checkName->where('id', '<>', $id);
  103. }
  104. if ($checkName->find()) {
  105. $this->error(__('配置名称已存在'));
  106. }
  107. // 验证必填字段
  108. $validationResult = $this->validateFields($type, [
  109. 'app_id' => $appId,
  110. 'mch_id' => $mchId,
  111. 'key' => $key,
  112. 'notify_url' => $notifyUrl,
  113. 'h5_notify_url' => $h5NotifyUrl,
  114. 'public_key_path' => $publicKeyPath,
  115. 'private_key_path' => $privateKeyPath
  116. ]);
  117. if ($validationResult !== true) {
  118. $this->error($validationResult);
  119. }
  120. $data = [
  121. 'name' => $name,
  122. 'type' => $type,
  123. 'app_id' => $appId,
  124. 'mch_id' => $mchId,
  125. 'key' => $key,
  126. 'notify_url' => $notifyUrl,
  127. 'h5_notify_url' => $h5NotifyUrl,
  128. 'public_key_path' => $type == 2 ? $publicKeyPath : '',
  129. 'private_key_path' => $type == 2 ? $privateKeyPath : '',
  130. 'status' => $status,
  131. 'update_time' => date('Y-m-d H:i:s')
  132. ];
  133. try {
  134. if (!empty($id)) {
  135. // 编辑
  136. $configInfo = Db::name('pay_config')
  137. ->where('id', $id)
  138. ->find();
  139. if (!$configInfo) {
  140. $this->error(__('配置不存在'));
  141. }
  142. // 如果启用此配置,需要禁用同类型的其他配置
  143. if ($status == 1 && $configInfo['status'] == 0) {
  144. Db::name('pay_config')
  145. ->where('type', $type)
  146. ->where('id', '<>', $id)
  147. ->update(['status' => 0]);
  148. }
  149. $result = Db::name('pay_config')
  150. ->where('id', $id)
  151. ->update($data);
  152. $message = '编辑成功';
  153. } else {
  154. // 新增
  155. $data['create_time'] = date('Y-m-d H:i:s');
  156. // 如果启用此配置,需要禁用同类型的其他配置
  157. if ($status == 1) {
  158. Db::name('pay_config')
  159. ->where('type', $type)
  160. ->update(['status' => 0]);
  161. }
  162. $result = Db::name('pay_config')
  163. ->insert($data);
  164. $id = Db::name('pay_config')->getLastInsID();
  165. $message = '新增成功';
  166. }
  167. } catch (\Exception $e) {
  168. $this->error('操作失败: ' . $e->getMessage());
  169. }
  170. if ($result) {
  171. $this->success($message, ['id' => $id]);
  172. } else {
  173. $this->error(__('操作失败'));
  174. }
  175. }
  176. /**
  177. * 验证字段
  178. * @param int $type 支付类型
  179. * @param array $fields 字段值
  180. * @return bool|string
  181. */
  182. private function validateFields(int $type, array $fields)
  183. {
  184. // 通用验证
  185. if (empty($fields['app_id'])) {
  186. return '应用ID不能为空';
  187. }
  188. if (empty($fields['mch_id'])) {
  189. return '商户ID不能为空';
  190. }
  191. if (empty($fields['key'])) {
  192. return 'API密钥不能为空';
  193. }
  194. // 类型特定验证
  195. if ($type == 1) { // 微信支付
  196. if (strlen($fields['key']) < 32) {
  197. return '微信支付API密钥长度必须至少32位';
  198. }
  199. } elseif ($type == 2) { // 支付宝
  200. if (empty($fields['private_key_path'])) {
  201. return '支付宝私钥地址不能为空';
  202. }
  203. }
  204. // URL验证
  205. if (!empty($fields['notify_url']) && !filter_var($fields['notify_url'], FILTER_VALIDATE_URL)) {
  206. return '支付通知地址格式不正确';
  207. }
  208. if (!empty($fields['h5_notify_url']) && !filter_var($fields['h5_notify_url'], FILTER_VALIDATE_URL)) {
  209. return 'H5支付通知地址格式不正确';
  210. }
  211. return true;
  212. }
  213. /**
  214. * 删除支付配置
  215. * @return void
  216. */
  217. public function delete(): void
  218. {
  219. $id = $this->request->post('id');
  220. if (empty($id)) {
  221. $this->error(__('参数错误'));
  222. }
  223. $configInfo = Db::name('pay_config')
  224. ->where('id', $id)
  225. ->find();
  226. if (!$configInfo) {
  227. $this->error(__('配置不存在'));
  228. }
  229. if ($configInfo['status'] == 1) {
  230. $this->error(__('当前配置已启用,请先禁用后再删除'));
  231. }
  232. $result = Db::name('pay_config')
  233. ->where('id', $id)
  234. ->delete();
  235. if ($result) {
  236. $this->success('删除成功');
  237. } else {
  238. $this->error(__('删除失败'));
  239. }
  240. }
  241. /**
  242. * 启用/禁用配置
  243. * @return void
  244. */
  245. public function toggleStatus(): void
  246. {
  247. $id = $this->request->post('id');
  248. if (empty($id)) {
  249. $this->error(__('参数错误'));
  250. }
  251. $configInfo = Db::name('pay_config')
  252. ->where('id', $id)
  253. ->find();
  254. if (!$configInfo) {
  255. $this->error(__('配置不存在'));
  256. }
  257. $newStatus = $configInfo['status'] == 1 ? 0 : 1;
  258. $statusText = $newStatus ? '启用' : '禁用';
  259. try {
  260. // 如果启用此配置,需要禁用同类型的其他配置
  261. if ($newStatus == 1) {
  262. Db::name('pay_config')
  263. ->where('type', $configInfo['type'])
  264. ->where('id', '<>', $id)
  265. ->update(['status' => 0]);
  266. }
  267. $result = Db::name('pay_config')
  268. ->where('id', $id)
  269. ->update([
  270. 'status' => $newStatus,
  271. 'update_time' => date('Y-m-d H:i:s')
  272. ]);
  273. } catch (\Exception $e) {
  274. $this->error('操作失败: ' . $e->getMessage());
  275. }
  276. if ($result) {
  277. $this->success($statusText . '成功');
  278. } else {
  279. $this->error($statusText . '失败');
  280. }
  281. }
  282. /**
  283. * 获取支付类型文本
  284. * @param int $type
  285. * @return string
  286. */
  287. private function getTypeText(int $type): string
  288. {
  289. $map = [
  290. 1 => '微信支付',
  291. 2 => '支付宝支付'
  292. ];
  293. return $map[$type] ?? '未知类型';
  294. }
  295. /**
  296. * 获取支付类型选项
  297. * @return void
  298. */
  299. public function typeOptions(): void
  300. {
  301. $options = [
  302. ['value' => 1, 'label' => '微信支付'],
  303. ['value' => 2, 'label' => '支付宝支付']
  304. ];
  305. $this->success('获取成功', $options);
  306. }
  307. /**
  308. * 获取状态选项
  309. * @return void
  310. */
  311. public function statusOptions(): void
  312. {
  313. $options = [
  314. ['value' => 0, 'label' => '禁用'],
  315. ['value' => 1, 'label' => '启用']
  316. ];
  317. $this->success('获取成功', $options);
  318. }
  319. /**
  320. * 获取支付配置模板
  321. * @return void
  322. */
  323. public function getTemplate(): void
  324. {
  325. $type = $this->request->get('type', 1);
  326. if ($type == 1) { // 微信支付模板
  327. $template = [
  328. 'name' => '微信支付配置',
  329. 'type' => 1,
  330. 'app_id' => 'wx1234567890abcdef',
  331. 'mch_id' => '1234567890',
  332. 'key' => 'your_wechat_api_key_32_characters_long',
  333. 'notify_url' => 'https://your-domain.com/api/pay/wechat/notify',
  334. 'h5_notify_url' => 'https://your-domain.com/api/pay/wechat/h5-notify',
  335. 'public_key_path' => '',
  336. 'private_key_path' => '',
  337. 'status' => 0
  338. ];
  339. } elseif ($type == 2) { // 支付宝模板
  340. $template = [
  341. 'name' => '支付宝支付配置',
  342. 'type' => 2,
  343. 'app_id' => '2021000123456789',
  344. 'mch_id' => '2088101123456789',
  345. 'key' => 'your_alipay_api_key',
  346. 'notify_url' => 'https://your-domain.com/api/pay/alipay/notify',
  347. 'h5_notify_url' => 'https://your-domain.com/api/pay/alipay/h5-notify',
  348. 'public_key_path' => '/path/to/alipay/public_key.pem',
  349. 'private_key_path' => '/path/to/alipay/private_key.pem',
  350. 'status' => 0
  351. ];
  352. } else {
  353. $template = [
  354. 'name' => '',
  355. 'type' => $type,
  356. 'app_id' => '',
  357. 'mch_id' => '',
  358. 'key' => '',
  359. 'notify_url' => '',
  360. 'h5_notify_url' => '',
  361. 'public_key_path' => '',
  362. 'private_key_path' => '',
  363. 'status' => 0
  364. ];
  365. }
  366. $this->success('获取成功', $template);
  367. }
  368. /**
  369. * 获取当前启用的配置
  370. * @return void
  371. */
  372. public function getActiveConfig(): void
  373. {
  374. $type = $this->request->get('type', 1);
  375. $config = Db::name('pay_config')
  376. ->where('type', $type)
  377. ->where('status', 1)
  378. ->find();
  379. if (!$config) {
  380. $this->error('未找到启用的支付配置');
  381. }
  382. $this->success('获取成功', $config);
  383. }
  384. }