yoomoney_api-2.5.2/YooMoneySecondReceiptModel.php
YooMoneySecondReceiptModel.php
<?php
use YooKassa\Client;
use YooKassa\Model\PaymentInterface;
use YooKassa\Model\PaymentStatus;
use YooKassa\Model\Receipt\PaymentMode;
use YooKassa\Model\ReceiptCustomer;
use YooKassa\Model\ReceiptItem;
use YooKassa\Model\ReceiptType;
use YooKassa\Model\Settlement;
use YooKassa\Request\Receipts\CreatePostReceiptRequest;
use YooKassa\Request\Receipts\ReceiptResponseInterface;
use YooKassa\Request\Receipts\ReceiptResponseItemInterface;
class YooMoneySecondReceiptModel
{
/**
* @var array
*/
private $orderInfo = array(
'orderId' => 0,
'user_email' => '',
'user_phone' => '',
);
/**
* @var PaymentInterface
*/
private $paymentInfo;
/**
* @var string
*/
private $settlementsSum;
/**
* @var Client
*/
private $client;
/**
* @var YooMoneyKassaLogger
*/
private $kassaLog;
/**
* YooMoneySecondReceiptModel constructor.
* @param $paymentInfo
* @param $orderInfo
* @param $client Client
*/
public function __construct($paymentInfo, $orderInfo, $client, $kassaLog)
{
$this->orderInfo = $orderInfo;
$this->paymentInfo = $paymentInfo;
$this->client = $client;
$this->kassaLog = $kassaLog;
}
/**
* @return bool
*/
public function sendSecondReceipt()
{
$this->kassaLog->sendHeka(array('second-receipt.webhook.init'));
$this->log("info", "Hook send second receipt");
if (!$this->isPaymentInfoValid($this->paymentInfo)) {
$this->kassaLog->sendHeka(array('second-receipt.webhook.fail'));
$this->log("error", "Invalid paymentInfo");
return false;
}
if (empty($this->orderInfo['user_email']) && empty($this->orderInfo['user_phone'])) {
$this->kassaLog->sendHeka(array('second-receipt.webhook.fail'));
$this->log("error", "Invalid orderInfo orderInfo = " . print_r($this->orderInfo, true));
return false;
}
$receiptRequest = $this->buildSecondReceipt($this->getLastReceipt($this->paymentInfo->getId()), $this->paymentInfo, $this->orderInfo);
if (empty($receiptRequest)) {
$this->kassaLog->sendHeka(array('second-receipt.webhook.fail'));
$this->log("error", "Last receipt is empty");
return false;
}
$this->log("info", "Second receipt request data: " . json_encode($receiptRequest->jsonSerialize()));
try {
$this->kassaLog->sendHeka(array('second-receipt.send.init'));
$response = $this->client->createReceipt($receiptRequest);
$this->kassaLog->sendHeka(array('second-receipt.send.init'));
} catch (Exception $e) {
$this->kassaLog->sendHeka(array('second-receipt.webhook.fail', 'second-receipt.send.fail'));
$this->log("error", "Request second receipt error: " . $e->getMessage());
return false;
}
$this->log("info", "Request second receipt result: " . json_encode($response->jsonSerialize()));
$this->generateSettlementsAmountSum($response);
$this->kassaLog->sendHeka(array('second-receipt.webhook.success'));
return true;
}
/**
* @return string
*/
public function getSettlementsSum()
{
return $this->settlementsSum;
}
/**
* @param ReceiptResponseInterface $response
*/
private function generateSettlementsAmountSum($response)
{
$amount = 0;
foreach ($response->getSettlements() as $settlement) {
$amount += $settlement->getAmount()->getIntegerValue();
}
$this->settlementsSum = $amount / 100.0;
}
/**
* @param ReceiptResponseInterface $lastReceipt
* @param PaymentInterface $paymentInfo
* @param $orderInfo
*
* @return void|CreatePostReceiptRequest
*/
private function buildSecondReceipt($lastReceipt, $paymentInfo, $orderInfo)
{
$this->kassaLog->sendHeka(array('second-receipt.create.init'));
if (!($lastReceipt instanceof ReceiptResponseInterface)) {
$this->kassaLog->sendHeka(array('second-receipt.create.skip'));
$this->log("info", "Second receipt isn't need, not found first receipt");
return;
}
if ($lastReceipt->getType() === "refund") {
$this->kassaLog->sendHeka(array('second-receipt.create.skip'));
$this->log("info", "Receipt type = refund, second receipt isn't need");
return;
}
$resendItems = $this->getResendItems($lastReceipt->getItems());
if (count($resendItems['items']) < 1) {
$this->kassaLog->sendHeka(array('second-receipt.create.skip'));
$this->log("info", "Second receipt isn't need");
return;
}
try {
$receiptBuilder = CreatePostReceiptRequest::builder();
$customer = $this->getReceiptCustomer($this->orderInfo);
if (empty($customer)) {
$this->kassaLog->sendHeka(array('second-receipt.create.fail'));
$this->log("error", "Need customer phone or email for second receipt");
return;
}
$receiptBuilder->setObjectId($paymentInfo->getId())
->setType(ReceiptType::PAYMENT)
->setItems($resendItems['items'])
->setSettlements(
array(
new Settlement(
array(
'type' => 'prepayment',
'amount' => array(
'value' => $resendItems['amount'],
'currency' => 'RUB',
),
)
),
)
)
->setCustomer($customer)
->setSend(true);
$receipt = $receiptBuilder->build();
$this->kassaLog->sendHeka(array('second-receipt.create.success'));
return $receipt;
} catch (\Exception $e) {
$this->kassaLog->sendHeka(array('second-receipt.create.fail'));
$this->log("error", $e->getMessage() . ". Property name:". $e->getProperty());
}
}
/**
* @param PaymentInterface $paymentInfo
* @return bool
*/
private function isPaymentInfoValid($paymentInfo)
{
if (empty($paymentInfo)) {
$this->log("error", "Fail send second receipt paymentInfo is null: " . print_r($paymentInfo, true));
return false;
}
if ($paymentInfo->getStatus() !== PaymentStatus::SUCCEEDED) {
$this->log("error", "Fail send second receipt payment have incorrect status: " . $paymentInfo->getStatus());
return false;
}
return true;
}
/**
* @param $orderInfo
* @return ReceiptCustomer
*/
private function getReceiptCustomer($orderInfo)
{
$customerData = array();
if (!empty($orderInfo['user_email'])) {
$customerData['email'] = $orderInfo['user_email'];
}
if (!empty($orderInfo['user_phone'])) {
$customerData['phone'] = $orderInfo['user_phone'];
}
return new ReceiptCustomer($customerData);
}
/**
* @param $paymentId
* @return mixed|ReceiptResponseInterface
*/
private function getLastReceipt($paymentId)
{
try {
$receipts = $this->client->getReceipts(array(
'payment_id' => $paymentId,
))->getItems();
} catch (\Exception $e) {
$this->log("error", "Fail get receipt message: " . $e->getMessage());
}
return array_pop($receipts);
}
/**
* @param ReceiptResponseItemInterface[] $items
*
* @return array
*/
private function getResendItems($items)
{
$resendItems = array(
'items' => array(),
'amount' => 0,
);
foreach ($items as $item) {
if ($item->getPaymentMode() === PaymentMode::FULL_PREPAYMENT) {
$item->setPaymentMode(PaymentMode::FULL_PAYMENT);
$resendItems['items'][] = new ReceiptItem($item->jsonSerialize());
$resendItems['amount'] += $item->getAmount() / 100.0;
}
}
return $resendItems;
}
/**
* @param $level
* @param $message
*/
public function log($level, $message)
{
YooMoneyLogger::$level($message);
}
}