Для изучающих Ruby / Rails, будет полезно ознакомиться с подборкой бесплатных онлайн курсов, туториалов и интерактивных занятий, посвященных языку программирования Ruby и фреймворку Ruby on Rails.


User
<?php
/*
Абстрактный класс на проведение оплаты.
Его нельзя вызывать напрямую, чтобы исключить случаи инжекта оплаты.
Этот класс должен расширяться другим классом конкретной платежной системы,
чтобы использовать методы проверки платежа самой платежной системы
*/
abstract class modWebPaymentsCreateProcessor extends modObjectCreateProcessor{
public $classKey = 'Payment';
protected $BillingProcessorsPath;
public function checkPermissions() {
// Проверяем подпись платежной системы
$ok = $this->checkSignature();
if($ok !== true){
$this->error($ok);
return false;
}
return parent::checkPermissions();
}
public function initialize(){
$this->BillingProcessorsPath = MODX_CORE_PATH . 'components/billing/processors/';
$this->setDefaultProperties(array(
'currency_id' => $this->modx->getOption('shopmodx.default_currency'),
));
if(!$this->getProperty('paysystem_id')){
return $this->error("Не был получен ID платежной системы");
}
return parent::initialize();
}
public function beforeSet(){
$this->setProperties(array(
"createdby" => $this->modx->user->id ? $this->modx->user->id : null,
"date" => time(),
));
return parent::beforeSet();
}
public function beforeSave(){
if(
!$currency_id = (int)$this->getProperty('currency_id')
OR !$currency = $this->modx->getObject('modResource', $currency_id)
OR ! $currency instanceof ShopmodxResourceCurrency
){
return $this->error("Не был получен объект валюты");
}
if(
!$paysystem_id = (int)$this->getProperty('paysystem_id')
OR !$paysystem = $this->modx->getObject('Paysystem', $paysystem_id)
OR ! $paysystem instanceof Paysystem
){
return $this->error("Не был получен объект платежной системы");
}
// Проверяем, если указан счет платежной системы, то надо убедиться, что
// он еще не числится в биллинге
if($paysys_invoice_id = $this->object->get('paysys_invoice_id')){
if($this->modx->getCount($this->classKey, array(
'paysys_invoice_id' => $paysys_invoice_id,
'paysystem_id' => $paysystem_id,
))){
return $this->error("Данный счет уже создан в системе.");
}
}
$this->object->addOne($currency);
$this->object->addOne($paysystem);
return parent::beforeSave();
}
/*
Обязательно надо прописывать метод, в котором будет выполняться проверка
подписи с сервера платежной системы
*/
abstract protected function checkSignature();
protected function log($msg, $level = null){
if($level === null){
$level = xPDO::LOG_LEVEL_INFO;
}
$this->modx->log($level, "[Basket - ".__CLASS__."] {$msg}");
$this->modx->log($level, print_r($this->getProperties(), true));
return $msg;
}
protected function error($msg){
return $this->log($msg, xPDO::LOG_LEVEL_ERROR);
}
/*
Логируем все ошибки процессора, на всякий случай
*/
public function failure($msg = '',$object = null) {
$this->error($msg);
if(!empty($this->object) && is_object($this->object)){
$this->error(print_r($this->object->toArray(), true));
}
return parent::failure($msg,$object);
}
public function cleanup() {
/*
// Если оплата прошла успешно, то обновляем статус заказа
*/
if($order_id = $this->object->get('order_id')){
$this->modx->runProcessor('mgr/orders/status/pay', array(
'order_id' => $order_id,
), array(
'processors_path' => $this->BillingProcessorsPath,
));
// На всякий случай сбрасываем счетчик ошибок, если вдруг в вызываемом
// процессоре были ошибки
$this->modx->error->reset();
}
return $this->success($this->getSuccessMessage(), $this->object);
}
protected function getSuccessMessage(){
return '';
}
}
return 'modWebPaymentsCreateProcessor';
<?php
/*
Проводка платежа от робокассы
*/
require_once dirname(dirname(__FILE__)). '/create.class.php';
class modWebPaymentsRobokassaCreateProcessor extends modWebPaymentsCreateProcessor{
public function initialize(){
$this->setProperties(array(
"paysystem_id" => $this->modx->getOption('robokassa.bill_serv_id'),
));
return parent::initialize();
}
/*
Проверяем подпись с робокассы
*/
protected function checkSignature(){
$mrh_pass2 = $this->modx->getOption('robokassa.mrh_pass2');
// Параметры, передаваемые в запросе от робокассы
$crc = mb_strtoupper($this->getProperty('SignatureValue'));
$out_sum = $this->getProperty('OutSum');
$inv_id = $this->getProperty('InvId');
$shp_aid = $this->getProperty('shp_aid');
$shp_order = $this->getProperty('shp_order', null);
$shp_trff = $this->getProperty('shp_trff');
$shp_uid = $this->getProperty('shp_uid');
$my_crc = mb_strtoupper(md5("{$out_sum}:{$inv_id}:{$mrh_pass2}:shp_aid={$shp_aid}:shp_order={$shp_order}:shp_trff={$shp_trff}:shp_uid={$shp_uid}"));
$this->modx->log(xPDO::LOG_LEVEL_INFO, "[Robokassa - robokassa.payResult]", print_r($_REQUEST, true));
// проверка корректности подписи
if ($my_crc !=$crc){
$error = "[Robokassa - robokassa.payResult] - Неверная подпись. Получена: '{$crc}'. Должна быть: '{$my_crc}'";
$this->modx->log(xPDO::LOG_LEVEL_ERROR, $error);
return "bad sign";
}
// else
$this->setProperties(array(
"sum" => $out_sum,
"order_id" => $shp_order,
"owner" => $shp_uid,
"paysys_invoice_id" => $inv_id,
));
return true;
}
protected function getSuccessMessage(){
return 'OK'.$this->getProperty('InvId');
}
}