MiniPayController.php 17 KB

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