美文网首页
微信公众号支付

微信公众号支付

作者: define光年 | 来源:发表于2019-09-26 16:07 被阅读0次

这里使用的tp5
首先将下面的文件放到extend文件夹下

<?php  
namespace wxpay;

class WeixinPay {

    protected $appid;  

    protected $mch_id;  

    protected $key;  

    protected $openid;  

    protected $out_trade_no; 

    protected $body;  

    protected $total_fee;  

    protected $identity;

    protected $sub_mchid;

    protected $attach;

    function __construct($appid, $openid, $mch_id, $key,$out_trade_no,$body,$total_fee,$identity,$sub_mchid,$attach="") {  

        $this->appid = $appid;  

        $this->openid = $openid;  

        $this->mch_id = $mch_id;  

        $this->key = $key;  

        $this->out_trade_no = $out_trade_no;  

        $this->body = $body;  

        $this->total_fee = $total_fee; 

        $this->identity = $identity;  

        $this->sub_mchid = $sub_mchid;   

        $this->attach = $attach;

    } 

     

    public function pay() {  

        //统一下单接口  

        $return = $this->weixinapp();  

        return $return;  

    }  

    //统一下单接口  

    private function unifiedorder() {  

        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';  

        $parameters = array(  

            'appid' => $this->appid, //小程序ID  

                'body' => $this->body,

                'mch_id' => $this->mch_id, //商户号  

                'nonce_str' => $this->createNoncestr(), //随机字符串  

//            'body' => 'test', //商品描述  

            //   'out_trade_no' => '', //商户订单号  

            //  'total_fee' => floatval(0.01 * 100), //总金额 单位 分    

            //  'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP  

            //  'spbill_create_ip' => '192.168.0.161', //终端IP  

                'notify_url' => $this->getNotifyUrl('/Wxpay/notify'), //通知地址  确保外网能正常访问  

                'out_trade_no'=> $this->out_trade_no,  
                
                'total_fee' => $this->total_fee,

                'trade_type' => 'JSAPI'//交易类型  

            );  

        if($this->identity == 1){
            $parameters['openid'] = $this->openid; //用户id  
        }
        if($this->identity == 2){
            $parameters['sub_appid'] = $this->appid; //小程序ID            
            $parameters['sub_mch_id'] = $this->mch_id; //商户号  
            $parameters['sub_openid'] = $this->openid; //用户id  
        }
        
        //自定义参数 (里面是订单类型|表单id|小程序id)
        if($this->attach){
            $parameters['attach'] = $this->attach;
        }

        //统一下单签名
        $parameters['sign'] = $this->getSign($parameters);
        $xmlData = $this->arrayToXml($parameters);  


        $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));

        return $return;  

    }  

    protected function getNotifyUrl($url){
      

      
        $current_url ='https://' . $_SERVER['HTTP_HOST'].$url;

      
        return $current_url;
    }

    private static function postXmlCurl($xml, $url, $second = 30)   

    {  

        $ch = curl_init();  

        //设置超时  

        curl_setopt($ch, CURLOPT_TIMEOUT, $second);  

        curl_setopt($ch, CURLOPT_URL, $url);  

        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);  

        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验  

        //设置header  

        curl_setopt($ch, CURLOPT_HEADER, FALSE);  

        //要求结果为字符串且输出到屏幕上  

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);  

        //post提交方式  

        curl_setopt($ch, CURLOPT_POST, TRUE);  

        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);  

        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);  

        curl_setopt($ch, CURLOPT_TIMEOUT, 40);  

        set_time_limit(0);  

        //运行curl  

        $data = curl_exec($ch);  

        //返回结果  

        if ($data) {  

            curl_close($ch);  

            return $data;  

        } else {  

            $error = curl_errno($ch);  

            curl_close($ch);  

            throw new WxPayException("curl出错,错误码:$error");  

        }  

    }  

    //数组转换成xml  

    protected function arrayToXml($arr) {  

        $xml = "<root>";  

        foreach ($arr as $key => $val) {  

            if (is_array($val)) {  

                $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";  

            } else {  

                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";  

            }  

        }  

        $xml .= "</root>";  

        return $xml;  

    }  

    //xml转换成数组  

    protected function xmlToArray($xml) {  

        //禁止引用外部xml实体   

        libxml_disable_entity_loader(true);  

        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);  

        $val = json_decode(json_encode($xmlstring), true);  

        return $val;  

    }  

    //微信小程序接口  

    private function weixinapp() {  

        //统一下单接口  

        $unifiedorder = $this->unifiedorder();
   
//        print_r($unifiedorder);  

        $parameters = array(  

            'appId' => $this->appid, //小程序ID  

            'timeStamp' => '' . time() . '', //时间戳  

            'nonceStr' => $this->createNoncestr(), //随机串  

            'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //数据包  

            'signType' => 'MD5'//签名方式  

        );  

        //签名  

        $parameters['paySign'] = $this->getSign($parameters);  

        return $parameters;  

    }  

    //作用:产生随机字符串,不长于32位  

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

    }  



    //作用:生成签名  

    protected function getSign($Obj) {  

        foreach ($Obj as $k => $v) {  

            $Parameters[$k] = $v;  

        }  

        //签名步骤一:按字典序排序参数  

        ksort($Parameters);  

        $String = $this->formatBizQueryParaMap($Parameters, false);  

        //签名步骤二:在string后加入KEY  

        $String = $String . "&key=" . $this->key;  

        //签名步骤三:MD5加密  

        $String = md5($String);  

        //签名步骤四:所有字符转为大写  

        $result_ = strtoupper($String);  

        return $result_;  

    }  



    ///作用:格式化参数,签名过程需要使用  

    protected function formatBizQueryParaMap($paraMap, $urlencode) {  

        $buff = "";  

        ksort($paraMap);  

        foreach ($paraMap as $k => $v) {  

            if ($urlencode) {  

                $v = urlencode($v);  

            }  

            $buff .= $k . "=" . $v . "&";  

        }  

        $reqPar;  

        if (strlen($buff) > 0) {  

            $reqPar = substr($buff, 0, strlen($buff) - 1);  

        }  

        return $reqPar;  

    }  

}  

支付界面当中
我这边先判断了一下是不是微信浏览器

// 判断浏览器类型
    var _browser="";
    if (/MicroMessenger/.test(window.navigator.userAgent)) {
       _browser="wechat";
    } else if (/AlipayClient/.test(window.navigator.userAgent)) {
      _browser="alipay";
    } else {
        _browser="other";
    }

然后判断用户信息 appid 路径自己设置 还可以设置不同的参数 参考后面拼接的info.id

// 微信进入判断用户信息
    if(_browser=="wechat"){
        if(!window.localStorage.getItem("u_id") && !GetQueryString("code")){
            window.location.href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxx&redirect_uri=http://pay.xxxxx.com/index/pay/index?id="+{$info.id}+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
        }else if(!window.localStorage.getItem("u_id") && GetQueryString("code")){
            $.post("/index/pay/getopenid",{code:GetQueryString("code")},function(e){
                console.log(e.data.openid)
                openid=e.data.openid;
                window.localStorage.setItem("u_id",e.data.openid)
            },"json")
        }else if(window.localStorage.getItem("u_id")){
            openid=window.localStorage.getItem("u_id")
        }
    }

上面的getopenid方法

//微信获取openid
function getopenid(){
    $appid      = 'xxx';
$appsecret  = 'xxx';
$code       = $_REQUEST['code'];


//第一步:取全局access_token
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";

$token = $this->_requestGetcurl($url);
//第二步:取得openid
$oauth2Url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$appsecret}&code={$code}&grant_type=authorization_code";
$oauth2 = $this->_requestGetcurl($oauth2Url);
$openid = $oauth2['openid'];//输出openid
if ($openid)
{
    $data = array(
        "openid" => $openid,
    );
    $adata['res']   = 1;
    $adata['data']  = $data;
    echo json_encode($adata);
    exit;
}
}


public function _requestGetcurl($url)
{
    //curl完成
    $curl = curl_init();
    //设置curl选项
    $header = array(
        "authorization: Basic YS1sNjI5dmwtZ3Nocmt1eGI2Njp1TlQhQVFnISlWNlkySkBxWlQ=",
        "content-type: application/json",
        "cache-control: no-cache",
        "postman-token: cd81259b-e5f8-d64b-a408-1270184387ca"
    );
    curl_setopt($curl, CURLOPT_HEADER, 1);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_URL, $url);//URL
    curl_setopt($curl, CURLOPT_HEADER, 0);             // 0:不返回头信息
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);//设置超时时间
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    // 发出请求
    $response = curl_exec($curl);
    if (false === $response) {
        echo '<br>', curl_error($curl), '<br>';
        return false;
    }
    curl_close($curl);
    $forms = stripslashes(html_entity_decode($response));
    $forms = json_decode($forms, TRUE);
    return $forms;
}

然后就是支付界面的提交 下面的post方法

//填写信息
    $('.submit').click(function(e){
        var money=$.trim($('#div').html());
        var receiveid=$("#receiveid").val();
        var businessmanid=$("#businessmanid").val();
        if(!(money>0)){
            alert("请输入大于零的数字")
            return false;
        }
//          alert("浏览器"+_browser);
//          alert("付款金额"+money);
//          alert("aaa="+UrlSearch());
        //提交信息 _browser浏览器信息  钱数money 用户id
        // e.preventDefault();      //阻止表单提交
        if(_browser=="wechat"){
            $.post("/index/wxpay/pay",{openid:openid,money:money,receiveid:receiveid,businessmanid:businessmanid},function(e){
                console.log(e)
                WeixinJSBridge.invoke(
                    'getBrandWCPayRequest', {
                        "appId":e.info.appId,     //公众号名称,由商户传入     
                        "timeStamp":e.info.timeStamp,         //时间戳,自1970年以来的秒数     
                        "nonceStr":e.info.nonceStr, //随机串     
                        "package":e.info.package,     
                        "signType":"MD5",         //微信签名方式:     
                        "paySign":e.info.paySign, //微信签名 

                    },
                    function(res){
                        if(res.err_msg == "get_brand_wcpay_request:ok" ){
                            alert("支付成功")
                        }
                    }
                );
            },"json")
        }
    })

提交到控制器 然后写到数据库里一个预订单 再返回给前端 前端根据返回信息调用上面的WeixinJSBridge.invoke 方法 这时会唤起支付的小窗口 让用户输入密码
输入完密码 支付完成 此时微信服务器会给回调方法发送支付成功的信息 将收取的信息订单号进行查询 更改状态即可
回调方法还没写



相关文章

  • PHP微信公众号支付开发总结

    微信公众号开发是很常见的开发,其中微信支付占有很大的比重。微信公众号分为服务号和订阅号,服务号支持微信支付。 前期...

  • 关注公众号领红包常见问题解答

    一、关注领红包对公众号的要求: 公众号必须开通“微信支付”和“现金红包”功能权限 登录微信公众平台 – 微信支付(...

  • 微信公众号配置

    微信支付 - 商户平台 商户号 支付证书 微信公众号 appid & appscret 开发 > 基本配置 > ...

  • 【微信】支付

    公众号支付 调用微信js支付接口的页面,必须接口域名授权。在公众平台中设置,最多可以授权3个。 使用微信公众号支付...

  • 关于微信公众号发红包|应该知道的几种玩法

    微信公众号发红包首先必须是开通微信支付了的公众号,支持开通微信支付的公众号类型包括:服务号和主体为政府或媒体资质的...

  • 微信支付

    公众号支付是指在微信app中访问的页面通过js直接调起微信支付; 一:设置域名 登录微信公众平台; 微信支付中设置...

  • 微信公众号网页支付summer版

    该文仅对于中间这种支付方式有参考价值哟 一、开发背景 在微信公众号中,需要进行微信支付且为微信公众号网页支付。 二...

  • 商城商品微信支付

    本次我们主要介绍的是公众号支付 1.当我们自己有微信公众号,开通了微信支付业务 2.我们到微信支付的官网,http...

  • 2019-08-19

    blog在线点单备案图标微信公众号微信支付微信赞赏支付宝出行红包支付宝支付支付宝红包

  • 微信支付

    微信公众号支付分为三类 以下主要介绍公众号H5授权支付 首先看一下微信支付的业务逻辑 大部分微信支付逻辑在于服务器...

网友评论

      本文标题:微信公众号支付

      本文链接:https://www.haomeiwen.com/subject/gthnuctx.html