PaymentController.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Events\RetailOutboundEvent;
  4. use App\Events\NewOrder;
  5. use App\Models\Amount;
  6. use App\Models\Integral;
  7. use App\Models\IntegralW;
  8. use App\Models\InventoryW;
  9. use App\Models\LogW;
  10. use App\Models\OrderW;
  11. use App\Models\UserZ;
  12. use App\Models\VipLog;
  13. use App\Models\Address;
  14. use App\Models\DwbsUser;
  15. use App\Models\Goods;
  16. use App\Models\GoodSku;
  17. use App\Models\Order;
  18. use App\Models\OrderDetail;
  19. use App\Models\Store;
  20. use App\Models\User;
  21. use App\Models\ZbsBasic;
  22. use App\Models\ZbsEnroll;
  23. use App\Models\ZbsOrder;
  24. use Carbon\Carbon;
  25. use EasyWeChat\Factory;
  26. use Illuminate\Http\Request;
  27. use Illuminate\Support\Facades\Auth;
  28. use Illuminate\Support\Facades\DB;
  29. use Illuminate\Support\Facades\Log;
  30. class PaymentController extends Controller
  31. {
  32. protected $option = [];
  33. protected $header = array();
  34. protected $retryTimes;
  35. public function pay(Request $request)
  36. {
  37. $order_no=$request->input('order_no');
  38. try{
  39. DB::transaction(function()use($order_no, &$order ,&$seconds){
  40. $order=Order::where('order_no',$order_no)->lockForUpdate()->first();
  41. $seconds=Carbon::now()->subSeconds(60)->toDateTimeString();//限制调起支付60秒
  42. if(empty($order)){
  43. throw new \Exception("订单有误");
  44. }
  45. if($order->prepare_pay_at >= $seconds){
  46. throw new \Exception("订单正在支付中");
  47. }
  48. $order->prepare_pay_at=Carbon::now();
  49. $order->save();
  50. });
  51. }catch(\Exception $e){
  52. return $this->error('450001',$e->getMessage());
  53. }
  54. if($order->apply_cancel == 2){
  55. return $this->error('450001','订单已取消');
  56. }
  57. if($order->is_pay != 0 || $order->status != 0){
  58. return $this->error('450001','订单状态有误');
  59. }
  60. if($order->account <= 0){
  61. return $this->error('450001','支付金额有误');
  62. }
  63. $openid=User::where('id',Auth::user()->id)->value('openId');
  64. $store=Store::where('id',$order->store_id)->first();
  65. if(empty($store)){
  66. return $this->error('450001','代理店铺信息不存在或者已被删除');
  67. }
  68. if($store->status==1){
  69. return $this->error('450001','代理店铺已被禁用');
  70. }
  71. $agent=DwbsUser::where('id',$store->user_id)->first();
  72. if(empty($agent)){
  73. return $this->error('450001','代理信息不存在或者已被删除');
  74. }
  75. if($agent->status==1){
  76. return $this->error('450001','代理已被禁用');
  77. }
  78. $options = $this->options($order->store_id);
  79. $payment = Factory::payment($options);
  80. $jssdk = $payment->jssdk;
  81. Log::info(round($order->account/1000,2));
  82. Log::info(round($order->account/10));
  83. $two_minutes=Carbon::now()->addSeconds(55)->toDateTimeString();//限制支付时间55秒
  84. $cancel_time=Carbon::parse($order->created_at)->addMinutes(59)->toDateTimeString();//系统自动取消时间前一分钟
  85. if(Carbon::now() >= $cancel_time){
  86. return $this->error('450001','订单将被取消');
  87. }
  88. if($two_minutes <= $cancel_time){
  89. $expire=date("YmdHis",strtotime($two_minutes));
  90. }else{
  91. $expire=date("YmdHis",strtotime($cancel_time));
  92. }
  93. Log::info('qaqaqaqaqa'.$expire);
  94. $attributes = [
  95. 'time_expire' => $expire,
  96. 'trade_type' => 'JSAPI', // 支付方式
  97. 'body' => '订单支付', // 订单说明
  98. 'out_trade_no' => mt_rand('1000','9999').'_'.$order_no, // 自定义订单号
  99. 'total_fee' => $order->account*100, // 单位:分
  100. 'openid' => $openid, // 当前用户的openId
  101. 'profit_sharing' => 'Y'
  102. ];
  103. $result = $payment->order->unify($attributes);
  104. if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
  105. $prepayId = $result['prepay_id'];
  106. $config = $jssdk->sdkConfig($prepayId);
  107. return response()->json([
  108. 'error_code'=>200,
  109. 'msg'=>'成功',
  110. 'data'=>$config
  111. ]);
  112. }
  113. Log::info($result);
  114. if ($result['return_code'] == 'FAIL' && array_key_exists('return_msg', $result)) {
  115. Log::info('订单支付失败:'.$order->user_id.'/'.$order_no.'/'.$order->money.'/'.$result['return_msg']);
  116. return response()->json([
  117. 'error_code'=>401,
  118. 'msg'=> $result['return_msg'],
  119. ]);
  120. }
  121. Log::info('订单支付失败:'.$order->user_id.'/'.$order_no.'/'.$order->money.'/'.$result['err_code_des']);
  122. return response()->json([
  123. 'error_code'=>401,
  124. 'msg'=> $result['err_code_des'],
  125. ]);
  126. }
  127. protected function options($id){
  128. return [
  129. 'app_id' => config('wechat.payment.default.app_id'),
  130. 'mch_id' => config('wechat.payment.default.mch_id'),
  131. 'sub_mch_id' => Store::where('id',$id)->value('sub_mchid'),
  132. 'key' => config('wechat.payment.default.key'),
  133. 'notify_url' => url('api/payment/notify')
  134. ];
  135. }
  136. public function notify(Request $request)
  137. {
  138. Log::info('支付回调成功');
  139. $options = [
  140. 'app_id' => config('wechat.payment.default.app_id'),
  141. 'mch_id' => config('wechat.payment.default.mch_id'),
  142. 'key' => config('wechat.payment.default.key'),
  143. 'notify_url' => url('api/payment/notify')
  144. ];
  145. $payment = Factory::payment($options);
  146. $response = $payment->handlePaidNotify(function ($message, $fail)
  147. {
  148. Log::info('支付返回数据:'.json_encode($message));
  149. LogW::create([
  150. 'content'=>json_encode($message),
  151. 'type'=>1
  152. ]);
  153. // 根据返回的订单号查询订单数据
  154. Log::info($message['out_trade_no']);
  155. $rand_no=explode('_',$message['out_trade_no'])[0];
  156. $message['out_trade_no']=explode('_',$message['out_trade_no'])[1];
  157. Log::info($message['out_trade_no']);
  158. $order=Order::where('order_no',$message['out_trade_no'])->first();
  159. if($order->is_pay==1){
  160. Log::info('订单号为:'.$message['out_trade_no'].'的订单已支付');
  161. return true;
  162. }
  163. if (!$order || $order->status == 1) {
  164. Log::info('订单不存在,订单号:'.$message['out_trade_no'].'/支付单号:'.$message['transaction_id'].'/支付状态:'.$message['result_code']);
  165. return true;//订单不存在 或者 订单已支付
  166. }
  167. if ($message['result_code'] === 'FAIL') { //支付失败
  168. Log::warning('支付失败');
  169. return true;
  170. }
  171. if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
  172. Log::info('支付成功,微信支付单号:'.$message['transaction_id']);
  173. // 支付成功后的业务逻辑
  174. if($message['result_code'] === 'SUCCESS') {
  175. $total_fee=$message['total_fee']/100;
  176. DB::transaction(function()use($order,$message,$total_fee,$rand_no){
  177. $basic=ZbsBasic::whereIn('keys',['round_start_time','round_end_time','season'])->pluck('value','keys')->toArray();
  178. $start_time=$basic['round_start_time'];
  179. $end_time=$basic['round_end_time'];
  180. $season=$basic['season'];
  181. Log::info('0000000-00000'.$start_time.'///'.$end_time.'///'.$season);
  182. $sto=Store::where('id',$order->store_id)->first();
  183. // $userz = UserZ::where('dwbs_id', $sto->user_id)->first();
  184. $userzs = UserZ::where('dwbs_id', $sto->user_id)->get();
  185. $order->is_zbs = 0;
  186. $integral=$order->total*2;
  187. $zbs=0; //不在争霸赛期间
  188. // if(!empty($userz)) { //争霸赛存在该用户
  189. if(count($userzs) > 0) { //争霸赛存在该用户
  190. $now = Carbon::now()->timestamp;
  191. $pay_time=Carbon::parse($message['time_end'])->timestamp;
  192. Log::info('<<<<<1>>>>>'.$now.'///'.$start_time.'///'.$end_time.'///'.$pay_time);
  193. if ($pay_time >= $start_time && $pay_time <= $end_time) { //在争霸赛期间
  194. // $uids = ZbsEnroll::where('season',$season)->where('is_refund',0)->where('status',0)->pluck('uid')->toArray();
  195. $uids = \Illuminate\Support\Facades\Cache::remember('uids', Carbon::now()->addHours(12), function () use ($season) {
  196. return ZbsEnroll::where('season', $season)->where('is_refund', 0)->where('status', 0)->pluck('uid')->toArray();
  197. });
  198. foreach($userzs as $key=>$val){
  199. if (in_array($val->id, $uids)) {//报名了争霸赛
  200. //标记争霸赛订单
  201. $order->is_zbs = 1;
  202. //学分变更
  203. $integral=0;
  204. $zbs=1; //在争霸赛期间
  205. }
  206. }
  207. // if (in_array($userz->id, $uids)) {//报名了争霸赛
  208. // //标记争霸赛订单
  209. // $order->is_zbs = 1;
  210. // //学分变更
  211. // $integral=0;
  212. // $zbs=1; //在争霸赛期间
  213. // }
  214. }
  215. }
  216. //学分变更
  217. $inte=Integral::where('order_no',$order->order_no)->where('store_id',$order->store_id)->where('type',1)->first();
  218. if(empty($inte)){
  219. Integral::create([
  220. 'store_id'=>$order->store_id,
  221. 'order_no'=>$order->order_no,
  222. 'num'=>$order->total,
  223. 'integral'=>$integral,
  224. 'integral_double'=>$integral,
  225. 'type'=>1,
  226. 'remark'=>'下单成功',
  227. 'is_zbs'=>$zbs,
  228. ]);
  229. }
  230. //修改订单状态
  231. $order->status = 1;
  232. $order->is_pay = 1;
  233. $order->pay_type = 1;
  234. $order->pay_money = $total_fee;
  235. $order->rand_no = $rand_no;
  236. $order->pay_open_id = $message['openid'];
  237. $order->self_pay = 0;
  238. $order->wechat_pay_no = $message['transaction_id'];
  239. $order->pay_at = $message['time_end'];
  240. $order->save();
  241. //店铺信息
  242. $store=Store::where('id',$order->store_id)->lockForUpdate()->first();
  243. $start_money= $store->pending_amount;
  244. $store->pending_amount = $store->pending_amount += $total_fee;
  245. $store->integral += $integral;
  246. $store->cycle_inte += $integral;
  247. $store->save();
  248. //规格销量
  249. $details=OrderDetail::where('order_no',$order->order_no)->get();
  250. foreach($details as $key=>$val){
  251. $where=[];
  252. $where['goods_id']=$val->goods_id;
  253. $where['size']=$val->size;
  254. $where['type']=$val->type;
  255. //规格销量
  256. $sku=GoodSku::where($where)->lockForUpdate()->first();
  257. $sku->sale_num += $val->num;
  258. $sku->save();
  259. //商品销量
  260. $goods=Goods::where('id',$val->goods_id)->lockForUpdate()->first();
  261. $goods->sale_num += $val->num;
  262. $goods->save();
  263. //减微店代理库存
  264. $arr_test=Store::getTest();
  265. if(in_array($order->store_id,$arr_test)){
  266. $storeInventory=Inventory::where(['store_id'=>$order->store_id,'goods_id'=>$val->goods_id,'sku_id'=>$val->sku_id])->lockForUpdate()->first();
  267. $storeInve_num=!empty($storeInventory)?$storeInventory->num:0;
  268. if($val->num > $storeInve_num){
  269. Log::info('【'.$store->name.'的店铺-'.$goods->main_attr.'-'.$val->type.'-'.$val->size.'】库存不足');
  270. }
  271. $storeInventory->num-=$val->num;
  272. $storeInventory->save();
  273. }
  274. }
  275. //用户vip变更
  276. $vipLog=VipLog::where('user_id',$order->user_id)
  277. ->where('store_id',$order->store_id)->first();
  278. if(empty($vipLog) && $order->total>=2){
  279. VipLog::create([
  280. 'user_id'=>$order->user_id,
  281. 'store_id'=>$order->store_id,
  282. 'order_no'=>$message['out_trade_no'],
  283. 'type'=>2,//购买两套,添加vip
  284. 'remark'=>'购买自动添加vip'
  285. ]);
  286. Order::where('order_no',$message['out_trade_no'])->update([
  287. 'vip'=>1
  288. ]);
  289. }
  290. //支付日志
  291. Amount::create([
  292. 'user_id' => $order->user_id,
  293. 'store_id' => $order->store_id,
  294. 'order_no' => $message['out_trade_no'],
  295. 'transaction_id'=> $message['transaction_id'],
  296. 'money' => $total_fee,
  297. 'type' => 1, //支付
  298. 'status' => 1, //成功
  299. 'service_fee' => 0,
  300. 'start_money' => $start_money,//支付前冻结金额
  301. 'end_money' => $store->pending_amount,//支付后冻结金额
  302. 'start_amount' => $store->available_amount,//支付前可用金额
  303. 'end_amount' => $store->available_amount,//支付后可用金额
  304. 'remark' => '收款',
  305. ]);
  306. });
  307. //减库存
  308. DB::connection('mysql_dwbs')->transaction(function()use($order) {
  309. event(new RetailOutboundEvent($order->order_no));
  310. },5);
  311. //算争霸赛学分
  312. ZbsOrder::create([
  313. 'order_id'=>$order->id,
  314. 'status'=>0,
  315. 'is_cancel'=>0,
  316. ]);
  317. //新订单通知
  318. $store=Store::where('id',$order->store_id)->first();
  319. $user=DwbsUser::withTrashed()->where('id',$store->user_id)->first();
  320. if($user->openid){
  321. Log::info($user->openid);
  322. $data['openid']=$user->openid;
  323. $data['data']=[
  324. 'first' => '您有新的客户订单,请及时处理',
  325. 'keyword1' => User::where('id',$order->user_id)->value('nickname'),
  326. 'keyword2' => number_format($order->account, 2),
  327. 'keyword3' => $order->order_no,
  328. 'keyword4' => $order->created_at
  329. ];
  330. event(new NewOrder($data));
  331. }
  332. }
  333. Log::info('支付结束');
  334. return true;
  335. }else{
  336. Log::info('通信失败');
  337. return $fail('通信失败,请稍后再通知我');
  338. }
  339. });
  340. return $response;
  341. }
  342. }