php微信jsapi支付 支付宝支付 两码合一
阅读原文时间:2021年07月13日阅读:2

产品开会提出了这样的需求:一个二维码可以微信支付也可以支付宝支付

经过自己的钻研以及询问技术高人(本人代码一般般)和网上搜索 最终实现其功能  我用微信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 '使用微信或者支付宝扫描支付';

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;  
}

}

code.html




微信支付



手机号:

选择套餐

  • 12次洗车次卡300元
  • 25次洗车次卡588元

《支付须知》

立即支付




车牌号:


发送验证码



确定


<!-- 须知弹窗 -->  
<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>  


(个人的需求 你们可以删除手机短信的验证 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='';  
        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就结束了   下一篇讲支付宝的流程以及代码操作

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器