zoukankan      html  css  js  c++  java
  • 小程序支付

    <?php
    
    /**
     * Created by PhpStorm.
     * User: zb
     * Date: 17-10-9
     * Time: 下午7:15
     */
    class PaysAction extends CommonAction
    {
        public function _initialize(){
            parent::_initialize();
        }
    
        public function pay(){
            $openid = trim($_POST['openid']);
            $total_price = (float)$_POST['total_price'] * 100;//~~~~
            $coupon_id = (int)$_POST['coupon_id'];
            $coupon_price = (float)$_POST['coupon_price'] * 100;
            $order_remark = trim($_POST['order_remark']);
            $old_order_num = trim($_POST['order_num']);//有order_num,再来一单购买
            if ($old_order_num == 'undefined'){
                $old_order_num = '';
            }
            $product_id = (int)$_POST['product_id'];//有product_id,立即购买~~~~NaN,undefined在int转化后都为0;
    
    
            if (!$openid){
                $this->json->setErr(10000,'缺少参数');
                $this->json->Send();
            }
            $user = M('user');
            $tel_flag = $user->where(array('openid'=>$openid))->find();
            if (!$tel_flag || !$tel_flag['id']){
                $this->json->setErr(10001,'未绑定手机号');
                $this->json->Send();
            }
            $uid = $tel_flag['id'];
            if ($total_price <= 0){
                $this->json->setErr(10002,'支付金额不可为0或负数');
                $this->json->Send();
            }
            $order_info = $this->makeorder($old_order_num,$product_id,$openid,$uid,$total_price,$coupon_id,$coupon_price,$order_remark);
            $order_num = $order_info['order_num'];
            $products_name = $order_info['products_name'];
    
    
            $unifiedorder = $this->unifiedorder($openid,$order_num,$total_price,$products_name);
            $data = [
                'appId'     => C('APPID'),
                'timeStamp' => time(),
                'nonceStr'  => $this->createNonceStr(),
                'package'   => 'prepay_id='.$unifiedorder['prepay_id'],
                'signType'  => 'MD5'
            ];
    
            $sign = $this->MakeSign($data);
            $data['sign'] = $sign;
            $this->json->setAttr('data',$data);
            $this->json->Send();
        }
    
    
        /***    生成订单    优惠券处理
         * @param $openid
         * @param $uid
         * @param $total_price
         * @param $coupon_id user_coupon中的id字段,而非coupon_id字段
         * @param $coupon_price 用户实际获取优惠额度,而非一定是表格中的price字段;
         * @param $order_remark 用户提交订单的备注信息;
         * @param $old_order_num 如有此参数,再来一单购买
         * @param $product_id 立即购买方式
         * @param order表格中的status字段     1未支付;2已支付;3已申请退款;4已退款;5已完成
         * @return string
         */
        private function makeorder($old_order_num='',$product_id=0,$openid,$uid,$total_price,$coupon_id,$coupon_price,$order_remark){
            $order = M('order');
            $now = time();
            if ($old_order_num && !$product_id){
                $order_num = 'os'.$uid.substr($now,3).rand(1000,9999);  //生成12位以上订单号~~~~如果开头有os,表示从order_shoppingcar转变而来
                $shoppingcar = M('order_shoppingcar');//~~~~
            }elseif($product_id && !$old_order_num){
                $order_num = 'qs'.$uid.substr($now,3).rand(1000,9999);  //生成12位以上订单号~~~~如果开头有qs,表示从quickbuy_shoppingcar转变而来
                $shoppingcar = M('quickbuy_shoppingcar');//~~~~
            }else{
                $order_num = $uid.substr($now,3).rand(1000,9999);       //生成12位以上订单号
                $shoppingcar = M('shoppingcar');//~~~~
            }
    
            $order_add_data = [
                'order_num'     =>  $order_num,
                'uid'           =>  $uid,
                'coupon_id'     =>  $coupon_id,
                'coupon_price'  =>  $coupon_price,
                'total_price'   =>  $total_price,//订单价格
                'status'        =>  1,
                'addtime'       =>  $now,//订单生成时间
                'remark'        =>  $order_remark
            ];
            $order_add_flag = $order->add($order_add_data);
    //        $sql = $order->getLastSql();
    //        $this->json->setAttr('sql',$sql);
    //        $this->json->Send();
    
    
            if (!$order_add_flag){
                $this->json->setErr(10003,'生成订单失败');
                $this->json->Send();
            }
            $return_data['order_num'] = $order_num;
            $map = array(
                'openid'    =>  $openid,
                'pnum'      =>  array('gt',0)
            );
    
            $shoppingcar_flag = $shoppingcar->where($map)->field('pid,pnum')->order('updatetime desc')->select();
            $shoppingcar_count = count($shoppingcar_flag);
            $product = M('product');
            $order_product = M('order_product');
            $products_name = '';
            for ($i=0;$i<$shoppingcar_count;$i++){
                $product_flag = $product->where(array('id'=>$shoppingcar_flag[$i]['pid']))->find();
                //如果该产品已下架或删除,购物车数据中该产品要剔除
                if ($product_flag['status'] == '0' || ($product_flag['is_del'] == '1')){
                    unset($shoppingcar_flag[$i]);
                    continue;
                }
                if (!$products_name){
                    $products_name .= $product_flag['title'];
                }else{
                    $products_name .= '-'.$product_flag['title'];
                }
                $product_add_data = [
                    'order_id'  =>  $order_add_flag,
                    'uid'       =>  $uid,
                    'pid'       =>  $shoppingcar_flag[$i]['pid'],
                    'pnum'      =>  $shoppingcar_flag[$i]['pnum'],
                    'p_name'    =>  $product_flag['title'],
                    'p_price'   =>  $product_flag['price'],
                    'addtime'   =>  $now
                ];
                $product_add_flag = $order_product->add($product_add_data);
                if (!$product_add_flag){
                    $this->json->setErr(10004,'订单产品数据添加失败');
                    $this->json->Send();
                }
            }
            $return_data['products_name'] = $products_name;
            return $return_data;
        }
    
        private function createNonceStr($length = 16) {
            $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
            $str ="";
            for ( $i = 0; $i < $length; $i++ )  {
                $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
            }
            return $str;
        }
    
        public function unifiedorder($openid,$order_num,$total_fee,$products_name){
            $trade_no = $order_num;
            $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
            $data = [
                'appid'             => C('APPID'),
                'mch_id'            => C('MCHID'),
                'nonce_str'         => $this->createNonceStr(),
                'sign_type'         => 'MD5',
                'body'              =>  $products_name,  //商品名称组合
                'attach'            => '****-附加数据',
                //'detail'            => '*****线上销售',
                'out_trade_no'      => $trade_no,               //订单号
                'fee_type'          => 'CNY',
                'total_fee'         => $total_fee,       //$total_fee,   for test~~~
                'spbill_create_ip'  => $_SERVER['REMOTE_ADDR'],
    //            'time_start'        => $this->getMillisecond(),
                'goods_tag'         => '******-商品标记',
                'notify_url'        => 'https://**************/api.php/Pays/order_notice',
                'trade_type'        => 'JSAPI',
                'openid'            => $openid
            ];
           $sign = $this->MakeSign($data);
           $data['sign'] = $sign;
    
           $xml = $this->ToXml($data);
    
           vendor('Func.Http');
           $result = $this->FromXml(Http::postXmlCurl($url,$xml));
            return $result;
        }
    
    
        public function FromXml($xml)
        {
            if(!$xml){
                throw new WxPayException("xml数据异常!");
            }
            //将XML转为array
            //禁止引用外部xml实体
            libxml_disable_entity_loader(true);
            $this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            return $this->values;
        }
    
        private  function getMillisecond()
        {
            //获取毫秒的时间戳
            $time = explode ( " ", microtime () );
            $time = $time[1] . ($time[0] * 1000);
            $time2 = explode( ".", $time );
            $time = $time2[0];
            return $time;
        }
    
        public function getSign(){
            $appid = C('APPID');
            $nocestr = $this->createNonceStr();
            $timeStamp = time();
    
    
        }
    
        public function ToXml($array)
        {
    
            if(!is_array($array)
                || count($array) <= 0)
            {
               return ;
            }
    
            $xml = '<xml version="1.0">';
            foreach ($array as $key=>$val)
            {
    
                if (is_numeric($val)){
                  $xml.="<".$key.">".$val."</".$key.">";
                }else{
                    $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
                }
            }
            $xml.="</xml>";
            return $xml;
        }
    
        private function MakeSign($data)
        {
            //签名步骤一:按字典序排序参数
            ksort($data);
    
            $string = $this->ToUrlParams($data);
            //签名步骤二:在string后加入KEY
            $string = $string . "&key=".C('WEIXIN_PAY_KEY');
    
            //签名步骤三:MD5加密
            $string = md5($string);
            //签名步骤四:所有字符转为大写
            $result = strtoupper($string);
    
            return $result;
    
        }
    
        private function ToUrlParams($array)
        {
            $buff = "";
            foreach ($array as $k => $v)
            {
                if($k != "sign" && $v != "" && !is_array($v)){
                    $buff .= $k . "=" . $v . "&";
                }
            }
    
            $buff = trim($buff, "&");
            return $buff;
        }
    
        //微信支付回调
        public function order_notice(){
            $xml = $GLOBALS['HTTP_RAW_POST_DATA'];
    
    // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了~~for test
    //        vendor('Func.Func');
    //        $hostname = 'http://'.Func::getHostName();
    //        $path = $hostname.'/static/log2.txt';
    //        file_put_contents($path,$xml);
    
            //将服务器返回的XML数据转化为数组
            //$data = self::xml2array($xml);
            $data = $this->FromXml($xml);
    
            // 保存微信服务器返回的签名sign
            $data_sign = $data['sign'];
            // sign不参与签名算法
            unset($data['sign']);
            //$sign = self::makeSign($data);
            $sign = $this->makeSign($data);
    
            // 判断签名是否正确  判断支付状态
            if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) {
                $result = $data;
                //获取服务器返回的数据
                $order_num = $data['out_trade_no'];         //订单单号
                $openid = $data['openid'];                  //付款人openID
                $total_fee = $data['total_fee'];            //付款金额
                $transaction_id = $data['transaction_id'];  //微信支付流水号
    
                $user = M('user');
                $user_flag = $user->where(array('openid'=>$openid))->field('id')->find();
                $uid = $user_flag['id'];
    
                $save_data = array(
                    'total_payed_price' =>  $total_fee,     //实际到帐金额
                    'transaction_id'    =>  $transaction_id,
                    'paytime'           =>  time(),
                    'status'            =>  2       //1未支付;2已支付;3已申请退款;4已退款;5已完成
                );
    
                $order = M('order');
                $order_save_flag = $order->where(array('order_num'=>$order_num,'uid'=>$uid))->save($save_data);
    
    
                //优惠券信息处理~~~~~发起订单还未必就支付~~~~~支付成功才处理
                $order_coupon_flag = $order->where(array('order_num'=>$order_num,'uid'=>$uid))->field('coupon_id,id')->find();
                $coupon_id = $order_coupon_flag['coupon_id'];
                if ($coupon_id){
                    $user_coupon = M('user_coupon');
                    $coupon_save_data = array(
                        'is_use'       =>  1,
                        'oid'          =>  $order_coupon_flag['id'],        //~~~~order订单的id
                        'update_time'  =>  time()
                    );
    
                    $user_coupon_save_flag = $user_coupon->where(array('id'=>$coupon_id))->save($coupon_save_data);
                    $user_coupon_find_flag = $user_coupon->where(array('id'=>$coupon_id))->field('coupon_id')->find();
                    if ($user_coupon_save_flag){
                        $coupon = M('coupon');
                        $coupon->where(array('id'=>$user_coupon_find_flag['coupon_id']))->setInc('used_number','+1');
                    }
                }
                //购物车信息清理
                // 1.订单号数字开头,立即购买方式,清空shoppingcar;
                // 2.订单号开头有sn,再来一单购买方式,清空order_shoppingcar(进入我的订单会清理),一定不要清理了shoppingcar
                // 2.订单号开头有qn,立即购买方式,清空quickbuy_shoppingcar(立即购买触发时间前会清理),一定不要清理了shoppingcar
                if (preg_match('/^(os)/',$order_num)){
                    $shoppingcar = M('order_shoppingcar');
                }elseif(preg_match('/^(qs)/',$order_num)){
                    $shoppingcar = M('quickbuy_shoppingcar');
                }else{
                    $shoppingcar = M('shoppingcar');
                }
                $clear_data['pnum'] = 0;
                $shoppingcar->where(array('openid'=>$openid))->save($clear_data);
            }else{
                $result = false;
            }
            // 返回状态给微信服务器
            if ($result) {
                $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
            }else{
                $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
            }
            echo $str;
            return $result;
        }
    
    
    }




    go_to_pay: function (e) {
    var that = this;
    var coupon_id = parseInt(e.currentTarget.dataset.coupon_id);//user_coupon的id
    var coupon_price = e.currentTarget.dataset.coupon_price;//实际优惠价格
    var total_price = e.currentTarget.dataset.total_price;
    var products_name = e.currentTarget.dataset.products_name;
    var order_num = e.currentTarget.dataset.order_num;//可以'',undefined
    var product_id = parseInt(e.currentTarget.dataset.product_id);//undefined转化int->NaN
    var input_order_remark = that.data.input_order_remark;

    wx.request({
    url: 'https://**************.net/api.php/Pays/pay',
    header: { 'content-type': 'application/x-www-form-urlencoded' },
    data: {
    openid: app.globalData.open_id,
    total_price: total_price,
    order_num: order_num,
    product_id: product_id,
    coupon_id: coupon_id,
    coupon_price: coupon_price,
    order_remark: input_order_remark,
    },
    method: 'POST', //注意header
    success: function (res) {
    if (res.errno) {
    wx.showToast(res.errdesc);
    return;
    }
    var datas = res.data;
    //console.log(typeof datas.data.timeStamp);
    wx.requestPayment({
    'timeStamp': datas.data.timeStamp.toString(),
    'nonceStr': datas.data.nonceStr,
    'package': datas.data.package,
    'signType': 'MD5',
    'paySign': datas.data.sign,
    'success': function (res) {
    console.log('支付成功');
    console.log(res);
    //return;
    },
    'fail': function (res) {
    console.log('支付失败');
    //console.log(res);
    return;
    },
    'complete': function (res) {
    console.log('支付完成');
    console.log(res);
    if (res.errMsg == 'requestPayment:ok') {
    wx.navigateTo({
    url: '/pages/pay/pay_success?products_name=' + products_name
    })
    }
    return;
    }
    });
    // console.log(res.data);
    }
    })
    },

      

  • 相关阅读:
    Diango基础学习
    Python02-作业(购物车)
    使用spring boot + Thymeleaf实现web小页面
    Python-01作业(登录和三级菜单)
    Java反射机制
    Socket编程
    利用java的url实现小型的网页爬虫
    关于在spring boot里使用Thymeleaf模板的application.properties配置
    Spring
    Spring-bean的自动装配
  • 原文地址:https://www.cnblogs.com/pansidong/p/8305642.html
Copyright © 2011-2022 走看看