zz 5 lat temu
rodzic
commit
aa16b1d850

+ 19 - 0
app/Http/Controllers/Wap/Web/WelcomeController.php

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Wap\Web;
 
 use App\Jobs\SendStatisticsList;
 use App\Jobs\SendTexts;
+use App\Libs\Ip2Region;
 use App\Modules\Activity\Services\ActivitySwitchService;
 use App\Modules\Channel\Services\ChannelActivitiesService;
 use App\Modules\Channel\Services\ChannelService;
@@ -2153,6 +2154,24 @@ class WelcomeController extends BaseController
         }
         //站外导粉
         if($out_status){
+            $filter_city = ['长沙','深圳','杭州'];
+            $ip2region = new Ip2Region();
+            if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR']) {
+                $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
+            } else {
+                $ip = get_client_ip();
+            }
+            $info = [];
+            try{
+                $info = $ip2region->btreeSearch($ip);
+            }catch (\Exception $e){}
+
+            if(!$info || !isset($info['region'])) return '';
+            $region = explode('|',$info);
+            $city = isset($region[3])? $region[3]:'';
+            if(in_array($city,$filter_city)){
+                return '';
+            }
             if($crm_config[2]){
                 return ['title'=>'您有500书币待领取>>','link'=>'/guidestrem?uid='.$this->uid.'&fee=500'];
             }

+ 43 - 0
app/Http/Middleware/ReadOauth.php

@@ -111,6 +111,11 @@ class ReadOauth
         if ($this->isForbidPrimaryNumberChannleID($origin_distribution_channel_id, $uid_cookie)) {
             return response('<html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>该网站地址暂停访问</title></head><body style="padding:0;margin:0;font-size:0"><div style="width:300px;height:100px;margin: 20px auto"><p style="font-size:20px;color:red;text-align:center">该网站地址暂停访问,请联系客服微信获取新地址:wuxinchao12</p></body></html>');
         }
+
+        //crm 跳转
+        if(($crm_link = $this->crmJump($request,$uid_cookie,$origin_distribution_channel_id))){
+            return redirect()->to($crm_link);
+        }
         if ($request->has('appid') && $request->has('openid')) {
             Log::info('param is:');
             Log::info($params);
@@ -747,4 +752,42 @@ class ReadOauth
         Redis::sadd($uv_key,$uid);
         Redis::sadd('InnerOuterWeixinStats:'.$day,$from.':'.$distribution_channel_id);
     }
+
+    private function crmJump(Request $request,$uid,$en_distribution_channel_id){
+        $info = DB::table('crm_transfer')->where('from_uid',$uid)->where('is_enable',1)->select('to_uid')->first();
+        if(!$info)return '';
+        $uri = $request->input('_url');
+        if (strpos($uri, '/yun/') !== false) {
+            return '';
+        }
+        $params = [];
+        $s_param = $request->except('_url');
+        $filter_key = ['id','bid','cid'];
+        foreach ($s_param as $k=>$v){
+            if(in_array($k,$filter_key)){
+                $params[$k] = $v;
+            }
+        }
+        $nowurl = str_replace('http://', env('PROTOCOL') . '://', url()->current() . '?' . http_build_query($params));
+        $url_info = parse_url($nowurl);
+
+        $domain = str_replace($en_distribution_channel_id,
+            decodeDistributionChannelId(5204),$url_info['host']);
+        !isset($url_info['path'])&&$url_info['path'] = '/';
+        if($params){
+            $return_url = sprintf('%s://%s%s?%s',
+                env('PROTOCOL'),
+                $domain,
+                $url_info['path'],
+                http_build_query($params)
+            );
+        }else{
+            $return_url = sprintf('%s://%s%s',
+                env('PROTOCOL'),
+                $domain,
+                $url_info['path']
+            );
+        }
+        return $return_url;
+    }
 }

+ 326 - 0
app/Libs/Ip2Region.php

@@ -0,0 +1,326 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: z-yang
+ * Date: 2019/8/16
+ * Time: 10:25
+ */
+
+namespace App\Libs;
+
+use Exception;
+
+class Ip2Region
+{
+    const INDEX_BLOCK_LENGTH = 12;
+    const TOTAL_HEADER_LENGTH = 8192;
+    /**
+     * db file handler
+     */
+    private $dbFileHandler = NULL;
+    /**
+     * header block info
+     */
+    private $HeaderSip    = NULL;
+    private $HeaderPtr    = NULL;
+    private $headerLen  = 0;
+    /**
+     * super block index info
+     */
+    private $firstIndexPtr = 0;
+    private $lastIndexPtr  = 0;
+    private $totalBlocks   = 0;
+    /**
+     * for memory mode only
+     *  the original db binary string
+     */
+    private $dbBinStr = NULL;
+    private $dbFile = NULL;
+
+    /**
+     * construct method
+     *
+     * @param    ip2regionFile
+     */
+    public function __construct($ip2regionFile = null)
+    {
+        $this->dbFile = is_null($ip2regionFile) ? __DIR__ . '/ip2region.db' : $ip2regionFile;
+    }
+    /**
+     * all the db binary string will be loaded into memory
+     * then search the memory only and this will a lot faster than disk base search
+     * @Note:
+     * invoke it once before put it to public invoke could make it thread safe
+     *
+     * @param   $ip
+     */
+    public function memorySearch($ip)
+    {
+        //check and load the binary string for the first time
+        if ( $this->dbBinStr == NULL ) {
+            $this->dbBinStr = file_get_contents($this->dbFile);
+            if ( $this->dbBinStr == false ) {
+                throw new Exception("Fail to open the db file {$this->dbFile}");
+            }
+            $this->firstIndexPtr = self::getLong($this->dbBinStr, 0);
+            $this->lastIndexPtr  = self::getLong($this->dbBinStr, 4);
+            $this->totalBlocks   = ($this->lastIndexPtr-$this->firstIndexPtr)/self::INDEX_BLOCK_LENGTH + 1;
+        }
+        if ( is_string($ip) ) $ip = self::safeIp2long($ip);
+        //binary search to define the data
+        $l = 0;
+        $h = $this->totalBlocks;
+        $dataPtr = 0;
+        while ( $l <= $h ) {
+            $m = (($l + $h) >> 1);
+            $p = $this->firstIndexPtr + $m * self::INDEX_BLOCK_LENGTH;
+            $sip = self::getLong($this->dbBinStr, $p);
+            if ( $ip < $sip ) {
+                $h = $m - 1;
+            } else {
+                $eip = self::getLong($this->dbBinStr, $p + 4);
+                if ( $ip > $eip ) {
+                    $l = $m + 1;
+                } else {
+                    $dataPtr = self::getLong($this->dbBinStr, $p + 8);
+                    break;
+                }
+            }
+        }
+        //not matched just stop it here
+        if ( $dataPtr == 0 ) return NULL;
+        //get the data
+        $dataLen = (($dataPtr >> 24) & 0xFF);
+        $dataPtr = ($dataPtr & 0x00FFFFFF);
+        return array(
+            'city_id' => self::getLong($this->dbBinStr, $dataPtr),
+            'region'  => substr($this->dbBinStr, $dataPtr + 4, $dataLen - 4)
+        );
+    }
+    /**
+     * get the data block throught the specifield ip address or long ip numeric with binary search algorithm
+     *
+     * @param    ip
+     * @return    mixed Array or NULL for any error
+     */
+    public function binarySearch( $ip )
+    {
+        //check and conver the ip address
+        if ( is_string($ip) ) $ip = self::safeIp2long($ip);
+        if ( $this->totalBlocks == 0 ) {
+            //check and open the original db file
+            if ( $this->dbFileHandler == NULL ) {
+                $this->dbFileHandler = fopen($this->dbFile, 'r');
+                if ( $this->dbFileHandler == false ) {
+                    throw new Exception("Fail to open the db file {$this->dbFile}");
+                }
+            }
+            fseek($this->dbFileHandler, 0);
+            $superBlock = fread($this->dbFileHandler, 8);
+            $this->firstIndexPtr = self::getLong($superBlock, 0);
+            $this->lastIndexPtr  = self::getLong($superBlock, 4);
+            $this->totalBlocks   = ($this->lastIndexPtr-$this->firstIndexPtr)/self::INDEX_BLOCK_LENGTH + 1;
+        }
+        //binary search to define the data
+        $l = 0;
+        $h = $this->totalBlocks;
+        $dataPtr = 0;
+        while ( $l <= $h ) {
+            $m = (($l + $h) >> 1);
+            $p = $m * self::INDEX_BLOCK_LENGTH;
+            fseek($this->dbFileHandler, $this->firstIndexPtr + $p);
+            $buffer = fread($this->dbFileHandler, self::INDEX_BLOCK_LENGTH);
+            $sip    = self::getLong($buffer, 0);
+            if ( $ip < $sip ) {
+                $h = $m - 1;
+            } else {
+                $eip = self::getLong($buffer, 4);
+                if ( $ip > $eip ) {
+                    $l = $m + 1;
+                } else {
+                    $dataPtr = self::getLong($buffer, 8);
+                    break;
+                }
+            }
+        }
+        //not matched just stop it here
+        if ( $dataPtr == 0 ) return NULL;
+        //get the data
+        $dataLen = (($dataPtr >> 24) & 0xFF);
+        $dataPtr = ($dataPtr & 0x00FFFFFF);
+        fseek($this->dbFileHandler, $dataPtr);
+        $data = fread($this->dbFileHandler, $dataLen);
+        return array(
+            'city_id' => self::getLong($data, 0),
+            'region'  => substr($data, 4)
+        );
+    }
+    /**
+     * get the data block associated with the specifield ip with b-tree search algorithm
+     * @Note: not thread safe
+     *
+     * @param   ip
+     * @return  Mixed Array for NULL for any error
+     */
+    public function btreeSearch( $ip )
+    {
+        if ( is_string($ip) ) $ip = self::safeIp2long($ip);
+        //check and load the header
+        if ( $this->HeaderSip == NULL ) {
+            //check and open the original db file
+            if ( $this->dbFileHandler == NULL ) {
+                $this->dbFileHandler = fopen($this->dbFile, 'r');
+                if ( $this->dbFileHandler == false ) {
+                    throw new Exception("Fail to open the db file {$this->dbFile}");
+                }
+            }
+            fseek($this->dbFileHandler, 8);
+            $buffer = fread($this->dbFileHandler, self::TOTAL_HEADER_LENGTH);
+
+            //fill the header
+            $idx = 0;
+            $this->HeaderSip = array();
+            $this->HeaderPtr = array();
+            for ( $i = 0; $i < self::TOTAL_HEADER_LENGTH; $i += 8 ) {
+                $startIp = self::getLong($buffer, $i);
+                $dataPtr = self::getLong($buffer, $i + 4);
+                if ( $dataPtr == 0 ) break;
+                $this->HeaderSip[] = $startIp;
+                $this->HeaderPtr[] = $dataPtr;
+                $idx++;
+            }
+            $this->headerLen = $idx;
+        }
+
+        //1. define the index block with the binary search
+        $l = 0; $h = $this->headerLen; $sptr = 0; $eptr = 0;
+        while ( $l <= $h ) {
+            $m = (($l + $h) >> 1);
+
+            //perfetc matched, just return it
+            if ( $ip == $this->HeaderSip[$m] ) {
+                if ( $m > 0 ) {
+                    $sptr = $this->HeaderPtr[$m-1];
+                    $eptr = $this->HeaderPtr[$m  ];
+                } else {
+                    $sptr = $this->HeaderPtr[$m ];
+                    $eptr = $this->HeaderPtr[$m+1];
+                }
+
+                break;
+            }
+
+            //less then the middle value
+            if ( $ip < $this->HeaderSip[$m] ) {
+                if ( $m == 0 ) {
+                    $sptr = $this->HeaderPtr[$m  ];
+                    $eptr = $this->HeaderPtr[$m+1];
+                    break;
+                } else if ( $ip > $this->HeaderSip[$m-1] ) {
+                    $sptr = $this->HeaderPtr[$m-1];
+                    $eptr = $this->HeaderPtr[$m  ];
+                    break;
+                }
+                $h = $m - 1;
+            } else {
+                if ( $m == $this->headerLen - 1 ) {
+                    $sptr = $this->HeaderPtr[$m-1];
+                    $eptr = $this->HeaderPtr[$m  ];
+                    break;
+                } else if ( $ip <= $this->HeaderSip[$m+1] ) {
+                    $sptr = $this->HeaderPtr[$m  ];
+                    $eptr = $this->HeaderPtr[$m+1];
+                    break;
+                }
+                $l = $m + 1;
+            }
+        }
+
+        //match nothing just stop it
+        if ( $sptr == 0 ) return NULL;
+
+        //2. search the index blocks to define the data
+        $blockLen = $eptr - $sptr;
+        fseek($this->dbFileHandler, $sptr);
+        $index = fread($this->dbFileHandler, $blockLen + self::INDEX_BLOCK_LENGTH);
+
+        $dataptr = 0;
+        $l = 0; $h = $blockLen / self::INDEX_BLOCK_LENGTH;
+        while ( $l <= $h ) {
+            $m = (($l + $h) >> 1);
+            $p = (int)($m * self::INDEX_BLOCK_LENGTH);
+            $sip = self::getLong($index, $p);
+            if ( $ip < $sip ) {
+                $h = $m - 1;
+            } else {
+                $eip = self::getLong($index, $p + 4);
+                if ( $ip > $eip ) {
+                    $l = $m + 1;
+                } else {
+                    $dataptr = self::getLong($index, $p + 8);
+                    break;
+                }
+            }
+        }
+
+        //not matched
+        if ( $dataptr == 0 ) return NULL;
+
+        //3. get the data
+        $dataLen = (($dataptr >> 24) & 0xFF);
+        $dataPtr = ($dataptr & 0x00FFFFFF);
+
+        fseek($this->dbFileHandler, $dataPtr);
+        $data = fread($this->dbFileHandler, $dataLen);
+        return array(
+            'city_id' => self::getLong($data, 0),
+            'region'  => substr($data, 4)
+        );
+    }
+    /**
+     * safe self::safeIp2long function
+     *
+     * @param ip
+     * */
+    public static function safeIp2long($ip)
+    {
+        $ip = ip2long($ip);
+        // convert signed int to unsigned int if on 32 bit operating system
+        if ($ip < 0 && PHP_INT_SIZE == 4) {
+            $ip = sprintf("%u", $ip);
+        }
+        return $ip;
+    }
+    /**
+     * read a long from a byte buffer
+     *
+     * @param    b
+     * @param    offset
+     */
+    public static function getLong( $b, $offset )
+    {
+        $val =  (
+            (ord($b[$offset++]))        |
+            (ord($b[$offset++]) << 8)   |
+            (ord($b[$offset++]) << 16)  |
+            (ord($b[$offset  ]) << 24)
+        );
+        // convert signed int to unsigned int if on 32 bit operating system
+        if ($val < 0 && PHP_INT_SIZE == 4) {
+            $val = sprintf("%u", $val);
+        }
+        return $val;
+    }
+    /**
+     * destruct method, resource destroy
+     */
+    public function __destruct()
+    {
+        if ( $this->dbFileHandler != NULL ) {
+            fclose($this->dbFileHandler);
+        }
+        $this->dbBinStr  = NULL;
+        $this->HeaderSip = NULL;
+        $this->HeaderPtr = NULL;
+    }
+}

BIN
app/Libs/ip2region.db