1. 程式人生 > >小程式的登入和支付介面

小程式的登入和支付介面

<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Powerless <
[email protected]
>
// +----------------------------------------------------------------------
namespace app\user\controller;
use think\Db;
use think\Validate;
use cmf\controller\HomeBaseController;
use app\user\model\UserModel;


//說明 
//1、登陸:getuserid()   getuserinfo()   如果有分享關係調用share() 我這個share裡的邏輯你用不了,你自己改寫
//2、支付:createOrders()   payResult()   注意小程式商戶支付的key


//這些介面都是從小程式前端呼叫


class SearchController extends HomeBaseController

   function _initialize()
   {
    parent::_initialize();
   }
       //xml轉換成陣列
   private 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;
   }   
  public function  share($m_id=0,$f_id=0){   //處理好友關係


      if($m_id>0 && $m_id!= $f_id ){
            $insert_data = array(
               'm_id'=> $m_id,    
               'f_id'=>$f_id
            );
        $m_id=intval($m_id);
        $f_id=intval($f_id);


         $f_list1 =  Db::query(" select count(1) as f_1 from cmf_gd_friend where `m_id` =  ".$m_id." and  `f_id` =  ".$f_id);
          $f_list2 =  Db::query(" select count(2) as f_2 from cmf_gd_friend where  `m_id` =  ".$f_id." and  `f_id` =  ".$m_id);
            $result=$f_list1[0]['f_1']+$f_list2[0]['f_2'];
    
            if(!$result){
                 Db::name('gd_friend')->insert($insert_data);
            }
       }   
   }   
  public   function genSign($user)
    {
        $sign = md5($user['id'] . '%' . $user['openid'] . '&' . time());
        return $sign;
    
    }
       //登陸1
   public function getuserid(){
      $code  = $this->request->param('code');
       $f_id  = $this->request->param('f_id');


      $appid ='wx48809052c4cd1f65';
      $secret='9516d525b6c4601712564bc65e565003';
      $url   = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$secret}&js_code=$code&grant_type=authorization_code";
      $data  = json_decode(file_get_contents($url),true);


      if ($data){
        $user = Db::name('gd_user')->where('openid',$data['openid'])->find();
        if(!$user){
         
          $sign = isset($user['sign']) ? $user['sign'] : $this->genSign($user);
         
          $sign_expire = intval(strtotime('+12 months'));
          $insert_data = array(
            'openid'=>$data['openid'],
            'session_key'=>$data['session_key'],
            'logintime'=>time(),
            'sign'=>$sign,
            'sign_expire'=>$sign_expire
          );
          $res = Db::name('gd_user')->insert($insert_data);    
          $sign = isset($user['sign']) ? $user['sign'] : $this->genSign($user);
          $user = Db::name('gd_user')->where('openid',$data['openid'])->find();
          $data = json_encode(['status' => 1,'sign' => $sign,'id'=>$user['id']]);
          if($f_id>0){
              $m_id = $user['id'];
              $this->share($m_id,$f_id);
          }
          
          return $data;                    
        } else {


          $update_data = array(
            'session_key'=>$data['session_key']    
          );
          $res = Db::name('gd_user')->where('id',$user['id'])->update($update_data);
        }
        $sign = isset($user['sign']) ? $user['sign'] : $this->genSign($user);
        $data = json_encode(['status' => 1,'sign' => $sign,'id'=>intval($user['id'])]);
        if($f_id>0){
              $m_id = $user['id'];
              $this->share($m_id,$f_id);
          }
        return $data;  
      }
       return  json_encode(['status' => 0,'msg'=>'獲取簽名失敗']);
  }




  public function getMidBySign($sign)
  {
    $user = db('gd_user')->where('sign',$sign)->find();
    if (! $user || $user['sign_expire'] < time()) {
      return null;
    }


    return json_encode($user['id']);
  }
     //登陸2
  public function getuserinfo(){
       // $request = Request::instance();


      $mid =$this->getMidBySign($this->request->param('sign'));


      if (! $mid) {
         return json_encode([
          'status' => 0,
          'msg' => '登入會話失效'
         ]);
     }
     $insert_data=array(
      'name'=>urlencode($this->request->param('nickName')),
      'avatar'=>$this->request->param('avatarUrl'),
      'sex'=>$this->request->param('gender')
    );
    $mid=intval(substr($mid,1,strlen($mid)-1));
     
    // $res = Db::name('gd_user')->where('id',$user['id'])->update($update_data);
     $res = Db::name('gd_user')->where('id',$mid)->update($insert_data);
      
          //登陸成功返回使用者資訊
     $data = Db::name('gd_user')->field('id')->where('id',$mid)->find();


     return  json_encode([$data,'status' => 1,'msg'=>'登陸成功']);
 }






 public function createOrders(){  //發起支付
$user_id = $this->request->param('user_id');


  $user_list = db('gd_user')->where('id',$user_id)->find();


        // 生成訂單
  $string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  $str = '';
  $length = rand(4, 8);
  for ($i = 0; $i < $length; $i ++) {
    $str .= $string[rand(0, 61)];
  }


  $out_trade_no = $user_list['id'] . $str . date('YmdHis', time());
  $insert = array(
    'uid' => $user_id,
    'out_trade_no'=>'E009' . $out_trade_no,
    'total_fee'=>1,
    'order_status'=>0,
                //'relate_id'=> $relate_id,
    'ip'=>$_SERVER['REMOTE_ADDR'],
    'order_time'=>time()
  );


  $params = [
    'out_trade_no' => 'E009' . $out_trade_no,
    'total_fee' => 1,
    'openid' => $user_list['openid']
  ];


  $order_insert = db('gd_orders')->insert($insert);


  if ($order_insert) {
    $result = $this->pay(json_encode($params));


    return json_encode([
      'status' => 1,
      'data' => json_decode($result)
    ]);
  } else {
    return [
      'status' => 0,
      'msg' => '生成訂單失敗'
    ];
  }     


}


    /*
    * 微信支付完成,回撥地址url方法
    */
    public function payResult() {
      $post = file_get_contents('php://input');    //接受POST資料
      $post_data = $this->xmlToArray($post);   //微信支付成功,返回回撥地址url的資料:XML轉陣列Array
      $postSign = $post_data['sign'];
      unset($post_data['sign']);
      //$this->debugLog($post, true);


      /* 微信官方提醒:
       *  商戶系統對於支付結果通知的內容一定要做【簽名驗證】,
       *  並校驗返回的【訂單金額是否與商戶側的訂單金額】一致,
       *  防止資料洩漏導致出現“假通知”,造成資金損失。
       */
       //通過訂單號查詢訂單詳情


      $orderDetail = db('gd_orders')->where('out_trade_no',$post_data['out_trade_no'])->find();
      if($post_data['return_code']=='SUCCESS' && $postSign && $orderDetail && $post_data['total_fee'] == $orderDetail['total_fee']){
          /*
          * 首先判斷,訂單是否已經更新為1,因為微信會總共傳送8次回撥確認
          * 其次,訂單已經為1的,直接返回SUCCESS
          * 最後,訂單沒有為1的,更新狀態為1,返回SUCCESS
          */
          if($orderDetail['order_status']){
            $this->return_success();
          }else{
      
                //是否首次支付
                 $userinfo = db('gd_user')->field('status,points')->where('id',$orderDetail['uid'])->find();
                 $order_update = array(
                  'order_status'=> 1,
                  'ok_time'=>time()
                );
                 $user_update = array(
                  'status'=> 1,
                );




                 $success = db('gd_orders')->where(['out_trade_no'=>$post_data['out_trade_no']])->update($order_update);
                     db('gd_user')->where(['id'=>$orderDetail['uid']])->update($user_update);
                 $data = array();
                 if($success){
                     if($userinfo['status']){
                    
                                 Db::name('gd_user')->where('id',$orderDetail['uid'])->setInc('points',10);      //支付增加10積分
                                 $data['points'] = $userinfo['points']+10;
                     }else{  //首次支付送20積分
                               
                                 Db::name('gd_user')->where('id',$orderDetail['uid'])->setInc('points',20);      //支付增加20積分
                                 $data['points'] = $userinfo['points']+20;
                     }
                                $success = db('gd_orders')->where('id',$orderDetail['uid'])->update(['status' => 1]);    //標記已經成功支付,方便下次判斷是否首次支付


                  }
                      //查出當前積分
                            echo json_encode($data);
                            $this->return_success();   
            }
        }
    }


  /*
     * 給微信傳送確認訂單金額和簽名正確,SUCCESS資訊 -xzz0521
     */
  private function return_success(){
    $return['return_code'] = 'SUCCESS';
    $return['return_msg'] = 'OK';
    $xml_post = '<xml>
    <return_code>'.$return['return_code'].'</return_code>
    <return_msg>'.$return['return_msg'].'</return_msg>
    </xml>';
    echo $xml_post;
  }


/*
    *支付介面
    */
public function pay($params) {
        //統一下單介面


  $return = $this->weixinapp(json_decode($params));


  return json_encode($return);


}


    //統一下單介面
private function unifiedorder($params) {
  $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
  $body = '一筆-畫圖'; //商品描述
  $parameters = array(
            'appid' => 'wx48809052c4cd1f65', //小程式ID
            'mch_id' => 1498313262, //商戶號
            'nonce_str' => $this->createNoncestr(), //隨機字串
            //'body' => 'test', 
            'body' => $body,
            //'out_trade_no' => '2015450806125348', //商戶訂單號
            'out_trade_no'=> $params->out_trade_no,
            //'total_fee' => floatval(0.01 * 100), //總金額 單位 分
            'total_fee' => $params->total_fee,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //終端IP
            //'spbill_create_ip' => '192.168.0.161', //終端IP
            'notify_url' => 'https://stroke.zealcdn.cn/user/search/payResult', //通知地址  確保外網能正常訪問
            'openid' => $params->openid, //使用者id
            'trade_type' => 'JSAPI'//交易型別
          );
        //統一下單簽名
  $parameters['sign'] = $this->getSign($parameters);
        //$this->debugLog($parameters['sign'], true);
  $xmlData = $this->arrayToXml($parameters);
  $return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
       
  return $return;
}


private function postXmlCurl($xml, $url, $type = false, $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);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        set_time_limit(0);
        //執行curl
        $data = curl_exec($ch);
        //print_r($data);die();
        //返回結果
        if ($data) {
          curl_close($ch);
          return $data;
        } else {
          $error = curl_errno($ch);
          curl_close($ch);
          throw new WxPayException("curl出錯,錯誤碼:$error");
        }
      }


    //陣列轉換成xml
      private function arrayToXml($arr) {
        $xml = "<root>";
        foreach ($arr as $key => $val) {
          if (is_array($val)) {
            $xml .= "<" . $key . ">" . arrayToXml($val) . "</" . $key . ">";
          } else {
            $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
          }
        }
        $xml .= "</root>";
        return $xml;
      }






    /**
    *微信小程式介面
    */
    private function weixinapp($params) {
        //統一下單介面


        $unifiedorder = $this->unifiedorder($params);




 
        if ($unifiedorder['return_code'] !== 'SUCCESS') {
          return false;
        }


        $parameters = array(
               'appId' => 'wx48809052c4cd1f65',
              'timeStamp' => '' . time() . '', //時間戳
              'nonceStr' => $this->createNoncestr(), //隨機串
              'package' => 'prepay_id=' . $unifiedorder['prepay_id'], //資料包
              'signType' => 'MD5'//簽名方式
            );


 


          //簽名
        $parameters['paySign'] = $this->getSign($parameters);
        return $parameters;
        
    }


    /**
    *作用:產生隨機字串,不長於32位
    */
    private function createNoncestr($length = 32) {
      $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      $str = "";
      for ($i = 0; $i < $length; $i++) {
        $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
      }
      return $str;
    }


    /**
    *作用:生成簽名
    */
    private function getSign($Obj) {
      foreach ($Obj as $k => $v) {
        $Parameters[$k] = $v;
      }
        //簽名步驟一:按字典序排序引數
      ksort($Parameters);
      $String = $this->formatBizQueryParaMap($Parameters, false);
        //簽名步驟二:在string後加入KEY
      $String = $String . "&key=" . 'chaonengzhexinnianshangxiaocheng';     //小程式支付商戶平臺的key

        //簽名步驟三:MD5加密
      $String = md5($String);
        //簽名步驟四:所有字元轉為大寫
      $result_ = strtoupper($String);
      return $result_;
    }


    /**
    *作用:格式化引數,簽名過程需要使用
    */
    private function formatBizQueryParaMap($paraMap, $urlencode) {
      $buff = "";
      ksort($paraMap);
      foreach ($paraMap as $k => $v) {
        if ($urlencode) {
          $v = urlencode($v);
        }
        $buff .= $k . "=" . $v . "&";
      }
      $reqPar;
      if (strlen($buff) > 0) {
        $reqPar = substr($buff, 0, strlen($buff) - 1);
      }
      return $reqPar;
    }










































































    public function search()
    {    
     //充值成功增加積分
      $keyword= $this->request->param('keyword');
      $num = $this->request->param('num');
      if(!$num){$num = 10;}
      $mobile = session('user_mobile');
      $id_name = Db::name('user')->field('id,mobile,avatar,user_nickname')->where(['mobile' => $mobile])->find();
      $id = $id_name['id'];
      $img_url = $id_name['avatar'];
      $nickname = $id_name['user_nickname'];


      $name = $id_name['mobile'];


      if($nickname){
       $name = $nickname;
     }else{
       $name = $id_name['mobile'];
     }
     if($keyword){
      $keywordComplex['name|certNo|mobile']    = ['like', "%$keyword%"];
      $usersQuery = Db::name('user_report');
      $data = $usersQuery->whereOr($keywordComplex)->where(['parent_id' => $id])->order("change_time DESC")->paginate($num);


    }else{
      $data = Db::name('user_report')->where(['parent_id' => $id])->order("change_time DESC")->paginate($num);
    }
    $page = $data->render();
    $this->assign('page', $page);
    $this->assign('id', $id);
    $pager = $this->request->param('page');


    $this->assign('num', $num); 
    $this->assign('img_url', $img_url); 
    $this->assign('name', $name); 
    $this->assign('pager', $pager); 
    $this->assign('data', $data); 
        // return 666;
        return $this->fetch(':list'); //顯示頁面,相當於display,顯示User下的list.html
      } 
    //貸款稽核


      public function query()
      {                 
        return $this->fetch(':query'); //顯示頁面,相當於display,顯示User下的list.html
      } 


      public function login($reqId, $partnerId, $certNo, $name, $mobile, $pwd, $smsCode) {
        $loginUrl = "https://credit.baiqishi.com/clweb/api/mno/login";
        $data = array('reqId'=>$reqId, 'partnerId'=>$partnerId, 'certNo'=>$certNo, 'name'=>$name, 'mobile'=>$mobile, 'pwd'=>$pwd, 'smsCode'=>$smsCode);


        $data = json_encode($data, JSON_UNESCAPED_UNICODE);


        $encode = mb_detect_encoding($data, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5'));
        $req = mb_convert_encoding($data, 'UTF-8', $encode);


        error_log($req);
        return $this->doPost($loginUrl, $req);
      }






















      private function doPost($url, $data) {
        $ch = curl_init();
        error_log($url.$data);


        $timeout = 1500;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        $rs = curl_exec($ch);
        curl_close($ch);


        $rs = json_decode($rs);
        return $rs;
      }


    }