wonderwong 2018-12-07 11:12:48 6539次浏览 0条评论 3 0 0
<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018-12-04
 * Time: 11:07 AM
 * Author: 王称意
 * QQ/Email: 984008813/wondely@126.com
 */
namespace app\service;
class WechatPay {

    public $key = '********************';

    public function createSign($params)
    {
       $sign =  $this->MakeSign($params);

       return $sign;
    }

    public function unifiedorder($params)
    {
        $xml = $this->ToXml($params);

        return $xml;
    }

    public function ToXml($params)
    {
        $xml = "<xml>";
        foreach ($params as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    public function XmlToArray($xml)
    {
        if(!$xml){
            return "xml数据异常!";
        }
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $data;
    }

    public function ToUrlParams($params)
    {
        $buff = "";
        foreach ($params as $k => $v)
        {
            if($k != "sign" && $v !="" && !is_array($v)){
                $buff .=$k."=".$v."&";
            }
        }

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

    public function MakeSign($params, $sign_type = 'MD5')
    {
        //签名步骤一:按字典序排序参数
        ksort($params);
        $string = $this->ToUrlParams($params);
        //签名步骤二:在string后加入KEY
        $string = $string."&key=".$this->key;
        //签名步骤三:MD5加密或者HMAC-SHA256
        if($sign_type == "MD5"){
            $string = md5($string);
        } else if($sign_type == "HMAC-SHA256") {
            $string = hash_hmac("sha256",$string ,$this->key);
        }
        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    public function getNonceStr($length = 31)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    public function postXmlCurl($xml, $url, $useCert = false, $second = 30)
    {
        $ch = curl_init();
        $curlVersion = curl_version();
        $ua = "WXPaySDK/3.0.9 (".PHP_OS.") PHP/".PHP_VERSION." CURL/".$curlVersion['version']."1518495571";

        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);

        $proxyHost = "0.0.0.0";
        $proxyPort = 0;
        //$config->GetProxy($proxyHost, $proxyPort);
        //如果有配置代理这里就设置代理
        if($proxyHost != "0.0.0.0" && $proxyPort != 0){
            curl_setopt($ch,CURLOPT_PROXY, $proxyHost);
            curl_setopt($ch,CURLOPT_PROXYPORT, $proxyPort);
        }
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
        curl_setopt($ch,CURLOPT_USERAGENT, $ua);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        if($useCert == true){
            //设置证书
            //使用证书:cert 与 key 分别属于两个.pem文件
            //证书文件请放入服务器的非web目录下
            $sslCertPath = "";
            $sslKeyPath = "";
            //$config->GetSSLCertPath($sslCertPath, $sslKeyPath);
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, $sslKeyPath);
        }
        //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");
            return "curl出错,错误码:$error";
        }
    }
}
?>
在根目录下面 建一个 service目录 复制上面的内容到一个文件。

<?php
class PayController extends AppController {

    public function actionIndex()
    {
        $good_id = \Yii::$app->request->post('good_id');
        $pay_type = \Yii::$app->request->post('pay_type');

        if(empty($good_id)){
            $this->msg['msg'] = '购买的商品不能为空';
            return $this->asJson($this->msg);
        }

        if(empty($pay_type)){
            $this->msg['msg'] = '请选择支付方式';
            return $this->asJson($this->msg);
        }

        $good_info = Goods::findOne($good_id);

        $user_info = $this->getUserInfo();

        $date_time = date('YmdHis');
        $order_id = 'wechat'.$good_id.$date_time;
        $orderModel = new BookOrder();
        $orderModel->order_id = $order_id;
        $orderModel->user_id = $user_info['id'];
        $orderModel->user_name = $user_info['username'];
        $orderModel->good_id = $good_id;
        $orderModel->agent_id = $user_info['source_id'];
        $orderModel->order_money = $good_info['goods_money'];
        $orderModel->pay_type = $pay_type;
        $orderModel->order_status = 0;
        $orderModel->create_time = time();
        $orderModel->save();

        //todo wechatSDk 微信支付的sdk
        if($pay_type == 2){
            $param = [
                'appid' =>'*******',
                'mch_id'=> '*******',
                'body'=> '嘻嘻嘻嘻嘻-充值中心',
                'out_trade_no'=> $order_id,
                'total_fee'=> 1, //$good_info['goods_money']*100,
                'spbill_create_ip'=> $_SERVER['REMOTE_ADDR'],
                'notify_url'=>'http://xxxxx.com/callback/wechat',
                'trade_type'=>'MWEB',
                'scene_info'=>'{"h5_info":{"type":"Wap","wap_url":"http://xxxxx.com","wap_name":"嘻嘻嘻嘻嘻"}}',
            ];

            $wechatPay = new WechatPay();
            $param['nonce_str'] = $wechatPay->getNonceStr();
            $param['sign'] = $wechatPay->createSign($param);
            $xml = $wechatPay->unifiedorder($param); //统一下单

            $data = $wechatPay->postXmlCurl($xml,'https://api.mch.weixin.qq.com/pay/unifiedorder');
            $data = $wechatPay->XmlToArray($data);
            //var_dump($data);
            if($data['return_code'] == 'SUCCESS' && $data['result_code'] == 'SUCCESS'){
                $this->msg['msg'] = '订单下单成功';
                $this->msg['order_id'] = $order_id;
                $this->msg['data'] = $data;
            }else{
                $this->msg['msg'] = $data['return_msg'];
            }
            return $this->asJson($this->msg);
        }

    }
}
?>
下单页面,调起微信支付。


<?php
class CallbackController extends Controller{

    public $enableCsrfValidation = false;

    public function actionWechat(){
        $msg = [
            'success' => "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>",
            'fail' =>"<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>"
        ];
        $xml =  file_get_contents('php://input');
        if(empty($xml)){
            Yii::info('回调异常','paylog');
            echo $msg['fail'];exit;
        }
        //Yii::info($xml,'paylog');
        $wechatPay = new WechatPay();
        $call_back = $wechatPay->XmlToArray($xml);
        //var_dump($call_back);

        if(empty($call_back)){
            Yii::info('数据非法请求','paylog');
            echo $msg['fail'];exit;
        }

        if($call_back['result_code'] == 'SUCCESS' && $call_back['return_code'] == 'SUCCESS'){

            $sign = $wechatPay->createSign($call_back);
            if($sign !== $call_back['sign']){
                //todo 返回信息签名异常的处理
                Yii::info('该订单签名异常'.$call_back['out_trade_no'],'paylog');
                echo $msg['fail'];
                exit;
            }

            $order_id = $call_back['out_trade_no'];
            $time = time();
            $order_info = BookOrder::find()->where(['order_id'=>$order_id])->one();
            $good_info = Goods::findOne($order_info['good_id']);

            if($order_info){
                if($order_info['order_status'] == 1){
                    Yii::info('该订单已支付,请勿重复支付'.$order_id,'paylog');
                    echo $msg['success'];
                    exit;
                }

                $ts = Yii::$app->db->beginTransaction();
                if($good_info['goods_type'] ==1){
                    $condition = ['user_id' =>$order_info['user_id']];
                    $userVip = UserVip::find()->where($condition)->one();
                    $end_time = 3600*24*30*$good_info['goods_num'];

                    if($userVip){
                        if($userVip['end_time'] > $time){
                            $plus_time = $userVip['end_time']+$end_time;
                        }else{
                            $plus_time = $time+$end_time;
                        }
                        $userVip->end_time = $plus_time;
                        $userUpdate = $userVip->save();
                    }else{
                        $userVip = new UserVip();
                        $userVip->user_id = $order_info['user_id'];
                        $userVip->begin_time = $time;
                        $userVip->end_time = $time+$end_time;
                        $userUpdate = $userVip->save();
                    }

                    $consumeCoin = new CoinConsume();
                    $consumeCoin->user_id = $order_info['user_id'];
                    $consumeCoin->consume_type = 3;
                    $consumeCoin->consume_msg = 'xxxxxxx';
                    $consumeCoin->consume_time = $time;
                    $consumeCoinUpdate = $consumeCoin->save();

                }else{
                    $userInfo = User::findOne($order_info['user_id']);

                    $consumeCoin = new CoinConsume();
                    $consumeCoin->user_id = $order_info['user_id'];
                    $consumeCoin->consume_type = 2;
                    $consumeCoin->coin_before = $userInfo['coin'];
                    $consumeCoin->consume_coin = $good_info['goods_num'];
                    $consumeCoin->coin_after = $userInfo['coin']+$good_info['goods_num'];
                    $consumeCoin->consume_msg = 'xxxxxxxx';
                    $consumeCoin->consume_time = $time;
                    $consumeCoinUpdate = $consumeCoin->save();

                    $userInfo->coin = $userInfo['coin']+$good_info['goods_num'];
                    $userUpdate = $userInfo->save();
                }

                $order_info->order_status = 1;
                $order_info->update_time = $time;
                $orderPayUpdate = $order_info->save();

                if($userUpdate && $consumeCoinUpdate && $orderPayUpdate){
                    $ts->commit();
                    Yii::info('该订单已支付成功,本地业务处理成功'.$order_id,'paylog');
                    echo $msg['success'];
                    exit;
                }else{
                    $ts->rollBack();
                    Yii::info('该订单已支付成功,本地业务操作失败,请在后台补单'.$order_id,'paylog');
                    echo $msg['fail'];
                    exit;
                }
            }else{
                Yii::info('该订单不存在,微信已经支付成功'.$order_id,'paylog');
                echo $msg['fail'];
                exit;
            }
        }
        echo $msg['fail'];
        exit;
    }

    public function actionAli(){

    }
}
    没有找到数据。
您需要登录后才可以评论。登录 | 立即注册