EC-CUBE みずほファクターのモジュールを2.13.3に対応させる
クレジット決済を行う方法どうでも良くて、ここに時間をかけることは本当にどうでも良いことですよね。
EC-CUBEなどソフトウェアの最新版に対応しないモジュールなんて、本当に使う価値がないと思います。
しかし「どうしても対応しないとならない」と相談を受けたので、ちょっとカスタマイズしてみました。
無事に動いているようですよ。
環境・条件
- EC-CUBE 2.11系が利用できる
- EC-CUBE 2.13.3にみずほファクターを設定する
- FTPが使える
- SQLが直接発行できる(できると楽)
- dtb_orderのmemo07、memo08、memo09、memo10が利用できる
- ここでは「画面連携」方法
- 改めて書く必要はないけど、自己責任でお願いね
①まずはEC-CUBE 2.11系で作業
まずはみずほファクターのモジュールを準備します。
ここではEC-CUBE 2.11.5で、みずほファクターのクレジット決済モジュールをインストールしました。
そして、無事にインストールが完了するまで管理画面で進めます。
②FTPでディレクトリをダウンロードして設置
インストールしたみずほファクターのモジュールをダウンロードします。
「/data/downloads/module/mdl_ksnavi」というディレクトリをまるごとダウンロードします。
そして、ダウンロードした「mdl_ksnavi」を、EC-CUBE 2.13.3の同じ場所にアップロードします。
「/data/downloads/module/」あたりですかね。
そして、「/data/downloads/module/mdl_ksnavi/module/source/data/」以下のファイルを、EC-CUBE 2.13.3の展開済み「data」ディレクトリに上書きします。
具体的には以下の様な配置になるかと思います。
/data/class_extends/page_extends/shopping/LC_Page_Shopping_LoadPaymentModule_Ex.php /data/class_extends/page_extends/shopping/LC_Page_Shopping_Payment_Ex.php /data/downloads/module/mdl_ksnavi/index.php /data/downloads/module/mdl_ksnavi/class/LC_Page_Mdl_Ksnavi.php /data/downloads/module/mdl_ksnavi/class/SC_Utils_Mdl_Ksnavi.php /data/downloads/module/mdl_ksnavi/config/setting.php /data/downloads/module/mdl_ksnavi/templates/failure.tpl /data/downloads/module/mdl_ksnavi/templates/index.tpl
③設定ファイルの調整
みずほファクターの設定ファイルを調整します。
設定ファイルは「data/downloads/module/mdl_ksnavi/config/setting.php」です。
特に以下の定数を調整する必要があります。
みずほファクターから指定された情報に設定をしてください。
- MDL_KSNAVI_SHOPID
- MDL_KSNAVI_CSHOPID
- MDL_KSNAVI_MDL_ID
- MDL_KSNAVI_PC_URL
- MDL_KSNAVI_MB_URL
- MDL_KSNAVI_HASH_PASSWORD
結果はdtb_orderに記録されて、デフォルトでは以下のようになっています。
取引番号の結果を格納する場所がないのでmemo07に追加することにします。
- memo07 には mbtran
- memo08 には rsltdcd
- memo09 には rsltcd
- memo10 には stran
そして以下のように定数を追加しておきます。
// mbtran格納カラム(取引番号) define('MDL_KSNAVI_MBTRAN_COLUMN', 'memo07');
④dtb_paymentテーブルへのSQL調整・発行
「/data/downloads/module/mdl_ksnavi/module/source/query/ksnavi.sql」を開いて、SQLを少し調整します。注意書きがあるので、基本的にはそれに併せてSQLを調整すれば問題ないです。
1つだけカラム名を変更する必要があるので、カラム名を変更しておきます。
「rule」を「rule_max」に変更します
そしてSQLを発行します。
⑤クラスファイルの調整
「LC_Page_Mdl_Ksnavi」クラスファイルを調整します。
LC_Pageの拡張となっていますが、LC_Page_Shopping_LoadPaymentModuleの拡張に直します。
それに伴い、requireするファイルも変更します。
メソッドは以下を調整しました。
- init
- lfGetRequestParam
- lfGenerateDigest
- lfOperateSuccess
- lfOperateFailure
<?php define("CLASS_PATH", DATA_REALDIR . 'class/'); require_once(CLASS_PATH . "pages/shopping/LC_Page_Shopping_LoadPaymentModule.php"); /** * 決済ナビ接続モジュール. * 受注情報よりパラメータを生成し決済ナビ側へ遷移する。 * * @package Page */ class LC_Page_Mdl_Ksnavi extends LC_Page_Shopping_LoadPaymentModule { /** * 初期化する * * @return void */ function init() { // parent::init(); // テンプレート(formからのpostのみ行う) $this->tpl_mainpage = MDL_KSNAVI_TEMPLATE_PATH . 'index.tpl'; $this->template = MDL_KSNAVI_TEMPLATE_PATH . 'index.tpl'; // submit先のURL if( SC_Display_Ex::detectDevice() == DEVICE_TYPE_MOBILE ){ // 携帯 $this->url = MDL_KSNAVI_MB_URL; }else{ // PC,スマホ $this->url = MDL_KSNAVI_PC_URL; } // ログファイル出力先 $this->log_file = MDL_KSNAVI_LOGFILE; // $this->arrInfo = SC_Helper_DB_Ex::sfGetBasisData(); } /** * main処理 * * @return void */ function process() { try{ // 開始 SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "====================================" ); SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "start.", __LINE__ ); // $_REQUESTから特定のキーの値だけ取得 $this->arrResponse = $this->lfGetResponceFromRequest(); SC_Utils_Mdl_Ksnavi::sfPrintLog( $this->arrResponse, __LINE__ ); // オーダーID取得 $this->order_id = $this->lfGetOrderId(); SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "order_id:".$this->order_id, __LINE__ ); // $_REQUESTから取得したパラメータが決済ナビからのレスポンスかどうか if($this->lfCheckResponse()){ // response SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "response mode.", __LINE__ ); // 処理対象の受注データが、まだ決済処理中かどうか if( $this->lfCheckValidOrder() ){ SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "valid response.", __LINE__ ); // 決済ナビからの処理結果が「成功」である場合 if($this->arrResponse['rsltcd'] == MDL_KSNAVI_SUCCESS_CODE){ // 成功時の処理 $this->lfOperateSuccess(); }else{ // 失敗時の処理 $this->lfOperateFailure(); } }else{ // 既に処理が済んでいる注文なのでページだけ表示する(結果の登録は行わない) SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "invalid response.", __LINE__ ); $this->lfOperateFailure(true); } // exit; }else{ // request SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "request mode.", __LINE__ ); // 送信するパラメータを取得 $this->arrParam = $this->lfGetRequestParam(); // テンプレート設定 $this->setTemplate($this->tpl_mainpage); // ヘッダ出力 header("Content-Type: text/html; charset=shift_jis"); } // レスポンス出力 $this->sendResponse(); // request end SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "resuest end.", __LINE__ ); SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "====================================" ); }catch( Exception $e ){ SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "[process]exception:".$e->getMessage(), __LINE__ ); return false; } } /** * デストラクタ * * @return void */ function destroy() { // parent::destroy(); } /** * Strunから受注IDを取得 * PCと同じ処理携帯だと決済ナビからの戻る際、 * セッションIDが無い為order_idが取れない。 * なので戻り値の中にあるstranを使って、 * lfRegistStranで登録したレコードのorder_idを取得する。 * * @return integer */ function _lfGetOrderIdFromStran($strun){ // $res = 0; // $objQuery = new SC_Query(); // $arrRet = $objQuery->select('order_id','dtb_order',MDL_KSNAVI_STRAN_COLUMN.'=?',array($strun)); if( count( $arrRet ) > 0 ){ $order_id = $arrRet[0]['order_id']; $_SESSION['order_id'] = $order_id; } // XSS対策も兼ねてキャスト return intval($order_id); } /** * 受注IDを取得 * * @return integer */ function _lfGetOrderId(){ // if (isset($_SESSION['order_id'])){ // セッションにあれば取得 $order_id = $_SESSION['order_id']; } else { // post,getにあれば取得してセッションに登録 $order_id = $_REQUEST['order_id']; $_SESSION['order_id'] = $order_id; } // XSS対策も兼ねてキャスト return intval($order_id); } /** 受注IDを取得 * * @return integer */ function lfGetOrderId(){ // オーダーID取得 if (SC_Display::detectDevice() == DEVICE_TYPE_MOBILE) { $order_id = $this->_lfGetOrderIdFromStran($this->arrResponse['stran']); }else{ $order_id = $this->_lfGetOrderId(); } return $order_id; } function lfGetResponceFromRequest(){ // 必須項目 $arrColumn = array(); $arrColumn[] = 'p_ver'; $arrColumn[] = 'stdate'; $arrColumn[] = 'stran'; $arrColumn[] = 'bkcode'; $arrColumn[] = 'shopid'; $arrColumn[] = 'cshopid'; $arrColumn[] = 'amount'; $arrColumn[] = 'mbtran'; $arrColumn[] = 'bktrans'; $arrColumn[] = 'tranid'; $arrColumn[] = 'ddate'; $arrColumn[] = 'rsltcd'; $arrColumn[] = 'rsltdcd'; $arrColumn[] = 'vdarte'; $arrColumn[] = 'rchksum'; // $arrRes = array(); // foreach( $arrColumn as $column ){ // if( array_key_exists( $column, $_REQUEST ) ){ // $arrRes[$column] = $_REQUEST[$column]; } } // return $arrRes; } /** * リクエスト用のパラメータ文字列を生成するのに必要な値を取得 * * @return array */ function lfGetRequestParam() { try{ // $arrParam = array(); // $objPurchase = new SC_Helper_Purchase_Ex(); // オーダーID取得 $order_id = $this->order_id; if( $order_id > 0 ){ // 受注情報の取得 $arrData = $objPurchase->getOrder($order_id); $arrParam['p_ver'] = MDL_KSNAVI_MDL_PROTOCOL; $arrParam['stdate'] = date('Ymd'); // $arrParam['vdate'] = ''; $arrParam['stran'] = $this->lfGetStran($order_id); $this->lfRegistStran($order_id,$arrParam['stran']); $arrParam['bkcode'] = 'bg01'; $arrParam['shopid'] = MDL_KSNAVI_SHOPID; $arrParam['cshopid'] = MDL_KSNAVI_CSHOPID; $arrParam['amount'] = $arrData['payment_total']; // $arrParam['custm'] = $arrData['order_kana01'].$arrData['order_kana02']; // $arrParam['custmKanji'] = $arrData['order_name01'].$arrData['order_name02']; // $arrParam['mailaddr'] = $arrData['order_email']; // $arrParam['tel'] = $arrData['order_tel01'].'-'.$arrData['order_tel02'].'-'.$arrData['order_tel03']; // shift_jisにエンコード foreach($arrParam as $k=>$v){ $arrParam[$k] = mb_convert_encoding($v,MDL_KSNAVI_MDL_ECNCODE,'UTF-8'); } $arrParam['schksum'] = $this->lfGenerateDigest($arrParam); SC_Utils_Mdl_Ksnavi::sfPrintLog( $arrParam, __LINE__ ); } // return $arrParam; }catch( Exception $e ){ SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "[lfGetRequestParam]exception:".$e->getMessage(), __LINE__ ); return array(); } } /** * 加盟店取引番号取得 * * @return string */ function lfGetStran($order_id=0){ try{ // $objQuery = new SC_Query(); // シーケンス名 $seq_name = "dtb_kessai_navi_dbkey"; // シーケンス専用テーブル $table_name = $seq_name . "_seq"; // テーブルが無ければ生成する if (DB_TYPE == 'mysql') { $query = ""; $query .= "create table if not exists ".$table_name." ( "; $query .= "sequence int(11) not null auto_increment, primary key (sequence) "; $query .= ") engine=myisam default charset=utf8 auto_increment=1;"; $objQuery->query($query); } // next値取得 $num = $objQuery->nextVal($seq_name); // 6桁整形 $stran = sprintf( '%06d', ( $num % 1000000 ) ); // SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "stran:".$stran, __LINE__ ); return $stran; }catch( Exception $e ){ SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "[lfGetStran]exception:".$e->getMessage(), __LINE__ ); return false; } } /** * DBキー取得 * 20桁なので「7桁+uniqid」で構成 * * @return string */ function lfGetDBKey($order_id=0){ // 上7桁は受注IDをベースに $prefix = 'k'.sprintf( '%06d', ( $order_id % 1000000 ) ); // 下13桁はuniqid $dbkey = uniqid($prefix); SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "[lfGetDBKey]dbkey:".$dbkey, __LINE__ ); // return $dbkey; } /** * ダイジェスト生成 * * @return string */ function lfGenerateDigest($arrParam){ // ハッシュパスワード $password = MDL_KSNAVI_HASH_PASSWORD; // 送信パラメータを順につなげる $str = ''; // $str .= $arrParam['p_ver']; // $str .= $arrParam['stdate']; // $str .= $arrParam['vdate']; // $str .= $arrParam['stran']; // $str .= $arrParam['bkcode']; // $str .= $arrParam['shopid']; // $str .= $arrParam['cshopid']; // $str .= $arrParam['amount']; // $str .= $arrParam['custm']; // $str .= $arrParam['custmKanji']; // $str .= $arrParam['mailaddr']; // $str .= $arrParam['tel']; // $str .= $password; // md5でハッシュ化 // $str = md5($str); // foreach ($arrParam as $key => $val) { $str .= $val; } $str .= $password; $strHash = md5($str); return urlencode($strHash); } /** * 照合することがあるかもしれないので * 加盟店取引番号を受注情報に登録しておく * * @return void */ function lfRegistStran($order_id,$stran){ try{ // $objQuery = new SC_Query(); // if( intval( $order_id ) > 0 && strlen( $stran ) > 0 ){ $sqlval = array(MDL_KSNAVI_STRAN_COLUMN => $stran); $objQuery->update('dtb_order',$sqlval,'order_id=?',array($order_id)); } }catch( Exception $e ){ SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "[lfRegistStran]exception:".$e->getMessage(), __LINE__ ); } } /** * 照合することがあるかもしれないので * 加盟店取引番号を受注情報に登録しておく * * @return void */ function lfRegistRsltcd($order_id,$rsltcd,$rsltdcd){ try{ // $objQuery = new SC_Query(); // if( intval( $order_id ) > 0 ){ // if( strlen( $rsltcd ) < 1 ){ $rsltcd = MDL_KSNAVI_NONE_CODE; } $sqlval = array(); $sqlval[MDL_KSNAVI_RESULT_COLUMN] = $rsltcd; $sqlval[MDL_KSNAVI_RESULT_DETAIL_COLUMN] = $rsltdcd; $sqlval[MDL_KSNAVI_MBTRAN_COLUMN] = $mbtran; $objQuery->update('dtb_order',$sqlval,'order_id=?',array($order_id)); } }catch( Exception $e ){ SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "[lfRegistRsltcd]exception:".$e->getMessage(), __LINE__ ); } } /** * * * @return void */ function lfCheckResponse(){ // 必須項目 $arrColumn = array(); $arrColumn[] = 'p_ver'; $arrColumn[] = 'stdate'; $arrColumn[] = 'stran'; //$arrColumn[] = 'bkcode'; $arrColumn[] = 'shopid'; $arrColumn[] = 'cshopid'; $arrColumn[] = 'amount'; $arrColumn[] = 'mbtran'; //$arrColumn[] = 'bktrans'; //$arrColumn[] = 'tranid'; //$arrColumn[] = 'ddate'; $arrColumn[] = 'rsltcd'; //$arrColumn[] = 'rsltdcd'; //$arrColumn[] = 'vdarte'; //$arrColumn[] = 'rchksum'; // $res = true; // foreach( $arrColumn as $column ){ // if( !array_key_exists( $column, $this->arrResponse ) ){ SC_Utils_Mdl_Ksnavi::sfPrintLog( "[lfCheckResponse]key '".$column."' in not found.", __LINE__ ); // $res = false; break; } } // return $res; } /** * * * @return void */ function lfOperateSuccess(){ // 正常に登録されたことを記録 $objCustomer = new SC_Customer(); $objSiteSess = new SC_SiteSession_Ex(); $objCartSess = new SC_CartSession_Ex(); $objPurchase = new SC_Helper_Purchase_Ex(); // オーダーID取得 $order_id = $this->order_id; // $this->lfRegistRsltcd($order_id,$this->arrResponse['rsltcd'],$this->arrResponse['rsltdcd']); // // $objPurchase->sfUpdateOrderStatus($order_id, ORDER_NEW, null, null, $sqlval); $objPurchase->sfUpdateOrderStatus($order_id, ORDER_PRE_END, null, null, $sqlval); // 受注完了メールを送信する。 $objPurchase->sendOrderMail($order_id); SC_Utils_Mdl_Ksnavi::sfPrintLog( "sendOrderMail", __LINE__ ); // セッションカート内の商品を削除する。 $objCartSess->delAllProducts(); // 注文一時IDを解除する。 $objPurchase->cleanupSession(null, $objCartSess, $objCustomer, $objCartSess->getKey()); $objSiteSess->unsetUniqId(); $objSiteSess->setRegistFlag(); // response end SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "response end.", __LINE__ ); SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "====================================" ); SC_Response_Ex::sendRedirect(SHOPPING_COMPLETE_URLPATH); exit; } /** * * * @return void */ function lfOperateFailure( $disp_only = false ){ // 正常に登録されたことを記録 $objCustomer = new SC_Customer(); $objSiteSess = new SC_SiteSession_Ex(); $objCartSess = new SC_CartSession_Ex(); $objPurchase = new SC_Helper_Purchase_Ex(); // オーダーID取得 $order_id = $this->order_id; if( !$disp_only ){ // // $this->lfRegistRsltcd($order_id,$this->arrResponse['rsltcd'],$this->arrResponse['rsltdcd']); $this->lfRegistRsltcd($order_id, $this->arrResponse['rsltcd'], $this->arrResponse['rsltdcd'], $this->arrResponse['mbtran']); } $this->disp_only = $disp_only; // セッションカート内の商品を削除する。 $objCartSess->delAllProducts(); // 注文一時IDを解除する。 unset($_SESSION['order_id']); $objPurchase->cleanupSession(null, $objCartSess, $objCustomer, $objCartSess->getKey()); $objSiteSess->unsetUniqId(); $objSiteSess->setRegistFlag(); // if (SC_Display::detectDevice() == DEVICE_TYPE_MOBILE) { $objView = new SC_MobileView(); } else { $objView = new SC_SiteView(); } $this->tpl_mainpage = MDL_KSNAVI_TEMPLATE_PATH . 'failure.tpl'; $objView->assignobj($this); $objView->display(SITE_FRAME); // response end SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "response end.", __LINE__ ); SC_Utils_Mdl_Ksnavi::sfPrintLogCore( "====================================" ); // exit; } /** * */ function lfCheckValidOrder(){ // $res = false; // オーダーID取得 $order_id = $this->order_id; // $objQuery = new SC_Query(); // $col = MDL_KSNAVI_RESULT_COLUMN; $from = 'dtb_order'; $where = 'order_id=? and status=?'; $arrval = array($order_id,ORDER_PENDING); $arrRet = $objQuery->select($col,$from,$where,$arrval); // 「支払処理中」のレコードが存在する if( count( $arrRet ) > 0 ){ // レコードはあるが決済ナビ処理結果が入っていない if( strlen( $arrRet[0][MDL_KSNAVI_RESULT_COLUMN] ) == 0 ){ // 有効(未処理)な受注 $res = true; } } // return $res; } /** * dtb_paymentへの登録(未使用) * * @return void */ function lfRegistKsnaviPayment(){ $query = ""; $query .= "INSERT "; $query .= "INTO "; $query .= "dtb_payment "; $query .= "( "; $query .= "payment_id, "; $query .= "payment_method, "; $query .= "charge, "; $query .= "rule, "; $query .= "rank, "; $query .= "note, "; $query .= "fix, "; $query .= "status, "; $query .= "del_flg, "; $query .= "creator_id, "; $query .= "create_date, "; $query .= "update_date, "; $query .= "payment_image, "; $query .= "upper_rule, "; $query .= "charge_flg, "; $query .= "rule_min, "; $query .= "upper_rule_max, "; $query .= "module_id, "; $query .= "module_path, "; $query .= "memo01, "; $query .= "memo02, "; $query .= "memo03, "; $query .= "memo04, "; $query .= "memo05, "; $query .= "memo06, "; $query .= "memo07, "; $query .= "memo08, "; $query .= "memo09, "; $query .= "memo10"; $query .= ") "; $query .= "VALUES "; $query .= "( "; $query .= "".MDL_KSNAVI_MDL_ID.", "; $query .= "'".MDL_KSNAVI_MDL_CODE."', "; $query .= "0, "; $query .= "NULL, "; $query .= "0, "; $query .= "NULL, "; $query .= "2, "; $query .= "1, "; $query .= "0, "; $query .= "2, "; $query .= "now(), "; $query .= "now(), "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "'".MDL_KSNAVI_PATH."/index.php', "; $query .= "NULL, "; $query .= "NULL, "; $query .= "'".MDL_KSNAVI_MDL_CODE."', "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "NULL, "; $query .= "'' "; $query .= ");"; $objQuery = new SC_Query(); $objQuery->query($query); } } ?>
⑥みずほファクターへ戻りURLを連絡
みずほファクターに「戻りURL設定」を設定してもらえば、作業は完了です。
設定してもらうURLは以下のとなるかと思います。
https://***.***.***/shopping/load_payment_module.php
まとめ
それほど難しいことなく調整できるかと思います。
ここでは「画面連携」を基準にしていますが、「データ連携」でも項目とロジックを多少調整すれば問題ないです。
作業が終わってしまっていて、みずほファクターをアイネクシオは利用していないのでこれ以上検証ができませんが、何か問題などあったらご指摘をお願いします。
「ソース掲載しちゃダメだよ」とか「アイキャッチはあれはダメでしょ」もご指摘ください~。