PaymentLogic.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | likeadmin快速开发前后端分离管理后台(PHP版)
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 开源版本可自由商用,可去除界面版权logo
  7. // | gitee下载:https://gitee.com/likeshop_gitee/likeadmin
  8. // | github下载:https://github.com/likeshop-github/likeadmin
  9. // | 访问官网:https://www.likeadmin.cn
  10. // | likeadmin团队 版权所有 拥有最终解释权
  11. // +----------------------------------------------------------------------
  12. // | author: likeadminTeam
  13. // +----------------------------------------------------------------------
  14. namespace app\common\logic;
  15. use app\common\enum\PayEnum;
  16. use app\common\enum\YesNoEnum;
  17. use app\common\model\effective\EffectiveCategory;
  18. use app\common\model\pay\PayWay;
  19. use app\common\model\recharge\RechargeOrder;
  20. use app\common\model\shops\ShopOrders;
  21. use app\common\model\user\User;
  22. use app\common\service\pay\AliPayService;
  23. use app\common\service\pay\WeChatPayService;
  24. use app\common\service\pay\WorkerWeChatPayService;
  25. use think\Exception;
  26. /**
  27. * 支付逻辑
  28. * Class PaymentLogic
  29. * @package app\common\logic
  30. */
  31. class PaymentLogic extends BaseLogic
  32. {
  33. /**
  34. * @notes 支付方式
  35. * @param $userId
  36. * @param $terminal
  37. * @param $params
  38. * @return array|false
  39. * @author 段誉
  40. * @date 2023/2/24 17:53
  41. */
  42. public static function getPayWay($userId, $terminal, $params)
  43. {
  44. try {
  45. $order = RechargeOrder::findOrEmpty($params['order_id'])->toArray();
  46. if (empty($order)) {
  47. throw new \Exception('待支付订单不存在');
  48. }
  49. //获取支付场景
  50. $pay_way = PayWay::alias('pw')
  51. ->join('dev_pay_config dp', 'pw.pay_config_id = dp.id')
  52. ->where(['pw.scene' => $terminal, 'pw.status' => YesNoEnum::YES])
  53. ->field('dp.id,dp.name,dp.pay_way,dp.icon,dp.sort,dp.remark,pw.is_default')
  54. ->order('pw.is_default desc,dp.sort desc,id asc')
  55. ->select()
  56. ->toArray();
  57. foreach ($pay_way as $k => &$item) {
  58. if ($item['pay_way'] == PayEnum::WECHAT_PAY) {
  59. $item['extra'] = '微信快捷支付';
  60. }
  61. if ($item['pay_way'] == PayEnum::ALI_PAY) {
  62. $item['extra'] = '支付宝快捷支付';
  63. }
  64. if ($item['pay_way'] == PayEnum::BALANCE_PAY) {
  65. $user_money = User::where(['id' => $userId])->value('user_money');
  66. $item['extra'] = '可用余额:' . $user_money;
  67. }
  68. // 充值时去除余额支付
  69. if ($params['from'] == 'recharge' && $item['pay_way'] == PayEnum::BALANCE_PAY) {
  70. unset($pay_way[$k]);
  71. }
  72. }
  73. return [
  74. 'lists' => array_values($pay_way),
  75. 'order_amount' => $order['order_amount'],
  76. ];
  77. } catch (\Exception $e) {
  78. self::setError($e->getMessage());
  79. return false;
  80. }
  81. }
  82. /**
  83. * @notes 获取支付状态
  84. * @param $params
  85. * @return array|false
  86. * @author 段誉
  87. * @date 2023/3/1 16:23
  88. */
  89. public static function getPayStatus($params)
  90. {
  91. try {
  92. $order = RechargeOrder::where(['user_id' => $params['user_id'], 'id' => $params['order_id']])
  93. ->findOrEmpty();
  94. $payTime = empty($order['pay_time']) ? '' : date('Y-m-d H:i:s', $order['pay_time']);
  95. $orderInfo = [
  96. 'order_id' => $order['id'],
  97. 'order_sn' => $order['sn'],
  98. 'order_amount' => $order['order_amount'],
  99. 'pay_way' => PayEnum::getPayDesc($order['pay_way']),
  100. 'pay_status' => PayEnum::getPayStatusDesc($order['pay_status']),
  101. 'pay_time' => $payTime,
  102. ];
  103. if (empty($order)) {
  104. throw new \Exception('订单不存在');
  105. }
  106. return [
  107. 'pay_status' => $order['pay_status'],
  108. 'pay_way' => $order['pay_way'],
  109. 'order' => $orderInfo
  110. ];
  111. } catch (\Exception $e) {
  112. self::setError($e->getMessage());
  113. return false;
  114. }
  115. }
  116. /**
  117. * @notes 获取预支付订单信息
  118. * @param $params
  119. * @return RechargeOrder|array|false|\think\Model
  120. */
  121. public static function getPayOrderInfo($params)
  122. {
  123. try {
  124. $order = RechargeOrder::findOrEmpty($params['order_id']);
  125. if ($order->isEmpty()) {
  126. throw new Exception('订单不存在');
  127. }
  128. //判断订单类型.服务订单尾款处理
  129. if($order['order_type'] == 0 and $order['pay_status'] == PayEnum::ISPAID)//服务工单
  130. {
  131. $order = RechargeOrder::where(['work_id'=>$order['work_id'],'pay_status'=>0])->findOrEmpty();
  132. if($order->isEmpty()){
  133. throw new Exception('订单已支付');
  134. }
  135. }
  136. if ($order['pay_status'] == PayEnum::ISPAID) {
  137. throw new Exception('订单已支付');
  138. }
  139. return $order;
  140. } catch (\Exception $e) {
  141. self::$error = $e->getMessage();
  142. return false;
  143. }
  144. }
  145. /**
  146. * @notes 获取电子商城预支付订单信息
  147. * @param $params
  148. * @return RechargeOrder|array|false|\think\Model
  149. */
  150. public static function getPayShopOrderInfo($params)
  151. {
  152. try {
  153. $order = ShopOrders::findOrEmpty($params['order_id']);
  154. if ($order->isEmpty()) {
  155. throw new Exception('订单不存在');
  156. }
  157. if ($order['pay_status'] == PayEnum::ISPAID) {
  158. throw new Exception('订单已支付');
  159. }
  160. return $order;
  161. } catch (\Exception $e) {
  162. self::$error = $e->getMessage();
  163. return false;
  164. }
  165. }
  166. /**
  167. * @notes 支付
  168. * @param $payWay
  169. * @param $from
  170. * @param $order
  171. * @param $terminal
  172. * @param $redirectUrl
  173. * @return array|false|mixed|string|string[]
  174. * @throws \Exception
  175. * @author mjf
  176. * @date 2024/3/18 16:49
  177. */
  178. public static function pay($payWay, $from, $order, $terminal, $redirectUrl)
  179. {
  180. // 支付编号-仅为微信支付预置(同一商户号下不同客户端支付需使用唯一订单号)
  181. $paySn = $order['sn'];
  182. if ($payWay == PayEnum::WECHAT_PAY) {
  183. $paySn = self::formatOrderSn($order['sn'], $terminal);
  184. }
  185. //更新支付方式
  186. switch ($from) {
  187. case 'recharge':
  188. RechargeOrder::update(['pay_way' => $payWay, 'pay_sn' => $paySn], ['id' => $order['id']]);
  189. break;
  190. case 'goods':
  191. RechargeOrder::update(['pay_way' => $payWay, 'pay_sn' => $paySn], ['id' => $order['id']]);
  192. break;
  193. }
  194. if ($order['order_amount'] == 0) {
  195. PayNotifyLogic::handle($from, $order['sn']);
  196. return ['sn' => $order['sn'],'need_pay'=>0];
  197. }
  198. //todo 测试订单
  199. // if($order['id']==11){
  200. // PayNotifyLogic::handle($from, $order['sn']);
  201. // return ['sn' => $order['sn'],'need_pay'=>0];
  202. // }
  203. $payService = null;
  204. switch ($payWay) {
  205. case PayEnum::WECHAT_PAY:
  206. $payService = (new WeChatPayService($terminal, $order['user_id'] ?? null));
  207. $order['pay_sn'] = $paySn;
  208. $order['redirect_url'] = $redirectUrl;
  209. $result = $payService->pay($from, $order);
  210. break;
  211. case PayEnum::ALI_PAY:
  212. $payService = (new AliPayService($terminal));
  213. $order['redirect_url'] = $redirectUrl;
  214. $result = $payService->pay($from, $order);
  215. break;
  216. default:
  217. self::$error = '订单异常';
  218. $result = false;
  219. }
  220. if (false === $result && !self::hasError()) {
  221. self::setError($payService->getError());
  222. }
  223. $result['need_pay'] = 1;
  224. return $result;
  225. }
  226. /**
  227. * @notes 支付
  228. * @param $payWay
  229. * @param $from
  230. * @param $order
  231. * @param $terminal
  232. * @param $redirectUrl
  233. * @return array|false|mixed|string|string[]
  234. * @throws \Exception
  235. * @author mjf
  236. * @date 2024/3/18 16:49
  237. */
  238. public static function workerPay($payWay, $from, $order, $userInfo, $redirectUrl)
  239. {
  240. $terminal = $userInfo['terminal'];
  241. // 支付编号-仅为微信支付预置(同一商户号下不同客户端支付需使用唯一订单号)
  242. $paySn = $order['sn'];
  243. if ($payWay == PayEnum::WECHAT_PAY) {
  244. $paySn = self::formatOrderSn($order['sn'], $terminal);
  245. }
  246. //更新支付方式
  247. switch ($from) {
  248. case 'recharge':
  249. RechargeOrder::update(['pay_way' => $payWay, 'pay_sn' => $paySn], ['id' => $order['id']]);
  250. break;
  251. case 'goods':
  252. RechargeOrder::update(['pay_way' => $payWay, 'pay_sn' => $paySn], ['id' => $order['id']]);
  253. break;
  254. }
  255. if ($order['order_amount'] == 0) {
  256. PayNotifyLogic::handle($from, $order['sn']);
  257. return ['sn' => $order['sn'],'need_pay'=>0];
  258. }
  259. $payService = null;
  260. switch ($payWay) {
  261. case PayEnum::WECHAT_PAY:
  262. $payService = (new WorkerWeChatPayService($terminal, $userInfo['user_id'] ?? null));
  263. $order['pay_sn'] = $paySn;
  264. $order['redirect_url'] = $redirectUrl;
  265. $result = $payService->pay($from, $order);
  266. break;
  267. default:
  268. self::$error = '订单异常';
  269. $result = false;
  270. }
  271. if (false === $result && !self::hasError()) {
  272. self::setError($payService->getError());
  273. }
  274. $result['need_pay'] = 1;
  275. return $result;
  276. }
  277. /**
  278. * @notes 电子商城支付
  279. * @param $payWay
  280. * @param $from
  281. * @param $order
  282. * @param $terminal
  283. * @param $redirectUrl
  284. * @return array|false|mixed|string|string[]
  285. * @throws \Exception
  286. */
  287. public static function shopPay($payWay, $from, $order, $userInfo, $redirectUrl)
  288. {
  289. $terminal = $userInfo['terminal'];
  290. // 支付编号-仅为微信支付预置(同一商户号下不同客户端支付需使用唯一订单号)
  291. $paySn = $order['sn'];
  292. if ($payWay == PayEnum::WECHAT_PAY) {
  293. $paySn = self::formatOrderSn($order['sn'], $terminal);
  294. }
  295. //更新支付方式
  296. switch ($from) {
  297. case 'shop_goods':
  298. ShopOrders::update(['pay_way' => $payWay, 'pay_sn' => $paySn], ['id' => $order['id']]);
  299. break;
  300. }
  301. if ($order['order_amount'] == 0) {
  302. PayNotifyLogic::handle($from, $order['sn']);
  303. return ['sn' => $order['sn'],'need_pay'=>0];
  304. }
  305. $payService = null;
  306. switch ($payWay) {
  307. case PayEnum::WECHAT_PAY:
  308. $payService = (new WorkerWeChatPayService($terminal, $userInfo['user_id'] ?? null));
  309. $order['pay_sn'] = $paySn;
  310. $order['redirect_url'] = $redirectUrl;
  311. $result = $payService->pay($from, $order);
  312. break;
  313. default:
  314. self::$error = '订单异常';
  315. $result = false;
  316. }
  317. if (false === $result && !self::hasError()) {
  318. self::setError($payService->getError());
  319. }
  320. // $result['need_pay'] = 1;
  321. return $result;
  322. }
  323. /**
  324. * @notes 设置订单号 支付回调时截取前面的单号 18个
  325. * @param $orderSn
  326. * @param $terminal
  327. * @return string
  328. * @author 段誉
  329. * @date 2023/3/1 16:31
  330. * @remark 回调时使用了不同的回调地址,导致跨客户端支付时(例如小程序,公众号)可能出现201,商户订单号重复错误
  331. */
  332. public static function formatOrderSn($orderSn, $terminal)
  333. {
  334. $suffix = mb_substr(time(), -4);
  335. return $orderSn . $terminal . $suffix;
  336. }
  337. }