微信公众号支付

class

<?php
namespace app\api\controller;

/***
 * jsapi支付
 */
class WxPay
{
    const KEY               = 'fc209d';                       //api密钥
    const APPID             = 'wxa2c';                     //appid
    const SECRET            = 'fc2093d';                    //商户密钥
    const MCH_ID            = '16040';                    //商户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';         //微信统一下单接口
    
    protected $openid = '';
    protected $notify_url = '';
    protected $out_trade_no = '';
    protected $total_fee = '';
    
    public function __construct( $openid , $notify_url , $out_trade_no , $total_fee ) {
        $this->openid = $openid;
        $this->notify_url = $notify_url;
        $this->out_trade_no = $out_trade_no;
        $this->total_fee = $total_fee;
    }
    
    /*
     *获取用户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(),
             'openid'           =>      $this->openid,
             'nonce_str'        =>      md5(time()),
             'body'             =>      'test',
//             'out_trade_no'     =>      uniqid(),
             'out_trade_no'     =>      $this->out_trade_no,
             'total_fee'        =>      $this->total_fee,
             'spbill_create_ip' =>      $_SERVER['REMOTE_ADDR'],
//             'notify_url'       =>      self::NOTIFY_URL,
             'notify_url'       =>      $this->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);
         
//         echo "<pre>";var_dump(  $orderData  );die;
         //返回订单结果
         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( $openid , $notify_url , $out_trade_no , $total_fee );
//    $json   = $pay->getJsParams();
    

 

调用

$pay_info = new WxPay( $pb_openid , $return_url , $order_info['order_sn'] , $order_info['pay_money'] * 100 );
            $pay_json = $pay_info->getJsParams();
            $pay_json_arr = json_decode($pay_json ,true );
            $this->success( "ok" , $pay_json_arr );

回调验签

public function wx_hall_notify() {
        
        $testxml  = file_get_contents("php://input");
//        file_put_contents('pay_wx_xml.txt', $testxml);
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
//        file_put_contents('pay_wx.txt', $jsonxml);
        $result = json_decode($jsonxml, true);  //转成数组
        if($result){
            $res_verify = $this->verifySign( $result );
            if( $res_verify != $result['sign'] ){
                echo "fial";die;
            }
            //如果成功返回了
            $this->charge_logic( $result );
//            $out_trade_no = $result['out_trade_no'];
//            if($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS'){
//                //
//            }
        }
//        echo "<pre>";var_dump(  $res  );die;
    }
    
    public function verifySign($params, $apikey="fc4d") {
        ksort($params);
        $string = "";
        foreach ($params as $k => $v) {

            if ($k != "sign" && $v != "" && !is_array($v)) {
                $string .= $k . "=" . $v . "&";
            }
        }
        $string = $string . "key=" . $apikey;
        $string = md5($string);
        $result = strtoupper($string);
        return $result;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值