微信支付jsapi
20200701微信支付
JsApi(在手机微信中打开进行支付)
1.引入api包
下载php版本API
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
注:
1.tp5.1框架下,将API文件中子文件夹放入extend/wxpay中
2.若使用框架,请以public为当前路径,进行文件路径处理
3.接收回调时,先写入文件,在读取文件,直接读取可能为空
2.准备参数
//微信商户信息
const APPID = ''; //商户唯一标识 const MCHID = ''; //商户收款账号 const KEY = ''; //交易过程生成签名的密钥 const APPSECRET = ''; //AppSecret是APPID对应的接口密码,用于获取接口调用凭证access_token时使用
3.获取openID
//判断是否有openId public function initialize(){ if(session('?openid')){ $openid = session('openid'); }else{ $weixin=new \app\admin\controller\Weixin(); //获取openId $weixin->getUserOpenId(); } } /** * 获取用户openid */ public function getUserOpenId(){ $request = Request::instance(); $method = $request->method(); $code= $request->get('code'); if(empty($code)){ $redirect_uri = urlencode("http://xxx/pay_test/public/wxpay/openid"); $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".$this->appid."&redirect_uri=".$redirect_uri."&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect"; $this->redirect($url); }else{ // 获取页面授权的access_token $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$this->appid."&secret=".$this->appsecret."&code=".$code."&grant_type=authorization_code"; // 3、拉取用户的openid $res = $this->http_curl($url,'get'); $access_token = $res["access_token"]; $openid = $res['openid']; if($openid){ //拉取成功 session('openid',$openid,'think'); session('access_token',$access_token,'think'); $this->redirect('/pay_test/public/wxpay'); }else{ //拉取失败 $this->error("openid拉取失败!"); } } } /** * $url 接口url * $type 请求类型 * $res 返回数据类型 * $arr post请求参数 */ public function http_curl($url, $type='get', $res='json', $arr=' '){ // 1、初始化curl $ch = curl_init(); // 2、设置curl参数,默认get方法请求的 curl_setopt($ch, CURLOPT_URL, $url); // 设置url curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 返回 //post方法请求 if($type == 'post') { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $arr); } // 3、采集(抓取) $output = curl_exec($ch); if($res == 'json') { if(curl_errno($ch)) { // 请求失败,返回错误信息 return curl_error($ch); }else { return json_decode($output, true); } } // 4、关闭curl curl_close($ch); }
4.统一下单
//统一下单 public function pay(){ $request = Request::instance(); //付款金额(分) $price = 1; $openid = session('openid'); if(!empty($openid)){ //微信支付生成 ini_set('date.timezone','Asia/Shanghai'); require_once "../extend/wxpay/lib/WxPay.Api.php"; include_once "../extend/wxpay/example/WxPay.JsApiPay.php"; require_once '../extend/wxpay/example/log.php'; require_once '../extend/wxpay/example/WxPay.Config.php'; $wxpay = new \WxPayApi(); $tools = new \JsApiPay(); $out_trade_no = "".date('YmdHis') . str_pad(mt_rand(1, 99999), 5, '0', STR_PAD_LEFT); //付款后回调地址 $notifyurl="http://xxx/pay_test/public/wxpay/redata"; //统一下单 $input = new \WxPayUnifiedOrder(); //商品描述 $input->SetBody("测试订单"); //商户订单号 $input->SetOut_trade_no($out_trade_no); //附加数据 $input->SetAttach("测试附加数据"); //标价金额 $input->SetTotal_fee($price); //交易起始时间 $input->SetTime_start(date("YmdHis")); //交易结束时间 $input->SetTime_expire(date("YmdHis", time() + 600)); //订单优惠标记 $input->SetGoods_tag("测试优惠标记"); //通知地址 $input->SetNotify_url($notifyurl); //交易类型 $input->SetTrade_type("JSAPI"); //用户标识 $input->SetOpenid($openid); $config = new \WxPayConfig(); //获取统一下单数据 $wxdata = $wxpay->unifiedOrder($config,$input); $jsApiParameters = $tools->GetJsApiParameters($wxdata); return ["code"=>0,"data"=>$jsApiParameters,"out_trade_no"=>$out_trade_no,"price"=>$price]; }else{ return ["code"=>-1,"msg"=>"openid不能为空"]; } }
5.jsapi支付
//微信支付JsApi public function index(){ //统一下单 $data = $this->pay(); //返回数据 $redata= $data['data']; //字符串转数组 $redata = json_decode($redata); foreach($redata as $k=>$val){ //获取package if( $k == "package"){ $targer = $val; } //获取nonceStr if($k == 'nonceStr'){ $noncestr = $val; } //获取paySign if($k == 'paySign'){ $sign = $val; } //获取timeStamp if($k == 'timeStamp'){ $time = $val; } } $out_trade_no = $data['out_trade_no']; $price = $data['price']; $this->assign('out_trade_no',$out_trade_no); $this->assign('price',$price); $this->assign('package',$targer); $this->assign('noncestr',$noncestr); $this->assign('sign',$sign); $this->assign('time',$time); return view('index'); }
6.调出微信支付插件
<script src="/pay_test/public/static/admin/js/jquery-3.1.1.min.js" type="text/javascript"></script> <script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script> <script> var nonceStr = "{$noncestr}"; var time = "{$time}"; var paySign = "{$sign}"; var package = "{$package}"; var out_trade_no = "{$out_trade_no}"; var price = "{$price}"; </script> <script> function onBridgeReady(){ WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId":"xxx", //公众号名称,由商户传入 "timeStamp":time, //时间戳,自1970年以来的秒数 "nonceStr":nonceStr, //随机串 "package":package, "signType":"MD5", //微信签名方式: "paySign":paySign //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ){ // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠 location.href = "http://xxx/redata?sign="+paySign+"&price="+price; } }); } if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } }else{ onBridgeReady(); } </script>
7. 支付成功,接收回调
public function redata(){
$get_data = request()->get(); //接收微信返回信息 $redata = file_get_contents("php://input"); //服务器根目录 define('BASE_PATH',$_SERVER['DOCUMENT_ROOT']); //文件目录 $dir = BASE_PATH.'/pay_test/public/uploads/admin/wxpay/'.date("Ymd")."/"; //文件名 $filepath = date('Y-m-d h:i:s', time())."txt"; //判断是否有该目录 if(!file_exists($dir)){ //创建目录 mkdir($dir,0777,true); } //写入接收到的信息 file_put_contents($dir.$filepath,$redata,FILE_APPEND); //获取文件中信息,转为字符串 $data = file_get_contents($dir.$filepath); //转为数组 $redata_array = (array)simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA); var_dump($redata_array); return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; }