CallbackService.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. <?php
  2. namespace app\api\service;
  3. use addons\fastchat\library\Chat;
  4. use app\admin\model\membership\Config;
  5. use app\api\model\order\Order;
  6. use app\api\model\order\Progress;
  7. use app\api\model\system\Message;
  8. use app\api\model\ThirdPayLog;
  9. use app\api\model\User;
  10. use app\api\model\user\Bill;
  11. use app\api\model\user\Vip;
  12. use app\api\model\user\Voucher;
  13. use app\api\model\user\Wallet;
  14. use redis\RedLock;
  15. use think\Db;
  16. use think\Exception;
  17. use think\Log;
  18. class CallbackService extends BaseService
  19. {
  20. private $userWalletModel;
  21. private $userBillModel;
  22. private $orderModel;
  23. private $thirdPayService;
  24. private $thirdPayLogModel;
  25. public function __construct()
  26. {
  27. $this->orderModel = new Order();
  28. $this->userWalletModel = new Wallet();
  29. $this->userBillModel = new Bill();
  30. $this->thirdPayService = new ThirdPayService();
  31. $this->thirdPayLogModel = new ThirdPayLog();
  32. }
  33. public function payOrderSuccess($out_trade_no)
  34. {
  35. $redLock = RedLock::of();
  36. $order = $this->orderModel->where([
  37. "no" => $out_trade_no,
  38. "status" => \E_ORDER_STATUS::Default
  39. ])->find();
  40. if (!$order)
  41. return $this->fail("订单不存在!");
  42. $lock = $redLock->lock(Order::OKey($order['id']));
  43. if (!is_array($lock))
  44. return $this->fail("资源竞争,稍后再试!");
  45. $massager = (new \app\api\model\massager\Massager())->findById($order["massager_id"]);
  46. if ($order["massager_id"] > 0) {
  47. if (!$massager)
  48. return $this->fail("助教不存在!");
  49. }
  50. $membership_no = "RBM" . time() . rand(10000, 99999);
  51. if ($order["membership_config_id"] > 0 && $order["membership_amount"] > 0) {
  52. $res = $this->thirdPayLogModel->save([
  53. "no" => $membership_no,
  54. "user_id" => $order["user_id"],
  55. "platform" => $order["pay_platform"],
  56. "type" => \E_USER_BILL_CHANGE_TYPE::MemberCharge[0],
  57. "reason" => \E_USER_BILL_CHANGE_TYPE::MemberCharge[1],
  58. "value" => null,
  59. "membership_config_id" => $order["membership_config_id"],
  60. "amount" => $order["membership_amount"],
  61. "status" => \E_BASE_STATUS::Default,
  62. "relation_no" => $out_trade_no,
  63. "createtime" => time(),
  64. "updatetime" => time()
  65. ]);
  66. if (!$res) {
  67. return $this->fail("会员订单保存异常");
  68. }
  69. }
  70. $wallet = $this->userWalletModel->getUserWallet($order->user_id);
  71. Db::startTrans();
  72. try {
  73. $this->orderModel->update([
  74. "status" => \E_ORDER_STATUS::Purchase,
  75. "pay_time" => time(),
  76. "updatetime" => time(),
  77. ], ["id" => $order->id]);
  78. if ($order["membership_config_id"] > 0 && $order["membership_amount"] > 0) {
  79. $r = $this->rechargeMembershipSuccess($membership_no);
  80. if (0 === $r->code()) {
  81. throw new Exception($r->msg());
  82. }
  83. }
  84. $bills = [
  85. [
  86. "user_id" => $order->user_id,
  87. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  88. "change_type" => \E_USER_BILL_CHANGE_TYPE::WxOrderConsumption[0],
  89. "change" => -($order["total_real_amount"] - $order["balance_deduction"]),
  90. "before" => 0,
  91. "after" => 0,
  92. "reason" => \E_USER_BILL_CHANGE_TYPE::WxOrderConsumption[1],
  93. "money" => 0,
  94. "give_money" => 0,
  95. "relation_no" => $order->no,
  96. "createtime" => time()
  97. ], [
  98. "user_id" => $order->user_id,
  99. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Score,
  100. "change_type" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderGive[0],
  101. "change" => $order["total_real_amount"],
  102. "before" => $wallet["score"],
  103. "after" => $wallet["score"] + $order["total_real_amount"],
  104. "reason" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderGive[1],
  105. "money" => 0,
  106. "give_money" => 0,
  107. "relation_no" => $order->no,
  108. "createtime" => time()
  109. ]
  110. ];
  111. // 余额抵扣
  112. if ($order["balance_deduction"] > 0) {
  113. $this->userWalletModel->where("id", $wallet["id"])->setDec("money", $order["balance_deduction"]);
  114. $bills[] = [
  115. "user_id" => $order->user_id,
  116. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  117. "change_type" => \E_USER_BILL_CHANGE_TYPE::BalanceDeduction[0],
  118. "change" => -$order["balance_deduction"],
  119. "before" => $wallet["money"],
  120. "after" => $wallet["money"] - $order["balance_deduction"],
  121. "reason" => \E_USER_BILL_CHANGE_TYPE::BalanceDeduction[1],
  122. "money" => -$order["balance_deduction"],
  123. "give_money" => 0,
  124. "relation_no" => $order->no,
  125. "createtime" => time()
  126. ];
  127. }
  128. $this->userBillModel->saveAll($bills);
  129. $progress = [];
  130. $types = $order["store_id"] > 0 ? [
  131. \E_ORDER_PROGRESS_TYPE::Start,
  132. \E_ORDER_PROGRESS_TYPE::Over,
  133. ] : ALL_ORDER_PROGRESS_TYPE;
  134. if ($order["reorder"] == 1) {
  135. $types = [
  136. \E_ORDER_PROGRESS_TYPE::Take,
  137. \E_ORDER_PROGRESS_TYPE::Over,
  138. ];
  139. }
  140. foreach ($types as $key => $value) {
  141. array_push($progress, [
  142. "order_id" => $order->id,
  143. "order_no" => $order->no,
  144. "type" => $value,
  145. "clock_in" => 0,
  146. "index" => $key + 1,
  147. "clock_in_time" => null,
  148. "lng" => null,
  149. "lat" => null,
  150. "card_image" => null,
  151. "createtime" => time(),
  152. "updatetime" => time()
  153. ]);
  154. }
  155. if ($massager && $massager["mobile"]) {
  156. $r = TencentCloudService::tencent_cloud_vms_send($massager["mobile"], "1478969", [$order["no"]]);
  157. Log::custom_log("Vms", [$r->code(), $r->msg(), $r->data()], "Vms");
  158. }
  159. if ($order["voucher_id"] > 0) {
  160. (new Voucher())->update([
  161. "status" => "use"
  162. ], ["id" => $order["voucher_id"]]);
  163. }
  164. (new Progress())->insertAll($progress);
  165. $this->userWalletModel->where("id", $wallet["id"])->setInc("score", $order["total_real_amount"]);
  166. if ($order["store_id"] > 0) {
  167. StoreService::inform($order["no"], $order["store_id"], $order["city_code"], $order["service_start_date"]);
  168. }
  169. if ($massager) {
  170. Chat::init(1)
  171. ->massager([$massager["id"]])
  172. ->send("您有新订单,请及时处理");
  173. }
  174. Db::commit();
  175. return $this->ok(true);
  176. } catch (Exception $e) {
  177. Db::rollback();
  178. return $this->fail($e->getMessage());
  179. } finally {
  180. UserService::updateGrouping($order["user_id"]);
  181. $redLock->unlock($lock);
  182. }
  183. }
  184. public function rechargeBalanceSuccess($no)
  185. {
  186. $thirdLock = new RedLock();
  187. $tLock = $thirdLock->lock(ThirdPayLog::TPKey($no));
  188. if (!is_array($tLock))
  189. return $this->fail("请稍后再试!");
  190. $pay_log = $this->thirdPayLogModel->getByNo($no);
  191. if (!$pay_log)
  192. return $this->fail("支付记录不存在!");
  193. $value = json_decode($pay_log["value"], true);
  194. if (!is_array($value) && !isset($value["user_id"])) {
  195. return $this->fail("自定义格式错误!");
  196. }
  197. $wallet = $this->userWalletModel->getUserWallet($value["user_id"]);
  198. Db::startTrans();
  199. try {
  200. $change_type = \E_ORDER_PAY_TYPE::ALi === $pay_log->platform ? \E_USER_BILL_CHANGE_TYPE::BalanceAliRecharge : \E_USER_BILL_CHANGE_TYPE::BalanceWxRecharge;
  201. $bill = [
  202. "user_id" => $value["user_id"],
  203. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  204. "change_type" => $change_type[0],
  205. "change" => $value["amount"] + $value["give"],
  206. "before" => $wallet->money + $wallet->give_money,
  207. "after" => ($wallet->money + $wallet->give_money) + $value["amount"] + $value["give"],
  208. "reason" => $change_type[1],
  209. "money" => $value["amount"],
  210. "give_money" => $value["give"],
  211. "relation_no" => $pay_log->no,
  212. "createtime" => time()
  213. ];
  214. $this->thirdPayLogModel->update([
  215. "status" => \E_BASE_STATUS::Normal
  216. ], ["id" => $pay_log->id]);
  217. $this->userWalletModel->where("id", $wallet->id)
  218. ->inc("money", $value["amount"])
  219. ->inc("give_money", $value["give"])
  220. ->update(["updatetime" => time()]);
  221. $this->userBillModel->save($bill);
  222. Db::commit();
  223. return $this->ok(true);
  224. } catch (Exception $e) {
  225. Db::rollback();
  226. return $this->fail($e->getMessage());
  227. } finally {
  228. $thirdLock->unlock($tLock);
  229. }
  230. }
  231. public function rechargeMembershipSuccess($no)
  232. {
  233. $thirdLock = new RedLock();
  234. $tLock = $thirdLock->lock(ThirdPayLog::TPKey($no));
  235. if (!is_array($tLock))
  236. return $this->fail("请稍后再试!");
  237. $pay_log = $this->thirdPayLogModel->getByNo($no);
  238. if (!$pay_log)
  239. return $this->fail("支付记录不存在!");
  240. Db::startTrans();
  241. try {
  242. $bill = [
  243. "user_id" => $pay_log["user_id"],
  244. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  245. "change_type" => \E_USER_BILL_CHANGE_TYPE::MemberCharge[0],
  246. "change" => -$pay_log["amount"],
  247. "before" => 0,
  248. "after" => 0,
  249. "reason" => \E_USER_BILL_CHANGE_TYPE::MemberCharge[1],
  250. "money" => 0,
  251. "give_money" => 0,
  252. "relation_no" => $pay_log->no,
  253. "createtime" => time()
  254. ];
  255. $this->thirdPayLogModel->update([
  256. "status" => \E_BASE_STATUS::Normal
  257. ], ["id" => $pay_log->id]);
  258. $user = (new User())->get($pay_log["user_id"]);
  259. if (is_null($user))
  260. throw new Exception("用户不存在");
  261. $config = (new Config())->get($pay_log["membership_config_id"]);
  262. if (is_null($config))
  263. throw new Exception("会员卡不存在");
  264. $now_time = time();
  265. if ($user["vip_invalid_time"] == null || $user["vip_invalid_time"] < $now_time) {//新用户没有充值过会员
  266. $vip_invalid_time = ($config["days"] * 24 * 60 * 60) + $now_time;
  267. } else {
  268. $vip_invalid_time = ($config["days"] * 24 * 60 * 60) + $user["vip_invalid_time"]; // 用户续约
  269. }
  270. (new Vip())->save([
  271. "user_id" => $user["id"],
  272. "starttime" => $now_time,
  273. "endtime" => $vip_invalid_time,
  274. "createtime" => time(),
  275. "updatetime" => time(),
  276. ]);
  277. (new User())->update([
  278. "vip_invalid_time" => $vip_invalid_time
  279. ], ["id" => $user["id"]]);
  280. $this->userBillModel->save($bill);
  281. Db::commit();
  282. return $this->ok(true);
  283. } catch (Exception $e) {
  284. Db::rollback();
  285. return $this->fail($e->getMessage());
  286. } finally {
  287. $thirdLock->unlock($tLock);
  288. }
  289. }
  290. public function refundSuccess($out_trade_no)
  291. {
  292. $redLock = RedLock::of();
  293. $order = $this->orderModel->where([
  294. "no" => $out_trade_no,
  295. ])->where("status", "IN", [
  296. \E_ORDER_STATUS::Purchase,
  297. \E_ORDER_STATUS::Proceed,
  298. \E_ORDER_STATUS::WaitFeedback
  299. ])->find();
  300. if (!$order)
  301. return $this->fail("订单不存在!");
  302. $lock = $redLock->lock(Order::OKey($order['id']));
  303. if (!is_array($lock))
  304. return $this->fail("资源竞争,稍后再试!");
  305. $trip_amount = $order["trip_amount"];
  306. $is_user_refund_trip = $order["is_refund_trip"];
  307. if ($is_user_refund_trip == 1)
  308. $trip_amount = 0;
  309. Db::startTrans();
  310. try {
  311. $save_bill = [
  312. "user_id" => $order["user_id"],
  313. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  314. "change_type" => \E_USER_BILL_CHANGE_TYPE::WxOrderRefund[0],
  315. "change" => $order["total_real_amount"] - $trip_amount - $order["balance_deduction"],
  316. "before" => 0,
  317. "after" => 0,
  318. "reason" => \E_USER_BILL_CHANGE_TYPE::WxOrderRefund[1],
  319. "money" => 0,
  320. "give_money" => 0,
  321. "relation_no" => $order["no"],
  322. "createtime" => time()
  323. ];
  324. // 出行费到账助教账户
  325. if ($order["massager_id"] > 0 && $trip_amount > 0) {
  326. $mWalletModel = new \app\api\model\massager\Wallet();
  327. // 出行费到账助教账户
  328. $mWallet = $mWalletModel->getWallet($order["massager_id"]);
  329. $mWalletModel->where("id", $mWallet->id)->setInc("profit_amount", $trip_amount);
  330. (new \app\api\model\massager\Bill())->insertAll([
  331. [
  332. "massager_id" => $order["massager_id"],
  333. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  334. "change_type" => \E_M_BILL_CHANGE_TYPE::Travel,
  335. "change" => $trip_amount,
  336. "before" => fixed2Float($mWallet->profit_amount),
  337. "after" => fixed2Float($mWallet->profit_amount + $trip_amount),
  338. "reason" => "出行费用",
  339. "relation_no" => $order->no,
  340. "createtime" => time()
  341. ]
  342. ]);
  343. }
  344. $auto_count = \db("cancel_order_log")->where("order_no", $order["no"])->where("createtime", "DESC")->find();
  345. $order_status = \E_ORDER_STATUS::Cancel;
  346. if ($auto_count) {
  347. if ($auto_count["order_status_enum"] == \E_ORDER_STATUS::AdminCancel) {
  348. $order_status = \E_ORDER_STATUS::Finish;
  349. // $res = (new ProfitService())->profit($order, User::where("id", $order["user_id"])->find(), true);
  350. // if (!$res->code())
  351. // throw new Exception($res->msg());
  352. } else {
  353. $order_status = $auto_count["order_status_enum"];
  354. }
  355. }
  356. $this->orderModel->update([
  357. "status" => $order_status,
  358. "cancel_time" => time(),
  359. "updatetime" => time()
  360. ], ["id" => $order->id]);
  361. $wallet = $this->userWalletModel->getUserWallet($order["user_id"]);
  362. // 优惠券|积分 退还
  363. if ($order["voucher_id"] > 0) {
  364. (new Voucher())->update(["status" => \E_BASE_STATUS::Normal], ["id" => $order["voucher_id"]]);
  365. }
  366. $this->userWalletModel->where("id", $wallet["id"])->setDec("score", $order["total_real_amount"]);
  367. $user_bills = [
  368. $save_bill,
  369. [
  370. "user_id" => $order->user_id,
  371. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Score,
  372. "change_type" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderRefund[0],
  373. "change" => -$order["total_real_amount"],
  374. "before" => $wallet["score"],
  375. "after" => $wallet["score"] - $order["total_real_amount"],
  376. "reason" => \E_USER_BILL_CHANGE_TYPE::ScoreOrderRefund[1],
  377. "money" => 0,
  378. "give_money" => 0,
  379. "relation_no" => $order->no,
  380. "createtime" => time()
  381. ]
  382. ];
  383. // 抵扣余额退还
  384. if ($order["balance_deduction"] > 0) {
  385. array_push($user_bills, [
  386. "user_id" => $order->user_id,
  387. "currency_type" => \E_USER_BILL_CURRENCY_TYPE::Money,
  388. "change_type" => \E_USER_BILL_CHANGE_TYPE::BalanceDeductionRefund[0],
  389. "change" => $order["balance_deduction"],
  390. "before" => $wallet["money"],
  391. "after" => $wallet["money"] + $order["balance_deduction"],
  392. "reason" => \E_USER_BILL_CHANGE_TYPE::BalanceDeductionRefund[1],
  393. "money" => $order["balance_deduction"],
  394. "give_money" => 0,
  395. "relation_no" => $order->no,
  396. "createtime" => time()
  397. ]);
  398. $this->userWalletModel->where("id", $wallet["id"])->setInc("money", $order["balance_deduction"]);
  399. }
  400. $this->userBillModel->saveAll($user_bills);
  401. Message::sendSystemMessage(
  402. \E_IDENTITY_TYPE::User,
  403. ["to_user_id" => $order->user_id],
  404. "取消订单通知",
  405. "您的订单【{$order->no}】已取消,订单金额/优惠券将原路返回您的账户!"
  406. );
  407. $user = (new User())->get($order['user_id']);
  408. if ($user) {
  409. TencentCloudService::tencent_cloud_sms_send('1913760', $user["mobile"], [$order["no"]]);
  410. }
  411. Db::commit();
  412. return $this->ok(true);
  413. } catch (Exception $e) {
  414. Db::rollback();
  415. return $this->fail($e->getMessage());
  416. } finally {
  417. UserService::updateGrouping($order["user_id"]);
  418. $redLock->unlock($lock);
  419. }
  420. }
  421. }