admin

微信公众号支付(原生PHP写法)
/*** * jsapi支付 */ class wxPay { const KEY ...
扫描右侧二维码阅读全文
13
2018/12

微信公众号支付(原生PHP写法)

 
/***
 * jsapi支付
 */
class wxPay
{
    const KEY               = 'KEY';                       //api密钥
    const APPID             = 'APPID';                     //appid
    const SECRET            = 'SECRET';                    //商户密钥
    const MCH_ID            = 'MCH_ID';                    //商户id
    const CODEURL           = 'https://open.weixin.qq.com/connect/oauth2/authorize?';   //微信获取code接口
    const REDIRECT_URI      = 'REDIRECT_URI';             //授权回调地址
    const ACCESS_TOKEN_URL  = 'https://api.weixin.qq.com/sns/oauth2/access_token?';     //获取access_token接口
    const USER_INFO_URL     = 'https://api.weixin.qq.com/sns/userinfo?';                //拉取用户信息接口
    const NOTIFY_URL        = 'NOTIFY_URL';            //支付结果通知地址
    const UNI_URL           = 'https://api.mch.weixin.qq.com/pay/unifiedorder';         //微信统一下单接口
    /*
     *获取用户openid
     微信文档地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
     */
     public function getOpenid()
     {
         $appid             = self::APPID; 
         $secert            = self::SECRET; 
         $redirect_url      = self::REDIRECT_URI;
         $access_token_url  = self::ACCESS_TOKEN_URL;
         $user_info_url     = self::USER_INFO_URL;
         $code_url          = self::CODEURL;
         session_start();
         //如果session中有openid,直接返回openid,否则...
         if(!isset($_SESSION['openid'])){
            if(!isset($_GET['code'])){
            //如果没有code,给用户构建一个跳转地址获得code,最终微信会跳转回redirect_url这个地址(这里是本页面),
            //跳转回来之后,会携带一个code
            $url = $code_url."appid=$appid&redirect_uri=$redirect_url&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
            header('Location:'.$url);
            exit;
             }else{
             //如果存在access_token,直接使用access_token拉取用户信息
             if(!isset($_SESSION['access_token'])){
                $code                     =       $_GET['code'];
                $url                      =       $access_token_url."appid=$appid&secret=$secert&code=$code&grant_type=authorization_code";
                $result                   =       file_get_contents($url);
                $result                   =       json_decode($result,true);
                $_SESSION['access_token'] =       $result['access_token'];
                $_SESSION['openid']       =       $result['openid'];
             }
             //拉取用户信息
                $openid                   =       $_SESSION['openid'];
                $access_token             =       $_SESSION['access_token'];
                $url1                     =       $user_info_url."access_token=$access_token&openid=$openid&lang=zh_CN";
             //result2 为获取到的用户信息,包含openid 微信头像....               
                $result2                  =       file_get_contents($url1);
             }
         }
         return $_SESSION['openid'];
     }
 
 
 
    /*
     *生成签名 
     微信文档签名规则:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3
     */
    public function getSign($arr = [])
    {
        //1.参数的值为空不参与签名,过滤参数为空的key
        $isNotEmptyArr = array_filter($arr);
        //2.按照字典进行排序
        ksort($isNotEmptyArr);
        //3.组成URL键值对,使用urldecode是为了适应isNotEmptyArr中包含了中文串
        $queryStr = urldecode(http_build_query($isNotEmptyArr));
        //4.和KEY拼接
        $stringSignTemp = $queryStr . '&key='.SELF::KEY;
        //对结果进行md5之后,全部转换成大写
        $sign =strtoupper(md5($stringSignTemp));
        //返回签名
        return $sign;
    }
 
    /**
     * 返回一个带签名的数组
     */
    public function setSign($arr)
    {
        $arr['sign'] = $this->getSign($arr);
        return $arr;
    }
    /*
     *验证签名 
     checkSign:需要校验的签名
     mySign:生成的校验签名
     返回:bool
     */
    public function checkSign($checkSign,$arr)
    {
        $mySign = $this->getSign($arr);
        return $mySign == $checkSign;
    }
 
     /**
      * 微信统一下单
      *微信文档地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
      */
     public function unifiedOrder()
     {
         //由api文档可知 以下是必须参数
         $params = [
             'appid'            =>      self::APPID,
             'mch_id'           =>      self::MCH_ID,
             'openid'           =>      $this->getOpenid(),
             'nonce_str'        =>      md5(time()),
             'body'             =>      'test',
             'out_trade_no'     =>      uniqid(),
             'total_fee'        =>      '1',
             'spbill_create_ip' =>      $_SERVER['REMOTE_ADDR'],
             'notify_url'       =>      self::NOTIFY_URL,
             'trade_type'       =>      'JSAPI'
         ];
         //生成带签名的数组
         $params                =       $this->setSign($params);
         //微信统一下单api需要的参数是一个xml,先把数组转换成xml
         $xml                   =       $this->ArrToXml($params);
         //调用统一下单api,给微信发送以上xml,微信的返回结果也是一个xml
         $result                =       $this->postXml(self::UNI_URL,$xml);
         //为了方便看,把微信返回的订单xml转换成数组
         $orderData             =       $this->XmlToArr($result);
         //返回订单结果
         return $orderData;
     }
 
     /***
      * 给指定的url地址发送xml数据的方法
      */
     public function postXml($url,$postfields)
     {
        $ch                             = curl_init();
        $params[CURLOPT_URL]            = $url;             //请求url地址
        $params[CURLOPT_HEADER]         = false;            //是否返回响应头信息
        $params[CURLOPT_RETURNTRANSFER] = true;             //是否将结果返回
        $params[CURLOPT_FOLLOWLOCATION] = true;             //是否重定向
        $params[CURLOPT_POST]           = true;             //请求方式
        $params[CURLOPT_POSTFIELDS]     = $postfields;
        $params[CURLOPT_SSL_VERIFYPEER] = false;            //是否跳过安全证书
        $params[CURLOPT_SSL_VERIFYHOST] = false;
        curl_setopt_array($ch, $params);                    //传入curl参数
        $content                        = curl_exec($ch);   //执行
        curl_close($ch);                                    //关闭连接
        return $content;
     }
 
     /*
     xml转换成数组
     */
     public function XmlToArr($xml)
     {
         if($xml == '') return '';
         libxml_disable_entity_loader(true);
         $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
         return $arr;
     }
 
     /**
      * 数组转换成xml
      */
    public function ArrToXml($arr)
    {
        if(!is_array($arr) || count($arr) == 0) 
        return '';
    $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; 
    }
 
     /*
      *获取微信的prepayid
      */
     public function getPrePayId()
     {
         $orderData = $this->unifiedOrder();
         return $orderData['prepay_id'];
     }
 
     /**
      * 获取到微信支付的getPrePayId参数后,构建支付所需要的json参数
      */
     public function getJsParams()
     {
         $params = [
             'appId'        =>      self::APPID,
             'timeStamp'    =>      time(),
             'nonceStr'     =>      md5(time()),
             'package'      =>      "prepay_id=".$this->getPrePayId(),
             'signType'     =>      'MD5',
         ];
         //注意 微信支付的签名参数是paySign 而不是sign
         $params['paySign'] = $this->setSign($params)['sign'];
         //返回前端支付的基本参数(json)
         return json_encode($params);
     }
}
    $pay    = new wxPay();
    $json   = $pay->getJsParams();
?>
<!-- 前端拿到$json 通过jssdk发起微信支付 -->
<script>
function onBridgeReady(){
   WeixinJSBridge.invoke(
      'getBrandWCPayRequest', 
      <?php echo $json;?>,
      function(res){
      if(res.err_msg == "get_brand_wcpay_request:ok" ){
      // 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      } 
   }); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}
最后修改:2019 年 05 月 10 日 01 : 56 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论