app/Plugin/VeriTrans4G2/Service/Payment/PaymentRecvService.php line 1672

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright (c) 2018 VeriTrans Inc., a Digital Garage company. All rights reserved.
  4.  * http://www.veritrans.co.jp/
  5.  */
  6. namespace Plugin\VeriTrans4G2\Service\Payment;
  7. use Doctrine\DBAL\Exception\DriverException;
  8. use Doctrine\DBAL\Exception\LockWaitTimeoutException;
  9. use Eccube\Entity\BaseInfo;
  10. use Eccube\Entity\Order;
  11. use Eccube\Entity\Master\OrderStatus;
  12. use Eccube\Entity\Cart;
  13. use Eccube\Entity\MailTemplate;
  14. use Eccube\Service\PurchaseFlow\PurchaseContext;
  15. use Plugin\VeriTrans4G2\Entity\Vt4gOrderPayment;
  16. use Plugin\VeriTrans4G2\Entity\Vt4gSubscOrder;
  17. use Plugin\VeriTrans4G2\Entity\Vt4gSubscOrderItem;
  18. use Plugin\VeriTrans4G2\Entity\Master\Vt4gSubscSaleType;
  19. use Symfony\Component\Mime\Address;
  20. use Symfony\Component\Mime\Email;
  21. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  22. use tgMdk\TGMDK_MerchantUtility;
  23. /**
  24.  * 結果(入金)通知受信処理クラス
  25.  */
  26. class PaymentRecvService extends BaseService
  27. {
  28.     /**
  29.      * 速報確報フラグ
  30.      */
  31.     private $fixed;
  32.     /**
  33.      * ネットバンク決済 注文完了メール送信タイミング
  34.      */
  35.     private $bankOrderMailSetting null;
  36.     /**
  37.      * 楽天ペイ 要求結果メール送信対象
  38.      */
  39.     private $rakutenMailSetting null;
  40.     /**
  41.      * 楽天ペイ 要求結果メールメッセージ
  42.      */
  43.     public $rakutenMailMsg;
  44.     /**
  45.      * 結果通知エラー報知メールメッセージ
  46.      */
  47.     public $errorMailMsg;
  48.     /**
  49.      * 入金報知メール 注文番号格納用配列
  50.      */
  51.     public $paymentInfoOrderNo;
  52.     /**
  53.      * 入金報知メール 設定値格納用配列
  54.      */
  55.     public $paymentInfoValues;
  56.     /**
  57.      * 結果通知前に想定されるorderstatusの値
  58.      */
  59.     const BEFORE_PUSH_RESULT_ORDER_STATUS = [
  60.         'id' => [
  61.             OrderStatus::NEW,
  62.             OrderStatus::PENDING
  63.         ]
  64.     ];
  65.     /**
  66.      * ヘッダーのチェックを行います。
  67.      *
  68.      * @param array $requestHeaders リクエストヘッダ情報の配列
  69.      * @return boolean true:チェックOK false:チェックNG
  70.      */
  71.     public function checkHeader($requestHeaders)
  72.     {
  73.         // ベリトランスペイメントゲートウェイからの通知電文を取得
  74.         $headers = [];
  75.         foreach ($requestHeaders as $header => $value) {
  76.             $headers[$header] = $value[0];
  77.             $this->mdkLogger->debug("$header$value[0]");
  78.         }
  79.         $headers array_change_key_case($headers,CASE_LOWER);
  80.         if(!array_key_exists('content-length'$headers) || $headers['content-length'] <= 0){
  81.             // 読み込めないので 500 を応答
  82.             $this->mdkLogger->error(trans('vt4g_plugin.payment.recv.not.exist.length'));
  83.             return false;
  84.         }
  85.         $body "";
  86.         $fp fopen("php://input""r");
  87.         if ($fp == false) {
  88.             $this->mdkLogger->error(trans('vt4g_plugin.payment.recv.recv.failed'));
  89.             // 読み込めないので 500 を応答
  90.             return false;
  91.         }
  92.         while (!feof($fp)) {
  93.             $body .= fgets($fp);
  94.         }
  95.         fclose($fp);
  96.         $this->mdkLogger->debug("Body: $body");
  97.         // Content-HMAC を利用して電文の改竄チェックを行う
  98.         $hmac array_key_exists('content-hmac'$headers) ? $headers['content-hmac'] : "";
  99.         if (strlen($hmac) <= 0) {
  100.             // Content-HMACがない 500 を応答
  101.             $this->mdkLogger->error(trans('vt4g_plugin.payment.recv.not.exist.hmac'));
  102.             return false;
  103.         }
  104.         if (!TGMDK_MerchantUtility::checkMessage($body$hmac)) {
  105.             $this->mdkLogger->error(trans('vt4g_plugin.payment.recv.valid.failed'));
  106.             // 改竄の疑いあり 500 を応答
  107.             return false;
  108.         }
  109.         $this->mdkLogger->info(trans('vt4g_plugin.payment.recv.valid.success'));
  110.         return true;
  111.     }
  112.     /**
  113.      * 結果(入金)通知データを取得します。
  114.      *
  115.      * @param array $arrPost
  116.      * @return array
  117.      */
  118.     public function getRecord($arrPost)
  119.     {
  120.         $arrRecord = [];
  121.         $arrHead   = [];
  122.         // ヘッダー情報の取得
  123.         foreach ($this->vt4gConst['VT4G_RECV_RECODE_HEAD'] as $val){
  124.             if (array_key_exists($val$arrPost)){
  125.                 $arrHead[$val] = $arrPost[$val];
  126.             }else{
  127.                 // ヘッダー情報なし
  128.                 return [[],[]];
  129.             }
  130.         }
  131.         $this->fixed array_key_exists('fixed'$arrPost) ? $arrPost['fixed'] : null;
  132.         // 明細情報
  133.         foreach ($arrPost as $key => $val) {
  134.             // 連番がついている項目のフィールド名と連番を取得する
  135.             // [ orderId0000=>123, total0000=>10 ]、[ orderId0001=>456 total0001=>20 ] という形で受信するので、
  136.             // [ 0 => [orderId => 123, total=>10 ], 1 => [orderId => 456, total=>20 ] ] という形にする。
  137.             $match = [];
  138.             if (preg_match('/^([a-zA-Z0-9]+)([0-9]{4})$/'$key$match) == false) {
  139.                 continue;
  140.             }
  141.             $arrRecord[(int)$match[2]][$match[1]] = $val;
  142.         }
  143.         return [$arrHead$arrRecord];
  144.     }
  145.     /**
  146.      * 結果(入金)通知情報の反映を行います。
  147.      * @param array $arrRecord
  148.      */
  149.     public function saveRecvData($arrRecord)
  150.     {
  151.         foreach ($arrRecord as $key => $record){
  152.             $count $key 1;
  153.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.data.count'),$count) . print_r($recordtrue));
  154.             // 結果通知の項目から決済内部IDを取得する
  155.             $payTypeId $this->getPayTypeId($record);
  156.             // 注文情報とそれに紐付く決済情報を取得する
  157.             $orderPayment $this->em->getRepository(Vt4gOrderPayment::class)->findOneBy(['memo01'=> $record['orderId']]);
  158.             if (empty($orderPayment)) {
  159.                 $order '';
  160.             } else {
  161.                 try {
  162.                     list($order$orderPayment) = $this->getLockedOrder($orderPayment->getOrderId());
  163.                 } catch (LockWaitTimeoutException $e) {
  164.                     throw $e;
  165.                 } catch (DriverException $e) {
  166.                     throw $e;
  167.                 }
  168.             }
  169.             // どちらかとれない場合はエラーメール対象。
  170.             // 申込結果の失敗通知ならメールは出さない。
  171.             if (empty($order) || empty($orderPayment)) {
  172.                 if ($this->checkAuthFailure($payTypeId$record)) {
  173.                     $this->mdkLogger->info(trans('vt4g_plugin.payment.recv.order.auth.failure'));
  174.                 } else {
  175.                     $this->mdkLogger->warn(trans('vt4g_plugin.payment.recv.order.not.exist'));
  176.                     $this->errorMailMsg[] = $this->makeErrorPushResult($record,trans('vt4g_plugin.payment.recv.order.not.exist'),'');
  177.                 }
  178.                 $this->em->rollback();
  179.                 continue;
  180.             }
  181.             if (empty($payTypeId)) {
  182.                 $this->mdkLogger->warn(trans('vt4g_plugin.payment.recv.order.not.payment'));
  183.                 $this->em->rollback();
  184.                 continue;
  185.             }
  186.             // 決済ごとの通知受信処理
  187.             $method "exec{$this->vt4gConst['VT4G_CODE_PAYTYPEID_'.$payTypeId]}RecvProcess";
  188.             $error $this->$method($order$orderPayment$record$payTypeId);
  189.             if (!empty($error)) {
  190.                 $this->errorMailMsg[] = $error;
  191.             }
  192.             $this->em->commit();
  193.         }
  194.     }
  195.     /**
  196.      * 結果通知の項目から決済内部IDを取得します。
  197.      *
  198.      * @param  array   $record 結果通知の項目
  199.      * @return string          決済内部ID 一致するものがない場合は空文字
  200.      */
  201.     private function getPayTypeId($record)
  202.     {
  203.         foreach ($this->vt4gConst['VT4G_RECV_RECODE_BODY'] as $key => $params) {
  204.             if ($this->arrayKeysExists($params$record)) {
  205.                 return $this->vt4gConst["$key"];
  206.             }
  207.         }
  208.         return '';
  209.     }
  210.     /**
  211.      * array_key_existsの配列版
  212.      *
  213.      * @param array $arrFormat
  214.      * @param array $arrRecord
  215.      * @return boolean
  216.      */
  217.     private function arrayKeysExists($arrFormat$arrRecord)
  218.     {
  219.         foreach ($arrFormat as $key){
  220.             if (!array_key_exists($key$arrRecord)){
  221.                 return false;
  222.             }
  223.         }
  224.         return true;
  225.     }
  226.     /**
  227.      * 決済申込の失敗結果通知であるかを調べます。
  228.      * @param  string $payTypeId 決済方法内部ID
  229.      * @param  array  $record    結果通知の項目
  230.      * @return bool   $isValid   決済申込の失敗結果通知ならtrue、異なるならfalse
  231.      */
  232.     private function checkAuthFailure($payTypeId$record)
  233.     {
  234.         $isValid false;
  235.         switch ($payTypeId) {
  236.             case $this->vt4gConst['VT4G_PAYTYPEID_CREDIT']:
  237.                 if (   $record['mpiMstatus']  != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']
  238.                     || $record['cardMstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']){
  239.                     $isValid true;
  240.                 }
  241.                 break;
  242.             case $this->vt4gConst['VT4G_PAYTYPEID_UPOP']:
  243.             case $this->vt4gConst['VT4G_PAYTYPEID_ALIPAY']:
  244.                 if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']
  245.                     && $record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  246.                     $isValid true;
  247.                 }
  248.                 break;
  249.             case $this->vt4gConst['VT4G_PAYTYPEID_RAKUTEN_V2']:
  250.                 $vResultCodes str_split($record['vResultCode'], 4);
  251.                 foreach ($vResultCodes as $vResultCode) {
  252.                     if ($vResultCode == $this->vt4gConst['VT4G_RESPONSE']['V_RESULT_CODE']['RAKUTEN']['REQUEST_TIMEOUT']) {
  253.                         $isValid true;
  254.                     }
  255.                 }
  256.                 break;
  257.             case $this->vt4gConst['VT4G_PAYTYPEID_PAYPAL']:
  258.                 if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE']
  259.                     && $this->fixed       == $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED']
  260.                     && $record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK'] ) {
  261.                     $isValid true;
  262.                 }
  263.                 break;
  264.             default:
  265.                 break;
  266.         }
  267.         return $isValid;
  268.     }
  269.     /**
  270.      * 本人認証の結果通知処理
  271.      * @param Order            $order        注文情報
  272.      * @param Vt4gOrderPayment $orderPayment 決済情報
  273.      * @param array            $record       結果通知の項目
  274.      * @param string           $payTypeId    決済方法内部ID
  275.      */
  276.     private function execCreditRecvProcess($order$orderPayment$record$payTypeId)
  277.     {
  278.         // 本人認証はトランザクションタイプが本人認証結果(3Dセキュア2.0を含む)の場合、処理する
  279.         if (!in_array($record['txnType'], $this->vt4gConst['VT4G_RECV_TXN_TYPE_CREDIT'])) {
  280.             $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  281.             return '';
  282.         }
  283.         $shouldSendMail false;
  284.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_12'];
  285.         // 申込時の処理区分から与信/売上の通知区分を判定
  286.         $withCapture  $this->getWithCapture($order);
  287.         $recvType     $withCapture === 1
  288.                       $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  289.                       $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  290.         $newPayStatus $recvType['VALUE'];
  291.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  292.         // 結果通知の処理結果
  293.         // MPI 単体サービスの通知はcardMstatusが空ですが、MPI 単体サービスは設定できないので考慮しません
  294.         if (   $record['mpiMstatus']  != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']
  295.             || $record['cardMstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  296.             $status 'mpiMstatus:'.$record['mpiMstatus'].' cardMstatus:'.$record['cardMstatus'];
  297.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$status));
  298.             // 結果通知項目の登録
  299.             $this->registPushRecord($orderPayment$record);
  300.         } else {
  301.             $memo10 unserialize($orderPayment->getMemo10());
  302.             if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  303.                 $shouldSendMail true;
  304.             }
  305.             $this->clearCartByOrder($order);
  306.             $this->updateMpiPushResult($order$orderPayment$record$newPayStatus$withCapture);
  307.             // 継続課金注文の登録
  308.             $this->saveSubscOrder($order);
  309.             if ($shouldSendMail) {
  310.                 $this->sendOrderMail($order);
  311.                 $this->updateSentOrderMailToSent($orderPayment);
  312.             }
  313.         }
  314.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  315.         return '';
  316.     }
  317.     /**
  318.      * コンビニ決済の結果通知処理
  319.      * @param Order            $order        注文情報
  320.      * @param Vt4gOrderPayment $orderPayment 決済情報
  321.      * @param array            $record       結果通知の項目
  322.      * @param string           $payTypeId    決済方法内部ID
  323.      */
  324.     private function execCVSRecvProcess($order$orderPayment$record$payTypeId)
  325.     {
  326.         $error '';
  327.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  328.         $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['DEPOSIT']; // 入金結果
  329.         $newPayStatus   $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE'];
  330.         $newOrderStatus OrderStatus::PAID;
  331.         $payStatuses    = [ $this->vt4gConst['VT4G_PAY_STATUS']['REQUEST']['VALUE'] ];
  332.         $memo05 $this->util->getPaymentMethodInfo($order->getPayment()->getId());
  333.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  334.         // 決済ログ作成
  335.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  336.         $this->setLogInfo('お支払店舗' $this->getPayConveni($record['cvsType']));
  337.         $this->setLogInfo('受付番号'   $record['receiptNo']);
  338.         $this->setLogInfo('受付日付'   $this->util->toDate($record['receiptDate']));
  339.         $this->setLogInfo('入金金額'   preg_match('/^[0-9]+$/'$record['rcvAmount']) ? number_format($record['rcvAmount']) : $record['rcvAmount']);
  340.         // 現在の支払方法検証
  341.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  342.         // 決済ステータス検証
  343.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  344.         // 注文ステータス検証
  345.         $error .= $this->checkOrderStatusPushResult($orderself::BEFORE_PUSH_RESULT_ORDER_STATUS$newOrderStatus);
  346.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  347.         if (!empty($error)) {
  348.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  349.         } elseif(!empty($memo05['send_payment_info_mail'])){
  350.             $this->paymentInfoOrderNo[] = $order->getOrderNo();
  351.             $this->paymentInfoValues[$order->getOrderNo()] = $memo05['send_payment_info_mail'];
  352.         }
  353.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  354.         return $error;
  355.     }
  356.     /**
  357.      * ネットバンク・ATM決済の結果通知処理
  358.      * @param Order            $order        注文情報
  359.      * @param Vt4gOrderPayment $orderPayment 決済情報
  360.      * @param array            $record       結果通知の項目
  361.      * @param string           $payTypeId    決済方法内部ID
  362.      */
  363.     private function execBankRecvProcess($order$orderPayment$record$payTypeId)
  364.     {
  365.         $error '';
  366.         $shouldSendMail false;
  367.         $memo05 $this->util->getPaymentMethodInfo($order->getPayment()->getId());
  368.         // ネットバンクとATMの通知は同じ項目なのでテーブルデータで判定
  369.         if ($orderPayment->getMemo03() == $this->vt4gConst['VT4G_PAYTYPEID_ATM']) {
  370.             $payTypeId $this->vt4gConst['VT4G_PAYTYPEID_ATM'];
  371.             $paymentMethod $this->util->getPaymentMethod($order->getPayment()->getId());
  372.             $payName $paymentMethod->getPaymentMethod();
  373.         } else {
  374.             // テーブルデータもネットバンクなら注文完了メール送信の判定
  375.             if (is_null($this->bankOrderMailSetting)) {
  376.                 if (is_array($memo05) && array_key_exists('mailTiming',$memo05)) {
  377.                     $this->bankOrderMailSetting $memo05['mailTiming'];
  378.                 } else {
  379.                     // 未登録の場合は設定画面の初期値と同じ値とする
  380.                     $this->bankOrderMailSetting $this->vt4gConst['VT4G_MAIL_TIMING']['BANK']['ON_PAYMENT'];
  381.                 }
  382.             }
  383.             $shouldSendMail $this->bankOrderMailSetting == $this->vt4gConst['VT4G_MAIL_TIMING']['BANK']['ON_RECEIVE'];
  384.             $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  385.         }
  386.         $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['DEPOSIT']; // 入金結果
  387.         $newPayStatus   $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE'];
  388.         $newOrderStatus OrderStatus::PAID;
  389.         $payStatuses    = [ ''$this->vt4gConst['VT4G_PAY_STATUS']['REQUEST']['VALUE'] ];
  390.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  391.         // 決済ログ作成
  392.         $this->setLogHeadPushResult($record$payTypeId$recvType$payName);
  393.         $this->setLogInfo('収納機関コード' $record['kikanNo']);
  394.         $this->setLogInfo('収納企業コード' $record['kigyoNo']);
  395.         $this->setLogInfo('収納日時'       $this->util->toDate($record['rcvDate']));
  396.         $this->setLogInfo('お客様番号'     $record['customerNo']);
  397.         $this->setLogInfo('確認番号'       $record['confNo']);
  398.         $this->setLogInfo('入金金額'       preg_match('/^[0-9]+$/'$record['rcvAmount']) ? number_format($record['rcvAmount']) : $record['rcvAmount']);
  399.         // 現在の支払方法検証
  400.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  401.         // 決済ステータス検証
  402.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  403.         // 注文ステータス検証
  404.         $error .= $this->checkOrderStatusPushResult($orderself::BEFORE_PUSH_RESULT_ORDER_STATUS$newOrderStatus);
  405.         if (!empty($error)) {
  406.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  407.         } else {
  408.             if(!empty($memo05['send_payment_info_mail']) && $payTypeId == $this->vt4gConst['VT4G_PAYTYPEID_ATM']){
  409.                 $this->paymentInfoOrderNo[] = $order->getOrderNo();
  410.                 $this->paymentInfoValues[$order->getOrderNo()] = $memo05['send_payment_info_mail'];
  411.             }
  412.         }
  413.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  414.         if (empty($error) && $shouldSendMail) {
  415.             $this->sendOrderMail($order);
  416.             $this->updateSentOrderMailToSent($orderPayment);
  417.         }
  418.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  419.         return $error;
  420.     }
  421.     /**
  422.      * 銀聯ネット決済の結果通知処理
  423.      * @param Order            $order        注文情報
  424.      * @param Vt4gOrderPayment $orderPayment 決済情報
  425.      * @param array            $record       結果通知の項目
  426.      * @param string           $payTypeId    決済方法内部ID
  427.      */
  428.     private function execUPOPRecvProcess($order$orderPayment$record$payTypeId)
  429.     {
  430.         $error '';
  431.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  432.         $shouldSendMail false;
  433.         $payStatuses = [];
  434.         switch ($record['txnType']) {
  435.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  436.                 // 申込時の処理区分から与信/売上の通知区分を判定
  437.                 $withCapture    $this->getWithCapture($order);
  438.                 $recvType       $withCapture === 1
  439.                                 $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  440.                                 $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  441.                 $newPayStatus   $recvType['VALUE'];
  442.                 $newOrderStatus $withCapture === OrderStatus::PAID OrderStatus::NEW;
  443.                 $payStatuses    = [ ''$recvType['VALUE'] ];
  444.                 $memo10 unserialize($orderPayment->getMemo10());
  445.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  446.                     $shouldSendMail true;
  447.                 }
  448.                 break;
  449.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE']:
  450.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']; // 売上結果
  451.                 $newPayStatus   '';
  452.                 $newOrderStatus '';
  453.                 break;
  454.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_REFUND']:
  455.                 // 返金の場合、現在の決済ステータスで判別する
  456.                 $recvType       $this->getRefundRecvSetting($orderPayment);
  457.                 $newPayStatus   '';
  458.                 $newOrderStatus '';
  459.                 break;
  460.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CANCEL']:
  461.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CANCEL'];  // 取消結果
  462.                 $newPayStatus   '';
  463.                 $newOrderStatus '';
  464.                 break;
  465.             default:
  466.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  467.                 return '';
  468.         }
  469.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  470.         // 決済ログ作成
  471.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  472.         $this->setLogInfo('システム追跡番号' $record['traceNumber']);
  473.         $this->setLogInfo('認証サービス日時' $this->util->toDateMMDD($record['traceTime']) . '(中国時間)');
  474.         $this->setLogInfo('精算金額'         preg_match('/^[0-9]+$/'$record['settleAmount']) ? number_format($record['settleAmount']) : $record['settleAmount']);
  475.         $this->setLogInfo('精算日付'         $this->util->toDateMMDD($record['settleDate']));
  476.         if (!(empty($record['settleRate']) || $record['settleRate'] == 'null')){
  477.             $this->setLogInfo('精算レート'   $record['settleRate']);
  478.         }
  479.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  480.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  481.             $newPayStatus   '';
  482.             $newOrderStatus '';
  483.             $shouldSendMail false;
  484.         }
  485.         // 現在の支払方法検証
  486.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  487.         // 決済ステータス検証
  488.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  489.         // 過去の受信情報と比較
  490.         $memo09 $orderPayment->getmemo09();
  491.         if (!empty($memo09)) {
  492.             $oldRecords unserialize($memo09);
  493.             foreach ($oldRecords as $oldRecord ) {
  494.                 if (   $oldRecord['txnType']     == $record['txnType']
  495.                     && $oldRecord['traceNumber'] == $record['traceNumber'] ) {
  496.                     $diff array_diff(
  497.                         [
  498.                             $oldRecord['mstatus'],
  499.                             $oldRecord['traceTime'],
  500.                             $oldRecord['settleAmount'],
  501.                             $oldRecord['settleDate'],
  502.                             $oldRecord['settleRate'],
  503.                         ],
  504.                         [
  505.                             $record['mstatus'],
  506.                             $record['traceTime'],
  507.                             $record['settleAmount'],
  508.                             $record['settleDate'],
  509.                             $record['settleRate'],
  510.                         ]);
  511.                     if (!empty($diff)) {
  512.                         $error .= $this->makeErrorMsg(trans('vt4g_plugin.payment.recv.result.different'));
  513.                         $newPayStatus   '';
  514.                         $newOrderStatus '';
  515.                         break;
  516.                     }
  517.                 }
  518.             }
  519.         }
  520.         if (!empty($error)) {
  521.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  522.         } else {
  523.             if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']
  524.                 && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  525.                 $this->clearCartByOrder($order);
  526.             }
  527.         }
  528.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  529.         if (empty($error) && $shouldSendMail) {
  530.             $this->sendOrderMail($order);
  531.             $this->updateSentOrderMailToSent($orderPayment);
  532.         }
  533.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  534.         return $error;
  535.     }
  536.     /**
  537.      * Alipayの結果通知処理
  538.      * @param Order            $order        注文情報
  539.      * @param Vt4gOrderPayment $orderPayment 決済情報
  540.      * @param array            $record       結果通知の項目
  541.      * @param string           $payTypeId    決済方法内部ID
  542.      */
  543.     private function execAlipayRecvProcess($order$orderPayment$record$payTypeId)
  544.     {
  545.         $error '';
  546.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  547.         $shouldSendMail false;
  548.         $payStatuses = [];
  549.         switch ($record['txnType']) {
  550.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  551.                 // Alipayは与信同時売上のみ
  552.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']; // 売上結果
  553.                 $newPayStatus   $recvType['VALUE'];
  554.                 $newOrderStatus OrderStatus::PAID;
  555.                 $payStatuses    = [ ''$recvType['VALUE'] ];
  556.                 $memo10 unserialize($orderPayment->getMemo10());
  557.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  558.                     $shouldSendMail true;
  559.                 }
  560.                 break;
  561.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_REFUND']:
  562.                 // 返金の場合、現在の決済ステータスで判別する
  563.                 $recvType       $this->getRefundRecvSetting($orderPayment);
  564.                 $newPayStatus   '';
  565.                 $newOrderStatus '';
  566.                 break;
  567.             default:
  568.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  569.                 return '';
  570.         }
  571.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  572.         // 決済ログ作成
  573.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  574.         $this->setLogInfo('決済センターとの取引ID'$record['centerTradeId']);
  575.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  576.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  577.             $newPayStatus   '';
  578.             $newOrderStatus '';
  579.             $shouldSendMail false;
  580.         }
  581.         // 現在の支払方法検証
  582.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  583.         // 決済ステータス検証
  584.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  585.         // 過去の受信情報と比較
  586.         $memo09 $orderPayment->getmemo09();
  587.         if (!empty($memo09)) {
  588.             $oldRecords unserialize($memo09);
  589.             foreach ($oldRecords as $oldRecord ) {
  590.                 if (   $oldRecord['txnType']       == $record['txnType']
  591.                     && $oldRecord['centerTradeId'] == $record['centerTradeId']
  592.                     && $oldRecord['mstatus']       != $record['mstatus']) {
  593.                     $error .= $this->makeErrorMsg(trans('vt4g_plugin.payment.recv.result.different'));
  594.                     $newPayStatus   '';
  595.                     $newOrderStatus '';
  596.                     break;
  597.                 }
  598.             }
  599.         }
  600.         if (!empty($error)) {
  601.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  602.         } else {
  603.             if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']
  604.                 && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  605.                 $this->clearCartByOrder($order);
  606.             }
  607.         }
  608.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  609.         if (empty($error) && $shouldSendMail) {
  610.             $this->sendOrderMail($order);
  611.             $this->updateSentOrderMailToSent($orderPayment);
  612.         }
  613.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  614.         return $error;
  615.     }
  616.     /**
  617.      * 楽天ペイの結果通知処理
  618.      * @param Order            $order        注文情報
  619.      * @param Vt4gOrderPayment $orderPayment 決済情報
  620.      * @param array            $record       結果通知の項目
  621.      * @param string           $payTypeId    決済方法内部ID
  622.      */
  623.     private function execRakutenRecvProcess($order$orderPayment$record$payTypeId)
  624.     {
  625.         $error '';
  626.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  627.         $shouldSendMail  false;
  628.         $isRequest false;
  629.         switch ($record['txnType']) {
  630.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  631.                 // 申込時の処理区分から与信/売上の通知区分を判定
  632.                 $withCapture    $this->getWithCapture($order);
  633.                 $recvType       $withCapture === 1
  634.                                 $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  635.                                 $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  636.                 $newPayStatus   $recvType['VALUE'];
  637.                 $newOrderStatus $withCapture === OrderStatus::PAID OrderStatus::NEW;
  638.                 $payStatuses    = [ ''$recvType['VALUE'] ];
  639.                 $memo10 unserialize($orderPayment->getMemo10());
  640.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  641.                     $shouldSendMail true;
  642.                 }
  643.                 break;
  644.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE']:
  645.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']; // 売上結果
  646.                 $newPayStatus   $recvType['VALUE'];
  647.                 $newOrderStatus $order->getOrderStatus()->getId() === OrderStatus::NEW ? OrderStatus::PAID '';
  648.                 $payStatuses    = [ $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE_REQUEST']['VALUE'] ];
  649.                 $isRequest      true;
  650.                 break;
  651.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CANCEL']:
  652.                 // 取消の場合、現在の決済ステータスで判別する
  653.                 $recvType       $this->getRefundRecvSetting($orderPayment);
  654.                 $newPayStatus   $recvType['VALUE'] == $this->vt4gConst['VT4G_PAY_STATUS']['REFUND']['VALUE']
  655.                                 ? $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']
  656.                                 : $this->vt4gConst['VT4G_PAY_STATUS']['CANCEL']['VALUE'];
  657.                 $newOrderStatus '';
  658.                 $payStatuses    $recvType['VALUE'] == $this->vt4gConst['VT4G_PAY_STATUS']['REFUND']['VALUE']
  659.                                 ? [ $this->vt4gConst['VT4G_PAY_STATUS']['REDUCTION_REQUEST']['VALUE'] ]
  660.                                 : [ $this->vt4gConst['VT4G_PAY_STATUS']['CANCEL_REQUEST']['VALUE'] ];
  661.                 $isRequest      true;
  662.                 break;
  663.             default:
  664.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  665.                 return '';
  666.         }
  667.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  668.         // 決済ログ作成
  669.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  670.         $this->setLogInfo('処理日時'                   $this->util->toDate($record['txnTime']));
  671.         $this->setLogInfo('楽天スーパーポイント利用額' preg_match('/^[0-9]+$/'$record['usedPoint']) ? number_format($record['usedPoint']) : $record['usedPoint']);
  672.         if (array_key_exists('rakutenOrderId'$record)) {
  673.             $this->setLogInfo('楽天取引ID' $record['rakutenOrderId']);
  674.         }
  675.         if (array_key_exists('balance'$record)) {
  676.             $this->setLogInfo('残高' preg_match('/^[0-9]+$/'$record['balance']) ? number_format($record['balance']) : $record['balance']);
  677.         }
  678.         if (array_key_exists('rakutenApiErrorCode'$record)) {
  679.             $this->setLogInfo('楽天API エラーコード' $record['rakutenApiErrorCode']);
  680.         }
  681.         if (array_key_exists('rakutenOrderErrorCode'$record)) {
  682.             $this->setLogInfo('楽天取引エラーコード' $record['rakutenOrderErrorCode']);
  683.         }
  684.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  685.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  686.             $newPayStatus   '';
  687.             $newOrderStatus '';
  688.             $shouldSendMail false;
  689.         }
  690.         // 現在の支払方法検証
  691.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  692.         // 決済ステータス検証
  693.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  694.         if (!empty($error)) {
  695.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  696.         } else {
  697.             // 売上と取消の結果通知の場合はメール本文の作成と処理結果コードをチェック
  698.             if ($isRequest) {
  699.                 if (is_null($this->rakutenMailSetting)) {
  700.                     $memo05 $this->util->getPaymentMethodInfo($order->getPayment()->getId());
  701.                     if (is_array($memo05) && array_key_exists('result_mail_target',$memo05)) {
  702.                         $this->rakutenMailSetting $memo05['result_mail_target'];
  703.                     } else {
  704.                         // 未登録の場合は設定画面の初期値と同じ値とする
  705.                         $this->rakutenMailSetting $this->vt4gConst['VT4G_MAIL_TARGET']['RAKUTEN']['FAILURE'];
  706.                     }
  707.                 }
  708.                 // 要求結果メールのメッセージを設定
  709.                 if ($this->rakutenMailSetting == $this->vt4gConst['VT4G_MAIL_TARGET']['RAKUTEN']['ALL']) {
  710.                     $this->rakutenMailMsg[] .= $this->makeRakutenReqMsg($record$order->getOrderNo(), $recvType);
  711.                 } elseif (   $this->rakutenMailSetting == $this->vt4gConst['VT4G_MAIL_TARGET']['RAKUTEN']['FAILURE']
  712.                     && $record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  713.                         $this->rakutenMailMsg[] .= $this->makeRakutenReqMsg($record$order->getOrderNo(), $recvType);
  714.                 }
  715.                 // 減額の通知で成功以外なら決済失敗にする。それ以外の通知で成功以外なら元の決済ステータスに戻す。
  716.                 if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  717.                     if ($recvType['VALUE'] == $this->vt4gConst['VT4G_PAY_STATUS']['REFUND']['VALUE']) {
  718.                         $newPayStatus $this->vt4gConst['VT4G_PAY_STATUS']['FAILURE']['VALUE'];
  719.                     } else {
  720.                         $memo10 unserialize($orderPayment->getMemo10());
  721.                         $newPayStatus $memo10['lastPayStatus'];
  722.                     }
  723.                 } else {
  724.                     // 処理成功で取消なら決済情報の決済金額を0にする。
  725.                     if ($recvType['VALUE'] == $this->vt4gConst['VT4G_PAY_STATUS']['CANCEL']['VALUE']) {
  726.                         $memo10 unserialize($orderPayment->getMemo10());
  727.                         $memo10['captureTotal'] = 0;
  728.                         $orderPayment->setMemo10(serialize($memo10));
  729.                     }
  730.                 }
  731.             }
  732.             // 先に結果通知が届くケースがあるので処理が成功した注文に紐付くカートをクリア
  733.             if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']
  734.                 && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  735.                 $this->clearCartByOrder($order);
  736.             }
  737.         }
  738.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  739.         if (empty($error) && $shouldSendMail) {
  740.             $this->sendOrderMail($order);
  741.             $this->updateSentOrderMailToSent($orderPayment);
  742.         }
  743.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  744.         return $error;
  745.     }
  746.     /**
  747.      * 楽天ペイV2の結果通知処理
  748.      * @param Order            $order        注文情報
  749.      * @param Vt4gOrderPayment $orderPayment 決済情報
  750.      * @param array            $record       結果通知の項目
  751.      * @param string           $payTypeId    決済方法内部ID
  752.      */
  753.     private function execRakutenV2RecvProcess($order$orderPayment$record$payTypeId)
  754.     {
  755.         $error '';
  756.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  757.         $shouldSendMail  false;
  758.         $payStatuses = [];
  759.         switch ($record['txnType']) {
  760.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  761.                 // 申込時の処理区分から与信/売上の通知区分を判定
  762.                 $withCapture    $this->getWithCapture($order);
  763.                 $recvType       $withCapture === 1
  764.                                 $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  765.                                 $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  766.                 $newPayStatus   $recvType['VALUE'];
  767.                 $newOrderStatus $withCapture === OrderStatus::PAID OrderStatus::NEW;
  768.                 $payStatuses    = [ ''$recvType['VALUE'] ];
  769.                 $memo10 unserialize($orderPayment->getMemo10());
  770.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  771.                     $shouldSendMail true;
  772.                 }
  773.                 break;
  774.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE']:
  775.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']; // 売上結果
  776.                 $newPayStatus   '';
  777.                 $newOrderStatus '';
  778.                 break;
  779.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CANCEL']:
  780.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CANCEL'];  // 取消結果
  781.                 $newPayStatus   '';
  782.                 $newOrderStatus '';
  783.                 break;
  784.             default:
  785.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  786.                 return '';
  787.         }
  788.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  789.         // 決済ログ作成
  790.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  791.         if ($record['txnType'] === $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']) {
  792.             $this->setLogInfo('処理日時' $this->util->toDate($record['txnTime']));
  793.             $this->setLogInfo('楽天取引ID' $record['rakutenOrderId']);
  794.             $this->setLogInfo('ゲートウェイ決済取引ID' $record['gatewayOrderId']);
  795.             $this->setLogInfo('楽天ポイント利用額' preg_match('/^[0-9]+$/'$record['usedPoint']) ? number_format($record['usedPoint']) : $record['usedPoint']);
  796.             $this->setLogInfo('クレジットカードのブランド' $record['cardBrand']);
  797.             $this->setLogInfo('クレジットカード番号の下4桁' $record['cardLast4']);
  798.             $this->setLogInfo('分割払いの回数' $record['cardInstallments']);
  799.             $this->setLogInfo('セキュリティコード認証利用有無' $record['cardCvc']);
  800.             $this->setLogInfo('3Dセキュア認証利用有無' $record['card3ds']);
  801.             $this->setLogInfo('取消受付期限' $this->util->toDate($record['cancelExpirationTime']));
  802.             if (!empty($record['captureExpirationTime'])) {
  803.                 $this->setLogInfo('売上受付期限' $this->util->toDate($record['captureExpirationTime']));
  804.             }
  805.             if (!empty($record['extendAuthExpirationTime'])) {
  806.                 $this->setLogInfo('与信延長受付期限' $this->util->toDate($record['extendAuthExpirationTime']));
  807.             }
  808.             $this->setLogInfo('金額変更受付期限' $this->util->toDate($record['updateExpirationTime']));
  809.             if (array_key_exists('rakutenApiErrorCode'$record)) {
  810.                 $this->setLogInfo('楽天APIエラーコード' $record['rakutenApiErrorCode']);
  811.             }
  812.             if (array_key_exists('rakutenApiErrorType'$record)) {
  813.                 $this->setLogInfo('楽天APIエラータイプ' $record['rakutenApiErrorType']);
  814.             }
  815.         } else if ($record['txnType'] === $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE'] || $record['txnType'] === $this->vt4gConst['VT4G_RECV_TXN_TYPE_CANCEL']) {
  816.             $this->setLogInfo('※' '売上や取消の結果通知には対応していないため、データの更新は行いません。');
  817.         }
  818.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  819.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  820.             $newPayStatus   '';
  821.             $newOrderStatus '';
  822.             $shouldSendMail false;
  823.         }
  824.         // 現在の支払方法検証
  825.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  826.         // 決済ステータス検証
  827.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  828.         if (!empty($error)) {
  829.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  830.         } else {
  831.             // 先に結果通知が届くケースがあるので処理が成功した注文に紐付くカートをクリア
  832.             if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']
  833.                 && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  834.                 $this->clearCartByOrder($order);
  835.             }
  836.         }
  837.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  838.         if (empty($error) && $shouldSendMail) {
  839.             $this->sendOrderMail($order);
  840.             $this->updateSentOrderMailToSent($orderPayment);
  841.         }
  842.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  843.         return $error;
  844.     }
  845.     /**
  846.      * リクルートかんたん支払いの結果通知処理
  847.      * @param Order            $order        注文情報
  848.      * @param Vt4gOrderPayment $orderPayment 決済情報
  849.      * @param array            $record       結果通知の項目
  850.      * @param string           $payTypeId    決済方法内部ID
  851.      */
  852.     private function execRecruitRecvProcess($order$orderPayment$record$payTypeId)
  853.     {
  854.         $error '';
  855.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  856.         $shouldSendMail false;
  857.         switch ($record['txnType']) {
  858.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  859.                 // 申込時の処理区分から与信/売上の通知区分を判定
  860.                 $withCapture    $this->getWithCapture($order);
  861.                 $recvType       $withCapture === 1
  862.                                 $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  863.                                 $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  864.                 $newPayStatus   $recvType['VALUE'];
  865.                 $newOrderStatus $withCapture === OrderStatus::PAID OrderStatus::NEW;
  866.                 $payStatuses    = [ ''$recvType['VALUE']];
  867.                 $memo10 unserialize($orderPayment->getMemo10());
  868.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  869.                     $shouldSendMail true;
  870.                 }
  871.                 break;
  872.             default:
  873.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  874.                 return '';
  875.         }
  876.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  877.         // 決済ログ作成
  878.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  879.         $this->setLogInfo('処理日時'             $this->util->toDate($record['txnTime']));
  880.         $this->setLogInfo('リクルート取引ID'     $record['recruitOrderId']);
  881.         $this->setLogInfo('利用ポイント'         preg_match('/^[0-9]+$/'$record['usePoint']) ? number_format($record['usePoint']) : $record['usePoint']);
  882.         $this->setLogInfo('付与ポイント'         preg_match('/^[0-9]+$/'$record['givePoint']) ? number_format($record['givePoint']) : $record['givePoint']);
  883.         $this->setLogInfo('リクルートクーポン'   preg_match('/^[0-9]+$/'$record['recruitCoupon']) ? number_format($record['recruitCoupon']) : $record['recruitCoupon']);
  884.         $this->setLogInfo('マーチャントクーポン' preg_match('/^[0-9]+$/'$record['merchantCoupon']) ? number_format($record['merchantCoupon']) : $record['merchantCoupon']);
  885.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  886.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  887.             $newPayStatus   '';
  888.             $newOrderStatus '';
  889.         }
  890.         // 現在の支払方法検証
  891.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  892.         // 決済ステータス検証
  893.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  894.         if (!empty($error)) {
  895.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  896.         } else {
  897.             // 先に結果通知が届くケースがあるので処理が成功した注文に紐付くカートをクリア
  898.             if ($record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  899.                 $this->clearCartByOrder($order);
  900.             }
  901.         }
  902.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  903.         if (empty($error) && $shouldSendMail) {
  904.             $this->sendOrderMail($order);
  905.             $this->updateSentOrderMailToSent($orderPayment);
  906.         }
  907.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  908.         return $error;
  909.     }
  910.     /**
  911.      * LINE Payの結果通知処理
  912.      * @param Order            $order        注文情報
  913.      * @param Vt4gOrderPayment $orderPayment 決済情報
  914.      * @param array            $record       結果通知の項目
  915.      * @param string           $payTypeId    決済方法内部ID
  916.      */
  917.     private function execLINEPayRecvProcess($order$orderPayment$record$payTypeId)
  918.     {
  919.         $error '';
  920.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  921.         $shouldSendMail false;
  922.         switch ($record['txnType']) {
  923.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  924.                 // 申込時の処理区分から与信/売上の通知区分を判定
  925.                 $withCapture    $this->getWithCapture($order);
  926.                 $recvType       $withCapture === 1
  927.                                 $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  928.                                 $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  929.                 $newPayStatus   $recvType['VALUE'];
  930.                 $newOrderStatus $withCapture === OrderStatus::PAID OrderStatus::NEW;
  931.                 $payStatuses    = [ ''$recvType['VALUE']];
  932.                 $memo10 unserialize($orderPayment->getMemo10());
  933.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  934.                     $shouldSendMail true;
  935.                 }
  936.                 break;
  937.             default:
  938.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  939.                 return '';
  940.         }
  941.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  942.         // 決済ログ作成
  943.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  944.         $this->setLogInfo('処理日時'         $this->util->toDate($record['txnTime']));
  945.         $this->setLogInfo('LINE Pay 取引番号'$record['linepayOrderId']);
  946.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  947.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  948.             $newPayStatus   '';
  949.             $newOrderStatus '';
  950.             $shouldSendMail false;
  951.         }
  952.         // 現在の支払方法検証
  953.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  954.         // 決済ステータス検証
  955.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  956.         if (!empty($error)) {
  957.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  958.         } else {
  959.             // 先に結果通知が届くケースがあるので処理が成功した注文に紐付くカートをクリア
  960.             if ($record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  961.                 $this->clearCartByOrder($order);
  962.             }
  963.         }
  964.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  965.         if (empty($error) && $shouldSendMail) {
  966.             $this->sendOrderMail($order);
  967.             $this->updateSentOrderMailToSent($orderPayment);
  968.         }
  969.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  970.         return $error;
  971.     }
  972.     /**
  973.      * PayPal決済の結果通知処理
  974.      * @param Order            $order        注文情報
  975.      * @param Vt4gOrderPayment $orderPayment 決済情報
  976.      * @param array            $record       結果通知の項目
  977.      * @param string           $payTypeId    決済方法内部ID
  978.      */
  979.     private function execPayPalRecvProcess($order$orderPayment$record$payTypeId)
  980.     {
  981.         $error '';
  982.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  983.         $shouldSendMail false;
  984.         $payStatuses = [];
  985.         // 速報確報フラグをレコードに持たせる
  986.         $record['fixed'] = $this->fixed;
  987.         switch ($record['txnType']) {
  988.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE']:
  989.                 $recvType       $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']; // 売上結果
  990.                 if ($record['fixed'] != $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED']) {
  991.                     $newPayStatus   $recvType['VALUE'];
  992.                     $newOrderStatus $order->getOrderStatus()->getId() == (OrderStatus::NEW || OrderStatus::PENDING) ? OrderStatus::PAID '';
  993.                     $payStatuses    = [
  994.                                         '',
  995.                                         $this->vt4gConst['VT4G_PAY_STATUS']['AUTH']['VALUE'],
  996.                                         $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE'],
  997.                                     ];
  998.                     $memo10 unserialize($orderPayment->getMemo10());
  999.                     if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  1000.                         $shouldSendMail true;
  1001.                     }
  1002.                 } else {
  1003.                     $newPayStatus '';
  1004.                     $newOrderStatus '';
  1005.                 }
  1006.                 break;
  1007.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_REFUND']:
  1008.                 // 返金の場合、現在の決済ステータスで判別する
  1009.                 $recvType       $this->getRefundRecvSetting($orderPayment);
  1010.                 $newPayStatus   '';
  1011.                 $newOrderStatus '';
  1012.                 break;
  1013.             default:
  1014.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  1015.                 return '';
  1016.         }
  1017.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  1018.         // 決済ログ作成
  1019.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  1020.         $this->setLogInfo('受付日時'  $this->util->toDate($record['receivedDatetime']));
  1021.         $this->setLogInfo('金額'      preg_match('/^[0-9]+$/'$record['amount']) ? number_format($record['amount']) : $record['amount']);
  1022.         $this->setLogInfo('お客様番号'$record['payerId']);
  1023.         $this->setLogInfo('取引識別子'$record['centerTxnId']);
  1024.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1025.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  1026.             $newPayStatus   '';
  1027.             $newOrderStatus '';
  1028.             $shouldSendMail false;
  1029.         }
  1030.         // 現在の支払方法検証
  1031.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  1032.         // 決済ステータス検証
  1033.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  1034.         // 過去の受信情報と比較
  1035.         $memo09 $orderPayment->getmemo09();
  1036.         if (!empty($memo09)) {
  1037.             $oldRecords  unserialize($memo09);
  1038.             $promptCnt   0;
  1039.             $diffRecode  false;
  1040.             $failerFixed false;
  1041.             foreach ($oldRecords as $oldRecord ) {
  1042.                 // payerId、centerTxnId、fixedが同じで、異なる結果を受信したらエラーメール
  1043.                 // 一つでも見つかればエラーメールなので、発見済みならスキップ
  1044.                 if (   $oldRecord['payerId']     == $record['payerId']
  1045.                     && $oldRecord['centerTxnId'] == $record['centerTxnId']
  1046.                     && $oldRecord['fixed']       == $record['fixed']
  1047.                     && !$diffRecode) {
  1048.                     $diff array_diff(
  1049.                         [
  1050.                             $oldRecord['mstatus'],
  1051.                             $oldRecord['receivedDatetime'],
  1052.                             $oldRecord['amount'],
  1053.                         ],
  1054.                         [
  1055.                             $record['mstatus'],
  1056.                             $record['receivedDatetime'],
  1057.                             $record['amount'],
  1058.                         ]);
  1059.                     $diffRecode = !empty($diff);
  1060.                 }
  1061.                 // 今回が確報なら速報の結果を確認
  1062.                 if ($record['fixed'] == $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED']) {
  1063.                     if (   $oldRecord['payerId']     == $record['payerId']
  1064.                         && $oldRecord['centerTxnId'] == $record['centerTxnId']
  1065.                         && $oldRecord['fixed']       != $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED'] ) {
  1066.                         $promptCnt++;
  1067.                         // 過去に成功の速報を受信していて、今回が成功以外の確報ならエラーメール対象
  1068.                         if (   $oldRecord['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']
  1069.                             && $record['mstatus']    != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1070.                             $failerFixed true;
  1071.                         }
  1072.                     }
  1073.                 }
  1074.             }
  1075.             // 過去の受信結果と異なる結果だった場合
  1076.             if ($diffRecode) {
  1077.                 $error .= $this->makeErrorMsg(trans('vt4g_plugin.payment.recv.result.different'));
  1078.                 $newPayStatus   '';
  1079.                 $newOrderStatus '';
  1080.             }
  1081.             if ($record['fixed'] == $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED']) {
  1082.                 if ($failerFixed) {
  1083.                     $error .= $this->makeErrorMsg(trans('vt4g_plugin.payment.recv.paypal.fixed.failure'));
  1084.                 }
  1085.                 // 速報がないのに確報の成功結果が届いたらエラーメール
  1086.                 if ($promptCnt == && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1087.                     $error .= $this->makeErrorMsg(trans('vt4g_plugin.payment.recv.paypal.fixed.not.prompt'));
  1088.                 }
  1089.             }
  1090.         } else {
  1091.             // 受信結果がないのに確報の成功結果が届いたらエラーメール
  1092.             if (   $record['fixed']   == $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED']
  1093.                 && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1094.                 $error .= $this->makeErrorMsg(trans('vt4g_plugin.payment.recv.paypal.fixed.not.prompt'));
  1095.             }
  1096.         }
  1097.         if (!empty($error)) {
  1098.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  1099.         } else {
  1100.             if (   $record['txnType'] == $this->vt4gConst['VT4G_RECV_TXN_TYPE_CAPTURE']
  1101.                 && $record['fixed']   != $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED']
  1102.                 && $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1103.                 $this->clearCartByOrder($order);
  1104.             }
  1105.         }
  1106.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  1107.         if (empty($error) && $shouldSendMail) {
  1108.             $this->sendOrderMail($order);
  1109.             $this->updateSentOrderMailToSent($orderPayment);
  1110.         }
  1111.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  1112.         return $error;
  1113.     }
  1114.     /**
  1115.      * PayPayの結果通知処理
  1116.      * @param Order            $order        注文情報
  1117.      * @param Vt4gOrderPayment $orderPayment 決済情報
  1118.      * @param array            $record       結果通知の項目
  1119.      * @param string           $payTypeId    決済方法内部ID
  1120.      */
  1121.     private function execPayPayRecvProcess($order$orderPayment$record$payTypeId)
  1122.     {
  1123.         $error '';
  1124.         $payName $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId];
  1125.         $shouldSendMail false;
  1126.         $payStatuses = [];
  1127.         switch ($record['txnType']) {
  1128.             case $this->vt4gConst['VT4G_RECV_TXN_TYPE_AUTH']:
  1129.                 // 申込時の処理区分から与信/売上の通知区分を判定
  1130.                 $withCapture    $this->getWithCapture($order);
  1131.                 $recvType       $withCapture === 1
  1132.                                 $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE'// 売上結果
  1133.                                 $this->vt4gConst['VT4G_PAY_STATUS']['AUTH'];   // 申込結果
  1134.                 $newPayStatus   $recvType['VALUE'];
  1135.                 $newOrderStatus $withCapture === OrderStatus::PAID OrderStatus::NEW;
  1136.                 $payStatuses    = [ ''$recvType['VALUE']];
  1137.                 $memo10 unserialize($orderPayment->getMemo10());
  1138.                 if (array_key_exists('sentOrderMail'$memo10) && $memo10['sentOrderMail'] === false) {
  1139.                     $shouldSendMail true;
  1140.                 }
  1141.                 break;
  1142.             default:
  1143.                 $this->mdkLogger->warn(sprintf(trans('vt4g_plugin.payment.recv.not.txn_type'),$record['txnType']));
  1144.                 return '';
  1145.         }
  1146.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.start'),$recvType['RECV_NAME'],$payName));
  1147.         // 決済ログ作成
  1148.         $this->setLogHeadPushResult($record$payTypeId$recvType);
  1149.         $this->setLogInfo('処理日時'      $this->util->toDate($record['txnTime']));
  1150.         $this->setLogInfo('PayPay 取引ID' $record['paypayOrderId']);
  1151.         if ($record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1152.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.mstatus.error'),$recvType['RECV_NAME'],$record['mstatus']));
  1153.             $newPayStatus   '';
  1154.             $newOrderStatus '';
  1155.             $shouldSendMail false;
  1156.         }
  1157.         // 現在の支払方法検証
  1158.         $error .= $this->checkPaymentTypeIDPushResult($order$orderPayment$newPayStatus$newOrderStatus);
  1159.         // 決済ステータス検証
  1160.         $error .= $this->checkPaymentStatusPushResult($orderPayment$payStatuses$newPayStatus$newOrderStatus);
  1161.         if (!empty($error)) {
  1162.             $error $this->makeErrorPushResult($record$error$order->getOrderNo());
  1163.         } else {
  1164.             // 先に結果通知が届くケースがあるので処理が成功した注文に紐付くカートをクリア
  1165.             if ($record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1166.                 $this->clearCartByOrder($order);
  1167.             }
  1168.         }
  1169.         $this->updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record);
  1170.         if (empty($error) && $shouldSendMail) {
  1171.             $this->sendOrderMail($order);
  1172.             $this->updateSentOrderMailToSent($orderPayment);
  1173.         }
  1174.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.save.end'),$recvType['RECV_NAME'],$payName));
  1175.         return $error;
  1176.     }
  1177.     /**
  1178.      * 結果通知の決済ログヘッダ部分の作成
  1179.      *
  1180.      * @param array   $record       通知レコード
  1181.      * @param integer $payTypeId    支払方法内部ID
  1182.      * @param array   $recvType     通知ごとの設定値
  1183.      * @param string  $payName      支払方法の名称
  1184.      */
  1185.     private function setLogHeadPushResult($record$payTypeId$recvType$payName null)
  1186.     {
  1187.         $statusLabel $recvType['LABEL'] == $this->vt4gConst['VT4G_PAY_STATUS']['DEPOSIT']['LABEL']
  1188.                     ? $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['LABEL']
  1189.                     : $recvType['LABEL'];
  1190.         // ログの共通ヘッダの作成
  1191.         $this->logData = [];
  1192.         $log_message  '';
  1193.         $log_message .= "[{$statusLabel}] ";
  1194.         $log_message .= "{$recvType['RECV_NAME']}通知受信";
  1195.         // PayPalの通知は速報、確報を付けて表示する
  1196.         if ($payTypeId == $this->vt4gConst['VT4G_PAYTYPEID_PAYPAL']){
  1197.             $log_message .= $record['fixed'] == $this->vt4gConst['VT4G_RECV_PAYPAL_FIXED'] ? '(確報)' '(速報)';
  1198.         }
  1199.         // 入金済みにする入金通知に成功、失敗はないので飛ばす
  1200.         if ($recvType['VALUE'] != $this->vt4gConst['VT4G_PAY_STATUS']['DEPOSIT']['VALUE']){
  1201.             if ($record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1202.                 $msg '成功';
  1203.             } elseif ($record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['PENDING']) {
  1204.                 $msg '保留';
  1205.             } else {
  1206.                 $msg '失敗';
  1207.             }
  1208.             $log_message .= ' ' $msg;
  1209.         }
  1210.         $this->setLogInfo('決済取引ID'$record['orderId']);
  1211.         $this->setLogInfo($payName ?? $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_'.$payTypeId], $log_message);
  1212.     }
  1213.     /**
  1214.      * 入金通知上のコンビニ名を取得します。
  1215.      *
  1216.      * @param  string $cvsType CVSタイプ
  1217.      * @return string          コンビニ名
  1218.      */
  1219.     private function getPayConveni($cvsType)
  1220.     {
  1221.         $arrConveni $this->vt4gConst['VT4G_RECV_CVS_TYPE'];
  1222.         if (array_key_exists($cvsType$arrConveni)) {
  1223.             return $arrConveni[$cvsType];
  1224.         } else {
  1225.             return '不明';
  1226.         }
  1227.     }
  1228.     /**
  1229.      * 注文と支払方法設定データの支払方法内部IDをチェックします。
  1230.      *
  1231.      * @param  Order             $order          注文情報
  1232.      * @param  Vt4gOrderPayment  $orderPayment   決済情報
  1233.      * @param  string           &$newPayStatus   更新予定の決済ステータス
  1234.      * @param  string           &$newOrderStatus 更新予定の注文ステータス
  1235.      * @return string            $error          エラーのときはメッセージ、それ以外は空文字
  1236.      */
  1237.     private function checkPaymentTypeIDPushResult($order$orderPayment, &$newPayStatus, &$newOrderStatus)
  1238.     {
  1239.         $paymentMethod $this->util->getPaymentMethod($order->getPayment()->getId());
  1240.         if(!empty($paymentMethod->getMemo03()) && $paymentMethod->getMemo03() == $orderPayment->getMemo03()) {
  1241.             return '';
  1242.         }
  1243.         // 以下エラーの場合
  1244.         $msg sprintf(trans('vt4g_plugin.payment.recv.payment_type_id.error'),$orderPayment->getMemo03(),$paymentMethod->getMemo03());
  1245.         $error $this->makeErrorMsg($msg);
  1246.         $newPayStatus '';
  1247.         $newOrderStatus '';
  1248.         return $error;
  1249.     }
  1250.     /**
  1251.      * 通知受信前の決済ステータスが想定通りであるかをチェックします。
  1252.      * チェックNGの場合は更新予定の決済ステータスと注文ステータスを空にします。
  1253.      * 更新予定の決済ステータスが空で渡された場合はOKとします。
  1254.      * @param  Vt4gOrderPayment $orderPayment   決済情報
  1255.      * @param  array            $payStatuses    想定される決済ステータスの配列
  1256.      * @param  string          &$newPayStatus   更新予定の決済ステータス
  1257.      * @param  string          &$newOrderStatus 更新予定の注文ステータス
  1258.      * @return string           $error          エラーのときはメッセージ、それ以外は空文字
  1259.      */
  1260.     private function checkPaymentStatusPushResult($orderPayment$payStatuses, &$newPayStatus, &$newOrderStatus)
  1261.     {
  1262.         if (empty($newPayStatus) || in_array($orderPayment->getMemo04(), $payStatuses)) {
  1263.             return '';
  1264.         }
  1265.         // 以下エラーの場合
  1266.         $names = [];
  1267.         foreach ($payStatuses as $payStatus) {
  1268.             $names[] = empty($payStatus) ? '値なし' $this->util->getPaymentStatusName($payStatus);
  1269.         }
  1270.         $msg sprintf(trans('vt4g_plugin.payment.recv.payment_status.error'),
  1271.                         $this->util->getPaymentStatusName($orderPayment->getMemo04()),
  1272.                         implode(' ',$names));
  1273.         $error $this->makeErrorMsg($msg);
  1274.         $newPayStatus   '';
  1275.         $newOrderStatus '';
  1276.         return $error;
  1277.     }
  1278.     /**
  1279.      * 通知受信前の注文ステータスが想定通りであるかをチェックします。
  1280.      * チェックNGの場合は更新予定の注文ステータスを空にします。
  1281.      * 更新予定の注文ステータスが空で渡された場合はOKとします。
  1282.      * @param  Order   $Order          注文情報
  1283.      * @param  array   $orderStatus    想定される注文ステータス
  1284.      * @param  string  $newOrderStatus 更新予定の注文ステータス
  1285.      * @return string  $error          エラーのときはメッセージ、それ以外は空文字
  1286.      */
  1287.     private function checkOrderStatusPushResult($order$orderStatus, &$newOrderStatus)
  1288.     {
  1289.         if (empty($newOrderStatus) || in_array($order->getOrderStatus()->getId(),$orderStatus['id'])) {
  1290.             return '';
  1291.         }
  1292.         // 以下エラーの場合
  1293.         $statusArray = [];
  1294.         $beforePushResultOrderStatus $this->em->getRepository(OrderStatus::class)->findBy($orderStatus);
  1295.         foreach($beforePushResultOrderStatus as $status ){
  1296.             $statusArray[] = $status->getName();
  1297.         }
  1298.         $msg sprintf(trans('vt4g_plugin.payment.recv.order_status.error'),
  1299.                         $order->getOrderStatus()->getName(),
  1300.                         implode(' ',$statusArray));
  1301.         $error $this->makeErrorMsg($msg);
  1302.         $newOrderStatus '';
  1303.         return $error;
  1304.     }
  1305.     /**
  1306.      * 本人認証結果通知の情報で受注を更新します。
  1307.      * @param Order            $order        注文情報
  1308.      * @param Vt4gOrderPayment $orderPayment 決済情報
  1309.      * @param array            $recode       結果通知の項目
  1310.      * @param integer          $newPayStatus 通知受信後の決済ステータス
  1311.      * @param integer          $withCapture  決済申込時点の処理区分
  1312.      * @param array $record 通知レコード
  1313.      */
  1314.     private function updateMpiPushResult($order$orderPayment$record$newPayStatus$withCapture)
  1315.     {
  1316.         $creditService $this->container->get('vt4g_plugin.service.payment_credit');
  1317.         $creditService->logData = [];
  1318.         $creditService->paymentResult['isOK']         = true;
  1319.         $creditService->paymentResult['vResultCode']  = $record['vResultCode'];
  1320.         $creditService->paymentResult['mErrMsg']      = "";
  1321.         $creditService->paymentResult['mStatus']      = $record['cardMstatus'];
  1322.         $creditService->paymentResult['orderId']      = $orderPayment->getMemo01();
  1323.         $memo10 unserialize($orderPayment->getMemo10());
  1324.         $creditService->paymentResult['paymentType']  = substr($memo10['card_type'], 02);
  1325.         $creditService->paymentResult['paymentCount'] = substr($memo10['card_type'], 2);
  1326.         $creditService->paymentResult['payStatus']    = $newPayStatus;
  1327.         $creditService->paymentResult['mpiHosting']   = true;
  1328.         $creditService->paymentResult['withCapture']  = $withCapture;
  1329.         // フラグをオンにしてcompleteOrderでメール送信とappendOrderMessageをやらない
  1330.         $creditService->isPaymentRecv true;
  1331.         $creditService->completeCreditOrder($order$orderPayment);
  1332.         // 結果通知項目の登録
  1333.         $this->registPushRecord($orderPayment$record);
  1334.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.order.update'), $order->getId()));
  1335.     }
  1336.     /**
  1337.      * ステータスの更新、結果通知項目の登録、決済ログの登録を行います。<br>
  1338.      * $newOrderStatusに値がある場合はdtb_orderの更新を行います。<br>
  1339.      * $newPayStatusに値がある場合はplg_vt4g_order_paymentの更新を行います。
  1340.      * @param Order            $order          注文情報
  1341.      * @param Vt4gOrderPayment $orderPayment   決済情報
  1342.      * @param integer          $newPayStatus   更新予定の決済ステータス
  1343.      * @param integer          $newOrderStatus 更新予定の注文ステータス
  1344.      * @param array            $record         結果通知の項目
  1345.      */
  1346.     private function updatePushResult($order$orderPayment$newPayStatus$newOrderStatus$record)
  1347.     {
  1348.         $orderId $order->getId();
  1349.         // 注文ステータスの更新
  1350.         if (!empty($newOrderStatus)) {
  1351.             if (empty($orderPayment->getMemo04())) {
  1352.                 $this->purchaseFlow->commit($order, new PurchaseContext());
  1353.             }
  1354.             $orderStatus $this->em->getRepository(OrderStatus::class)->find($newOrderStatus);
  1355.             $this->em->getRepository(Order::class)->changeStatus($orderId$orderStatus);
  1356.         }
  1357.         // 決済ステータスの更新
  1358.         if (!empty($newPayStatus)) {
  1359.             $orderPayment->setMemo04($newPayStatus);
  1360.             $this->em->persist($orderPayment);
  1361.             $this->em->flush();
  1362.         }
  1363.         // 結果通知項目の登録
  1364.         $this->registPushRecord($orderPayment$record);
  1365.         // 決済ログテーブルにログを追加
  1366.         $this->setOrderLog($order);
  1367.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.order.update'), $orderId));
  1368.     }
  1369.     /**
  1370.      * エラー出力
  1371.      *
  1372.      * @param  array  $record    結果通知の項目
  1373.      * @param  string $error     メッセージ
  1374.      * @param  string $orderNo   注文番号
  1375.      * @return string $new_error エラーメッセージ
  1376.      */
  1377.     private function makeErrorPushResult($record$error$orderNo '')
  1378.     {
  1379.         $orderId $record['orderId'];
  1380.         $newError = <<<__EOS__
  1381. 決済取引ID : $orderId
  1382.   注文番号 : $orderNo
  1383. エラー原因 : $error
  1384. __EOS__;
  1385.         return $newError;
  1386.     }
  1387.     /**
  1388.      * 楽天ペイ 要求結果メッセージ作成
  1389.      * @param  array  $record   結果通知の項目
  1390.      * @param  string $orderNo  注文番号
  1391.      * @param  array  $recvType 結果通知ごとの設定値
  1392.      * @return string $payLabel 決済方法の名称
  1393.      */
  1394.     private function makeRakutenReqMsg($record$orderNo ''$recvType)
  1395.     {
  1396.         $orderId $record['orderId'];
  1397.         $ret  $recvType['VALUE'] == $this->vt4gConst['VT4G_PAY_STATUS']['REFUND']['VALUE']
  1398.                 ? $this->vt4gConst['VT4G_LABEL_RENAME']['RAKUTEN']['REFUND']
  1399.                 : $recvType['LABEL'];
  1400.         $ret .= $record['mstatus'] == $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK'] ? '成立' '不成立';
  1401.         if (   $recvType['VALUE'] == $this->vt4gConst['VT4G_PAY_STATUS']['REFUND']['VALUE']
  1402.             && $record['mstatus'] != $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  1403.             $ret .= sprintf('(%s)',trans('vt4g_plugin.payment.recv.order.retry'));
  1404.         }
  1405.         $msg = <<<__EOS__
  1406. 決済取引ID : $orderId
  1407.   注文番号 : $orderNo
  1408.   要求結果 : $ret
  1409. __EOS__;
  1410.         return $msg;
  1411.     }
  1412.     /**
  1413.      * エラーとなった情報をメールで送信します。
  1414.      * @param array $arrHead 結果通知ヘッダー情報
  1415.      */
  1416.     public function sendErrorMail($arrHead)
  1417.     {
  1418.         $pushDateTime $this->util->toDate($arrHead['pushTime']);
  1419.         $errors implode(LF$this->errorMailMsg);
  1420.         $content $this->container->get('twig')->render(
  1421.             "VeriTrans4G2/Resource/template/default/Mail/vt4g_payment_recv_error.twig",
  1422.             [
  1423.                 'pluginName' => $this->vt4gConst['VT4G_SERVICE_NAME'],
  1424.                 'pushDateTime' => $pushDateTime,
  1425.                 'pushId' => $arrHead['pushId'],
  1426.                 'errors' => $errors
  1427.             ],
  1428.             'text/html'
  1429.             );
  1430.         $this->mdkLogger->debug(trans('vt4g_plugin.payment.recv.show.error_mail') .LF$content);
  1431.         $this->sendMail($this->vt4gConst['VT4G_SERVICE_NAME'] . $this->vt4gConst['VT4G_RECV_MAIL_SUBJECT']['ERROR'], $content);
  1432.         $this->mdkLogger->info(trans('vt4g_plugin.payment.recv.send.error_mail'));
  1433.     }
  1434.     /**
  1435.      * 楽天ペイの要求結果メールを送信します。
  1436.      * @param array $arrHead 結果通知ヘッダー情報
  1437.      */
  1438.     public function sendRakutenReqMail($arrHead)
  1439.     {
  1440.         $pushDateTime $this->util->toDate($arrHead['pushTime']);
  1441.         $msg implode(LF$this->rakutenMailMsg);
  1442.         $content $this->container->get('twig')->render(
  1443.             "VeriTrans4G2/Resource/template/default/Mail/vt4g_payment_recv_request_result.twig",
  1444.             [
  1445.                 'paymentName' => $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_60'],
  1446.                 'pushDateTime' => $pushDateTime,
  1447.                 'pushId' => $arrHead['pushId'],
  1448.                 'msg' => $msg
  1449.             ],
  1450.             'text/html'
  1451.             );
  1452.         $subject $this->vt4gConst['VT4G_SERVICE_NAME']
  1453.                   . '- '
  1454.                   $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_60']
  1455.                   . $this->vt4gConst['VT4G_RECV_MAIL_SUBJECT']['RESULT'];
  1456.         $this->sendMail($subject$content);
  1457.         $this->mdkLogger->info(trans('vt4g_plugin.payment.recv.send.request_mail'));
  1458.     }
  1459.     /**
  1460.      * コンビニ・ATM決済で入金となった注文をメール送信します。
  1461.      *
  1462.      */
  1463.     public function sendPaymentInfoMail()
  1464.     {
  1465.         $orders $this->em->getRepository(Order::class)->findBy(['order_no'=> $this->paymentInfoOrderNo]);
  1466.         $baseInfo $this->em->getRepository(BaseInfo::class)->get();
  1467.         $mailTemplate $this->em->getRepository(MailTemplate::class)->findOneBy(['name'=> $this->vt4gConst['VT4G_DTB_MAIL_TEMPLATE']['PAYMENT_INFO']['NAME']]);
  1468.         $htmlFileName $this->mailService->getHtmlTemplate($mailTemplate->getFileName());
  1469.         $configService $this->container->get('vt4g_plugin.service.admin.plugin.config');
  1470.         $subData $configService->getSubData();
  1471.         $subject '['.$baseInfo->getShopName().'] '.$mailTemplate->getMailSubject();
  1472.         foreach ($orders as $order) {
  1473.             $historyUrl is_null($order->getCustomer())
  1474.                         ? null
  1475.                         $this->container->get('router')->generate('mypage_history',['order_no' => $order->getOrderNo()],UrlGeneratorInterface::ABSOLUTE_URL);
  1476.             $body $this->twig->render($mailTemplate->getFileName(), [
  1477.                 'Order' => $order,
  1478.                 'historyUrl' => $historyUrl
  1479.             ]);
  1480.             if (!is_null($htmlFileName)) {
  1481.                 $htmlBody $this->twig->render($htmlFileName, [
  1482.                     'Order' => $order,
  1483.                     'historyUrl' => $historyUrl
  1484.                 ]);
  1485.             } else {
  1486.                 $htmlBody null;
  1487.             }
  1488.             $to $this->paymentInfoValues[$order->getOrderNo()] == $this->vt4gConst['VT4G_PAYMENT_INFO_MAIL']['TO']['CUSTOMER']
  1489.                 ? $order->getEmail()
  1490.                 : null;
  1491.             $this->mdkLogger->debug(trans('vt4g_plugin.payment.recv.show.payment_info') .LF$body);
  1492.             $this->sendMail($subject$body$htmlBody$baseInfo$subData$to);
  1493.             $this->mdkLogger->info(trans('vt4g_plugin.payment.recv.send.payment_info'));
  1494.         }
  1495.     }
  1496.     /**
  1497.      * メールを送信します。
  1498.      * @param string   $subject  件名
  1499.      * @param string   $body     本文(テキスト)
  1500.      * @param string   $htmlBody 本文(HTML)
  1501.      * @param array    $baseInfo 店舗情報
  1502.      * @param array    $subData  プラグイン設定情報
  1503.      * @param string   $to       送信先メールアドレス
  1504.      */
  1505.     private function sendMail($subject$body$htmlBody null$baseInfo null$subData null$to null)
  1506.     {
  1507.         // 基本情報取得
  1508.         if (is_null($baseInfo)) {
  1509.             $baseInfo $this->em->getRepository(BaseInfo::class)->get();
  1510.         }
  1511.         // メール送信クラス生成
  1512.         $message = (new Email())
  1513.         ->subject($subject)
  1514.         ->from(New Address($baseInfo->getEmail03(), $baseInfo->getShopName()))
  1515.         ->replyTo($baseInfo->getEmail04())
  1516.         ->returnPath($baseInfo->getEmail04())
  1517.         ->text($body);
  1518.         if (!is_null($htmlBody)) {
  1519.             $message->html($htmlBody);
  1520.         }
  1521.         if (is_null($subData)) {
  1522.             $configService $this->container->get('vt4g_plugin.service.admin.plugin.config');
  1523.             $subData $configService->getSubData();
  1524.         }
  1525.         $shopMail = !empty($subData['vt4g_email']) ? $subData['vt4g_email'] : $baseInfo->getEmail01();
  1526.         if (!is_null($to)) {
  1527.             $message->to($to)
  1528.             ->bcc($shopMail);
  1529.         } else {
  1530.             $message->to($shopMail);
  1531.         }
  1532.         $this->mailer->send($message);
  1533.     }
  1534.     /**
  1535.      * 注文情報に紐付くカート情報を削除します。
  1536.      * @param Order $order 注文情報
  1537.      */
  1538.     private function clearCartByOrder($order)
  1539.     {
  1540.         $cart $this->em
  1541.                 ->getRepository(Cart::class)
  1542.                 ->findOneBy(['Customer' => $order->getCustomer(),'pre_order_id' => $order->getPreOrderId()]);
  1543.         if (!empty($cart)) {
  1544.             $this->em->remove($cart);
  1545.             $this->em->flush($cart);
  1546.         }
  1547.     }
  1548.     /**
  1549.      * 決済情報に結果通知項目を登録します。
  1550.      * @param Vt4gOrderPayment $orderPayment 決済情報
  1551.      * @param array            $record       結果通知の項目
  1552.      */
  1553.     private function registPushRecord($orderPayment$record)
  1554.     {
  1555.         $memo09 = [];
  1556.         $records $orderPayment->getmemo09();
  1557.         if (!empty($records)) {
  1558.             $memo09 unserialize($records);
  1559.         }
  1560.         $memo09[] = $record;
  1561.         $orderPayment->setmemo09(serialize($memo09));
  1562.         $this->em->persist($orderPayment);
  1563.         $this->em->flush();
  1564.     }
  1565.     /**
  1566.      * 返金結果通知の設定値を取得します。
  1567.      *
  1568.      * @param  Vt4gOrderPayment $orderPayment 決済情報
  1569.      * @return array                          通知ごとの設定値
  1570.      */
  1571.     private function getRefundRecvSetting($orderPayment)
  1572.     {
  1573.         // 売上か減額要求中で返金、削除通知が来た場合は「返金通知」
  1574.         // それ以外で返金、削除通知が来た場合は「取消通知」とする
  1575.         switch ($orderPayment->getMemo04()) {
  1576.             case $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']:
  1577.             case $this->vt4gConst['VT4G_PAY_STATUS']['REDUCTION_REQUEST']['VALUE']:
  1578.                 return $this->vt4gConst['VT4G_PAY_STATUS']['REFUND']; // 返金結果
  1579.             default:
  1580.                 return $this->vt4gConst['VT4G_PAY_STATUS']['CANCEL']; // 取消結果
  1581.         }
  1582.     }
  1583.     /**
  1584.      * 決済ログとエラーメール用のメッセージを作成します。
  1585.      * @param  string $msg メッセージ
  1586.      * @return string      エラーメール用メッセージ
  1587.      */
  1588.     private function makeErrorMsg($msg)
  1589.     {
  1590.         $this->setLogInfo('結果通知エラー'$msg);
  1591.         $this->mdkLogger->info(sprintf(trans('vt4g_plugin.payment.recv.reason.error_mail'),$msg));
  1592.         return $msg.PHP_EOL;
  1593.     }
  1594.     /**
  1595.      * 継続課金注文・明細データの保存
  1596.      * @param  Object   $order  注文
  1597.      *
  1598.      * @return boolean
  1599.      */
  1600.     public function saveSubscOrder($order)
  1601.     {
  1602.         // 注文明細
  1603.         $order_items $order->getOrderItems();
  1604.         // 継続課金の販売種別の場合のみ保存
  1605.         $saleTypeId $order->getSaleTypes()[0]->getId();
  1606.         $subscSaleType $this->em->getRepository(Vt4gSubscSaleType::class)->findOneBy(['sale_type_id' => $saleTypeId]);
  1607.         if (is_null($subscSaleType)) {
  1608.             // 継続課金の販売種別でない場合は登録しない
  1609.             return false;
  1610.         }
  1611.         $order_id $order->getId();
  1612.         $customer_id $order->getCustomer()->getId();
  1613.         // 継続課金注文データが登録済みならスキップ
  1614.         $subscOrder $this->em->getRepository(Vt4gSubscOrder::class)->find($order_id);
  1615.         if (!empty($subscOrder)){
  1616.             return false;
  1617.         }
  1618.         // 決済センター戻りと結果通知を同時受信してデッドロックが発生したら、
  1619.         // 一方の通信の処理でデータが登録されるはずなので、次の処理に進む
  1620.         try {
  1621.             // 継続課金注文データの保存
  1622.             $subscOrder = new Vt4gSubscOrder();
  1623.             $subscOrder ->setOrderId($order_id)
  1624.                         ->setCustomerId($customer_id)
  1625.                         ->setSubscSaleTypeId($saleTypeId);
  1626.             $this->em->persist($subscOrder);
  1627.             $this->em->flush();
  1628.             // 継続課金注文明細データの保存
  1629.             $idxSubscOrderItem = [];
  1630.             foreach ($order_items as $oder_item) {
  1631.                 // 商品マスタ情報を保持している注文明細のみ保存する(送料などを除外する)
  1632.                 if ($puroduct $oder_item->getProduct()) {
  1633.                     $subscOrder = new Vt4gSubscOrderItem();
  1634.                     $puroduct_id $puroduct->getId();
  1635.                     $prod_class_id $oder_item->getProductClass()->getId();
  1636.                     $shipping_id $oder_item->getShipping()->getId();
  1637.                     $idx sprintf('%s-%s-%s-%s'$order_id$puroduct_id$prod_class_id$shipping_id);
  1638.                     if (in_array($idx$idxSubscOrderItem)) continue; // 重複した商品は登録しない
  1639.                     $idxSubscOrderItem[] = $idx;
  1640.                     $subscOrder ->setOrderId($order_id)
  1641.                                 ->setProductId($puroduct_id)
  1642.                                 ->setProductClassId($prod_class_id)
  1643.                                 ->setShippingId($shipping_id)
  1644.                                 ->setSubscStatus($this->vt4gConst['VTG4_SUBSC_STATUS_SUBSC']); // 継続
  1645.                     $this->em->persist($subscOrder);
  1646.                 }
  1647.             }
  1648.             $this->em->flush();
  1649.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.shopping.credit.saved.subsc.order'),$order_id));
  1650.         } catch (\Doctrine\DBAL\Exception $e) {
  1651.             $msg $e->getMessage();
  1652.             if(strpos($msg,'deadlock') !== false || strpos($msg,'Deadlock') !== false) {
  1653.                 $this->mdkLogger->info(sprintf(trans('vt4g_plugin.db.deadlock'),'結果通知の継続課金注文保存処理'));
  1654.             } else {
  1655.                 $this->mdkLogger->error($e->getMessage());
  1656.                 throw $e;
  1657.             }
  1658.         }
  1659.     }
  1660. }