这篇文章主要介绍扫码支付场景二。
目前有两种模式,模式一比模式二稍微复杂点,至于模式一与模式二的具体内容,流程,微信开发文档都有详细介绍,这里就不多说废话,接下来赶紧上教程!
[title]下载SDK类文件[/title]
并SDK文件/lib下的几个文件放置到/ThinkPHP/Library/Vendor/
[title]修改WxPay.pub.config.php中的配置选项[/title]
//=======【基本信息设置】===================================== //微信公众号身份的唯一标识。审核通过后,在微信发送的邮件中查看 const APPID = '公众号表示ID'; //受理商ID,身份标识 const MCHID = '商户ID'; //商户支付密钥Key。审核通过后,在微信发送的邮件中查看 const KEY = 'KEY密匙'; //JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看 const APPSECRET = 'SECRET密匙'; //=======【JSAPI路径设置】=================================== //获取access_token过程中的跳转uri,通过跳转将code传入jsapi支付页面 const JS_API_CALL_URL = 'http://www.laoji.org'; //=======【证书路径设置】===================================== //证书路径,注意应该填写绝对路径 const SSLCERT_PATH = "__ROOT__\paypem\\apiclient_cert.pem"; const SSLKEY_PATH = "__ROOT__\paypem\\apiclient_key.pem"; //=======【异步通知url设置】=================================== //异步通知url,商户根据实际开发过程设定 const NOTIFY_URL = 'http://www.laoji.org/wxpay/notify'; //=======【curl超时设置】=================================== //本例程通过curl使用HTTP POST方法,此处可修改其超时时间,默认为30秒 const CURL_TIMEOUT = 30;
[title]新建微信的Controller方法,目录位置为:\Application\Home\Controller\WxpayController.class.php [/title]
<?php /** * WxpayController.class.php * 微信支付控制器 * 网站地址: https://www.jiloc.com/43212.html * Author: 老季 ( admin@laoji.org ) * Date: 2017年4月18日 */ namespace Home\Controller; class WxpayController extends HomeController { //初始化 public function _initialize() { //引入类文件 vendor('Wxpay.WxPayPubHelper'); } private function makeOrder($ary){ $data = array(); $data['userid'] = session('user_auth')['uid']; if ( !$data['userid'] ){ $this->error('用户ID错误! -> '.$data['uid'],'/my/publishlist'); } // 检查船舶信息 $data['shipinfoid'] = $ary['id']; $ShipInfo = M('ShipInfo')->where(array('id'=>$ary['id']))->find(); if( !$ShipInfo ){ $this->error('信息ID错误! -> '.$ary['id'],'/my/publishlist'); } // 检查支付价格 $data['ordercatid'] = $ary['catid']; $OrderCat = M('OrderCat')->where(array('id'=>$ary['catid']))->find(); if( !$OrderCat ){ $this->error('产品价格错误! -> '.$ary['catid'],'/my/publishlist'); } $data['ordid'] = "LJ".$ary['TYPE'].date('YmdHis',time()).rand(11,99); $data['ordtime'] = time(); $data['ordtitle'] = $ShipInfo['title']; $data['ordbuydays'] = $OrderCat['days']; $data['ordfee'] = $data['ordprice'] = $OrderCat['price']; $data['status'] = 0; M('OrderList')->add($data); return $data['ordid']; } //生成二维码 public function qrcode() { // 生成订单 $_POST['TYPE'] = 'W'; $out_trade_no = $this->makeOrder($_POST); $ordtotal_fee = str_replace(".","",$_POST['ordtotal_fee']*100); //使用统一支付接口 $unifiedOrder = new \UnifiedOrder_pub(); //设置统一支付接口参数 //设置必填参数 $unifiedOrder->setParameter("body",$_POST['ordsubject'] );//商品描述 //自定义订单号,此处仅作举例 $timeStamp = time(); $unifiedOrder->setParameter("out_trade_no",$out_trade_no);//商户订单号 $unifiedOrder->setParameter("total_fee",$ordtotal_fee);//总金额 $unifiedOrder->setParameter("notify_url", \WxPayConf_pub::NOTIFY_URL);//通知地址 $unifiedOrder->setParameter("trade_type","NATIVE");//交易类型 //非必填参数,商户可根据实际情况选填 //$unifiedOrder->setParameter("sub_mch_id","XXXX");//子商户号 //$unifiedOrder->setParameter("device_info","XXXX");//设备号 //$unifiedOrder->setParameter("attach","XXXX");//附加数据 //$unifiedOrder->setParameter("time_start","XXXX");//交易起始时间 //$unifiedOrder->setParameter("time_expire","XXXX");//交易结束时间 // $unifiedOrder->setParameter("goods_tag","");//商品标记 // $unifiedOrder->setParameter("openid","19405");//用户标识 //$unifiedOrder->setParameter("product_id","XXXX");//商品ID //获取统一支付接口结果 $unifiedOrderResult = $unifiedOrder->getResult(); // var_dump($unifiedOrder); //商户根据实际情况设置相应的处理流程 if ($unifiedOrderResult["return_code"] == "FAIL") { //商户自行增加处理流程 echo "通信出错:".$unifiedOrderResult['return_msg']."<br>"; } elseif($unifiedOrderResult["result_code"] == "FAIL") { //商户自行增加处理流程 echo "错误代码:".$unifiedOrderResult['err_code']."<br>"; echo "错误代码描述:".$unifiedOrderResult['err_code_des']."<br>"; } elseif($unifiedOrderResult["code_url"] != NULL) { //从统一支付接口获取到code_url $code_url = $unifiedOrderResult["code_url"]; //商户自行增加处理流程 //...... } $this->assign('title',$_POST['ordsubject']); $this->assign('total_fee',$_POST['ordtotal_fee']); $this->assign('out_trade_no',$out_trade_no); $this->assign('code_url',urlencode($code_url)); $this->assign('unifiedOrderResult',$unifiedOrderResult); $this->display(); } public function notify() { //使用通用通知接口 $notify = new \Notify_pub(); //存储微信的回调 $xml = $GLOBALS['HTTP_RAW_POST_DATA']; $notify->saveData($xml); // var_dump($xml); //验证签名,并回应微信。 //对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败, //微信会通过一定的策略(如30分钟共8次)定期重新发起通知, //尽可能提高通知的成功率,但微信不保证通知最终能成功。 if($notify->checkSign() == FALSE){ $notify->setReturnParameter("return_code","FAIL");//返回状态码 $notify->setReturnParameter("return_msg","签名失败");//返回信息 }else{ $notify->setReturnParameter("return_code","SUCCESS");//设置返回码 } $returnXml = $notify->returnXml(); echo $returnXml; //==商户根据实际情况设置相应的处理流程,此处仅作举例======= //以log文件形式记录回调信息 // $log_ = new Log_(); // $log_name= __ROOT__."/Public/notify_url.log";//log文件路径 // $this->log_result($log_name,"【接收到的notify通知】:\n".$xml."\n"); if($notify->checkSign() == TRUE) { if ($notify->data["return_code"] == "FAIL") { //此处应该更新一下订单状态,商户自行增删操作 log_result($log_name,"【通信出错】:\n".$xml."\n"); $this->error("通信出错"); } elseif($notify->data["result_code"] == "FAIL"){ //此处应该更新一下订单状态,商户自行增删操作 // log_result($log_name,"【业务出错】:\n".$xml."\n"); $this->error("业务出错"); } elseif( $notify->data['return_code'] == "SUCCESS" && $notify->data['result_code'] == "SUCCESS"){ $out_trade_no = $notify->data['out_trade_no']; $parameter = array( "out_trade_no" => $notify->data['out_trade_no'], //商户订单编号; "transaction_id" => $notify->data['transaction_id'], //微信支付订单号 "total_fee" => $notify->data['total_fee'], //交易金额; "result_code" => "SUCCESS", //交易状态 "time_end" => $notify->data['time_end'], //支付完成时间 "openid" => $notify->data['openid'], //用户标识 ); if (!$this->checkorderstatus($out_trade_no)){ $this->orderhandle($parameter); } return true; //$this->success("支付成功!"); } else{ //此处应该更新一下订单状态,商户自行增删操作 // log_result($log_name,"【支付成功】:\n".$xml."\n"); $this->error("UNKNOW ERROR"); } //商户自行增加处理流程, //例如:更新订单状态 //例如:数据库操作 //例如:推送支付完成信息 } } //查询订单 public function orderQuery() { if($this->checkorderstatus( I('post.out_trade_no') )){ $this->ajaxReturn("SUCCESS"); }; $this->ajaxReturn("FAILD"); } //在线交易订单支付处理函数 //函数功能:根据支付接口传回的数据判断该订单是否已经支付成功; //返回值:如果订单已经成功支付,返回true,否则返回false; private function checkorderstatus($ordid){ $ordstatus=M('OrderList')->where(array('ordid'=>$ordid))->getField('ordstatus'); if($ordstatus==1){ return true; }else{ return false; } } //处理订单函数 //更新订单状态,写入订单支付后返回的数据 private function orderhandle($parameter){ $ordid=$parameter['out_trade_no']; $data['payment_trade_no'] =$parameter['transaction_id']; $data['payment_trade_status'] =$parameter['result_code']; $data['payment_notify_time'] =$parameter['time_end']; $data['payment_buyer_email'] =$parameter['openid']; $data['ordstatus'] =1; M('OrderList')->where(array('ordid'=>$ordid))->save($data); $Order = M('OrderList')->where(array('ordid'=>$ordid))->find(); $ship_due_date = M("ShipInfo")->where(array('id'=>$Order['shipinfoid']))->find(); if( $ship_due_date['due_date'] > time() ){ $due_date = $ship_due_date['due_date']+($Order['ordbuydays']*86400); }else{ $due_date = strtotime("+".$Order['ordbuydays']." day"); } M('ShipInfo')->where(array('id'=>$Order['shipinfoid']))->save(array('due_date'=>$due_date,'status'=>1,'top'=>1)); return ; } }
[title]
二维码生成页面的html,目录位置\Application\Home\View\default\Wxpay\qrcode.html
[/title]
<extend name="Base/common"/> <block name="body"> <div class="center clearfix"> <div class="bread"> <a class="link" href="/">首页></a><span class="on">支付页面</span> </div> <div class="pay_con_zl"> <div class="p_tit_zl">支付页面</div> <div class="p_info_zl"> <p>标题:{$title}</p> <p>支付金额:<span style="font-size:24px; font-weight:bold; color:#F00;">¥{$total_fee}元</span>,请使用微信扫描下方二维码完成支付<span style="padding-left:20px; color:#F00;">2小时之内,请尽快扫描支付</span></p> <P><img alt="扫码支付" src="https://www.jiloc.com/wp-content/uploads/20170409040501NP4.jpg" style="width:150px;height:150px;"/></P> </div> </div> </div> <script language="JavaScript"> function Check(){ var out_trade_no = "{$out_trade_no}"; $.post("{:U('wxpay/orderQuery')}", { out_trade_no: out_trade_no}, function(data){ if(data == "SUCCESS"){ window.location = '{:U("my/paystatus",array("ordtype"=>"payed"))}'; } }); } window.setInterval("Check()",3000); </script> </block>
表单提交以后则跳转到二维码生成页面,提交地址:/wxpay/qrcode ,效果如下图:
微信客户端支付成功以后,该页面会自动跳转到支付成功页面。
[title]回调数据库表建立[/title]
[title]微信平台配置[/title]
微信公众平台上的配置了,这里我遇到过问题,如果有在这里遇到问题的同学请留言,比如出现了access_deined或者access_notallowed等问题,这都可能是因为这里配置不对。
请看配置过程截图:
支付授权目录设置为:http://laoji.org/wxpay/
[title]注意:[/title]
微信支付订单中的totla_fee的单位为分,比如1元,传值为100(分)