HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: /virtual/nagasaki/public_html/ec/app/Plugin/GmoEpsilon/Service/Client/GmoEpsilon_Base.php
<?php

namespace Plugin\GmoEpsilon\Service\Client;

use Guzzle\Service\Client;
use Guzzle\Http\Exception\BadResponseException;
use Plugin\GmoEpsilon\Util\PaymentUtil;
use Plugin\GmoEpsilon\Util\PluginUtil;
use Eccube\Entity\MailHistory;
use Guzzle\Http\Exception\RequestException;
use Guzzle\Http\Exception\CurlException;

/**
 * 決済モジュール 決済処理 基底クラス
 */
class GmoEpsilon_Base
{

    protected $app;
    protected $const;

    /**
     * コンストラクタ
     *
     * @return void
     */
    function __construct(\Eccube\Application $app)
    {
        $this->app = $app;
        $this->const = $app['config']['GmoEpsilon']['const'];
    }

    /**
     * 決済処理
     *
     * @param \Eccube\Entity\Order $Order
     * @param \Plugin\GmoEpsilon\Entity\Extension\PaymentExtension $PaymentExtension
     * @return render
     */
    function payProcess($Order, $PaymentExtension)
    {
        // リクエストパラメータをセット
        $arrParameter = $this->setParameter($Order, $PaymentExtension);

        // データ送信(POST)
        $objPlugin =& PluginUtil::getInstance($this->app);
        $destination_url = $objPlugin->getSubData('destination_url');
        $arrXML = $this->sendData($destination_url, $arrParameter);

        // エラーチェック
        $err_code = $this->getXMLValue($arrXML, 'RESULT', 'ERR_CODE');
        if (!empty($err_code)) {
            $this->app['monolog.gmoepsilon']->addInfo('request error. error_code = ' . $err_code);
            $error_title = 'システムエラーが発生しました。';
            $error_message = $this->getXMLValue($arrXML, 'RESULT', 'ERR_DETAIL');
            return $this->app['view']->render('error.twig', compact('error_title', 'error_message'));
        }

        // 受注番号をセット
        $this->app['session']->set('eccube.plugin.epsilon.orderId', $Order->getId());

        // Epsilonに遷移
        return $this->transitionEpsilon($arrXML);
    }

    /**
     * 決済完了処理
     *
     * @param \Eccube\Entity\Order $Order
     * @param array $response
     */
    function compProcess($Order, $response)
    {
        $cartService = $this->app['eccube.service.cart'];

        // チェックパラメータを取得
        $arrCheckParameter = $this->getCheckParameter();

        // パラメータをチェック
        if (!$this->checkParameter($response, $arrCheckParameter)) {
            $this->app['monolog.gmoepsilon']->addInfo('response error. get fraud GET.');
            $error_title = 'システムエラーが発生しました。';
            $error_message = '不正なGETリクエストを受信しました。';
            return $this->app['view']->render('error.twig', compact('error_title', 'error_message'));
        }

        // 受注情報が更新されていない場合 ※決済完了通知との競合を避けるため
        $OrderExtension = $this->app['eccube.plugin.epsilon.repository.order_extension']->find($Order->getId());
        if (empty($OrderExtension)) {
            // トランザクション制御
            $em = $this->app['orm.em'];
            $em->getConnection()->beginTransaction();
            try {
                // 受注情報を更新
                $this->updateOrder($Order, $response);

                $em->getConnection()->commit();
                $em->flush();
            } catch (\Exception $e) {
                $em->getConnection()->rollback();
                $em->close();

                $this->app->log($e);

                $this->app->addError('front.shopping.system.error');
                return $this->app->redirect($this->app->url('shopping_error'));
            }

        }

        // カート削除
        $cartService->clear()->save();

        // 受注IDを完了画面に引き継ぐ
        $this->app['session']->set('eccube.front.shopping.order.id', $Order->getId());

        // メール送信
        $this->sendOrderMail($Order);

        // 注文完了画面に遷移
        return $this->app->redirect($this->app->url('shopping_complete'));
    }

    /**
     * 取得レスポンスパラメータの項目チェック
     *
     * @param array $response
     * @param array $arrCheckParameter
     * @return boolean
     */
    function checkParameter($response, $arrCheckParameter)
    {
        foreach ($arrCheckParameter as $key) {
            if (!isset($response[$key])) {
                return false;
            }
        }

        return true;
    }

    /**
     * 受注情報を更新
     *
     * @param \Eccube\Entity\Order $Order
     * @param array $response
     */
    function updateOrder($Order, $response)
    {
        // 受注情報更新
		$OrderStatus = $this->app['eccube.repository.order_status']->find($this->app['config']['order_pre_end']);
        $this->app['eccube.repository.order']->changeStatus($Order->getId(), $OrderStatus);

        // 在庫情報更新
        $this->app['eccube.service.order']->setStockUpdate($this->app['orm.em'], $Order);

        if ($this->app->isGranted('ROLE_USER')) {
            // 会員の場合、購入金額を更新
            $this->app['eccube.service.order']->setCustomerUpdate($this->app['orm.em'], $Order, $this->app->user());
        }

        $OrderExtension = new \Plugin\GmoEpsilon\Entity\Extension\OrderExtension();
        $OrderExtension->setId($Order->getId());
        $OrderExtension->setTransCode($response['trans_code']);

        $this->app['orm.em']->persist($OrderExtension);
    }

    /**
     * 受注メールを送信
     *
     * @param \Eccube\Entity\Order $Order
     */
    function sendOrderMail($Order)
    {
        $this->app['eccube.service.mail']->sendOrderMail($Order);

        // 送信履歴を保存.
        $MailTemplate = $this->app['eccube.repository.mail_template']->find(1);

        // 3.0.7ではMailService::sendOrderMailの戻り値がないため再度作成する
        $body = $this->app->renderView($MailTemplate->getFileName(), array(
            'header' => $MailTemplate->getHeader(),
            'footer' => $MailTemplate->getFooter(),
            'Order' => $Order,
        ));

        $MailHistory = new MailHistory();
        $MailHistory
            ->setSubject('[' . $this->app['eccube.repository.base_info']->get()->getShopName() . '] ' . $MailTemplate->getSubject())
            ->setMailBody($body)
            ->setMailTemplate($MailTemplate)
            ->setSendDate(new \DateTime())
            ->setOrder($Order);
        $this->app['orm.em']->persist($MailHistory);
        $this->app['orm.em']->flush($MailHistory);
    }

    /**
     * リクエストパラメータを設定
     *
     * @param \Eccube\Entity\Order $Order
     * @param \Plugin\GmoEpsilon\Entity\Extension\PaymentExtension
     * @return array
     */
    function setParameter($Order, $PaymentExtension)
    {
        $cartItems = array();
        $cartItems = $this->app['eccube.service.cart']->getCart()->getCartItems();

        $objPlugin =& PluginUtil::getInstance($this->app);
        $Customer = $Order->getCustomer();
        $user_id = is_null($Customer) ? 'non_customer' : $Customer->getId();

        $itemInfo = $this->getItemInfo();

        $mission_code = $PaymentExtension->getMissionCode();
        if (is_null($mission_code)) {
            $mission_code = 1;
        } else {
            // 定期購入・非会員の場合、空文字に置き換え
            $user_id = $user_id == 'non_customer' ? '' : $user_id;
        }

        // 送信データを作成
        $arrResult = array(
            'contract_code' => $objPlugin->getSubData('contract_code'),
            'user_id' => $user_id,                                              // ユーザID
            'user_name' => $Order->getName01().$Order->getName02(),             // ユーザ名
            'user_mail_add' => $Order->getEmail(),                              // メールアドレス
            'order_number' => $Order->getId(),                                  // オーダー番号
            'item_code' => $itemInfo['item_code'],                              // 商品コード(代表)
            'item_name' => $itemInfo['item_name'],                              // 商品名(代表)
            'item_price' => $Order->getPaymentTotal(),                          // 商品価格(税込み総額)
            'st_code' => $PaymentExtension->getStCode(),                        // 決済区分
            'mission_code' => $mission_code,                                    // 課金区分(固定)
            'process_code' => '1',                                              // 処理区分(固定)
            'xml' => '1',                                                       // 応答形式(固定)
            'memo1' => "",                                                      // 予備01
            'memo2' => "EC-CUBE3_" . date("YmdHis"),                            // 予備02
            'delivery_id' => '99',
            );

        return $arrResult;
    }

    /**
     * リクエストを送信
     *
     * @param string $url
     * @param array $arrParameter
     * @return array or boolean
     */
    function sendData($url, $arrParameter)
    {
        //パラメータの文字コードをUTF8⇒EUCJPに変換
        // mb_convert_variables("EUC-JP", "UTF-8", $arrParameter);
        mb_convert_variables("SJIS-win", "UTF-8", $arrParameter);

        $arrVal = array();
        // SSLバージョンの設定を取得
        $post = $this->app['request']->get('config');
        $objPlugin = PluginUtil::getInstance($this->app);
        $sslVersion = $objPlugin->getSubData('ssl_version');
        if (!empty($post['ssl_version'])) {
        	$sslVersion = $post['ssl_version'];
        } else if (empty($sslVersion) && empty($post['ssl_version'])){
        	$sslVersion = 0;
        }
        // POSTデータを送信し、応答情報を取得する
        $client = new Client('', array('curl.options' => array('CURLOPT_SSLVERSION' => $sslVersion)));
        $request = $client->post($url, array(), $arrParameter);
        $response = "";
        try {
            $response = $request->send();
        } catch (CurlException $e) {
            $this->app['monolog.gmoepsilon']->addInfo('CurlException. url='.$url.' parameter='.print_r($arrParameter,true));
            return $e->getErrorNo();
        } catch (BadResponseException $e) {
            $this->app['monolog.gmoepsilon']->addInfo('BadResponseException. url='.$url.' parameter='.print_r($arrParameter,true));
            return false;
        } catch (\Exception $e) {
            $this->app['monolog.gmoepsilon']->addInfo('Exception. url='.$url.' parameter='.print_r($arrParameter,true));
            return false;
        }

        $response = $response->getBody(true);

        if (is_null($response)) {
            // $msg = 'レスポンスデータエラー: レスポンスがありません。';
            return false;
        }

        // Shift-JISをUNICODEに変換する
        $response = str_replace("x-sjis-cp932", "UTF-8", $response);

        // XMLパーサを生成する。
        $parser = xml_parser_create('utf-8');

        // 空白文字は読み飛ばしてXMLを読み取る
        xml_parser_set_option($parser,XML_OPTION_TARGET_ENCODING,"UTF-8");
        xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,1);

        // 配列にXMLのデータを格納する
        $err = xml_parse_into_struct($parser,$response,$arrVal,$idx);

        // 開放する
        xml_parser_free($parser);

        return $arrVal;

    }

    /**
     * Epsilon決済画面に遷移
     *
     * @param array $arrXML
     */
    function transitionEpsilon($arrXML)
    {
        // Epsilon決済画面に遷移
        $url = $this->getXMLValue($arrXML,'RESULT','REDIRECT');
        $response = $this->app->redirect($url);
        return $response;
    }

    /**
     * カートから代表商品情報を取得
     *
     * @return array
     */
    function getItemInfo()
    {
        $CartItems = $this->app['eccube.service.cart']->getCart()->getCartItems();
        foreach ($CartItems as $value) {
            $CartItem = $value;
            break;
        }
        $ProductClass = $CartItem->getObject();
        $Product = $ProductClass->getProduct();

        $itemInfo = array();
        $itemInfo['item_code'] = $ProductClass->getCode();
        $itemInfo['item_name'] = $Product->getName().'×'.$CartItem->getQuantity().'個(代表)';

        return $itemInfo;
    }

    /**
     * XMLのタグを指定し、要素を取得
     *
     * @param array $arrVal
     * @param string $tag
     * @param string $att
     * @return string
     */
    function getXMLValue($arrVal, $tag, $att)
    {
        $ret = "";
        foreach((array)$arrVal as $array) {
            if($tag == $array['tag']) {
                if(!is_array($array['attributes'])) {
                    continue;
                }
                foreach($array['attributes'] as $key => $val) {
                    if($key == $att) {
                        $ret = mb_convert_encoding(urldecode($val), 'UTF-8', 'SJIS');
                        break;
                    }
                }
            }
        }

        return $ret;
    }

    /**
     * 注文完了画面、受注メール用の決済情報を設定 (same as the EC-CUBE2)
     *
     * @param array $arrPayInfo
     * @param string $key
     * @param string $name
     * @param string $value
     */
    function setPayInfo(&$arrPayInfo, $key, $name, $value)
    {
        $arrPayInfo[$key]['name'] = $name;
        $arrPayInfo[$key]['value'] = $value;
    }

}