MiniPayController.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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\LogW;
  8. use App\Models\VipLog;
  9. use App\Models\Address;
  10. use App\Models\DwbsUser;
  11. use App\Models\Goods;
  12. use App\Models\GoodSku;
  13. use App\Models\Order;
  14. use App\Models\OrderDetail;
  15. use App\Models\Store;
  16. use App\Models\User;
  17. use Carbon\Carbon;
  18. use EasyWeChat\Factory;
  19. use Illuminate\Http\Request;
  20. use Illuminate\Support\Facades\Auth;
  21. use Illuminate\Support\Facades\DB;
  22. use Illuminate\Support\Facades\Log;
  23. class MiniPayController extends Controller
  24. {
  25. protected $option = [];
  26. protected $header = array();
  27. protected $retryTimes;
  28. public function pay(Request $request)
  29. {
  30. $order_no=$request->input('order_no');
  31. try{
  32. DB::transaction(function()use($order_no, &$order ,&$seconds){
  33. $order=Order::where('order_no',$order_no)->lockForUpdate()->first();
  34. $seconds=Carbon::now()->subSeconds(60)->toDateTimeString();//限制调起支付60秒
  35. if(empty($order)){
  36. throw new \Exception("订单有误");
  37. }
  38. if($order->prepare_pay_at >= $seconds){
  39. throw new \Exception("订单正在支付中");
  40. }
  41. $order->prepare_pay_at=Carbon::now();
  42. $order->save();
  43. });
  44. }catch(\Exception $e){
  45. return $this->error('450001',$e->getMessage());
  46. }
  47. if($order->apply_cancel == 2){
  48. return $this->error('450001','订单已取消');
  49. }
  50. if($order->is_pay != 0 || $order->status != 0){
  51. return $this->error('450001','订单状态有误');
  52. }
  53. if($order->account <= 0){
  54. return $this->error('450001','支付金额有误');
  55. }
  56. $openid=User::where('id',Auth::user()->id)->value('openId');
  57. $store=Store::where('id',$order->store_id)->first();
  58. if(empty($store)){
  59. return $this->error('450001','代理店铺信息有误');
  60. }
  61. if($store->status==1){
  62. return $this->error('450001','代理店铺已被禁用');
  63. }
  64. $options = $this->options($order->store_id);
  65. $payment = Factory::payment($options);
  66. $jssdk = $payment->jssdk;
  67. Log::info(round($order->account/1000,2));
  68. Log::info(round($order->account/10));
  69. $two_minutes=Carbon::now()->addSeconds(55)->toDateTimeString();//限制支付时间55秒
  70. $cancel_time=Carbon::parse($order->created_at)->addMinutes(59)->toDateTimeString();//系统自动取消时间前一分钟
  71. if(Carbon::now() >= $cancel_time){
  72. return $this->error('450001','订单将被取消');
  73. }
  74. if($two_minutes <= $cancel_time){
  75. $expire=date("YmdHis",strtotime($two_minutes));
  76. }else{
  77. $expire=date("YmdHis",strtotime($cancel_time));
  78. }
  79. Log::info('1qaqaqaqaqa'.$expire);
  80. $attributes = [
  81. 'time_expire' => $expire,
  82. 'trade_type' => 'JSAPI', // 支付方式
  83. 'body' => '订单支付', // 订单说明
  84. 'out_trade_no' => mt_rand('1000','9999').'_'.$order_no, // 自定义订单号
  85. 'total_fee' => $order->account*100, // 单位:分
  86. 'sub_openid' => $openid, // 当前用户的openId
  87. 'profit_sharing' => 'Y'
  88. ];
  89. $result = $payment->order->unify($attributes);
  90. if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
  91. $prepayId = $result['prepay_id'];
  92. $config = $jssdk->sdkConfig($prepayId);
  93. return response()->json([
  94. 'error_code'=>200,
  95. 'msg'=>'成功',
  96. 'data'=>$config
  97. ]);
  98. }
  99. if ($result['return_code'] == 'FAIL' && array_key_exists('return_msg', $result)) {
  100. Log::info('订单支付失败:'.$order->user_id.'/'.$order_no.'/'.$order->money.'/'.$result['return_msg']);
  101. return response()->json([
  102. 'error_code'=>401,
  103. 'msg'=> $result['return_msg'],
  104. ]);
  105. }
  106. Log::info('订单支付失败:'.$order->user_id.'/'.$order_no.'/'.$order->money.'/'.$result['err_code_des']);
  107. return response()->json([
  108. 'error_code'=>401,
  109. 'msg'=> $result['err_code_des'],
  110. ]);
  111. }
  112. protected function options($id){
  113. return [
  114. 'app_id' => 'wxf536016d4923e584',//config('wechat.payment.default.app_id'),
  115. 'mch_id' => config('wechat.payment.default.mch_id'),
  116. 'sub_mch_id' => Store::where('id',$id)->value('sub_mchid'),
  117. 'key' => config('wechat.payment.default.key'),
  118. 'notify_url' => url('api/payment/notify')
  119. ];
  120. }
  121. public function notify(Request $request)
  122. {
  123. Log::info('支付回调成功');
  124. $options = [
  125. 'app_id' => 'wxf536016d4923e584',//config('wechat.payment.default.app_id'),
  126. 'mch_id' => config('wechat.payment.default.mch_id'),
  127. 'key' => config('wechat.payment.default.key'),
  128. 'notify_url' => url('api/payment/notify')
  129. ];
  130. $payment = Factory::payment($options);
  131. $response = $payment->handlePaidNotify(function ($message, $fail)
  132. {
  133. Log::info('支付返回数据:'.json_encode($message));
  134. LogW::create([
  135. 'content'=>json_encode($message),
  136. 'type'=>1
  137. ]);
  138. // 根据返回的订单号查询订单数据
  139. Log::info($message['out_trade_no']);
  140. $rand_no=explode('_',$message['out_trade_no'])[0];
  141. $message['out_trade_no']=explode('_',$message['out_trade_no'])[1];
  142. Log::info($message['out_trade_no']);
  143. $order=Order::where('order_no',$message['out_trade_no'])->first();
  144. if($order->is_pay==1){
  145. Log::info('订单号为:'.$message['out_trade_no'].'的订单已支付');
  146. return true;
  147. }
  148. if (!$order || $order->status == 1) {
  149. Log::info('订单不存在,订单号:'.$message['out_trade_no'].'/支付单号:'.$message['transaction_id'].'/支付状态:'.$message['result_code']);
  150. return true;//订单不存在 或者 订单已支付
  151. }
  152. if ($message['result_code'] === 'FAIL') { //支付失败
  153. Log::warning('支付失败');
  154. return true;
  155. }
  156. if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
  157. Log::info('支付成功,微信支付单号:'.$message['transaction_id']);
  158. // 支付成功后的业务逻辑
  159. if($message['result_code'] === 'SUCCESS') {
  160. $total_fee=$message['total_fee']/100;
  161. DB::transaction(function()use($order,$message,$total_fee,$rand_no){
  162. //修改订单状态
  163. $order->status = 1;
  164. $order->is_pay = 1;
  165. $order->pay_type = 1;
  166. $order->pay_money = $total_fee;
  167. $order->rand_no = $rand_no;
  168. $order->pay_open_id = $message['openid'];
  169. $order->self_pay = 0;
  170. $order->wechat_pay_no = $message['transaction_id'];
  171. $order->pay_at = $message['time_end'];
  172. $order->save();
  173. //学分变更
  174. $integral=$order->total*5;
  175. Integral::create([
  176. 'store_id'=>$order->store_id,
  177. 'order_no'=>$order->order_no,
  178. 'num'=>$order->total,
  179. 'integral'=>$integral,
  180. 'integral_double'=>$integral,
  181. 'type'=>1,
  182. 'remark'=>'下单成功'
  183. ]);
  184. //店铺信息
  185. $store=Store::where('id',$order->store_id)->lockForUpdate()->first();
  186. $start_money= $store->pending_amount;
  187. $store->pending_amount = $store->pending_amount += $total_fee;
  188. $store->integral += $integral;
  189. $store->save();
  190. //规格销量
  191. $details=OrderDetail::where('order_no',$order->order_no)->get();
  192. foreach($details as $key=>$val){
  193. $where=[];
  194. $where['goods_id']=$val->goods_id;
  195. $where['size']=$val->size;
  196. $where['type']=$val->type;
  197. //规格销量
  198. $sku=GoodSku::where($where)->lockForUpdate()->first();
  199. $sku->sale_num += $val->num;
  200. $sku->save();
  201. //商品销量
  202. $goods=Goods::where('id',$val->goods_id)->lockForUpdate()->first();
  203. $goods->sale_num += $val->num;
  204. $goods->save();
  205. }
  206. //用户vip变更
  207. $vipLog=VipLog::where('user_id',$order->user_id)
  208. ->where('store_id',$order->store_id)->first();
  209. if(empty($vipLog) && $order->total>=2){
  210. VipLog::create([
  211. 'user_id'=>$order->user_id,
  212. 'store_id'=>$order->store_id,
  213. 'order_no'=>$message['out_trade_no']
  214. ]);
  215. Order::where('order_no',$message['out_trade_no'])->update([
  216. 'vip'=>1
  217. ]);
  218. }
  219. //支付日志
  220. Amount::create([
  221. 'user_id' => $order->user_id,
  222. 'store_id' => $order->store_id,
  223. 'order_no' => $message['out_trade_no'],
  224. 'transaction_id'=> $message['transaction_id'],
  225. 'money' => $total_fee,
  226. 'type' => 1, //支付
  227. 'status' => 1, //成功
  228. 'service_fee' => 0,
  229. 'start_money' => $start_money,//支付前冻结金额
  230. 'end_money' => $store->pending_amount,//支付后冻结金额
  231. 'start_amount' => $store->available_amount,//支付前可用金额
  232. 'end_amount' => $store->available_amount,//支付后可用金额
  233. 'remark' => '收款',
  234. ]);
  235. });
  236. //减库存
  237. DB::connection('mysql_dwbs')->transaction(function()use($order) {
  238. event(new RetailOutboundEvent($order->order_no));
  239. },5);
  240. //新订单通知
  241. $store=Store::where('id',$order->store_id)->first();
  242. $user=DwbsUser::withTrashed()->where('id',$store->user_id)->first();
  243. if($user->openid){
  244. Log::info($user->openid);
  245. $data['openid']=$user->openid;
  246. $data['data']=[
  247. 'first' => '您有新的客户订单,请及时处理',
  248. 'keyword1' => User::where('id',$order->user_id)->value('nickname'),
  249. 'keyword2' => number_format($order->account, 2),
  250. 'keyword3' => $order->order_no,
  251. 'keyword4' => $order->created_at
  252. ];
  253. event(new NewOrder($data));
  254. }
  255. }
  256. Log::info('支付结束');
  257. return true;
  258. }else{
  259. Log::info('通信失败');
  260. return $fail('通信失败,请稍后再通知我');
  261. }
  262. });
  263. return $response;
  264. }
  265. }