TP5.0之微信开发

TP5.0之微信开发

  • 开发准备工作
  • 获取微信open_id和微信用户信息
  • 微信支付之公众号支付
  • 微信支付jssdk

开发准备工作

1.微信开发文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
2.微信支付sdk下载:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
3.Thinkphp5.0下载:http://www.thinkphp.cn/down.html
4.注意在微信平台配置好域名等参数

获取微信open_id和微信用户信息

1.获取openid需要前端给一个code,通过code获取open_id
2.php封装一个http请求函数

    /**
     * 发送HTTP请求方法
     * @param  string $url    请求URL
     * @param  array  $params 请求参数
     * @param  string $method 请求方法GET/POST
     * @return array  $data   响应数据
     */
    function httpCurl($url, $params, $method = 'POST', $header = array(), $multi = false){
        date_default_timezone_set('PRC');
        $opts = array(
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER     => $header,
            CURLOPT_COOKIESESSION  => true,
            CURLOPT_FOLLOWLOCATION => 1,
            CURLOPT_COOKIE         =>session_name().'='.session_id(),
        );
        /* 根据请求类型设置特定参数 */
        switch(strtoupper($method)){
            case 'GET':
                // $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
                // 链接后拼接参数  &  非?
                $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
                break;
            case 'POST':
                //判断是否传输文件
                $params = $multi ? $params : http_build_query($params);
                $opts[CURLOPT_URL] = $url;
                $opts[CURLOPT_POST] = 1;
                $opts[CURLOPT_POSTFIELDS] = $params;
                break;
            default:
                throw new Exception('不支持的请求方式!');
        }
        /* 初始化并执行curl请求 */
        $ch = curl_init();
        curl_setopt_array($ch, $opts);
        $data  = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        if($error) throw new Exception('请求发生错误:' . $error);
        return  $data;
    }

3.获取open_id

    public function get_access_token($code)
    {
        $params['secret']=$this->appsecret;
        $params['appid']=$this->appid;
        $params['code']=$code;
        $params['grant_type']="authorization_code";
        $token_url = "https://api.weixin.qq.com/sns/oauth2/access_token";
        $token_data = $this->httpCurl($token_url, $params, 'GET');
        $token_data=json_decode($token_data);
        $token_data = (array)$token_data;
        return $token_data;
    }

4.获取用户信息

 public function get_user_info($access_token)
    {
        $params['secret']=$this->appsecret;
        $params['appid']=$this->appid;
        $params['access_token']=$access_token['access_token'];
        $params['openid']=$access_token['openid'];
        $params['lang']='zh_CN';
        $url = "https://api.weixin.qq.com/sns/userinfo";
        $token_data = $this->httpCurl($url, $params, 'GET');
        $token_data=json_decode($token_data);
        $token_data = (array)$token_data;
        return $token_data;
    }

微信支付之公众号支付

1.微信支付类,引用于白俊遥博客中thinkphp3.2的写的支付类
附上源码

use think\Config;
error_reporting(E_ALL);
ini_set('display_errors', '1');
header("Content-Type: text/html;charset=utf-8");
// 定义时区
ini_set('date.timezone','Asia/Shanghai');

class Weixinpay {
    // 定义配置项
    private $config=array(
        'APPID'              => '', // 微信支付APPID
        'MCHID'              => '', // 微信支付MCHID 商户收款账号
        'KEY'                => '', // 微信支付KEY
        'APPSECRET'          => '',  //公众帐号secert
        'NOTIFY_URL'         => 'http://paysdk.weixin.qq.com/notify.php', // 接收支付状态的连接  改成自己的域名
    );

    // 构造函数
    public function __construct(){
 
        // 如果不是在thinkphp框架中使用;那么注释掉下面一行代码;直接补全 private $config 即可
        $this->config= Config::get('WEIPAY');

    }

    /**
     * 统一下单
     * @param  array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单金额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型:JSAPI,NATIVE,APP)
     */
    public function unifiedOrder($order){
        // 获取配置项
        $weixinpay_config=$this->config;
        $config=array(
            'appid'=>$weixinpay_config['APPID'],
            'mch_id'=>$weixinpay_config['MCHID'],
            'nonce_str'=>'test',
            'spbill_create_ip'=>'127.0.0.1',
            'notify_url'=>$weixinpay_config['NOTIFY_URL']
        );

        // 合并配置数据和订单数据
        $data=array_merge($order,$config);

        // 生成签名
        $sign=$this->makeSign($data);

        $data['sign']=$sign;
        $xml=$this->toXml($data);

        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//接收xml数据的文件
        $header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组
        $ch = curl_init ($url);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地没有指定curl.cainfo路径的错误
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $response = curl_exec($ch);
        if(curl_errno($ch)){
            // 显示报错信息;终止继续执行
            curl_error($ch);
        }
        curl_close($ch);
        $result=$this->toArray($response);
        // 显示错误信息
        if ($result['return_code']=='FAIL') {
            die($result['return_msg']);
        }
        $result['sign']=$sign;
        $result['nonce_str']='test';
        return $result;
    }


    /**
     * 验证
     * @return array 返回数组格式的notify数据
     */
    public function notify(){
        // 获取xml
        $xml=file_get_contents('php://input', 'r');
        // 转成php数组
        $data=$this->toArray($xml);
        // 保存原sign
        $data_sign=$data['sign'];
        // sign不参与签名
        unset($data['sign']);
        $sign=$this->makeSign($data);
        // 判断签名是否正确  判断支付状态
        if ($sign===$data_sign && $data['return_code']=='SUCCESS' && $data['result_code']=='SUCCESS') {
            $result=$data;
        }else{
            $result=false;
        }
        // 返回状态给微信服务器
        if ($result) {
            $str='';
        }else{
            $str='';
        }
        echo $str;
        return $result;
    }

    /**
     * 输出xml字符
     * @throws WxPayException
     **/
    public function toXml($data){
        if(!is_array($data) || count($data) <= 0){
            throw new WxPayException("数组数据异常!");
        }
        $xml = "";
        foreach ($data as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val.".$key.">";
            }else{
                $xml.="<".$key.">.$val."]]>.$key.">";
            }
        }
        $xml.="";

        return $xml;
    }

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

    /**
     * 将xml转为array
     * @param  string $xml xml字符串
     * @return array       转换得到的数组
     */
    public function toArray($xml){
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $result;
    }

    /**
     * 获取jssdk需要用到的数据
     * @return array jssdk需要用到的数据
     */
    public function getParameters($data){
        // 获取配置项
        $config=$this->config;
        // 取出订单号
        $out_trade_no=$data['out_trade_no'];
        // 组合获取prepay_id的url
        $openid=$data['openid'];
        // 订单数据  请根据订单号out_trade_no 从数据库中查出实际的body、total_fee、out_trade_no、product_id
        $order=array(
            'body'=>'test',// 商品描述(需要根据自己的业务修改)
            'total_fee'=>1,// 订单金额  以(分)为单位(需要根据自己的业务修改)
            'out_trade_no'=>$out_trade_no,// 订单号(需要根据自己的业务修改)
            'product_id'=>'1',// 商品id(需要根据自己的业务修改)
            'trade_type'=>'JSAPI',// JSAPI公众号支付
            'openid'=>$openid// 获取到的openid
        );
        // 统一下单 获取prepay_id
        $unified_order=$this->unifiedOrder($order);
        // 获取当前时间戳
        $time=time();
        // 组合jssdk需要用到的数据
        $data=array(
            'appId'=>$config['APPID'], //appid
            'timeStamp'=>strval($time), //时间戳
            'nonceStr'=>$unified_order['nonce_str'],// 随机字符串
            'package'=>'prepay_id='.$unified_order['prepay_id'],// 预支付交易会话标识
            'signType'=>'HMAC-SHA256'//加密方式
        );
        // 生成签名
        $data['paySign']=$this->makeSign($data);
        return $data;
    }

    /**
     * 生成支付二维码
     * @param  array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单金额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型:JSAPI,NATIVE,APP)
     */
    public function pay($order){
        $result=$this->unifiedOrder($order);
        $decodeurl=urldecode($result['code_url']);
        qrcode($decodeurl);
    }

    /**
     * curl 请求http
     */
    public function curl_get_contents($url){
        $ch=curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);                //设置访问的url地址
        // curl_setopt($ch,CURLOPT_HEADER,1);               //是否显示头部信息
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);               //设置超时
        curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);   //用户访问代理 User-Agent
        curl_setopt($ch, CURLOPT_REFERER,$_SERVER['HTTP_HOST']);        //设置 referer
        curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);          //跟踪301
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);        //返回结果
        $r=curl_exec($ch);
        curl_close($ch);
        return $r;
    }
}

2.使用这个类进行支付操作
类文件放置于
TP5.0之微信开发_第1张图片

        Vendor('Weixinpay.Weixinpay');
        $wxpay=new \Weixinpay();
        // 获取jssdk需要用到的数据
        $paydata=['out_trade_no'=>time(),"openid"=>"test"];
        $data=$wxpay->getParameters($paydata);
        // 将数据分配到前台页面
        $assign=array(
            'data'=>($data)
        );
       return json($assign);

3.支付回调

        Vendor('Weixinpay.Weixinpay');
        $wxpay=new \Weixinpay();
        $data=$wxpay->notify();
        if (!$data) {
            return 0;
        }

微信支付jssdk

注意获取jssdk的接口路径需要,要在微信平台配置
附件 https://pan.baidu.com/s/15E2miSrBp_AEYyUJNYizlw 提取码 vyzs

        Vendor('weixin.JsSdk');
        $jssdk = new \JsSdk("open_id", "key");
        $r=Request::instance();
        $url=$r->param("url");
        if(empty($url)){
            return json(['code'=>0,"msg"=>"url不可为空!"]);
        }
        $signPackage = $jssdk->GetSignPackage($url);
        if($signPackage==0){
            return json(['code'=>0,"data"=>"","msg"=>"获取失败"]);
        }
        return  json(['code'=>1,"data"=>$signPackage,"msg"=>"获取成功"]);

你可能感兴趣的:(thinkphp,微信)