getOrderInfo($event[$event_key]['order_id']); \Yii::error(__CLASS__ . " resp-> " . var_export($resp, true)); // 判断是否已经记录当前订单 if (WechatVideoShopOrder::getOne([ ['third_order_id' => $event[$event_key]['order_id']] ])) return true; // 本地订单已经存在那么就不在处理 // 如果有分销员,那么就需要判断是否作为其下级,以及判断当前用户是否存在,不存在则需要注册 // 创建订单 if (!empty($resp['order'])) { $w_order = $resp['order']; $w_order_openid = $w_order['openid'] ?? ''; // 买家身份标识 $w_order_unionid = $w_order['unionid'] ?? ''; // 买家在开放平台的唯一标识符,若当前视频号小店已绑定到微信开放平台帐号下会返回,详见UnionID 机制说明 $w_order_id = $w_order['order_id']; // 订单号 $w_order_status = $w_order['status']; // 订单状态,枚举值见OrderStatus $w_order_detail = $w_order['order_detail']; // 订单详细数据信息 $w_order_aftersale_detail = $w_order['aftersale_detail']; // 售后信息 $w_goods = $w_order_detail['product_infos']; $w_pay_info = $w_order_detail['pay_info'] ?? []; $w_price_info = $w_order_detail['price_info'] ?? []; $w_delivery_info = $w_order_detail['delivery_info'] ?? []; $w_address_info = $w_delivery_info['address_info'] ?? []; $w_delivery_product_info = $w_delivery_info['delivery_product_info'] ?? []; $w_coupon_info = $w_order_detail['coupon_info'] ?? []; $w_ext_info = $w_order_detail['ext_info'] ?? []; $w_sharer_info = $w_order_detail['sharer_info'] ?? []; $w_settle_info = $w_order_detail['settle_info'] ?? []; $w_aftersale_order_list = $w_order_aftersale_detail['aftersale_order_list'] ?? []; $w_on_aftersale_order_cnt= $w_order_aftersale_detail['on_aftersale_order_cnt'] ?? 0; // 查找用户 - 如果没有用户那么就需要注册用户 // 如果没有取到分销员,那么就放入延迟队列进行处理 // 因为微信小店下架了分销,所以订单不需要对分销员进行操作 /*if (empty($w_sharer_info) && !empty(WechatVideoShopEnums::CUSTOMER_DELAY[$this->customer_num])) { // 这里需要入列 \Yii::$app->services->rabbitMq->delay(WechatVideoShopEnums::CUSTOMER_DELAY[$this->customer_num], ['mall_id' => $this->mall_id, 'shop_id' => $this->shop_id, 'customer_num' => $this->customer_num + 1, 'data' => $event], WeChatCallbackLogic::class, 'channels_ec_order_new'); return; }*/ $t = \Yii::$app->db->beginTransaction(); try { // 获取用户 [$userInfo, $share_user_id] = $this->getUser($w_order_unionid, $w_order_openid, $w_order, $w_sharer_info); // 收货地址 $addr = $this->getAddress($w_address_info, $userInfo->user_id); // 购物车 $sku_ids = $this->setCart($w_goods, $userInfo->user_id); // 生成平台订单 - 这里应该是独立的事务 $order = $this->getOrder($userInfo->user_id, [ 'data' => [ 'address_id' => $addr->id, 'attr_ids' => $sku_ids ], 'type' => 'cart', // 走购物车 ]); $order_ids = explode(",", $order['transaction']['order_ids']); $orders = Order::lists([ 'where' => [ ['id' => $order_ids] ] ]); // 设置为视频号订单 Order::updateAll(['order_source' => WechatVideoShopEnums::ADDONS_NAME, 'marketing_type' => WechatVideoShopEnums::ADDONS_NAME], ['in', 'id', $order_ids]); $insert_order = []; foreach ($orders as $item) { $insert_order[] = [ 'created_at' => time(), 'updated_at' => time(), 'mall_id' => $this->mall_id, 'user_id' => $userInfo->user_id, 'order_no' => $item['order_no'], 'content' => Json::encode($w_order), 'shop_id' => $this->shop_id, 'order_id' => $item['id'], 'third_order_id' => $w_order_id, 'third_order_status'=> $w_order_status, 'parent_id' => $share_user_id, // 没有分享人的时候不给分佣 ]; } if (!empty($insert_order)) { // 插入订单 WechatVideoShopOrder::find()->createCommand() ->batchInsert(WechatVideoShopOrder::tableName(), array_keys($insert_order[0]), $insert_order)->execute(); } // 插件订单 // $wechatOrderModel = new WechatVideoShopOrder(); // $wechatOrderModel->mall_id = $this->mall_id; // $wechatOrderModel->user_id = $userInfo->user_id; // $wechatOrderModel->order_id = $order['transaction']['order_ids']; // 有可能会有多个 // $wechatOrderModel->order_no = $order_no; // $wechatOrderModel->third_order_id = $w_order_id; // $wechatOrderModel->content = $w_order; // $wechatOrderModel->third_order_status = $w_order_status; // $wechatOrderModel->shop_id = $this->shop_id; // if (!$wechatOrderModel->save()) throw new \Exception($wechatOrderModel->getErrorMessage()); $t->commit(); } catch (\Exception $e) { $t->rollBack(); \Yii::error(FormatHelper::exception($e, __METHOD__)); throw new \Exception($e->getMessage()); } } } /** * 订单取消 * @param array $event * @param string $event_key * @return void * @throws \Exception */ public function cancel(array $event, string $event_key = 'order_info') { $orders = $this->getByThirdOrderId($event[$event_key]['order_id'], $event, 'channels_ec_order_cancel'); if (is_string($orders)) { return true; } foreach ($orders as $order) { // 取消订单 $params['mall_id'] = $this->mall_id; $params['user_id'] = $order['user_id']; $params['operator_id'] = 0; $params['operator_name'] = self::OPERATOR_NAME; $params['id'] = $order['order_id']; $params['order_status'] = OrderStatusEnum::REPEAL; $res = Order::close($params); if (!$res) throw new \Exception(Order::getStaticError()); } } /** * 订单支付 * @param array $event * @param string $event_key * @return void * @throws Exception * @throws \Exception */ public function paid(array $event, string $event_key = 'order_info') { $orders = $this->getByThirdOrderId($event[$event_key]['order_id'], $event, 'channels_ec_order_pay'); if (is_string($orders)) { return true; } foreach ($orders as $order) { $res = Order::pay($order['order'], 1, ''); // 默认为微信支付 if($res === false) throw new Exception(Order::getStaticError()); // 本地订单也需要修改为支付状态 } $order_ids = array_column($orders, 'id'); if (!empty($order_ids)) { WechatVideoShopOrder::updateAll(['is_pay' => StatusEnum::ENABLED], ['and', ['in', 'id', $order_ids]]); } } /** * 发货 * @param array $event * @param string $event_key * @return void * @throws \Exception */ public function ship(array $event, string $event_key = 'order_info') { $orders = $this->getByThirdOrderId($event[$event_key]['order_id'], $event, 'channels_ec_order_deliver'); if (is_string($orders)) { return true; } $resp = $this->getOrderInfo($event[$event_key]['order_id']); if (empty($resp['order'])) throw new \Exception('订单获取失败'); $delivery_product_info = $resp['order']['order_detail']['delivery_info']['delivery_product_info'][0] ?? []; if (empty($delivery_product_info)) throw new \Exception("发货记录不存在"); $delivery_product_infos = $delivery_product_info['product_infos'] ?? []; foreach ($orders as $order) { $params['mall_id'] = $this->mall_id; $params['mch_id'] = 0; $params['operator_id'] = 0; $params['operator_name'] = self::OPERATOR_NAME; $params['id'] = $order['order_id']; $shipping_skus = array_column($delivery_product_infos, 'sku_id'); $shipping_local_skus = array_column($resp['order']['order_detail']['product_infos'], 'out_sku_id', 'sku_id'); switch ($delivery_product_info['']) { case WechatVideoShopDeliveryTypeEnums::DELIVERY_TYPE_SELF_SHIP: case WechatVideoShopDeliveryTypeEnums::DELIVERY_TYPE_SIGN_CONTRACT: case WechatVideoShopDeliveryTypeEnums::DELIVERY_TYPE_ONLINE: $params['shipping_type'] = StatusEnum::ENABLED; // 物流 break; case WechatVideoShopDeliveryTypeEnums::DELIVERY_TYPE_VIRTUAL_SHIP: $params['shipping_type'] = StatusEnum::DISABLED; // 无需物流 break; } // 取出快递公司 $expressCompany = WechatVideoShopExpressCompany::getOne([ ['delivery_id' => $delivery_product_info['delivery_id']] ]); // 默认为其他快递公司 $express_id = 10000; $express_name = '其他'; if (!empty($expressCompany)) { $express_id = $expressCompany->company_id; $express_name = $expressCompany->delivery_name; } $order_detail_ids = OrderDetail::find()->where(['mall_id' => $this->mall_id]) ->andWhere(['order_id' => $params['id']]) ->andWhere(['goods_attr_id' => $shipping_local_skus])->select('id')->column(); $params['order_detail_ids'] = $order_detail_ids; $params['express_id'] = $express_id; $params['express_name'] = $express_name; $params['customer_name'] = ''; $params['express_no'] = $delivery_product_info['waybill_id']; $params['memo'] = ''; if (empty($params['shipping_change'])) { $res = OrderExpress::delivery($params); // 发货 } else { $res = OrderExpress::shippingChange($params);// 修改物流 } if (!$res) throw new \Exception(OrderExpress::getStaticError()); } } /** * 签收 * @param array $event * @param string $event_key * @return void * @throws \Exception */ public function sing(array $event, string $event_key = 'order_info') { $orders = $this->getByThirdOrderId($event[$event_key]['order_id'], $event, 'channels_ec_order_confirm'); if (is_string($orders)) { return true; } foreach ($orders as $order) { $params['mall_id'] = $this->mall_id; $params['user_id'] = $order['user_id']; $params['operator_id'] = 0; $params['operator_name'] = self::OPERATOR_NAME; $params['id'] = $order['order_id']; $res = Order::takeDelivery($params); if (!$res) throw new \Exception(Order::getStaticError()); } } /** * 结算 * @param array $event * @param string $event_key * @return void * @throws \Exception */ public function settlement(array $event, string $event_key = 'order_info') { $orders = $this->getByThirdOrderId($event[$event_key]['order_id'], $event, 'channels_ec_order_settle'); if (is_string($orders)) { return true; } WechatVideoShopOrder::updateAll(['is_settle' => StatusEnum::ENABLED, 'settle_at' => time()], ['and', ['third_order_id' => $event[$event_key]['order_id']], ['is_pay' => OrderStatusEnum::PAY], ['in', 'order_status', [OrderStatusEnum::SING, OrderStatusEnum::ACCOMPLISH]]]); } /** * 其他信息更新 * @param array $event * @param string $event_key * @return void * @throws \Exception */ public function update(array $event, string $event_key = 'order_info') { $orders = $this->getByThirdOrderId($event[$event_key]['order_id'], $event, 'channels_ec_order_ext_info_update'); if (is_string($orders)) { return true; } $resp = $this->getOrderInfo($event[$event_key]['order_id']); switch ($event[$event_key]['type']) { case WechatVideoShopOrderUpdateEnums::Order_UPDATE_TYPE_COMMISSION: // 联盟佣金 break; case WechatVideoShopOrderUpdateEnums::Order_UPDATE_TYPE_ADDRESS: // 地址修改 // 收货地址 foreach ($orders as $order) { $w_order_detail = $resp['order']['order_detail']; // 订单详细数据信息 $w_delivery_info = $w_order_detail['delivery_info'] ?? []; $w_address_info = $w_delivery_info['address_info'] ?? []; $addr = $this->getAddress($w_address_info, $order['user_id']); $params['receiver_name'] = $addr->name; $params['mobile'] = $addr->mobile; $params['province'] = $addr->province; $params['city'] = $addr->city; $params['area'] = $addr->district; $params['address'] = $addr->detail; $params['region_name'] = "{$addr->province} {$addr->city} {$addr->district}"; $params['mall_id'] = $this->mall_id; $params['mch_id'] = 0; $params['operator_id'] = 0; $params['operator_name'] = self::OPERATOR_NAME; $params['id'] = $order['order_id']; if (!Order::changeAddress($params)) throw new \Exception(Order::getStaticError()); } break; case WechatVideoShopOrderUpdateEnums::Order_UPDATE_TYPE_SELLER_REMARK: // 商家备注 foreach ($orders as $order) { $params['mall_id'] = $this->mall_id; $params['mch_id'] = 0; $params['operator_id'] = 0; $params['operator_name'] = self::OPERATOR_NAME; $params['seller_remark'] = $resp['order']['ext_info']['merchant_notes'] ?? ''; // 商家备注 $params['remark'] = $resp['order']['ext_info']['customer_notes'] ?? ''; // 买家备注 $params['id'] = $order['order_id']; if (!Order::remark($params)) throw new \Exception(Order::getStaticError()); } break; case WechatVideoShopOrderUpdateEnums::Order_UPDATE_TYPE_VIRTUAL_NUMBER: // 虚拟号码 break; } } /** * 获取多个订单 * @param $third_order_id * @param $event * @param $method * @return mixed * @throws \Exception */ protected function getByThirdOrderId($third_order_id, $event, $method) { $orders = WechatVideoShopOrder::lists([ 'where' => [ ['third_order_id' => $third_order_id] ], 'with' => ['order' => function($query) { $query->with(['detail']); }, 'user' => function($query) { $query->select('id, nickname'); }] ]); // $orders = WechatVideoShopOrder::getOne([ // ['third_order_id' => $third_order_id] // ], true, ['order' => function($query) { // $query->with(['detail']); // }, 'user' => function($query) { // $query->select('id, nickname'); // }]); if (empty($orders)) { // 延时队列 // 如果没有取到分销员,那么就放入延迟队列进行处理 $is_delay = '未延时'; $sec = WechatVideoShopEnums::CUSTOMER_DELAY[$this->customer_num] ?? 0; if (!empty($sec)) { // 这里需要入列 \Yii::$app->services->rabbitMq->delay($sec, ['mall_id' => $this->mall_id, 'shop_id' => $this->shop_id, 'customer_num' => $this->customer_num + 1, 'data' => $event], WeChatCallbackLogic::class, $method); $is_delay = "延时 $sec 秒, 操作方法为: $method"; } // throw new \Exception("记录不存在, $is_delay"); \Yii::error(__METHOD__ . " --> 记录不存在, $is_delay -> $third_order_id"); return ""; } return $orders; } /** * 通过第三方订单编号获取订单信息 * @param $third_order_id * @return mixed|null * @throws \Exception */ protected function findByThirdOrderId($third_order_id) { $order = WechatVideoShopOrder::getOne([ ['third_order_id' => $third_order_id] ], true, ['order' => function($query) { $query->with(['detail']); }, 'user' => function($query) { $query->select('id, nickname'); }]); if (empty($order)) throw new \Exception("记录不存在"); return $order; } /** * @param $w_order_unionid * @param $w_order_openid * @param array $order * @param array $share_info * @return array * @throws Exception * @throws \Exception */ protected function getUser($w_order_unionid, $w_order_openid, array $order, array $share_info = []) { $ui_where = [ ['mall_id' => $this->mall_id], ['platform' => User::PLATFORM_WECHAT_VIDEO_SHOP], ]; $is_find_by_unionid = false; if (!empty($w_order_unionid)) { $is_find_by_unionid = true; $ui_where[] = ['unionid' => $w_order_unionid]; } else { $ui_where[] = ['openid' => $w_order_openid]; } $userInfo = UserInfo::getOne($ui_where); // 判断当前用户 // 判断当前用户之前是否有订单 - 且是否有上级,如果有的话那么就直接将奖励分给旧的分销员 if (!empty($userInfo)) { $o_Order = WechatVideoShopOrder::getOne([ ['user_id' => $userInfo->user_id], ['>', 'parent_id', StatusEnum::DISABLED] ], false, [], 'id asc', 'parent_id'); if (!empty($o_Order) && !empty($o_Order->parent_id)) { $sUserInfo = UserInfo::getOne([ ['mall_id' => $this->mall_id], ['user_id' => $o_Order->parent_id], ]); } } /* 因为微信小店下架了分销,所以去除分享员信息 if (!empty($share_info) && empty($sUserInfo)) { // 分销员不为空并且之前的分销员为空 // 不能用OR,因为如果当前用户有注册过那么当前的openid就写不进去了 $sUserInfo = $this->getShareUserInfo($share_info); if (empty($sUserInfo)) { // 如果分销员不存在,那么就为其注册一个用户 - 分销员注册 $sUser = User::setDataByNoTransaction([ 'mall_id' => $this->mall_id, 'parent_id' => StatusEnum::DELETE, 'nickname' => '微信视频小店用户', 'source' => User::SOURCE_WECHAT_VIDEO_SHOP, 'platform' => User::TYPE_WECHAT_VIDEO_SHOP, ]); if (!$sUser) throw new \Exception(User::getStaticError()); // 需要创建用户? $sUserInfo = UserInfo::setData([ 'openid' => $share_info['sharer_openid'], 'unionid' => $share_info['sharer_unionid'], 'platform' => User::PLATFORM_WECHAT_VIDEO_SHOP, 'mall_id' => $this->mall_id, 'user_id' => $sUser->id ]); } }*/ if (empty($userInfo)) { // 注册用户id $user = User::setDataByNoTransaction([ 'mall_id' => $this->mall_id, 'parent_id' => !empty($sUserInfo) ? $sUserInfo->user_id : StatusEnum::DELETE, 'nickname' => '微信视频小店用户', 'source' => User::SOURCE_WECHAT_VIDEO_SHOP, 'platform' => User::TYPE_WECHAT_VIDEO_SHOP, ]); if (!$user) throw new \Exception(User::getStaticError()); // 需要注册 $userInfo = UserInfo::setData([ 'openid' => $w_order_openid, 'unionid' => $w_order_unionid, 'platform' => User::PLATFORM_WECHAT_VIDEO_SHOP, 'mall_id' => $this->mall_id, 'user_id' => $user->id ]); if (!$userInfo) throw new \Exception(UserInfo::getStaticError()); } else { // 如果使用的unionid取出来的用户数据那么就需要判断openid是否已经添加,如果没有添加那么就需要添加一行数据 if ($is_find_by_unionid && empty(UserInfo::getOne([ ['mall_id' => $this->mall_id], ['platform' => User::PLATFORM_WECHAT_VIDEO_SHOP], ['openid' => $w_order_openid] ]))) { // 如果是通过unionid查询的,那么判断是否有openid的记录 $userInfo = UserInfo::setData([ 'openid' => $w_order_openid, 'unionid' => $w_order_unionid, 'platform' => User::PLATFORM_WECHAT_VIDEO_SHOP, 'mall_id' => $this->mall_id, 'user_id' => $userInfo->user_id ]); if (!$userInfo) throw new \Exception(UserInfo::getStaticError()); } } return [$userInfo, !empty($sUserInfo) ? $sUserInfo->user_id : 0]; } /** * 获取分享人ID * @param array $share_info * @return mixed|null * @throws \Exception */ protected function getShareUserInfo(array $share_info) { $sui_where = [ ['mall_id' => $this->mall_id], ]; $is_find_by_unionid = false; if (!empty($share_info['sharer_unionid'])) { $is_find_by_unionid = true; $sui_where[] = ['unionid' => $share_info['sharer_unionid']]; } else { $sui_where[] = ['openid' => $share_info['sharer_openid']]; } $userInfo = UserInfo::getOne($sui_where); // 如果是通过unionid获取的那么就需要判断当前openid是否已经添加 if ($is_find_by_unionid && !empty($userInfo) && empty(UserInfo::getOne([ ['mall_id' => $this->mall_id], ['platform' => User::PLATFORM_WECHAT_VIDEO_SHOP], ['openid' => $share_info['sharer_openid']] ]))) { $userInfo = UserInfo::setData([ 'openid' => $share_info['sharer_openid'], 'unionid' => $share_info['sharer_unionid'], 'platform' => User::PLATFORM_WECHAT_VIDEO_SHOP, 'mall_id' => $this->mall_id, 'user_id' => $userInfo->user_id ]); if (!$userInfo) throw new \Exception(UserInfo::getStaticError()); } // 分销员用户信息 return $userInfo; } /** * 创建平台订单 * @param int $user_id * @param array $params * @return array * @throws \Exception */ protected function getOrder(int $user_id, array $params) { $orderFormLogic = new OrderFormLogic(); $form = $orderFormLogic->getDefaultform($this->mall_id, $user_id); $form->attributes = $params; $form['action'] = AppEnum::ACTION_CREATE; // 初始化订单数据 $orderInitDataLogic = new OrderInitDataLogic(); $form = $orderInitDataLogic->execute($form, $form->type); if ($form === false) throw new \Exception($orderInitDataLogic->getError()); $orderMarketingLogic = new OrderMarketingLogic(); $form = $orderMarketingLogic->run($form, true); if ($form === false) throw new \Exception($orderMarketingLogic->getError()); $res = Order::createOrder($form); if ($res === false) throw new \Exception(Order::getStaticError()); return $res; } /** * @param array $addr * @param int $user_id * @return mixed|null * @throws \Exception */ protected function getAddress(array $addr, int $user_id) { // 取出数据 $region = WechatVideoShopRegion::getOne([ ['level' => 3], ['name' => $addr['county_name']], ['level_one_name' => $addr['province_name']], ['level_two_name' => $addr['city_name']], ]); if (empty($region)) throw new \Exception("地区 [{$addr['county_name']}] 不存在"); $address = UserAddress::getOne([ ['user_id' => $user_id], ['name' => $addr['user_name']], ['province_id' => $region->local_one_id], ['city_id' => $region->local_two_id], ['district_id' => $region->id], ['detail' => $addr['detail_info']], ['mobile' => $addr['tel_number']], ]); if (empty($address)) { $address = UserAddress::setData([ 'user_id' => $user_id, 'name' => $addr['user_name'], 'province_id' => $region['local_one_id'], 'province' => $region['local_one_name'], 'city_id' => $region['local_two_id'], 'city' => $region['local_two_name'], 'district_id' => $region['id'], 'district' => $region['name'], 'mobile' => $addr['tel_number'], 'detail' => $addr['detail_info'], ]); if (!$address) throw new \Exception(UserAddress::getStaticError()); } return $address; } /** * 加入购物车 * @param array $goods * @param int $user_id * @return array * @throws \Exception */ protected function setCart(array $goods, int $user_id) { $sku_ids = array_column($goods, 'out_sku_id'); $goods_ids = GoodsAttr::lists([ 'where' => [ ['id' => $sku_ids] ], 'select' => 'id, goods_id', 'index' => 'id' ]); foreach ($goods as $good) { Cart::addCart([ 'num' => $good['sku_cnt'], 'mch_id' => 0, 'mall_id' => $this->mall_id, 'user_id' => $user_id, 'attr_id' => $good['out_sku_id'], 'goods_id' => $goods_ids[$good['out_sku_id']], 'buy_limit_nums' => 0, 'buy_limit_total_num' => 0, ]); } return $sku_ids; } /** * 获取订单详情 * @param $order_id * @return array * @throws \Exception */ protected function getOrderInfo($order_id) { $orderInfoModel = new OrderInfoModel(); $orderInfoModel->order_id = $order_id; return WechatRequestHelper::accessTokenAndToArray(new OrderInfoRequest($this->config), $orderInfoModel); } }