PayOrdersService.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. <?php
  2. namespace App\Services\Common;
  3. use App\Models\PayOrdersModel;
  4. use App\Services\BaseService;
  5. use App\Services\PaymentService;
  6. use App\Services\RedisService;
  7. /**
  8. * 充值缴费订单服务
  9. */
  10. class PayOrdersService extends BaseService
  11. {
  12. /**
  13. * 构造函数
  14. * @author laravel开发员
  15. * @since 2020/11/11
  16. * AccountService constructor.
  17. */
  18. public function __construct()
  19. {
  20. $this->model = new PayOrdersModel();
  21. }
  22. /**
  23. * 获取列表
  24. */
  25. public function getList()
  26. {
  27. $params = request()->all();
  28. $page = $params['page'] ?? 1;
  29. $limit = $params['limit'] ?? 20;
  30. $type = $params['type'] ?? '';
  31. $status = $params['status'] ?? '';
  32. $keyword = $params['keyword'] ?? '';
  33. $startTime = $params['start_time'] ?? '';
  34. $endTime = $params['end_time'] ?? '';
  35. $query = PayOrdersModel::where('mark', 1);
  36. // 类型筛选
  37. if ($type !== '') {
  38. $query->where('type', $type);
  39. }
  40. // 状态筛选
  41. if ($status !== '') {
  42. $query->where('status', $status);
  43. }
  44. // 关键词搜索
  45. if (!empty($keyword)) {
  46. $query->where(function ($q) use ($keyword) {
  47. $q->where('order_no', 'like', "%{$keyword}%")
  48. ->orWhere('account', 'like', "%{$keyword}%")
  49. ->orWhere('transaction_id', 'like', "%{$keyword}%")
  50. ->orWhereHas('user', function ($sq) use ($keyword) {
  51. $sq->where('nickname', 'like', "%{$keyword}%")
  52. ->orWhere('mobile', 'like', "%{$keyword}%");
  53. });
  54. });
  55. }
  56. // 时间范围
  57. if (!empty($startTime)) {
  58. $query->where('create_time', '>=', strtotime($startTime));
  59. }
  60. if (!empty($endTime)) {
  61. $query->where('create_time', '<=', strtotime($endTime . ' 23:59:59'));
  62. }
  63. $total = $query->count();
  64. $list = $query->with(['user:id,nickname,mobile'])
  65. ->orderBy('create_time', 'desc')
  66. ->offset(($page - 1) * $limit)
  67. ->limit($limit)
  68. ->get()
  69. ->toArray();
  70. // 格式化数据
  71. foreach ($list as &$item) {
  72. $item['total'] = number_format($item['total'], 2, '.', '');
  73. $item['discount'] = number_format($item['discount'], 2, '.', '');
  74. $item['pay_total'] = number_format($item['pay_total'], 2, '.', '');
  75. $item['charge_amount'] = number_format($item['charge_amount'] ?? 0, 2, '.', '');
  76. $item['refund_money'] = number_format($item['refund_money'] ?? 0, 2, '.', '');
  77. $item['create_time_text'] = date('Y-m-d H:i:s', strtotime($item['create_time']));
  78. $item['update_time_text'] = date('Y-m-d H:i:s', strtotime($item['update_time']));
  79. $item['pay_at_text'] = $item['pay_at'] ? date('Y-m-d H:i:s', strtotime($item['pay_at'])) : '-';
  80. // 用户信息
  81. if (isset($item['user'])) {
  82. $item['user_nickname'] = $item['user']['nickname'] ?? '';
  83. $item['user_mobile'] = $item['user']['mobile'] ?? '';
  84. }
  85. }
  86. return [
  87. 'code' => 0,
  88. 'msg' => '获取成功',
  89. 'data' => $list,
  90. 'count' => $total
  91. ];
  92. }
  93. /**
  94. * 获取详情
  95. */
  96. public function getInfo($id = null)
  97. {
  98. if ($id === null) {
  99. $id = request()->input('id');
  100. }
  101. $info = PayOrdersModel::where('id', $id)
  102. ->where('mark', 1)
  103. ->with(['user:id,nickname,mobile', 'meal'])
  104. ->first();
  105. if (!$info) {
  106. return ['code' => 1, 'msg' => '记录不存在'];
  107. }
  108. $info = $info->toArray();
  109. $info['total'] = number_format($info['total'], 2, '.', '');
  110. $info['discount'] = number_format($info['discount'], 2, '.', '');
  111. $info['pay_total'] = number_format($info['pay_total'], 2, '.', '');
  112. $info['charge_amount'] = number_format($info['charge_amount'] ?? 0, 2, '.', '');
  113. $info['refund_money'] = number_format($info['refund_money'] ?? 0, 2, '.', '');
  114. $info['create_time_text'] = date('Y-m-d H:i:s', (int)$info['create_time']);
  115. $info['update_time_text'] = date('Y-m-d H:i:s', (int)$info['update_time']);
  116. $info['pay_at_text'] = $info['pay_at'] ? date('Y-m-d H:i:s', strtotime($info['pay_at'])) : '-';
  117. // 三要素验证方式文本
  118. $ytypeMap = [1 => '身份证后6位', 2 => '银行卡后6位', 3 => '营业执照后6位'];
  119. $info['ytype_text'] = $ytypeMap[$info['ytype'] ?? 0] ?? '-';
  120. // 用户信息
  121. if (isset($info['user'])) {
  122. $info['user_nickname'] = $info['user']['nickname'] ?? '';
  123. $info['user_mobile'] = $info['user']['mobile'] ?? '';
  124. }
  125. return [
  126. 'code' => 0,
  127. 'msg' => '获取成功',
  128. 'data' => $info
  129. ];
  130. }
  131. /**
  132. * 删除
  133. */
  134. public function delete()
  135. {
  136. $id = request()->input('id');
  137. $order = PayOrdersModel::where('id', $id)
  138. ->where('mark', 1)
  139. ->first();
  140. if (!$order) {
  141. return ['code' => 1, 'msg' => '记录不存在'];
  142. }
  143. $order->mark = 0;
  144. $order->save();
  145. return ['code' => 0, 'msg' => '删除成功'];
  146. }
  147. /**
  148. * 批量删除
  149. */
  150. public function deleteAll($ids = null)
  151. {
  152. if ($ids === null) {
  153. $ids = request()->input('ids', []);
  154. }
  155. $count = PayOrdersModel::whereIn('id', $ids)
  156. ->where('mark', 1)
  157. ->update(['mark' => 0]);
  158. return [
  159. 'code' => 0,
  160. 'msg' => "成功删除{$count}条记录"
  161. ];
  162. }
  163. /**
  164. * 已支付或充值中的订单
  165. * @return array|mixed
  166. */
  167. public function getCheckOrderList()
  168. {
  169. $cacheKey = "caches:orders:payCheckList";
  170. $datas = RedisService::get($cacheKey);
  171. if ($datas) {
  172. return $datas;
  173. }
  174. $datas = $this->model->where(['mark' => 1])
  175. ->whereIn('status', [2, 3])
  176. ->select(['id', 'order_no', 'transaction_id', 'pay_total as money', 'status'])
  177. ->orderBy('id', 'desc')
  178. ->limit(500)
  179. ->get()
  180. ->keyBy('order_no');
  181. $datas = $datas ? $datas->toArray() : [];
  182. if ($datas) {
  183. $datas = array_chunk($datas, 100);
  184. RedisService::set($cacheKey, $datas, rand(20, 30));
  185. }
  186. return $datas;
  187. }
  188. /**
  189. * 已支付充值失败退款失败订单
  190. * @return array|mixed
  191. */
  192. public function getFailedOrderList()
  193. {
  194. $cacheKey = "caches:orders:failedList";
  195. $datas = RedisService::get($cacheKey);
  196. if ($datas) {
  197. return $datas;
  198. }
  199. $datas = $this->model->where(['refund_status'=>3,'status'=>5,'mark' => 1])
  200. ->select(['id', 'order_no', 'transaction_id', 'pay_total as money', 'status'])
  201. ->orderBy('id', 'desc')
  202. ->limit(500)
  203. ->get()
  204. ->keyBy('order_no');
  205. $datas = $datas ? $datas->toArray() : [];
  206. if ($datas) {
  207. $datas = array_chunk($datas, 100);
  208. RedisService::set($cacheKey, $datas, rand(20, 30));
  209. }
  210. return $datas;
  211. }
  212. /**
  213. * 充值订单退款(补充处理)
  214. * @param $orders
  215. * @return array
  216. * @throws \Yansongda\Pay\Exception\ContainerException
  217. * @throws \Yansongda\Pay\Exception\InvalidParamsException
  218. * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
  219. */
  220. public function failedOrderRefund($orders)
  221. {
  222. $success = [];
  223. if ($orders) {
  224. foreach ($orders as $order) {
  225. $total = isset($order['money']) ? $order['money'] : 0;
  226. $refundStatus = PaymentService::make()->refund($order, 'pay');
  227. $updateData = ['refund_status' => $refundStatus ? 1 : 3, 'status' => 5, 'failed_remark' => '充值失败原路退款','refund_remark'=>PaymentService::make()->getError(), 'refund_money' => $refundStatus ? $total : 0,'refund_at'=>date('Y-m-d H:i:s'), 'update_time' => time()];
  228. if (!PayOrdersModel::where(['id' => $order['id']])->update($updateData)) {
  229. $errors[$order['order_no']] = '充值失败退款处理失败';
  230. } else {
  231. $success[$order['order_no']] = "退款{$total}成功";
  232. $errors[$order['order_no']] = $refundStatus ? '充值失败原路退款' : '充值失败退款失败';
  233. }
  234. sleep(2);
  235. }
  236. }
  237. if($success){
  238. RedisService::clear("caches:orders:failedList");
  239. }
  240. $this->error = '充值订单退款处理成功';
  241. return ['success' => $success, 'errors' => $errors];
  242. }
  243. /**
  244. * 验证订单状态
  245. * @param $orders
  246. * @return array
  247. * @throws \Yansongda\Pay\Exception\ContainerException
  248. * @throws \Yansongda\Pay\Exception\InvalidParamsException
  249. * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
  250. */
  251. public function checkOrder($orders)
  252. {
  253. $nos = array_keys($orders);
  254. $noStr = implode(',', $nos);
  255. $result = DyrPayService::make()->query($noStr);
  256. $datas = isset($result['data']) ? $result['data'] : [];
  257. $errors = [];
  258. $success = [];
  259. if ($datas) {
  260. foreach ($datas as $item) {
  261. $no = isset($item['out_trade_num']) ? $item['out_trade_num'] : '';
  262. $remark = isset($item['remark']) ? $item['remark'] : '充值失败';
  263. $order_number = isset($item['order_number']) ? $item['order_number'] : '';
  264. $charge_amount = isset($item['charge_amount']) ? $item['charge_amount'] : 0;
  265. $charge_kami = isset($item['charge_kami']) ? $item['charge_kami'] : '';
  266. $state = isset($item['state']) ? $item['state'] : -1;
  267. if (in_array($state, [1, 3])) {
  268. $success[$no] = $state;
  269. $updateData = ['status' => $state == 3 ? 6 : 4, 'order_trade_no' => $order_number, 'charge_kami' => $charge_kami, 'charge_amount' => $charge_amount, 'update_time' => time()];
  270. if (!PayOrdersModel::where(['order_no' => $no])->update($updateData)) {
  271. $errors[$no] = '充值处理失败';
  272. }
  273. unset($orders[$no]);
  274. } else if ($state == 0) {
  275. unset($orders[$no]);
  276. $errors[$no] = '充值中';
  277. } else {
  278. $errors[$no] = $remark;
  279. }
  280. }
  281. }
  282. // 未查询到充值记录,批量退款
  283. if ($orders) {
  284. foreach ($orders as $order) {
  285. $total = isset($order['money']) ? $order['money'] : 0;
  286. $refundStatus = PaymentService::make()->refund($order, 'pay');
  287. $updateData = ['refund_status' => $refundStatus ? 1 : 3, 'status' => 5, 'failed_remark' => '充值失败原路退款','refund_remark'=>PaymentService::make()->getError(), 'refund_money' => $refundStatus ? $total : 0,'refund_at'=>date('Y-m-d H:i:s'), 'update_time' => time()];
  288. if (!PayOrdersModel::where(['id' => $order['id']])->update($updateData)) {
  289. $errors[$order['order_no']] = '充值失败退款处理失败';
  290. } else {
  291. $errors[$order['order_no']] = $refundStatus ? '充值失败原路退款' : '充值失败退款失败';
  292. }
  293. sleep(2);
  294. }
  295. }
  296. $this->error = '订单状态验证处理成功';
  297. return ['success' => $success, 'errors' => $errors];
  298. }
  299. }