微信支付的坑(思路)

获取openid页面刷新:https://bbs.csdn.net/topics/391115929

异步通知验证签名:微信返回xml数据中的sign使用的是HMAC-SHA256加密方法,所以不能使用md5进行验签

<?php
namespace Service\Controller;


use Base\Webbase;
use Service\Controller\WechatPayBankController;
class PayController extends Webbase
{
    public function _initialize()
    {
        parent::_initialize(); // TODO: Change the autogenerated stub
        Vendor('Wxpay.example.WxPay#JsApiPay');
        Vendor('Wxpay.example.log');

        //初始化日志
        $logHandler= new \CLogFileHandler("../logs/".date('Y-m-d').'.log');
        $log = \Log::Init($logHandler, 15);
    }
    public function wxpay()
    {

        $orderid = $_POST['orderid']?$_POST['orderid']: session("orderid");
        session("orderid",$orderid);
        if(!$orderid)
        {
            $this->websuccess(self::START_ALIPAY_OR_WX,'订单号为空');
        }
        $body =  $ordertype = substr(session('orderid'),0,1);		//订单类型

            //获取用户openid
            $tools = new \JsApiPay();
            $openId = $tools->GetOpenid();



            //②、统一下单
            $input = new \WxPayUnifiedOrder();
            $input->SetBody($body);        //商品描述
            //$input->SetAttach("test");    //附加数据暂未使用到可以注释掉
            $input->SetOut_trade_no(session('orderid'));//商户订单号,此处订单号根据实际项目中订单号进行赋值,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一
            $input->SetTotal_fee(1);      //订单总金额,单位为分
            $input->SetTime_start(date("YmdHis"));//订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010
            $input->SetTime_expire(date("YmdHis", time() + 600));//订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。订单失效时间是针对订单号而言的,由于在请求支付的时候有一个必传参数prepay_id只有两小时的有效期,所以在重入时间超过2小时的时候需要重新请求下单接口获取新的prepay_id
            //$input->SetGoods_tag("test");//订单优惠标记,使用代金券或立减优惠功能时需要的参数,项目暂未使用到,因此注释掉
            $input->SetNotify_url("http://www.**.com/index.php/**/pay/jsapi_notify");//异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
            $input->SetTrade_type("JSAPI");//交易类型JSAPI 公众号支付;NATIVE 扫码支付;APP APP支付;
            $input->SetOpenid($openId);
            $config = new \WxPayConfig();

            $order = \WxPayApi::unifiedOrder($config, $input);
            // var_dump($order);
            //echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
            // $this->printf_info($order);
            $jsApiParameters = $tools->GetJsApiParameters($order);
            //  var_dump($jsApiParameters);
            // return $jsApiParameters;
            //  var_dump($jsApiParameters);//die();
            // return $jsApiParameters;
            file_put_contents('./wxtest.log',$jsApiParameters);

            //获取共享收货地址js函数参数
            // $editAddress = $tools->GetEditAddressParameters();
            //将数据渲染到模板中或前端页面中
            $assign=array(
                'data'=>$jsApiParameters,
                'amount'=>1/100,
                'channel'=>$body
            );
            $this->assign($assign);
            $this->display();
        
    }

    public function printf_info($data)
    {
        foreach($data as $key=>$value){
            echo "<font color='#00ff55;'>$key</font> :  ".htmlspecialchars($value, ENT_QUOTES)." <br/>";
        }
    }

    public function h5pay()
    {
       
        header("Content-type:text/html;Charset=utf-8");
        $headers = array(
            'REFERER: '."http://www.**.com",
            'USER-AGENT:'.$_SERVER["HTTP_USER_AGENT"]
        );

        //获取配置信息
        $wxconfig = new \WxPayConfig();

        $orderid = $_POST['orderid'];

        if(!$orderid)
        {
            $this->websuccess(self::START_ALIPAY_OR_WX,'订单号为空');
        }

  
        if($uac['created_state'] == 1)
        {
            $this->websuccess(self::START_ALIPAY_OR_WX,'订单号已支付,无需重新支付');
        }
        $body =  $ordertype = substr($orderid,0,1);		//订单类型
      
        $money= $uac['amount'];//充值金额

        $userip = $this->get_client_ip(); //获得用户设备IP
        $appid = $wxconfig->GetAppId();//微信给的
        $mch_id = $wxconfig->GetMerchantId();//微信官方的
        $key = $wxconfig->GetKey();//自己设置的微信商家key
        
        $out_trade_no = $orderid;//平台内部订单号
        $nonce_str=MD5($out_trade_no);//随机字符串
        $body = $body;//内容
        $total_fee = $money; //金额
        $spbill_create_ip = $userip; //IP
        $notify_url = "http://www.**.com/index.php/**/pay/wap_notify"; //回调地址(支付完成之后微信会将结果参数带入这个方法) 这个根据自己逻辑需求填写
        $trade_type = 'MWEB';//交易类型 具体看API 里面有详细介绍
        $scene_info ='{"h5_info": {"type":"Android","app_name": "**","package_name": "com.**.www.**"}}';//场景信息 必要参数
        // $scene_info ='{"h5_info": {"type":"Wap","wap_url": "http://www.**.com","wap_name": "**"}}';//场景信息 必要参数
        $signA ="appid=$appid&body=$body&mch_id=$mch_id&nonce_str=$nonce_str&notify_url=$notify_url&out_trade_no=$out_trade_no&scene_info=$scene_info&spbill_create_ip=$spbill_create_ip&total_fee=$total_fee&trade_type=$trade_type";

        $strSignTmp = $signA."&key=$key"; //拼接字符串 注意顺序微信有个测试网址 顺序按照他的来 直接点下面的校正测试 包括下面XML 是否正确
        $sign = strtoupper(MD5($strSignTmp)); // MD5 后转换成大写

        $post_data="<xml><appid>$appid</appid><body>$body</body><mch_id>$mch_id</mch_id><nonce_str>$nonce_str</nonce_str><notify_url>$notify_url</notify_url><out_trade_no>$out_trade_no</out_trade_no><scene_info>$scene_info</scene_info><spbill_create_ip>$spbill_create_ip</spbill_create_ip><total_fee>$total_fee</total_fee><trade_type>$trade_type</trade_type><sign>$sign</sign></xml>";//拼接成XML格式 *XML格式文件要求非常严谨不能有空格这点一定要注意

        //这里是官方给的微信支付接口签名校验工具可以对你拼接的xml数据进行校验对比重点是对比签名sign是否正确
        //https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=20_1


        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信下单接口连接不用更改

        $dataxml = $this->http_post($url,$post_data,$headers);//传参调用curl请求
        $objectxml = (array)simplexml_load_string($dataxml,'SimpleXMLElement',LIBXML_NOCDATA); //将微信返回的XML 转换成数组
        $objectxml['mweb_url'] = $objectxml['mweb_url']."&redirect_url=".urlencode("http://www.yixianglife.com/yxlife_new/ty/ty.html");
        file_put_contents('h5pay.log',json_encode($objectxml));
        $this->websuccess(self::OUTPUT_SUCCESS,'成功',$objectxml);
        
    }

    /**
     * 微信wap支付异步通知
     */
    public function wap_notify()
    {
        //获取商户key
        $wxconfig = new \WxPayConfig();
        $key = $wxconfig->GetKey();
        //获取微信发送的数据
        $notifuedData = file_get_contents("php://input");
        file_put_contents("./wxxml.log","信息:".$notifuedData."\n",FILE_APPEND);
        //将XML数据转换成数组
        $xmlObj = simplexml_load_string($notifuedData,'SimpleXMLElement',LIBXML_NOCDATA);
        $xmlObj = json_decode(json_encode($xmlObj),true);

        file_put_contents("./wxwapnotify.log","信息:".json_encode($xmlObj)."\n",FILE_APPEND);
        //发送成功进行验签
        if ($xmlObj['return_code'] == "SUCCESS" && $xmlObj['result_code'] == "SUCCESS")
        {
            file_put_contents("./orderdata.log","订单号1:".$xmlObj['out_trade_no'],FILE_APPEND);
            ksort($xmlObj);
            $buff = "";
            foreach ($xmlObj as $k=>$v)
            {
                if ($k!='sign')
                {
                    $buff .= $k.'='.$v.'&';
                }
            }
            $stringSignTemp = $buff .'key='.$key;

            $sign =strtoupper(md5($stringSignTemp));

            //签名步骤四:所有字符转为大写
            $sign = strtoupper($sign);
            file_put_contents("./sign.log","sign:".$sign."|".$xmlObj['sign']."\n",FILE_APPEND);
            if ( $sign == $xmlObj['sign']) {
                // 逻辑出来
          
                //通知微信成功获取到
                $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                echo $str;exit;
            }

        }

    }



    public function http_post($url='',$post_data=array(),$header=array(),$timeout=30) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 跳过证书检查
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

        $response = curl_exec($ch);

        curl_close($ch);

        return $response;
    }

    /**
     * jaapi支付异步通知
     */
    public function jsapi_notify()
    {

        $wxconfig = new \WxPayConfig();
        $key = $wxconfig->GetKey();
        //echo $key."<br>";
        // 获取微信回调的数据
        $notifiedData = file_get_contents('php://input');

        //XML格式转换
        $xmlObj = simplexml_load_string($notifiedData, 'SimpleXMLElement', LIBXML_NOCDATA);
        $xmlObj = json_decode(json_encode($xmlObj),true);
        file_put_contents("./wxnotifyinfoaccept.log","信息:".json_encode($xmlObj)."\n",FILE_APPEND);
        // 当支付通知返回支付成功时
        if ($xmlObj['return_code'] == "SUCCESS" && $xmlObj['result_code'] == "SUCCESS") {
            file_put_contents("./orderdata.log","订单号1:".$xmlObj['out_trade_no'],FILE_APPEND);

            //获取返回的所以参数
            //这里是要把微信返给我们的所有值,先删除sign的值,其他值 按ASCII从小到大排序,md5加密+‘key’;
            ksort($xmlObj);
            $buff = '';
            foreach ($xmlObj as $k => $v){
                if($k != 'sign'){
                    $buff .= $k . '=' . $v . '&';
                }
            }
            $stringSignTemp = $buff . 'key='.$key;//key为证书密钥
            //md5处理
            $sign = strtoupper(hash_hmac('sha256', $stringSignTemp, $key));
            file_put_contents("./sign.log","sign:".$sign."|".$xmlObj['sign'],FILE_APPEND);
            //验签名,默认支持MD5          
            if ( $sign == $xmlObj['sign']) {
               //做处理
      
                //通知微信成功获取到
                $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                echo $str;exit;
            }
        }
    }

    /**
     * 获取用户真实ip
     * @return string
     */
    public function get_client_ip() {
        if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $ip = getenv('HTTP_CLIENT_IP');
        } elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $ip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $ip = getenv('REMOTE_ADDR');
        } elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }

        return preg_match('/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';
    }



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值