说明:首先说明自己在开发中遇到的坑
(1)没有将itppay_cert.pem文件没有放到指定目录下
(2)异步回调调用参数的时候没有在线上测试,
(3)项目里面被设置了路由访问权限,自己回调函数的路由访问不到(被这个折腾的要死,支付回调非常常见的犯错)
(4)用它的demo里面的file_get_contents("php://input");获取不到数据(具体原因不知道为什么,有可能我们公司封装的框架里面的一些设置和官网不同),后来换成 $data = $GLOBALS['HTTP_RAW_POST_DATA'];获取数据成功
1.官网下载SDK,地址:https://www.itppay.com/help/sdk
2.图片内容放到根目录下
3.控制器里的方法的
function itp() { // 金额 商品介绍 商品名称 $amount = 0.01; // $amount = I('post.amount'); $body = I('post.body'); $subject = I('post.subject'); $user_id = I('post.user_id'); // 建立请求 $itpPay = new ItppayModel(); $res = $itpPay->itppay($amount, $body, $subject,$user_id); echo $res; }
4..itppay支付所需要的参数代码如下,自己封装到MODEL类下(参数根据你自己的具体情况而定)
<?php /* * * 功能:明天云平台支付类 * 说明:构造支付请求函数及生成签名,支付接口表单HTML文本 * 版本:1.0 * 日期:2017-05-15 */ class ItppayModel extends Model { //支付请求地址 appid 支付密钥 lala var $itppay_gateway = "http://www.itppay.com/newsdk/api/v1.0/cli/order_pc/0"; var $itppay_appid = '0000000022'; var $itppay_key = "e7d4c31780d1379c6af38f82e455967c"; /** * itppay智付云支付 * */ function itppay($amount,$body,$subject,$user_id){ $parameter=array( "amount" =>$amount*100,//[必填]订单总金额,单位(分) "appid" =>$this->itppay_appid,//[必填]//交易发起所属app "body" =>$body,//[必填]商品描述 "clientIp" =>$_SERVER["REMOTE_ADDR"],//[必填]客户端IP "cpChannel" =>"",//CP分发渠道 "currency" =>"",//币种,默认RMB "description" =>"",//订单附加描述 "expireMs" =>"",//过期时间毫秒数,默认24小时过期 "extra" =>"",//附加数据,以键值对形式存放,例如{"key":"value"} "mchntOrderNo" =>date("Y").date("m").date("d").rand(10000,100000).'_'.$user_id,//[必填]商户订单号,必须唯一性 "notifyUrl" =>"http://shike.118.easysoft168.com/Global/itp_callback",//[必填]订单支付结果异步通知地址,用于接收订单支付结果通知,必须以http或https开头 "returnUrl" => "http://shike.118.easysoft168.com/FrontPcMerchant/release_third",//[必填]订单支付结果同步跳转地址,用于同步跳转到商户页面,必须以http或https开头 "subject" =>$subject,//[必填]商品名称 "version" =>"pc_NoEncrypt",//接口版本号,值为pc_NoEncrypt时,则明天平台返回商户参数时,不进行RSA加密 "payChannelId" =>""//支付渠道id ); // dump($parameter);die(); $orderInfo=$this->getOrderInfo($parameter); // dump($orderInfo);die; $html=$this->RequestForm($orderInfo, "跳转中..."); return $html; } /** * 生成签名 * $parameter 已排序要签名的数组 * $moveNull 是否清除为空的参数 * return 签名结果字符串 */ function setSignature($parameter, $moveNull=true) { $signature=""; if(is_array($parameter)){ ksort($parameter); foreach($parameter as $k=>$v){ if($moveNull){ if($v!=="" && !is_null($v)){ $signature .= $k."=".$v."&"; } }else{ $signature .= $k."=".$v."&"; } } // dump($signature);die; if($signature){ $signature .= "key=".$this->itppay_key; // dump($signature);die; $signature = md5($signature); } } return $signature; } /** * 生成POST传递值 * $parameter 已排序要签名的数组 * return 生成的字符串 */ function setPostValue($parameter) { $orderInfo=""; if(is_array($parameter)){ $parameter["signature"] = $this->setSignature($parameter); foreach($parameter as $k=>$v){ if($v!=="" && !is_null($v)){ $orderInfo[$k] = $v; } } } $orderInfo = json_encode($orderInfo,JSON_UNESCAPED_UNICODE); return $orderInfo; } /** * 获取加密后的参数数据 * $parameter 已排序要签名的数组 * return 加密后的字符串 */ function getOrderInfo($parameter) { $crypto=""; $orderInfo = $this->setPostValue($parameter); //绝对路径 //$itppay_cert = file_get_contents("D:/php/Apache24/htdocs/itppay_cert.pem"); //相对路径 请根据项目自行更正 $itppay_cert = file_get_contents("itppay_cert.pem"); $publickey = openssl_pkey_get_public($itppay_cert); foreach(str_split($orderInfo, 117) as $chunk){ openssl_public_encrypt($chunk, $encryptData, $publickey); $crypto .= $encryptData; } $crypto = base64_encode($crypto); return $crypto; } /** * 建立以表单形式构造 * $orderInfo POST传递参数值 * $button 提交按钮显示内容 * return HTML表单 */ function RequestForm($orderInfo, $button){ $html .= "<form id=\"itppay_form\" name=\"itppay_form\" action=\"".$this->itppay_gateway."\" method=\"post\">"; $html .= "<input type=\"hidden\" name=\"orderInfo\" value=\"".$orderInfo."\">"; $html .= "<input type=\"submit\" value=\"".$button."\">"; $html .= "</form>"; //去除等待2秒后执行 //$html .= "<script>setTimeout(function(){document.forms['itppay_form'].submit();}, 2000);</script>"; $html .= "<script>document.forms['itppay_form'].submit();</script>"; return $html; } /** * POST提交 * $url 提交地址 * $data POST提交的数组 * return 字符串 */ function curl($url, $data){ //创建curl资源 $curl=curl_init(); //设置URL和相应的选项 curl_setopt($curl, CURLOPT_URL, $url); if(!empty($data)){ curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //执行curl $output=curl_exec($curl); //关闭并释放curl资源 curl_close($curl); return $output; } } ?>
5.获取回调参数(log_file是公司自己封装的一个方法,为的是打印获取到的回调参数)
function itp_callback() { // 获取传递数据 $data = $GLOBALS['HTTP_RAW_POST_DATA']; $parameter = json_decode($data, true); log_file('parameter='.json_encode($parameter),'debug_data'); $signature = $parameter["signature"]; unset($parameter["signature"]); /* * * 签名 */ $itpPay = new ItppayModel(); $signature_local=$itpPay->setSignature($parameter); $logFile = fopen("log.txt", "a+"); fclose(fopen("log2.txt", "w")); $logFile2 = fopen("log2.txt", "a+"); if ($signature && $signature == $signature_local) { //$parameter["orderNo"]明天云平台生成的订单号 //$parameter["mchntOrderNo"]商户订单号,可根据商户订单号查询商户网站中该订单信息,并执行业务处理 //$parameter["orderDt"]下单日期 //$parameter["paidTime"]订单支付完成时间 //$parameter["extra"]附加数据 //$parameter["paySt"]支付结果状态,0:待支付;1:支付中;2:支付成功;3:支付失败;4:已关闭 switch ($parameter["paySt"]) { case 0: fwrite($logFile, "[" . $parameter["mchntOrderNo"] . "]--->待支付\r\n"); fwrite($logFile2, "[" . $parameter["mchntOrderNo"] . "]--->待支付\r\n"); break; case 1: fwrite($logFile, "[" . $parameter["mchntOrderNo"] . "]--->支付中\r\n"); fwrite($logFile2, "[" . $parameter["mchntOrderNo"] . "]--->支付中\r\n"); break; case 2: fwrite($logFile, "[" . $parameter["mchntOrderNo"] . "]--->支付成功\r\n"); fwrite($logFile2, "[" . $parameter["mchntOrderNo"] . "]--->支付成功\r\n"); // 获取用户id $mchntOrderNo =$parameter["mchntOrderNo"]; $user_id_array = explode('_',$mchntOrderNo); $user_id =$user_id_array[1]; // 变动金额(正负数) $amount =$parameter["amount"]/100; // 管理员备注,线上充值时,该参数为第三方支付平台返回的交易码 $remark =$parameter["body"]; // 智付云生成的相关订单号 $order_id =$parameter["orderNo"]; // 第三方官方订单号 $proof =$parameter["outTransactionId"]; $acc_obj =new AccountModel(); // 将金额充值到余额中 $acc_obj->addAccount($user_id,AccountModel::ONLINE_VOUCHER,$amount,$remark,$order_id,$proof); // 在余额中扣除需要支付的金额 $acc_obj->addAccount($user_id,AccountModel::ONLINE_VOUCHER,$amount*-1,$remark,$order_id,$proof); break; case 3: fwrite($logFile, "[" . $parameter["mchntOrderNo"] . "]--->支付失败\r\n"); fwrite($logFile2, "[" . $parameter["mchntOrderNo"] . "]--->支付失败\r\n"); break; case 4: fwrite($logFile, "[" . $parameter["mchntOrderNo"] . "]--->已关闭\r\n"); fwrite($logFile2, "[" . $parameter["mchntOrderNo"] . "]--->已关闭\r\n"); break; } foreach ($parameter as $k => $v) { fwrite($logFile, $k . "=" . $v . "\r\n"); fwrite($logFile2, $k . "=" . $v . "\r\n"); } fwrite($logFile, "\r\n\r\n"); fwrite($logFile2, "\r\n\r\n"); } else { fwrite($logFile, "[" . $parameter["mchntOrderNo"] . "]--->验签失败\r\n"); fwrite($logFile2, "[" . $parameter["mchntOrderNo"] . "]--->验签失败\r\n"); } fclose($logFile); fclose($logFile2); echo "{\"success\":\"true\"}"; }6.log_file的封装函数
function log_file($str, $file_name = '', $daily_write = false, $user_id = 0) { $sess_user_id = intval(session('user_id')); if ( $user_id == 0 || ($user_id == $sess_user_id) ) { $file_path = 'logs/'; $file_path .= $file_name ? $file_name . ($daily_write ? '.' . date('Y-m-d', time()) : '') . '.log' : 'event.' . date('Y-m-d', time()) . '.log'; $file = fopen($file_path, 'a'); fwrite($file, date('Y-m-d H:i:s', time()) . "\n" . $str . "\n"); fclose($file); } }