app/Plugin/VeriTrans4G2/Service/Payment/CreditService.php line 1140

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 Eccube\Entity\Customer;
  8. use Eccube\Entity\Order;
  9. use Plugin\VeriTrans4G2\Entity\Vt4gOrderPayment;
  10. use Plugin\VeriTrans4G2\Entity\Vt4gSubscOrder;
  11. use Plugin\VeriTrans4G2\Entity\Vt4gSubscOrderItem;
  12. use Plugin\VeriTrans4G2\Entity\Master\Vt4gSubscSaleType;
  13. use Plugin\VeriTrans4G2\Entity\Master\Vt4gSubscProductOrderCmpMailInfo;
  14. use Plugin\VeriTrans4G2\Form\Type\Shopping\PaymentCreditType;
  15. use Plugin\VeriTrans4G2\Form\Type\Shopping\PaymentCreditAccountType;
  16. use Plugin\VeriTrans4G2\Form\Type\Shopping\PaymentCreditOneClickType;
  17. use tgMdk\TGMDK_Transaction;
  18. use tgMdk\dto\MpiGetResultRequestDto;
  19. use tgMdk\dto\CardCaptureRequestDto;
  20. use tgMdk\dto\CardAuthorizeRequestDto;
  21. use tgMdk\dto\CardReAuthorizeRequestDto;
  22. use tgMdk\dto\MpiAuthorizeRequestDto;
  23. use tgMdk\dto\MpiReAuthorizeRequestDto;
  24. use tgMdk\dto\CardRetryRequestDto;
  25. // クレジットカード決済関連処理
  26. class CreditService extends BaseService
  27. {
  28.     /**
  29.      * クレジットカード情報入力フォームを生成
  30.      * @param  array $paymentInfo クレジットカード決済設定
  31.      * @return object             クレジットカード情報入力フォーム
  32.      */
  33.     public function createCreditForm($paymentInfo)
  34.     {
  35.         return $this->container->get('form.factory')
  36.             ->create(PaymentCreditType::class, compact('paymentInfo'));
  37.     }
  38.     /**
  39.      * ベリトランス会員ID決済用の入力フォームを生成
  40.      *
  41.      * @param  array $paymentInfo クレジットカード決済設定
  42.      * @return object             ベリトランス会員ID決済用入力フォーム
  43.      */
  44.     public function createAccountForm($paymentInfo)
  45.     {
  46.         return $this->container->get('form.factory')
  47.             ->create(PaymentCreditAccountType::class, compact('paymentInfo'));
  48.     }
  49.     /**
  50.      * 再取引用の入力フォームを生成
  51.      *
  52.      * @param  array $paymentInfo クレジットカード決済設定
  53.      * @return object             再取引用入力フォーム
  54.      */
  55.     public function createOneClickForm($paymentInfo)
  56.     {
  57.         return $this->container->get('form.factory')
  58.             ->create(PaymentCreditOneClickType::class, compact('paymentInfo'));
  59.     }
  60.     /**
  61.      * クレジットカード決済処理
  62.      * (MDKトークン利用・再取引)
  63.      *
  64.      * @param  array   $inputs  フォーム入力データ
  65.      * @param  array   $payload 追加参照データ
  66.      * @param  array   &$error  エラー
  67.      * @return boolean          決済が正常終了したか
  68.      */
  69.     public function commitNormalPayment($inputs$payload, &$error)
  70.     {
  71.         // 本人認証フラグ
  72.         $isMpi $payload['paymentInfo']['mpi_flg'];
  73.         // ベリトランス会員ID決済の有効設定フラグ
  74.         $useAccountPayment $payload['paymentInfo']['one_click_flg'] === $this->vt4gConst['VT4G_CREDIT_ONE_CLICK']['VERITRANS_ID'];
  75.         // かんたん決済の有効設定フラグ
  76.         $useReTradePayment $payload['paymentInfo']['one_click_flg'] === $this->vt4gConst['VT4G_CREDIT_ONE_CLICK']['RETRADE'];
  77.         // ベリトランス会員ID決済フラグ
  78.         $isAccountPayment $payload['mode'] === 'account';
  79.         // 再取引フラグ
  80.         $isReTrade $payload['mode'] === 'retrade';
  81.         // 本人認証後フラグ
  82.         $isAfterAuth false;
  83.         // カード名義人名
  84.         switch ($payload['mode']) {
  85.             case 'token':
  86.                 $cardName = !empty($inputs['payment_credit']['card_name']) ? $inputs['payment_credit']['card_name'] : null;
  87.                 break;
  88.             case 'retrade':
  89.                 $cardName = !empty($inputs['payment_credit_one_click']['card_name']) ? $inputs['payment_credit_one_click']['card_name'] : null;
  90.                 break;
  91.             case 'account':
  92.                 $cardName = !empty($inputs['payment_credit_account']['card_name']) ? $inputs['payment_credit_account']['card_name'] : null;
  93.                 break;
  94.             default:
  95.                 $cardName null;
  96.                 break;
  97.         }
  98.         // 2023/1から3Dセキュアのバージョン切り替えを廃止。本人認証ありの場合は3Dセキュア2.0を利用。
  99.         $deviceChannel $this->vt4gConst['VT4G_CREDIT_DEVICE_CHANNEL'];
  100.         // 決済金額 (整数値で設定するため小数点以下切り捨て)
  101.         $amount floor($payload['order']->getPaymentTotal());
  102.         // 継続課金商品の判別
  103.         $subscSaleType $this->util->checkSubscriptionOrder($payload['order']); // 継続課金商品の判断 $subscSaleTypeがnullでなかったら継続課金商品
  104.         // 少額与信を使用の判別
  105.         $useFewCredit $this->util->checkFewCreditSaleType($subscSaleType); // 少額与信対象を判別
  106.         if ($subscSaleType) {
  107.             if ($useFewCredit) {
  108.                 // 継続課金商品かつ小額与信の場合は「与信のみ」設定に強制
  109.                 $payload['paymentInfo']['withCapture'] = 0;
  110.             }
  111.         }
  112.         if ($useFewCredit) {
  113.             // 少額与信を使用する場合は設定値で上書き
  114.             $amount $this->vt4gConst['VT4G_FEW_CREDIT_AMOUNT'];
  115.         }
  116.         // カード情報登録フラグ
  117.         $doRegistCardinfo $isAccountPayment || (isset($inputs['payment_credit']['cardinfo_regist']) && $inputs['payment_credit']['cardinfo_regist'] === '1');
  118.         // カード情報登録フラグ(再取引)
  119.         $doRegistReTradeCardinfo $isReTrade || (isset($inputs['payment_credit']['cardinfo_retrade']) && $inputs['payment_credit']['cardinfo_retrade'] === '1');
  120.         // 再取引決済の場合に元取引IDのバリデーションを行う
  121.         if ($isReTrade && !$this->isValidReTradeOrder($inputs['payment_order_id'], $payload['user']->getid())) {
  122.             $error['payment'] = trans('vt4g_plugin.shopping.credit.mErrMsg.retrade').'<br/>';
  123.             return false;
  124.         }
  125.         // MDKリクエスト生成・レスポンスのハンドリングに使用するデータ
  126.         $sources array_merge(
  127.             compact('isMpi'),
  128.             compact('useAccountPayment'),
  129.             compact('useReTradePayment'),
  130.             compact('isReTrade'),
  131.             compact('isAfterAuth'),
  132.             compact('amount'),
  133.             compact('inputs'),
  134.             compact('doRegistCardinfo'),
  135.             compact('doRegistReTradeCardinfo'),
  136.             compact('cardName'),
  137.             compact('deviceChannel'),
  138.             $payload
  139.         );
  140.         // MDKリクエストを生成
  141.         $mdkRequest $this->makeMdkRequest($sources);
  142.         $orderId $mdkRequest->getOrderId();
  143.         $sources['orderid'] = $orderId;
  144.         $cardType $inputs['payment_credit']['payment_type'] ?? '';
  145.         if ($isAccountPayment) {
  146.             $cardType $inputs['payment_credit_account']['payment_type'] ?? '';
  147.         }
  148.         if ($isReTrade) {
  149.             $cardType $inputs['payment_credit_one_click']['payment_type'] ?? '';
  150.         }
  151.         // 決済データを登録
  152.         $payment = [
  153.             'orderId'    => $orderId,
  154.             'payStatus'  => '',
  155.             'cardType'   => $cardType,
  156.             'cardAmount' => $amount,
  157.             'withCapture' => $payload['paymentInfo']['withCapture'],
  158.             'useFewCredit' => $useFewCredit// 少額与信の使用有無
  159.             'doRegistReTradeCardinfo' => $doRegistReTradeCardinfo,
  160.             'orderCompleteFlg' => false,
  161.             'sentOrderMail' => false,
  162.         ];
  163.         //本人認証ありの場合のみ、cardNameを登録する。
  164.         if($isMpi){
  165.             $payment['cardName'] = $cardName;
  166.         }
  167.         $this->setOrderPayment($payload['order'], $payload['orderPayment'], $payment, [], [], $inputs['token_id'] ?? '');
  168.         $this->em->commit();
  169.         $this->mdkLogger->info(
  170.             sprintf(
  171.                 $isMpi trans('vt4g_plugin.payment.shopping.mdk.start.mpi') : trans('vt4g_plugin.payment.shopping.mdk.start'),
  172.                 $this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_10']
  173.             )
  174.         );
  175.         $mdkTransaction = new TGMDK_Transaction();
  176.         $mdkResponse $mdkTransaction->execute($mdkRequest);
  177.         return $this->handleMdkResponse($mdkResponse$sources$error);
  178.     }
  179.     /**
  180.      * クレジットカード決済処理
  181.      * (本人認証リダイレクト)
  182.      *
  183.      * @param  object  $request リクエストデータ
  184.      * @param  array   $payload 追加参照データ
  185.      * @param  array   &$error  エラー
  186.      * @return boolean          決済が正常終了したか
  187.      */
  188.     public function commitMpiPayment($request$payload, &$error)
  189.     {
  190.         // ベリトランス会員ID決済フラグ
  191.         $useAccountPayment $payload['paymentInfo']['one_click_flg'] === $this->vt4gConst['VT4G_CREDIT_ONE_CLICK']['VERITRANS_ID'];
  192.         // オーダーID
  193.         $orderId htmlspecialchars($request->get('OrderId'));
  194.         if (empty($orderId)) {
  195.             $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.request.id'));
  196.             $error['payment'] = $this->getErrorMessage();
  197.             return false;
  198.         }
  199.         $mdkRequest = new MpiGetResultRequestDto();
  200.         // リクエスト実行
  201.         $mdkRequest->setOrderId($orderId);
  202.         $this->mdkLogger->info(trans('vt4g_plugin.payment.shopping.mpi.payment.start'));
  203.         $mdkTransaction = new TGMDK_Transaction();
  204.         $mdkResponse $mdkTransaction->execute($mdkRequest);
  205.         $sources = [
  206.             'isMpi'             => true,
  207.             'useAccountPayment' => $useAccountPayment,
  208.             'isAfterAuth'       => true,
  209.             'order'             => $payload['order'],
  210.             'paymentInfo'       => $payload['paymentInfo'],
  211.             'user'              => $payload['user'],
  212.             'orderPayment'      => $payload['orderPayment'],
  213.         ];
  214.         return $this->handleMdkResponse($mdkResponse$sources$error);
  215.     }
  216.     /**
  217.      * 売上処理
  218.      *
  219.      * @param  array $payload 売上処理に使用するデータ
  220.      * @return array          売上処理結果データ
  221.      */
  222.     public function operateCapture($payload)
  223.     {
  224.         // 注文ステータス
  225.         $orderStatus $payload['order']->getOrderStatus()['id'];
  226.         // 決済ステータス
  227.         $paymentStatus $payload['orderPayment']->getMemo04();
  228.         // 決済申込時のレスポンス
  229.         $prevPaymentResult unserialize($payload['orderPayment']->getMemo05());
  230.         // レスポンス初期化
  231.         $authOperationResult $this->initPaymentResult();
  232.         // 決済ステータスが売上の場合
  233.         if ($paymentStatus == $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']) {
  234.             // 現在の取引ID
  235.             $originPaymentOrderId $payload['orderPayment']->getMemo01();
  236.             // 決済ログ情報を初期化
  237.             $this->logData = [];
  238.             // 再決済
  239.             $authOperationResult $this->operateAuth($payload$this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']);
  240.             if (!$authOperationResult['isOK']) {
  241.                 $authOperationResult['message'] = $authOperationResult['vResultCode'].':'.$authOperationResult['mErrMsg'];
  242.                 $this->mdkLogger->info(print_r($authOperationResulttrue));
  243.                 return $authOperationResult;
  244.             }
  245.             // 更新処理
  246.             $this->updateByAdmin($payload['orderPayment'], $authOperationResult$orderStatus);
  247.             $this->em->flush();
  248.             $this->logData = [];
  249.             // 再決済後の取引ID
  250.             $newPaymentOrderId $authOperationResult['orderId'];
  251.             // 再決済前の取引を取消
  252.             $payload['orderPayment']->setMemo01($originPaymentOrderId);
  253.             $cancelOperationResult $this->operateCancel($payload);
  254.             // 再決済後の取引IDを再設定
  255.             $payload['orderPayment']->setMemo01($newPaymentOrderId);
  256.             // memo10更新
  257.             $memo10 unserialize($payload['orderPayment']->getMemo10());
  258.             $memo10['card_amount'] = floor($payload['order']->getPaymentTotal());
  259.             $payload['orderPayment']->setMemo10(serialize($memo10));
  260.             // キャンセル処理が異常終了の場合
  261.             if (!$cancelOperationResult['isOK']) {
  262.                 $this->mdkLogger->info(print_r($cancelOperationResulttrue));
  263.                 return $cancelOperationResult;
  264.             }
  265.             $this->mdkLogger->info(print_r($authOperationResulttrue));
  266.             return $authOperationResult;
  267.         }
  268.         $payId   $payload['orderPayment']->getMemo03();
  269.         $payName $this->util->getPayName($payId);
  270.         $this->mdkLogger->info(
  271.             sprintf(
  272.                 trans('vt4g_plugin.admin.order.credit.capture.start'),
  273.                 $payName
  274.             )
  275.         );
  276.         // レスポンス初期化
  277.         $operationResult $this->initPaymentResult();
  278.         // 取引ID
  279.         $paymentOrderId $payload['orderPayment']->getMemo01();
  280.         // memo01から取得できない場合
  281.         if (empty($paymentOrderId)) {
  282.             // 決済申込時のレスポンスから取得できない場合
  283.             if (empty($prevPaymentResult['orderId'])) {
  284.                 $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.order.id'));
  285.                 $operationResult['message'] = trans('vt4g_plugin.payment.shopping.error');
  286.                 return $operationResult;
  287.             }
  288.             // 決済申込時の結果から取得
  289.             $paymentOrderId $prevPaymentResult['orderId'];
  290.         }
  291.         $mdkRequest = new CardCaptureRequestDto();
  292.         // 取引ID
  293.         $mdkRequest->setOrderId($paymentOrderId);
  294.         // 決済金額
  295.         $mdkRequest->setAmount(floor($payload['order']->getPaymentTotal()));
  296.         $mdkTransaction = new TGMDK_Transaction();
  297.         $mdkResponse $mdkTransaction->execute($mdkRequest);
  298.         // レスポンス検証
  299.         if (!isset($mdkResponse)) {
  300.             $this->mdkLogger->fatal(trans('vt4g_plugin.payment.shopping.mdk.error'));
  301.             $operationResult['message'] = trans('vt4g_plugin.payment.shopping.error');
  302.             $this->mdkLogger->info(print_r($operationResulttrue));
  303.             return $operationResult;
  304.         }
  305.         // 結果コード
  306.         $operationResult['mStatus'] = $mdkResponse->getMStatus();
  307.         // 詳細コード
  308.         $operationResult['vResultCode'] = $mdkResponse->getVResultCode();
  309.         // エラーメッセージ
  310.         $operationResult['mErrMsg'] = $mdkResponse->getMErrMsg();
  311.         // 異常終了レスポンスの場合
  312.         if ($operationResult['mStatus'] === $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['NG']) {
  313.             $operationResult['message']  = $operationResult['vResultCode'].':';
  314.             $operationResult['message'] .= $operationResult['mErrMsg'];
  315.             $this->mdkLogger->info(print_r($operationResulttrue));
  316.             return $operationResult;
  317.         }
  318.         $operationResult['isOK']        = true;
  319.         // 取引ID
  320.         $operationResult['orderId']     = $mdkResponse->getOrderId();
  321.         // 決済サービスタイプ
  322.         $operationResult['payStatus']   = $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE'];
  323.         // 売上金額
  324.         $amount floor($payload['order']->getPaymentTotal());
  325.         $operationResult['card_amount'] = $amount;
  326.         // 決済変更ログ情報を設定
  327.         $this->logData = [];
  328.         $this->setLog($payload['order'], $operationResult);
  329.         // 変更後の金額をログ出力
  330.         $amount number_format($amount);
  331.         $this->setLogInfo('売上確定金額'$amount);
  332.         $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.order.id'). $operationResult['orderId']);
  333.         $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.capture.amount'). $amount);
  334.         // ログの出力
  335.         $this->mdkLogger->info(print_r($operationResulttrue));
  336.         return $operationResult;
  337.     }
  338.     /**
  339.      * 決済処理の実行
  340.      *
  341.      * @param  array $payload 決済に使用するデータ
  342.      * @return array          決済結果データ
  343.      */
  344.     public function operateNewly($payload)
  345.     {
  346.         $payId $payload['orderPayment']->getMemo03();
  347.         $payName $this->util->getPayName($payId);
  348.         $accountCardId $payload['inputs']->get('accountCardId');
  349.         $reTradeOrderId $payload['inputs']->get('reTradeOrderId');
  350.         $jpo $payload['inputs']->get('jpo');
  351.         $withCapture $payload['inputs']->get('withCapture');
  352.         $this->mdkLogger->info(
  353.             sprintf(
  354.                 trans('vt4g_plugin.admin.order.credit.newly.start'),
  355.                 $payName
  356.             )
  357.         );
  358.         // レスポンス初期化
  359.         $operationResult $this->initPaymentResult();
  360.         if ((empty($accountCardId) && empty($reTradeOrderId)) || (!empty($accountCardId) && !empty($reTradeOrderId))
  361.             || empty($jpo) || !($withCapture === '0' || $withCapture === '1')) {
  362.             $this->mdkLogger->fatal(
  363.                 sprintf(
  364.                     trans('vt4g_plugin.admin.order.credit.param.error'),
  365.                     $accountCardId,
  366.                     $reTradeOrderId,
  367.                     $jpo,
  368.                     $withCapture
  369.                     )
  370.                 );
  371.             $operationResult['message'] = trans('vt4g_plugin.admin.order.update_payment_status.error');
  372.             return $operationResult;
  373.         }
  374.         $mdkRequest = ($accountCardId) ? new CardAuthorizeRequestDto() : new CardReAuthorizeRequestDto();
  375.         $mdkRequest->setOrderId($this->getMdkOrderId($payload['order']->getid()));
  376.         $mdkRequest->setAmount(floor($payload['order']->getPaymentTotal()));
  377.         $mdkRequest->setJpo($jpo);
  378.         $mdkRequest->setWithCapture($withCapture 'true' 'false');
  379.         if ($accountCardId) {
  380.             $mdkRequest->setCardId($accountCardId);
  381.             $mdkRequest->setAccountId($payload['order']->getCustomer()->vt4g_account_id);
  382.         } else {
  383.             $mdkRequest->setOriginalOrderId($reTradeOrderId);
  384.         }
  385.         $mdkTransaction = new TGMDK_Transaction();
  386.         $mdkResponse $mdkTransaction->execute($mdkRequest);
  387.         // レスポンス検証
  388.         if (!isset($mdkResponse)) {
  389.             $this->mdkLogger->fatal(trans('vt4g_plugin.payment.shopping.mdk.error'));
  390.             $operationResult['message'] = trans('vt4g_plugin.payment.shopping.error');
  391.             return $operationResult;
  392.         }
  393.         // 結果コード
  394.         $operationResult['mStatus'] = $mdkResponse->getMStatus();
  395.         // 詳細コード
  396.         $operationResult['vResultCode'] = $mdkResponse->getVResultCode();
  397.         // エラーメッセージ
  398.         $operationResult['mErrMsg'] = $mdkResponse->getMErrMsg();
  399.         // 異常終了レスポンスの場合
  400.         if ($operationResult['mStatus'] !== $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  401.             $operationResult['message']  = $operationResult['vResultCode'].':';
  402.             $operationResult['message'] .= $operationResult['mErrMsg'];
  403.             return $operationResult;
  404.         }
  405.         // 通常クレジットカード決済の正常終了
  406.         $operationResult['isOK'] = true;
  407.         // 取引ID取得
  408.         $operationResult['orderId'] = $mdkResponse->getOrderId();
  409.         // マスクされたクレジットカード番号
  410.         $operationResult['cardNumber'] = null;
  411.         // 入力したカード名義
  412.         $operationResult['lastName'] = null;
  413.         $operationResult['firstName'] = null;
  414.         $operationResult['paymentType'] = substr($jpo02);
  415.         $operationResult['paymentCount'] = substr($jpo2);
  416.         // memo10
  417.         $operationResult['card_amount'] = floor($payload['order']->getPaymentTotal());
  418.         $operationResult['card_type'] = $jpo;
  419.         // memo02
  420.         $operationResult['customerId'] = $payload['order']->getCustomer()->getId();
  421.         // 決済状態を保持
  422.         $operationResult['payStatus'] = $withCapture
  423.             $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']
  424.             : $this->vt4gConst['VT4G_PAY_STATUS']['AUTH']['VALUE'];
  425.         $operationResult['mpiHosting'] = false;
  426.         $operationResult['withCapture'] = $withCapture;
  427.         // 決済変更ログ情報を設定
  428.         $this->logData = [];
  429.         $this->setLog($payload['order'], $operationResult);
  430.         // 変更後の金額をログ出力
  431.         $amount number_format(floor($payload['order']->getPaymentTotal()));
  432.         $this->setLogInfo('売上確定金額'$amount);
  433.         // ログの出力
  434.         $this->mdkLogger->info(print_r($operationResulttrue));
  435.         return $operationResult;
  436.     }
  437.     /**
  438.      * キャンセル処理
  439.      *
  440.      * @param  array $payload キャンセル処理に使用するデータ
  441.      * @return array          キャンセル処理結果データ
  442.      */
  443.     public function operateCancel($payload)
  444.     {
  445.         // キャンセル共通処理
  446.         list($operationResult$mdkResponse) = parent::operateCancel($payload);
  447.         // 取消処理の場合、継続課金ステータスを解約にする(再売上時の前決済取消時は決済ステータスは売上のままなのでスキップ)
  448.         // 取消操作の場合
  449.         if ($this->vt4gConst['VT4G_OPERATION_CANCEL'] === $payload['mode']) {
  450.             // 継続課金ステータスを解約に更新
  451.             $subscOrderItems $this->em->getRepository(Vt4gSubscOrderItem::class)->findBy(['order_id' => $payload['order']->getId()]);
  452.             if (count($subscOrderItems) > 0) {
  453.                 // 継続課金の注文の場合(ここではflushしない)
  454.                 foreach ($subscOrderItems as $item) {
  455.                     $item->setSubscStatus($this->vt4gConst['VTG4_SUBSC_STATUS_CANCEL']);
  456.                 }
  457.             }
  458.         }
  459.         // ログの出力
  460.         $this->mdkLogger->info(print_r($operationResulttrue));
  461.         if ($operationResult['isOK']) {
  462.             $amount number_format($mdkResponse->getReqAmount());
  463.             $this->setLogInfo('取消金額'$amount);
  464.             $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.order.id'). $operationResult['orderId']);
  465.             $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.cancel.amount'). $amount);
  466.         }
  467.         return $operationResult;
  468.     }
  469.     /**
  470.      * 再決済処理
  471.      *
  472.      * @param  array   $payload       再決済処理に使用するデータ
  473.      * @param  integer $paymentStatus 決済ステータス
  474.      * @return array                  再決済処理結果データ
  475.      */
  476.     public function operateAuth($payload$paymentStatus)
  477.     {
  478.         $paymentId   $payload['order']->getPayment()->getId();
  479.         $payId       $payload['orderPayment']->getMemo03();
  480.         $payName     $this->util->getPayName($payId);
  481.         $paymentInfo $this->util->getPaymentMethodInfo($paymentId);
  482.         // 決済申込時のレスポンス
  483.         $prevPaymentResult unserialize($payload['orderPayment']->getMemo05());
  484.         // レスポンス初期化
  485.         $operationResult $this->initPaymentResult();
  486.         $this->mdkLogger->info(
  487.             sprintf(
  488.                 trans('vt4g_plugin.admin.order.credit.again.start'),
  489.                 $payName
  490.             )
  491.         );
  492.         // 再決済対象の取引ID
  493.         $paymentOrderId $payload['orderPayment']->getMemo01();
  494.         // memo01から取得できない場合
  495.         if (empty($paymentOrderId)) {
  496.             // 決済申込時のレスポンスから取得できない場合
  497.             if (empty($prevPaymentResult['orderId'])) {
  498.                 $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.order.id'));
  499.                 $operationResult['message'] = trans('vt4g_plugin.payment.shopping.error');
  500.                 return $operationResult;
  501.             }
  502.             // 決済申込時の結果から取得
  503.             $paymentOrderId $prevPaymentResult['orderId'];
  504.         }
  505.         // 支払回数
  506.         $memo10 unserialize($payload['orderPayment']->getMemo10());
  507.         $cardType $memo10['card_type'];
  508.         $mdkRequest = new CardReAuthorizeRequestDto();
  509.         // 取引ID
  510.         $mdkRequest->setOrderId($this->getMdkOrderId($payload['order']->getid()));
  511.         // 再決済対象の取引ID
  512.         $mdkRequest->setOriginalOrderId($paymentOrderId);
  513.         // 決済金額
  514.         $mdkRequest->setAmount(floor($payload['order']->getPaymentTotal()));
  515.         // 支払回数
  516.         $mdkRequest->setJpo($cardType);
  517.         // 売上フラグ
  518.         if ($paymentStatus == $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']) {
  519.             $mdkRequest->setWithCapture('true');
  520.         } else {
  521.             $mdkRequest->setWithCapture($paymentInfo['withCapture'] ? 'true' 'false');
  522.         }
  523.         $mdkTransaction = new TGMDK_Transaction();
  524.         $mdkResponse $mdkTransaction->execute($mdkRequest);
  525.         $operationResult['payStatus'] = $paymentStatus;
  526.         // レスポンス検証
  527.         if (!isset($mdkResponse)) {
  528.             $this->mdkLogger->fatal(trans('vt4g_plugin.payment.shopping.mdk.error'));
  529.             $operationResult['message'] = trans('vt4g_plugin.payment.shopping.error');
  530.             return $operationResult;
  531.         }
  532.         // 結果コード
  533.         $operationResult['mStatus'] = $mdkResponse->getMStatus();
  534.         // 詳細コード
  535.         $operationResult['vResultCode'] = $mdkResponse->getVResultCode();
  536.         // エラーメッセージ
  537.         $operationResult['mErrMsg'] = $mdkResponse->getMErrMsg();
  538.         // 異常終了レスポンスの場合
  539.         if ($operationResult['mStatus'] === $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['NG']) {
  540.             $operationResult['message']  = $operationResult['vResultCode'].':';
  541.             $operationResult['message'] .= $operationResult['mErrMsg'];
  542.             $this->mdkLogger->info(print_r($operationResulttrue));
  543.             return $operationResult;
  544.         }
  545.         $operationResult['isOK']        = true;
  546.         // 取引ID
  547.         $operationResult['orderId']     = $mdkResponse->getOrderId();
  548.         // 決済サービスタイプ
  549.         $operationResult['serviceType'] = $mdkResponse->getServiceType();
  550.         // 決済ステータス
  551.         $operationResult['payStatus']   = $paymentStatus;
  552.         // 決済金額
  553.         $amount floor($payload['order']->getPaymentTotal());
  554.         $operationResult['card_amount'] = $amount;
  555.         // 取引IDを更新
  556.         $orderPayment $this->em->getRepository(vt4gOrderPayment::class)->find($payload['order']->getId());
  557.         $orderPayment->setMemo01($operationResult['orderId']);
  558.         $this->em->flush();
  559.         // 決済変更ログ情報を設定
  560.         $this->setLog($payload['order'], $operationResult);
  561.         // 変更後の金額をログ出力
  562.         $amount number_format($amount);
  563.         $this->setLogInfo('再取引金額'$amount);
  564.         $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.order.id'). $operationResult['orderId']);
  565.         $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.again.amount'). $amount);
  566.         $this->mdkLogger->info(print_r($operationResulttrue));
  567.         return $operationResult;
  568.     }
  569.     /**
  570.      * MDKリクエストを生成
  571.      *
  572.      * @param  array  &$sources リクエスト生成に必要なデータ
  573.      * @return object           MDKリクエストオブジェクト
  574.      */
  575.     private function makeMdkRequest(&$sources)
  576.     {
  577.         if ($sources['isMpi']) {
  578.             $request $sources['isReTrade']
  579.                 ? new MpiReAuthorizeRequestDto() // 本人認証あり (再取引)
  580.                 : new MpiAuthorizeRequestDto();  // 本人認証あり
  581.         } else {
  582.             $request $sources['isReTrade']
  583.                 ? new CardReAuthorizeRequestDto() // 本人認証なし (再取引)
  584.                 : new CardAuthorizeRequestDto();  // 本人認証なし
  585.         }
  586.         // 受注番号
  587.         $request->setOrderId($this->getMdkOrderId($sources['order']->getId()));
  588.         $request->setAmount($sources['amount']);
  589.         // 再取引の場合
  590.         if ($sources['isReTrade']) {
  591.             // 元取引ID
  592.             $request->setOriginalOrderId($sources['inputs']['payment_order_id']);
  593.             // 支払い方法
  594.             $request->setJpo($sources['inputs']['payment_credit_one_click']['payment_type']);
  595.         } else {
  596.             // ベリトランス会員ID決済利用の場合
  597.             if ($sources['useAccountPayment'] && !empty($sources['user']) && $sources['doRegistCardinfo']) {
  598.                 $accountId $this->getAccountId($sources['user'], $sources['order']->getPayment()->getId());
  599.                 // ベリトランス会員ID情報をログ出力
  600.                 $this->mdkLogger->info((empty($sources['user']->vt4g_account_id)
  601.                                         ? trans('vt4g_plugin.shopping.credit.account.payment.new')
  602.                                         : trans('vt4g_plugin.shopping.credit.account.payment')
  603.                                         )
  604.                                         .$accountId);
  605.                 // ベリトランス会員ID
  606.                 $request->setAccountId($accountId);
  607.                 // 仮登録フラグによりMPIのレスポンスは会員情報が空になるので、MPIのときはここの値を使用する
  608.                 $sources['accountId'] = $accountId;
  609.             }
  610.             // 登録済みのカードを使用する場合
  611.             if ($sources['mode'] === 'account') {
  612.                 $cardId $sources['inputs']['card_id'];
  613.                 $this->mdkLogger->info(trans('vt4g_plugin.shopping.credit.account.card').$cardId);
  614.                 // カードID
  615.                 $request->setCardId($cardId);
  616.                 // 支払い方法
  617.                 $request->setJpo($sources['inputs']['payment_credit_account']['payment_type']);
  618.             } else {
  619.                 // トークン情報をログ出力
  620.                 $this->mdkLogger->info(
  621.                     sprintf(
  622.                         trans('vt4g_plugin.shopping.credit.token'),
  623.                         $sources['inputs']['token_id'],
  624.                         $sources['inputs']['token_expire_date']
  625.                     )
  626.                 );
  627.                 // MDKトークン
  628.                 $request->setToken($sources['inputs']['token_id']);
  629.                 // 支払い方法
  630.                 $request->setJpo($sources['inputs']['payment_credit']['payment_type']);
  631.             }
  632.         }
  633.         // 決済種別
  634.         $request->setWithCapture($sources['paymentInfo']['withCapture'] ? 'true' 'false');
  635.         // 本人認証の場合
  636.         if ($sources['isMpi']) {
  637.             $request->setServiceOptionType($sources['paymentInfo']['mpi_option']);
  638.             // URL設定
  639.             $redirectionUri $this->util->generateUrl(
  640.                 'vt4g_shopping_payment',
  641.                 ['mode' => 'comp']
  642.             );
  643.             $request->setRedirectionUri($redirectionUri);
  644.             $pluginSetting $this->util->getPluginSetting();
  645.             if(!empty($pluginSetting["push_url_auto_setting"])){
  646.                 $request->setPushUrl($this->util->generateUrl('vt4g_plugin_shopping_payment_recv'));
  647.             }
  648.             $request->setHttpUserAgent($_SERVER['HTTP_USER_AGENT']);
  649.             $request->setHttpAccept($_SERVER['HTTP_ACCEPT']);
  650.             $request->setVerifyTimeout($this->vt4gConst['VT4G_CREDIT_VERIFY_TIMEOUT']);
  651.             $request->setCardholderName($sources['cardName']);
  652.             $request->setDeviceChannel($sources['deviceChannel']);
  653.             $request->setVerifyResultLink($this->vt4gConst['VT4G_CREDIT_VERIFY_RESULT_LINK']);
  654.             // 仮登録フラグの設定
  655.             if ($sources['useAccountPayment'] && !empty($sources['user']) && $sources['mode'] != 'account') {
  656.                 $request->setTempRegistration($this->vt4gConst['VT4G_CREDIT_PAYNOWID_TEMP_REG']);
  657.             }
  658.         }
  659.         return $request;
  660.     }
  661.     /**
  662.      * MDKリクエストのレスポンスのハンドリング
  663.      * (各パターン共通処理)
  664.      *
  665.      * @param  object  $response MDKリクエストのレスポンス
  666.      * @param  array   $sources  ハンドリングに必要なデータ
  667.      * @param  array   &$error   エラー表示用配列
  668.      * @return boolean           レスポンスを正常に処理したかどうか
  669.      */
  670.     private function handleMdkResponse($response$sources, &$error)
  671.     {
  672.         // レスポンス初期化
  673.         $this->initPaymentResult();
  674.         // レスポンス検証
  675.         if (!isset($response)) {
  676.             // システムエラー
  677.             $this->mdkLogger->fatal(trans('vt4g_plugin.payment.shopping.mdk.error'));
  678.             $error['payment'] = $this->getErrorMessage();
  679.             return false;
  680.         }
  681.         // 結果コード
  682.         $this->paymentResult['mStatus'] = $response->getMStatus();
  683.         // 詳細コード
  684.         $this->paymentResult['vResultCode'] = $response->getVResultCode();
  685.         // エラーメッセージ
  686.         $this->paymentResult['mErrMsg'] = $response->getMerrMsg();
  687.         // 異常終了レスポンスの場合
  688.         if ($this->paymentResult['mStatus'] === $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['NG']) {
  689.             $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.payment'));
  690.             $this->mdkLogger->fatal(print_r($this->paymentResulttrue));
  691.             $error['payment'] = $this->getErrorMessage();
  692.             return false;
  693.         }
  694.         // 本人認証なし かつ 保留レスポンスの場合
  695.         if (!$sources['isMpi'] && $this->paymentResult['mStatus'] === $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['PENDING']) {
  696.             // リトライを実行
  697.             $retryResult $this->retryMdkRequest($sources['orderId'], $error);
  698.             if (!$retryResult) {
  699.                 $error['payment'] = $this->getErrorMessage();
  700.                 return false;
  701.             }
  702.             // リトライのレスポンスを使用
  703.             $response $retryResult;
  704.         }
  705.         // 本人認証ありの場合
  706.         if ($sources['isMpi']) {
  707.             return $sources['isAfterAuth']
  708.                 ? $this->handleMpiAfterAuthResponse($response$sources$error)
  709.                 : $this->handleMpiBeforeAuthResponse($response$sources);
  710.         }
  711.         // 本人認証なしの場合
  712.         return $this->handleNormalResponse($response$sources$error);
  713.     }
  714.     /**
  715.      * MDKリクエストのレスポンスのハンドリング
  716.      * (本人認証なしパターン)
  717.      *
  718.      * @param  object  $response MDKリクエストのレスポンス
  719.      * @param  array   $sources  ハンドリングに必要なデータ
  720.      * @param  array   &$error   エラー表示用配列
  721.      * @return boolean           レスポンスを正常に処理したかどうか
  722.      */
  723.     private function handleNormalResponse($response$sources, &$error)
  724.     {
  725.         // 通常クレジットカード決済の正常終了
  726.         $this->paymentResult['isOK'] = true;
  727.         // 取引ID取得
  728.         $this->paymentResult['orderId'] = $response->getOrderId();
  729.         // マスクされたクレジットカード番号
  730.         $this->paymentResult['cardNumber'] = $response->getReqCardNumber();
  731.         // 支払い方法・支払い回数
  732.         $jpo $response->getReqJpoInformation();
  733.         $this->paymentResult['paymentType'] = substr($jpo02);
  734.         $this->paymentResult['paymentCount'] = substr($jpo2);
  735.         // 決済状態を保持
  736.         $this->paymentResult['payStatus'] = $sources['paymentInfo']['withCapture']
  737.             ? $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']
  738.             : $this->vt4gConst['VT4G_PAY_STATUS']['AUTH']['VALUE'];
  739.         $this->paymentResult['mpiHosting'] = false;
  740.         $this->paymentResult['withCapture'] = $sources['paymentInfo']['withCapture'];
  741.         $this->mdkLogger->info(print_r($this->paymentResulttrue));
  742.         // 正常終了の場合
  743.         if ($this->paymentResult['isOK']) {
  744.             // 継続課金注文・明細データの保存
  745.             $this->saveSubscOrder($sources);
  746.             // ベリトランス会員ID決済の場合
  747.             if ($sources['useAccountPayment'] && !empty($sources['user']) && $sources['doRegistCardinfo']) {
  748.                 // ベリトランス会員IDをテーブルに保存
  749.                 $accountId $response->getPayNowIdResponse()->getAccount()->getAccountId();
  750.                 $this->saveAccountId($sources['user']->getId(), $accountId);
  751.             }
  752.             if (!$sources['doRegistReTradeCardinfo']) {
  753.                 // ベリトランスID決済, 利用無し, かんたん決済にて「利用しない」選択時にカード番号を未登録とする
  754.                 $this->paymentResult['cardNumber'] = null;
  755.             }
  756.             $isCompleted $this->completeCreditOrder($sources['order'], $sources['orderPayment']);
  757.             // 受注完了処理
  758.             if (!$isCompleted) {
  759.                 $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.complete'));
  760.                 $error['payment'] = $this->defaultErrorMessage;
  761.                 return false;
  762.             }
  763.         }
  764.         return true;
  765.     }
  766.     /**
  767.      * MDKリクエストのレスポンスのハンドリング
  768.      * (本人認証あり・認証ページへのリダイレクト前処理)
  769.      *
  770.      * @param  object  $response MDKリクエストのレスポンス
  771.      * @param  array   $sources  ハンドリングに必要なデータ
  772.      * @return void
  773.      */
  774.     private function handleMpiBeforeAuthResponse($response$sources)
  775.     {
  776.         // ベリトランス会員ID決済の場合
  777.         if ($sources['useAccountPayment'] && !empty($sources['user']) && !empty($sources['accountId'])) {
  778.             // ベリトランス会員IDをセッションに保存
  779.             $accountId $sources['accountId'];
  780.             $this->container->get('session')->set(
  781.                 $this->vt4gConst['VT4G_CREDIT_VERITRANS_ID_SESSION_KEY'],
  782.                 $accountId
  783.             );
  784.         }
  785.         $limitDate = new \DateTime();
  786.         $limitDate $limitDate->modify(sprintf('+%s minutes'$this->vt4gConst['VT4G_CREDIT_VERIFY_TIMEOUT']));
  787.         $rollbackDate $this->util->getRollbackDate($limitDate->format('Y-m-d H:i:s'), $this->vt4gConst['VT4G_PAYTYPEID_CREDIT']);
  788.         $orderPayment $sources['orderPayment'];
  789.         $orderPayment->setRollbackDate($rollbackDate);
  790.         //カード情報の登録
  791.         if($sources['doRegistReTradeCardinfo']){
  792.             $orderPayment->setMemo07($response->getReqCardNumber());
  793.         }
  794.         $this->paymentResult['isOK'] = true;
  795.         $this->paymentResult['orderId'] = $response->getOrderId();
  796.         $this->paymentResult['cardNumber'] = $response->getReqCardNumber();
  797.         $jpo $response->getReqJpoInformation();
  798.         $this->paymentResult['paymentType'] = substr($jpo02);
  799.         $this->paymentResult['paymentCount'] = substr($jpo2);
  800.         $this->paymentResult['mpiHosting'] = 1;
  801.         $this->paymentResult['isMpi'] = true;
  802.         $this->paymentResult['withCapture'] = $sources['paymentInfo']['withCapture'];
  803.         $this->paymentResult['resResponseContents'] = $response->getResResponseContents();
  804.         $this->paymentResult['rollbackDate'] = $rollbackDate;
  805.         $this->mdkLogger->info(print_r($this->paymentResulttrue));
  806.         // データ登録時にrollbackDateのタイムゾーンが変更されるので、ログ出力後にデータ登録を実行
  807.         // @see https://doc4.ec-cube.net/i18n_timezone
  808.         $this->em->persist($orderPayment);
  809.         $this->em->flush();
  810.         $this->em->commit();
  811.         // 認証ページ用レスポンスを表示して処理を終了
  812.         echo $this->paymentResult['resResponseContents'];
  813.         exit;
  814.     }
  815.     /**
  816.      * MDKリクエストのレスポンスのハンドリング
  817.      * (本人認証あり・認証ページからのリダイレクト後処理)
  818.      *
  819.      * @param  object  $response MDKリクエストのレスポンス
  820.      * @param  array   $sources  ハンドリングに必要なデータ
  821.      * @param  array   &$error   エラー表示用配列
  822.      * @return boolean           レスポンスを正常に処理したかどうか
  823.      */
  824.     private function handleMpiAfterAuthResponse($response$sources, &$error)
  825.     {
  826.         // 対象が見つからなかった場合
  827.         if (is_null($response)) {
  828.             $this->initPaymentResult();
  829.             $this->paymentResult['mErrMsg'] = trans('vt4g_plugin.shopping.credit.mErrMsg.transaction');
  830.             $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.mpi.payment'));
  831.             $error['payment'] = $this->getErrorMessage();
  832.             return false;
  833.         }
  834.         // 結果コード
  835.         $this->paymentResult['mStatus'] = $response->getMStatus();
  836.         // 詳細コード 決済の詳細結果コードに応じたエラーメッセージを出力のために一時的に変える
  837.         $this->paymentResult['vResultCode'] = $response->getMpiVResultCode();
  838.         // カード結果コード
  839.         $this->paymentResult['cardMstatus'] = $response->getCardMstatus();
  840.         // MPI 結果コード
  841.         $this->paymentResult['mpiMstatus'] = $response->getMpiMstatus();
  842.         // MPI 詳細コード
  843.         $this->paymentResult['mpiVresultCode'] = $response->getMpiVResultCode();
  844.         // 本人認証の結果検証
  845.         if ($this->paymentResult['mpiMstatus'] !== $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  846.             $this->paymentResult['mErrMsg'] = trans('vt4g_plugin.shopping.credit.mErrMsg.mpi.payment');
  847.             $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.mpi.payment'));
  848.             $error['payment'] = $this->getErrorMessage();
  849.             return false;
  850.         }
  851.         // カード決済の結果検証
  852.         if ($this->paymentResult['cardMstatus'] !== $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  853.             $this->paymentResult['mErrMsg'] = trans('vt4g_plugin.shopping.credit.mErrMsg.credit.payment');
  854.             $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.credit.payment'));
  855.             $error['payment'] = $this->getErrorMessage();
  856.             return false;
  857.         }
  858.         // 詳細コード 一時的に変更していたものを元に戻す
  859.         $this->paymentResult['vResultCode'] = $response->getVResultCode();
  860.         $withCapture $this->getWithCapture($sources['order']);
  861.         // プラグインver.1.0.0で登録した決済が本人認証から戻ってきた場合は
  862.         // 決済情報に処理区分が無いので、代わりに設定画面の値を使用する
  863.         if (is_null($withCapture)) {
  864.             $withCapture $sources['paymentInfo']['withCapture'];
  865.         }
  866.         // 正常終了
  867.         $this->paymentResult['isOK'] = true;
  868.         $this->paymentResult['mErrMsg'] = '';
  869.         $this->paymentResult['orderId'] = $response->getOrderId();
  870.         $orderPayment $sources['orderPayment'];
  871.         $memo10 unserialize($orderPayment->getMemo10());
  872.         $card_type $memo10['card_type'];
  873.         $this->paymentResult['paymentType'] = substr($card_type02);
  874.         $this->paymentResult['paymentCount'] = substr($card_type2);
  875.         $this->paymentResult['payStatus'] = $withCapture
  876.             $this->vt4gConst['VT4G_PAY_STATUS']['CAPTURE']['VALUE']
  877.             : $this->vt4gConst['VT4G_PAY_STATUS']['AUTH']['VALUE'];
  878.         $this->paymentResult['mpiHosting'] = true;
  879.         $this->paymentResult['withCapture'] = $withCapture;
  880.         $this->mdkLogger->info(print_r($this->paymentResulttrue));
  881.         // 正常終了の場合
  882.         if ($this->paymentResult['isOK']) {
  883.             // 継続課金注文・明細データの保存
  884.             $this->saveSubscOrder($sources);
  885.             // ベリトランス会員ID決済の場合
  886.             if ($sources['useAccountPayment']) {
  887.                 $session $this->container->get('session');
  888.                 $sessionKey $this->vt4gConst['VT4G_CREDIT_VERITRANS_ID_SESSION_KEY'];
  889.                 // セッションにベリトランス会員IDが保存されている場合
  890.                 if ($session->has($sessionKey)) {
  891.                     // ベリトランス会員IDをテーブルに保存
  892.                     $this->saveAccountId($sources['user']->getId(), $session->get($sessionKey));
  893.                     // セッションから削除
  894.                     $session->remove($sessionKey);
  895.                 }
  896.             }
  897.             $isCompleted $this->completeCreditOrder($sources['order'], $orderPayment);
  898.             // 受注完了処理
  899.             if (!$isCompleted) {
  900.                 $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.complete'));
  901.                 $error['payment'] = $this->getErrorMessage();
  902.                 return false;
  903.             }
  904.         }
  905.         return true;
  906.     }
  907.     /**
  908.      * MDKリクエストのリトライを実行
  909.      *
  910.      * @param  string      $orderId 取引ID
  911.      * @param  array       &$error  画面表示用エラー配列
  912.      * @return object|null          リトライレスポンス(異常終了の場合にnull)
  913.      */
  914.     private function retryMdkRequest($orderId, &$error)
  915.     {
  916.         $isSucceeeded false;
  917.         for ($count 0$count $this->vt4gConst['VT4G_REQUEST']['CREDIT']['RETRY_LIMIT']; $count++) {
  918.             // インターバル
  919.             sleep($this->vt4gConst['VT4G_REQUEST']['CREDIT']['RETRY_WAIT']);
  920.             $this->mdkLogger->info(trans('vt4g_plugin.payment.shopping.mdk.restart'));
  921.             $mdkRequest = new CardRetryRequestDto();
  922.             $mdkRequest->setOrderId($orderId);
  923.             $mdkTransaction = new TGMDK_Transaction();
  924.             $mdkResponse $mdkTransaction->execute($mdkRequest);
  925.             // 異常終了の場合
  926.             if (!isset($mdkResponse)) {
  927.                 $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.restart'));
  928.                 $error['payment'] = $this->getErrorMessage();
  929.                 return null;
  930.             }
  931.             $this->paymentResult['mStatus']     = $mdkResponse->getMStatus();
  932.             $this->paymentResult['vResultCode'] = $mdkResponse->getVResultCode();
  933.             $this->paymentResult['mErrMsg']     = $mdkResponse->getMerrMsg();
  934.             // 正常終了の場合
  935.             if ($mdkResponse->getMStatus() === $this->vt4gConst['VT4G_RESPONSE']['MSTATUS']['OK']) {
  936.                 $isSucceeeded true;
  937.                 break;
  938.             }
  939.         }
  940.         // リトライが全部失敗した場合
  941.         if (!$isSucceeeded) {
  942.             $this->mdkLogger->fatal(trans('vt4g_plugin.shopping.credit.fatal.restart.end'));
  943.             $error['payment'] = $this->getErrorMessage();
  944.             return null;
  945.         }
  946.         return $mdkResponse;
  947.     }
  948.     /**
  949.      * ベリトランス会員IDを会員テーブルに保存
  950.      *
  951.      * @param  integer $customerId 加盟店会員ID
  952.      * @param  string  $accountId  ベリトランス会員ID
  953.      * @return void
  954.      */
  955.     private function saveAccountId($customerId$accountId)
  956.     {
  957.         $customer $this->em->getRepository(Customer::class)->find($customerId);
  958.         // ベリトランス会員IDが未設定の場合に保存
  959.         if (empty($customer->vt4g_account_id)) {
  960.             $customer->vt4g_account_id $accountId;
  961.             $this->em->flush();
  962.         }
  963.     }
  964.     /**
  965.      * 受注完了処理
  966.      *
  967.      * @param Order            $order        注文情報
  968.      * @param Vt4gOrderPayment $orderPayment 注文に紐づく決済情報
  969.      * @return void
  970.      */
  971.     public function completeCreditOrder($order$orderPayment)
  972.     {
  973.         if (!$this->paymentResult['isOK']) {
  974.             return false;
  975.         }
  976.         // 決済情報 (memo05)
  977.         $payment $this->paymentResult;
  978.         // メール情報 (memo06)
  979.         $this->mailData = [];
  980.         $this->setMailTitle($this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_10']);
  981.         $this->setMailInfo('決済取引ID'$this->paymentResult['orderId']);
  982.         $paymentMethod $this->util->getPaymentMethod($order->getPayment()->getId());
  983.         $this->setMailAdminSetting($paymentMethod);
  984.         $subscSaleType $this->util->checkSubscriptionOrder($order); // 継続課金商品の判断 $subscSaleTypeがnullでなかったら継続課金商品
  985.         $subscMailInfoRepos $this->em->getRepository(Vt4gSubscProductOrderCmpMailInfo::class);
  986.         if (isset($subscSaleType)) {
  987.             $processedList = [];
  988.             foreach ($order->getOrderItems() as $item) {
  989.                 $product_id $this->util->getProductIdByOrderItem($item->getId());
  990.                 // メッセージ追加済みの商品IDはスキップする
  991.                 if (!in_array($product_id$processedList) ) {
  992.                     $info $subscMailInfoRepos->findOneBy(['product_id' => $product_id]);
  993.                     if (isset($info)) {
  994.                         $this->setMailInfo($info->getOrderCmpMailTitle(), $info->getOrderCompMailBody());
  995.                         $processedList[] = $product_id;
  996.                     }
  997.                 }
  998.             }
  999.         }
  1000.         // 決済変更ログ情報 (plg_vt4g_order_logテーブル)
  1001.         $this->setLog($order);
  1002.         // 注文ステータス更新
  1003.         if (!$this->setNewOrderStatus($order,$payment['withCapture'])) {
  1004.             return false;
  1005.         }
  1006.         // 受注完了処理
  1007.         $this->completeOrder($order$orderPayment$payment$this->logData$this->mailData);
  1008.         return true;
  1009.     }
  1010.     /**
  1011.      * 再取引決済 元取引IDのバリデーション
  1012.      *
  1013.      * @param  integer $paymentOrderId 元取引ID
  1014.      * @param  integer $customerId     会員ID
  1015.      * @return boolean                 元取引が存在するか
  1016.      */
  1017.     private function isValidReTradeOrder($paymentOrderId$customerId)
  1018.     {
  1019.         $limitDate date(
  1020.             $this->vt4gConst['VT4G_CREDIT_RETRADE']['DATETIME_FORMAT'],
  1021.             strtotime(sprintf('- %d month'$this->vt4gConst['VT4G_CREDIT_RETRADE']['VALID_MONTH']))
  1022.         );
  1023.         return $this->em->getRepository(Vt4gOrderPayment::class)->existsReTradeOrder(
  1024.             $customerId,
  1025.             $this->vt4gConst['VT4G_PAYTYPEID_CREDIT'],
  1026.             $limitDate,
  1027.             $paymentOrderId
  1028.         );
  1029.     }
  1030.     /**
  1031.      * ベリトランス会員IDを取得
  1032.      * (登録されていない場合は新しく採番)
  1033.      *
  1034.      * @param  object  $customer  会員情報
  1035.      * @param  integer $paymentId 決済方法ID
  1036.      * @return string             ベリトランス会員ID
  1037.      */
  1038.     private function getAccountId($customer$paymentId)
  1039.     {
  1040.         return empty($customer->vt4g_account_id)
  1041.             ? $this->generateAccountId($customer$paymentId)
  1042.             : $customer->vt4g_account_id;
  1043.     }
  1044.     /**
  1045.      * ベリトランスIDを新規採番
  1046.      *
  1047.      * @param  object  $customer   会員情報
  1048.      * @param  integer $paymentId  決済方法ID
  1049.      * @return string              ベリトランス会員ID
  1050.      */
  1051.     private function generateAccountId($customer$paymentId)
  1052.     {
  1053.         $paymentInfo $this->util->getPaymentMethodInfo($paymentId);
  1054.         $prefix     $paymentInfo['veritrans_id_prefix'];
  1055.         $customerId $this->util->zeroPadding($customer->getId(), $this->vt4gConst['VT4G_CUSTOMER_ID_DIGITS']);
  1056.         $hash       md5($customer->getEmail());
  1057.         $now        date("YmdHis");
  1058.         return "{$prefix}{$customerId}@{$hash}{$now}";
  1059.     }
  1060.     /**
  1061.      * メール内容の設定と完了画面の内容設定
  1062.      *
  1063.      * @param  object $order         注文データ
  1064.      * @param  array  $paymentResult 決済レスポンスデータ
  1065.      * @return array  $mailData      メールの説明文
  1066.      */
  1067.     public function setMail($order$paymentResult null)
  1068.     {
  1069.         if (is_null($paymentResult)) {
  1070.             $paymentResult $this->paymentResult;
  1071.         }
  1072.         $this->mailData = [];
  1073.         $this->setMailTitle($this->vt4gConst['VT4G_PAYNAME_PAYTYPEID_10']);
  1074.         $this->setMailInfo('決済取引ID'$paymentResult['orderId']);
  1075.         $paymentMethod $this->util->getPaymentMethod($order->getPayment()->getId());
  1076.         $this->setMailAdminSetting($paymentMethod);
  1077.         return $this->mailData;
  1078.     }
  1079.     /**
  1080.      * ログ出力内容を設定
  1081.      *
  1082.      * @param  object $order Orderクラスインスタンス
  1083.      * @return void
  1084.      */
  1085.     private function setLog($order$paymentResult null)
  1086.     {
  1087.         if (is_null($paymentResult)) {
  1088.             $paymentResult $this->paymentResult;
  1089.         }
  1090.         $this->timeKey '';
  1091.         $payId $this->util->getPayId($order->getPayment()->getId());
  1092.         $payName $this->util->getPayName($payId);
  1093.         $payStatusName $this->util->getPaymentStatusName($paymentResult['payStatus']);
  1094.         $this->setLogInfo('決済取引ID'$paymentResult['orderId']);
  1095.         $this->setLogInfo($payNamesprintf(
  1096.             $this->isPaymentRecv trans('vt4g_plugin.shopping.credit.recv.status') : trans('vt4g_plugin.shopping.credit.payment.status'),
  1097.             $payStatusName
  1098.         ));
  1099.     }
  1100.     /**
  1101.      * レスポンスを元にエラーメッセージを取得
  1102.      *
  1103.      * @return string エラーメッセージ
  1104.      */
  1105.     private function getErrorMessage()
  1106.     {
  1107.         $defaultMessage $this->defaultErrorMessage;
  1108.         if (!empty($this->paymentResult['vResultCode'])) {
  1109.             $defaultMessage .= '[' $this->paymentResult['vResultCode'] . ']';
  1110.         }
  1111.         $vResultCode $this->paymentResult['vResultCode'];
  1112.         if (empty($vResultCode)) {
  1113.             return $defaultMessage;
  1114.         }
  1115.         $extendMessage '';
  1116.         foreach (str_split($vResultCode4) as $code) {
  1117.             if ($code === '0000') {
  1118.                 continue;
  1119.             }
  1120.             $transKey $this->vt4gConst['VT4G_CREDIT_ERR_TRANS_PREFIX'] . $code;
  1121.             $transMessage trans($transKey);
  1122.             if ($transMessage !== $transKey) {
  1123.                 $extendMessage .= '<br />' $transMessage;
  1124.             }
  1125.         }
  1126.         if (empty($extendMessage)) {
  1127.             $extendMessage '<br />' trans($this->vt4gConst['VT4G_CREDIT_ERR_TRANS_PREFIX'].'DEFAULT');
  1128.         }
  1129.         return $defaultMessage $extendMessage;
  1130.     }
  1131.     /**
  1132.      * ダミーモードを判定します。
  1133.      * @return boolean||null trueとnull:ダミーモード、false:本番モード
  1134.      */
  1135.     protected function isDummyMode()
  1136.     {
  1137.         $subData $this->util->getPluginSetting();
  1138.         if (isset($subData)) {
  1139.             return $subData['dummy_mode_flg'] == '1';
  1140.         } else {
  1141.             return true;
  1142.         }
  1143.     }
  1144.     /**
  1145.      * 継続課金注文・明細データの保存
  1146.      * @param  array   $sources  保存する元データ
  1147.      *
  1148.      * @return boolean
  1149.      */
  1150.     public function saveSubscOrder($sources)
  1151.     {
  1152.         // 継続課金の販売種別が確認
  1153.         $saleTypeId $sources['order']->getSaleTypes()[0]->getId();
  1154.         $subscSaleType $this->em->getRepository(Vt4gSubscSaleType::class)
  1155.                                     ->findOneBy(['sale_type_id' => $saleTypeId]);
  1156.         if (is_null($subscSaleType)) {
  1157.             // 継続課金の販売種別でない場合は登録しない
  1158.             return false;
  1159.         }
  1160.         $order_id $sources['order']->getId();
  1161.         $customer_id null;
  1162.         if (isset($sources['user'])){
  1163.             $customer_id $sources['user']->getId();
  1164.         } else {
  1165.             $customer_id $this->em->getRepository(Order::class)
  1166.                 ->findOneBy(['id' => $order_id])->getCustomer()->getId();
  1167.         }
  1168.         // 継続課金注文データが登録済みならスキップ
  1169.         $subscOrder $this->em->getRepository(Vt4gSubscOrder::class)->find($order_id);
  1170.         if (!empty($subscOrder)){
  1171.             return false;
  1172.         }
  1173.         // 決済センター戻りと結果通知を同時受信してデッドロックが発生したら、
  1174.         // 一方の通信の処理でデータが登録されるはずなので、次の処理に進む
  1175.         try {
  1176.             // 継続課金注文データの保存
  1177.             $subscOrder = new Vt4gSubscOrder();
  1178.             $subscOrder ->setOrderId($order_id)
  1179.                         ->setCustomerId($customer_id)
  1180.                         ->setSubscSaleTypeId($sources['order']->getSaleTypes()[0]->getId());
  1181.             $this->em->persist($subscOrder);
  1182.             $this->em->flush();
  1183.             // 継続課金注文明細データの保存
  1184.             $oder_items $sources['order']->getOrderItems();
  1185.             $idxSubscOrderItem = [];
  1186.             foreach ($oder_items as $oder_item) {
  1187.                 // 商品マスタ情報を保持している注文明細のみ保存する(送料などを除外する)
  1188.                 if ($puroduct $oder_item->getProduct()) {
  1189.                     $subscOrder = new Vt4gSubscOrderItem();
  1190.                     $puroduct_id $puroduct->getId();
  1191.                     $prod_class_id $oder_item->getProductClass()->getId();
  1192.                     $shipping_id $oder_item->getShipping()->getId();
  1193.                     $idx sprintf('%s-%s-%s-%s'$order_id$puroduct_id$prod_class_id$shipping_id);
  1194.                     if (in_array($idx$idxSubscOrderItem)) continue;
  1195.                     $idxSubscOrderItem[] = $idx;
  1196.                     $subscOrder ->setOrderId($order_id)
  1197.                                 ->setProductId($puroduct_id)
  1198.                                 ->setProductClassId($prod_class_id)
  1199.                                 ->setShippingId($shipping_id)
  1200.                                 ->setSubscStatus($this->vt4gConst['VTG4_SUBSC_STATUS_SUBSC']); // 継続
  1201.                     $this->em->persist($subscOrder);
  1202.                 }
  1203.             }
  1204.             $this->em->flush();
  1205.             $this->mdkLogger->info(sprintf(trans('vt4g_plugin.shopping.credit.saved.subsc.order'),$order_id));
  1206.         } catch (\Doctrine\DBAL\Exception $e) {
  1207.             $msg $e->getMessage();
  1208.             if(strpos($msg,'deadlock') !== false || strpos($msg,'Deadlock') !== false) {
  1209.                 $this->mdkLogger->info(sprintf(trans('vt4g_plugin.db.deadlock'),'決済センター戻りの継続課金注文保存処理'));
  1210.             } else {
  1211.                 $this->mdkLogger->error($e->getMessage());
  1212.                 throw $e;
  1213.             }
  1214.         }
  1215.     }
  1216. }