项目环境:thinkphp
感叹:到处是坑!!!!!
注意点:第一点,网页授权获取openid,应用微信插件laneWeChat (微信开发框架)
第二点,获取openid要跳转几次页面把openid值保存到session中或是url地址中
第三点,授权目录的地址与访问地址的大小写要一直
流程:
1,下载插件lanewechat放到thinkphp,verdor目录底下,并配置好
代码段配置
微信端配置
2,入口页面函数
public function new_pay(){
//全局引入微信支付类
vendor('WxPay.lib.WxPay.Api');
//=========步骤1:网页授权获取用户openid============
//①、获取用户openid
$tools = new \JsApiPay();
$openId = $tools->GetOpenid();
}
3,进入getopenid()类,此时进入的code为空值,跳转到Paynew目录下getcode控制器index函数
public function GetOpenid($fromurl)
{
if (!isset($_GET['code'])){
//触发微信返回code码
$baseUrl = urlencode('http://luochao.tunnel.qydev.com/yershopv/index.php/PayNew/GetCode/index'.$_SERVER['QUERY_STRING']);
$url = $this->__CreateOauthUrlForCode($baseUrl);
Header("Location:$url");
redirect($url);
exit();
} else {
//获取code码,以获取openid
$code = $_GET['code'];
$openid = $this->getOpenidFromMp($code);
redirect(session('ect')."?openid=".$openid);
return $openid;
}
}
4,getcode控制处理,载入lanewechat类插件获得code值,根据code值获取openid值,把openid值保存到session或url中都可以,在跳转
<?php namespace PayNew\Controller; vendor('LaneWeChat.lanewechat'); use LaneWeChat\Core\WeChatOAuth; class GetCodeController { function index() { //第一步,获取CODE //此时页面跳转到了http://www.lanecn.com/index.php,code和state在GET参数中。 $code = $_GET['code']; echo "code:".$code."<br>"; echo "ur:".$ur."<br>"; //第二步,获取access_token网页版 $openId = WeChatOAuth::getAccessTokenAndOpenId($code); //获得openid值 $opid = $openId['openid']; echo 'openid='.$opid."<br>"; //第三步,获取用户信息 $ur = "http://luochao.tunnel.qydev.com/yershopv/index.php/Wxpay/getOpenid.html"; // $_SESSION["openid"]=$opid; $url=$ur."?openid=".$opid; //把openid值存到url中 echo $url; redirect($url); //跳转到指定页面 } } 5,在url中获取openid值,并执行一下步骤
function getOpenid() { $url = $_SERVER['QUERY_STRING']; //获取url地址“?”后面的字符串“openid=xxxxxxxxx” $openidurl = explode('=',$url); //已“=”分隔为数组 $openid = $openidurl[1]; // 拿到openid的值 //②、统一下单 $tools = new \JsApiPay(); $input = new \WxPayUnifiedOrder(); $input->SetBody("test");//商品或支付单简要描述 $input->SetAttach("test");//附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据 $input->SetOut_trade_no(\WxPayConfig::MCHID . date("YmdHis")); $input->SetTotal_fee("1");//订单总金额,只能为整数,单位为分 $input->SetTime_start(date("YmdHis"));//订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010 $input->SetTime_expire(date("YmdHis", time() + 600));//订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010 $input->SetGoods_tag("test");//商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠 $input->SetNotify_url(dirname('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']) . '/notify.php'); $input->SetTrade_type("JSAPI");//取值如下:JSAPI,NATIVE,APP $input->SetOpenid($openid);//trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。下单前需要调用【网页授权获取用户信息】接口获取到用户的Openid $order = \WxPayApi::unifiedOrder($input);//统一下单 接口 //这里的openid值传错会出现签名错误,key值错误也会出现签名错误,参数要传正确 echo '<font color="#f00"><b>订单信息</b></font><br/>'; $jsApiParameters = $tools->GetJsApiParameters($order);//jsapi支付的参数 //获取共享收货地址js函数参数 $editAddress = $tools->GetEditAddressParameters(); $this->assign('jsApiParameters', $jsApiParameters); $this->assign('editAddress', $editAddress); $this->display(); } 6,视图页面(getopenid.html),直接拿的微信官方页面,要做一些修改 把原来的
// WeixinJSBridge.log(res.err_msg); // alert(res.err_code+res.err_desc+res.err_msg); 注释掉,改成红色区域代码快,目的是判断支付结果,若支付成功跳转到控制器jsapisuccess函数(url传个orderid过去)
function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, function(res){ //判断支付结果跳转到cotroll函数页面,做订单支付成功处理,传orderid if (res.err_msg == 'get_brand_wcpay_request:cancel') { alert("您已取消了此次支付"); // document.location.href = "http://"+location.hostname+"/index.php?g=Mpage&m=MManage&a=PayFail&orderid="+{$orderid}; return; } else if (res.err_msg == 'get_brand_wcpay_request:fail') { alert("支付失败,请重新尝试"); return; } else if (res.err_msg == 'get_brand_wcpay_request:ok') { alert("支付成功!"); document.location.href = 'http://luochao.tunnel.qydev.com/yershopv/index.php/Pay/jsapisuccess.html?orderid={$orderid}'; } else { alert("未知错误" + res.error_msg); return; } // WeixinJSBridge.log(res.err_msg); // alert(res.err_code+res.err_desc+res.err_msg); } ); }
7,支付成功跳转过来到 pay/jsapisuccess 处理付款成功后的订单
/** * jsapi支付成功 */ public function jsapisuccess(){ //获取url地址问号后面的字符“orderid=xxxxxxx”,分隔为数组,去除orderid值 $url = $_SERVER['QUERY_STRING']; $orderidurl = explode('=',$url); $orderid = $orderidurl[1]; if ( !empty($orderid) ){ //orderid判断不为空 /**订单支付成功操作*/ $jsapiMoney = session("jsapiMoney");//从seesion获取到支付金额 支付提交是要把金额保存到session,在这里调用 $money = $jsapiMoney / 100 ; /*修改订单状态为已支付*/ $dataa = array('status'=>'1','ispay'=>'2');//订单已经支付,状态为已提交 $info = M('order')->where(array('tag' => $orderid))->setField($dataa); if(!empty($info)){ } else{ M('order')->where(array('orderid' => $orderid))->setField($dataa); } /*支付完后写入到支付表中*/ M("Pay")->add(array( 'out_trade_no' => $orderid, 'money' => $money, 'status' => 0, 'create_time' => time(), 'update_time' => time() )); $this->display('Pay/over'); } } 8,跳转到Pay/over支付完成页面,至此整个jsapi支付流程完成