/** * Вызвать запрос к сервису на возврат средств. * * @param int $reserve_id * * @return bool * * @throws ReservesPaybackException */ public function doPayback($reserve_id) { $paybackData = $this->db()->row("\n SELECT *\n FROM {$this->TABLE}\n WHERE reserve_id = ?i\n ", $reserve_id); //Если запроса не существует if (!$paybackData) { throw new ReservesPaybackException(ReservesPaybackException::PAYBACK_NOTFOUND); } //Если запрос уже успешно обработан //(урал так как если вдруг неполучится сменить статус резерва возврата а возврат пройдет то можно повторить) //if($paybackData['status'] == self::STATUS_SUCCESS) // throw new ReservesPaybackException(ReservesPaybackException::ALREADY_PAYBACK_MSG); $is_timeout = $this->isTimeout($paybackData['cnt'], $paybackData['last']); //Таймаут еще не вышел нужно поставить в очередь if (!$is_timeout) { return false; } //Превышен лимит прерываем цикл для этого запроса if ($is_timeout === -1) { throw new ReservesPaybackException(ReservesPaybackException::REQUEST_LIMIT); } //Если не существует самого резерва $reserveInstance = ReservesModelFactory::getInstanceById($paybackData['reserve_id']); if (!$reserveInstance) { throw new ReservesPaybackException(ReservesPaybackException::PAYBACK_NOTFOUND); } $data['cnt'] = $paybackData['cnt'] + 1; $data['last'] = 'NOW()'; try { //Готовим запрос $returnPaymentRequest = new ReturnPaymentRequest(); $returnPaymentRequest->setShopId(yandex_kassa::SHOPID_SBR); $returnPaymentRequest->setClientOrderId($paybackData['id']); $returnPaymentRequest->setInvoiceId($paybackData['invoice_id']); $returnPaymentRequest->setCurrency($this->getCurrency()); $returnPaymentRequest->setCause(sprintf(self::PAYBACK_CAUSE, $reserveInstance->getNUM())); $returnPaymentRequest->setAmount(number_format($paybackData['price'], 2, '.', '')); //Делаем запрос к API сервиса $result = $this->getApiFacade()->returnPayment($returnPaymentRequest); //Выставляем статус и код ошибки $data['status'] = $result->getStatus(); $data['error'] = !$result->isSuccess() ? $result->getError() : 0; } catch (Exception $e) { //В случае аварии при транспорте API //пишем в лог и просим поставить задачу в очередь $data['status'] = self::STATUS_FAIL; $data['error'] = 10000 + intval($e->getCode()); $this->db()->update($this->TABLE, $data, 'id = ?i', $paybackData['id']); throw new ReservesPaybackException($e->getMessage(), true); } $this->db()->update($this->TABLE, $data, 'id = ?i', $paybackData['id']); $new_status = $this->getSubStatus($result->getStatus()); //Нет смысла менять статус так как система уже в таком же статусе //например долгий процесс ожидания if ($reserveInstance->getStatusBack() != $new_status) { //Не удалост сменить статус if (!$reserveInstance->changeBackStatus($new_status)) { throw new ReservesPaybackException(ReservesPaybackException::CANT_CHANGE_SUBSTATUS, true); } } //Ошибки при которых ставить в очередь нет смысла if (!$result->isSuccess() && in_array($result->getError(), array(403, 404, 405, 412, 413, 414, 417))) { throw new ReservesPaybackException(ReservesPaybackException::API_CRITICAL_FAIL, $result->getError()); } //Если статус еще не оплачен то нужно //повторить и поставить задачу в очередь return $reserveInstance->isStatusBackPayed(); }
/** * Запрос выплаты у сервиса * * @param type $reserve_id */ public function doPayout($reserve_id) { //Если не существует самого резерва $reserveInstance = ReservesModelFactory::getInstanceById($reserve_id); if (!$reserveInstance) { throw new ReservesPayoutQueueException(ReservesPayoutQueueException::RESERVE_NOTFOUND); } //Если статус БС неподходит if (!$reserveInstance->isAllowPayoutForQueue()) { throw new ReservesPayoutQueueException(ReservesPayoutQueueException::RESERVE_STATUS_FAIL); } //Задачи на выплату $request_list = $this->getPayouts($reserve_id); if (!$request_list) { throw new ReservesPayoutQueueException(ReservesPayoutQueueException::NOTFOUND); } $substatus = ReservesModel::SUBSTATUS_PAYED; $is_done = true; $_work_request = array(); foreach ($request_list as $request) { if (in_array($request['status'], array(self::STATUS_NEW, self::STATUS_INPROGRESS, self::STATUS_FAIL))) { $_work_request = $request; $is_done = false; break; } } //Оказывается все уже выплачено if ($is_done) { //Попытаемся сменить статус $reserveInstance->changePayStatus($substatus); throw new ReservesPayoutQueueException(ReservesPayoutQueueException::PAYED); } $type = null; $reqv = array(); //Получаем реквизиты из слепка $data_reqv = $this->getPayoutReqv($reserve_id); if ($data_reqv) { $reqv = mb_unserialize($data_reqv['fields']); if ($reqv) { $type = $data_reqv['pay_type']; } } //Есть ли реквизиты для выплаты if (empty($reqv)) { throw new ReservesPayoutException(ReservesPayoutException::REQV_INVALID); } //Вычисляем тайм аут $last = empty($_work_request['last']) ? $_work_request['date'] : $_work_request['last']; $is_timeout = $this->isTimeout($_work_request['cnt'], $last); if (!$is_timeout) { //Таймаут еще не вышел нужно поставить в очередь return false; } elseif ($is_timeout === -1) { //Превышен лимит прерываем цикл для этого запроса throw new ReservesPayoutQueueException(ReservesPayoutQueueException::REQUEST_LIMIT); } //Формирование запроса к API сервиса и обработка ответа try { $depositionRequest = new DepositionRequest(); $depositionRequest->setAgentId($this->agent_id); $depositionRequest->setCurrency($this->currency); $depositionRequest->setPofOfferAccepted(1); $depositionRequest->setSmsPhoneNumber(trim(str_replace('+', '', $reqv['mob_phone']))); foreach ($request_list as $key => $request) { if ($request['status'] == static::STATUS_SUCCESS) { continue; } $depositionRequest->setAmount(number_format($request['price'], 2, '.', '')); $depositionRequest->setClientOrderId($request['id']); //Заполняем общие параметры для платежей //Например реквизиты юзера switch ($type) { case ReservesPayoutPopup::PAYMENT_TYPE_RS: //Реквизиты юзера $fio = explode(' ', $reqv['fio']); $depositionRequest->setTmpFirstName(@$fio[1]); $depositionRequest->setTmpMiddleName(@$fio[2]); $depositionRequest->setTmpLastName(@$fio[0]); case ReservesPayoutPopup::PAYMENT_TYPE_CARD: //Реквизиты юзера $fio = explode(' ', $reqv['fio']); $depositionRequest->setPdrFirstName(@$fio[1]); $depositionRequest->setPdrMiddleName(@$fio[2]); $depositionRequest->setPdrLastName(@$fio[0]); if (isset($reqv['rez_type']) && @$reqv['rez_type'] == sbr::RT_UABYKZ) { $depositionRequest->setPdrDocType(10); } else { $depositionRequest->setPdrDocType(21); } $depositionRequest->setPdrDocNumber(@$reqv['idcard_ser'] . @$reqv['idcard']); $date = explode('.', @$reqv['idcard_from']); $depositionRequest->setPdrDocIssueYear(@$date[2]); $depositionRequest->setPdrDocIssueMonth(@$date[1]); $depositionRequest->setPdrDocIssueDay(@$date[0]); $depositionRequest->setPdrDocIssuedBy(@$reqv['idcard_by']); $country_iso = @$reqv['country_iso']; //@todo: если не удалось выявить код то Россия Матушка :D ! $depositionRequest->setPdrCountry($country_iso ? $country_iso : 643); //парсим адрес по формату: //127287, Россия, г. Москва, ул. 2-я Хуторская д 38А стр.9 $info = explode(',', @$reqv['address']); if (isset($reqv['index']) && !empty($reqv['index'])) { $depositionRequest->setPdrPostcode($reqv['index']); } else { $depositionRequest->setPdrPostcode(trim(@$info[0])); } if (isset($reqv['city']) && !empty($reqv['city'])) { $depositionRequest->setPdrCity($reqv['city']); $depositionRequest->setPdrBirthPlace($reqv['city']); } else { $depositionRequest->setPdrCity(trim(@$info[2])); $depositionRequest->setPdrBirthPlace(trim(@$info[2])); } if (count($info) > 4) { unset($info[0], $info[1], $info[2]); $depositionRequest->setPdrAddress(trim(implode(',', $info))); } else { $depositionRequest->setPdrAddress(trim(@$info[3])); } $depositionRequest->setPdrBirthDate(@$reqv['birthday']); break; } //Специфика для каждого платежа в отдельности switch ($type) { case ReservesPayoutPopup::PAYMENT_TYPE_YA: $depositionRequest->setDstAccount($reqv['el_yd']); break; case ReservesPayoutPopup::PAYMENT_TYPE_CARD: $depositionRequest->setDstAccount(25700130535186); $depositionRequest->setSkrDestinationCardSynonim($reqv['skr_destinationCardSynonim']); break; case ReservesPayoutPopup::PAYMENT_TYPE_RS: $depositionRequest->setDstAccount(2570066962077); $bank = explode(',', $reqv['bank_name']); $depositionRequest->setBankName(trim(@$bank[0])); if (isset($reqv['bank_city']) && !empty($reqv['bank_city'])) { $depositionRequest->setBankCity(trim(@$reqv['bank_city'])); } else { $depositionRequest->setBankCity(trim(@$bank[1])); } $depositionRequest->setBankBIK(trim(@$reqv['bank_bik'])); $depositionRequest->setBankCorAccount(trim(@$reqv['bank_ks'])); $depositionRequest->setBankKPP(trim(@$reqv['bank_kpp'])); $depositionRequest->setBankINN(trim(@$reqv['bank_inn'])); /*@todo: ЯД меняет формат на ходу, тут устаревший if (isset($reqv['bank_assignment']) && !empty($reqv['bank_assignment'])) { $depositionRequest->setDepositAccount(@$reqv['bank_rs']); $depositionRequest->setFaceAccount(@$reqv['bank_assignment']); } else { $depositionRequest->setRubAccount(@$reqv['bank_rs']); } */ $bank_rs = trim(@$reqv['bank_rs']); $depositionRequest->setDepositAccount($bank_rs); $depositionRequest->setFaceAccount($bank_rs); $depositionRequest->setCustAccount($bank_rs); break; default: throw new ReservesPayoutException(ReservesPayoutException::TYPE_INVALID, $type); } $current_substatus = ReservesModel::SUBSTATUS_PAYED; //Запрос к API $result = $this->getApiFacade()->testDeposition($depositionRequest); if (!$result->isSuccess() && $result->getError() != 26) { $current_substatus = ReservesModel::SUBSTATUS_ERR; } else { $result = $this->getApiFacade()->makeDeposition($depositionRequest); if ($result->getStatus() == static::STATUS_INPROGRESS) { $current_substatus = ReservesModel::SUBSTATUS_INPROGRESS; } elseif ($result->getStatus() == static::STATUS_FAIL) { $current_substatus = ReservesModel::SUBSTATUS_ERR; } } $_request = array('status' => $result->getStatus(), 'error' => !$result->isSuccess() ? $result->getError() : 0, 'last' => 'NOW()', 'cnt' => $request['cnt'] + 1, 'techmessage' => $result->getTechMessage()); $is_done = $this->db()->update($this->TABLE, $_request, 'id = ?i', $result->getClientOrderId()); //Не удалось обновить значит ошибка if (!$is_done) { $current_substatus = ReservesModel::SUBSTATUS_ERR; } if ($current_substatus == ReservesModel::SUBSTATUS_ERR) { if ($substatus != ReservesModel::SUBSTATUS_INPROGRESS) { $substatus = $current_substatus; } $techmessage = $result->getTechMessage(); if ($techmessage) { $techmessage = " ({$techmessage})"; } $this->errorLog($reserve_id, sprintf(ReservesPayoutException::LAST_PAYED_FAIL, $result->getClientOrderId(), $result->getError(), $techmessage)); } elseif ($current_substatus == ReservesModel::SUBSTATUS_INPROGRESS) { $substatus = $current_substatus; } } //Сохраняем в историю слепок с последнего ответа $this->saveToHistory($reserve_id); } catch (Exception $e) { $this->errorLog($reserve_id, $e->getMessage()); $substatus = ReservesModel::SUBSTATUS_ERR; } //Нет смысла менять статус так как система уже в таком же статусе //например долгий процесс ожидания if ($reserveInstance->getStatusPay() != $substatus) { //Не удалост сменить статус if (!$reserveInstance->changePayStatus($substatus)) { throw new ReservesPayoutQueueException(ReservesPayoutQueueException::CANT_CHANGE_SUBSTATUS, true); } } //Ошибки при которых ставить в очередь нет смысла if ($reserveInstance->isStatusPayError()) { throw new ReservesPayoutQueueException(ReservesPayoutQueueException::API_CRITICAL_FAIL, $result->getError()); } return $reserveInstance->isStatusPayPayed(); }
/** * Выставяем счет оплаты по безналу для резерва. * * @param string $type - тип платежа (тут всегда bank) * @param array $data * * @return \xajaxResponse */ function quickPaymentReserveBank($type, $data) { $objResponse =& new xajaxResponse(); $uid = get_uid(false); if ($uid <= 0) { return $objResponse; } //Проверка на юрика $reqvs = ReservesHelper::getInstance()->getUserReqvs($uid); if ($reqvs['form_type'] != sbr::FT_JURI) { return $objResponse; } $reqv = $reqvs[$reqvs['form_type']]; //Проверка наличия резерва средств $reserve_id = intval(@$data['quick_payment_reserve_form']); $reserveInstance = ReservesModelFactory::getInstanceById($reserve_id); if (!$reserveInstance) { return $objResponse; } $reserve_data = $reserveInstance->getReserveData(); if ($reserve_data['emp_id'] != $uid || !$reserveInstance->isEmpAllowFinance()) { return $objResponse; } //Если уже был платеж то обновляем страницу if (!$reserveInstance->isStatusNew()) { $objResponse->script('window.location.reload()'); return $objResponse; } $reqv['is_send_docs'] = @$data['is_reserve_send_docs'] == 1; $file = $reserveInstance->getReservesBank()->generateInvoice2($reqv, true); if (!$file) { $objResponse->script("\n var qp_reserve = quick_payment_factory.getQuickPayment('reserve');\n if(qp_reserve) qp_reserve.show_error('Не удалось создать файл счета. Попробуйте еще раз.');\n "); return $objResponse; } $success_text = 'Для резервирования суммы на сайте вам был сформирован ' . '<a href="' . WDCPREFIX . '/' . $file->path . $file->name . '" target="_blank">счет на оплату</a>.<br />' . 'Счет также доступен вам в заказе в списке загруженных документов.'; $objResponse->script("\n var qp_reserve = quick_payment_factory.getQuickPayment('reserve');\n if(qp_reserve) qp_reserve.show_success('" . $success_text . "');\n "); return $objResponse; }
//require_once($_SERVER['DOCUMENT_ROOT'] . "/classes/config.php"); //require_once($_SERVER['DOCUMENT_ROOT'] . "/classes/profiler.php"); //require_once($_SERVER['DOCUMENT_ROOT'] . "/classes/billing.php"); require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/reqv.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/sbr_meta.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/classes/reserves/ReservesModelFactory.php'; //------------------------------------------------------------------------------ $results = array(); //$profiler = new profiler(); //------------------------------------------------------------------------------ $uid = 33; $reqvs = sbr_meta::getUserReqvs($uid); $reqv = $reqvs[$reqvs['form_type']]; //Проверка наличия резерва средств $reserve_id = 3; $reserveInstance = ReservesModelFactory::getInstanceById($reserve_id); $reserve_data = $reserveInstance->getReserveData(); $sum = $reserve_data['reserve_price']; $sum = $sum < 10 ? 10 : $sum; $reqv['price'] = $sum; $reserveInstance->getReservesBank()->generateInvoice($reqv); //------------------------------------------------------------------------------ //$profiler->start('fill_frl_mem'); //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //$profiler->stop('fill_frl_mem'); //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ array_walk($results, function (&$value, $key) { $value = sprintf('%s = %s' . PHP_EOL, $key, $value); });