Roman

Roman

С нами с 21 августа 2017; Место в рейтинге пользователей: #124
Roman
24 июля 2020, 12:27
0
Но только вот почему это мешает продлить SSL сертификат?
Roman
21 марта 2020, 14:16
0
У Вас несколько опросов на странице?
Roman
03 февраля 2020, 20:03
0
В логах пусто. Адресата пробовал менять на gmail.com, в спаме в первую очередь проверял.
Roman
30 января 2020, 10:17
0
нужно чтобы было:
3.25, а не 03:25
Roman
20 января 2020, 12:53
0
Изваял маленький скрипт, вытаскивающий кол-во просмотров
if(!$videoid)
{
  $output = 'Введите ID видео';
  return $output;
}
$tpl = $modx->getOption('tpl', $scriptProperties, 'tpl.videoGallery.views');

  $Youtube_API_KEY = $modx->getOption('videogallery_youtube_api_key');
    $json = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=statistics&id=" . $videoid . "&key=". $Youtube_API_KEY );
    $jsonData = json_decode($json);
    $views = $jsonData->items[0]->statistics->viewCount;

    $output = $modx->getChunk($tpl, array(
        'views' => $views
    ));    

    return  $output;
Мой первый скрипт. Возможно говнокод — но он работает XD.
UPD: хотелось бы увидеть в новой обнове videoGallery возможность подтягивать просмотры с видеороликов.
Roman
17 января 2020, 16:44
0
UDP: PT — не знаю что. 02M минуты 07S — сек. Не доперло изначально, думал что это за формат странный какой то XD.
{$videoDuration | replace : "PT" : "" | replace : "M" : ":" | replace : "S" : ""}
Roman
17 января 2020, 15:55
0
Приветствую! У меня в продолжительность ролика попадают данные вида: PT02M07S
Что это за формат?
Roman
08 января 2020, 21:15
0
А вот с innerJoin заработало! Спасибо большое за направление!
[[!msProducts?
    &parents=`3`
    &limit=`10`
    &showLog=`1`
    &tpl=`tpl.msProducts.row.single2`
      &innerJoin=`{
      "option1": {
        "class": "msProductOption",
        "on": "option1.key = 'Rating' AND option1.product_id = msProduct.id AND option1.value >= 3 AND option1.value < 5"
      }
      }`
    &includeThumbs=`medium`
]]
Roman
08 января 2020, 21:04
0
Попробовал c &optionFilter=`['Rating:>=' =>3, 'AND:Rating:<=' =>5]`
не выводит нужные товары.
<pre class="msProductsLog">0.0000501: pdoTools loaded.
0.0000918: Conditions prepared
0.0000219: xPDO query object created
0.0000811: leftJoined <i>msProductData</i> as <b>Data</b>
0.0000520: leftJoined <i>msVendor</i> as <b>Vendor</b>
0.0000451: leftJoined <i>msProductFile</i> as <b>medium</b>
0.0000010: Grouped by <b>msProduct.id, `medium`.url</b>
0.0000200: Added selection of <b>msProduct</b>: <small>`id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties`</small>
0.0000091: Added selection of <b>msProductData</b>: <small>`article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`</small>
0.0000081: Added selection of <b>msVendor</b>: <small>`name` AS `vendor.name`, `resource` AS `vendor.resource`, `country` AS `vendor.country`, `logo` AS `vendor.logo`, `address` AS `vendor.address`, `phone` AS `vendor.phone`, `fax` AS `vendor.fax`, `email` AS `vendor.email`, `description` AS `vendor.description`, `properties` AS `vendor.properties`</small>
0.0000041: Added selection of <b>msProductFile</b>: <small>url as `medium`</small>
0.0007470: Processed additional conditions
0.0008922: Added where condition: <b>class_key=msProduct, msProduct.parent:IN(3,860,861,867,874,878,880,881,882,888,893,897,903,906,910,920,926,960,1013,1018,1023,862,863,864,865,866,1172,1173,1174,868,869,870,871,872,873,875,876,877,879,883,884,885,886,887,1159,1160,1161,889,890,891,892,894,895,896,898,899,900,901,902,904,905,1162,907,908,909,911,912,913,914,915,916,917,918,919,1168,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1165,1170,1167,1163,1166,1164,1171,1169,1014,1015,1016,1017,1019,1020,1021,1022,1024,1025,1026,1027), msProduct.published=1, msProduct.deleted=0</b>
0.0000291: Sorted by <b>msProduct.id</b>, <b>ASC</b>
0.0000019: Limited to <b>10</b>, offset <b>0</b>
0.0001681: SQL prepared <small>"SELECT `msProduct`.`id`, `msProduct`.`type`, `msProduct`.`contentType`, `msProduct`.`pagetitle`, `msProduct`.`longtitle`, `msProduct`.`description`, `msProduct`.`alias`, `msProduct`.`alias_visible`, `msProduct`.`link_attributes`, `msProduct`.`published`, `msProduct`.`pub_date`, `msProduct`.`unpub_date`, `msProduct`.`parent`, `msProduct`.`isfolder`, `msProduct`.`introtext`, `msProduct`.`richtext`, `msProduct`.`template`, `msProduct`.`menuindex`, `msProduct`.`searchable`, `msProduct`.`cacheable`, `msProduct`.`createdby`, `msProduct`.`createdon`, `msProduct`.`editedby`, `msProduct`.`editedon`, `msProduct`.`deleted`, `msProduct`.`deletedon`, `msProduct`.`deletedby`, `msProduct`.`publishedon`, `msProduct`.`publishedby`, `msProduct`.`menutitle`, `msProduct`.`donthit`, `msProduct`.`privateweb`, `msProduct`.`privatemgr`, `msProduct`.`content_dispo`, `msProduct`.`hidemenu`, `msProduct`.`class_key`, `msProduct`.`context_key`, `msProduct`.`content_type`, `msProduct`.`uri`, `msProduct`.`uri_override`, `msProduct`.`hide_children_in_tree`, `msProduct`.`show_in_tree`, `msProduct`.`properties`, `Data`.`article`, `Data`.`price`, `Data`.`old_price`, `Data`.`weight`, `Data`.`image`, `Data`.`thumb`, `Data`.`vendor`, `Data`.`made_in`, `Data`.`new`, `Data`.`popular`, `Data`.`favorite`, `Data`.`tags`, `Data`.`color`, `Data`.`size`, `Data`.`source`, `Vendor`.`name` AS `vendor.name`, `Vendor`.`resource` AS `vendor.resource`, `Vendor`.`country` AS `vendor.country`, `Vendor`.`logo` AS `vendor.logo`, `Vendor`.`address` AS `vendor.address`, `Vendor`.`phone` AS `vendor.phone`, `Vendor`.`fax` AS `vendor.fax`, `Vendor`.`email` AS `vendor.email`, `Vendor`.`description` AS `vendor.description`, `Vendor`.`properties` AS `vendor.properties`, `medium`.url as `medium` FROM `qzJhWwMZkqLc_site_content` AS `msProduct` LEFT JOIN `qzJhWwMZkqLc_ms2_products` `Data` ON `msProduct`.`id` =  `Data`.`id` LEFT JOIN `qzJhWwMZkqLc_ms2_vendors` `Vendor` ON Data.vendor=Vendor.id LEFT JOIN `qzJhWwMZkqLc_ms2_product_files` `medium` ON `medium`.product_id = msProduct.id AND `medium`.rank = 0 AND `medium`.path LIKE '%/medium/%' WHERE  ( `msProduct`.`class_key` = 'msProduct' AND `msProduct`.`parent` IN (3,860,861,867,874,878,880,881,882,888,893,897,903,906,910,920,926,960,1013,1018,1023,862,863,864,865,866,1172,1173,1174,868,869,870,871,872,873,875,876,877,879,883,884,885,886,887,1159,1160,1161,889,890,891,892,894,895,896,898,899,900,901,902,904,905,1162,907,908,909,911,912,913,914,915,916,917,918,919,1168,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1165,1170,1167,1163,1166,1164,1171,1169,1014,1015,1016,1017,1019,1020,1021,1022,1024,1025,1026,1027) AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 )  GROUP BY msProduct.id, `medium`.url ORDER BY msProduct.id ASC LIMIT 10 "</small>
0.0023639: SQL executed
0.0000701: Rows fetched
0.0000999: Returning raw data
0.0004129: Checked the active modifiers
0.0010409: Loaded "modChunk" with name "tpl.msProducts.row.single2"
0.0010371: Retrieved data from cache "default/pdotools/modchunk/71"
0.0068295: Time to load products options
0.0294430: <b>Total time</b>
4 194 304: <b>Memory usage</b>
</pre>
Roman
07 января 2020, 21:00
0
Так тоже не работает.
[[!msProducts?
&parents=`3`
&limit=`10`
&tpl=`tpl.msProducts.row.single2`
&optionFilters=`{"Rating:>=":3,"Rating:<=":5}`
&includeThumbs=`medium`
&showLog=`1`
]]
Roman
07 января 2020, 20:51
0
Так отрабатывает:
[[!msProducts?
                                        &parents=`3`
                                        &limit=`10`
                                        &tpl=`tpl.msProducts.row.single2`
                                        &optionFilters=`{"Rating:>=":3}`
                                        &includeThumbs=`medium`
                                        &showLog=`1`
                                    ]]

Но условие не то
0.0000429: pdoTools loaded.
0.0000932: Conditions prepared
0.0000150: xPDO query object created
0.0000739: leftJoined <i>msProductData</i> as <b>Data</b>
0.0000539: leftJoined <i>msVendor</i> as <b>Vendor</b>
0.0000439: leftJoined <i>msProductFile</i> as <b>medium</b>
0.0000432: leftJoined <i>msProductOption</i> as <b>Rating</b>
0.0000010: Grouped by <b>msProduct.id, `medium`.url</b>
0.0000212: Added selection of <b>msProduct</b>: <small>`id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties`</small>
0.0000091: Added selection of <b>msProductData</b>: <small>`article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`</small>
0.0000079: Added selection of <b>msVendor</b>: <small>`name` AS `vendor.name`, `resource` AS `vendor.resource`, `country` AS `vendor.country`, `logo` AS `vendor.logo`, `address` AS `vendor.address`, `phone` AS `vendor.phone`, `fax` AS `vendor.fax`, `email` AS `vendor.email`, `description` AS `vendor.description`, `properties` AS `vendor.properties`</small>
0.0000050: Added selection of <b>msProductFile</b>: <small>url as `medium`</small>
0.0008221: Processed additional conditions
0.0009320: Added where condition: <b>class_key=msProduct, Rating.value:>==3, msProduct.parent:IN(3,860,861,867,874,878,880,881,882,888,893,897,903,906,910,920,926,960,1013,1018,1023,862,863,864,865,866,1172,1173,1174,868,869,870,871,872,873,875,876,877,879,883,884,885,886,887,1159,1160,1161,889,890,891,892,894,895,896,898,899,900,901,902,904,905,1162,907,908,909,911,912,913,914,915,916,917,918,919,1168,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1165,1170,1167,1163,1166,1164,1171,1169,1014,1015,1016,1017,1019,1020,1021,1022,1024,1025,1026,1027), msProduct.published=1, msProduct.deleted=0</b>
0.0000281: Sorted by <b>msProduct.id</b>, <b>ASC</b>
0.0000019: Limited to <b>10</b>, offset <b>0</b>
0.0001841: SQL prepared <small>"SELECT `msProduct`.`id`, `msProduct`.`type`, `msProduct`.`contentType`, `msProduct`.`pagetitle`, `msProduct`.`longtitle`, `msProduct`.`description`, `msProduct`.`alias`, `msProduct`.`alias_visible`, `msProduct`.`link_attributes`, `msProduct`.`published`, `msProduct`.`pub_date`, `msProduct`.`unpub_date`, `msProduct`.`parent`, `msProduct`.`isfolder`, `msProduct`.`introtext`, `msProduct`.`richtext`, `msProduct`.`template`, `msProduct`.`menuindex`, `msProduct`.`searchable`, `msProduct`.`cacheable`, `msProduct`.`createdby`, `msProduct`.`createdon`, `msProduct`.`editedby`, `msProduct`.`editedon`, `msProduct`.`deleted`, `msProduct`.`deletedon`, `msProduct`.`deletedby`, `msProduct`.`publishedon`, `msProduct`.`publishedby`, `msProduct`.`menutitle`, `msProduct`.`donthit`, `msProduct`.`privateweb`, `msProduct`.`privatemgr`, `msProduct`.`content_dispo`, `msProduct`.`hidemenu`, `msProduct`.`class_key`, `msProduct`.`context_key`, `msProduct`.`content_type`, `msProduct`.`uri`, `msProduct`.`uri_override`, `msProduct`.`hide_children_in_tree`, `msProduct`.`show_in_tree`, `msProduct`.`properties`, `Data`.`article`, `Data`.`price`, `Data`.`old_price`, `Data`.`weight`, `Data`.`image`, `Data`.`thumb`, `Data`.`vendor`, `Data`.`made_in`, `Data`.`new`, `Data`.`popular`, `Data`.`favorite`, `Data`.`tags`, `Data`.`color`, `Data`.`size`, `Data`.`source`, `Vendor`.`name` AS `vendor.name`, `Vendor`.`resource` AS `vendor.resource`, `Vendor`.`country` AS `vendor.country`, `Vendor`.`logo` AS `vendor.logo`, `Vendor`.`address` AS `vendor.address`, `Vendor`.`phone` AS `vendor.phone`, `Vendor`.`fax` AS `vendor.fax`, `Vendor`.`email` AS `vendor.email`, `Vendor`.`description` AS `vendor.description`, `Vendor`.`properties` AS `vendor.properties`, `medium`.url as `medium` FROM `qzJhWwMZkqLc_site_content` AS `msProduct` LEFT JOIN `qzJhWwMZkqLc_ms2_products` `Data` ON `msProduct`.`id` =  `Data`.`id` LEFT JOIN `qzJhWwMZkqLc_ms2_vendors` `Vendor` ON Data.vendor=Vendor.id LEFT JOIN `qzJhWwMZkqLc_ms2_product_files` `medium` ON `medium`.product_id = msProduct.id AND `medium`.rank = 0 AND `medium`.path LIKE '%/medium/%' LEFT JOIN `qzJhWwMZkqLc_ms2_product_options` `Rating` ON `Rating`.product_id = Data.id AND `Rating`.key = 'Rating' WHERE  ( `msProduct`.`class_key` = 'msProduct' AND `Rating`.`value` >= '3' AND `msProduct`.`parent` IN (3,860,861,867,874,878,880,881,882,888,893,897,903,906,910,920,926,960,1013,1018,1023,862,863,864,865,866,1172,1173,1174,868,869,870,871,872,873,875,876,877,879,883,884,885,886,887,1159,1160,1161,889,890,891,892,894,895,896,898,899,900,901,902,904,905,1162,907,908,909,911,912,913,914,915,916,917,918,919,1168,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1165,1170,1167,1163,1166,1164,1171,1169,1014,1015,1016,1017,1019,1020,1021,1022,1024,1025,1026,1027) AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 )  GROUP BY msProduct.id, `medium`.url ORDER BY msProduct.id ASC LIMIT 10 "</small>
0.0027151: SQL executed
0.0000300: Rows fetched
0.0000339: Returning raw data
0.0005920: Checked the active modifiers
0.0011730: Loaded "modChunk" with name "tpl.msProducts.row.single2"
0.0013311: Compiled Fenom chunk with name "modchunk/71"
0.0017719: Time to load products options
0.0099621: <b>Total time</b>
6 291 456: <b>Memory usage</b>
Roman
07 января 2020, 20:44
0
Rating — это опция, а не TV шка
Roman
07 января 2020, 20:38
0
0.0000441: pdoTools loaded.
0.0001481: Conditions prepared
0.0000229: xPDO query object created
0.0003591: Included list of tvs: <b></b>
0.0001049: leftJoined <i>msProductData</i> as <b>Data</b>
0.0000479: leftJoined <i>msVendor</i> as <b>Vendor</b>
0.0000448: leftJoined <i>msProductFile</i> as <b>medium</b>
0.0000019: Grouped by <b>msProduct.id, `medium`.url</b>
0.0000200: Added selection of <b>msProduct</b>: <small>`id`, `type`, `contentType`, `pagetitle`, `longtitle`, `description`, `alias`, `alias_visible`, `link_attributes`, `published`, `pub_date`, `unpub_date`, `parent`, `isfolder`, `introtext`, `richtext`, `template`, `menuindex`, `searchable`, `cacheable`, `createdby`, `createdon`, `editedby`, `editedon`, `deleted`, `deletedon`, `deletedby`, `publishedon`, `publishedby`, `menutitle`, `donthit`, `privateweb`, `privatemgr`, `content_dispo`, `hidemenu`, `class_key`, `context_key`, `content_type`, `uri`, `uri_override`, `hide_children_in_tree`, `show_in_tree`, `properties`</small>
0.0000088: Added selection of <b>msProductData</b>: <small>`article`, `price`, `old_price`, `weight`, `image`, `thumb`, `vendor`, `made_in`, `new`, `popular`, `favorite`, `tags`, `color`, `size`, `source`</small>
0.0000079: Added selection of <b>msVendor</b>: <small>`name` AS `vendor.name`, `resource` AS `vendor.resource`, `country` AS `vendor.country`, `logo` AS `vendor.logo`, `address` AS `vendor.address`, `phone` AS `vendor.phone`, `fax` AS `vendor.fax`, `email` AS `vendor.email`, `description` AS `vendor.description`, `properties` AS `vendor.properties`</small>
0.0000041: Added selection of <b>msProductFile</b>: <small>url as `medium`</small>
0.0007989: Processed additional conditions
0.0009210: Added where condition: <b>class_key=msProduct, Rating:>==3, AND:Rating:<==4, msProduct.parent:IN(3,860,861,867,874,878,880,881,882,888,893,897,903,906,910,920,926,960,1013,1018,1023,862,863,864,865,866,1172,1173,1174,868,869,870,871,872,873,875,876,877,879,883,884,885,886,887,1159,1160,1161,889,890,891,892,894,895,896,898,899,900,901,902,904,905,1162,907,908,909,911,912,913,914,915,916,917,918,919,1168,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1165,1170,1167,1163,1166,1164,1171,1169,1014,1015,1016,1017,1019,1020,1021,1022,1024,1025,1026,1027), msProduct.published=1, msProduct.deleted=0</b>
0.0000300: Sorted by <b>msProduct.id</b>, <b>ASC</b>
0.0000019: Limited to <b>10</b>, offset <b>0</b>
0.0001969: SQL prepared <small>"SELECT `msProduct`.`id`, `msProduct`.`type`, `msProduct`.`contentType`, `msProduct`.`pagetitle`, `msProduct`.`longtitle`, `msProduct`.`description`, `msProduct`.`alias`, `msProduct`.`alias_visible`, `msProduct`.`link_attributes`, `msProduct`.`published`, `msProduct`.`pub_date`, `msProduct`.`unpub_date`, `msProduct`.`parent`, `msProduct`.`isfolder`, `msProduct`.`introtext`, `msProduct`.`richtext`, `msProduct`.`template`, `msProduct`.`menuindex`, `msProduct`.`searchable`, `msProduct`.`cacheable`, `msProduct`.`createdby`, `msProduct`.`createdon`, `msProduct`.`editedby`, `msProduct`.`editedon`, `msProduct`.`deleted`, `msProduct`.`deletedon`, `msProduct`.`deletedby`, `msProduct`.`publishedon`, `msProduct`.`publishedby`, `msProduct`.`menutitle`, `msProduct`.`donthit`, `msProduct`.`privateweb`, `msProduct`.`privatemgr`, `msProduct`.`content_dispo`, `msProduct`.`hidemenu`, `msProduct`.`class_key`, `msProduct`.`context_key`, `msProduct`.`content_type`, `msProduct`.`uri`, `msProduct`.`uri_override`, `msProduct`.`hide_children_in_tree`, `msProduct`.`show_in_tree`, `msProduct`.`properties`, `Data`.`article`, `Data`.`price`, `Data`.`old_price`, `Data`.`weight`, `Data`.`image`, `Data`.`thumb`, `Data`.`vendor`, `Data`.`made_in`, `Data`.`new`, `Data`.`popular`, `Data`.`favorite`, `Data`.`tags`, `Data`.`color`, `Data`.`size`, `Data`.`source`, `Vendor`.`name` AS `vendor.name`, `Vendor`.`resource` AS `vendor.resource`, `Vendor`.`country` AS `vendor.country`, `Vendor`.`logo` AS `vendor.logo`, `Vendor`.`address` AS `vendor.address`, `Vendor`.`phone` AS `vendor.phone`, `Vendor`.`fax` AS `vendor.fax`, `Vendor`.`email` AS `vendor.email`, `Vendor`.`description` AS `vendor.description`, `Vendor`.`properties` AS `vendor.properties`, `medium`.url as `medium` FROM `qzJhWwMZkqLc_site_content` AS `msProduct` LEFT JOIN `qzJhWwMZkqLc_ms2_products` `Data` ON `msProduct`.`id` =  `Data`.`id` LEFT JOIN `qzJhWwMZkqLc_ms2_vendors` `Vendor` ON Data.vendor=Vendor.id LEFT JOIN `qzJhWwMZkqLc_ms2_product_files` `medium` ON `medium`.product_id = msProduct.id AND `medium`.rank = 0 AND `medium`.path LIKE '%/medium/%' WHERE  ( `msProduct`.`class_key` = 'msProduct' AND `msProduct`.`Rating` >= '3' AND `msProduct`.`Rating` <= '4' AND `msProduct`.`parent` IN (3,860,861,867,874,878,880,881,882,888,893,897,903,906,910,920,926,960,1013,1018,1023,862,863,864,865,866,1172,1173,1174,868,869,870,871,872,873,875,876,877,879,883,884,885,886,887,1159,1160,1161,889,890,891,892,894,895,896,898,899,900,901,902,904,905,1162,907,908,909,911,912,913,914,915,916,917,918,919,1168,921,922,923,924,925,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1165,1170,1167,1163,1166,1164,1171,1169,1014,1015,1016,1017,1019,1020,1021,1022,1024,1025,1026,1027) AND `msProduct`.`published` = 1 AND `msProduct`.`deleted` = 0 )  GROUP BY msProduct.id, `medium`.url ORDER BY msProduct.id ASC LIMIT 10 "</small>
0.0005741: Could not process query, error #1054: Unknown column 'msProduct.Rating' in 'where clause'
0.0026512: <b>Total time</b>
6 291 456: <b>Memory usage</b>
Roman
24 декабря 2019, 09:48
+1
Спасибо большое! Разобрался сам)) Нужно не полностью массив передавать, а передавать его через цикл
Да, я дергаю API стороннего сервиса, нужно сделать синхронизацию товаров и категорий.
P.S.
//Формируем массив
foreach ($items as $key => $item) {
$resourcedata[] = array(
        'class_key' => 'msCategory',
        'pagetitle' => $item['Id'],
        'parent' => 3,
        'template' => 3,
        'show_in_tree' => 1,
    );
}
//Скармливаем его runProcessor' у
for($i=0; $i<count($resourcedata); $i++){
$response = $modx->runProcessor('resource/create',$resourcedata[$i]);
  if($response->isError()){
        echo 'Ошибка';
    }else{
        echo 'Создал';
    }
}
Roman
06 декабря 2019, 09:51
0
А как же корзина в интернет-магазине? Как она реализована?
Roman
10 ноября 2019, 15:03
0
Спасибо! Выкрутился через параметр &tplFirst
Roman
11 октября 2019, 13:19
0
Хук YandexMoneyHook
<?php
$eventName = $modx->event->name;
$_isAdmin = ($modx->user->sudo == 1);

if (!defined('YANDEXMONEY_PATH')) {
    define('YANDEXMONEY_PATH', MODX_CORE_PATH."components/yandexmoney/");
}
require_once YANDEXMONEY_PATH.'model/yandexmoney.class.php';

$snippet = $modx->getObject('modSnippet',array('name' => 'YandexMoney'));
$config = $snippet->getProperties();

$ym = new Yandexmoney($modx, $config);

if (!empty($_SESSION['shk_lastOrder']) && !empty($_SESSION['shk_lastOrder']['id'])) {
    $ym->pay_method = !empty($_SESSION['shk_lastOrder']['payment']) ? $_SESSION['shk_lastOrder']['payment'] : '';
    $order_id = (int)$_SESSION['shk_lastOrder']['id'];
}
if (!empty($_POST['payment'])) $ym->pay_method = $_POST['payment'];
if (!empty($_POST['email'])) $ym->email = $_POST['email'];
if (!empty($_POST['phone'])) $ym->phone = $_POST['phone'];
if (!empty($_POST['alfaLogin'])) $ym->alfaLogin = $_POST['alfaLogin'];
if (!empty($_POST['qiwiPhone'])) $ym->qiwiPhone = $_POST['qiwiPhone'];

if (!$ym->checkPayMethod()) {
    return false;
}
$modx->addPackage('shopkeeper3',  $modx->getOption('core_path').'components/shopkeeper3/model/');
$order = $modx->getObject('shk_order', $order_id);

if (!$order) {
    return false;
}
$output = '';

if ($order_id && $_POST['order']) {
    $ym->userId = $modx->getLoginUserID('web') ? $modx->getLoginUserID('web') : 0;
    $ym->orderId = $order_id;
    $ym->orderTotal = $_SESSION['shk_lastOrder']['price'];
    $ym->orderTotal = floatval(str_replace(array(',',' '), array('.',''), $ym->orderTotal));
    $ym->comment = $_POST['message'];

    $_host = str_replace(array('http://', 'https://'), '' , $modx->config['site_url']);
    $host = 'https://' . $_host . 'assets/components/yandexmoney/connector_result.php';
    $ym->successUrl = $host.'?success=1';
    $ym->failUrl = $host.'?fail=1';

    echo $ym->createFormHtml();
    exit;
}
return true;
Roman
10 октября 2019, 16:49
0
Я делал все по гайду яндекса и у меня не заработала. Ниже привел правки в коде
Roman
10 октября 2019, 16:47
0
Конфиг:
MODX Revolution 2.7.1-pl
shopkeeper3 3.2.7-pl3
yandexmoney 1.0.4-pl
Вывожу через Formit.
[[!FormIt?
&hooks=`spam,shk_fihook,email,FormItAutoResponder,YandexMoneyHook,redirect`
&submitVar=`order-[[+id]]`
&emailTpl=`shopOrderReport`
&emailSubject=`В интернет-магазине [[++site_name]] сделан новый заказ`
&emailTo=`info@blabla.ru`
&emailFrom=`info@blabla.ru`

&fiarSubject=`Вы сделали заказ в интернет-магазине [[++site_name]]`
&fiarTpl=`shopOrderReport`
&fiarFromName=`[[++site_name]]`
&fiarFrom=`info@blabla.ru`
&fiarReplyTo=`[[++emailsender]]`
&fiarToField=`email`


&redirectTo=`357`
&validate=`agree:required,email:required,fullname:required,phone:required:regexp="^\+7\s\(\d{3}\)\s\d{3}\s\d{2}\s\d{2}$",course:required,g-recaptcha-response:required`
&errTpl=`<br /><span class="error">[[+error]]</span>`
]]
Сниппет: shk_fihook
<?php
/**
 * FormIt hook for Shopkeeper 3.x
 */

//ini_set('display_errors',1);
//error_reporting(E_ALL);

$output = false;

if(!defined('SHOPKEEPER_PATH')){
    define('SHOPKEEPER_PATH', MODX_CORE_PATH."components/shopkeeper3/");
}

//Определяем параметры сниппета Shopkeeper
$sys_property_sets = $modx->getOption( 'shk3.property_sets', $modx->config, 'default' );
$sys_property_sets = explode( ',', $sys_property_sets );
$propertySetName = trim( current( $sys_property_sets ) );

$snippet = $modx->getObject('modSnippet',array('name'=>'Shopkeeper3'));
$properties = $snippet->getProperties();
if( $propertySetName != 'default' && $modx->getCount( 'modPropertySet', array( 'name' => $propertySetName ) ) > 0 ){
    $propSet = $modx->getObject( 'modPropertySet', array( 'name' => $propertySetName ) );
    $propSetProperties = $propSet->getProperties();
    if(is_array($propSetProperties)) $properties = array_merge($properties,$propSetProperties);
}

$lang = $modx->getOption( 'lang', $properties, 'ru' );
$modx->getService( 'lexicon', 'modLexicon' );
$modx->lexicon->load( $lang . ':shopkeeper3:default' );

if( !empty( $_SESSION['shk_order'] ) ){
    
    require_once SHOPKEEPER_PATH . "model/shopkeeper.class.php";
    $shopCart = new Shopkeeper( $modx, $properties );
    
    $modx->addPackage( 'shopkeeper3', SHOPKEEPER_PATH . 'model/' );
    
    //shopkeeper settings
    $contacts_fields = array();
    $response = $modx->runProcessor('getsettings',
        array( 'settings' => array('contacts_fields') ),
        array( 'processors_path' => $modx->getOption( 'core_path' ) . 'components/shopkeeper3/processors/mgr/' )
    );
    if ($response->isError()) {
        echo $response->getMessage();
    }
    if($result = $response->getResponse()){
        
        $temp_arr = !empty( $result['object']['contacts_fields'] ) ? $result['object']['contacts_fields'] : array();
        if( !empty( $temp_arr ) ){
            
            foreach( $temp_arr as $opt ){
                
                $contacts_fields[$opt['name']] = $opt;
                
            }
            
        }
        
    }
    
    $userId = $modx->getLoginUserID( $modx->context->key );
    if( !$userId ) $userId = 0;
    
    //Контактные данные
    $contacts = array();
    $allFormFields = $hook->getValues();
    foreach( $allFormFields as $key => $val ){
        
        if( in_array( $key, array_keys( $contacts_fields ) ) ){
            
            $temp_arr = array(
                'name' => $contacts_fields[$key]['name'],
                'value' => $val,
                'label' => $contacts_fields[$key]['label']
            );
            
            array_push( $contacts, $temp_arr );
            
        }
        
    }
    
    $contacts = json_encode( $contacts );
    
    $emailField = $modx->getOption( 'fiarToField', $hook->config, 'email' );
    $phoneField = $modx->getOption( 'phoneField', $hook->config, 'phone' );
    $deliveryField = $modx->getOption( 'deliveryField', $hook->config, 'shk_delivery' );
    $paymentField = $modx->getOption( 'paymentField', $hook->config, 'payment' );
    
    //Доставка
    $delivery_price = !empty( $shopCart->delivery['price'] ) ? $shopCart->delivery['price'] : 0;
    $delivery_name = !empty( $shopCart->delivery['label'] ) ? $shopCart->delivery['label'] : '';
    if( !$delivery_name ){
	$delivery_name = !empty( $allFormFields[$deliveryField] ) ? $allFormFields[$deliveryField] : '';
    }
    
    //Сохраняем данные заказа
    $order = $modx->newObject('shk_order');
    $insert_data = array(
        'contacts' => $contacts,
        'options' => '',
        'price' => Shopkeeper::$price_total,
        'currency' => $shopCart->config['currency'],
        'date' => strftime('%Y-%m-%d %H:%M:%S'),
        'sentdate' => strftime('%Y-%m-%d %H:%M:%S'),
        'note' => '',
        'email' => isset( $allFormFields[$emailField] ) ? $allFormFields[$emailField] : '',
        'delivery' => $delivery_name,
        'delivery_price' => $delivery_price,
        'payment' => isset( $allFormFields[$paymentField] ) ? $allFormFields[$paymentField] : '',
        'tracking_num' => '',
        'phone' => isset( $allFormFields[$phoneField] ) ? $allFormFields[$phoneField] : '',
        'status' => $modx->getOption( 'shk3.first_status', null, '1' )
    );
    if( $userId ){
        $insert_data['userid'] = $userId;
    }
    $order->fromArray($insert_data);
    $saved = $order->save();
    
    //Сохраняем товары заказа
    if( $saved ){

        $purchasesData = $shopCart->getProductsData( true );

        foreach( $shopCart->data as $key => $p_data ){

            $options = !empty( $p_data['options'] ) ? json_encode( $p_data['options'] ) : '';
            $fields_data = !empty( $purchasesData[ $key ] ) ? $purchasesData[ $key ] : array();
            $fields_data['url'] = !empty( $p_data['url'] ) ? $p_data['url'] : '';
            unset( $fields_data['id'] );
            $fields_data_str = json_encode( $fields_data );

            $insert_data = array(
                'p_id' => $p_data['id'],
                'order_id' => $order->id,
                'name' => $p_data['name'],
                'price' => $p_data['price'],
                'count' => $p_data['count'],
                'class_name' => $p_data['className'],
                'package_name' => $p_data['packageName'],
                'data' => $fields_data_str,
                'options' => $options
            );

            $purchase = $modx->newObject('shk_purchases');
            $purchase->fromArray( $insert_data );
            $purchase->save();

        }

        $shopCart->setOrderDataSession( $order->toArray() );

    }
    
    $modx->invokeEvent( 'OnSHKChangeStatus', array( 'order_ids' => array( $order->id ), 'status' => $order->status ) );
    
    $orderOutputData = $shopCart->getOrderData( $order->id );
    
    //OnSHKsaveOrder
    $evtOut = $modx->invokeEvent('OnSHKsaveOrder',array('order_id' => $order->get('id')));
    if(is_array($evtOut)) $orderOutputData .= implode('',$evtOut);
    
    $hook->setValues(array(
        'orderID' => $order->get('id'),
        'orderDate' => $order->get('date'),
        'orderPrice' => $order->get('price'),
        'orderCurrency' => $shopCart->config['currency'],
        'orderOutputData' => $orderOutputData
    ));
    
    $shopCart->request_empty( false );
    
    $output = true;
    
}else{
    
    $hook->addError( 'error_message', $modx->lexicon('shk.order_empty') );
    $output = false;
    
}

return $output;
assets/components/yandexmoney/connector_result.php
<?php
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';

require_once MODX_CORE_PATH.'config/'.MODX_CONFIG_KEY.'.inc.php';
require_once MODX_CORE_PATH.'model/modx/modx.class.php';

$modx = new modX();
$modx->initialize('web');

$snippet = $modx->getObject('modSnippet', array('name' => 'YandexMoney'));
$config  = $snippet->getProperties();

if (!defined('YANDEXMONEY_PATH')) {
    define('YANDEXMONEY_PATH', MODX_CORE_PATH."components/yandexmoney/");
}

require_once YANDEXMONEY_PATH.'model/yandexmoney.class.php';

if (isset($_GET['fail']) && $_GET['fail'] == 1) {
    if ($res = $modx->getObject('modResource', $config['fail_page_id'])) {
        $modx->sendRedirect($modx->makeUrl($config['fail_page_id'], '', '', 'full'));
    }
    exit;
} elseif (isset($_GET['success']) && $_GET['success'] == 1) {
    if ($res = $modx->getObject('modResource', $config['success_page_id'])) {
        $modx->sendRedirect($modx->makeUrl($config['success_page_id'], '', '', 'full'));
    }
    exit;
} elseif (isset($_GET['return']) && $_GET['return'] == 1) {
    $orderId = isset($_GET['order_id']) ? (int)$_GET['order_id'] : 0;
    if ($orderId !== 0) {
        $modx->addPackage('shopkeeper3',  $modx->getOption('core_path').'components/shopkeeper3/model/');;
        $order = $modx->getObject('shk_order',array('id'=>$orderId));
        if ($order) {
            $sql  = 'SELECT payment_id FROM '.$modx->getTableName('YandexMoneyKassaPayment').' WHERE `order_id` = :orderId';
            $stmt = $modx->prepare($sql);
            $stmt->bindValue(':orderId', $orderId, \PDO::PARAM_INT);
            $stmt->execute();
            $dataSet = $stmt->fetch();
            $stmt->closeCursor();
            if (!empty($dataSet)) {
                $paymentId = $dataSet[0];
                $ym        = new Yandexmoney($modx, $config);
                $payment   = $ym->getPaymentById($paymentId);
                if ($payment !== null) {
                    if ($payment->getPaid()) {
                        if ($payment->getStatus() === \YandexCheckout\Model\PaymentStatus::WAITING_FOR_CAPTURE) {
                            $ym->capturePayment($payment, false);
                        }
                        $paymentInfo = $ym->getPaymentById($paymentId);
                        if ($paymentInfo->getStatus() == \YandexCheckout\Model\PaymentStatus::SUCCEEDED) {
                            $ym->updateOrderStatus($order, $config['ya_billing_status']);
                        }
                        if ($res = $modx->getObject('modResource', $config['success_page_id'])) {
                            $modx->sendRedirect($modx->makeUrl($config['success_page_id'], '', '', 'full'));
                        }
                        exit;
                    }
                }
            }
        }
    }
    if ($res = $modx->getObject('modResource', $config['fail_page_id'])) {
        $modx->sendRedirect($modx->makeUrl($config['fail_page_id'], '', '', 'full'));
    }
    exit;
} elseif (isset($_GET['notification']) && $_GET['notification'] == 1) {
    $source = file_get_contents('php://input');
    $ym     = new Yandexmoney($modx, $config);
    if (empty($source)) {
        $ym->log('notice', 'Call capture notification controller without body');
        header('HTTP/1.1 400 Empty notification object');

        return;
    }
    $ym->log('info', 'Notification body: '.$source);
    $json = json_decode($source, true);
    if (empty($json)) {
        if (json_last_error() === JSON_ERROR_NONE) {
            $message = 'empty object in body';
        } else {
            $message = 'invalid object in body: '.json_last_error_msg();
        }
        $ym->log('warning', 'Invalid parameters in capture notification controller - '.$message);
        header('HTTP/1.1 400 Invalid notification object');

        return;
    }
    try {
        if ($json['event'] == \YandexCheckout\Model\NotificationEventType::PAYMENT_WAITING_FOR_CAPTURE) {
            $object = new YandexCheckout\Model\Notification\NotificationWaitingForCapture($json);
            $ym->log('error', 'Notification waiting for capture init');
        } else {
            $object = new YandexCheckout\Model\Notification\NotificationSucceeded($json);
            $ym->log('error', 'Notification succeeded init');
        }
    } catch (\Exception $e) {
        $ym->log('error', 'Invalid notification object - '.$e->getMessage());
        header('HTTP/1.1 500 Server error: '.$e->getMessage());

        return;
    }
    $payment = $ym->getPaymentById($object->getObject()->getId());
    if ($payment === null) {
        $ym->log('error', 'Payment not found ');
        echo json_encode(array('success' => false, 'reason' => 'Payment not found'));
        exit();
    }
    $result = $ym->capturePayment($object->getObject());
    if (!$result) {
        header('HTTP/1.1 500 Server error 1');
        exit();
    }
    if ($result->getStatus() === \YandexCheckout\Model\PaymentStatus::SUCCEEDED) {
        try {
            $orderId = $object->getObject()->getMetadata()->offsetGet('order_id');
            $modx->addPackage('shopkeeper3',  $modx->getOption('core_path').'components/shopkeeper3/model/');
            $order = $modx->getObject('shk_order',array('id'=>$orderId));
            
            $res   = $ym->updateOrderStatus($order, $config['ya_billing_status']);
        } catch (Exception $e) {
            $ym->log('info', var_export($e, true));
        }
    } else {
        $ym->log('info', 'Failed');
    }

    echo json_encode(array('success' => ($result->getStatus() === \YandexCheckout\Model\PaymentStatus::SUCCEEDED)));
    exit();
}

$ym = new Yandexmoney($modx, $config);
$ym->ProcessResult();
Не помню, вносил ли правки но кину сюда же
core/components/yandexmoney/model/yandexmoney.class.php
<?php

/**
 * YandexMoney for MODX Revo
 *
 * Payment
 *
 * @author YandexMoney
 * @package yandexmoney
 * @version 2.0.0
 */

use YandexCheckout\Model\Payment;

require_once YANDEXMONEY_PATH.'lib/autoload.php';

$modx->addPackage('yandexmoney', YANDEXMONEY_PATH . 'model/');

class Yandexmoney
{
    /** @var int Оплата через yandex.деньги вообще не используется */
    const MODE_NONE = 0;

    /** @var int Оплата производится через Яндекс.Кассу */
    const MODE_KASSA = 1;

    /** @var int Оплата производится через Яндекс.Деньги */
    const MODE_MONEY = 2;

    /** @var int Оплата производится через Яндекс.Платёжку */
    const MODE_BILLING = 3;

    /** @var int Какой способ оплаты используется, одна из констант MODE_XXX */
    private $mode;

    private $paymode;

    public $email = false;
    public $phone = false;

    public $test_mode;
    public $org_mode;

    public $orderId;
    public $orderTotal;
    public $userId;

    public $successUrl;
    public $failUrl;

    public $reciver;
    public $formcomment;
    public $short_dest;
    public $writable_targets = 'false';
    public $comment_needed = 'true';
    public $label;
    public $quickpay_form = 'shop';
    public $payment_type = '';
    public $targets;
    public $sum;
    public $comment;
    public $need_fio = 'true';
    public $need_email = 'true';
    public $need_phone = 'true';
    public $need_address = 'true';

    public $shopid;
    public $account;
    public $password;

    public $method_ym;
    public $method_cards;
    public $method_cash;
    public $method_wm;
    public $method_ab;
    public $method_sb;
    public $method_installments;

    public $pay_method;

    public $alfaLogin;
    public $qiwiPhone;

    public $debug_log;

    /** @var string Идентификатор магазина в Яндекс.Платёжке */
    public $ya_billing_id;

    /** @var string Описание платежа, заданное из админки */
    public $ya_billing_purpose;

    /** @var string ФИО плательщика, переданное из запроса пользователя */
    public $ya_billing_fio;

    private $_apiClient;

    function __construct(modX &$modx, $config = array())
    {
        $this->mode = self::MODE_NONE;
        switch ($config['mode']) {
            case 1:
                $this->mode = self::MODE_MONEY;
                break;
            case 2:
            case 3:
                $this->mode = self::MODE_KASSA;
                break;
            case 4:
                $this->mode = self::MODE_BILLING;
                break;
        }

        $this->org_mode = ($config['mode'] == 2 || $config['mode'] == 3);
        $this->paymode = (bool) ($config['mode'] == 3);

        if (isset($config) && is_array($config)){
            foreach ($config as $k=>$v){
                if ($k != 'mode') {
                    $this->$k = $v;
                }
            }
        }
        $this->modx =& $modx;
        $this->config = $config;

        if (empty($this->debug_log)) {
            $this->debug_log = false;
        } else {
            $this->debug_log = true;
        }
    }

    public function getFormUrl()
    {
        if ($this->mode != self::MODE_BILLING) {
            $demo = ($this->test_mode) ? 'demo' : '';
            $mode = ($this->org_mode) ? '/eshop.xml' : '/quickpay/confirm.xml';
            return 'https://' . $demo . 'money.yandex.ru' . $mode;
        }
        return 'https://money.yandex.ru/fastpay/confirm';
    }

    public function checkPayMethod()
    {
        if ($this->mode == self::MODE_BILLING) {
            $fio = explode(' ', $_POST['ya-billing-fio']);
            if (count($fio) != 3) {
                return false;
            }
            foreach ($fio as $index => $value) {
                $value = trim($value);
                if (empty($value)) {
                    return false;
                }
                $fio[$index] = $value;
            }
            $this->ya_billing_fio = implode(' ', $fio);
            return true;
        }
        if ($this->mode == self::MODE_KASSA) {
            if (!$this->paymode) {
                if (in_array($this->pay_method, \YandexCheckout\Model\PaymentMethodType::getEnabledValues())) {
                    if ($this->pay_method === \YandexCheckout\Model\PaymentMethodType::QIWI) {
                        $phone = preg_replace('/[^\d]+/', '', $this->qiwiPhone);
                        if (empty($phone)) {
                            return false;
                        }
                        $this->qiwiPhone = $phone;
                    }
                    if ($this->pay_method === \YandexCheckout\Model\PaymentMethodType::ALFABANK) {
                        $login = trim($this->alfaLogin);
                        if (empty($login)) {
                            return false;
                        }
                        $this->alfaLogin = $login;
                    }
                }
            }
            return true;
        }
        return (in_array($this->pay_method, array('PC','AC','MC','GP','WM','AB','SB','MA','PB','QW', 'installments')) || $this->paymode);
    }

    public function getSelectHtml()
    {
        $result = json_encode(array('mode' => $this->mode));
        if ($this->mode == self::MODE_MONEY) {
            return "<option value=''>Яндекс.Касса (банковские карты, электронные деньги и другое)</option>";
        } elseif ($this->mode == self::MODE_KASSA) {
            if ($this->paymode) {
                return "<option value=''>Яндекс.Касса (банковские карты, электронные деньги и другое)</option>";
            }
            $translations = array(
                \YandexCheckout\Model\PaymentMethodType::ALFABANK => array('ab', 'Оплата через Альфа-Клик'),
                \YandexCheckout\Model\PaymentMethodType::MOBILE_BALANCE => array('ma', 'Платеж со счета мобильного телефона'),
                \YandexCheckout\Model\PaymentMethodType::CASH => array('cash', 'Оплата наличными через кассы и терминалы'),
                \YandexCheckout\Model\PaymentMethodType::WEBMONEY => array('wm', 'Оплата из кошелька в системе WebMoney'),
                \YandexCheckout\Model\PaymentMethodType::QIWI => array('qw', 'Оплата через QIWI Wallet'),
                \YandexCheckout\Model\PaymentMethodType::SBERBANK => array('sb', 'Оплата через Сбербанк: оплата по SMS или Сбербанк Онлайн'),
                \YandexCheckout\Model\PaymentMethodType::YANDEX_MONEY => array('ym', 'Оплата из кошелька в Яндекс.Деньгах'),
                \YandexCheckout\Model\PaymentMethodType::BANK_CARD => array('cards', 'Оплата с произвольной банковской карты'),
                \YandexCheckout\Model\PaymentMethodType::INSTALLMENTS => array('installments', 'Заплатить по частям'),
                \YandexCheckout\Model\PaymentMethodType::TINKOFF_BANK => array('tinkoff_bank', 'Интернет-банк Тинькофф'),
            );
            $list_methods = array();
            foreach (\YandexCheckout\Model\PaymentMethodType::getEnabledValues() as $paymentMethodCode) {
                $list_methods[$paymentMethodCode] = array(
                    'key'   => $translations[$paymentMethodCode][0],
                    'label' => $translations[$paymentMethodCode][1],
                );
            }
            $output = '';
            foreach ($list_methods as $long_name => $method_desc) {
                $key = $method_desc['key'];
                $by_default = (in_array($key, array('ym', 'cards'))) ? true : $this->org_mode;
                if ($this->{'method_' . $key} == 1 && $by_default) {
                    $output .= '<option value="' . $long_name . '"';
                    if ($this->pay_method == $long_name) {
                        $output .= ' selected ';
                    }
                    $output .= '>' . $method_desc['label'] . '</option>';
                }
            }
            return $output;
        } elseif ($this->mode == self::MODE_BILLING) {
            return "<option value='4'>Яндекс.Платежка (банковские карты, кошелек)</option>";
        }
        return $result;
    }

    public function createFormHtml()
    {
        global $modx;

        /** @var shk_order $order */
        $order = $modx->getObject('shk_order',array('id' => $this->orderId));

        if ($this->mode == self::MODE_KASSA) {
            $redirectUrl = 'https://' . str_replace(array('http://', 'https://'), '' , $modx->config['site_url'])
                . 'assets/components/yandexmoney/connector_result.php?return=1&order_id=' . $this->orderId;
            $payment = $this->createKassaPayment($order, $redirectUrl);
            if ($payment === null) {
                header('Location: ' . $root.'assets/components/yandexmoney/connector_result.php?fail=1');
                exit();
            }
        }

        $html = '';

        $site_url = $modx->config['site_url'];
        $payType = ($this->paymode) ? '' : $this->pay_method;
        $addInfo = ($this->email!==false)?'<input type="hidden" name="cps_email" value="'.$this->email.'" >':'';
        $addInfo .= ($this->phone!==false)?'<input type="hidden" name="cps_phone" value="'.$this->phone.'" >':'';
        $html .= '<form method="POST" action="'.$this->getFormUrl().'"  id="paymentform" name = "paymentform">';
        if ($this->mode == self::MODE_KASSA) {
            /** @var \YandexCheckout\Model\Confirmation\ConfirmationRedirect $confirmation */
            $confirmation = $payment->getConfirmation();
            if ($confirmation !== null && $confirmation->getType() === \YandexCheckout\Model\ConfirmationType::REDIRECT) {
                $redirectUrl = $confirmation->getConfirmationUrl();
            }
            $html = '<script> document.location = "' . $redirectUrl . '"; </script>';
        } elseif ($this->mode == self::MODE_MONEY) {
            $html .= '  <input type="hidden" name="receiver" value="'.$this->account.'">
                       <input type="hidden" name="formcomment" value="Order '.$this->orderId.'">
                       <input type="hidden" name="short-dest" value="Order '.$this->orderId.'">
                       <input type="hidden" name="writable-targets" value="'.$this->writable_targets.'">
                       <input type="hidden" name="comment-needed" value="'.$this->comment_needed.'">
                       <input type="hidden" name="label" value="'.$this->orderId.'">
                       <input type="hidden" name="quickpay-form" value="'.$this->quickpay_form.'">
                       <input type="hidden" name="paymentType" value="'.$this->pay_method.'">
                       <input type="hidden" name="targets" value="Заказ '.$this->orderId.'">
                       <input type="hidden" name="sum" value="'.$this->orderTotal.'" data-type="number" >
                       <input type="hidden" name="comment" value="'.$this->comment.'" >
                       <input type="hidden" name="need-fio" value="'.$this->need_fio.'">
                       <input type="hidden" name="need-email" value="'.$this->need_email.'" >
                       <input type="hidden" name="need-phone" value="'.$this->need_phone.'">
                       <input type="hidden" name="need-address" value="'.$this->need_address.'">
                        <input type="hidden" name="successUrl" value="'.$site_url.'assets/components/yandexmoney/connector_result.php?success=1">';
        } elseif ($this->mode == self::MODE_BILLING) {
            $narrative = $this->parsePlaceholders($this->ya_billing_purpose, $order);
            $html .= '<input type="hidden" name="formId" value="'.$this->ya_billing_id.'" />
                <input type="hidden" name="narrative" value="'.htmlspecialchars($narrative).'" />
                <input type="hidden" name="fio" value="'.htmlspecialchars($this->ya_billing_fio).'" />
                <input type="hidden" name="sum" value="'.$this->orderTotal.'" />
                <input type="hidden" name="quickPayVersion" value="2" />';
            $this->updateOrderStatus($order, $this->config['ya_billing_status']);
        }
        if ($this->mode !== self::MODE_KASSA) {
            $html .= '<input type="hidden" name="cms_name" value="modx" >
                </form>
                <script type="text/javascript">
                    document.getElementById("paymentform").submit();
                </script>';
        }

        echo $html;
        exit;
    }

    /**
     * @param shk_order $order
     * @param string $redirectUrl
     * @return \YandexCheckout\Model\PaymentInterface
     */
    private function createKassaPayment($order, $redirectUrl)
    {
        try {
            $builder = \YandexCheckout\Request\Payments\CreatePaymentRequest::builder();
            $builder->setClientIp($_SERVER['REMOTE_ADDR'])
                ->setAmount($this->orderTotal)
                ->setCapture(true)
                ->setDescription($this->createDescription($order))
                ->setMetadata(array(
                    'order_id' => $this->orderId,
                    'cms_name' => 'ya_api_modx_revolution',
                    'module_version' => '1.0.4',
                ));
            $confirmation = array(
                'type' => \YandexCheckout\Model\ConfirmationType::REDIRECT,
                'returnUrl' => $redirectUrl,
            );
            if (!$this->paymode) {
                if ($this->pay_method === \YandexCheckout\Model\PaymentMethodType::ALFABANK) {
                    $paymentMethod = array(
                        'type' => $this->pay_method,
                        'login' => $this->alfaLogin,
                    );
                    $confirmation = \YandexCheckout\Model\ConfirmationType::EXTERNAL;
                } elseif ($this->pay_method === \YandexCheckout\Model\PaymentMethodType::QIWI) {
                    $paymentMethod = array(
                        'type' => $this->pay_method,
                        'phone' => $this->qiwiPhone,
                    );
                } else {
                    $paymentMethod = $this->pay_method;
                }
                $builder->setPaymentMethodData($paymentMethod);
            }
            $builder->setConfirmation($confirmation);
            if (isset($this->config['ya_kassa_send_check']) && $this->config['ya_kassa_send_check']) {
                $this->addReceipt($builder, $order);
            }
            $request = $builder->build();
            if (isset($this->config['ya_kassa_send_check']) && $this->config['ya_kassa_send_check']) {
                $request->getReceipt()->normalize($request->getAmount());
            }
        } catch (\Exception $e) {
            $this->log('error', 'Failed to create request: ' . $e->getMessage());
            return null;
        }

        try {
            $response = $this->getClient()->createPayment($request);
        } catch (\Exception $e) {
            $this->log('error', 'Failed to create payment: ' . $e->getMessage());
            return null;
        }

        global $modx;

        /** @var YandexMoneyKassaPayment $record */
        $record = $modx->getObject('YandexMoneyKassaPayment', $this->orderId);
        $this->log('debug', 'Fetching payment from db: ' . ($record === null ? 'null' : $record->get('payment_id')));
        if ($record === null) {
            $this->log('debug', 'Create db payment');
            $record = $modx->newObject('YandexMoneyKassaPayment');
            $record->set('order_id', $this->orderId);
        }
        $record->set('payment_id', $response->getId());
        $record->save();

        return $response;
    }

    /**
     * @param string $paymentId
     * @return \YandexCheckout\Model\PaymentInterface|null
     */
    public function getPaymentById($paymentId)
    {
        try {
            $payment = $this->getClient()->getPaymentInfo($paymentId);
        } catch (Exception $e) {
            $this->log('error', 'Failed to find payment ' . $paymentId);
            $payment = null;
        }
        return $payment;
    }

    /**
     * @param \YandexCheckout\Model\PaymentInterface $payment
     * @param bool $fetch
     * @return \YandexCheckout\Model\PaymentInterface|null
     */
    public function capturePayment($payment, $fetch = true)
    {
        if ($fetch) {
            $payment = $this->getPaymentById($payment->getId());
            if ($payment === null) {
                return null;
            }
        }
        if ($payment->getStatus() === \YandexCheckout\Model\PaymentStatus::WAITING_FOR_CAPTURE) {
            try {
                $builder = \YandexCheckout\Request\Payments\Payment\CreateCaptureRequest::builder();
                $builder->setAmount($payment->getAmount());
                $request = $builder->build();
            } catch (Exception $e) {
                return null;
            }
            try {
                $response = $this->getClient()->capturePayment($request, $payment->getId());
            } catch (\Exception $e) {
                return null;
            }
        } else {
            $response = $payment;
        }
        return $response;
    }

    /**
     * @param \YandexCheckout\Request\Payments\CreatePaymentRequestBuilder $builder
     * @param shk_order $order
     */
    private function addReceipt($builder, $order)
    {
        $builder->setReceiptEmail($order->_fields['email']);

        $shippingMethod = null;
        $shippingPrice = 0;
        if ($content = unserialize($order->_fields['content'])) {
            foreach ($content as $item) {
                if ($item['price'] > 0) {
                    $builder->addReceiptItem($item['name'], $item['price'], $item['count'], $this->config['tax_id']);
                } elseif (isset($item['tv_add']['shk_delivery'])) {
                    $shippingMethod = $item['tv_add']['shk_delivery'];
                }
            }
        }

        if (!empty($shippingMethod)) {
            foreach (unserialize($order->_fields['addit']) as $items) {
                foreach ($items as $item) {
                    if (isset($item[0]) && $item[0] === $shippingMethod) {
                        $shippingPrice = $item[1];
                    }
                }
            }
        }

        if ($shippingMethod && $shippingPrice > 0) {
            $builder->addReceiptShipping($shippingMethod, $shippingPrice, $this->config['tax_id']);
        }
    }

    public function checkSign($callbackParams)
    {
        if ($this->org_mode) {
            $string = $callbackParams['action'].';'.$callbackParams['orderSumAmount'].';'.$callbackParams['orderSumCurrencyPaycash'].';'.$callbackParams['orderSumBankPaycash'].';'.$callbackParams['shopId'].';'.$callbackParams['invoiceId'].';'.$callbackParams['customerNumber'].';'.$this->password;
            $md5 = strtoupper(md5($string));
            return ($callbackParams['md5']==$md5);
        } else {
            $string = $callbackParams['notification_type'].'&'.$callbackParams['operation_id'].'&'.$callbackParams['amount'].'&'.$callbackParams['currency'].'&'.$callbackParams['datetime'].'&'.$callbackParams['sender'].'&'.$callbackParams['codepro'].'&'.$this->password.'&'.$callbackParams['label'];
            $check = (sha1($string) == $callbackParams['sha1_hash']);
            if (!$check){
                header('HTTP/1.0 401 Unauthorized');
                return false;
            }
            return true;
        }
    }

    public function sendCode($callbackParams, $code)
    {
        if (!$this->org_mode) {
            if ($code === 0) {
                header('HTTP/1.0 200 OK');
            } else {
                header('HTTP/1.0 401 Unauthorized');
            }
            return;
        }
        header("Content-type: text/xml; charset=utf-8");
        $xml = '<?xml version="1.0" encoding="UTF-8"?>
            <'.$callbackParams['action'].'Response performedDatetime="'.date("c").'" code="'.$code.'" invoiceId="'.$callbackParams['invoiceId'].'" shopId="'.$this->shopid.'"/>';
        echo $xml;
    }

    /* оплачивает заказ */
    public function ProcessResult()
    {
        $callbackParams = $_POST;
        if ($this->checkSign($callbackParams)) {
            $order_id = ($this->org_mode)? intval($callbackParams["orderNumber"]):intval($callbackParams["label"]);
            if ($order_id) {
                $this->modx->addPackage('shopkeeper3', MODX_CORE_PATH."components/shopkeeper3/model/");
                $order = $this->modx->getObject('shk_order',array('id'=>$order_id));
                $amount = number_format($order->get('price'),2,".",'');
                $pay_amount = number_format($callbackParams[($this->org_mode)?'orderSumAmount':'amount'], 2, '.', '');
                if ($pay_amount === $amount) {
                    if ($callbackParams['action'] == 'paymentAviso' || !$this->org_mode){
                        $order->set('status', 5);
                        $order->save();
                    }
                    $this->sendCode($callbackParams, 0);
                } else {
                    $this->sendCode($callbackParams, 100);
                }
            } else {
                $this->sendCode($callbackParams, 200);
            }
        } else {
            $this->sendCode($callbackParams, 1);
        }
    }

    /**
     * @return int
     */
    public function getMode()
    {
        return $this->mode;
    }

    /**
     * Преобразует шаблон назначения платежа в удобоваримую строку
     * @param string $template Шаблон назначения платежя
     * @param shk_order $order Информация о заказе
     * @return string Строка для отправки в Яндекс.Деньги
     */
    private function parsePlaceholders($template, shk_order $order)
    {
        $replace = array(
            '%order_id%' => $order->id,
        );
        foreach ($order->toArray() as $key => $value) {
            if (is_scalar($value)) {
                $replace['%' . $key . '%'] = $value;
            }
        }
        return strtr($template, $replace);
    }

    /**
     * Устанавливает новый статус исполнения заказа
     * @param shk_order $order Инстанс изменяемого заказа
     * @param string $status Новый статус заказа
     */
    public function updateOrderStatus(shk_order $order, $status)
    {

        if ($status > 0) {
            $order->set('status', $status);
            return $order->save();
        }
    }

    private function getClient()
    {
        if ($this->_apiClient === null) {
            $this->_apiClient = new \YandexCheckout\Client();
            $this->_apiClient->setAuth($this->shopid, $this->password);
            $this->_apiClient->setLogger($this);
        }
        return $this->_apiClient;
    }

    public function log($level, $message, $context = array())
    {
        if (!$this->debug_log) {
            return;
        }
        if (!empty($context) && (is_array($context) || $context instanceof Traversable)) {
            $search = array();
            $replace = array();
            foreach ($context as $key => $value) {
                $search[] = '{' . $key . '}';
                $replace[] = $value;
            }
            $message = str_replace($search, $replace, $message);
        }
        $path = YANDEXMONEY_PATH . '/logs';
        if (!file_exists($path)) {
            mkdir($path);
        }
        $fileName = $path . '/module.log';
        $fd = fopen($fileName, 'a');
        flock($fd, LOCK_EX);
        fwrite($fd, date(DATE_ATOM) . ' [' . $level . '] - ' . $message . PHP_EOL);
        flock($fd, LOCK_UN);
        fclose($fd);
    }

    /**
     * @param $order
     * @return string
     */
    private function createDescription($order)
    {
        $descriptionTemplate = !empty($this->config['description_template'])
            ? $this->config['description_template']
            : 'Оплата заказа №%id%';

        $replace  = array();
        $patterns = explode('%', $descriptionTemplate);
        foreach ($patterns as $pattern) {
            $value = $order->get($pattern);
            if (!is_null($value) && is_scalar($value)) {
                $replace['%'.$pattern.'%'] = $value;
            }
        }

        $description = strtr($descriptionTemplate, $replace);

        return (string)mb_substr($description, 0, Payment::MAX_LENGTH_DESCRIPTION);
    }
}