Skip to content

Instantly share code, notes, and snippets.

@ig0r74
Created December 12, 2025 15:34
Show Gist options
  • Select an option

  • Save ig0r74/128abdfce69d145370c04357742cf196 to your computer and use it in GitHub Desktop.

Select an option

Save ig0r74/128abdfce69d145370c04357742cf196 to your computer and use it in GitHub Desktop.
MODX CityAds postback
<?php
class cityAds
{
/** @var modX $modx */
public $modx;
/**
* @param modX $modx
* @param array $config
*/
function __construct(modX &$modx, array $config = [])
{
$this->modx =& $modx;
$corePath = MODX_CORE_PATH . 'components/cityads/';
$this->config = array_merge([
'corePath' => $corePath,
'modelPath' => $corePath . 'model/',
'campaignСode' => $this->modx->getOption('cityads_campaign_code'),
'postbackKey' => $this->modx->getOption('cityads_postback_key'),
'url' => $this->modx->getOption('admitad_url', null, 'https://postback.cityads.com/service/postback', true),
], $config);
}
/**
* Получение даты и времени оплаты
*/
public function postbackOrder(msOrder $order)
{
if (!$order) {
$this->modx->log(MODX_LOG_LEVEL_ERROR, '[cityads] error. $order not specified');
return;
}
$uid = $this->getCityAdsUid();
if (!$uid) {
$this->modx->log(MODX_LOG_LEVEL_ERROR, '[cityads] error. $uid not specified. Order id: ' . $order->get('id'));
}
$products = $order->getMany('Products');
$prepared = [];
// объединяем товары с одинаковым id
foreach ($products as $product) {
$productId = $product->get('product_id');
if (isset($prepared[$productId])) {
$prepared[$productId] = $prepared[$productId] + $product->get('count');
} else {
$prepared[$productId] = $product->get('count');
}
}
$basket = [];
foreach ($prepared as $id => $count) {
foreach ($products as $product) {
if ($product->get('product_id') == $id) {
$productCategory = '';
if ($msProduct = $product->getOne('Product')) {
if ($msCategoryMembers = $msProduct->getMany('Categories')) {
foreach ($msCategoryMembers as $cat) {
if ($msCategory = $cat->getOne('Category')) {
$productCategory = $msCategory->get('pagetitle');
break;
}
}
}
}
$basket[] = [
'pid' => $id,
'pn' => $product->get('name'),
'up' => $product->get('price'),
'pc' => $productCategory,
'qty' => $count,
];
}
}
}
$data = [
// 'postback_key' => $this->config['postbackKey'],
'order_id' => $order->get('id'),
'click_id' => $uid,
// 'customer_type' => 'new', // Обязателен при разделении выплат по типам пользователя. Стандартные значения: new — новый пользователь, returned — возвращённый пользователь
'order_total' => $order->get('cost') - $order->get('delivery_cost'),
'currency' => 'RUR',
// 'basket' => json_encode($basket, JSON_UNESCAPED_UNICODE),
'status' => 'new', // Допустимые значения: new – открытый лид, done – одобренный лид, cancel – отмененный лид. done и cancel – окончательные статусы, не могут быть изменены впоследствии
];
$url = $this->config['url'] . '?' . http_build_query($data) . '&basket=' . str_replace(' ', '+', json_encode($basket, JSON_UNESCAPED_UNICODE));
file_get_contents($url);
}
public function getCityAdsUid()
{
return isset($_COOKIE['_caid']) ? $_COOKIE['_caid'] : null;
}
}
<?php
switch($modx->event->name) {
case 'msOnCreateOrder':
if (!isset($_COOKIE['_a_last_paid_click'])) break;
if ($_COOKIE['_a_last_paid_click'] == 'cityads') {
$modx->loadClass('cityAds', MODX_CORE_PATH . 'components/cityads/model/', true, true);
$cityAds = new cityAds($modx, []);
if (!$cityAds) {
$modx->log(MODX_LOG_LEVEL_ERROR, 'Could not load cityAds class!');
}
$cityAds->postbackOrder($msOrder);
}
break;
}
return;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment