微信公众号支付

javascript前台

<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
layui.use(['layer'],function () {
        var layer=layui.layer;
        $('.goumai').click(function () {
            var id="{$data.id}";
            $.ajax({
                url:'/index/video/order',
                data:{id:id},
                type:'post',
                success: function (data) {
                    if(data.status=='success'){
                        $.ajax({
                            url:'/index/wxpay/pay',
                            data:{id:data.id},
                            type:'post',
                            success:function (res) {
                                WeixinJSBridge.invoke(
                                    'getBrandWCPayRequest', {
                                        "appId": res.data.appId,     //公众号名称,由商户传入
                                        "timeStamp":res.data.timeStamp,  //时间戳,自1970年以来的秒数
                                        "nonceStr":res.data.nonceStr, //随机串
                                        "package":res.data.package,
                                        "signType":res.data.signType, //微信签名方式:
                                        "paySign":res.data.paySign //微信签名
                                    },
                                    function(e){
                                        if(e.err_msg=="get_brand_wcpay_request:ok" ){
                                            $.ajax({
                                                url: '/index/wxpay/gaiorder',
                                                data: {id:data.id},
                                                type: 'post',
                                                success: function (resb) {
                                                    if(resb.status='success'){
                                                        location.href='/index/video/paysuccess';
                                                    }else{
                                                        location.href='/index/video/payerror';
                                                    }
                                                }
                                            })
                                        }else if(e.err_msg=="get_brand_wcpay_request:cancel"){
                                            layer.msg('<span style=color:#fff>您已取消支付</span>')
                                        }else{
                                            layer.msg('<span style=color:#fff>支付失败</span>')
                                        }
                                    }
                                )

                            }
                        })
                    }
                }
            })
        });

生成订单

    public function order(Request $request)
    {
        $user_id=session('userid');
        $id=Request()->post('id');
        $video=Db::name('video')->find($id);

        $order_num=time().rand(111,999);  //订单号
        $data=[
            'uid'=>$user_id, //用户id
            'video_id'=>$id,    //视频id
            'price'=>$video['price'],  //vip金额
            'order_num'=>$order_num,  //订单号
            'create_time'=>time(),   //购买时间
            'status'=>0, //订单状态
            'differ'=>1,
        ];
        $id=Db::name('order')->insertGetId($data);
        if($id) return json(['status'=>'success','id'=>$id]);
    }

    //微信支付
    public function paysuccess(){
        return view();
    }
    public function payerror(){
        return view();
    }

调起支付

class Wxpay extends Controller {
    protected $appid;
    protected $mch_id;//商户号
    protected $key;
    protected $openid; //用户id
    protected $out_trade_no; //$out_trade_no;//订单号
    protected $body;//自定义商品描述
    protected $total_fee; //金额
    protected $notify_url; //异步通知地址
    protected $trade_type; //交易类型
    protected $config;

    function get_client_ip($type = 0, $adv = true) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if($adv){
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos    =   array_search('unknown',$arr);
                if(false !== $pos) unset($arr[$pos]);
                $ip     =   trim($arr[0]);
            }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip     =   $_SERVER['HTTP_CLIENT_IP'];
            }elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip     =   $_SERVER['REMOTE_ADDR'];
            }
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u",ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }

    public function pay(Request $re) {
        $id=$re->param('id');
        $order=Db('order')->where('id',$id)->find();
        $openid=Db('user')->where('id',$order['uid'])->value('openid');
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $config=Db('wxpay_config')->where('id',1)->find();
        $price=$order['price'];
        $str=$this->createNoncestr();
        $parameters = array(
            'appid' => $config['appid'], //小程序ID
            'mch_id' => $config['mch_id'], //商户号
            'nonce_str' => $str, //随机字符串
            'body' => $config['body'], //商品描述
            'out_trade_no'=> $order['order_num'],//订单号
            'total_fee' =>$price*100,//$total_fee*100, //金额
            'spbill_create_ip' => $this->get_client_ip(), //终端IP
            'notify_url' => $config['notify_url'], //通知地址  确保外网能正常访问
            'openid' => $openid, //用户id
            'trade_type' => $config['trade_type'],//交易类型
        );

        //统一下单签名
        $parameters['sign'] = $this->getSign($parameters,$config['key']); //生成签名
        $xmlData = $this->arrayToXml($parameters);
        $a=$this->postXmlCurl($xmlData, $url, 60);
        $return = $this->xmlToArray($a);

        if($return['return_msg']=='OK'){
            $parameters = array(
                'appId' => $config['appid'], //小程序ID
                'timeStamp' => '"'.time().'"', //时间戳
                'nonceStr' => $str, //随机串
                'package' => 'prepay_id='.$return['prepay_id'], //数据包
                'signType' => 'MD5'//签名方式
            );
            //签名
            $parameters['paySign'] = $this->getSign($parameters,$config['key']);
            return json(['status'=>'success','msg'=>'','data'=>$parameters]);
        }else{
            return json(['status'=>'error']);
        }
    }

    //支付成功逻辑处理
    public function gaiorder(){
        $id=Request()->param('id');
        $order=Db('order')->where('id',$id)->find();
        if($order){
            if($order['status'] == 0){
                if($order['differ']==1){
                    $data=[
                        'payment_time'=>time(),
                        'status'=>1
                    ];
                    $result=Db::name('order')->where('order_num',$order['order_num'])->update($data);
                    if($result){
                        //更新余额
                        $userid=Db::name('video')->where('id',$order['video_id'])->value('uid');
                        $balance=Db::name('user')->where('id',$userid)->value('balance');
                        $balance+=$order['price']*0.7;
                        Db::name('user')->where('id',$userid)->update(['balance'=>$balance]);
                        return json(['status'=>'success','msg'=>'支付成功']);
                    }else{
                        return json(['status'=>'error','msg'=>'支付失败']);
                    }
                }
                if($order['differ']==2){
                    $data=[
                        'payment_time'=>time(),
                        'status'=>1
                    ];
                    $result=Db::name('order')->where('order_num',$order['order_num'])->update($data);
                    if($result){
                        //更新余额
                        $user_id=Db::name('order')->where('order_num',$order['order_num'])->value('user_id');
                        $balance=Db::name('user')->where('id',$user_id)->value('balance');
                        $balance+=$order['price'];
                        Db::name('user')->where('id',$user_id)->update(['balance'=>$balance]);
                        return json(['status'=>'success','msg'=>'支付成功']);
                    }else{
                        return json(['status'=>'error','msg'=>'支付失败']);
                    }
                }
            }
        }
    }

    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转换成数组
    private 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;
    }
    
    //数组转换成xml
    private 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;
    }
    //作用:格式化参数,签名过程需要使用
    private 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;
    }
    
    //作用:生成签名
    private function getSign($Obj,$AppSecret) {

        foreach ($Obj as $k => $v) {
            $Parameters[$k] = $v;
        }
        //签名步骤一:按字典序排序参数
        ksort($Parameters);
        $String = $this->formatBizQueryParaMap($Parameters, false);
        //签名步骤二:在string后加入KEY
        $String = $String . "&key=" . $AppSecret;
        //签名步骤三:MD5加密
        $String = md5($String);
        //签名步骤四:所有字符转为大写
        $result_ = strtoupper($String);
        return $result_;
    }
    //作用:产生随机字符串,不长于32位
    private 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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值