使用的是官方提供方的php接口:create_direct_pay_by_user-PHP-UTF-8
将lib下的四个文件复制至:yii项目\protected\vendor\下
四个文件分别是:alipay_core.function.php、alipay_md5.function.php、alipay_notify.class.php、alipay_submit.class.php
将CA证书文件:cacert.pem在yii项目\目录和 yii项目\protected\controllers下各复制一份
在main.php的项目配置文件中加入支付宝的相关配置参数:
'params'=>array( 'alipay_config'=>array( 'partner' =>'',//必填 'key'=>'',//必填 'sign_type'=>strtoupper('MD5'),//必填 'input_charset'=> strtolower('utf-8'),//必填 'cacert'=>getcwd().'/cacert.pem',//必填且CA证书文件能有效访问,否则会有sign错误 'transport'=>'http',//如果你的服务器支持https请填写https ), 'alipay' =>array( 'seller_email'=>'',//必填 'notify_url'=>'http://res.locoy.com/index.php?r=pay/notifyUrl', 'return_url'=>'http://res.locoy.com/index.php?r=pay/returnUrl',//必填 'successpage'=>'account/list',//处理成功后的页面 'errorpage'=>'shopcart/list',//处理失败的页面 ), ),
然后写一个支付的控制器:
<?php class PayController extends Controller { public function ActionAlipay($id) { $model = Shopcart::model()->findByPk($id); header("Content-type:text/html;charset=utf-8"); Yii::import('application.vendor.*'); require_once('alipay_core.function.php'); require_once('alipay_md5.function.php'); require_once('alipay_notify.class.php'); require_once('alipay_submit.class.php'); $alipay_config = Yii::app()->params['alipay_config']; $payment_type = "1"; $notify_url = Yii::app()->params['alipay']['notify_url']; //需http://格式的完整路径,不能加?id=123这类自定义参数 //页面跳转同步通知页面路径 $return_url = Yii::app()->params['alipay']['return_url']; //需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/ //卖家支付宝帐户 $seller_email = Yii::app()->params['alipay']['seller_email']; //必填 //商户订单号 $out_trade_no = $model->trade_id; //商户网站订单系统中唯一订单号,必填 //订单名称 $subject = $model->trade_name; //必填 //付款金额 $total_fee = $model->trade_money; //必填 //订单描述 $body = $model->trade_name.':'.$model->trade_money; //商品展示地址 $show_url = ''; //需以http://开头的完整路径,例如:http://www.xxx.com/myorder.html //防钓鱼时间戳 $anti_phishing_key = ""; //若要使用请调用类文件submit中的query_timestamp函数 //客户端的IP地址 $exter_invoke_ip = ""; //非局域网的外网IP地址,如:221.0.0.1 /************************************************************/ //构造要请求的参数数组,无需改动 $parameter = array( "service" => "create_direct_pay_by_user", "partner" => trim($alipay_config['partner']), "payment_type" => $payment_type, "notify_url" => $notify_url, "return_url" => $return_url, "seller_email" => $seller_email, "out_trade_no" => $out_trade_no, "subject" => $subject, "total_fee" => $total_fee, "body" => $body, "show_url" => $show_url, "anti_phishing_key" => $anti_phishing_key, "exter_invoke_ip" => $exter_invoke_ip, "_input_charset" => trim(strtolower($alipay_config['input_charset'])) ); // print_r($parameter);die; //建立请求 $alipaySubmit = new AlipaySubmit($alipay_config); $html_text = $alipaySubmit->buildRequestForm($parameter,"get", "确认"); echo $html_text; } public function actionNotifyUrl() { header("Content-type:text/html;charset=utf-8"); Yii::import('application.vendor.*'); require_once('alipay_core.function.php'); require_once('alipay_md5.function.php'); require_once('alipay_notify.class.php'); require_once('alipay_submit.class.php'); $alipay_config = Yii::app()->params['alipay_config']; //计算得出通知验证结果 $alipayNotify = new AlipayNotify($alipay_config); $verify_result = $alipayNotify->verifyNotify(); if ($verify_result) {//验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //请在这里加上商户的业务逻辑程序代 //——请根据您的业务逻辑来编写程序(以下代码仅作参考)—— //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表 $out_trade_no = $_POST['out_trade_no']; //商户订单号 $trade_no = $_POST['trade_no']; //支付宝交易号 $trade_status = $_POST['trade_status']; //交易状态 $total_fee = $_POST['total_fee']; //交易金额 $notify_id = $_POST['notify_id']; //通知校验ID。 $notify_time = $_POST['notify_time']; //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。 $buyer_email = $_POST['buyer_email']; //买家支付宝帐号; $parameter = array( "out_trade_no" => $out_trade_no, //商户订单编号; "trade_no" => $trade_no, //支付宝交易号; "total_fee" => $total_fee, //交易金额; "trade_status" => $trade_status, //交易状态 "notify_id" => $notify_id, //通知校验ID。 "notify_time" => $notify_time, //通知的发送时间。 "buyer_email" => $buyer_email, //买家支付宝帐号; ); if ($_POST['trade_status'] == 'TRADE_FINISHED') { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 if(!checkorderstatus($out_trade_no)){ orderhandle($parameter); //进行订单处理,并传送从支付宝返回的参数; } //注意: //该种交易状态只在两种情况下出现 //1、开通了普通即时到账,买家付款成功后。 //2、开通了高级即时到账,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月以内可退款、一年以内可退款等)后。 //调试用,写文本函数记录程序运行情况是否正常 // logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } else if ($_POST['trade_status'] == 'TRADE_SUCCESS') { //判断该笔订单是否在商户网站中已经做过处理 //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //如果有做过处理,不执行商户的业务程序 if(!checkorderstatus($out_trade_no)){ orderhandle($parameter); //进行订单处理,并传送从支付宝返回的参数; } //注意: //该种交易状态只在一种情况下出现——开通了高级即时到账,买家付款成功后。 //调试用,写文本函数记录程序运行情况是否正常 //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } //——请根据您的业务逻辑来编写程序(以上代码仅作参考)—— echo "success"; //请不要修改或删除 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } else { //验证失败 echo "fail"; } } public function actionReturnUrl(){ header("Content-type:text/html;charset=utf-8"); Yii::import('application.vendor.*'); require_once('alipay_core.function.php'); require_once('alipay_md5.function.php'); require_once('alipay_notify.class.php'); require_once('alipay_submit.class.php'); $alipay_config = Yii::app()->params['alipay_config']; $alipayNotify = new AlipayNotify($alipay_config);//计算得出通知验证结果 $verify_result = $alipayNotify->verifyReturn(); if($verify_result) { //验证成功 //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 $out_trade_no = $_GET['out_trade_no']; //商户订单号 $trade_no = $_GET['trade_no']; //支付宝交易号 $trade_status = $_GET['trade_status']; //交易状态 $total_fee = $_GET['total_fee']; //交易金额 $notify_id = $_GET['notify_id']; //通知校验ID。 $notify_time = $_GET['notify_time']; //通知的发送时间。 $buyer_email = $_GET['buyer_email']; //买家支付宝帐号; $parameter = array( "out_trade_no" => $out_trade_no, //商户订单编号; "trade_no" => $trade_no, //支付宝交易号; "total_fee" => $total_fee, //交易金额; "trade_status" => $trade_status, //交易状态 "notify_id" => $notify_id, //通知校验ID。 "notify_time" => $notify_time, //通知的发送时间。 "buyer_email" => $buyer_email, //买家支付宝帐号 ); if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') { if(!checkorderstatus($out_trade_no)){ orderhandle($parameter); //进行订单处理,并传送从支付宝返回的参数; } $this->redirect(Yii::app()->createUrl(Yii::app()->params['alipay']['successpage']));//跳转到配置项中配置的支付成功页面; }else { echo "trade_status=".$_GET['trade_status']; $this->redirect(Yii::app()->createUrl(Yii::app()->params['alipay']['errorpage']));//跳转到配置项中配置的支付失败页面; } }else { //验证失败 //如要调试,请看alipay_notify.php页面的verifyReturn函数 echo "验证失败!"; } } }
一下是两个上面控制器中用到的两个处理方法:我是写在了一个可以定义全局方法的functions.php文件中
你可以把这两个方法写在购物车或者其他的模型中进行调用
//在线交易订单支付处理函数 //函数功能:根据支付接口传回的数据判断该订单是否已经支付成功; //返回值:如果订单已经成功支付,返回true,否则返回false; function checkorderstatus($ordid){ $criteria = new CDbCriteria; $criteria->addCondition('trade_id = :ordid'); $criteria->params[':ordid'] = $ordid; $criteria->select = 'status'; $ordstatus = Shopcart::model()->find($criteria); if($ordstatus->status == 1){ return true; }else{ return false; } } //处理订单函数 //更新订单状态,写入订单支付后返回的数据 function orderhandle($parameter){ $ordid = $parameter['out_trade_no']; $buyer = $parameter['buyer_email']; $status = 1; $criteria = new CDbCriteria; $criteria->addCondition('trade_id = :ordid'); $criteria->params[':ordid'] = $ordid; $model = Shopcart::model()->find($criteria); $model->trade_account = $buyer; $model->status = $status; if($model->update()){ $income = new Income(); $income->uid = $model->uid; $income->recharge_money = $model->trade_money; $income->time = time(); $income->detail = "你在".$model->trade_paytime. " ,充值了".$model->trade_money." 个积分"; if($income->save()) { $user = User::model()->findByPk(Yii::app()->user->id); $have = $user->credit; $add = $model->trade_money; $user->credit = $have + $add; if($user->update()){ return true; } else { return false; } } else { return false; } } else { return false; }
由于yii初始路由方式为index.php?r=XX/XX 所以后面也算是带参的url,在支付成功后会出现验证失败的情况,解决办法是更改alipy_core.function.php中的paraFilter()方法
function paraFilter($para) { $para_filter = array(); while (list ($key, $val) = each ($para)) { if($key == "sign" || $key == "sign_type" || $val == "" || $key == 'r')continue; else $para_filter[$key] = $para[$key]; } return $para_filter; }