美文网首页
php 微信支付回调校验的两种做法

php 微信支付回调校验的两种做法

作者: php转go | 来源:发表于2021-03-06 11:04 被阅读0次

    支付的时候设置了异步回调地址
    微信回调返回的数据是xml

    <xml><appid><![CDATA[wx6a94d840sssssss]]></appid>
    <attach><![CDATA[test]]></attach>
    <bank_type><![CDATA[OTHERS]]></bank_type>
    <cash_fee><![CDATA[1]]></cash_fee>
    <fee_type><![CDATA[CNY]]></fee_type>
    <is_subscribe><![CDATA[Y]]></is_subscribe>
    <mch_id><![CDATA[1602876300]]></mch_id>
    <nonce_str><![CDATA[5dh7wiradptg55udp7w9rmlrur8madrv]]></nonce_str>
    <openid><![CDATA[oo44a5uldojwVmL27KS4R0APR_gw]]></openid>
    <out_trade_no><![CDATA[sdkphp20210305164812]]></out_trade_no>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <sign><![CDATA[BD851430C2493F16A49B70A5B5D26DE4F2906B1CB3B5B969193DB9671DAE4AAF]]></sign>
    <time_end><![CDATA[20210305164816]]></time_end>
    <total_fee>1</total_fee>
    <trade_type><![CDATA[JSAPI]]></trade_type>
    <transaction_id><![CDATA[4200000892202103057215065043]]></transaction_id>
    </xml>
    

    直接用post或者get是获取不到微信返回的数据,需要使用 file_get_contents("php://input");

    实现代码

        /**
         * @return string
         */
        public function notify(): string
        {
            $xmlstr = file_get_contents("php://input");
            if(empty($xmlstr)) return '非法访问';
            $xmlObj = simplexml_load_string($xmlstr, 'SimpleXMLElement', LIBXML_NOCDATA);
            $data = json_decode(json_encode($xmlObj),true);
            if ($this->checkSign($data)) {
            //校验通过,可以再增加对微信官方订单查询,判断订单真实性
                return 'success';
            }
            return 'fail';
        }
        /**校验签名
         * @param array $arr
         * @return bool
         */
        private function checkSign(array $arr): bool
        {
            $sign = $arr['sign'];
            unset($arr['sign']);
            $key='1234';//微信商户平台支付设置的key
            ksort($arr);//根据key升序排序
            $str=http_build_query($arr);//数组字典排序拼接字符串
            $stringSignTemp = $str.'&key='.$key;//拼接上key
            $signValue = md5($stringSignTemp);//md5处理
            $signValue = strtoupper($signValue);//转大写
            return $signValue == $sign;
    
        }
    

    也可以这样,直接使用官方SDK

    
    require_once "../lib/WxPay.Api.php";
    require_once '../lib/WxPay.Notify.php';
    require_once "WxPay.Config.php";
    require_once 'log.php';
    
    //初始化日志
    $logHandler= new CLogFileHandler("../logs/".date('Y-m-d').'.log');
    $log = Log::Init($logHandler, 15);
    
    class PayNotifyCallBack extends WxPayNotify
    {
        //查询订单
        public function Queryorder($transaction_id)
        {
            $input = new WxPayOrderQuery();
            $input->SetTransaction_id($transaction_id);
    
            $config = new WxPayConfig();
            $result = WxPayApi::orderQuery($config, $input);
            Log::DEBUG("query:" . json_encode($result));
            if(array_key_exists("return_code", $result)
                && array_key_exists("result_code", $result)
                && $result["return_code"] == "SUCCESS"
                && $result["result_code"] == "SUCCESS")
            {
                return true;
            }
            return false;
        }
    
        /**
        *
        * 回包前的回调方法
        * 业务可以继承该方法,打印日志方便定位
        * @param string $xmlData 返回的xml参数
        *
        **/
        public function LogAfterProcess($xmlData)
        {
            Log::DEBUG("call back, return xml:" . $xmlData);
            return;
        }
        
        //重写回调处理函数
        /**
         * @param WxPayNotifyResults $data 回调解释出的参数
         * @param WxPayConfigInterface $config
         * @param string $msg 如果回调处理失败,可以将错误信息输出到该方法
         * @return true回调出来完成不需要继续回调,false回调处理未完成需要继续回调
         */
        public function NotifyProcess($objData, $config, &$msg)
        {
            var_dump($objData);
            $data = $objData->GetValues();
            //TODO 1、进行参数校验
            if(!array_key_exists("return_code", $data) 
                ||(array_key_exists("return_code", $data) && $data['return_code'] != "SUCCESS")) {
                //TODO失败,不是支付成功的通知
                //如果有需要可以做失败时候的一些清理处理,并且做一些监控
                $msg = "异常异常";
                return false;
            }
            if(!array_key_exists("transaction_id", $data)){
                $msg = "输入参数不正确";
                return false;
            }
    
            //TODO 2、进行签名验证
            try {
                $checkResult = $objData->CheckSign($config);
                if($checkResult == false){
                    //签名错误
                    Log::ERROR("签名错误...");
                    return false;
                }
            } catch(Exception $e) {
                Log::ERROR(json_encode($e));
            }
    
            //TODO 3、处理业务逻辑
            Log::DEBUG("call back:" . json_encode($data));
            $notfiyOutput = array();
            
            
            //查询订单,判断订单真实性
            if(!$this->Queryorder($data["transaction_id"])){
                $msg = "订单查询失败";
                return false;
            }
            return true;
        }
    }
    $config = new WxPayConfig();
    Log::DEBUG("begin notify");
    $notify = new PayNotifyCallBack();
    $notify->Handle($config, false);
    

    相关文章

      网友评论

          本文标题:php 微信支付回调校验的两种做法

          本文链接:https://www.haomeiwen.com/subject/iopjqltx.html