ѡ̳

标题: 增加微信公众号支付 [打印本页]

作者: admin    时间: 2018-12-27 22:12
标题: 增加微信公众号支付
<?php

defined('IN_PHPCMS') or exit('No permission resources.');


if (isset($set_modules) && $set_modules == TRUE)

{

    $i = isset($modules) ? count($modules) : 0;

    $modules[$i]['code']    = basename(__FILE__, '.class.php');

    $modules[$i]['name']    = L('weixinpay', '', 'pay');

    $modules[$i]['desc']    = L('weixinpay_desc', '', 'pay');

    $modules[$i]['is_cod']  = '0';

    $modules[$i]['is_online']  = '1';

    $modules[$i]['author']  = '易百讯开发团队';

    $modules[$i]['website'] = 'http://www.yibaixun.com/';

    $modules[$i]['version'] = '1.0.0';

    $modules[$i]['config']  = array(

       array('name' => 'weixinpay_appid','type' => 'text','value' => ''),

       array('name' => 'weixinpay_appsecret','type' => 'text','value' => ''),

        array('name' => 'weixinpay_mchid','type' => 'text','value' => ''),

       array('name' => 'weixinpay_key','type' => 'text','value' => ''),

    );



    return;

}

pc_base::load_app_class('pay_abstract','','0');

  //  开启session
$session_storage = 'session_'.pc_base::load_config('system','session_storage');

pc_base::load_sys_class($session_storage);


class Weixinpay extends paymentabstract{



   public function __construct($config = array()) {

      if (!empty($config)) $this->set_config($config);



      $this->config['return_url'] = return_url('Weixinpay'); //大写

      $this->config['weixinpay_signtype'] = 'MD5';



   }

   public function getpreparedata() {

      $prepare_data  = array();



      return $prepare_data;

   }



   public  function get_code()

   {

      if (!defined('CHARSET'))

      {

         $charset = 'utf-8';

      }

      else

      {

         $charset = CHARSET;

      }

      $charset = strtoupper($charset);



      //配置参数

      $this->payments =  $this->config ;//"Weixinpay";

      //根目录url

      $root_url = '/';

      //查找openid



      $account_db = pc_base::load_model('pay_account_model');

      $member_db = pc_base::load_model('member_model');



      $payorderinfo = $account_db->get_one(array('id'=> $this->order_info['id']), '`userid`');



      $memberinfo = $member_db->get_one(array('userid'=> $payorderinfo['userid']), '`connectid`'); //这里需要获取会员的openid



      //$openid = $memberinfo['connectid'];

        $openid = $_SESSION['openid'];

        if(empty($openid)){

              echo "获取openid失败!";

          //这个openid 需要预先获取 一般在网站入口那里 设置 :不存在openid 测请求 返回code  通过code 获取openid

          }


      $this->setParameter("openid",$openid);

      //商品描述

      $this->setParameter("body", $this->order_info['id']);



      //商户订单号

      $this->setParameter("out_trade_no", $this->order_info['id']);

      //订单总金额

      $this->setParameter("total_fee", $this->product_info['price'] * 100);

      //支付币种

      //$this->setParameter("fee_type", "1");

      //通知URL

      $this->setParameter("notify_url", $this->config['return_url']);

      //订单生成的机器IP

      $this->setParameter("spbill_create_ip", ip());

      //传入参数字符编码

      $this->setParameter("input_charset", $charset);

      //交易类型

      $this->setParameter("trade_type","JSAPI");



      $prepay_id = $this->getPrepayId();



      $this->setPrepayId($prepay_id);

      //  为微信支付返回不能带参数 只能伪静态

        // echo $this->config['return_url'];



      $jsapi = $this->getParameters();
        $price = $this->product_info['price'];

       // print_r(json_decode($jsapi,true));

      //wxjsbridge

        $html = <<<EOF
        <html> <head><title>微信支付</title> </head>
         <body style="display: flex;
    justify-content:center;
    align-items: center; width: 100%;">
    <br/>
   
   <div align="center" style="width:100%; display: block;" >
      <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px"> $price </span></b></font><br/><br/>
      <button style="width:90%; height:100px; line-height: 100px; border-radius:5px;background-color:#00b43c; border:0px #00b43c solid; cursor: pointer;  color:white;  font-size:36px;" type="button"color:#34b434;font-style:italic;">callpay()" >立即支付</button>
   </div>
</body>
</html>
                    <script type="text/javascript">
                      //调用微信JS api 支付
                    function jsApiCall()
                    {
                    
                        WeixinJSBridge.invoke(
                            'getBrandWCPayRequest',$jsapi,
                            function(res){
                                    WeixinJSBridge.log(res.err_msg);
                                 if(res.err_msg == "get_brand_wcpay_requestk") {
                                      location.href='/index.php?m=member';  
                                 }else{
                                    alert(res.err_code+res.err_desc+res.err_msg);
                                    
                                 }
                            }
                        );
                    }
               
                    function callpay()
                    {
                        
                  
                         if (typeof WeixinJSBridge == "undefined"){
                            if( document.addEventListener ){
                                document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                            }else if (document.attachEvent){
                                document.attachEvent('WeixinJSBridgeReady', jsApiCall);
                                document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                            }
                        }else{
                            jsApiCall();
                        }
                    }
                    
                    callpay();
                    
                    </script>
EOF;

      $button = $html;



      return $button;





   }



   /**

    * 客户端接收数据

    * 状态码说明  (0 交易完成 1 交易失败 2 交易超时 3 交易处理中 4 交易未支付)
     *
     *
     *
     * 执行日期:2016-11-18-00:37:17
    【接收到的notify通知】:
    <xml><appid><![CDATA[wxe3d0167cf9c9fbb2]]></appid>
    <attach><![CDATA[10]]></attach>
    <bank_type><![CDATA[CFT]]></bank_type>
    <cash_fee><![CDATA[2]]></cash_fee>
    <fee_type><![CDATA[CNY]]></fee_type>
    <is_subscribe><![CDATA[Y]]></is_subscribe>
    <mch_id><![CDATA[1383733802]]></mch_id>
    <nonce_str><![CDATA[s4l9wggn9dxx356pie7jguv0mahu8fbq]]></nonce_str>
    <openid><![CDATA[oudtvwBsblPqpKiGPSi-2qaPsm30]]></openid>
    <out_trade_no><![CDATA[14794006211967]]></out_trade_no>
    <result_code><![CDATA[SUCCESS]]></result_code>
    <return_code><![CDATA[SUCCESS]]></return_code>
    <sign><![CDATA[51520F6851E5CC3B46F37D7CA8A22898]]></sign>
    <time_end><![CDATA[20161118003718]]></time_end>
    <total_fee>2</total_fee>
    <trade_type><![CDATA[JSAPI]]></trade_type>
    <transaction_id><![CDATA[4002572001201611180049986614]]></transaction_id>
    </xml>
     *
     *

    */

    public function receive() {

        //获取通知的数据
         $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
         //$xml = file_get_contents('php://input');
        $postdata=$this->xmlToArray($xml);

        //$this->logResult("log::respond::postdata:",$postdata);

        $wxsign = $postdata['sign'];


        $this->payments =  $this->config ;// 同步系统配置参数

         //排除无关的sign

        unset($postdata['sign']);

        $sign = $this->getSign($postdata);


        $return_data['order_status'] = 5;    //必要参数


        $sinarr = array('wxsign'=>$wxsign,'sign'=>$sign,'key'=>$this->payments['weixinpay_key']);


        $this->logResult("log::respond::sign_pk_data:",$sinarr);

          //先不比对签名
          if ($wxsign == $sign) {
            // 交易成功
            if ($postdata['result_code'] == 'SUCCESS') {
                // 获取out_trade_no 传过去的订单号

                $return_data['order_id'] = $postdata['out_trade_no']; //必要参数
                $return_data['order_status'] = 0;

               // $this->logResult("log::respond::success_data:",$return_data);

                $returndata['return_code'] = 'SUCCESS';
                //order_paid($order_sn, 2);
            }


        } else {
            $return_data['order_status'] = 5;
            $returndata['return_code'] = 'FAIL';
            $returndata['return_msg'] = '签名失败';
        }

        return $return_data;




    }







    /**

     * 相应服务器应答状态

     * @param $result

     */

    public function response($result) {

       if (FALSE == $result) echo 'ok';

      else echo 'success';

    }



    /**

     * 返回字符过滤

     * @param $parameter

     */

   private function filterParameter($parameter)

   {

      $para = array();

      foreach ($parameter as $key => $value)

      {

         if ('sign' == $key || 'sign_type' == $key || '' == $value || 'm' == $key  || 'a' == $key  || 'c' == $key   || 'code' == $key ) continue;

         else $para[$key] = $value;

      }

      return $para;

   }





   // 设置请求参数

   function setParameter($parameter, $parameterValue) {

      $this->parameters[$this->trimString($parameter)] = $this->trimString($parameterValue);

   }



   // 设置参数时需要用到的字符处理函数

   function trimString($value){

      $ret = null;

      if (null != $value) {

         $ret = $value;

         if (strlen($ret) == 0) {

            $ret = null;

         }

      }

      return $ret;

   }



   //生成随机数

   function create_noncestr( $length = 32 ) {

      $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

      $str ="";

      for ( $i = 0; $i < $length; $i++ )  {

         $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);

      }

      return $str;

   }





   // 获取prepay_id

   function getPrepayId()

   {

      $this->postXml();

      $this->result = $this->xmlToArray($this->response);

      $prepay_id = $this->result["prepay_id"];

      return $prepay_id;

   }





   // post请求xml

   function postXml()

   {

      $xml = $this->createXml();

      $this->response = $this->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder','30');

       //var_dump($this->response);

      return $this->response;

   }





   // 设置标配的请求参数,生成签名,生成接口参数xml

   function createXml()

   {

      $this->parameters["appid"] = $this->payments['weixinpay_appid'];//公众账号ID

      $this->parameters["mch_id"] = $this->payments['weixinpay_mchid'];//商户号

      $this->parameters["nonce_str"] = $this->create_noncestr();//随机字符串

      $this->parameters["sign"] = $this->getSign($this->parameters);//签名

        //print_r($this->parameters);

      return  $this->arrayToXml($this->parameters);

   }



   function xmlToArray($xml)

   {

      //XML转为array

      $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

      return $array_data;

   }



   function arrayToXml($arr)

   {

      $xml = "<xml>";

      foreach ($arr as $key=>$val)

      {

         if (is_numeric($val))

         {

            $xml.="<".$key.">".$val."</".$key.">";



         }

         else

            $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";

      }

      $xml.="</xml>";

      return $xml;

   }

     /**
      * @brief xmlarray转换数据格式
      * @param xml $xmlData
      * @return array
      */
     private function converArray($xmlData)
     {
         $result = array();
         $xmlHandle = xml_parser_create();
         xml_parse_into_struct($xmlHandle, $xmlData, $resultArray);

         foreach($resultArray as $key => $val)
         {
             if($val['tag'] != 'XML')
             {
                 $result[$val['tag']] = $val['value'];
             }
         }
         return array_change_key_case($result);
     }



   function postXmlCurl($xml,$url,$second=30)

   {

      //初始化curl

      $ch = curl_init();

      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

      $data = curl_exec($ch);

      curl_close($ch);

      //var_dump($data);

      if($data)

      {

         //curl_close($ch);

         return $data;

      }

      else

      {

         $error = curl_errno($ch);

         echo "curl出错,错误码:$error"."<br>";

         echo "<a href='http://curl.haxx.se/libcurl/c/libcurl-errors.html'>错误原因查询</a></br>";

         curl_close($ch);

         return false;

      }

   }



   // 作用:生成签名

   public function getSign($Obj)

   {

      foreach ($Obj as $k => $v)

      {

         $Parameters[$k] = $v;

      }

      //签名步骤一:按字典序排序参数

      ksort($Parameters);

      $String = $this->formatBizQueryParaMap($Parameters, false);

      //echo 'string1'.$String.'</br>';

      //签名步骤二:在string后加入KEY

      $String = $String."&key=".$this->payments['weixinpay_key'];

      //echo "string2".$String."</br>";

      //签名步骤三:MD5加密

      $String = md5($String);

      //echo "string3 ".$String."</br>";

      //签名步骤四:所有字符转为大写

      $result_ = strtoupper($String);

      //echo "result ".$result_."</br>";

      return $result_;

   }



   /**

    *     格式化参数,签名过程需要使用

    */

   function formatBizQueryParaMap($paraMap, $urlencode)

   {

      $buff = "";

      ksort($paraMap);

      foreach ($paraMap as $k => $v)

      {

         if($urlencode)

         {

            $v = urlencode($v);

         }

         //$buff .= strtolower($k) . "=" . $v . "&";

         $buff .= $k . "=" . $v . "&";

      }

      $reqPar;

      if (strlen($buff) > 0)

      {

         $reqPar = substr($buff, 0, strlen($buff)-1);

      }

      return $reqPar;

   }



   function setPrepayId($prepayId)

   {

      $this->prepay_id = $prepayId;

   }

   /**

    *     设置jsapi的参数

    */

   function getParameters()

   {

      $jsApiObj["appId"] = $this->payments['weixinpay_appid'];

      $timeStamp = time();

      $jsApiObj["timeStamp"] = "$timeStamp";

      $jsApiObj["nonceStr"] = $this->create_noncestr();

      $jsApiObj["package"] = "prepay_id=$this->prepay_id";

      $jsApiObj["signType"] = $this->payments['weixinpay_signtype'];

      $jsApiObj["paySign"] = $this->getSign($jsApiObj);

        $this->parameters = json_encode($jsApiObj);

      return $this->parameters;

   }



     //增加



     function logResult($word = '',$var=array()) {

         $output= strftime("%Y%m%d %H:%M:%S", time()) . "\n" ;
         $output .= $word."\n" ;
         if(!empty($var)){
             $output .= print_r($var, true)."\n";
         }
         $output.="\n";

         $log_path=PHPCMS_PATH . "/log/";
         if(!is_dir($log_path)){
             @mkdir($log_path, 0777, true);
         }

         file_put_contents($log_path."weixin.txt", $output, FILE_APPEND | LOCK_EX);
     }



}

?>

作者: admin    时间: 2018-12-27 22:14
预先获取openid,    返回路径不能带参数  只能伪静态,     签名 时带上key  .

# 微信支付通知的专用的伪静态

RewriteRule ^pay/respond_Weixinpay.html   index.php?m=pay&c=respond&a=respond&code=Weixinpay

作者: admin    时间: 2018-12-27 22:18
//微信浏览器
   if(isMobile()&&strstr($_SERVER['HTTP_USER_AGENT'],'MicroMessenger')){


       $session_storage = 'session_'.pc_base::load_config('system','session_storage');

       pc_base::load_sys_class($session_storage);

       $weixin_arr = M('pay_payment')->where(array('pay_code'=>'Weixinpay'))->find();
       $weixin_config = json_decode($weixin_arr['config'],true);
       $appid = $weixin_config['weixinpay_appid']['value'];
       $appkey = $weixin_config['weixinpay_appsecret']['value'];


       if(empty($_SESSION['openid'])&&!isset($_GET['code'])){


           if($weixin_config['weixinpay_appid']['value']){

              $backurl = APP_PATH."index.php";

              header("location:http://open.weixin.qq.com/connect/oauth2/authorize?appid=".$appid."&redirect_uri=".$backurl."&response_type=code&scope=snsapi_base&state=qqchongzhi#wechat_redirect");

           }


       }

       if(isset($_GET['code'])&&strlen($_GET['code'])>30){


           $code = $_GET['code'];
           $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$appkey&code=$code&grant_type=authorization_code";

           $content = file_get_contents( $url);

           $resdata = json_decode($content,true);

            $_SESSION['openid'] = $resdata['openid'];



       }

//header('location:'.$siteurl.'index.php?m=wap&siteid='.$siteid);

}




欢迎光临 ѡ̳ (http://www.sunminxuan.cn/bbs/) Powered by Discuz! X3.4