php微信jsapi支付 支付宝支付 两码合一
产品开会提出了这样的需求:一个二维码可以微信支付也可以支付宝支付
经过自己的钻研以及询问技术高人(本人代码一般般)和网上搜索 最终实现其功能 我用微信jsapi 和 支付宝网页支付
其实并不怎么难:
1.微信jsapi支付流程(微信官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)
2.支付宝支付流程
好了废话不多说 开始开发 代码上(Tp5开发)
首先 需要生成一个二维码这个想必大家都会吧!!! phpqrcode(下载地址:https://sourceforge.net/projects/phpqrcode/ )
1 require_once ROOT_PATH.'/phpqrcode/phpqrcode.php'; 2 $value='http://'.$_SERVER['HTTP_HOST'].'/admin.php/pay/wx_zfb; //二维码链接 (这个是重中之重!!!) 3 $errorCorrectionLevel = 'H';//容错级别 4 $matrixPointSize = 6;//生成图片大小 5 //生成二维码图片 6 QRcode::png($value, 'code/1.png', $errorCorrectionLevel, $matrixPointSize, 2); 7 $logo = 'code/kunchuan.png';//准备好的logo图片 8 $QR = 'code/1.png';//已经生成的原始二维码图 9 if ($logo !== FALSE) { 10 $QR = imagecreatefromstring(file_get_contents($QR)); 11 $logo = imagecreatefromstring(file_get_contents($logo)); 12 /* $QR = imagecreatefrompng($QR); 13 $logo = imagecreatefrompng($logo);*/ 14 if (imageistruecolor($logo)) 15 { 16 imagetruecolortopalette($logo, false, 65535);//添加这行代码来解决颜色失真问题 17 } 18 19 $QR_width = imagesx($QR);//二维码图片宽度 20 $QR_height = imagesy($QR);//二维码图片高度 21 $logo_width = imagesx($logo);//logo图片宽度 22 $logo_height = imagesy($logo);//logo图片高度 23 $logo_qr_width = $QR_width / 5; 24 $scale = $logo_width/$logo_qr_width; 25 $logo_qr_height = $logo_height/$scale; 26 $from_width = ($QR_width - $logo_qr_width) / 2; 27 //重新组合图片并调整大小 28 imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width, 29 $logo_qr_height, $logo_width, $logo_height); 30 } 31 32 $lujing = 'code/merge1'.png'; 33 34 //输出图片 35 imagepng($QR,$lujing); 36 return '<img src="http://'.$_SERVER['HTTP_HOST'].'/'.$lujing.'" alt="使用微信或者支付宝扫描支付">';
ok我们就生成一个二维码 因为个人隐私 我就生成了一个百度的二维码
通过扫描二维码 我们跳转到 wx_zfb方法:
public function wx_zfb() { //根据自己的需求 链接上边有参数就接值 没有就不做判断 // if($this->request->isGet()) // { //在PHP中HTTP_USER_AGENT是用来获取用户的相关信息的,包括用户使用的浏览器,操作系统等信息, $http_user_agent = $_SERVER['HTTP_USER_AGENT']; if (strpos($http_user_agent, 'MicroMessenger'))
{
$url="code”;//处理微信支付的方法 header("location:{$url}"); exit; }elseif (strpos($http_user_agent, 'AlipayClient')) { //支付宝链接
$url="aliyun”;//处理微信支付的方法
header("location:{$url}"); exit
}else{ $this->assign('error_data','请使用微信或者支付宝扫码哦!'); return $this->view->fetch('pay/error'); } // }else{ // $this->assign('error_data','暂时没有哦'); // return $this->view->fetch('pay/error'); //} }
接下来精彩的代码即将上线(微信jsapi支付)
damo下载:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
首先我们要了解微信jsapi的开发流程
好了这些你们就了解一下就可以了
public function code() { $appid = '*******';//微信的appid $appKey = '******';//APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), 请妥善保管, 避免密钥泄露获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN $mchid='*******';//商户平台的id $apiKey='*******';//KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置), 请妥善保管, 避免密钥泄露设置地址:https://pay.weixin.qq.com/index.php/account/api_cert $wxPay = new WxpayService($mchid,$appid,$appKey,$apiKey); $openid = $wxPay->GetOpenid(); if($openid){ Session::set("openid", $openid); }else{ $openid=session('openid'); } //公众号中的话可以授权-获取用户信息 // $wxPays=new WxPayUser($appid,$appKey); // $data = $wxPays->GetOpenid(); // $user = $WxPayUser->getUserInfo($data['openid'],$data['access_token']); $this->assign('openid',$openid); $this->assign('ip_user',$ip_user); return $this->view->fetch(); }
WxpayService.php
<?php namespace addons\epay\library; use fast\Http; class WxpayService { protected $mchid; protected $appid; protected $appKey; protected $apiKey; public $data = null; public function __construct($mchid, $appid, $appKey,$key) { $this->mchid = $mchid; //https://pay.weixin.qq.com 产品中心-开发配置-商户号 $this->appid = $appid; //微信支付申请对应的公众号的APPID $this->appKey = $appKey; //微信支付申请对应的公众号的APP Key $this->apiKey = $key; //https://pay.weixin.qq.com 帐户设置-安全设置-API安全-API密钥-设置API密钥 } /** * 通过跳转获取用户的openid,跳转流程如下: * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code * @return 用户的openid */ public function GetOpenid() { //通过code获得openid if (!isset($_GET['code'])){ //触发微信返回code码 $_SERVER['HTTPS']=isset($_SERVER['HTTPS'])?$_SERVER['HTTPS']:''; $scheme = $_SERVER['HTTPS']=='on' ? 'https://' : 'http://'; $uri = $_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']; if($_SERVER['REQUEST_URI']) $uri = $_SERVER['REQUEST_URI']; $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$uri); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $openid = $this->getOpenidFromMp($code); return $openid; } } /** * 通过code从工作平台获取openid机器access_token * @param string $code 微信跳转回来带上的code * @return openid */ public function GetOpenidFromMp($code) { $url = $this->__CreateOauthUrlForOpenid($code); $res = self::curlGet($url); //取出openid $data = json_decode($res,true); $this->data = $data; $data['openid']=isset($data['openid'])?$data['openid']:''; $openid = $data['openid']; return $openid; } /** * 构造获取open和access_toke的url地址 * @param string $code,微信跳转带回的code * @return 请求的url */ private function __CreateOauthUrlForOpenid($code) { $urlObj["appid"] = $this->appid; $urlObj["secret"] = $this->appKey; $urlObj["code"] = $code; $urlObj["grant_type"] = "authorization_code"; $bizString = $this->ToUrlParams($urlObj); return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString; } /** * 构造获取code的url连接 * @param string $redirectUrl 微信服务器回跳的url,需要url编码 * @return 返回构造好的url */ private function __CreateOauthUrlForCode($redirectUrl) { $urlObj["appid"] = $this->appid; $urlObj["redirect_uri"] = "$redirectUrl"; $urlObj["response_type"] = "code"; $urlObj["scope"] = "snsapi_base"; $urlObj["state"] = "STATE"."#wechat_redirect"; $bizString = $this->ToUrlParams($urlObj); return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString; } /** * 拼接签名字符串 * @param array $urlObj * @return 返回已经拼接好的字符串 */ private function ToUrlParams($urlObj) { $buff = ""; foreach ($urlObj as $k => $v) { if($k != "sign") $buff .= $k . "=" . $v . "&"; } $buff = trim($buff, "&"); return $buff; } /** * 统一下单 * @param string $openid 调用【网页授权获取用户信息】接口获取到用户在该公众号下的Openid * @param float $totalFee 收款总费用 单位元 * @param string $outTradeNo 唯一的订单号 * @param string $orderName 订单名称 * @param string $notifyUrl 支付结果通知url 不要有问号 * @param string $timestamp 支付时间 * @return string */ public function createJsBizPackage($openid, $totalFee, $outTradeNo, $orderName, $notifyUrl, $timestamp) { $config = array( 'mch_id' => $this->mchid, 'appid' => $this->appid, 'key' => $this->apiKey, ); // $orderName = iconv('GBK','UTF-8',$orderName); $unified = array( 'appid' => $config['appid'], 'attach' => 'pay', //商家数据包,原样返回,如果填写中文,请注意转换为utf-8 'body' => $orderName, 'mch_id' => $config['mch_id'], 'nonce_str' => self::createNonceStr(), 'notify_url' => $notifyUrl, 'openid' => $openid, //rade_type=JSAPI,此参数必传 'out_trade_no' => $outTradeNo, 'spbill_create_ip' => '127.0.0.1', 'total_fee' => floatval($totalFee) * 100, //单位 转为分 'trade_type' => 'JSAPI', ); $unified['sign'] = self::getSign($unified, $config['key']); $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified)); //禁止引用外部xml实体 libxml_disable_entity_loader(true); $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA); if ($unifiedOrder === false) { die('parse xml error'); } if ($unifiedOrder->return_code != 'SUCCESS') { die($unifiedOrder->return_msg); } if ($unifiedOrder->result_code != 'SUCCESS') { die($unifiedOrder->err_code); } $arr = array( "appId" => $config['appid'], "timeStamp" => "$timestamp", //这里是字符串的时间戳,不是int,所以需加引号 "nonceStr" => self::createNonceStr(), "package" => "prepay_id=" . $unifiedOrder->prepay_id, "signType" => 'MD5', ); $arr['paySign'] = self::getSign($arr, $config['key']); return $arr; } public static function curlGet($url = '', $options = array()) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 30); if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function curlPost($url = '', $postData = '', $options = array()) { if (is_array($postData)) { $postData = http_build_query($postData); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数 if (!empty($options)) { curl_setopt_array($ch, $options); } //https请求 不验证证书和host curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $data = curl_exec($ch); curl_close($ch); return $data; } public static function createNonceStr($length = 16) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $str = ''; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } public static function arrayToXml($arr) { $xml = "<xml>"; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } else $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; } $xml .= "</xml>"; return $xml; } public function notify() { $config = array( 'mch_id' => $this->mchid, 'appid' => $this->appid, 'key' => $this->apiKey, ); $postStr = file_get_contents('php://input'); //禁止引用外部xml实体 libxml_disable_entity_loader(true); $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); $result_1 = json_encode(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA)); file_put_contents("1.txt",$result_1, FILE_APPEND); $arr = (array)$postObj; return $arr; } public static function getSign($params, $key) { ksort($params, SORT_STRING); $unSignParaString = self::formatQueryParaMap($params, false); $signStr = strtoupper(md5($unSignParaString . "&key=" . $key)); return $signStr; } protected static function formatQueryParaMap($paraMap, $urlEncode = false) { $buff = ""; ksort($paraMap); foreach ($paraMap as $k => $v) { if (null != $v && "null" != $v) { if ($urlEncode) { $v = urlencode($v); } $buff .= $k . "=" . $v . "&"; } } $reqPar = ''; if (strlen($buff) > 0) { $reqPar = substr($buff, 0, strlen($buff) - 1); } return $reqPar; } }
View Code
code.html
<html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"> <title>微信支付</title> <style> * {margin:0;padding:0;} body {font-size:12px;font-family:"Microsoft YaHei","微软雅黑",sans-serif;color:#333;background-color:#f7f7f7;width:100%;} .clearfix:after { content: "."; display: block; font-size: 0; height: 0; clear: both; visibility: hidden; } .clearfix { display: inline-table;} *html .clearfix { height: 1%; } .clearfix { display: block; } *+html .clearfix { min-height: 1%; } ul,li{ list-style:none;border:0; box-sizing:border-box; } .main {margin:0 auto;width:100%;max-width:750px;min-width:320px;background-color:#f7f7f7;} .btnpay {margin:0.8rem auto 0;width:100%;} .btnpay span {display:block;margin:0 auto;width:6.74rem;height:0.8rem;line-height:0.8rem;background-color:#80D983;border-radius:0.1rem;color:#fff;font-size:0.34rem;letter-spacing:0.06rem;text-align:center;} .xinxi{ margin:0 auto; width: 90%; line-height: 46px; display: flex; flex-direction: row; font-size: 0.32rem; border-bottom: #ccc solid 1px; color: #333;} .moneychose{ margin:0 auto; width: 90%;} .moneychose p {font-size:16px;color:#8D8D8F; line-height: 42px;} .moneychose .list{ display: flex; } .moneychose .list li{ width: 45%; margin-right:5%; border: #ccc solid 1px; background-color: #fff; border-radius:3px; text-align: center; padding:10px 0;} .moneychose .list li span{ font-size: 0.32rem;display: block;} .moneychose .list li.active{border: #e56d33 solid 1px; color:#e56d33;} .tipbox{ margin:10px auto 0; width: 90%;} .tipbox a{ text-decoration:none; color: #999; font-size:0.28rem;} .tkbox .mask,.tkknowbox .mask{margin:0 auto;width:100%;height:100%;position:fixed;left:0px;top:0px;opacity:0.85;z-index:9998;background-color:rgb(0,0,0);} .tkbox .mymodel,.tkknowbox .mytk{width:6.2rem; padding: 0.25rem 0 0.25rem 0; position:fixed;z-index:10000;display:block;border-radius:5px;background-color:#FFFFFF;} .mymodel .inputblock{ margin:0 auto 0.3rem; width:5.6rem;} .mymodel .inputs {width:100%;height:0.8rem;line-height:0.8rem;font-size:0.32rem;border:1px solid #CFCFCF;text-indent:0.2rem;outline:none;white-space:pre;overflow-x:scroll;} .frminput {margin:0.3rem auto 0;display:flex;flex-direction:row;} .frminput input {margin-left:0.3rem;width:2.4rem;height:0.8rem;line-height:0.8rem;font-size:0.30rem;padding-left:0.2rem;border:1px solid #CFCFCF; outline:none; } .frminput .sendCodeBtn {margin-left:0.3rem;width:2rem;height:0.8rem;line-height:0.8rem;background-color:#e56d33;border-radius:5upx;color:#fff;text-align:center;font-size:0.26rem;} .btnconfrm {margin:0.5rem auto 0;width:5rem;} .btnconfrm span {display:block;margin:0 auto;width:100%;height:0.8rem;line-height:0.8rem;background-color:#80D983;border-radius:0.1rem;color:#fff;font-size:0.34rem;letter-spacing:0.06rem;text-align:center;} .topcar{ width: 100%; display: flex; flex-direction: row; margin-bottom: 0.15rem;} .topcar .cartip{ font-size: 0.32rem;width:1.1rem;height:0.6rem; line-height:0.6rem; padding-left: 0.3rem;} .che_tit{ text-align:center; padding:20px;} .ul_pro{ background-color:#CED3D9; text-align:center; padding:4px 2px; font-size:0.32rem;} .ul_pro li{ float:left; width:11.11%; padding:2px;box-sizing: border-box;} .ul_pro .li_close{ float:right; width:22.22%;} .ul_pro .li_close span{ background-color:#ACB3BB;} .ul_pro .li_clean{ float:right; width:22.22%;} .ul_pro li span{ display:block; background-color:#fff; border-radius:4px;line-height:32px; padding-top:2px; } .ul_pro li span:active{ background-color:#4DA9F2; color:#fff;} .ul_input{ width:4.6rem; margin:0 auto; } .ul_input li{ float:left; width:14%; padding:0.02rem;text-align:center; } .ul_input li span{ display:block; background-color:#fff; border:1px solid #ccc; border-radius:4px; width:0.5rem; margin:0 auto; height:0.5rem; line-height:0.5rem;font-size: 0.36rem;} .ul_keybord{ background-color:#CED3D9; text-align:center; padding:4px 2px; font-size:14px;} .ul_keybord li{ float:left; width:10%; padding:2px;box-sizing: border-box;} .ul_keybord .ikey20{ margin-left:5%;} .ul_keybord .li_w{ width:11.11%; } .ul_keybord .li_close{ float:right; width:22.22%;} .ul_keybord .li_close span{ background-color:#ACB3BB;} .ul_keybord .li_clean{ float:right; width:22.22%;} .ul_keybord li span{ display:block; background-color:#fff; border-radius:4px; box-shadow: 2px 2px 2px #888888;line-height:32px; padding-top:2px; } .ul_keybord li span:active{ background-color:#4DA9F2; color:#fff;} .tkknowbox .closetk{ width: 0.58rem; height: 0.58rem; position: absolute; top:-39px;right:-9px;z-index: 10001;} .tkknowbox .closetk .icon{width: 0.58rem; height: 0.58rem;} .tkknowbox .knowmain{ padding:5px 5% 0; font-size: 0.28rem; color: #666; line-height:24px;} .tkknowbox .knowmain .tit{ font-size: 0.30rem;} </style> <script type="text/javascript"> //调用微信JS api 支付 function jsApiCall(msg) { WeixinJSBridge.invoke( 'getBrandWCPayRequest', msg, function (res) { WeixinJSBridge.log(res.err_msg); if (res.err_msg == 'get_brand_wcpay_request:ok') { window.location.href="www.baidu.com"; // alert('支付成功!'); } else if(res.err_msg=='get_brand_wcpay_request:cancel') { layer.msg('支付取消'); }else{ layer.msg('支付失败'); // alert('支付失败:' + res.err_code + res.err_desc + res.err_msg); } } ); } function callpay(msg) { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } } else { jsApiCall(msg); } } </script> </head> <body> <section class="main"> <section class="xinxi"> <span>手机号:</span> <span id="phones"></span> </section> <section class="moneychose"> <p>选择套餐</p> <ul class="list"> <li class="active" data-type='1'><span>12次洗车次卡</span><span>300元</span></li> <li data-type='2'><span>25次洗车次卡</span><span>588元</span></li> </ul> <input type="hidden" name="openid" id='openid' value="<?php echo $openid;?>"> <input type="hidden" name="car_num_id" id='car_num_id' value=""> </section> <section class="tipbox" id="tipbox"><span>《支付须知》</span></section> <div class="btnpay" onclick="telypay()"><span>立即支付</span></div> </section> <!-- 弹框开始 --> <section class="tkbox" > <section class="mask"></section> <section class="mymodel"> <section class="tipinput"> <section class="topcar"> <div class="cartip">车牌号:</div> <div class="car_input"> <ul class="clearfix ul_input"> <li class="input_pro"><span></span></li> <li class="input_pp input_zim"><span></span></li> <li class="input_pp"><span></span></li> <li class="input_pp"><span></span></li> <li class="input_pp"><span></span></li> <li class="input_pp"><span></span></li> <li class="input_pp"><span></span></li> </ul> </div> </section> <div class="inputblock"><input id="phone" type="number" maxlength="11" autocomplete="off" class="inputs" placeholder="请输入手机号" onfocus="closePro()" ></div> <section class="frminput"> <input type="number" id="code" class="inputcode" onfocus="closePro()" placeholder="请输入验证码" /> <section class="sendCodeBtn" datamark="0" id="sendCodeBtn">发送验证码</section> </section> </section> <section class="btnconfrm" id="btnconfrm"><span>确定</span></section> </section> </section> <!-- 须知弹窗 --> <section class="tkknowbox" style="display:none;"> <section class="mask"></section> <section class="mytk"> <section class="closetk" onclick="$('.tkknowbox').hide();" ><img src="/code/iconclose.png" alt="关闭须知弹框" class="icon" /></section> <section class="knowmain"> <p><span class="tit" >1)次卡:</span><br> <span style="font-weight: bold;">轿车</span>:300元套餐(内含12次洗车服务);588元套餐(内含25次洗车服务且赠送一次打蜡)<br> <span style="font-weight: bold;">SUV</span>: 350元套餐(内含12次洗车服务);688元套餐(内含25次洗车服务且赠送一次打蜡)<br> </p> <p><span class="tit" >2)次卡升级为年卡:</span><br>将剩余次卡数折合为钱数,并支付所差金额;即可升级为年卡且次卡剩余次数清空;<br></p> <p>3)其他问题,请联系客服热线 ********** 咨询</p> </section> </section> </section> <!-- 弹框结束 --> <script type="text/javascript" src="/assets/js/jquery.min.js"></script> <script src="/assets/js/shop.js" ></script> <script type="text/javascript"> var isClick = true; function telypay() { if(!isClick){ return false; } // 这里可以写你onclick事件需要获取传到后台的值 var openid = $('#openid').val(); var price; $(".list li").each(function(){ if($(this).hasClass('active')){ console.log($(this).attr("data-type")); price = $(this).attr("data-type"); } }); $.ajax({ type: 'post', url: "/admin.php/pay/sub_pay", data: { 'price': price, 'openid': openid}, dataType: 'json', success: function (msg) { isClick = true; callpay(msg); } }); } $(function () { //隐藏弹框 var is_user=<?php echo $is_user;?>; var car_num_id=<?php echo $car_num_id;?>; var phone=<?php echo $phone;?>; if(is_user - 1 == 0){ $("#car_num_id").val(car_num_id); $('#phones').text(phone); $(".tkbox").hide(); } var W = $('.mymodel').width(); var H = $('.mymodel').height(); var winWid = $(window).width() / 2 - W / 2; var winHig = $(window).height() / 2 - H / 2; $(".mymodel").css({ 'left': winWid, 'top': winHig }); $(".list li").click(function(){ $(".list li").removeClass('active'); $(this).addClass('active'); console.log($(this).attr("data-type")); }); //发送验证码 $("#sendCodeBtn").click(function(){ var datamark = $(this).attr('datamark'); //console.log(datamark); if(datamark - 1 == 0){ return false; } var phone = $("#phone").val(); if(!phone){ layer.msg('请填写您的手机号'); return false; } var myreg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/; if (!myreg.test(phone)) { layer.msg('请填写正确的手机号'); return false; } $.ajax({ type: 'post', url: "/admin.php/pay/send_code", data: { 'phone': phone}, dataType: 'json', success: function (msg) { if(msg.code < 0){ layer.msg(msg.msg); }else if(msg.code > 0){ settime($("#sendCodeBtn")); layer.msg('发送验证码成功'); } return false; } }); //settime($("#sendCodeBtn")); //此处请求接口,成功后下面 }); var countdown = 60; function settime(obj) { if (countdown == 0) { $(obj).attr("datamark", "0"); $(obj).html("获取验证码"); countdown = 60; return; } else { $(obj).attr("datamark", "1"); $(obj).html(countdown + "s后重新获取"); countdown--; } setTimeout(function () { settime(obj) }, 1000); } //确定按钮点击 $("#btnconfrm").click(function () { var carnum = $(".car_input").attr("data-pai"); if(carnum == undefined){ layer.msg('请填写您的车牌号'); return false; } carnum = carnum.replace(/[\r\n]/g,"").replace(/\s*/g,""); // console.log(carnum); if(carnum.length - 7 < 0){ layer.msg('请填写您的车牌号'); return false; } var phone = $("#phone").val(); var code = $("#code").val(); if(!phone){ layer.msg('请填写您的手机号'); return false; } var myreg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/; if (!myreg.test(phone)) { layer.msg('请填写正确的手机号'); return false; } if(!code){ layer.msg('请填写您的验证码'); return false; } $('#pro').remove(); $.ajax({ type: 'post', url: "/admin.php/pay/car_num", data: { 'carnum': carnum, 'phone': phone, 'code': code}, dataType: 'json', success: function (message) { msgs=JSON.parse(message); if(msgs.status=='0'){ layer.msg(msgs.msg); return false; }else{ $("#car_num_id").val(msgs.id); $('#phones').text(msgs.phone); $(".tkbox").hide(); layer.msg('提交成功'); // console.log(msg.id +"手机号"+"验证码"+msg.phone); return true; } } }); //console.log(carnum +"手机号"+phone+"验证码"+code); return false; }); $("#tipbox").click(function(){ $(".tkknowbox").show(); var W1 = $('.mytk').width(); var H1 = $('.mytk').height(); var winWid1 = $(window).width() / 2 - W1 / 2; var winHig1 = $(window).height() / 2 - H1 / 2; $(".mytk").css({ 'left': winWid1, 'top': winHig1 }); }); }); (function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function () { var clientWidth = docEl.clientWidth; if (!clientWidth) return; if (clientWidth >= 750) { docEl.style.fontSize = '100px'; } else { docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'; } }; if (!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window); </script> </body> </html>
(个人的需求 你们可以删除手机短信的验证 send_code 和car_num 的入库)
你们只用sub_pay方法
public function sub_pay() { $openid=$this->request->post('openid'); $price=$this->request->post('price'); $price=0.01;//测试金额 // $outTradeNo = uniqid(); //你自己的商品订单号 //今日日期+时间戳后五位+毫秒从第三位到第八位+ $outTradeNo = date('Ymd').substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(1000, 9999)); $orderName = '支付测试'; //订单标题 $notifyUrl = 'http://'.$_SERVER['HTTP_HOST'].'/admin.php/Pay/callback'; //付款成功后的回调地址(不要有问号) $payTime = time(); //提交时间 $order_price=$price*100; //测试 $sql="INSERT INTO order(`pay_type`,`order_status`,`order_num`,`shop_id`,`pay_status`,`order_price`,`create_time`) VALUES('2','0','$outTradeNo','$ip_user','0','$order_price','$payTime')"; Db::execute($sql); //处理一下数据
$conf = $this->payconfig($orderName,$openid,$outTradeNo,$order_price,$orderName,$notifyUrl); $jsApiObj["appId"] =$conf['appid']; $timeStamp = time(); $jsApiObj["timeStamp"] = "$timeStamp"; $jsApiObj["nonceStr"] = $this->createNoncestr(); $jsApiObj["package"] ="prepay_id=".$conf['prepay_id']; $jsApiObj["signType"] = "MD5"; $jsApiObj["paySign"] = $this->MakeSign($jsApiObj,'KunLunqifuWangRUIHua162588080619'); echo json_encode($jsApiObj); }
payconfig方法
#微信JS支付参数获取-注意下面是支付方法可以不需要管!!!# protected function payconfig($title,$openid,$no, $fee, $body,$notifyUrl) { $config = array( 'mch_id' => '********', 'appid' => '*******', 'key' => '**************', ); $url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; $data['appid'] =$config['appid']; $data['mch_id'] =$config['mch_id']; //商户号 $data['device_info'] ='WEB'; $data['body'] = $body; $data['out_trade_no'] =$no; //订单号 $data['total_fee'] = $fee; //金额 $data['spbill_create_ip'] = $_SERVER["REMOTE_ADDR"]; $data['notify_url'] =$notifyUrl; $data['trade_type'] = 'JSAPI'; $data['openid'] = $openid; //获取openid $data['nonce_str'] = $this->createNoncestr(); $data['sign'] = $this->MakeSign($data,$config['key']); //print_r($data); $xml = $this->ToXml($data); $curl = curl_init(); // 启动一个CURL会话 curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); //设置header // curl_setopt($curl, CURLOPT_HEADER, FALSE); //要求结果为字符串且输出到屏幕上 curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_POST, TRUE); //发送一个常规的Post请求 curl_setopt($curl, CURLOPT_POSTFIELDS, $xml); // Post提交的数据包 curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环 $tmpInfo = curl_exec($curl); // 执行操作 curl_close($curl); //关闭CURL会话 $arr = $this->FromXml($tmpInfo); return $arr; }
/**
* 异步回调通知
* 说明:需要在支付文件中(如native.php或者jsapi.php)的填写回调地址。例如:http://www.xxx.com/wx/notify.php
* 付款成功后,微信服务器会将付款结果通知到该页面 我的是 callback方法
*/
public function callback() { $xml = file_get_contents("php://input"); $log = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true); $log_1=json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)); file_put_contents('1.txt',$log_1,FILE_APPEND);//只有返回参数写进文件中才可以打印 切记切记切记
3.1根据返回的信息在生成签名防止数据泄漏导致出现“假通知”,造成资金损失。
$apiKey="*******";
$newSign = $this->verifySign($log,$apiKey);
//判断数据库金额和支付金额是否一致 判断签名是否一致
if (($yorder_data['order_price']) == (int)$trade['total_fee']&& $newSign == $trade["sign"] ) //
{
直接写你的操作数据库逻辑就ok了
}
//必须加这个!!!!
$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
echo $str; } /* $log=array ( 'appid' => 'wx3c3f93ddce1e7845', 'bank_type' => 'OTHERS', 'cash_fee' => '1', 'device_info' => 'WEB', 'fee_type' => 'CNY', 'is_subscribe' => 'Y', 'mch_id' => '1602777325', 'nonce_str' => 'oz5dzyotw0qyz2a8x2elenbki268cyt5', 'openid' => 'os2J15vmqW1KXHLZAL4IwBtP7hL8', 'out_trade_no' => '2021070824865563665180', 'result_code' => 'SUCCESS', 'return_code' => 'SUCCESS', 'sign' => '02B66C17D8A31D0F943448979357DDEB', 'time_end' => '20210708141109', 'total_fee' => '1', 'trade_type' => 'JSAPI', 'transaction_id' => '4200001181202107085997485076', );*/
相关的方法
/** * 作用:产生随机字符串,不长于32位 */ public function createNoncestr($length = 32) { $chars = "abcdefghijklmnopqrstuvwxyz0123456789"; $str = ""; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } return $str; } /** * 作用:产生随机字符串,不长于32位 */ public function randomkeys($length) { $pattern = '1234567890123456789012345678905678901234'; $key = null; for ($i = 0; $i < $length; $i++) { $key .= $pattern{mt_rand(0, 30)}; //生成php随机数 } return $key; } /** * 将xml转为array * @param string $xml * @throws WxPayException */ public function FromXml($xml) { //将XML转为array return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)),true); } /** * 输出xml字符 * @throws WxPayException **/ public function ToXml($arr) { $xml = "<xml>"; foreach ($arr as $key => $val) { if (is_numeric($val)) { $xml .= "<" . $key . ">" . $val . "</" . $key . ">"; } else { $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">"; } } $xml .= "</xml>"; return $xml; } /** * 生成签名 * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值 */ protected function MakeSign($arr,$key) { ksort($arr); $string = $this->ToUrlParams($arr); //签名步骤二:在string后加入KEY $string = $string."&key=$key"; //key秘钥 //签名步骤三:MD5加密 $string = md5($string); //签名步骤四:所有字符转为大写 $result = strtoupper($string); return $result; } /** * 格式化参数格式化成url参数 */ protected function ToUrlParams($arr) { $buff = ""; foreach ($arr as $k => $v){ if ($k != "sign" && $v != "" && !is_array($v)) { $buff .= $k . "=" . $v . "&"; } } $buff = trim($buff, "&"); return $buff; } // 判断返回的签名和根据数据生成的数据判断是否相同,防止数据泄漏导致出现“假通知”,造成资金损失。 function verifySign($params, $apikey) { ksort($params); $string = ""; foreach ($params as $k => $v) { if ($k != "sign" && $v != "" && !is_array($v)) { $string .= $k . "=" . $v . "&"; } } $string = $string . "key=" . $apikey; $string = md5($string); $result = strtoupper($string); return $result; }
到这里 微信jsapi就结束了 下一篇讲支付宝的流程以及代码操作