interface Type
{
const SMS = 1;
const EMAIL = 2;
public function sendSms() :bool;
public function sendEmail() :bool;
}
abstract class Base implements Type, Errorable
{
/**
* @var \Bitrix\Main\ErrorCollection
*/
protected $errorCollection;
protected $type;
/**
* Short Uri lifetime in database
* @var int
*/
const SHOT_URI_LIFE_TIME = 86000;
/**
* Return array of module names.
* @return array
*/
abstract protected function getDependencies():array;
public function __construct($type = self::SMS)
{
$this->type = $type;
$this->errorCollection = new ErrorCollection();
}
/**
* Checking errors.
* @return bool
*/
public function hasErrors()
{
return !empty($this->getErrors());
}
/**
* Getting array of errors.
* @return Error[]
*/
public function getErrors()
{
return $this->errorCollection->toArray();
}
/**
* Getting once error with the necessary code.
* @param string $code Code of error.
* @return Error
*/
public function getErrorByCode($code)
{
return $this->errorCollection->getErrorByCode($code);
}
/**
* Check moduled dependencies.
* @return void
* @throws \Bitrix\Main\LoaderException
*/
protected function checkDependencies()
{
foreach ($this->getDependencies() as $moduleName)
{
if (!Loader::includeModule($moduleName))
throw new \Bitrix\Main\LoaderException("Depended module {$moduleName} not included");
}
}
/**
* Deleting old short uri from database
*
* @return void
* @throws \Bitrix\Main\ObjectException
*/
public function deleteOldShortUri()
{
$time = time() - self::SHOT_URI_LIFE_TIME;
$time = \Bitrix\Main\Type\DateTime::createFromTimestamp($time);
$delIds = [];
$db = \CBXShortUri::GetList([], []);
while ($row = $db->Fetch())
{
if (new \Bitrix\Main\Type\DateTime($row['MODIFIED']) <= $time)
$delIds[] = $row['ID'];
}
foreach ($delIds as $id)
\CBXShortUri::Delete($id);
}
}
public function sendSms(): bool
{
$this->checkDependencies();
$this->deleteOldShortUri();
$this->fillOrdersNotPaid();
$this->processSendSms();
return true;
}
protected function getShotUri($link)
{
$domain = Core::SHOP_DOMAIN. '.site.ru';
return $domain . \CBXShortUri::GetShortUri($link);
}
protected function fillOrdersIdNotPaid()
{
try {
$date = new Main\Type\DateTime();
$date->add("-".self::MINUTES_SEND_EVENT." minutes");
/**
* @var ORM\Query\Query $query
* @var ORM\Objectify\Collection $collection
*/
$query = Sale\Internals\OrderTable::query();
$query->setSelect(['ID']);
$query
->where(Query::filter()
->logic(ORM\Query\Filter\ConditionTree::LOGIC_AND)
->where('DATE_INSERT', '<=', $date)
->where('DATE_INSERT', '>', new Main\Type\DateTime(self::ORDER_DATE_START, 'd.m.Y H:i:s'))
)
->where(Query::filter()
->logic(ORM\Query\Filter\ConditionTree::LOGIC_OR)
->whereNull(self::ORDER_PROP_SENDNOTIFY_CODE.'.VALUE')
->where(self::ORDER_PROP_SENDNOTIFY_CODE.'.VALUE', 'N')
)
->where('DATE_INSERT', '<=', $date)
->where('CANCELED', 'N')
->where('STATUS_ID', Order\OrderService::ORDER_STATUS_NEW)
->where('PAYMENT.PAY_SYSTEM.CODE', SiteCore\Core::ONLINE_PAYMENT_CODE)
->where('PAYMENT.PAID', 'N');
$query->registerRuntimeField(
new Main\Entity\ReferenceField(
self::ORDER_PROP_SENDNOTIFY_CODE,
Sale\Internals\OrderPropsValueTable::class,
[
'=this.ID' => 'ref.ORDER_ID',
'ref.CODE' => new Main\DB\SqlExpression('?', self::ORDER_PROP_SENDNOTIFY_CODE)
]
)
);
$collection = $query->fetchCollection();
foreach ($collection as $item) {
$this->ordersId[] = $item->getId();
}
}
catch (\Exception|\Error $e) {
$this->errorCollection->setError(new Main\Error($e->getMessage()), $e->getCode());
}
}
array (
'USER_PHONE' => $phone,
'ORDER_NUMBER' => $order->getField('ACCOUNT_NUMBER'),
'ORDER_SUM' => $order->getPrice(),
'PAYMENT_LINK' => $this->getShotUri($paymentLink)
)
protected function fillOrdersNotPaid()
{
$this->fillOrdersIdNotPaid();
foreach ($this->ordersId as $orderId) {
try {
$order = \Bitrix\Sale\Order::load($orderId);
$propertyCollection = $order->getPropertyCollection();
$paymentCollection = $order->getPaymentCollection();
if ($phone = $propertyCollection->getPhone()) {
$phone = SiteCore\Tools\DataAlteration::clearPhone($phone->getValue());
} else {
continue;
}
$payment = $paymentCollection[0];
$service = Sale\PaySystem\Manager::getObjectById($payment->getPaymentSystemId());
$initResult = $service->initiatePay($payment, null, Sale\PaySystem\BaseServiceHandler::STRING);
$invoiceId = $initResult->getPsData()['PS_INVOICE_ID'];
$paymentLink = str_replace('#INVOICE_ID#', $invoiceId, self::PAY_LINK);
if ($phone && $paymentLink)
{
$this->orders[$order->getId()] = $order;
$this->arNotifications[$order->getId()] = [
'USER_PHONE' => $phone,
'ORDER_NUMBER' => $order->getField('ACCOUNT_NUMBER'),
'ORDER_SUM' => $order->getPrice(),
'PAYMENT_LINK' => $this->getShotUri($paymentLink)
];
}
}
catch (\Exception|\Error $e) {
$this->errorCollection->setError(new Main\Error($e->getMessage()), $e->getCode());
}
}
}
protected function processSendSms()
{
if ($this->arNotifications)
{
foreach ($this->arNotifications as $orderId => $notifyData)
{
$propertyCollection = $this->orders[$orderId]->getPropertyCollection();
$propItem = $propertyCollection->getItemByOrderPropertyCode(self::ORDER_PROP_SENDNOTIFY_CODE);
if ($propItem === null)
{
$error = new Main\Error('Order property '.self::ORDER_PROP_SENDNOTIFY_CODE. ' not found');
$this->errorCollection->setError($error);
continue;
}
$event = new \Bitrix\Main\Sms\Event(self::SMS_EVENT_TYPE, $notifyData);
$res = $event->send(true);
if (!$res->isSuccess()) {
foreach ($res->getErrorCollection() as $error)
$this->errorCollection->setError($error);
$errorMessages = $res->getErrorMessages();
$strErrorMessages = implode("<br>", $errorMessages);
\CEventLog::Log(
"SECURITY",
"SMS_SEND_ERROR",
"main",
'',
implode('<br>', [$notifyData['USER_PHONE'], 'notpaidSms', $strErrorMessages])
);
}
else
{
$propItem->setValue('Y');
$res = $this->orders[$orderId]->save();
if (!$res->isSuccess())
{
foreach ($res->getErrorCollection() as $error)
$this->errorCollection->setError($error);
}
}
}
}
}
<?php
set_time_limit(0);
define("NO_KEEP_STATISTIC", true);
define("NOT_CHECK_PERMISSIONS", true);
$_SERVER["DOCUMENT_ROOT"] = str_replace('/local/cron', '',__DIR__);
if (php_sapi_name() !== 'cli')
{
header('HTTP/1.1 403 Forbidden');
die();
}
require_once($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
use O2k\SiteCore\Services\Order\Notification;
/**
* Module o2k.sitecore included in init.php
*/
$notify = new Notification\NotPaid();
$notify->sendSms();
if ($notify->hasErrors())
{
foreach ($notify->getErrors() as $error)
echo $error->getMessage() .PHP_EOL;
}