首先说下,支付宝提供的demo不一定完全正确,可能回缺少些步骤,所以,最好按照规则文档的步骤参照demo写。
先说遇到的问题:
1.错误0001,缺少partner、service等必参数
最初选择的sign_type ='0001' 即rsa 的加密方式,需要用到公钥和私钥。公钥和私钥在支付宝的demo中都有,只是,如果使用支付宝的公钥和私钥大家都知道,不太安全。所以,一般应该在自己的电脑上生成一个公钥和私钥http://hmifly.blog.163.com/blog/static/128583507201403111438312,公钥是用来加密的,私钥是用来解密的,所以我们项目中用的公钥是支付宝默认的公钥和私钥是自己生成的私钥,然后将自己生成的公钥上传到支付宝。这样,我们传给支付宝的数据通过支付宝默认的公钥加密,然后支付宝通过自己默认的私钥解密;而支付宝返回来的数据,通过我们上传的公钥加密,然后会穿到我们的项目中后,我们通过自己生成的私钥解密。流程是这样的,但后来闲麻烦,选择了MD5加密的方法,所以就不用公钥个私钥了。
2.错误0004,req_data 传参格式不正确
这是因为,在个支付宝传参时,用的是xml格式,而我们上传的nofifyurl 和returnurl等参数中包含&等特殊符号,后来,我将这部分数据改写成一个www.XXX.com/alipay_returnurl.php ,然后指向方法returnurl。然后数据就传过去了。或者可以通过<![CDADA[ $URL]]>,将含有特殊字符的链接地址阻止“编译”。
下面说下具体步骤:
1.和接及时到账接口一样,将支付宝的几个类和方法文件包含到Vender下
2.新建一个PayAction.class.php文件
接收参数较网站即时到账略有不同
<?php 2 header("content-type:text/html;charset=utf-8"); 3 class PayAction extends Action{ 4 5 //在类初始化方法中,引入相关类库 6 public function _initialize() { 7 8 9 //wap端的 10 vendor('AlipayWap.CorefunctionWap'); 11 vendor('AlipayWap.Md5functionWap'); 12 vendor('AlipayWap.NotifyWap'); 13 vendor('AlipayWap.SubmitWap'); 14 vendor('AlipayWap.RsafunctionWap'); 15 16 } 17 18 19 //wap端的 20 21 public function doalipay(){ 22 //echo "<pre>";var_dump( $_SERVER );echo "</pre>"; 23 //返回格式 24 $format = "xml";//必填,不需要修改//返回格式 25 $v = "2.0"; 26 //这里我们通过TP的C函数把配置项参数读出,赋给$alipay_config; 27 $alipay_config=C('alipay_config'); 28 29 /**************************请求参数**************************/ 30 $payment_type = C('alipay_config.sign_type'); //支付类型 //必填,不能修改 31 $notify_url = C('alipay.notify_urlWap'); //服务器异步通知页面路径 32 $return_url = C('alipay.return_urlWap');//页面跳转同步通知页面路径 33 $merchant_url = C('alipay.merchant_urlWap');//操作中断返回地址 34 $seller_email = C('alipay.seller_email');//卖家支付宝帐户必填 35 $out_trade_no = $_POST['trade_no']; //商户订单号 通过支付页面的表单进行传递,注意要唯一! 36 $subject = $_POST['ordsubject']; //订单名称 //必填 通过支付页面的表单进行传递 37 $total_fee = $_POST['ordtotal_fee']; //付款金额 //必填 通过支付页面的表单进行传递 38 $body = $_POST['ordbody']; //订单描述 通过支付页面的表单进行传递 39 $show_url = $_POST['ordshow_url'];//商品展示地址 通过支付页面的表单进行传递 40 $anti_phishing_key = "";//防钓鱼时间戳 //若要使用请调用类文件submit中的query_timestamp函数 41 //$exter_invoke_ip = get_client_ip();//var_dump($exter_invoke_ip);die(); //客户端的IP地址 42 $exter_invoke_ip = $_SERVER["REMOTE_ADDR"];//var_dump($exter_invoke_ip);die(); //客户端的IP地址 43 /************************************************************/ 44 45 //对前台传过来的价钱数据做判断 46 $orderId=$out_trade_no; 47 $oOb=M("order"); 48 $orderArr=$oOb->field("count(*) as num")->where("orderId='{$orderId}'")->select(); 49 $num=$orderArr[0]['num']; 50 if($num==0){ 51 $coOb = M("cardorder"); 52 $arr = $coOb->where("orderId='{$orderId}'")->select(); 53 //var_dump($arr); 54 $realPrice = $arr[0]['price'] - $arr[0]['discount'] - $arr[0]['yhqPrice']; 55 //var_dump($total_fee); var_dump($realPrice); die; 56 if($total_fee != $realPrice){ 57 header("location:index.php?m=Member&a=payFail"); 58 } 59 }else{ 60 61 $arr=$oOb->where("orderId='{$orderId}'")->select(); 62 $realPrice = $arr[0]['price'] - $arr[0]['discount'] - $arr[0]['yhq']; 63 64 if($total_fee != $realPrice){ 65 header("location:index.php?m=Member&a=payFail"); 66 } 67 } 68 $call_back_url = $return_url; 69 //请求业务参数详细 70 $req_data = '<direct_trade_create_req><notify_url>' . $notify_url . '</notify_url><call_back_url>' . $call_back_url . '</ call_back_url><seller_account_name>' . $seller_email . '</seller_account_name><out_trade_no>' . $out_trade_no . '</ out_trade_no><subject>' . $subject . '</subject><total_fee>' . $total_fee . '</total_fee><merchant_url>' . $merchant_url . '</ merchant_url></direct_trade_create_req>'; 71 //echo "req_data";var_dump($req_data);echo "----------------------------------"; 72 //必填 73 //构造要请求的参数数组,无需改动 74 $para_token = array( 75 "service" => "alipay.wap.trade.create.direct", 76 "partner" => trim($alipay_config['partner']), 77 "sec_id" => $payment_type, 78 "format" => $format, 79 "v" => $v, 80 "req_id" => $out_trade_no, 81 "req_data" => trim($req_data), 82 "_input_charset" => trim(strtolower($alipay_config['input_charset'])) 83 ); 84 //echo "<pre>";var_dump($para_token);echo "</pre>";die(); 85 //建立请求 86 $alipaySubmit = new AlipaySubmit($alipay_config); 87 88 $html_text = $alipaySubmit->buildRequestHttp($para_token); 89 //var_dump($html_text);die(); 90 //URLDECODE返回的信息 91 $html_text = urldecode($html_text); 92 //echo "<pre>";var_dump($html_text);echo "</pre>";die(); 93 //解析远程模拟提交后返回的信息 94 $para_html_text = $alipaySubmit->parseResponse($html_text); 95 //var_dump($para_html_text);die; 96 //获取request_token 97 $request_token = $para_html_text['request_token']; 98 99 //var_dump($request_token); 102 /**************************根据授权码token调用交易接口alipay.wap.auth.authAndExecute**************************/ 103 104 //业务详细 105 $req_data = '<auth_and_execute_req><request_token>' . $request_token . '</request_token></auth_and_execute_req>'; 106 //必填 107 108 $parameter = array( 109 "service" => "alipay.wap.auth.authAndExecute", 110 "partner" => trim($alipay_config['partner']), 111 "sec_id" => $payment_type, 112 "format" => $format, 113 "v" => $v, 114 "req_id" => $out_trade_no, 115 "req_data" => trim($req_data), 116 "_input_charset" => trim(strtolower($alipay_config['input_charset'])) 117 ); 118 //var_dump($parameter);die(); 119 $parameter1 = paraFilter($parameter); 120 $parameter2 = argSort($parameter); 121 //建立请求 122 $alipaySubmit = new AlipaySubmit($alipay_config); 123 $mysign = $alipaySubmit -> buildRequestMysign($parameter2); 124 $parameter2['sign'] = $mysign; 125 //echo "<pre>";var_dump($parameter2);echo "</pre>";die(); 126 $html_text = $alipaySubmit->buildRequestForm($parameter2,"get", "确认"); 127 echo $html_text; 128 } 129 130 function notifyurlWap(){ 131 132 $str= "111 "; 133 if(isset($_POST) && !empty($_POST)){ 134 foreach($_POST as $k=>$v){ 135 $str .= $k ."=>".$v." "; 136 } 137 } 138 file_put_contents("notifyurlWap.txt",$str,FILE_APPEND); 139 $alipay_config=C('alipay_config'); 140 //计算得出通知验证结果 141 $alipayNotify = new AlipayNotify($alipay_config); 142 $verify_result = $alipayNotify->verifyNotify(); 143 file_put_contents("notifyurlWap.txt",$verify_result,FILE_APPEND); 144 if($verify_result) { 145 //验证成功 146 file_put_contents("notifyurlWap.txt","验证成功",FILE_APPEND); 147 $doc = new DOMDocument(); 148 file_put_contents("notifyurlWap.txt","doc对象成功",FILE_APPEND); 149 $notify_data = $_POST['notify_data']; 150 $doc->loadXML($notify_data); 151 file_put_contents("notifyurlWap.txt",unserialize($doc),FILE_APPEND); 152 if( ! empty($doc->getElementsByTagName( "notify" )->item(0)->nodeValue) ) { 153 //商户订单号 154 $out_trade_no = $doc->getElementsByTagName( "out_trade_no" )->item(0)->nodeValue; 155 //支付宝交易号 156 $trade_no = $doc->getElementsByTagName( "trade_no" )->item(0)->nodeValue; 157 //交易状态 158 $trade_status = $doc->getElementsByTagName( "trade_status" )->item(0)->nodeValue; 159 $parameter = array( 160 "out_trade_no" => $out_trade_no, //商户订单编号; 161 "trade_no" => $trade_no, //支付宝交易号; 162 "trade_status" => $trade_status, //交易状态 163 ); 164 //file_put_contents("/index/paylog.txt",$parameter,FILE_APPEND); 165 file_put_contents("notifyurlWap.txt",$out_trade_no,FILE_APPEND); 166 file_put_contents("notifyurlWap.txt",$trade_no,FILE_APPEND); 167 file_put_contents("notifyurlWap.txt",$trade_status,FILE_APPEND); 168 if($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS') { 169 if(!checkorderstatus($out_trade_no)){ 170 orderhandle($parameter); 171 //进行订单处理,并传送从支付宝返回的参数; 172 } 173 } 174 echo "success"; //请不要修改或删除 175 } 176 }else { 177 //验证失败 178 echo "fail"; 179 } 180 } 181 182 function returnurlWap(){ 183 184 $alipay_config = C('alipay_config'); 185 $alipayNotify = new AlipayNotify($alipay_config);//计算得出通知验证结果 186 $verify_result = $alipayNotify->verifyReturn(); 187 //var_dump($_GET); 188 if($verify_result) { 189 //验证成功 190 //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 191 $out_trade_no = $_GET['out_trade_no']; //商户订单号 192 $trade_no = $_GET['trade_no']; //支付宝交易号 193 $trade_status = $_GET['result']; //交易状态 194 195 $parameter = array( 196 "out_trade_no" => $out_trade_no, //商户订单编号; 197 "trade_no" => $trade_no, //支付宝交易号; 198 "trade_status" => $trade_status, //交易状态 199 ); 200 201 //echo "<pre>";var_dump($parameter);echo "</pre>";die(); 202 203 if($_GET['result'] == 'success' ) { 204 if(!checkorderstatus($out_trade_no)){ 205 orderhandle($parameter); //进行订单处理,并传送从支付宝返回的参数; 206 //die(); 207 } 208 $this->redirect(C('alipay.successpage'));//跳转到配置项中配置的支付成功页面; 209 }else { 210 //echo "trade_status=".$_GET['trade_status']; 211 $this->redirect(C('alipay.errorpage'));//跳转到配置项中配置的支付失败页面; 212 } 213 }else { 214 //验证失败 215 //如要调试,请看alipay_notify.php页面的verifyReturn函数 216 echo "支付失败!"; 217 } 218 } 219 220 }
3.在index/Common/common.php中加入两个函数,在上面Action中调用
//判断订单的状态是否已经修改 function checkorderstatus($orderId){ 94 $oOb=M("order"); 95 $cOb=M('cardorder'); 96 $orderArr=$oOb->field("count(*) as num")->where("orderId='{$orderId}'")->select(); 97 $num=$orderArr[0]['num']; 98 if($num==0){ 99 $ordstatus=$cOb->where("orderId='".$orderId."'")->getField('status'); 100 }else{ 101 $ordstatus=$oOb->where("orderId='".$orderId."'")->getField('status'); 102 } 103 if($ordstatus==1){ 104 return false; 105 }else{ 106 return true; 107 } 108 }
function orderhandle($parameter){ 112 123 $orderId=$parameter['out_trade_no']; 124 $oOb=M("order"); 125 $orderArr=$oOb->field("count(*) as num")->where("orderId='{$orderId}'")->select(); 126 $num=$orderArr[0]['num']; 130 $date=date("Y-m-d H:i:s"); 131 if($num==0){ 132 $coOb=M("cardorder"); 133 $arr=$coOb->where("orderId='{$orderId}'")->select(); 134 //echo "<pre>";var_dump($arr);echo "</pre>"; 135 $pid=$arr[0]['pid']; 136 $coOb->query("update r_cardorder set status=2,updateTime='{$date}' where orderId='{$orderId}'"); 137 //echo $coOb->getLastSql(); 138 $cOb=M("card"); 139 $cOb->query("update r_card set store=store-1 where id={$pid}"); 140 $cArr=$cOb->where("id={$pid}")->select(); 141 $buyedOb=M("buyedcard"); $type = $cArr[0]['type']; 152 $buyedArr=array("CCID"=>$arr[0]['CCID'],"type"=>$type,"beginTime"=>$cArr[0]['beginTime'],"endTime"=>$cArr[0]['endTime'], "data"=>$cArr[0]['data']); 153 $re2=$buyedOb->data($buyedArr)->add(); 154 $yhqId=$arr[0]['yhqId']; 155 if($yhqId!=0){ 156 $yOb=M("yhq"); 157 $yOb->query("update r_yhq set status=2,updateTime='{$date}' where id={$yhqId}"); 158 } 159 160 }else{ 161 $arr=$oOb->where("orderId='{$orderId}'")->select(); 162 //var_dump($arr); 163 $pid=$arr[0]['pid']; 164 $oOb->query("update r_order set status=2 ,updated_at='{$date}' where orderId='{$orderId}'"); 165 $ob=M("product"); 166 $ob->query("update r_product set store=store-1 where id={$pid}"); 167 }
4.修改配置文件 index/config.php
共5个必传参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//支付宝配置参数 36 'alipay_config' =>array( 37 'partner' => '1234567890123456' , //这里是你在成功申请支付宝接口后获取到的PID; 38 'key' => 'qwaszxasqwqi07jyl6eudgzdfcmtpmxu' , //这里是你在成功申请支付宝接口后获取到的Key 39 'sign_type' =>strtoupper( 'MD5' ), 40 'input_charset' => strtolower( 'utf-8' ), 41 'cacert' => getcwd(). '\cacert.pem' , 42 'transport' => 'http' , 43 ), 44 46 47 'alipay' =>array( 48 //这里是卖家的支付宝账号,也就是你申请接口时注册的支付宝账号 49 'seller_email' => 'xxx@xxx.cn' , 50 //这里是异步通知页面url,提交到项目的Pay控制器的notifyurl方法; 51 //'notify_url'=>'http://www.xxx.com/index.php?m=Pay&a=notifyurlWap', 53 //这里是页面跳转通知url,提交到项目的Pay控制器的returnurl方法; 55 //支付成功跳转到的页面,我这里跳转到项目的Member控制器,myorder方法,并传参payed(已支付列表) |
5.在html中将支付宝必要的参数传到PayAction.class.php 里的doalipay 中,html文件如下:
<form action="?m=Pay&a=doalipay" method="post" id="form"> 237 238 <div class="title1 clear"> 239 <div class="leftt"> 240 <img style="margin: 0.4em" src="{{$pArr.thumbimg}}" class="iconimg" width="100%"> 241 </div> 242 <div class="desc"> 243 <h2>{{$pArr.title}}</h2> 244 245 <div>价格:¥{{$pArr.price-$pArr.discount}} 元</div> 246 247 </div> 248 <input type="hidden" name="trade_no" value="{{$orderId}}"><!--订单号--> //必传 249 250 <input type="hidden" name="ordsubject" value="WiFi随身宝"><!--订单名称--> //必传 251 <input type="hidden" name="ordbody" value="{{$data}}"><!--订单描述--> //必传 252 </div> 253 254 255 <input type="hidden" name="ordtotal_fee" value="{{$pArr.price-$pArr.discount}}" id="priceNew"><!--总金额--> //必传 256 <input type="hidden" name="ordshow_url" value="http://m.heimiwifi.com/index.php?m=Product&a=detail_buy&id={{$pArr.id}}"><!--商品展示url--> //必传 257 258 </div> 259 260 <div class="card_pay"> 261 <div class="cp_title">选择支付方式</div> 262 <div class="pay_div clear pay_div1"> 263 <div class="pay_left"> 264 <img width="100%" src="__ROOT__/index/Tpl/images/checked.png" id="pay1"> 265 </div> 266 <div class="pay_middle"> 267 <img width="100%" src="__ROOT__/index/Tpl/images/alipayicon.png"> 268 </div> 269 <div class="pay_right clear pay_div2"> 270 <span class="p1">支付宝在线支付</span>
284 </div>
285 </div>
286 </div>
287
288 <div class="sureOrderBtn">
289 <div class="sure_left">
290 <h2 style="color:#e54a3e;">应付金额:¥<span id="totalprice">{{$pArr.price-$pArr.discount}}</span> 元</h2>
291 </div>
292 <div class="sure_right">
293 <img style="line-height:140px" width="100%" src="__ROOT__/index/Tpl/images/ok.gif" id="orderBtn" >
294 </div>
295
296 </div>
297 </form>
tip:
可能整合完后在跳到支付宝页面时会有一个确定按钮,显示几秒钟后自动跳转,想要隐藏这个按钮,只要在支付宝提供的类文件submit.php中将方法buildRequestForm中的 $sHtml = $sHtml."<input type='submit' value='".$button_name."' ></form>";改成$sHtml = $sHtml."<input type='submit' value='".$button_name."' style='display:none;'></form>"; 即可