微信统一下单、异步通知接口

一、统一下单

官方文档 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1

二、微信支付异步通知

官方文档 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_7&index=3
微信官方文档提示:
在这里插入图片描述

注意: 该链接 不能携带参数 ,有些php框架默认的路由形式是带有参数的,如:index.php?r=site/index,这样也会导致返回失败。

三、代码

<?php
class wxpay
{
    public $appid = 'wxXXXXXXXXX';   #应用APPID
    public $mchud = '14XXXXXXXX';    #商户号
    public $wxkey = '7cXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

    /**
     * 微信支付统一下单
     */
    public function wxpay()
    {
        $name = 'apple';
        $orderno = '100100100';
        $price = '10000';

        $request_data = array(
            'appid' => $this->appid, #应用APPID
            'mch_id' => $this->mchud, #商户号
            'trade_type' => 'APP', #支付类型
            'nonce_str' => $this->unicode(), #随机字符串 不长于32位
            'body' => $name, #商品名称
            'out_trade_no' => $orderno, #商户后台订单号
            'total_fee' => $price, #商品价格(单位分)
            'spbill_create_ip' => $_SERVER['SERVER_ADDR'], #用户端实际ip
            'notify_url' => 'http://127.0.0.1:9000/wxpay/wx_notify' #异步通知回调地址(wx_notify方法)
        );
        // 获取签名
        $request_data['sign'] = $this->get_sign($request_data);
        // 拼装数据
        $xml_data = $this->set_xmldata($request_data);

        // 发送请求
        $res = $this->send_prePaycurl($xml_data);
        
        if ($res['return_code'] == 'SUCCESS' && $res['result_code'] == 'SUCCESS') {
            $two_data['appid'] = $this->appid; #APPID
            $two_data['partnerid'] = $this->mchud; #商户号
            $two_data['prepayid'] = $res['prepay_id']; //预支付交易会话标识
            $two_data['noncestr'] = $this->unicode();
            $two_data['timestamp'] = time();
            $two_data['package'] = "Sign=WXPay";
            $two_data['sign'] = $this->get_twosign($two_data);
            $arr['code'] = 1;
            $arr['showMsg'] = 'success';
            $arr['errorMsg'] = '';
            $arr['data'] = $two_data;
        } else {
            $arr['code'] = 0;
            $arr['showMsg'] = '';
            $arr['errorMsg'] = $res['err_code_des'];
            $arr['data'] = [];
        }
        echo json_encode($arr);
    }

    //通过curl发送数据给微信接口的函数
    private function send_prePaycurl($xmlData)
    {
        header("Content-Type: text/html; charset=utf-8");
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $header[] = "Content-type: text/xml;";
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $xmlData);
        $data = curl_exec($curl);
        if (curl_errno($curl)) {
            print curl_error($curl);
        }
        curl_close($curl);
        return $this->_xmldataparse($data);
    }

    //xml数据解析函数
    private function _xmldataparse($data)
    {
        $msg = array();
        $msg = (array) simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
        return $msg;
    }

    //生成xml格式的函数
    private function set_xmldata($data)
    {
        $xmlData = "<xml>";
        foreach ($data as $key => $value) {
            $xmlData .= "<" . $key . "><![CDATA[" . $value . "]]></" . $key . ">";
        }
        $xmlData = $xmlData . "</xml>";
        return $xmlData;
    }

    //一次签名的函数
    private function get_sign($data)
    {
        ksort($data);
        $str = '';
        foreach ($data as $key => $value) {
            $str .= !$str ? $key . '=' . $value : '&' . $key . '=' . $value;
        }
        $str .= '&key=' . $this->wxkey;
        // echo $str;die;
        $sign = strtoupper(md5($str));
        return $sign;
    }

    //二次签名的函数
    private function get_twosign($data)
    {
        $sign_data = array(
            "appid" => $data['appid'],
            "partnerid" => $data['partnerid'],
            "prepayid" => $data['prepayid'],
            "noncestr" => $data['noncestr'],
            "timestamp" => $data['timestamp'],
            "package" => $data['package'],
        );
        return $this->get_sign($sign_data);
    }

    //微信回调
    public function wx_notify()
    {
        //允许从外部加载XML实体(防止XML注入攻击)
        libxml_disable_entity_loader(true);
        $postStr = $this->post_data(); //接收post数据
        $obj = simplexml_load_string($postStr,"SimpleXMLElement", LIBXML_NOCDATA);
        $result_arr = json_decode(json_encode($obj),true);
        if($result_arr['result_code'] == 'SUCCESS'){//交易成功
            return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }else{
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }
    }

    /*
     *  接收post数据
     *  微信是用$GLOBALS['HTTP_RAW_POST_DATA'];这个函数接收post数据的
     */
    public function post_data()
    {
        $receipt = $_REQUEST;
        if ($receipt == null) {
            $receipt = file_get_contents("php://input");
            if ($receipt == null) {
                $receipt = $GLOBALS['HTTP_RAW_POST_DATA'];
            }
        }
        return $receipt;
    }

    //把对象转成数组
    public function object_toarray($arr)
    {
        if (is_object($arr)) {
            $arr = (array) $arr;
        }if (is_array($arr)) {
            foreach ($arr as $key => $value) {
                $arr[$key] = $this->object_toarray($value);
            }
        }
        return $arr;
    }

    /**
     * 格式化参数格式化成url参数
     */
    private function params_tourl($arr)
    {
        $weipay_key = $this->wxkey; //微信的key,这个是微信支付给你的key,不要瞎填。
        $buff = "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff . '&key=' . $weipay_key;
    }

    //随机字符串
    public function unicode() {
        $str = uniqid(mt_rand(),1);
        $str=sha1($str);
        return md5($str);
    }

    //生成订单号
    function genRandomString($len = 5) {
        $chars = array(
            "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
            "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
            "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G",
            "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
            "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2",
            "3", "4", "5", "6", "7", "8", "9"
        );
        $charsLen = count($chars) - 1;
        // 将数组打乱
        shuffle($chars);
        $output = "";
        for ($i = 0; $i < $len; $i++) {
            $output .= $chars[mt_rand(0, $charsLen)];
        }
        return $output;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值