mParam = $param; } private function success() { return ($this->mParam['Succeed'] =='Y'); } private function filter_param($param) { $filter = []; foreach ($param as $key => $value) { if($key != 'Signature') { $filter[$key] = ($value);//urlencode } } $pos = 0; $count = count($filter); $str = ''; foreach ($filter as $key => $value) { $str .= "{$key}=" . "{$value}"; if($pos != $count -1) { $str .= "&"; } $pos++; } return $str; } private function sign() { $strsign = $this->mParam['Signature']; $signAsc = explode("|", $strsign); $sign = ''; foreach ($signAsc as $v) { if ($v ==='') { continue; } $sign .= chr($v); } return $sign; } private function public_key() { $pub_key = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALuUIwMGhvbpCwYzKCMzvSMQiLAAj5y74cN09N1TXVONPWhvLWkuzEPSd1ogPJLWiVyEG7gEIBT3zTlCV+NMou0CAwEAAQ=='; // if(CMPPAY_ONLINE == true) { // $pub_key = 'MIGJAoGBALKsktbh7j9O9pM0p7qnxxImgODqxjpiT7Xl2bvZCywJtwsNI6CchqAagOYGJjG0NZsnjFunTw5YM9TD5KxsUOILAL6IaNMH/fWREhVjkUDJ4CYtLWlKozElvXRp1iZxf66yHHhN4t7TE5S9NWpEBSn37TEfFLU99Go1WReI1XN1AgMBAAE='; // } else { // // } $pk = chunk_split($pub_key, 64, "\n"); $pk = "-----BEGIN PUBLIC KEY-----\n{$pk}-----END PUBLIC KEY-----\n"; return $pk; } public function check() { if($this->success() == false) { return false; } $sign = $this->sign(); $pk = $this->public_key(); $pkid = openssl_pkey_get_public($pk); $content = $this->filter_param($this->mParam); $ok = openssl_verify($content, $sign, $pkid, OPENSSL_ALGO_SHA1); openssl_free_key($pkid); return $ok; } private function substr($arr,$src) { $len = strlen($src); $ar_len = 0; foreach ($arr as $key => $value) { $ar_len += intval($value); } if($ar_len > $len) return false; $result = []; $pos = 0; foreach ($arr as $key => $len) { $val = substr($src,$pos,$len); $pos += $len; $result[$key] = $val; } return $result; } public function format() { $body = $this->mParam['MerchantPara']; $params = preg_split('/\||:/', $body); $result = []; for ($i = 0; $i < count($params); ++$i) { $key = $params[$i]; $val = $params[++$i]; $result[$key] = $val; } $ar_key = array("BranchID" => 4,"CoNo" => 6, "Date" => 8,"trade_no" => 20); $msg = $this->substr($ar_key,$this->mParam['Msg']); $result['trade_no'] = $msg['trade_no']; return $result; } } class cmbpay implements IPay { const notify_signurl = BASE_SITE_URL . '/mobile/cmbpay_sign.php'; const notify_payurl = BASE_SITE_URL . '/mobile/cmbpay_notify.php'; const app_returl = BASE_SITE_URL . '/mobile/index.php'; const debug_notify_signurl = 'http://121.43.114.153/mobile/cmbpay_sign.php'; const debug_notify_payurl = 'http://121.43.114.153/mobile/cmbpay_notify.php'; const debug_app_returl = 'http://121.43.114.153/mobile/index.php'; static public function config() { if(CMPPAY_ONLINE == true) { return array( 'PAY_URL' => 'https://netpay.cmbchina.com/netpayment/BaseHttp.dll?PrePayEUserP', 'CMCX_URL' => 'http://58.61.30.110/CmbBank_B2B/UI/DIDI/DoBusiness.ashx', //签约协议查询接口 'MchNo' => 'N6255331',//协议商户企业编号 //请填写自己的商户企业编号 'BranchID' => '0021',//开户分行号 4位 请自己配置 'CoNo' => '006438', //商户号 6位 请自己配置 'singKey' => 'StanleyLRLZ12345',//签名密钥 查询单笔订单需要 ); } else { return array( 'PAY_URL' => 'http://61.144.248.29:801/netpayment/BaseHttp.dll?PrePayEUserP', 'CMCX_URL' => 'http://58.61.30.110/CmbBank_B2B/UI/DIDI/DoBusiness.ashx', //签约协议查询接口 'MchNo' => 'P0026365',//协议商户企业编号 //请填写自己的商户企业编号 'BranchID' => '0021',//开户分行号 4位 请自己配置 'CoNo' => '000140', //商户号 6位 请自己配置 'singKey' => '',//签名密钥 查询单笔订单需要 测试环境为空 ); } } static private function pay_notify_url() { if(is_debug()) { return self::debug_notify_payurl; } else { return self::notify_payurl; } } static private function app_returl() { if(is_debug()) { return self::debug_app_returl; } else { return self::app_returl; } } static private function sign_notify_url() { if(is_debug()) { return self::debug_notify_signurl; } else { return self::notify_signurl; } } public function on_notify($param) { $nofity = new NotifyData($param); if($nofity->check()) { return $nofity->format(); } else { Log::record('招行支付回调错误',Log::ERR); return false; } } public function gen_pay($pay_sn, $cents,$order_sn,$subject) { $config = self::config(); $bill_no = mt_rand(1000000000, 9999999999); $payprice = $cents / 100; $time = time(); $date = date('Ymd', $time); $user_id = $_SESSION['member_id']; $attach = "pay_sn:{$pay_sn}|order_sn:{$order_sn}|member_id:{$user_id}"; $param = $this->gen_param($time,$payprice,$attach,$bill_no); $code = $this->genMerchantCode($param); $ret_pam = "act=pay_return&op=cmbpay&pay_sn={$pay_sn}&order_sn={$order_sn}&member_id={$user_id}"; $data = [ 'BranchID' => $config['BranchID'], 'CoNo' => $config['CoNo'], 'BillNo' => $bill_no, 'Amount' => $payprice, 'Date' => $date, 'ExpireTimeSpan' => '30', 'MerchantUrl' => self::pay_notify_url(), 'MerchantPara' => $attach, 'MerchantCode' => $code, 'MerchantRetUrl' => self::app_returl(), 'MerchantRetPara' => $ret_pam ]; $count = count($data); $strParam = ''; $index = 0; foreach ($data as $key => $value) { $strParam .= "{$key}=" . urlencode($value); if($index != $count - 1) { $strParam .= "&"; } ++$index; } return array("req_url" => $config['PAY_URL'],"data" => $strParam); } private function gen_param($time,$payprice,$attach,$bill_no) { $config = self::config(); $date = date('Ymd', $time); $seq = $date . $bill_no; $user_id = $_SESSION['member_id']; $param = [ 'strKey' => $config['singKey'], 'strDate' => $date, 'strBranchID' => $config['BranchID'], 'strCono' => $config['CoNo'], 'strBillNo' => $bill_no, 'strAmount' => "{$payprice}", 'strMerchantPara' => $attach, 'strMerchantUrl' => self::pay_notify_url(), 'strPayerID' => "{$user_id}", 'strPayeeID' => '', 'strClientIP' => $_SERVER['REMOTE_ADDR'], 'strGoodsType' => '54011600', 'strReserved' => join('', [ '', '' . $user_id . '', '' . date('YmdHis', $time) . '', '' . $config['MchNo'] . '', '' . $seq . '', '' . self::sign_notify_url() . '', '', ]) ]; return $param; } private function genMerchantCode($param) { $str = ''; if (!empty($param['strClientIP'])) { $str .= '<$ClientIP$>' . $param['strClientIP'] . ''; } if (!empty($param['strGoodsType'])) { $str .= '<$GoodsType$>' . $param['strGoodsType'] . ''; } if (!empty($param['strReserved'])) { $str .= '<$Reserved$>' . $param['strReserved'] . ''; } $rnd = mt_rand(); $str = $rnd . '|' . $param['strPayerID'] . '<$CmbSplitter$>' . $param['strPayeeID'] . $str; $rc4Key = md5($param['strKey']); $rc4Key = pack('H*', $rc4Key); $rc4Val = openssl_encrypt($str, "RC4", $rc4Key, true); $rc4Val = base64_encode($rc4Val); $rc4Val = str_replace('+', '*', $rc4Val); $sha1Val = $param['strKey'] . $rc4Val . $param['strDate'] . $param['strBranchID'] . $param['strCono'] . $param['strBillNo'] . $param['strAmount'] . $param['strMerchantPara'] . $param['strMerchantUrl']; $sha1Val = sha1($sha1Val); return "|{$rc4Val}|{$sha1Val}"; } }