PaymentService.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. <?php
  2. namespace app\common\service;
  3. use app\common\model\GreenScoreLogModel;
  4. use app\common\model\PaymentModel;
  5. use app\common\model\ScoreLogModel;
  6. use app\common\model\ServicesOrderModel;
  7. use app\common\model\ShopGoodsModel;
  8. use app\common\model\ShopOrderGoodsModel as OrderGoods;
  9. use app\common\model\ShopOrderModel;
  10. use app\common\model\ThirdpayBackModel;
  11. use app\common\model\UserModel;
  12. use think\facade\Db;
  13. use utils\RedisCache;
  14. /**
  15. * 支付服务 by wes
  16. * Class PaymentService
  17. * @package app\common\service
  18. */
  19. class PaymentService
  20. {
  21. protected static $instance = null;
  22. protected $cacheTime = 7200;
  23. protected $payWayArr = [
  24. 1 => 'wxpay',
  25. 2 => 'alipay',
  26. 3 => 'balancePay',
  27. 6 => 'greenScorePay',
  28. 14 => 'huifuPay',
  29. 15 => 'sqzpay',
  30. 16 => 'sqzAliPay',
  31. 17 => 'sqzWxPay',
  32. 18 => 'sqzYljk',
  33. 19 => 'usdtPay',
  34. 20 => 'yswkPay',
  35. 22 => 'dkpay',
  36. 56 => 'ysftyPay',
  37. 66 => 'dkysf',
  38. ];
  39. protected $model = null;
  40. public function __construct()
  41. {
  42. $this->model = new PaymentModel();
  43. }
  44. /**
  45. * 静态化入口
  46. * @return static|null
  47. */
  48. public static function make()
  49. {
  50. if (!self::$instance) {
  51. self::$instance = new static();
  52. }
  53. return self::$instance;
  54. }
  55. /**
  56. * 获取支付方式标识
  57. * @param $payType 支付类型
  58. * @return string
  59. */
  60. public function getPayCode($payType)
  61. {
  62. return isset($this->payWayArr[$payType]) ? $this->payWayArr[$payType] : 'defpay';
  63. }
  64. /**
  65. * 按状态获取支付单数量
  66. * @param $uid
  67. * @param $orderType
  68. * @param $state
  69. * @param int $time 时间/小时,默认2小时
  70. * @return array|mixed
  71. * @throws \think\db\exception\DataNotFoundException
  72. * @throws \think\db\exception\DbException
  73. * @throws \think\db\exception\ModelNotFoundException
  74. */
  75. public function getPaymentCountByState($uid, $orderSn = '', $orderType, $state, $time = 2)
  76. {
  77. $cacheKey = "caches:paymentCall:u{$uid}_ot{$orderType}_s{$state}_{$time}_{$orderSn}";
  78. $data = RedisCache::get($cacheKey);
  79. if ($data) {
  80. return $data;
  81. }
  82. $where = [];
  83. if ($orderType) {
  84. $where['order_type'] = $orderType;
  85. }
  86. if ($state) {
  87. $where['state'] = $state;
  88. }
  89. $data = $this->model->where($where)->where(function ($query) use ($time, $orderSn) {
  90. if ($time > 0) {
  91. $query->where('creat_at', '>=', time() - $time * 3600);
  92. }
  93. if ($orderSn) {
  94. $query->where('remarks', $orderSn);
  95. }
  96. })->count('id');
  97. if ($data) {
  98. RedisCache::set($cacheKey, $data, rand(3, 5));
  99. }
  100. return $data;
  101. }
  102. /**
  103. * 验证订单是否已支付
  104. * @param $uid
  105. * @param $orderSn
  106. * @return array|mixed
  107. * @throws \think\db\exception\DataNotFoundException
  108. * @throws \think\db\exception\DbException
  109. * @throws \think\db\exception\ModelNotFoundException
  110. */
  111. public function checkPaymentState($uid, $orderSn)
  112. {
  113. $cacheKey = "caches:paymentState:u{$uid}_sn{$orderSn}";
  114. $data = RedisCache::get($cacheKey);
  115. if ($data) {
  116. return $data;
  117. }
  118. $data = $this->model->where(['state' => 6])->where(function ($query) use ($orderSn) {
  119. if ($orderSn) {
  120. $query->where('remarks', $orderSn);
  121. }
  122. })->value('id');
  123. if ($data) {
  124. RedisCache::set($cacheKey, $data, rand(2, 3));
  125. }
  126. return $data;
  127. }
  128. /**
  129. * 获取支付信息(有缓存)
  130. * @param $outTradeNo
  131. * @param int $state
  132. * @param string $field
  133. * @param false $cache
  134. * @return array|mixed
  135. */
  136. public function getCacheInfo($outTradeNo, $state = 7, $field = '', $cache = false)
  137. {
  138. $cacheKey = "caches:payment:info:otn{$outTradeNo}_{$state}" . ($field ? '_' . md5($field) : '');
  139. $data = RedisCache::get($cacheKey);
  140. if ($data && $cache) {
  141. return $data;
  142. }
  143. $where = ['out_trade_no' => $outTradeNo];
  144. if ($state) {
  145. $where['state'] = $state;
  146. }
  147. $field = $field ? $field : 'id,out_trade_no,uid,total_fee,state,trade_type,out_trade_no1,hy_token_id,syl_sureorderid,hy_bill_no,is_retreat,pay_way,order_type,sid,remarks,trade_no';
  148. $data = $this->model->where($where)
  149. ->field($field)
  150. ->order('creat_at desc')
  151. ->findOrEmpty();
  152. if ($data && $cache) {
  153. RedisCache::set($cacheKey, $data, rand(5, 10));
  154. }
  155. return $data;
  156. }
  157. /**
  158. * 线上支付回调处理
  159. * @param $outTradeNo
  160. * @param $payMoney
  161. * @param $payType
  162. * @param $content
  163. * @throws \think\Exception
  164. * @throws \think\db\exception\DataNotFoundException
  165. * @throws \think\db\exception\DbException
  166. * @throws \think\db\exception\ModelNotFoundException
  167. */
  168. public function payBack($outTradeNo, $payMoney, $payType, $content)
  169. {
  170. $nowTime = date('Y-m-d H:i:s');
  171. $params = $content ? json_decode($content, true) : [];
  172. $payConfig = PayConfigService::make()->getInfoByChannel($payType, 1, 1);
  173. $payCode = isset($payConfig['pay_code']) && $payConfig['pay_code']? $payConfig['pay_code'] : '';
  174. if(empty($payConfig) || empty($payCode)){
  175. sr_throw('该支付暂未开放');
  176. }
  177. $cacheKey = "caches:payNotify:{$payCode}:otn_{$outTradeNo}:";
  178. RedisCache::set($cacheKey . 'catch', ['params' => $params, 'date' => $nowTime], $this->cacheTime);
  179. // 验证支付请求信息
  180. $payInfo = PaymentService::make()->getCacheInfo($outTradeNo, 0);
  181. $payId = isset($payInfo['id']) ? $payInfo['id'] : 0;
  182. $payUid = isset($payInfo['uid']) ? $payInfo['uid'] : 0;
  183. $payState = isset($payInfo['state']) ? intval($payInfo['state']) : 0;
  184. $totalFee = isset($payInfo['total_fee']) ? floatval($payInfo['total_fee']) : 0;
  185. $orderSn = isset($payInfo['remarks']) ? trim($payInfo['remarks']) : '';
  186. $orderType = isset($payInfo['order_type']) ? intval($payInfo['order_type']) : 0;
  187. if (!$payInfo || $payUid <= 0 || empty($orderSn) || $payState != 7) {
  188. $error = empty($payInfo) || !$payId || empty($orderSn) ? "单号{$orderSn}支付信息不存在或参数错误" : "单号{$orderSn}已经回调支付";
  189. $logData = ['params' => $params, 'payInfo' => $payInfo, 'msg' => $error, 'date' => $nowTime];
  190. RedisCache::set($cacheKey . 'error', $logData, $this->cacheTime);
  191. sr_throw($error);
  192. }
  193. // 验证支付金额
  194. if ($payMoney < $totalFee || $totalFee <= 0) {
  195. $logData = ['params' => $params, 'payInfo' => $payInfo, 'msg' => "单号{$orderSn}支付金额错误", 'date' => $nowTime];
  196. RedisCache::set($cacheKey . 'error', $logData, $this->cacheTime);
  197. sr_throw("单号{$orderSn}支付金额错误");
  198. }
  199. // 更新支付状态
  200. if (!PaymentModel::where('id', $payId)->update(['state' => 6, 'pay_at' => $nowTime])) {
  201. $logData = ['params' => $params, 'payInfo' => $payInfo, 'msg' => "单号{$orderSn}更新支付状态失败", 'date' => $nowTime];
  202. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  203. sr_throw("单号{$orderSn}更新支付状态失败");
  204. }
  205. // 第三方回调数据
  206. $data = [
  207. 'out_order_no' => $outTradeNo,
  208. 'content' => $content,
  209. 'create_time' => sr_getcurtime(time()),
  210. 'type' => $payType,
  211. 'uid' => $payUid,
  212. 'money' => $payMoney
  213. ];
  214. if (!ThirdpayBackModel::insertGetid($data)) {
  215. $logData = ['params' => $params, 'payInfo' => $payInfo, 'third' => $data, 'msg' => "单号{$orderSn}处理第三方回调数据错误", 'date' => $nowTime];
  216. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  217. sr_throw("单号{$orderSn}处理第三方回调数据错误");
  218. }
  219. /* TODO 服务商订单处理 */
  220. if ($orderType == 6) {
  221. // 获取验证订单信息
  222. $orderInfo = ServiceOrderService::make()->getInfoBySn($orderSn, $payUid);
  223. $orderId = isset($orderInfo['order_id']) ? $orderInfo['order_id'] : 0;
  224. $orderMoney = isset($orderInfo['payment']) ? floatval($orderInfo['payment']) : 0;
  225. $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : 0;
  226. if (empty($orderInfo) || $orderId <= 0 || $orderMoney <= 0) {
  227. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'msg' => "服务商订单{$orderSn}不存在或参数错误", 'date' => $nowTime];
  228. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  229. sr_throw("服务商订单{$orderSn}不存在或参数错误");
  230. }
  231. // 验证订单状态
  232. if ($orderStatus != 1) {
  233. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'msg' => "服务商订单{$orderSn}订单已处理", 'date' => $nowTime];
  234. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  235. sr_throw("服务商订单{$orderSn}订单已处理");
  236. }
  237. // 更新订单状态
  238. if (!ServicesOrderModel::where('order_id', $orderId)->update(['status' => 2, 'pay_type' => $payType, 'updated_time' => $nowTime])) {
  239. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'msg' => "服务商订单{$orderSn}更新状态错误", 'date' => $nowTime];
  240. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  241. sr_throw("服务商订单{$orderSn}更新状态错误");
  242. }
  243. // 更新用户服务商有效期
  244. $date = sr_getcurtime(time(), 'Y-m-d');
  245. $expireDay = date('Y-m-d', strtotime("$date +1 month"));
  246. if (!UserModel::where('id', $payUid)->update(['store_type' => 1, 'store_expire_time' => $expireDay, 'update_time' => time()])) {
  247. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'storeExpire' => $expireDay, 'msg' => "服务商订单{$orderSn}更新用户服务商有效期错误", 'date' => $nowTime];
  248. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  249. sr_throw("服务商订单{$orderSn}更新用户服务商有效期错误");
  250. }
  251. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'storeExpire' => $expireDay, 'msg' => "服务商订单{$orderSn}支付回调处理成功", 'date' => $nowTime];
  252. RedisCache::set($cacheKey . "success_{$orderSn}", $logData, $this->cacheTime);
  253. } /** TODO 商城订单处理 **/
  254. elseif ($orderType == 4) {
  255. // 获取验证订单信息
  256. $orderInfo = ShopOrderService::make()->getInfoBySn($orderSn, $payUid);
  257. $orderId = isset($orderInfo['order_id']) ? $orderInfo['order_id'] : 0;
  258. $orderMoney = isset($orderInfo['payment']) ? floatval($orderInfo['payment']) : 0;
  259. $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : -1;
  260. if (empty($orderInfo) || $orderId <= 0 || $orderMoney <= 0) {
  261. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}不存在或参数错误", 'date' => $nowTime];
  262. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  263. sr_throw("商城订单{$orderSn}不存在或参数错误");
  264. }
  265. // 验证订单状态
  266. if ($orderStatus != 0) {
  267. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}订单已处理", 'date' => $nowTime];
  268. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  269. sr_throw("商城订单{$orderSn}订单已处理");
  270. }
  271. // 更新订单状态
  272. if (!ShopOrderModel::where('order_id', $orderId)->update(['status' => 1, 'pay_type' => $payType, 'updated_time' => $nowTime])) {
  273. $logData = ['params' => $params, 'payInfo' => $payInfo, 'order' => $orderInfo, 'msg' => "服务商订单{$orderSn}更新状态错误", 'date' => $nowTime];
  274. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  275. sr_throw("服务商订单{$orderSn}更新状态错误");
  276. }
  277. // 增加订单商品销量
  278. $updateSale = ShopOrderModel::alias('a')
  279. ->leftJoin('shop_order_goods og', 'og.order_id=a.order_id')
  280. ->leftJoin('shop_goods g', 'g.goods_id=og.goods_id')
  281. ->where(['a.order_id' => $orderId, 'a.user_id' => $payUid])
  282. ->update([
  283. 'g.sales_volume' => Db::raw('g.sales_volume + og.num'),
  284. 'g.real_sales_volume' => Db::raw('g.real_sales_volume + og.num'),
  285. ]);
  286. if (!$updateSale) {
  287. $logData = ['params' => $params, 'orderInfo' => $orderInfo, 'payInfo' => $payInfo, 'error' => "商城订单{$orderSn}更新商品销量失败", 'date' => $nowTime];
  288. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, 7200);
  289. sr_throw("商城订单{$orderSn}更新商品销量失败");
  290. }
  291. // 更新用户交易额(消费)
  292. $userInfo = UserService::make()->getCacheInfo($payUid, 'id,mobile,score,money,path', false);
  293. $upperPath = isset($userInfo['path']) ? $userInfo['path'] : '';
  294. if ($userInfo && !UserModel::where('id', $payUid)->inc('total_income', $totalFee)->inc('total_team_income', $totalFee)->update()) {
  295. $logData = ['params' => $params, 'payInfo' => $payInfo, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}更新用户交易数据错误", 'date' => $nowTime];
  296. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  297. sr_throw("商城订单{$orderSn}更新用户交易数据错误");
  298. }
  299. // 更新团队交易额数据
  300. if ($upperPath && !UserModel::whereIn('id', explode(',', $upperPath))->inc('total_team_income', $totalFee)->update()) {
  301. $logData = ['params' => $params, 'payInfo' => $payInfo, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}更新用户上级交易数据错误", 'date' => $nowTime];
  302. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  303. sr_throw("商城订单{$orderSn}更新用户上级交易数据错误");
  304. }
  305. // 赠送积分处理
  306. $rebateScore = isset($orderInfo['rebate_score']) ? floatval($orderInfo['rebate_score']) : 0;
  307. if ($rebateScore > 0 && $userInfo) {
  308. // 更新用户账户积分
  309. if (!UserModel::where('id', $payUid)->inc('score', $rebateScore)->update()) {
  310. $logData = ['params' => $params, 'payInfo' => $payInfo, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}赠送积分处理错误", 'date' => $nowTime];
  311. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  312. sr_throw("商城订单{$orderSn}赠送积分处理错误");
  313. }
  314. // 处理积分流水明细
  315. $userScore = isset($userInfo['score']) ? floatval($userInfo['score']) : 0;
  316. $data = [
  317. 'uid' => $payUid,
  318. 'type' => 3,
  319. 'score' => $rebateScore,
  320. 'create_at' => sr_getcurtime(time()),
  321. 'state' => 1,
  322. 'before_score' => $userScore,
  323. 'after_score' => floatval($userScore + $rebateScore),
  324. 'from_id' => $payId,
  325. 'uid2' => 0
  326. ];
  327. if (!ScoreLogModel::insertGetId($data)) {
  328. $logData = ['params' => $params, 'payInfo' => $payInfo, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}赠送积分明细处理错误", 'date' => $nowTime];
  329. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  330. sr_throw("商城订单{$orderSn}赠送积分明细处理错误");
  331. }
  332. }
  333. $logData = ['params' => $params, 'payInfo' => $payInfo, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}回调处理成功", 'date' => $nowTime];
  334. RedisCache::set($cacheKey . "success_{$orderSn}", $logData, $this->cacheTime);
  335. }
  336. return true;
  337. }
  338. /**
  339. * 账户支付处理
  340. * @param $payUid
  341. * @param $orderSn
  342. * @param $payType
  343. * @throws \think\Exception
  344. * @throws \think\db\exception\DataNotFoundException
  345. * @throws \think\db\exception\DbException
  346. * @throws \think\db\exception\ModelNotFoundException
  347. */
  348. public function accountPayBack($payUid, $orderSn, $payType = 6)
  349. {
  350. $nowTime = date('Y-m-d H:i:s');
  351. $params = ['uid' => $payUid, 'order_sn' => $orderSn, 'pay_type' => $payType];
  352. $payConfig = PayConfigService::make()->getInfoByChannel($payType, 1, 1);
  353. $payCode = isset($payConfig['pay_code']) && $payConfig['pay_code']? $payConfig['pay_code'] : '';
  354. if(empty($payConfig) || empty($payCode)){
  355. sr_throw('该支付暂未开放');
  356. }
  357. $cacheKey = "caches:payNotify:{$payCode}:otn_{$orderSn}:";
  358. RedisCache::set($cacheKey . 'catch', ['params' => $params, 'date' => $nowTime], $this->cacheTime);
  359. // 获取验证订单信息
  360. $orderInfo = ShopOrderService::make()->getInfoBySn($orderSn, $payUid);
  361. $orderId = isset($orderInfo['order_id']) ? $orderInfo['order_id'] : 0;
  362. $totalFee = isset($orderInfo['payment']) ? floatval($orderInfo['payment']) : 0;
  363. $orderStatus = isset($orderInfo['status']) ? intval($orderInfo['status']) : -1;
  364. if (empty($orderInfo) || $orderId <= 0 || $totalFee <= 0) {
  365. $logData = ['params' => $params, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}不存在或参数错误", 'date' => $nowTime];
  366. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  367. sr_throw("商城订单{$orderSn}不存在或参数错误");
  368. }
  369. // 验证订单状态
  370. if ($orderStatus != 0) {
  371. $logData = ['params' => $params, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}订单已处理", 'date' => $nowTime];
  372. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  373. sr_throw("商城订单{$orderSn}订单已处理");
  374. }
  375. // 用户信息
  376. $userInfo = UserService::make()->getCacheInfo($payUid, 'id,mobile,green_score,score,money,path', false);
  377. if(empty($userInfo)){
  378. $logData = ['params' => $params, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}账户信息不寻找或已被冻结", 'date' => $nowTime];
  379. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  380. sr_throw('账户信息不寻找或已被冻结');
  381. }
  382. // 支付处理
  383. Db::startTrans();
  384. try {
  385. switch ($payType) {
  386. case 3: // 余额支付
  387. // 验证账户余额
  388. $userMoney = isset($userInfo['money']) ? floatval($userInfo['money']) : 0;
  389. if ($userMoney < $totalFee) {
  390. $logData = ['params' => $params, 'order' => $orderInfo, 'userInfo' => $userInfo, 'msg' => "服务商订单{$orderSn}账户余额不足", 'date' => $nowTime];
  391. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  392. sr_throw('账户余额不足');
  393. }
  394. // 扣款
  395. if (!UserModel::where('id', $payUid)->inc('money', $totalFee)->update()) {
  396. $logData = ['params' => $params, 'order' => $orderInfo, 'userInfo' => $userInfo, 'msg' => "服务商订单{$orderSn}余额支付失败", 'date' => $nowTime];
  397. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  398. sr_throw('余额支付失败');
  399. }
  400. // 流水
  401. $log = [
  402. 'uid' => $payUid,
  403. 'type' => 11,
  404. 'score' => $totalFee,
  405. 'create_at' => sr_getcurtime(time()),
  406. 'state' => 2, // 1进账,2-出账
  407. 'before_score' => $userMoney,
  408. 'after_score' => max(0, $userMoney - $totalFee),
  409. 'from_id' => $orderId,
  410. 'uid2' => 0
  411. ];
  412. if (!GreenScoreLogModel::insertGetId($log)) {
  413. $logData = ['params' => $params, 'order' => $orderInfo, 'userInfo' => $userInfo,'log'=>$log, 'msg' => "服务商订单{$orderSn}账户余额支付处理失败", 'date' => $nowTime];
  414. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  415. sr_throw('账户余额支付处理失败');
  416. }
  417. break;
  418. case 6: // 绿色积分
  419. // 验证账户
  420. $userGreenScore = isset($userInfo['green_score']) ? floatval($userInfo['green_score']) : 0;
  421. if ($userGreenScore < $totalFee) {
  422. $logData = ['params' => $params, 'order' => $orderInfo, 'userInfo' => $userInfo, 'msg' => "服务商订单{$orderSn}账户绿色积分不足", 'date' => $nowTime];
  423. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  424. sr_throw('账户绿色积分不足');
  425. }
  426. // 扣款
  427. if (!UserModel::where('id', $payUid)->inc('green_score', $totalFee)->update()) {
  428. $logData = ['params' => $params, 'order' => $orderInfo, 'userInfo' => $userInfo, 'msg' => "服务商订单{$orderSn}账户绿色积分支付失败", 'date' => $nowTime];
  429. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  430. sr_throw('绿色积分支付失败');
  431. }
  432. // 流水
  433. $log = [
  434. 'uid' => $payUid,
  435. 'type' => 4,
  436. 'score' => $totalFee,
  437. 'create_at' => sr_getcurtime(time()),
  438. 'state' => 2, // 1进账,2-出账
  439. 'before_score' => $userGreenScore,
  440. 'after_score' => max(0, $userGreenScore - $totalFee),
  441. 'from_id' => $orderId,
  442. 'uid2' => 0
  443. ];
  444. if (!GreenScoreLogModel::insertGetId($log)) {
  445. $logData = ['params' => $params, 'order' => $orderInfo, 'userInfo' => $userInfo,'log'=>$log, 'msg' => "服务商订单{$orderSn}绿色积分支付处理失败", 'date' => $nowTime];
  446. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  447. sr_throw('绿色积分支付处理失败');
  448. }
  449. break;
  450. default:
  451. sr_throw("该支付方式暂不支持");
  452. break;
  453. }
  454. // 更新订单状态
  455. if (!ShopOrderModel::where('order_id', $orderId)->update(['status' => 1, 'pay_type' => $payType, 'updated_time' => $nowTime])) {
  456. $logData = ['params' => $params, 'order' => $orderInfo, 'msg' => "服务商订单{$orderSn}更新状态错误", 'date' => $nowTime];
  457. RedisCache::set($cacheKey . '_error', $logData, $this->cacheTime);
  458. sr_throw("服务商订单{$orderSn}更新状态错误");
  459. }
  460. // 写入支付信息
  461. $outTradeNo = 'BA' . createdOrderSn();
  462. $log = [
  463. 'total_fee' => $totalFee,
  464. 'trade_type' => 'app',
  465. 'body' => '购买商品',
  466. 'state' => 6,
  467. 'out_trade_no' => $outTradeNo,
  468. 'pay_way' => 3,
  469. 'remarks' => $orderId,
  470. 'order_type' => 4,
  471. 'pay_at' => sr_getcurtime(time()),
  472. 'uid' => $payUid,
  473. 'voucher_img' => '',
  474. 'out_trade_no1' => ''
  475. ];
  476. if (!PaymentModel::insertGetId($log)) {
  477. $logData = ['params' => $params, 'orderInfo' => $orderInfo,'payLog'=>$log, 'error' => "商城订单{$orderSn}更新商品销量失败", 'date' => $nowTime];
  478. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, 7200);
  479. sr_throw("商城订单{$orderSn}更新商品销量失败");
  480. }
  481. // 增加订单商品销量
  482. $updateSale = ShopOrderModel::alias('a')
  483. ->leftJoin('shop_order_goods og', 'og.order_id=a.order_id')
  484. ->leftJoin('shop_goods g', 'g.goods_id=og.goods_id')
  485. ->where(['a.order_id' => $orderId, 'a.user_id' => $payUid])
  486. ->update([
  487. 'g.sales_volume' => Db::raw('g.sales_volume + og.num'),
  488. 'g.real_sales_volume' => Db::raw('g.real_sales_volume + og.num'),
  489. ]);
  490. if (!$updateSale) {
  491. $logData = ['params' => $params, 'orderInfo' => $orderInfo, 'error' => "商城订单{$orderSn}更新商品销量失败", 'date' => $nowTime];
  492. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, 7200);
  493. sr_throw("商城订单{$orderSn}更新商品销量失败");
  494. }
  495. // 更新用户交易额(消费)
  496. $upperPath = isset($userInfo['path']) ? $userInfo['path'] : '';
  497. if ($userInfo && !UserModel::where('id', $payUid)->inc('total_income', $totalFee)->inc('total_team_income', $totalFee)->update()) {
  498. $logData = ['params' => $params, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}更新用户交易数据错误", 'date' => $nowTime];
  499. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  500. sr_throw("商城订单{$orderSn}更新用户交易数据错误");
  501. }
  502. // 更新团队交易额数据
  503. if ($upperPath && !UserModel::whereIn('id', explode(',', $upperPath))->inc('total_team_income', $totalFee)->update()) {
  504. $logData = ['params' => $params, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}更新用户上级交易数据错误", 'date' => $nowTime];
  505. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  506. sr_throw("商城订单{$orderSn}更新用户上级交易数据错误");
  507. }
  508. // 赠送积分处理
  509. $rebateScore = isset($orderInfo['rebate_score']) ? floatval($orderInfo['rebate_score']) : 0;
  510. if ($rebateScore > 0 && $userInfo) {
  511. // 更新用户账户积分
  512. if (!UserModel::where('id', $payUid)->inc('score', $rebateScore)->update()) {
  513. $logData = ['params' => $params, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}赠送积分处理错误", 'date' => $nowTime];
  514. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  515. sr_throw("商城订单{$orderSn}赠送积分处理错误");
  516. }
  517. // 处理积分流水明细
  518. $userScore = isset($userInfo['score']) ? floatval($userInfo['score']) : 0;
  519. $data = [
  520. 'uid' => $payUid,
  521. 'type' => 3,
  522. 'score' => $rebateScore,
  523. 'create_at' => sr_getcurtime(time()),
  524. 'state' => 1,
  525. 'before_score' => $userScore,
  526. 'after_score' => floatval($userScore + $rebateScore),
  527. 'from_id' => $orderId,
  528. 'uid2' => 0
  529. ];
  530. if (!ScoreLogModel::insertGetId($data)) {
  531. $logData = ['params' => $params, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}赠送积分明细处理错误", 'date' => $nowTime];
  532. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  533. sr_throw("商城订单{$orderSn}赠送积分明细处理错误");
  534. }
  535. }
  536. Db::commit();
  537. $logData = ['params' => $params, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => "商城订单{$orderSn}回调处理成功", 'date' => $nowTime];
  538. RedisCache::set($cacheKey . "success_{$orderSn}", $logData, $this->cacheTime);
  539. return true;
  540. }catch (\Exception $exception){
  541. Db::rollback();
  542. $msg = $exception->getMessage();
  543. $logData = ['params' => $params, 'user' => $userInfo, 'order' => $orderInfo, 'msg' => $msg, 'trace'=>$exception->getTrace(), 'date' => $nowTime];
  544. RedisCache::set($cacheKey . "error_{$orderSn}", $logData, $this->cacheTime);
  545. sr_throw($msg? $msg:'支付失败');
  546. }
  547. return false;
  548. }
  549. }