error = $msg; return false; } /** * 提现打款 * * @param array $params * @return array [boolean, string] */ public function withdrawToPay($params) { $mall_id = $params['mall_id'] ?? ''; $order_ids = $params['ids'] ?? ''; /** * @var Apply */ $apply = Apply::find()->where(['mall_id' => $mall_id])->one(); if (empty($apply)) { return [false, "支付宝代付配置未设置"]; } if ($apply->auth_status != 2) { return [false, "支付宝代付未授权"]; } $list = Withdraw::find() ->where([ 'id' => $order_ids, 'mall_id' => $mall_id, 'status' => Withdraw::STATUS_AGREE, 'type' => "alipay", ]) ->asArray() ->all(); if (empty($list)) { return [false, "没有符合条件的提现记录"]; } $uniqid = uniqid(); $lock_key = "alitopay_order_lock_" . $mall_id; if (!LockHelper::lock($lock_key, $uniqid)) { return [false, "操作频繁请稍后重试"]; }; try { $order_insert = $trans_list = []; foreach ($list as $cash) { // 收款对象 $ali_user = Json::decode($cash['extra']); if (empty($ali_user['name']) || empty($ali_user['mobile'])) { return [false, "订单{$cash['order_no']},支付宝名称或者支付宝账号为空"]; } if ($cash['actual_num'] < 1) { return [false, "订单{$ali_user['name']},打款金额必须大于1元"]; } // $ali_user['name'] = '陆福佳'; // $ali_user['mobile'] = '15820232749'; $one['mall_id'] = $apply->mall_id; $one['order_sn'] = time() . rand(1000, 9999); $one['type'] = Order::TYPE_WITHDRAWAL; $one['money'] = $cash['actual_num']; $one['name'] = $ali_user['name']; $one['account'] = $ali_user['mobile']; $one['source_id'] = $cash['id']; $one['source_sn'] = $cash['order_no']; $one['created_at'] = time(); $one['updated_at'] = time(); $order_insert[] = $one; } $db = \Yii::$app->db->beginTransaction(); $res = \Yii::$app->db ->createCommand() ->batchInsert(Order::tableName(), array_keys($order_insert[0]), $order_insert) ->execute(); if (!$res) { LockHelper::uLock($lock_key, $uniqid); $db->rollBack(); return [false, "创建代付订单失败"]; } // 修改提现记录,打款中 $res = UserWithdrawLog::updateAll(['status' => 5, 'updated_at' => time()], ['id' => $order_ids]); if (!$res) { LockHelper::uLock($lock_key, $uniqid); $db->rollBack(); return [false, "修改提现记录失败"]; } // 发起代付请求 try { $res = $this->ali_to_pay($apply, $order_insert); if ($res == false) { LockHelper::uLock($lock_key, $uniqid); $db->rollBack(); return [false, $this->error]; } else { LockHelper::uLock($lock_key, $uniqid); $db->commit(); } return [true, $res]; } catch (\Exception$e) { \Yii::error($e); LockHelper::uLock($lock_key, $uniqid); $db->rollBack(); return [false, $this->error($e->getMessage())]; } } catch (\Exception$e) { \Yii::error($e); isset($db) && $db->rollBack(); LockHelper::uLock($lock_key, $uniqid); return [false, $e->getMessage()]; } } public function orderToPay($mall_id, $ids) { } public function withdrawChannel($param) { $mall_id = $param['mall_id'] ?? 0; $data = Apply::findOne(['mall_id' => $mall_id]); $is_install = 0; if (!empty($data) && $data['auth_status'] == 2) { $is_install = 1; } return [ "alitopay" => [ 'is_install' => $is_install, ], ]; } public function orderQuery($id) { $order = Order::findOne($id); if ($order->status != 2) { return $this->error("订单状态不是打款中..."); } $mch = MiddleMch::getMch($order->mall_id); try { $api = new MiddleApi($mch); $res = $api->query($order->batch_sn); if (isset($res['order_list'])) { $this->orderNotifyHandle($res['order_list']); return true; } return $this->error("查询失败"); } catch (\Exception$e) { return $this->error($e->getMessage()); } } /** * 支付宝代付 * * @param Apply $apply * @param array $orders * @return string|false */ private function ali_to_pay(Apply $apply, $orders) { $order_sn = []; foreach ($orders as $order) { /** 创建支付宝数据 start **/ $data['out_biz_no'] = $order['order_sn']; $data['trans_amount'] = $order['money']; $data['order_title'] = '收益'; $data['payee_info'] = [ 'identity' => $order['account'], 'identity_type' => 'ALIPAY_LOGON_ID', 'name' => $order['name'], ]; $trans_list[] = $data; $order_sn[] = $order['order_sn']; /** 创建支付宝数据 end **/ } $out_batch_no = 'TX' . date("Ymd") . $apply->mall_id . rand(1000, 9999); Order::updateAll(["batch_sn" => $out_batch_no], ['mall_id' => $apply->mall_id, 'order_sn' => $order_sn]); $title = '收益提现'; $api_data = [ 'alipay_app_id' => $apply->alipay_app_id, 'out_batch_no' => $out_batch_no, 'order_title' => $title, 'trans_order_list' => Json::encode($trans_list), ]; // 发起代付请求 try { $mch = MiddleMch::getMch($apply->mall_id); $api = new MiddleApi($mch); $res = $api->pay($api_data); if (!isset($res['form_html'])) { return $this->error("代付订单 form_html 未定义"); } Order::updateAll(["status" => 2, 'updated_at' => time()], ['mall_id' => $apply->mall_id, 'order_sn' => $order_sn]); return $res['form_html']; } catch (\Exception$e) { \Yii::error($e); return $this->error($e->getMessage()); } } public function orderNotifyHandle($order_list) { foreach ($order_list as $item) { $order = Order::find()->where(['order_sn' => $item['out_biz_no'], 'status' => 2])->one(); if (empty($order)) { continue; } switch ($item['status']) { case "success": // 成功 $res = $this->_success($order, $item); break; case "wait": // 打款中,不做处理 break; case "fail": $res = $this->_fail($order, $item); // 失败 break; case "disuse": // 取消,也作为失败 break; } } return true; } private function _success(Order $order, $response) { $res = Order::updateAll(['status' => 3, 'msg' => '成功', 'updated_at' => time()], ['id' => $order->id]); if (!$res) { return $this->error("修改订单状态success失败"); } if ($order->type == 2) { // 手动打款的,直接返回成功 return true; } // 提现打款,要修改提现记录 $cash = UserWithdrawLog::findOne($order->source_id); UserWithdrawLog::remit_success($cash); // 提现成功... return true; } private function _fail(Order $order, $response) { $msg = $response['error_msg'] ?? "未知错误"; $res = Order::updateAll(['status' => 4, 'msg' => $msg, 'updated_at' => time()], ['id' => $order->id]); if (!$res) { return $this->error("修改订单状态success失败"); } if ($order->type == 2) { // 手动打款的,直接返回成功 return true; } // 提现打款,要修改提现记录 $cash = UserWithdrawLog::findOne($order->source_id); UserWithdrawLog::remit_fail($cash, $msg); // 失败... return true; } public function list($mall_id, $param) { $name = $param['name'] ?? ''; $batch_sn = $param['batch_sn'] ?? ''; $account = $param['account'] ?? ''; $source_sn = $param['source_sn'] ?? ''; $limit = $param['limit'] ?? 10; $page = $param['page'] ?? 1; $type = $param['type'] ?? ''; $status = $param['status'] ?? ''; $where[] = ["=", "mall_id", $mall_id]; $name && $where[] = ["=", "name", $name]; $batch_sn && $where[] = ["=", "batch_sn", $batch_sn]; $account && $where[] = ["=", "account", $account]; $source_sn && $where[] = ["=", "source_sn", $source_sn]; $type && $where[] = ["=", "type", $type]; $status && $where[] = ["=", "status", $status]; $params = array('where' => $where, 'order' => 'created_at desc', 'limit' => $limit); $list = Order::listPage($params, false, true); return $list; // $pagination = new Pagination(['totalCount' => $model->count(), 'pageSize' => $limit]); // $model->limit($pagination->limit)->offset($pagination->offset); // $list = $model->asArray() // ->orderBy('created_at desc') // ->all(); // $data['list'] = $list; // $data['page_count'] = $pagination->pageCount; // $data['current_page'] = $page + 1; // return $data; } /** * 返回前端提现方式 * * @param array $params * @return array */ public static function getWithdrawWay($params) { $mall_id = $params['mall_id']; // mall_id为空 后台显示提现方式 if (empty($mall_id)) return ['alipay' => '支付宝代付']; $apply = (new ApplyService())->getApply($mall_id); if ($apply && $apply['auth_status'] == 2) { return ['alipay' => '支付宝代付']; } return []; } public function ereceiptApply($mall_id, Order $order) { if (empty($order)) throw new \Exception('订单不存在'); $alipay = new AlipayService($mall_id); $request = new AlipayDataBillEreceiptApplyRequest(); $params = [ 'type' => 'FUND_DETAIL', 'key' => $order->order_id ]; $request->setBizContent(json_encode($params)); $result = $alipay->getAopClientMall()->execute($request); $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response"; $resultCode = $result->$responseNode->code; if (!empty($resultCode) && $resultCode == 10000) { $order->file_id = $result->$responseNode->file_id; $order->save(); return $order->file_id; } else { throw new \Exception($result->$responseNode->msg); } } public function ereceiptQuery($mall_id, Order $order) { if (empty($order)) throw new \Exception('订单不存在'); $alipay = new AlipayService($mall_id); $request = new AlipayDataBillEreceiptQueryRequest(); $params = [ 'file_id' => $order->file_id, ]; $request->setBizContent(json_encode($params)); $result = $alipay->getAopClientMall()->execute($request); $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response"; $resultCode = $result->$responseNode->code; $relative_filename = 'alipay/' . $mall_id; if (!empty($resultCode) && $resultCode == 10000) { $file_name = $order->order_id . '_' . time(); $absolute_dir = \Yii::getAlias('@attachment') . '/alipay/' . $mall_id . '/'; $res = CurlHelper::downImgRar($result->$responseNode->download_url, $file_name, 'pdf', $absolute_dir); $obj = new CsvTool(); $url = $obj->upload($mall_id, $relative_filename . '/' . $file_name . '.pdf'); $order->download_url = $url; $order->save(); unlink($res); return $url; } else { throw new \Exception($result->$responseNode->msg); } } public function fundTransCommonQuery($mall_id, $id) { try { $order = Order::findOne(['mall_id' => $mall_id, 'id' => $id]); if (empty($order)) throw new \Exception('订单不存在'); $alipay = new AlipayService($mall_id); $request = new AlipayFundTransCommonQueryRequest(); $params = [ 'out_biz_no' => $order->order_sn, 'biz_scene' => 'DIRECT_TRANSFER', 'product_code' => 'TRANS_ACCOUNT_NO_PWD', ]; $request->setBizContent(json_encode($params)); $result = $alipay->getAopClientMall()->execute($request); $responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response"; $resultCode = $result->$responseNode->code; if (!empty($resultCode) && $resultCode == 10000) { $order->order_id = $result->$responseNode->pay_fund_order_id; $order->save(); $this->ereceiptApply($mall_id, $order); sleep(1); $this->ereceiptQuery($mall_id, $order); return $result->$responseNode->pay_fund_order_id; } else { return $this->error($result->$responseNode->msg); } } catch (\Exception $e) { return $this->error($e->getMessage()); } } }