CronLogic.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. <?php
  2. namespace App\Http\Logic\Cron;
  3. use App\Exceptions\CommonException;
  4. use App\Http\Bean\Cron\logic\HandleOrderParamBean;
  5. use App\Http\Bean\Util\Jutuike\GetOrderListParamBean;
  6. use App\Http\Bean\Util\Meituan\OrderListParamBean;
  7. use App\Http\Bean\Util\Pdd\Ddk\OrderListIncrementGetParamBean;
  8. use App\Http\Enum\ErrorEnum;
  9. use App\Http\Enum\OrderStatusEnum;
  10. use App\Http\Enum\PlatformTypeEnum;
  11. use App\Http\Logic\BaseLogic;
  12. use App\Http\Logic\Order\OrderLogic;
  13. use App\Http\Utils\BaseUtil;
  14. use App\Http\Utils\HeiMaUtil;
  15. use App\Http\Utils\Jutuike\JutuikeUtil;
  16. use App\Http\Utils\LoggerFactoryUtil;
  17. use App\Http\Utils\Meituan\MeituanLianmengUtil;
  18. use App\Http\Utils\Pdd\DuoDuoKeUtil;
  19. use App\Http\Utils\WechatAccountUtil;
  20. use App\Models\CategoryModel;
  21. use App\Models\TaobaoPidModel;
  22. use App\Models\UserCashModel;
  23. use App\Models\UserFinanceModel;
  24. use App\Models\UserModel;
  25. use App\Models\UserOrderCommissionModel;
  26. use App\Models\UserOrderModel;
  27. use App\Models\WechatAccountModel;
  28. use EasyWeChat\Factory;
  29. use Illuminate\Support\Facades\DB;
  30. class CronLogic extends BaseLogic
  31. {
  32. /**
  33. * 获取美团订单
  34. */
  35. public static function meituanOrderslogic()
  36. {
  37. $params = request()->all();
  38. $arr = [
  39. "appkey"=>env("MEITUAN_LIANMENG_KEY"),
  40. "type"=>$params["order_type"],
  41. "startTime"=>time()-$params["minute"]*60,
  42. "endTime"=>time(),
  43. // "startTime"=>strtotime("2021-09-22 11:25:00"),
  44. // "endTime"=>time(),
  45. "page"=>1,
  46. "limit"=>30,
  47. "queryTimeType"=>2,
  48. ];
  49. $instance = new LoggerFactoryUtil(CronLogic::class);
  50. $instance->info("获取订单数据开始");
  51. $bean = new OrderListParamBean($arr);
  52. $res = MeituanLianmengUtil::orderList($bean);
  53. // dd($res);
  54. $instance->info("美团返回数据:".json_encode($res));
  55. $instance->info("订单数量:".$res["total"]);
  56. if($res){
  57. //存在数据,写入订单数据表
  58. if($res["total"]){
  59. $instance->info("订单数据:".json_encode($res));
  60. BaseUtil::sendBaoJing("","获取到订单数量:".$res["total"],"定时获取美团订单");
  61. //处理订单
  62. self::checkOrder($res["dataList"],$params["order_type"]);
  63. //判断订单数量是否大于分页
  64. $pageNum = ceil($res["total"]/100)-1;
  65. if($pageNum){
  66. for ($i=1;$i<=$pageNum;$i++){
  67. $arr["page"]++;
  68. $bean = new OrderListParamBean($arr);
  69. $res = MeituanLianmengUtil::orderList($bean);
  70. if ($res) {
  71. //存在数据,写入订单数据表
  72. if ($res["total"]) {
  73. self::checkOrder($res["dataList"],$params["order_type"]);
  74. }
  75. }
  76. }
  77. }
  78. }
  79. }
  80. }
  81. /**
  82. * 处理订单
  83. */
  84. protected static function checkOrder($orders,$orderType)
  85. {
  86. foreach ($orders as $data) {
  87. switch ($data["status"]) {
  88. case 1://已付款
  89. $orderStatus = OrderStatusEnum::ALREADY_PAY;
  90. break;
  91. case 8://已收货
  92. $orderStatus = OrderStatusEnum::ALREADY_RECEIVE;
  93. break;
  94. case 9://已退款或风控
  95. $orderStatus = OrderStatusEnum::ALREADY_REFUND;
  96. break;
  97. }
  98. $params = [
  99. "spreadSonType" => 0,//订单子类型
  100. "orderNumber" => $data["orderid"],//订单编号
  101. "payTime" => date("Y-m-d H:i:s", $data["paytime"]),//支付时间
  102. "orderPrice" => $data["payprice"] * 100,//订单金额
  103. "orderCommission" => $data["profit"] * 100,//订单佣金
  104. "orderTitle" => $data["smstitle"],//订单标题
  105. "orderRefundPrice" => isset($data["refundprice"]) ? $data["refundprice"] * 100 : 0,//退款金额
  106. "orderRefundTime" => isset($data["refundtime"]) ? date("Y-m-d H:i:s", $data["refundtime"]) : null,//退款时间
  107. "orderRefundCommission" => isset($data["refundprofit"]) ? $data["refundprofit"] : 0,//退款佣金
  108. "orderStatus" => $orderStatus,//订单状态
  109. "orderCouponPrice" => 0,//订单优惠
  110. "productImgUrl" => "https://pic.rmb.bdstatic.com/bjh/f049242a789a22fb1a412bb6418c52e2.jpeg",//商品图片
  111. "spreadType"=>PlatformTypeEnum::PLATFORM_MEITUAN,//订单类型
  112. "userSpreadId"=>$data["sid"],//用户推广位
  113. "platformSpreadId"=>$data["sid"],//平台推广位
  114. "createdAt"=>date("Y-m-d H:i:s", $data["paytime"])
  115. ];
  116. $bean = new HandleOrderParamBean($params);
  117. OrderLogic::handleOrderLogic($bean);
  118. }
  119. }
  120. /**
  121. * 聚推客订单逻辑
  122. */
  123. public static function jutuikeOrdersLogic()
  124. {
  125. $params = request()->all();
  126. $startTime = date("Y-m-d H:i:s",time()-600);
  127. $endTime = date("Y-m-d H:i:s");
  128. if(isset($params["start_time"])){
  129. $startTime = $params["start_time"];
  130. }
  131. if (isset($params["end_time"])){
  132. $endTime= $params["end_time"];
  133. }
  134. $page = 1;
  135. $params = [
  136. "start_time"=>$startTime,
  137. "end_time"=>$endTime,
  138. "query_type"=>2,
  139. "page"=>$page,
  140. "pageSize"=>100
  141. ];
  142. $bean = new GetOrderListParamBean($params);
  143. $data = JutuikeUtil::getOrderList($bean);
  144. $instance = new LoggerFactoryUtil(CronLogic::class);
  145. $instance->info("上游返回数据:".json_encode($data));
  146. if($data["code"]!=1){
  147. //上游错误
  148. return;
  149. }
  150. //判断是否存在订单
  151. $orderLists = $data["data"]["data"];
  152. if(count($orderLists)){
  153. BaseUtil::sendBaoJing("","获取到订单数量:".count($orderLists),"定时获取聚推客订单");
  154. }
  155. foreach ($orderLists as $orderList){
  156. self::handleOrderLogic($orderList);
  157. }
  158. }
  159. public static function handleOrderLogic($orderList)
  160. {
  161. //判断订单状态
  162. switch ($orderList["status"]){
  163. case 0://未付款
  164. $orderStatus = OrderStatusEnum::PRE_PAY;
  165. break;
  166. case 1://已付款
  167. $orderStatus = OrderStatusEnum::ALREADY_PAY;
  168. break;
  169. case 2://待结算
  170. $orderStatus = OrderStatusEnum::ALREADY_RECEIVE;
  171. break;
  172. case 3://已结算
  173. $orderStatus = OrderStatusEnum::ALREADY_FINISH;
  174. break;
  175. case 4://无效订单
  176. $orderStatus = OrderStatusEnum::ALREADY_CANCEL;
  177. break;
  178. }
  179. //获取活动图片
  180. $actImgUrl = CategoryModel::query()
  181. ->where("platform_type",PlatformTypeEnum::PLATFORM_JUTUIKE)
  182. ->where("activity_id",$orderList["act_id"])
  183. ->value("category_img_url");
  184. $params = [
  185. "spreadSonType" => 0,//订单子类型
  186. "orderNumber" => $orderList["order_sn"],//订单编号
  187. "payTime" => $orderList["pay_time"],//支付时间
  188. "orderPrice" => $orderList["order_price"] * 100,//订单金额
  189. "orderCommission" => $orderList["jtk_share_fee"] * 100,//订单佣金
  190. "orderTitle" => $orderList["order_title"],//订单标题
  191. "orderRefundPrice" => 0,//退款金额
  192. "orderRefundTime" => null,//退款时间
  193. "orderRefundCommission" => 0,//退款佣金
  194. "orderStatus" => $orderStatus,//订单状态
  195. "orderCouponPrice" => 0,//订单优惠
  196. "productImgUrl" => $actImgUrl,//商品图片
  197. "spreadType"=>PlatformTypeEnum::PLATFORM_JUTUIKE,//订单类型
  198. "userSpreadId"=>$orderList["sid"],//用户推广位
  199. "platformSpreadId"=>$orderList["sid"],//平台推广位
  200. "createdAt"=>$orderList["create_time"],//订单创建时间
  201. ];
  202. $bean = new HandleOrderParamBean($params);
  203. OrderLogic::handleOrderLogic($bean);
  204. }
  205. /**
  206. * 定时获取淘宝订单逻辑
  207. */
  208. public static function taobaoOrdersLogic()
  209. {
  210. //获取黑马授权账号
  211. $heimaDatas = $data = TaobaoPidModel::query()
  212. ->select([DB::raw("any_value(heima_app_key) as heima_app_key"),DB::raw("any_value(heima_app_secret) as heima_app_secret"),"heima_sid"])
  213. ->groupBy("heima_sid")
  214. ->get();
  215. $instance = new LoggerFactoryUtil(CronLogic::class);
  216. foreach ($heimaDatas as $heimaData){
  217. //查询黑马账号下的订单
  218. $orders = HeiMaUtil::getOrderList($heimaData);
  219. if(!isset($orders["publisher_order_dto"])){
  220. break;
  221. }
  222. $orders = $orders["publisher_order_dto"];
  223. if($orders){
  224. BaseUtil::sendBaoJing("","获取到淘宝订单:".count($orders),"定时获取黑马淘客订单");
  225. }
  226. $instance->info("黑马淘客订单:".json_encode($orders));
  227. try{
  228. foreach ($orders as $orderList){
  229. switch ($orderList["tk_status"]){
  230. case 3:
  231. //订单结算
  232. $orderStatus = OrderStatusEnum::ALREADY_RECEIVE;
  233. break;
  234. case 12:
  235. //订单付款
  236. $orderStatus = OrderStatusEnum::ALREADY_PAY;
  237. break;
  238. case 13:
  239. //订单失效
  240. $orderStatus = OrderStatusEnum::ALREADY_CANCEL;
  241. break;
  242. case 14:
  243. //订单成功
  244. $orderStatus = OrderStatusEnum::ALREADY_PAY;
  245. break;
  246. }
  247. $params = [
  248. "spreadSonType" => 0,//订单子类型
  249. "orderNumber" => $orderList["trade_id"],//订单编号
  250. "payTime" => $orderList["tb_paid_time"],//支付时间
  251. "orderPrice" => $orderList["alipay_total_price"]*100,//订单金额
  252. "orderCommission" => $orderList["pub_share_pre_fee"]*100,//订单佣金
  253. "orderTitle" => $orderList["item_title"],//订单标题
  254. "orderRefundPrice" => 0,//退款金额
  255. "orderRefundTime" => null,//退款时间
  256. "orderRefundCommission" => 0,//退款佣金
  257. "orderStatus" => $orderStatus,//订单状态
  258. "orderCouponPrice" => 0,//订单优惠
  259. "productImgUrl" => $orderList["item_img"]??"",//商品图片
  260. "spreadType"=>PlatformTypeEnum::PLATFORM_TAOBAO,//订单类型
  261. "userSpreadId"=>$orderList["adzone_id"],//用户推广位
  262. "platformSpreadId"=>$orderList["adzone_id"],//平台推广位
  263. "createdAt"=>$orderList["tk_create_time"],//订单创建时间
  264. ];
  265. $bean = new HandleOrderParamBean($params);
  266. OrderLogic::handleOrderLogic($bean);
  267. }
  268. }catch (\Throwable $exception){
  269. BaseUtil::sendBaoJing("","淘宝订单更新失败:".$exception->getMessage(),"定时获取黑马淘客订单");
  270. }
  271. }
  272. }
  273. /**
  274. * 获取拼多多订单逻辑
  275. */
  276. public static function pddOrdersLogic()
  277. {
  278. $params = [
  279. "startUpdateTime"=>time()-600,
  280. "endUpdateTime"=>time()
  281. ];
  282. $bean = new OrderListIncrementGetParamBean($params);
  283. $res = DuoDuoKeUtil::orderListIncrementGet($bean);
  284. $instance = new LoggerFactoryUtil(CronLogic::class);
  285. $instance->info("上游返回信息:".json_encode($res));
  286. if (isset($res["error_response"])){
  287. return;
  288. }
  289. if($res["order_list_get_response"]["total_count"]){
  290. BaseUtil::sendBaoJing("","获取到订单数量:".$res["order_list_get_response"]["total_count"],"定时获取拼多多订单");
  291. }
  292. //获取数据
  293. $datas = $res["order_list_get_response"]["order_list"];
  294. foreach ($datas as $orderList){
  295. switch ($orderList["order_status"]){
  296. case 0:
  297. //已支付
  298. $orderStatus = OrderStatusEnum::ALREADY_PAY;
  299. break;
  300. case 1:
  301. //已成团
  302. $orderStatus = OrderStatusEnum::ALREADY_PAY;
  303. break;
  304. case 2:
  305. //确认收货
  306. $orderStatus = OrderStatusEnum::ALREADY_RECEIVE;
  307. break;
  308. case 3:
  309. //审核成功
  310. $orderStatus = OrderStatusEnum::ALREADY_RECEIVE;
  311. break;
  312. case 4:
  313. //审核失败(不可提现)
  314. $orderStatus = OrderStatusEnum::ALREADY_CANCEL;
  315. break;
  316. case 5:
  317. //已经结算
  318. $orderStatus = OrderStatusEnum::ALREADY_RECEIVE;
  319. break;
  320. case 10:
  321. //已处罚
  322. $orderStatus = OrderStatusEnum::ALREADY_CANCEL;
  323. break;
  324. }
  325. $params = [
  326. "spreadSonType" => 0,//订单子类型
  327. "orderNumber" => $orderList["order_sn"],//订单编号
  328. "payTime" => date("Y-m-d H:i:s",$orderList["order_pay_time"]),//支付时间
  329. "orderPrice" => $orderList["order_amount"],//订单金额
  330. "orderCommission" => $orderList["promotion_amount"],//订单佣金
  331. "orderTitle" => $orderList["goods_name"],//订单标题
  332. "orderRefundPrice" => 0,//退款金额
  333. "orderRefundTime" => null,//退款时间
  334. "orderRefundCommission" => 0,//退款佣金
  335. "orderStatus" => $orderStatus,//订单状态
  336. "orderCouponPrice" => 0,//订单优惠
  337. "productImgUrl" => "https://pic.rmb.bdstatic.com/bjh/6d9fb4a81eb5fc933da8949854c4fab2.jpeg",//商品图片
  338. "spreadType"=>PlatformTypeEnum::PLATFORM_PINGDUODUO,//订单类型
  339. "userSpreadId"=>$orderList["p_id"],//用户推广位
  340. "platformSpreadId"=>$orderList["p_id"],//平台推广位
  341. "createdAt"=>date("Y-m-d H:i:s",$orderList["order_create_time"]),//订单创建时间
  342. ];
  343. $bean = new HandleOrderParamBean($params);
  344. OrderLogic::handleOrderLogic($bean);
  345. }
  346. }
  347. /**
  348. * 发送用户下单模版
  349. */
  350. public static function sendOrderTemplateLogic()
  351. {
  352. $instance = new LoggerFactoryUtil(CronLogic::class);
  353. //1.新增粉丝通知
  354. $userFans = UserModel::query()
  355. ->where("invite_user_id","<>",0)
  356. ->where("user_notify_status",0)
  357. ->get();
  358. foreach ($userFans as $userFan){
  359. //获取推荐人
  360. $inviteUser = UserModel::findById($userFan->invite_user_id);
  361. if($inviteUser){
  362. try{
  363. //获取公众号实例
  364. $app = WechatAccountUtil::getAppByID($userFan->wechat_account_id);
  365. $data = [
  366. 'touser' => $inviteUser->user_open_id,
  367. 'template_id' => env("WECHAT_FANS_TEMPLATE_URL"),
  368. 'url' => env("WECHAT_FANS_URL"),
  369. 'data' => [
  370. 'first' => "亲,您有新的粉丝",
  371. 'keyword1' => $userFan->user_nickname,
  372. 'keyword2' => $userFan->id+100000,
  373. "remark"=>"粉丝将提供分享佣金,粉丝越多比例越高哦,点击查看详情"
  374. ],
  375. ];
  376. $res = $app->template_message->send($data);
  377. $instance->info("粉丝通知微信返回结果:".json_encode($res));
  378. }catch (\Throwable $exception){
  379. $instance->info("粉丝通知结果异常:".$exception->getMessage());
  380. }
  381. UserModel::query()->where("id",$userFan->id)->update(
  382. [
  383. "user_notify_status"=>1
  384. ]
  385. );
  386. }
  387. }
  388. //2.获取自购已支付且未通知进行模版推送
  389. $orders = UserOrderCommissionModel::query()
  390. ->where("commission_status",0)
  391. ->where("order_commission",">",0)
  392. ->where("user_id","<>",0)
  393. ->where("order_notify_status",0)
  394. ->limit(10)
  395. ->get();
  396. foreach ($orders as $order){
  397. //判断是否自购订单
  398. if($order->user_provider_id){
  399. //反佣订单
  400. $user = UserModel::findById($order->user_id);
  401. if($user){
  402. try{
  403. //获取公众号实例
  404. $app = WechatAccountUtil::getAppByID($user->wechat_account_id);
  405. $tmpOrder = UserOrderModel::query()->where("order_number",$order->order_number)->first();
  406. $privideUser = UserModel::findById($order->user_provider_id);
  407. $data = [
  408. 'touser' => $user->user_open_id,
  409. 'template_id' => env("WECHAT_FANS_ORDER_TEMPLATE_URL"),
  410. 'url' => env("WECHAT_FANS_ORDER_URL"),
  411. 'data' => [
  412. 'first' => "粉丝下单成功通知",
  413. 'keyword1' => $order->order_number,
  414. 'keyword2' => $tmpOrder->product_name,
  415. 'keyword3' => $order->created_at,
  416. 'keyword4' => round($tmpOrder->order_price/100,2)."元",
  417. 'keyword5' => $privideUser->user_nickname,
  418. "remark"=>"您的粉丝有新的订单,分享佣金已产生,3天后结算到您账户中,点击详情跳转粉丝订单"
  419. ],
  420. ];
  421. $res = $app->template_message->send($data);
  422. $instance->info("粉丝下单微信返回结果:".json_encode($res));
  423. }catch (\Throwable $exception){
  424. $instance->info("粉丝下单通知结果异常:".$exception->getMessage());
  425. }
  426. }
  427. }else{
  428. $user = UserModel::findById($order->user_id);
  429. if($user){
  430. try{
  431. //获取公众号实例
  432. $app = WechatAccountUtil::getAppByID($user->wechat_account_id);
  433. $tmpOrder = UserOrderModel::query()->where("order_number",$order->order_number)->first();
  434. $data = [
  435. 'touser' => $user->user_open_id,
  436. 'template_id' => env("WECHAT_ORDER_TEMPLATE_URL"),
  437. 'url' => env("WECHAT_ORDER_URL"),
  438. 'data' => [
  439. 'first' => "下单成功通知",
  440. 'keyword1' => $order->created_at,
  441. 'keyword2' => $tmpOrder->product_name,
  442. 'keyword3' => $order->order_number,
  443. "remark"=>"感谢您的使用,每月20号结算上个月的佣金,将会结算到您的账户中点击详情跳转我的订单"
  444. ],
  445. ];
  446. $res = $app->template_message->send($data);
  447. $instance->info("自购下单微信返回结果:".json_encode($res));
  448. }catch (\Throwable $exception){
  449. $instance->info("自购下单通知结果异常:".$exception->getMessage());
  450. }
  451. }
  452. }
  453. UserOrderCommissionModel::query()->where("id",$order->id)->update(
  454. [
  455. "order_notify_status"=>1
  456. ]
  457. );
  458. }
  459. //3.获取上月已结算订单,并通知
  460. $completeOrders = UserOrderCommissionModel::query()
  461. ->where("commission_status",1)
  462. ->where("order_commission",">",0)
  463. ->where("user_id","<>",0)
  464. ->where("order_complete_notify_status",0)
  465. ->groupBy("user_id")
  466. ->select(["user_id",DB::Raw("sum(order_commission) as total_order_commission"),DB::Raw("GROUP_CONCAT(id) as ids")])
  467. ->get();
  468. foreach ($completeOrders as $order){
  469. $user = UserModel::findById($order->user_id);
  470. if($user){
  471. try{
  472. //获取公众号实例
  473. $app = WechatAccountUtil::getAppByID($user->wechat_account_id);
  474. $data = [
  475. 'touser' => $user->user_open_id,
  476. 'template_id' => env("WECHAT_COMPLETE_ORDER_TEMPLATE_URL"),
  477. 'url' => env("WECHAT_BALANCE_URL"),
  478. 'data' => [
  479. 'first' => "上月订单佣金已结算完成",
  480. 'keyword1' => round($order["total_order_commission"]/100,2)."元",
  481. 'keyword2' => round($order["total_order_commission"]/100,2)."元",
  482. 'keyword3' => date("Y-m-d H:i:s"),
  483. "remark"=>"订单佣金已结算完成,可以立即提现哦!零钱秒到账"
  484. ],
  485. ];
  486. $res = $app->template_message->send($data);
  487. $instance->info("订单结算微信返回结果:".json_encode($res));
  488. }catch (\Throwable $exception){
  489. $instance->info("订单结算通知结果异常:".$exception->getMessage());
  490. }
  491. }
  492. UserOrderCommissionModel::query()->whereIn("id",explode(",",$order["ids"]))->update(
  493. [
  494. "order_complete_notify_status"=>1
  495. ]
  496. );
  497. }
  498. }
  499. /**
  500. * 结算佣金逻辑(每月的20号18点结算上个月的佣金)
  501. */
  502. public static function settlementOrderCommissionLogic()
  503. {
  504. //获取上个月的开始结束时间
  505. $startTime = date("Y-m-d",strtotime("-1 month"))." 00:00:00";
  506. $endTime = date("Y-m-")."01 00:00:00";
  507. //获取上个月未结算的订单且未退款
  508. //这里有个bug,chunk里面自己改自己会导致有的数据娶不到
  509. UserOrderCommissionModel::query()
  510. ->where("commission_status",0)
  511. ->where("order_commission",">",0)
  512. ->where("user_id","<>",0)
  513. ->where("order_complete_notify_status",0)
  514. ->where("created_at","<",$endTime)
  515. ->chunk(300,function ($orderCommissions){
  516. foreach ($orderCommissions as $orderCommission){
  517. try{
  518. //开启事务
  519. DB::beginTransaction();
  520. //1.修改用户的余额
  521. $user = UserModel::query()->lock(true)->find($orderCommission["user_id"]);
  522. if($user){
  523. $userRes = UserModel::query()
  524. ->where("id",$orderCommission["user_id"])
  525. ->increment("user_balance",$orderCommission["order_commission"]);
  526. if(!$userRes){
  527. DB::rollBack();
  528. throw new CommonException(ErrorEnum::ERROR_SYSTEM);
  529. }
  530. //2.添加用户流水记录
  531. $logRes = UserFinanceModel::query()
  532. ->insert(
  533. [
  534. "user_id"=>$orderCommission["id"],
  535. "order_number"=>$orderCommission["order_number"],
  536. "user_before_balance"=>$user["user_balance"],
  537. "user_after_balance"=>$orderCommission["order_commission"]+$user["user_balance"],
  538. "finance_balance"=>$orderCommission["order_commission"],
  539. "finance_remark"=>"订单佣金结算",
  540. "finance_type"=>1,
  541. "finance_number"=>uniqid("fbt-"),
  542. "created_at"=>date("Y-m-d H:i:s"),
  543. "updated_at"=>date("Y-m-d H:i:s"),
  544. "cash_status"=>1
  545. ]
  546. );
  547. if(!$logRes){
  548. DB::rollBack();
  549. throw new CommonException(ErrorEnum::ERROR_SYSTEM);
  550. }
  551. //3.修改佣金记录为已结算
  552. $commissionRes = UserOrderCommissionModel::query()
  553. ->where("id",$orderCommission["id"])
  554. ->update(
  555. [
  556. "commission_status"=>1,
  557. "updated_at"=>date("Y-m-d H:i:s")
  558. ]
  559. );
  560. if(!$commissionRes){
  561. DB::rollBack();
  562. throw new CommonException(ErrorEnum::ERROR_SYSTEM);
  563. }
  564. DB::commit();
  565. }
  566. }catch (\Throwable $exception){}
  567. }
  568. });
  569. }
  570. /**
  571. * 处理提现打款逻辑
  572. */
  573. public static function transferFinanceLogic()
  574. {
  575. $account = WechatAccountModel::query()
  576. ->where("wechat_app_code","fanbuting")
  577. ->first();
  578. $config = [
  579. "app_id"=>$account["wechat_app_id"],
  580. "mch_id"=>$account["account_mch_id"],
  581. "key"=>$account["account_key"],
  582. "cert_path"=>$account["account_cert_path"],
  583. "key_path"=>$account["account_key_path"]
  584. ];
  585. $app = Factory::payment($config);
  586. //获取已审核且未打款的提现记录
  587. $cashLogs = UserCashModel::query()
  588. ->where("check_status",2)
  589. ->where("cash_status",0)
  590. ->get();
  591. if(!$cashLogs){
  592. return ;
  593. }
  594. //将打款记录修改为执行中
  595. $logIds = [];
  596. foreach ($cashLogs as $cashLog){
  597. $logIds[] = $cashLog["id"];
  598. }
  599. UserCashModel::query()
  600. ->whereIn("id",$logIds)
  601. ->update(
  602. [
  603. "cash_status"=>1
  604. ]
  605. );
  606. foreach ($cashLogs as $cashLog){
  607. //1.获取用户的openId
  608. $user = UserModel::query()->find($cashLog["user_id"]);
  609. if($user){
  610. $res = $app->transfer->toBalance(
  611. [
  612. "partner_trade_no"=>$cashLog["cash_order_number"],
  613. "openid"=>$user["user_open_id"],
  614. "check_name"=>"NO_CHECK",//不校验姓名
  615. "re_user_name"=>"",//真实姓名
  616. "amount"=>$cashLog["cash_money"],
  617. "desc"=>"用户提现"
  618. ]
  619. );
  620. //判断是否支付成功
  621. if($res["return_code"]=="SUCCESS" && $res["result_code"]=="SUCCESS"){
  622. UserCashModel::query()
  623. ->where("id",$cashLog["id"])
  624. ->update(
  625. [
  626. "cash_status"=>2,
  627. "upstream_response"=>json_encode($res),
  628. "cash_receive_at"=>date("Y-m-d H:i:s")
  629. ]
  630. );
  631. $cash_status = 1;//打款成功
  632. }else{
  633. //打款失败
  634. UserCashModel::query()
  635. ->where("id",$cashLog["id"])
  636. ->update(
  637. [
  638. "cash_status"=>3,
  639. "upstream_response"=>json_encode($res)
  640. ]
  641. );
  642. $cash_status = 2;//打款失败
  643. }
  644. //修改提现流水的状态
  645. UserFinanceModel::query()->where("id",$cashLog["user_finance_id"])
  646. ->update(
  647. [
  648. "cash_status"=>$cash_status,
  649. "updated_at"=>date("Y-m-d H:i:s")
  650. ]
  651. );
  652. }
  653. }
  654. }
  655. /**
  656. * 打款失败退款逻辑
  657. */
  658. public static function callbackCashLogic()
  659. {
  660. //获取已审核且未打款的提现记录
  661. $cashLogs = UserCashModel::query()
  662. ->where("callback_status",0)
  663. ->where(function ($query){
  664. $query->where("check_status",3)
  665. ->orWhere("cash_status",3);
  666. })
  667. ->get();
  668. if(!$cashLogs){
  669. return;
  670. }
  671. foreach ($cashLogs as $cashLog){
  672. DB::beginTransaction();
  673. //获取用户
  674. $user = UserModel::query()->lock(true)->find($cashLog["user_id"]);
  675. //1.用户金额增加
  676. $userRes = UserModel::query()
  677. ->where("id",$user["user_id"])
  678. ->increment("user_balance",$cashLog["cash_money"]);
  679. if(!$userRes){
  680. DB::rollBack();
  681. break;
  682. }
  683. //2.添加流水记录
  684. $financeRes = UserFinanceModel::query()->insert(
  685. [
  686. "user_id"=>$cashLog["user_id"],
  687. "user_before_balance"=>$user["user_balance"],
  688. "user_after_balance"=>$user["user_balance"]+$cashLog["cash_money"],
  689. "finance_balance"=>$cashLog["cash_money"],
  690. "finance_remark"=>"提现失败退回,原提现记录ID为:".$cashLog["id"],
  691. "finance_type"=>1,
  692. "finance_number"=>BaseUtil::getOrderNumber(),
  693. "created_at"=>date("Y-m-d H:i:s"),
  694. "updated_at"=>date("Y-m-d H:i:s"),
  695. ]
  696. );
  697. if(!$financeRes){
  698. DB::rollBack();
  699. break;
  700. }
  701. //3.修改提现记录为退款成功
  702. $cashRes = UserCashModel::query()
  703. ->where("id",$cashLog["id"])
  704. ->update([
  705. "callback_status"=>1
  706. ]);
  707. if(!$cashRes){
  708. DB::rollBack();
  709. break;
  710. }
  711. DB::commit();
  712. }
  713. }
  714. }