【PHP急救】Laravel 微信小程序支付 类


这是本人在网络上整合的一份小程序支付后端代码,当然,加上了和优化了一家,原文地址我不记得了,如果后期发现,会加上出处;调用方法非常简单:

 // 调起微信支付
        $wx_obj = new WxPayNewClass();
        $ret = $wx_obj->Pay($order,$open_id);

类文件只需要一个就可以了。

类名字,自己定义;

<?php
namespace App\LyClass;
/**
 * Created by PhpStorm.
 * User: pc
 * Date: 2018/3/18
 * Time: 15:26
 */

class WxPayNewClass
{
    public $values = [];

    //微信支付
    public function Pay($order,$open_id){
        // 参数获取
        $appid        = config('api.xcx_conf')['app_id']; // 如果是公众号 就是公众号的appid
        $mch_id       = config('api.xcx_conf')['mch_id']; // 设置商户id
        $notify_url   = config('api.xcx_conf')['notify_url']; // 回调地址
        $nonce_str    = $this->nonce_str(); // 随机字符串
        $out_trade_no = $order['od_no'] ;   // 商户订单号
        $body         = $order['od_title']; // 订单名称
        $fee          = $order['od_price']; // 订单金额
        $openid       = $open_id;   // 当前下单支付者的open_id
        $total_fee    = $fee * 100; // 单位是分所以乘以100
        $trade_type   = 'JSAPI';    // 交易类型 默认
        $spbill_create_ip = $_SERVER['SERVER_ADDR']; // 服务端ip地址
        $this->values = [
            'appid'      => $appid, // 小程序的AppId
            'body'       => $body, // 订单名称
            'mch_id'     => $mch_id, // 设置商户id
            'nonce_str'  => $nonce_str,//随机字符串
            'notify_url' => $notify_url,
            'openid'     => $openid,
            'out_trade_no' => $out_trade_no,
            'spbill_create_ip' => $spbill_create_ip,//终端的ip
            'total_fee'  => $total_fee,//总金额 最低为一块钱 必须是整数
            'trade_type' => $trade_type,
        ];
        //签名
        $this->values['sign'] = $this->MakeSign();
        $post_xml = $this->ToXml();
        //统一接口prepay_id
        $url   = 'https://api.mch.weixin.qq.com/pay/unifiedorder'; // 请求地址设定
        $xml   = $this->http_request($url, $post_xml);             // 执行请求
        $array = $this->xml_to_array($xml);                        // 全要大写
        $array['nonce_str'] = $nonce_str;
        $array['sign']      = $this->values['sign'];
        $array['out_trade_no'] = $out_trade_no;
        $data  = $this->dis_ret($array,$nonce_str,$out_trade_no);  // 返回结果处理
        if(!$data['state']) return r_json(204,'微信服务器繁忙,创建订单失败,请重试!');
        return r_json(200,'请求成功',$data);// 返回结果处理
    }

    /**
     * 处理返回结果
     * @param  $array
     * @param  $nonce_str
     * @param  $out_trade_no
     * @return mixed
     * @author YuanPengChao
     */
    private function dis_ret($array,$nonce_str,$out_trade_no){
        if ($array['return_code'] == 'SUCCESS' && $array['result_code'] == 'SUCCESS') {
            $time = get_now_time();
            $tmp = [];//临时数组用于签名
            $tmp['appId']     = config('api.xcx_conf')['app_id'];
            $tmp['timeStamp'] = "$time";
            $tmp['nonceStr']  = $nonce_str;
            $tmp['package']   = 'prepay_id=' . $array['prepay_id'];
            $tmp['signType']  = 'MD5';

            $data['state'] = 1;
            $data['timeStamp'] = "$time";      // 时间戳
            $data['nonceStr'] = $nonce_str;    // 随机字符串
            $data['package'] = 'prepay_id=' . $array['prepay_id'];//统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=*
            $data['signType'] = 'MD5';         // 签名算法,暂支持 MD5
            $data['paySign'] = $this->sign($tmp);//签名,具体签名方案参见微信公众号支付帮助文档;
            $data['out_trade_no'] = $out_trade_no;
        } else {
            $data['state'] = 0;
            $data['text'] = "错误";
            $data['result_code'] = $array['result_code'];
            $data['return_msg']  = $array['return_msg'];
        }
        return $data;
    }

    //签名 $data要先排好顺序
    private function sign($data){
        ksort($data);
        $buff = "";
        foreach ($data as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }
        $string = trim($buff, "&");
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=". config('api.xcx_conf')['wx_key'];
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    //随机32位字符串
    private function nonce_str()
    {
        $result = '';
        $str = 'QWERTYUIOPASDFGHJKLZXVBNMqwertyuioplkjhgfdsamnbvcxz';
        for ($i = 0; $i < 32; $i++) {
            $result .= $str[rand(0, 48)];
        }
        return $result;
    }

    /**
     * 生成签名
     * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
     */
    public function MakeSign() {
        //签名步骤一:按字典序排序参数
        ksort($this->values);
        $string = $this->ToUrlParams();
        //签名步骤二:在string后加入KEY
        $string = $string . "&key=". config('api.xcx_conf')['wx_key'];
        //签名步骤三:MD5加密
        $string = md5($string);
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    public function ToUrlParams()
    {
        $buff = "";
        foreach ($this->values as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function ToXml() {
        if(!is_array($this->values)
            || count($this->values) <= 0)
        {
            throw new WxPayException("数组数据异常!");
        }

        $xml = "<xml>";
        foreach ($this->values as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    //curl请求啊
    public function http_request($url, $data = null, $headers = array()) {
        $curl = curl_init();
        if (count($headers) >= 1) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($curl, CURLOPT_URL, $url);

        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);

        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    /**
     * 将支付完成后的Xml数据转换为数组
     * @param  String $xml 传过来的xml数据
     * @return Array
     * @author YuanPengChao
     */
    public function xml_to_array($xml){
        if (!$xml) return [];
        $pp = xml_parser_create();
        xml_parse_into_struct($pp, $xml, $ret);
        xml_parser_free($pp);
        if (!$ret) return [];
        $reta = [];
        foreach($ret as $k => $v){
            $tag = $v['tag'];
            switch (strtoupper($tag)){
                case 'APPID':
                    $reta['appid'] = $v['value'];
                    break;
                case 'BANK_TYPE':
                    $reta['bank_type'] = $v['value'];
                    break;
                case 'CASH_FEE':
                    $reta['cash_fee'] = $v['value'];
                    break;
                case 'FEE_TYPE':
                    $reta['fee_type'] = $v['value'];
                    break;
                case 'IS_SUBSCRIBE':
                    $reta['is_subscribe'] = $v['value'];
                    break;
                case 'MCH_ID':
                    $reta['mch_id'] = $v['value'];
                    break;
                case 'NONCE_STR':
                    $reta['nonce_str'] = $v['value'];
                    break;
                case 'OPENID':
                    $reta['openid'] = $v['value'];
                    break;
                case 'OUT_TRADE_NO':
                    $reta['out_trade_no'] = $v['value'];
                    break;
                case 'RESULT_CODE':
                    $reta['result_code'] = $v['value'];
                    break;
                case 'RETURN_CODE':
                    $reta['return_code'] = $v['value'];
                    break;
                case 'SIGN':
                    $reta['sign'] = $v['value'];
                    break;
                case 'TIME_END':
                    $reta['time_end'] = $v['value'];
                    break;
                case 'TOTAL_FEE':
                    $reta['total_fee'] = $v['value'];
                    break;
                case 'TRADE_TYPE':
                    $reta['trade_type'] = $v['value'];
                    break;
                case 'TRANSACTION_ID':
                    $reta['transaction_id'] = $v['value'];
                    break;
                case 'PREPAY_ID':
                    $reta['prepay_id'] = $v['value'];
                    break;
                case 'RETURN_MSG':
                    $reta['return_msg'] = $v['value'];
                    break;
            }

        }
        return $reta;
    }

}


上一篇

评论



鲁班七号:网站不错哦,发出的文章都是干货。 加油ヾ(◍°∇°◍)ノ゙
03月29日 21:09
网站/shl设计:回复 鲁班七号 说的不错!
05月28日 15:22
网站/shl设计:回复 网站/shl设计 站长怎么联系你有给问题请教。
05月28日 15:25
PHP笔记:回复 网站/shl设计 ypengchao@126.com
06月26日 11:38

最新评论

PHP笔记: ypengchao@126.com 查看原文 06月26日 11:38
PHP笔记: 用数据库 查看原文 06月26日 11:37
网站/shl设计: 如果关闭浏览器了,session就没有了呀。再打开浏览器不就可以重新登陆了。 查看原文 05月28日 15:26
网站/shl设计: 站长怎么联系你有给问题请教。 查看原文 05月28日 15:25
网站/shl设计: 说的不错! 查看原文 05月28日 15:22

分享

扫一扫,快速分享到微信

赞助商