龚哥哥 - 山里男儿 爱生活、做自己!
2015最新微信支付APP 服务端处理
发表于 2015-8-31 | PHP
<?php

/**
 * 微信支付驱动
 * @author  Devil
 * @version v_1.0.0
 */
class WeiXin
{
    private $config;

    /**
     * [__construct 从数据库读取微信申请的密钥]
     */
    public function __construct() 
    {
        $this->config = array(
                'partner_id'        =>  '',
                'partner_key'       =>  '',
                'appid'             =>  '',
                'secret'            =>  '',
                'pay_sign_key'      =>  '',
                'notify_url'        =>  '',
            );
    }

    /**
     * [Get_App_Code 生成支付信息]
     * @param  [array] $order   [订单数据]
     * @return [string]         [支付信息]
     */
    public function Get_App_Code($order)
    {
        /* 标题空格处理 */
        if(!empty($order['subject'])) $order['subject'] = str_replace(array(' ', "\n", "\r"), '', $order['subject']);

        $access_token = $this->Get_Access_Token();
        $param = array(
            'appid'         =>  $this->config['appid'],
            'traceid'       =>  $order['out_trade_no'],
            'noncestr'      =>  md5(time().rand()),
            'package'       =>  $this->GetParamData($order),
            'timestamp'     =>  time(),
            'sign_method'   =>  'sha1',
        );

        /* 获取支付签名 */
        $param['app_signature'] = $this->GetAppSign($param);

        /* 生成预支付 */
        $data = $this->GenprePayInsert($param, $access_token);

        /* 生成支付信息 */
        if(!empty($data['prepayid']) && !empty($data['errmsg']) && $data['errmsg'] == 'Success')
        {
            $pay = array(
                    'appid'         =>  $this->config['appid'],
                    'noncestr'      =>  $param['noncestr'],
                    'package'       =>  'Sign=WXPay',
                    'partnerid'     =>  $this->config['partner_id'],
                    'prepayid'      =>  $data['prepayid'],
                    'timestamp'     =>  $param['timestamp']
                );
            $pay['sign'] = $this->GetAppSign($pay);
            return $pay;
        }
        return '';
    }

    /**
     * [GenprePayInsert 生成预支付]
     * @param [array] $param        [请求参数]
     * @param [token] $access_token [token]
     */
    private function GenprePayInsert($param, $access_token)
    {
        return json_decode($this->Curl_Post('https://api.weixin.qq.com/pay/genprepay?access_token='.$access_token, json_encode($param)), true);
    }

    /**
     * [GetAppSign signature签名生成]
     * @param [array] $param    [参数数据]
     */
    private function GetAppSign($param)
    {
        unset($param['sign_method']);
        $param['appkey'] = $this->config['pay_sign_key'];
        ksort($param);
        return sha1($this->SetParam($param));
    }

    /**
     * [GetParamData 获取参数数据]
     * @param  [array] $data    [订单数据]
     * @return [array]          [参数和sign]
     */
    private function GetParamData($data)
    {
        $order = array(
            'bank_type'         =>  'WX',
            'body'              =>  $data['subject'],
            'total_fee'         =>  $data['total_fee']*100, /* 微信要求需要乘以100 */
            'spbill_create_ip'  =>  $GLOBALS['pz_log']->Getip(),
            'out_trade_no'      =>  $data['out_trade_no'],
            'notify_url'        =>  $this->config['notify_url'],
            'partner'           =>  $this->config['partner_id'],
            'fee_type'          =>  1,
            'input_charset'     =>  'UTF-8',
            'attach'            =>  'weixin',
        );
        ksort($order);

        $sgin = strtoupper(md5($this->SetParam($order).'&key='.$this->config['partner_key']));
        return $this->SetParam($order, true).'&sign='.$sgin;
    }

    /**
     * [Curl_Post curl模拟post]
     * @param  [string] $url  [请求地址]
     * @param  [array] $post  [发送的post数据]
     */
    private function Curl_Post($url, $post) {
        $options = array(
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HEADER         => false,
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $post,
        );

        $ch = curl_init($url);
        curl_setopt_array($ch, $options);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

    /**
     * [SetParam url模式字符串拼接]
     * @param [array]  $param         [需要拼接的参数]
     * @param [boolean] $is_urlencode [是否urlencode转义value]
     */
    private function SetParam($param, $is_urlencode = false)
    {
        $str = '';
        foreach($param as $k=>$v) 
        {
            if($is_urlencode)
            {
                $str .= $k.'='.urlencode($v).'&';
            } else {
                $str .= $k.'='.$v.'&';
            }
        }
        return substr($str, 0, -1);
    }

    /**
     * [Get_Access_Token 获取微信支付token]
     * @return [string]         [token]
     */
    private function Get_Access_Token()
    {   
        if(file_exists('/tmp/weixin_pay_token.json'))
        {
            $temp = json_decode(file_get_contents('/tmp/weixin_pay_token.json'), true);
            if($temp['time'] > time()) $token = $temp['token'];
        }
        if(empty($token)) $token = $this->Set_Access_Token();
        return $token;
    }

    /**
     * [Set_Access_Token token设置]
     * @return [string]     [token]
     */
    private function Set_Access_Token()
    {
        $temp = json_decode(file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$this->config["appid"].'&secret='.$this->config['secret']), true);
        if(!empty($temp['access_token']))
        {
            $data = array(
                    'token' =>  $temp['access_token'],
                    'time'  =>  time()+7000
                );
            if(!is_dir('/tmp')) mkdir('/tmp');
            file_put_contents('/tmp/weixin_pay_token.json', json_encode($data));
            return $temp['access_token'];
        }
        return '';
    }

    /**
     * [Respond 响应操作]
     * @return [string] [响应处理结果]
     */
    public function Respond()
    {
        $param = $_GET;
        if(empty($param)) return;
        $param_sign = $param['sign']; unset($param['sign']);

        ksort($param);
        $sign = strtoupper(md5($this->SetParam($param).'&key='.$this->config['partner_key']));
        if($param_sign != $sign) return;

        /* check_money方法 价格校验是否一致 */
        if(isset($param['trade_state']) && $param['trade_state'] == 0 && check_money($param['out_trade_no'], $param['total_fee']/100))
        {
            //如果成功这里就可以处理自己的订单了,标识符是 $param['out_trade_no']
        }
    }
}

?>

发表评论:

TOP