Что-то не то с формированием заказа через API

Доброе утро!
Вчера весь вечер провозился и так и не понял что не так: есть сниппет, который по стандартной Безумкинской схеме отрабатывает аякс-запросы, один из экшенов принимает данные о товарах, программно формирует заказ и создаёт его, но проблема в том, что не смотря на параметр json_response=true,во время выполнения
$miniShop2->order->submit()
ответ не отдаётся вообще и код после этого вызова не выполняется, а по аяксу пользователю отправляется простыня с хтмл-текстом страницы, вместо json с ответом. Вот кусок кода с этим функционалом:
case 'submit':
    try {
	$data = $_POST['data'];
	$profile = $modx->user->getOne('Profile');
	$scriptProperties = array(
            'json_response' => true, // возвращать ответы в JSON
        );
	$miniShop2 = $modx->getService('miniShop2');
        $miniShop2->initialize($modx->context->key,$scriptProperties);
        $miniShop2->order->clean();
        $miniShop2->order->add('user_id', $modx->user->id);
        $miniShop2->order->add('delivery', 10);
        $miniShop2->order->add('payment', 20);
        $miniShop2->order->add('email', $profile->get('email'));
        $miniShop2->order->add('phone', $profile->get('phone'));
        $miniShop2->order->add('receiver', $profile->get('fullname'));
        $miniShop2->order->add('comment', $data['comment']);
        
        $oldcart = $miniShop2->cart->get();
        $miniShop2->cart->clean();
        foreach($data['items'] as $item) {
            $miniShop2->cart->add($item['id'],$item['count']);
        }
        $res = $miniShop2->order->submit(); //в $res ничего не попадает, и код после этой строки не выполняется
        //вместо этого по аяксу пользователю улетает хтмл текущей страницы.
    	$miniShop2->cart->set($oldcart);
  } catch (Exception $e) {
       $res = 'error! ' . print_r($e);
  }
  break;
В чём косяк может быть? Вроде судя по докам так всё должно работать. Может именно из-за аякса что-то не то?
Сам заказ формируется и сохраняется нормально, если что.
Антон
13 марта 2019, 08:36
modx.pro
1
2 200
0
Поблагодарить автора Отправить деньги

Комментарии: 19

Vlad Brise
13 марта 2019, 12:06
1
0
Добрый день, попробуйте создать заказ через процессор, я например так и делаю по аяксу.
Пример рабочего процессора:
class orderCreate extends modProcessor

{
  public $name;
  public $phone;
  public $street;
  public $building;
  public $room;
  public $city;
  public $email;
  public $user_id;
  public $cost;
  public $createdon;
  public $object;
  public $order;
  /* @var pdoTools $pdo */
  protected $pdo;
  protected $toEmail;
  protected $prod_id;
  protected $ms2;
  protected $alias_id;
  
  public function initialize()
  {
    $this->pdo = $this->modx->getService('pdoTools');
    $this->ms2 = $this->modx->getService('miniShop2');
    $this->createdon = date('Y-m-d H:i:s');
    $this->name = trim(htmlspecialchars($_POST['name']));
    $this->phone = trim(htmlspecialchars($_POST['phone']));
    $this->email = trim(htmlspecialchars($_POST['email']));
    $this->city = trim(htmlspecialchars($_POST['city']));
    $this->street = trim(htmlspecialchars($_POST['street']));
    $this->building = trim(htmlspecialchars($_POST['building']));
    $this->room = trim(htmlspecialchars($_POST['room']));
    $this->prod_id = (int)trim(htmlspecialchars($_POST['id']));
    if (!$this->object = $this->modx->getObject('modResource', $this->prod_id)){
      return $this->failure('Такого товара не существует');
    }

    

    return parent::initialize();
  }
  public function process()
  {
    
    $create = $this->createOrder();
    if ($create != true) {
      return $this->failure($create);
    }
    return $this->success('Заказ успешно создан');
  }
  public function createOrder()
  {
    $order = $this->modx->newObject('msOrder');
    $order->fromArray([
      'num' => $this->getNum(),
      'user_id' => $this->getCustomerId(),
      'createdon' => $this->createdon,
      'delivery' => 1,
      'payment' => 1,
      'email' => $this->email,
      'cart_cost' => $this->object->get('price'),
      'cost' => $this->object->get('price'),
      'status' => 1,
      'context' => 'web'
    ]);
    
    $this->beforeSave($order);
    if (!$order->save()) {
      return 'Ошибка создания заказа';
    }
    $this->ms2->changeOrderStatus($order->get('id'), 1);

    
    return true;

  }

  public function getCustomerId()
  {


    if ($this->modx->user->isAuthenticated()) {
      $profile = $this->modx->user->Profile;
      if (!$profile->get('email')) {
        $profile->set('email', $this->email);
        $profile->save();
      }
      $uid = $this->modx->user->id;
    } else {
      if ($user = $this->modx->getObject('modUser', array('username' => $this->email))) {
        $uid = $user->get('id');
      } elseif ($profile = $this->modx->getObject('modUserProfile', array('email' => $this->email))) {
        $uid = $profile->get('internalKey');
      } else {
        /** @var modUser $user */
        $user = $this->modx->newObject('modUser', array('username' => $this->email, 'password' => md5(rand())));
        $profile = $this->modx->newObject('modUserProfile', array(
          'email' => $this->email,
          'fullname' => $this->name,
        ));
        $user->addOne($profile);
        /** @var modUserSetting $setting */
        $setting = $this->modx->newObject('modUserSetting');
        $setting->fromArray(array(
          'key' => 'cultureKey',
          'area' => 'language',
          'value' => $this->modx->getOption('cultureKey', null, 'en', true)
        ),'', true);
        $user->addMany($setting);
        $user->save();

        if ($groups = $this->modx->getOption('ms2_order_user_groups', null, false)) {
          $groups = array_map('trim', explode(',', $groups));
          foreach ($groups as $group) {
            $user->joinGroup($group);
          }
        }
        $uid = $user->get('id');
      }
    }

    return $uid;
  }


  public function beforeSave(msOrder $order){
    $addressArray = [
      'receiver' => $this->name,
      'phone' => $this->phone,
      'email' => $this->email,
      'city' => $this->city,
      'street' => $this->street,
      'building' => $this->building,
      'room' => $this->room
    ];
    /** @var msOrderAddress $address */
    $address = $this->modx->newObject('msOrderAddress');
    $address->fromArray(array_merge($addressArray, [
      'user_id' => $this->getCustomerId(),
      'createdon' => $this->createdon,
    ]));
    $productArr = [];

    $product = $this->modx->newObject('msOrderProduct');


    $product->fromArray([
      'product_id' => $this->prod_id,
      'cost' => $this->object->get('price'),
      'price' => $this->object->get('price'),
      'name' => $this->object->get('pagetitle'),
    ]);

    $productArr[] = $product;

    $order->addOne($address);
    $order->addMany($productArr);
  }
  
    /**
     * Return current number of order
     *
     * @return string
     */
    public function getNum()
    {
        $cur = date('ym');
        $num = 0;

        $c = $this->modx->newQuery('msOrder');
        $c->where(array('num:LIKE' => "{$cur}%"));
        $c->select('num');
        $c->sortby('id', 'DESC');
        $c->limit(1);
        if ($c->prepare() && $c->stmt->execute()) {
            $num = $c->stmt->fetchColumn();
        }
        if (empty($num)) {
            $num = date('ym') . '/0';
        }
        $num = explode('/', $num);
        $num = $cur . '/' . ($num[1] + 1);

        return $num;
    }

}

return 'orderCreate';
Лично мне так удобнее, не знаю как остальным, но решение рабочее.
Мы просто используем методы минишоповского класса создания заказа, и будет все точно так же как и при стандартном оформлении, даже сообщение пользователю придет.
    Антон
    13 марта 2019, 12:26
    0
    Ох, вот это радикальненько. А не будет проблем с правами пользователей? Это же из сниппета на пользовательской странице вызываться будет.
    И всё равно хочется разобраться, почему не работает json_response. Призываю богов минишопа! @Василий Наумкин, @Володя, почему стандартный
    $miniShop2->order->submit()
    отдаёт хтмл вместо json, как описано в топике?
      Vlad Brise
      13 марта 2019, 12:40
      0
      Не будет, там метод создания пользователя минишопа, которому даются стандартные права user-member
        Александр
        08 марта 2023, 15:17
        0
        вот спустя почти 4 года проблема с
        $miniShop2->order->submit()
        осталась.
        Удалось кому-то решить?
          Константин Ильин
          08 марта 2023, 15:55
          0
          У меня так вызывается
          $scriptProperties = [
               'json_response' => 1,
          ];
          /* возможно эта строчка поможет */
          $miniShop2 = $modx->getService('minishop2','miniShop2', MODX_CORE_PATH . 'components/minishop2/model/minishop2/', $scriptProperties);
          
          $miniShop2->initialize($modx->context->key, $scriptProperties);
          $miniShop2->order->clean();
          $miniShop2->cart->clean();
          $miniShop2->cart->add($dataForm['id'],($dataForm["count"] ?: 1),$option);
          /* ... */
          $resp['r'] = json_decode($miniShop2->order->submit(),1);
            Александр
            08 марта 2023, 16:03
            0
            Действительно
            $scriptProperties = ['json_response' => 1];
            помогает, но в таком случае ответ приходит в виде html с содержимым {«data»: {«msorder»:15}} и полностью игнорирует построение ответа.
            Вот пример:
            if (isset($response['success']) && $response['success'] == true) {
                        $result['post'] = $this->properties;
                        $result['response'] = $response;
                        $result['orderId'] = $response['data']['msorder'];
                        $miniShop2->cart->clean();
                        return $this->success('', $result);
                    }
            и по идее, вывод должен быть таким только с наполненной data[]:
            {
                "success": true,
                "message": "",
                "object": {
                    "post": {
                        "payment": "1",
                        "delivery": "1",
                        "name": "Алекс",
                        "email": "test@test.ru"
                    },
                    "response": {
                        "success": true,
                        "message": "",
                        "data": []
                    },
                    "orderId": null
                },
                "code": 200
            }
            а выведет при включенном json_response вот так:
            {"success":true,"message":"","data":{"msorder":53}}
            Причем в html формате.

            Никак не могу решить данную проблему
              Константин Ильин
              08 марта 2023, 16:44
              0
              видимо у меня так же, т.е. нужно самостоятельно получить заказ, т.к. далее у меня такой код:

              $resp['r'] = $arr = json_decode($miniShop2->order->submit(),1);
              if($arr['success'] && $arr["data"]["msorder"] > 0){
                  $msOrder = $modx->getObject('msOrder', $arr["data"]["msorder"]);
                  $order = $msOrder->toArray();
                  $resp['out'] = $pdo->parseChunk('@FILE cart/fastOrderSuccess.tpl',$arr);
              }
                Константин Ильин
                08 марта 2023, 16:54
                0
                не только 'json_response' => 1, а getService тоже смотрите параметры передаю
                  Александр
                  08 марта 2023, 17:57
                  0
                  Не помогло, к сожалению.
                  Повторил ваше получение заказа и все равно тот же вывод
                  {"success":true,"message":"","data":{"msorder":56}}
                  в виде html с игнорированием вообще каких-либо конструкций вывода информации. Что само по себе очень странно.
                  Даже нет ошибки из-за отсутствия такого чанка как у вас (специально решил не менять, чтобы вызвать ошибку)
                    Константин Ильин
                    08 марта 2023, 18:11
                    0
                    код весь покажите тогда

                    там еще $pdo->… выше получаю:
                    $pdo = $modx->getService('pdoTools');
                      Александр
                      08 марта 2023, 18:20
                      0
                      <?php
                      
                      class shopOrder2 extends shopBaseRestController
                      {
                          public $allowedMethods = array('post');
                      
                          public function post()
                          {
                              
                              // инициализируем miniShop2
                                  $scriptProperties = [
                                      'json_response' => 1,
                                  ];
                              	
                              	$miniShop2 = $this->modx->getService('minishop2','miniShop2', MODX_CORE_PATH . 'components/minishop2/model/minishop2/', $scriptProperties);
                              	
                              	// опции товара, если они необходимы
                              	$option = array();
                              	/*$option = array(
                              	  "option1" => "value1",
                              	  "option2" => "value2",
                              	);*/
                              	// инициализируем miniShop2 в текущем контексте
                              	$miniShop2->initialize($this->modx->context->key, $scriptProperties);
                              
                              $cart = $miniShop2->cart->get();
                      
                              if (!count($cart)) {
                                  $result = [
                                      'message' => 'Корзина пуста',
                                      'success' => false
                                  ];
                                  return $this->failure('', $result);
                              }
                      
                              //Получатель
                              $email = $this->getProperty('email');
                              $phone = $this->getProperty('phone');
                              $receiver = $this->getProperty('name');
                      
                              //Дата и время доставки
                              //$soon = (bool)$this->getProperty('soon');
                              $delivery_date = $this->getProperty('delivery_date');
                              $delivery_time = $this->getProperty('delivery_time');
                      
                              //Адрес
                              $street = $this->getProperty('street');
                              $building = $this->getProperty('building');
                              $room = $this->getProperty('apartment');
                              $entrance = $this->getProperty('entrance');
                              $floor = $this->getProperty('floor');
                      
                              $comment = $this->getProperty('comment');
                      
                              //Доставка и оплата
                              $payment = (int)$this->getProperty('payment');
                              $delivery = (int)$this->getProperty('delivery');
                      
                              $miniShop2->order->add('payment', $payment);
                              $miniShop2->order->add('delivery', $delivery);
                      
                              $miniShop2->order->add('receiver', $receiver);
                              $miniShop2->order->add('email', $email);
                              $miniShop2->order->add('phone', $phone);
                      
                              $miniShop2->order->add('soon', $soon);
                              $miniShop2->order->add('delivery_date', $delivery_date);
                              $miniShop2->order->add('delivery_time', $delivery_time);
                      
                              $miniShop2->order->add('street', $street);
                              $miniShop2->order->add('building', $building);
                              $miniShop2->order->add('room', $room);
                              $miniShop2->order->add('entrance', $entrance);
                              $miniShop2->order->add('floor', $floor);
                              $miniShop2->order->add('comment', $comment);
                      
                              $result['r'] = json_decode($miniShop2->order->submit(),1);
                              
                              $result['r'] = $arr = json_decode($miniShop2->order->submit(),1);
                              if($arr['success'] && $arr["data"]["msorder"] > 0){
                                  $msOrder = $modx->getObject('msOrder', $arr["data"]["msorder"]);
                                  $order = $msOrder->toArray();
                                  $result['orderId'] = $order;
                                  $resp['out'] = $pdo->parseChunk('@FILE cart/fastOrderSuccess.tpl',$arr);
                              }
                              $result['orderId'] = $response['data']['msorder'];
                              
                              return $this->success('', $result);
                      
                          }
                      }
                        Константин Ильин
                        08 марта 2023, 18:41
                        0
                        у вас видимо какой-то отдельный компонент-класс и как вы его запускаете не совсем понятно, но пользуйтесь тогда для отладки, в разных участках кода
                        $this->modx->log(1, print_r($result,1));
                        Смотреть в Журнале ошибок в самом модх.
                        Начните с самого простого в самом начале функции post()
                        $this->modx->log(1, print_r('Это я class shopOrder2 запустился',1));
                        если у вас журнале вообще ничего не выводит и ошибки тоже(и ошибки в серверном логе тоже нет), то скорее всего ваш класс вообще не запускается и с ним не работает modx или вы его вообще не вызываете и т.п.
                          Александр
                          08 марта 2023, 18:49
                          0
                          все вызывается и работает (заказ то создается), если отключить json_response, то я получу ответ в том виде, который я отдаю, но без id новосозданного заказа.
                          Данный контроллер используется в api для построения фронта отдельно от modx
                          Константин Ильин
                          08 марта 2023, 19:04
                          0
                          Тут дальше только выяснять постепенно как я писал вам ранее, выводите в лог или как то логгируйте, что получаете и т.д. сам Пример(!) как у меня работает я дал, ну и в теории повторюсь вы получаете строку с заказом ее надо из json вытащить и получить заказ.

                          так же в вашем коде два раза вызывается $miniShop2->order->submit()

                          Так же вы не поменяли $modx на $this->modx
                          Адаптируйте мой код под ваш самостоятельно
                          Александр
                          08 марта 2023, 20:06
                          0
                          в итоге получилось.
                          Спасибо вам больше за помощь!
                          Константин Ильин
                          08 марта 2023, 20:16
                          0
                          Не за что! В чем была проблема?
                          Александр
                          08 марта 2023, 20:19
                          0
                          Как понял, в самом компоненте, в котором работал с контроллером.
                          Использовал свой код + ваши подсказки и код в другом контроллере от zoomx и все сработало.
                          Хотя до этого и там не работало.
      Артем
      18 октября 2019, 05:53
      0
      Та же самая проблема
        Антон
        18 октября 2019, 12:03
        0
        Я так и не сборолся. В итоге вручную создал объект заказа и привязал к нему всё нужное.
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        19