PHP开发微信小程序支付

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/php_lzr/article/details/85015413

本人亲自开发 流程基本与微信支付一致 没什么特别的不一样  其中 有俩坑 和大家分享一下 其中一个是 回调地址不允许带参数 一个订单号 只能支付一回 如果中途放弃支付 还用之前的订单号码 微信这边 会报错的 订单状态有待支付 重新支付的时候 最好更新下订单编号  还有需要证书验证 去开通的微信商户号里直接下载就好 话不多说 上代码

首先是微信的统一下单接口

统一下单地址 

https://api.mch.weixin.qq.com/pay/unifiedorder
<?php
require_once "wxxcxpay.conf.php";

class wxxcxpayExt {

    //微信小程序接口
    public static function weixinapp($par) {

        //统一下单接口
        $unifiedorder = self::xcxpay($par);

        // 统一下单出错,参数出错等原因
        if($unifiedorder['return_code'] == 'FAIL') {
            $retrunInfo['code'] = 0;
            $retrunInfo['msg'] = $unifiedorder['return_msg'];
            return $retrunInfo;
        }

        $parameters = array(
            'appId' => ,                                // 小程序ID
            'timeStamp' => ''.time().'',                        // 时间戳
            'nonceStr' => self::nonce_str(),                  // 随机串
            'package' => 'prepay_id='.$unifiedorder['prepay_id'], // 数据包
            'signType' => 'MD5'                                     // 签名方式
        );

        // 小程序发起支付签名
        $parameters['paySign'] = self::sign($parameters);

        // 成功返回
        $retrunInfo['code'] = 1;
        $retrunInfo['msg'] = $parameters;
        return $retrunInfo;
    }

    //微信小程序支付
    public static function xcxpay($par){
        //统一支付接口
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';

        // 这里的参数顺序一定要按下面的,不然可能就一直报商户号此功能未授权等错误
        $parameters = array(
            'appid' => ,            // 小程序ID
            'body' => $par['subject'],  // 商品描述
            'mch_id' => ,          // 商户号
            'nonce_str' => self::nonce_str(),             // 随机字符串
            'notify_url' => $par['notify_url'],          //'https://shop.gdpress.cn/syw_jingzhun/index.php/Api/xiaochengxu/notify_url_api', // 通知地址 确保外网能正常访问
            'openid' => $par['openid'],                          // 用户id
            'out_trade_no'=> $par['out_trade_no'],    // 商户订单号
            //'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],    // 终端IP
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],      // 终端IP
            'total_fee' => $par['total_fee'],  // 单位 分
            'trade_type' => 'JSAPI',           // 交易类型
            'attach' => $par['pay_id']  //自定义参数
        );

        //统一下单签名
        $parameters['sign'] =self::sign($parameters);

        $xmlData =  self::arrayToXml($parameters);
        $return  =  self::postXmlCurl($xmlData, $url, 60);
        $return_lists  =  self::xmlToArray($return);

        return $return_lists;
    }
    // curl请求方法封装
    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");
        }
    }




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

    //签名
    public static function sign($data){
        ksort($data);
        $stringA = '';
        foreach ($data as $key=>$value){
        if(!$value) continue;
        if($stringA)
            $stringA .= '&'.$key."=".$value;
            else $stringA = $key."=".$value;
        }
        $wx_key = ;//申请支付后有给予一个商户账号和密码,登陆后自己设置的key
        $stringSignTemp = $stringA.'&key='.$wx_key;
        $sign = strtoupper(md5($stringSignTemp));
        return $sign;

    }




    //数组转换成xml
    private static function arrayToXml($arr) {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_array($val)) {
                $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    //xml转换成数组
    public static 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 = $GLOBALS['HTTP_RAW_POST_DATA'];
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
$request = ' 原始数据 '.var_export($GLOBALS['HTTP_RAW_POST_DATA'], 1).',处理后数据 : '.var_export($data, 1).'.';
if ($data && $data['return_code'] == 'SUCCESS') {
    这里面处理自己的业务逻辑 修改订单转态
}else{
    setOpeLog('xcxpay',$request,'','xcxpay error');
}

验证签名

猜你喜欢

转载自blog.csdn.net/php_lzr/article/details/85015413