php微信支付,退款,企业转账类

微信支付,退款,企业转账类–参数配置可直接使用

封装的比较垃圾,各位大师请勿吐槽
<?php

/**
* 微信支付
*/
class WxPay
{
    protected $values = [];//参数集合
    const APPID = '';   //绑定支付的APPID
    const MCHID = '';           //商户号
    const KEY = ''; //商户支付密钥
    const APPSECRET = '';   //公众帐号secert(仅JSAPI支付的时候需要配置
    #证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要,可登录商户平台下载
    #API证书下载地址:https://pay.weixin.qq.com/index.php/account/api_cert,下载之前需要安装商户操作证书)
    const SSLCERT_PATH = ROOT_PATH.'/cert/apiclient_cert.pem';
    const SSLKEY_PATH = ROOT_PATH.'/cert/apiclient_key.pem';

    function __construct()
    {
        $this->values = [];
    }

    #微信支付
    public function wxPay($orderId='')
    {
        if (null == $orderId || empty($orderId)) {
            exit("<script> alert('该订单不存在!');history.back(); </script>");
        }
        #微信支付,更新订单编号
        do {
            $order_sn = order_sn();
        } while ( Db::table('orders')->where('pay_order_num',$order_sn)->value('id') );

        Db::table('orders')->where('id',$orderId)->update(['pay_order_num'=>$order_sn]);

        $orderInfo = Db::table('orders')->where('id',$orderId)->field('id,pay_order_num,real_price,uid')->find();

        $openid = Db::table('users')->where('id',$orderInfo['uid'])->value('openid');
        $setAttr = [
            'body' =>'微信季利亚',
            'openid' =>$openid,
            'appid' =>self::APPID,
            'out_trade_no' =>$orderInfo['pay_order_num'],
            'total_fee' => $orderInfo['real_price'] * 100,
            'notify_url' =>WEB_URL.'/home/notify/wechatNotify',
            'mch_id' => self::MCHID,
            'spbill_create_ip' => self::clientIp(),
            'nonce_str' => self::getNonceStr(),
            'trade_type' =>'JSAPI'
        ];
        $this->values = $setAttr;   //配置赋给values属性
        $sign = $this->MakeSign();  //获取签名
        $this->values['sign'] = $sign;  
        $xmlstr = $this->ToXml(); //生成微信请求xml数据格式
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";   //请求url参数
        $dataxml =self::postXmlCurl($xml,$url);//传参调用curl请求
        $objectxml = $this->xmlToArray($dataxml);
        $prepay_id = '';
        if(isset($objectxml["prepay_id"])){
            $prepay_id = $objectxml["prepay_id"];
        }
        $timeStamp = time();
        $data = [
            'appId' =>self::APPID,
            'timeStamp' => "$timeStamp",
            'nonceStr' =>self::getNonceStr(),
            'package' => "prepay_id=$prepay_id",
            'signType' => "MD5"
        ];
        $this->values = $data;
        $data['paySign'] = $this->MakeSign();
        $this->assign('jsApiParameters',json_encode($data));
        return view('wechat/wxchatpay');
    }

    /**微信退款
    *@param $out_trade_no 订单号
    */
    public  function refund($out_trade_no='')
    {

        if(!$out_trade_no){    
            throw new \Exception("订单号出错", 1);
        }

        $order = db('orders')->where('pay_order_num',$out_trade_no)->where('status',7)->find();
        if (empty($order)) {
            throw new \Exception("订单不存在", 1);
        }
        $config = [
            'out_trade_no'=> $out_trade_no,
            'refund_fee'   =>(int)$order['return_price'] * 100,
            'total_fee'    =>(int)$order['real_price']*100,
            'out_refund_no'=>self::MCHID.date("YmdHis"),
            'appid'        =>self::APPID,
            'mch_id'       =>self::MCHID,
            'nonce_str'    =>self::getNonceStr()
        ];
        $this->values = $config;
        $sign = $this->MakeSign();     //生成sign签名
        $this->values['sign'] = $sign; 
        $xmlstr = $this->ToXml();    //生成微信请求xml数据格式
        $url = "https://api.mch.weixin.qq.com/secapi/pay/refund";  //退款url
        $dataxml = self::postXmlCurl($xmlstr,$url,true);//传参调用curl请求
        $objectxml = $this->xmlToArray($dataxml);
        if($objectxml['return_code'] =='SUCCESS' && $objectxml['result_code'] =='SUCCESS'){
            return 1;
        }else{
            throw new \Exception($objectxml['return_msg'], 1);
        }       
    }


    //微信提现
    public function Withdrawals($orderCode,$openid,$money){ 

        if(!$orderCode || !$openid || $money<1){     
            return 0;
        }   
        $config = [
            'amount'=> $amount,
            'check_name'   =>'NO_CHECK',
            'desc'    =>'季利亚金币提现',
            'mch_appid'=>self::APPID,
            'mchid'        =>self::MCHID,
            'nonce_str'    =>self::getNonceStr(),
            'openid'       =>$openid,
            'partner_trade_no'=>$orderCode,
            'spbill_create_ip'=>self::clientIp
        ];
        $this->values = $config;
        $sign = $this->MakeSign();     //生成sign签名
        $this->values['sign'] = $sign; 
        $xmlstr = $this->ToXml();    //生成微信请求xml数据格式
        //接口地址
        $url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
        $dataxml = self::postXmlCurl($xmlstr,$url,true);//传参调用curl请求

        $objectxml = $this->xmlToArray($dataxml);//将微信返回的XML 转换成数组

        if($objectxml['return_code'] =='SUCCESS' && $objectxml['result_code'] =='SUCCESS'){
            return 1;
        }else{
            throw new \Exception($objectxml['return_msg'], 1);
        }
    } 


    /**
     *  作用:将xml转为array
     */
    public function xmlToArray($xml)
    {
        //将XML转为array
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }


    /**
     * 
     * 产生随机字符串,不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public static function getNonceStr($length = 32) 
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";  
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {  
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);  
        } 
        return $str;
    }

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

    /**
     * 格式化参数格式化成url参数
     */
    public function ToUrlParams()
    {
        $buff = "";
        foreach ($this->values as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * 输出xml字符
    **/
    public function ToXml()
    {
        if(!is_array($this->values) 
            || count($this->values) <= 0)
        {
            throw new Exception('数组异常', 1);
        }

        $xml = "<xml>";
        foreach ($this->values as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml; 
    }

    #获取客户端ip
    private static function clientIp()
    {
        $ip = '';
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }else{
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        $ip_arr = explode(',', $ip);
        return $ip_arr[0];
    }


    /**
     * 以post方式提交xml到对应的接口url
     * 
     * @param string $xml  需要post的xml数据
     * @param string $url  url
     * @param bool $useCert 是否需要证书,默认不需要
     * @param int $second   url执行超时时间,默认30s
     * @throws WxPayException
     */
    private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)
    {
        // halt($url);     
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        if($useCert == true){
            //设置证书
            //使用证书:cert 与 key 分别属于两个.pem文件
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT,self::SSLCERT_PATH);
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY,self::SSLKEY_PATH);
        }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        } else { 
            $error = curl_errno($ch);
            curl_close($ch);
            throw new \Exception("curl出错,错误码:$error");
        }
    }
}
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值