_user_id = $user_id; $this->_order_data = $buy_info; $this->_post_data = $request; $this->_address_data = $address; try { DB::beginTransaction(); //第1步 执行下单 $order_info = $this->_createOrderStep1(); return $order_info; } catch (\Exception $e) { DB::rollBack(); return ['error' => $e->getMessage()]; } } /** * 生成订单 * @param array $input * @throws Exception * @return array array(支付单sn,订单列表) */ private function _createOrderStep1() { $paycode = $this->makePaySn($this->_user_id); //订单数据 $order_insert = array(); $order_insert['order_sn'] = $this->makeOrderSn($paycode); // 订单编号 $order_insert['uid'] = $this->_user_id; $order_insert['pay_name'] = '微信支付';// 目前只有微信支付 $order_insert['pay_id'] = 1;// 目前只有微信支付 $order_insert['order_status'] = ShopOrder::STATUS_WAIT_PAY;// 待支付 $order_insert['shipping_status'] = ShopOrder::SHIPING_STATUS_WAIT_SEND;// 待发货 $order_insert['pay_status'] = ShopOrder::PAY_WAIT;// 待支付下单 $order_insert['actual_price'] = $this->_order_data['actualPrice'];// 订单实际要支付的金额 $order_insert['order_price'] = $this->_order_data['orderTotalPrice'];// 订单总价 $order_insert['goods_price'] = $this->_order_data['goodsTotalPrice'];// 商品总价 $order_insert['freight_price'] = $this->_order_data['freightPrice'];// 配送费用 $order_insert['coupon_id'] = $this->_order_data['checkedCouponId'];// 使用的优惠券id $order_insert['coupon_price'] = $this->_order_data['couponPrice'];// 优惠金额 $order_insert['add_time'] = Carbon::now();// 订单生成时间 // 收货地址 $order_insert['country'] = $this->_address_data['country_id'];// 国家id 1 中国 $order_insert['province'] = $this->_address_data['province_id'];// 省市id $order_insert['city'] = $this->_address_data['city_id'];// 城市id $order_insert['district'] = $this->_address_data['district_id'];// 区县、街道id $order_insert['address'] = $this->_address_data['address'];// 详细地址 $order_insert['consignee'] = $this->_address_data['user_name'];// 收件人 $order_insert['mobile'] = $this->_address_data['mobile'];// 收件人手机号 //用户留言 $order_insert['postscript'] = empty($this->_post_data->remark) ? '用户无留言' : $this->_post_data->remark; $order_goods_insert = array(); // 订单附表的数据 // 执行插入 $order_model = ShopOrder::create($order_insert); if (!$order_model->id) { throw new \Exception('订单保存失败[未生成支付单]'); } foreach ($this->_order_data['checkedGoodsList'] as $k => $va) { if ($va['number']) { $order_goods_insert[] = [ 'order_id' => $order_model->id, 'goods_id' => $va['goods_id'], 'goods_name' => $va['goods_name'], 'retail_price' => $va['retail_price'], 'market_price' => $va['market_price'], 'list_pic_url' => $va['list_pic_url'] ? $va['list_pic_url'] : '', 'number' => $va['number'], ]; $re1 = $this->addSaleNum($va['goods_id'], $va['number']); if (!$re1) { throw new \Exception('订单保存失败[商品库存不足]'); } } } $order_goods_model = DB::table('shop_order_goods')->insert($order_goods_insert); // 清除购物车商品 $cartRe = CartLogic::clearCart($this->_user_id); if ($order_goods_model) { DB::commit(); return $order_model->toArray(); } else { $this->pay_log('order_goods_insert.error' . var_export($order_goods_insert, true)); throw new \Exception('订单商品保存失败'); } } public function addSaleNum($id, $num = 1) { $goods = ShopGoods::lockForUpdate()->find($id); if (empty($goods) || $goods->goods_number < $num) { return false; } $goods->sell_volume = $goods->sell_volume + $num; $goods->goods_number = $goods->goods_number - $num; return $goods->save(); } /** * 生成支付单编号(两位随机 + 从2000-01-01 00:00:00 到现在的秒数+微秒+会员ID%1000),该值会传给第三方支付接口 * 长度 =2位 + 10位 + 3位 + 3位 = 18位 * 1000个会员同一微秒提订单,重复机率为1/100 * @return string */ public function makePaySn($member_id) { return mt_rand(10, 99) . sprintf('%010d', time() - 946656000) . sprintf('%03d', (float)microtime() * 1000) . sprintf('%03d', (int)$member_id % 1000); } /** * 订单编号生成规则 * 生成订单编号(年取1位 + $pay_id取13位 + 第N个子订单取2位) * 1000个会员同一微秒提订单,重复机率为1/100 * @param $pay_sn * @return string */ public function makeOrderSn($pay_sn) { //记录生成子订单的个数,如果生成多个子订单,该值会累加 static $num; if (empty($num)) { $num = 1; } else { $num++; } return (date('y', time()) % 9 + 1) . sprintf('%013d', $pay_sn) . sprintf('%02d', $num); } // 支付第一步 public function pay_step1($attributes, $openid) { $time = time(); $app = Factory::payment(config('wechat.payment.default')); $result = $app->order->unify([ 'body' => '小T商城', 'detail' => '小T商城的订单', 'out_trade_no' => $attributes['order_sn'], 'total_fee' => $attributes['actual_price'] * 100, 'trade_type' => 'JSAPI', 'openid' => $openid, ]); $this->pay_log('order:' . var_export($attributes, true) . ' result:' . var_export($result, true)); if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') { // 如果成功生成统一下单的订单,那么进行二次签名 二次签名的参数必须与下面相同 $params = [ 'appId' => config('wechat.payment.default.app_id'), 'timeStamp' => time(), 'nonceStr' => $result['nonce_str'], 'package' => 'prepay_id=' . $result['prepay_id'], 'signType' => 'MD5', ]; $params['paySign'] = generate_sign($params, config('wechat.payment.default.key')); return $params; } else { // 返回错误信息 $this->pay_log('json_prepare' . var_export($result, true)); return false; } } /** * 记录日志 */ private function pay_log($msg) { $msg = date('H:i:s') . "|" . $msg . "\r\n"; $msg .= '| GET:' . var_export($_GET, true) . "\r\n"; file_put_contents('./log/pay' . date('Y-m-d') . ".log", $msg, FILE_APPEND); } }