作者归档 清心醉

通过清心醉

Maplesgory Global : This account has been blocked for hacking or unauthorized use of third-party programs.

You officially call me hacking and bot behavior.

But the game master said that I used a third-party macro, and I couldn’t accept the result.
This is the link published on the official website:
https://forums.maplestory.nexon.net/discussion/32452/ban-data-from-05-26-2022-06-01-2022

https://maplestory.nexon.net/micro-site/74738

EU Region – Hacking/Botting

AdeleQXZ, AngelicQXZ, ArkQXZ, AssassinQXZ, AvengerQXZ, BanditQXZ, BattleMageQX, BingleiQXZ, BlasterQXZ, BrawlerQXZ, CadenaQXZ, CannoneerQXZ, ClericQXZ, CrossbowmanQ, EvanQXZ, GunslingerQX, HayatoQXZ, HelixAOA, HoyoungQXZ, HunterQXZ, huoduQXZ, IIIiumQXZ, JettQXZ, KainQXZ, KaiserQXZ, KannaQXZ, KinesisQXZ, laraQXZ, LuminousQXZ, MachanicQXZ, MercedesQXZ, NightWalkerQ, PathfinderQX, PhantomQXZ, Q0X0Z, QingXinZui, rarnQXZ, ShadeQXZ, SlayerQXZ, ThunderQXZ, WildHunterQX, WindArcherQX, XenonQX

These characters are all mine, more than 40 characters in one account.
Is it because the name in my account has QXZ or QX, making you think I am a robot account? Then the reason for the title is the third-party macro settings?

I appealed a few times and I didn’t have any Hacking/Botting on, but the system just kept saying I used Hacking/Botting

The official did not provide a clear definition of what Hacking/Botting is.
I manually upgraded the large character name “QingXinZui”, and you all inexplicably gave a permanent ban.

I started to come back to play this game on February 1, 2022. It cost nearly 15,000 US dollars. The character QingXinZui is already level 251, and it is almost ready to solo Lucid. Originally, I was planning to play Black Mage at level 255 this month.

From CMS to GMS, I don’t understand what the so-called third-party macro settings are here.
I just don’t understand, what do the above reviewers mean? Spend so much money to play, there are reincarnations and BOD rings, and permanent bans are permanent bans. As for the use of other third parties for this kind of consumption? If it is hacking, it means that there is a problem with my own computer. It will be suspended for 3 days and remind the player that the computer may be poisoned and cause a permanent ban.

In general, GMS has no human rights than CMS and TMS, and the permanent ban is all up to you. Players do not have any right to appeal at all. To put it bluntly, there is a recharge ahead, as long as the recharge is suspended, a permanent ban will be given immediately.

Should the game operator consider the feelings of a real user who spent more than $15,000 and was permanently banned?
First: whether to consider comprehensively, new users, even if the computer is really installed with software (including VPN) that will be identified as hacking or third-party tools, at least a notice should be given to tell everyone what software should not be opened at the same time as the game, Avoid permanent bans, you didn’t do that, just straight permanent bans.
Second: I have appealed many times. I am sometimes busy, and the child will play with my computer. I don’t know whether the operation of the child will also lead to the ban. However, as operators, you have not seriously considered the feelings of players like us who have children at home, which means that no one who plays this game can have children? If you have children, do you have to place a number when you are not at the computer?
Third: I also sincerely express that if the child opens the software by mistake (because there are other game applications on my computer), even if it is detected by the system, there may be suspicion of opening a robot, which is not what our players are willing to do. Yes, you can set a fine threshold, and then use it as supervision. If the real user is not using the robot, the amount of the fine can be transferred to NX. Otherwise, if the computer is remotely controlled by others and manipulated by others, how many players will be driven away by you? In the current network environment, a computer that accidentally installed someone else’s Trojan horse virus is remotely controlled by someone else, and they remotely control it to see that the player is not next to the computer and then install a robot, deliberately making the player banned. So, in this case, the responsibility for the problem is still on the player? In this case, is it because in order to play Adventure Island, there can be nothing in the computer, and players must also learn network security knowledge to avoid the virus in the computer being banned by hackers, otherwise players will not play?

Not only do you hate robots, we, as consumer players, hate robots even more (otherwise, it would be boring if the equipment that cost so much money could not be sold at auction). But the GMS management staff are not players at all.

I can only say that I advise all Maplestory players to be careful with their money, and don’t be careless, and in the end there will be nothing left.

通过清心醉

How Maplestory tricks users.

Maplestory first recharges by citing customers, tempts equipment lottery, and then tempts users to buy and sell equipment and strengthen equipment.
When your consumption reaches a certain level and the consumption is suspended, as long as the consumption limit is not reached for more than one month, the Nexon administrator will find a reason to ban your account. The reason is always that you use a third party. Special attention is paid here to the so-called third party, including Windows applications such as Facebook, Youtube, etc. That is to say, as long as you have Nexon on your computer, they compete or they do not want your computer Existing applications, you play the game is to use a third party to violate the agreement, this reason can directly ban your account permanently.
In this way, your consumption will be completely deceived by them, and then when you contact Nexon’s customer service, they will tell you that there is no way to lift the ban. If you want to play, you can re-register a new account and re-consume.
Maplestory, is the world’s largest game fraud company, I hope everyone can take this as a warning.

通过清心醉

maplestory This account has been blocked for hacking or unauthorized use of third-party programs.

The Maplestory game under Nexon is a scam game. I started playing GlOBAL Luna Server on February 1, 2022. I upgrade normally every day, and I wear a 22-star BOD ring. The monthly consumption is about 1000-3000 US dollars, and the total cumulative consumption is About $13,000.
Because the equipment is almost done, I don’t think about getting the equipment for the time being, so there is no consumption lottery and Rubik’s cube washing.
On May 30, 2022, when the character was upgraded normally, the system detected that I was using a third party, and asked the client for evidence. If the client could not come up with evidence, it was said to be confidential, and the data was checked by a specialized game master. If you continue to ask questions, you will be banned from applying for an account unban appeal.
They just let you consume first, and then you almost suspend consumption, and just find a reason to ban you, and it is a permanent ban.

通过清心醉

PHP CRC16物联网硬件通讯升级

<?php
class crc{

private $SerialNumber = 1; //自增加
private $SerialNumberXOR = 254; //自减少

function issleep($time = 1){
    sleep($time);
}

private $binFile = '';
private $getSocketData = ''; //获取的16进制数据
function setBinFile($str){
    $this->binFile .=$str;
}
function getBinFile($str){
    $this->binFile .=$str;
    //$this->getSocketData .=$str;
}

function CreateSetLogFile($file){
    $file = SET_FILE;
    if($this->binFile){
        $hexstr = str_replace(" ","",$this->binFile);
        $data = pack('H*', $hexstr);
        file_put_contents($file, $data, true);
    }

    //因为获取的是16进制 所以直接写入16进制文件
    $getfile = GET_FILE;
    if($this->getSocketData){
        //$hexstr = str_replace(" ","",$this->getSocketData);
        //$data = pack('H*', $hexstr);
        file_put_contents($getfile, $this->getSocketData, true);
    }
}

public $str = array();
function setlog($str){
    $this->str[] = $str;
    $str = $str."\r\n";
    echo iconv('utf-8','gbk//IGNORE',$str);
}

function chaString($string){
    $str = '';
    for($i=0;$i<strlen($string);$i++){
        $str .= $this->getByteData($i, $string);
    }
    return $str;
}

function getByteData($k,$str){
    if($k%2==0){
        return " ".$str[$k];
    } else {
        return $str[$k];
    }
}
//字符串转16进制
function strToHex($str){
    $hex="";
    for($i=0;$i<strlen($str);$i++)
        $hex.=dechex(ord($str[$i]));
        $hex=strtoupper($hex);
        return $hex;
}
//16进制转字符串
function hexToStr($hex){
    $str="";
    for($i=0;$i<strlen($hex)-1;$i+=2)
        $str.=chr(hexdec($hex[$i].$hex[$i+1]));
        return $str;
}

function crc16($string) {
    $crc = 0xA28C;
    for ($x = 0; $x < strlen ($string); $x+=2) {
        $sys = '';
        if(isset($string[$x]) && isset($string[$x+1])){
            $sys = $string[$x].$string[$x+1];
        } else {
            continue;
        }
        //echo "sys = ". $sys."\r\n";
        $sys = hexdec($sys);

        $crc  ^= $sys;
        for ($y = 0; $y < 8; $y++) {
            $lbs = $crc & 0x0001;
            $crc >>=1;
            if($lbs == 1){
                $crc ^= 0x8408;
            }
        }
    }
    $crc ^=0xFFFF;
    return $crc;
}


private function dechexSerialNumber(){
    $str = dechex($this->SerialNumber);
    $str = $this->setHeadZero($str);
    $this->SerialNumber++;
    return $str;
}
private function dechexSerialNumberXOR(){
    $str = dechex($this->SerialNumberXOR);
    $str = $this->setHeadZero($str);
    $this->SerialNumberXOR--;
    return $str;
}

//前补0
private function setHeadZero($str,$max = 2){
    $leng = strlen($str);
    for($i=$leng;$i<$max;$i++){
        $str = "0".$str;
    }
    return $str;
}
//后补0
private function setEndZero($str,$max = 4){
    $leng = strlen($str);
    for($i=$leng;$i<$max;$i++){
        $str = $str."0";
    }
    return $str;
}


public function getdata($packet){
    $data = array();
    $data[0] = '6D';
    $data[1] = 'AC';
    $data[2] = $this->dechexSerialNumber();
    $data[3] = $this->dechexSerialNumberXOR();
    $packetNum = count($packet); //Packet Length
    $packetNum = dechex($packetNum);
    $packetNum = $this->setHeadZero($packetNum,4); //因为高字节要在前,比如包长度=10 那么实际就是0010,高低位转换就是10 00
    //数据包长度高低位
    $data[4] = substr($packetNum, 2,2);
    $data[5] = substr($packetNum, 0,2);

    //指令开始 协议头
    $command = '';

    for($i=0;$i<count($data);$i++){
        $command = $command.$this->setHeadZero($data[$i])." ";
        //$crcString .= $this->setHeadZero($data[$i]);
    }
    $crcString = '';
    //指令内容体
    for($i=0;$i<count($packet);$i++){
        $command = $command.$this->setHeadZero($packet[$i])." ";
        $crcString .= $this->setHeadZero($packet[$i]);
    }
    $crc = '';
    $temp_crc = dechex($this->crc16($crcString));
    $sum = strlen($temp_crc);
    for($i=$sum;$i<4;$i++){
        $temp_crc = "0".$temp_crc;
    }
    $crc = $temp_crc;
    $crc1 = $this->setHeadZero(substr($crc,2,2));
    $crc2 = $this->setHeadZero(substr($crc, 0,2));
    $command = $command.$crc1. " ".$crc2;
    $commandArray = array();
    return $command;
}

private function heightlow($readInt){
    $byte1 = (($readInt & 0xff));
    $byte2 = (($readInt & 0xff00) >> 8);
    // 拼装成 "高字节在后,低字节在前"的格式
    $realint = ($byte1 & 0xff) << 0 | ($byte2 & 0xff) << 8;
    //echo $byte1." = ".$byte2."\r\n";
    return $realint;
}
//更新
public function getUpdatePacket(){
    $data[0] = 26; //command
    $data[1] = 11; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    return $data;
}
//握手
public function getHandshake(){
    $data[0] = 20; //command
    $data[1] = 11; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    return $data;
}

private $falshAddress = 64;
private $defaultFalshAddress = 64; //falsh默认的10进制地址

private function getFalshAddress($zizeng = true){
    $falshAddress = $this->falshAddress;
    if($zizeng == true){
        $this->falshAddress = $this->falshAddress+2;
    }
    return dechex($falshAddress);
}
//跳转到Application
public function runApp(){
    $data[0] = 21;
    $data[1] = 11;
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    return $data;
}

//校验falsh
public function checkFalsh($res){
    $data[0] = 25;
    $data[1] = 12; 
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    $data[3] = dechex($this->defaultFalshAddress);

    //大小 = 224*0x200;
    $data[10] = dechex($this->defaultFalshAddress);
    $data[11] = 56;
    $data[12] = 00;
    $data[13] = 00;
    //dechex(224*0x200);
    return $data;
}
//擦除
public function getRemove(){
    $data[0] = 24; //command
    $data[1] = 12; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    $data[3] = $this->getFalshAddress(false);
    //大小 = 224*0x200;
    $data[10] = dechex($this->defaultFalshAddress);
    $data[11] = 56;
    $data[12] = 00;
    $data[13] = 00;
    //dechex(224*0x200);
    return $data;
}
//下载
public function getUpload($arr){
    $data[0] = 22; //command
    $data[1] = 12; //type
    //p2-p9
    for($i=2;$i<=9;$i++){
        $data[$i] = 00;
    }
    $data[3] = $this->getFalshAddress(); //dechex();
    $array = explode(" ",$arr);
    for($i=0;$i<count($array);$i++){
        if(!empty($array[$i])){
            $data[] = $array[$i];
        }
    }
    return $data;
}

}

使用方式:

$filename = “C:\crc\APP-2020-02-05.bin”;
$host = ‘192.168.1.122’;
$port = 502;
define(“SET_FILE”,’C:\crc\log.log’);
define(“GET_FILE”,’C:\crc\getlog.log’);

require_once ‘crc.php’;
$req = new crc();
$res = bin2hex(file_get_contents($filename));
if (!$res){
$req->setlog(“打开更新文件失败”);
return;
}
$req->setlog(“连接设备中…”);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO,array(‘sec’ => 1, ‘usec’ => 1));
$result = @socket_connect($sock, $host, $port);
if($result == false){
$req->setlog(“设备连接失败”);
return false;
}

//发送数据
function send($sock,$packets,$crc){
$status = socket_last_error($sock);
if($status!=0){
return false;
}
//记录的数据为字符串,实际发送的时候 重新转换成16进制的数据格式
$t = $packets;
$packets = str_split(str_replace(‘ ‘, ”, $packets), 2); //chr(hexdec($packets));
$packet = null;
for($i=0;$isetBinFile($t);
$res = getrec($sock,$crc);
$crc->getBinFile(bin2hex($res));
$crc->setlog(“接收的16进制数据:”.bin2hex($res));
return true;
}

function getrec($socket,$crc){
$rec = null;
$time = time();
$crc->setlog(“接收数据”);
while (@socket_recv($socket, $rec, 4096, 0)) { //设置接收长度最大值缓冲区
if($time+10setlog(“接收数据超时”);
break;
}
return $rec;
}
return false;
}
//

$req->setlog(“设备连接成功”);
$req->setlog(“更新帧”);
$getUpdatePacket = $req->getUpdatePacket(); //更新的包
$packets = $req->getdata($getUpdatePacket);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();
$req->setlog(“握手”);
$getHandshake = $req->getHandshake(); //更新的包
$packets = $req->getdata($getHandshake);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$req->setlog(“擦除falsh”);
$getRemove = $req->getRemove();
$packets = $req->getdata($getRemove);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$arr = array();
$head = 0;
$end = 1024;
$length = strlen($res);
while(true){
if($length<=0){ break; } $arr[] = substr($res, $head,$end); $head = ($head+1024); $length = ($length-1024); } for($i=0;$isetlog(“第”.($i+1).”次下载数据”);
$str = $req->chaString($arr[$i]);;
$getUpload = $req->getUpload($str);
$packets = $req->getdata($getUpload);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();
}

$req->setlog(“校验falsh”);
$checkfalsh = $req->checkFalsh($res);
$packets = $req->getdata($checkfalsh);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$req->setlog(“跳转到Application”);
$runApp = $req->runApp();
$packets = $req->getdata($runApp);
$req->setlog($packets);
if(send($sock, $packets,$req) == false){
$req->setlog(“发送数据”.$packets.”失败”);
}
$req->issleep();

$req->setlog(“执行完成”);
$req->setlog(“创建写入文件”);
$req->CreateSetLogFile(SET_FILE);

通过清心醉

WordPress目录安全权限

不管实在Linux还是Windows系统,我们都需要对PHP的系统应用进行权限的控制

Windows上我不懂,不给与评价

但是Liunx,默认很多权限是755,其实也足够了,但是不排除很多漏洞引起的垃圾文件被POST上传,其中最常见的就是POST木马脚本,什么一键改代码,改数据库的

针对WordPress,首先,我们给与整个web站点设置555权限

然后,因为我们的后台发布的文章,可能会需要上传图片/音频/视频等文件类型,这里就需要进行写入的权限

因此我们给与对应的上传目录设置755权限即可.

即:/web/wp-content/uploads

(切忌不要设置777,755就足够,777如果目录及文件权限过高,当心整个服务器给黑!)

通过清心醉

Ngây Thơ

Thời gian sẽ chẳng đợi chờ điều gì và cho đến khi ta nhận ra
Tình yêu giống một trò đùa dại khờ
Hay anh quá ngây thơ khi tin vào em.
Cánh hoa phai tàn kìa tiếng mưa đang rơi
Lòng bỗng như chơi vơi càng nhớ em không rời.
Đã hơn hai giờ nhắm mắt nhưng không mơ
đầu vẫn đang ngu ngơ chìm đắm trong hững hờ.

Từng cuộc gọi mỗi tối làm sao anh
Quên kìa giọng nói em còn vương vấn anh.
Thì thầm đâu đó lời nào bên tai vậy
Là lời nói yêu em là người nói điêu.
Là do anh ngây thơ tưởng tình là cơn mơ.
Là do anh ngây thơ tưởng tình là cơn mơ

Thời gian sẽ chẳng đợi chờ điều gì và cho đến khi ta nhận ra
Tình yêu giống một trò đùa dại khờ
Hay anh quá ngây thơ khi tin vào em.
Cánh hoa phai tàn kìa tiếng mưa đang rơi
Lòng bỗng như chơi vơi càng nhớ em không rời.
Đã hơn hai giờ nhắm mắt nhưng không mơ
đầu vẫn đang ngu ngơ chìm đắm trong hững hờ.

Từng cuộc gọi mỗi tối làm sao anh
Quên kìa giọng nói em còn vương vấn anh.
Thì thầm đâu đó lời nào bên tai vậy
Là lời nói yêu em là người nói điêu.
Là do anh ngây thơ tưởng tình là cơn mơ.
Là do anh ngây thơ tưởng tình là cơn mơ

通过清心醉

Move Your Body

Move Your Body – Sia
Poetry in your body
你如诗般扣人心弦的身体
You got it in every way
正用各种姿态舞动着
And can’t you see it’s you I’m watching
你知不知道我正注视着你
I am hot for you in every way
我妖娆多姿 供你尽情享用
And turn around, let me see you
转过身来 让我好好看着你
Wanna free you with my rhythm
想要你与我跟随节奏纵情自由
I know you can’t get enough
我深知你不会轻易满足
When I turn up with my rhythm
当我唤醒身体 律动起来
Your body’s poetry, speak to me
你的身体如诗般地对我呼唤
Won’t you let me be your rhythm tonight
难道今夜不想让我与你共享节奏的欢愉
Move your body, move your body
摇摆起来 魅惑迷人
I wanna be your muse, use my music
我想做你的音乐女神 被写进你的音乐
And let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body, move your body
摇摆起来 魅惑迷人
Your body’s poetry speak to me
你的身体如诗般地对我呼唤
Won’t you let me be your rhythm tonight
难道今夜不想让我与你共享节奏的欢愉
Move your body, move your body
摇摆起来 魅惑迷人
I wanna be your muse, use my music
我想成为你的缪斯女神 被写进你的音乐
And let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body move your body
摇摆起来 魅惑迷人
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
Poetry in your body
你如诗般扣人心弦的身体
Got it started or never end
勾起你的欲望 愈演愈烈
Feel my rhythm in your system
感受我在你体内的律动
This is living, I’m your only friend
这就是生活我是你唯一的朋友
Feel the beat in your chest
感受你的心跳
Beat your chest like an animal
正猛烈的跳动
Free the beast from its cage
就如挣脱牢笼重获自由的猛兽
Free the rage like an animal
就如挣脱牢笼重获自由的猛兽
Your body’s poetry, speak to me
你的身体如诗般地对我呼唤
Won’t you let me be your rhythm tonight
难道今夜不想让我与你共享节奏的欢愉
Move your body move your body
摇摆起来 魅惑迷人
I wanna be your muse, use my music
我想做你的音乐女神 被写进你的音乐
And let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body, move your body
摇摆起来 魅惑迷人
Your body’s poetry, speak to me
你的身体如诗般地对我呼唤
Won’t you let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body, move your body
摇摆起来 魅惑迷人
I wanna be your muse, use my music
我想做你的音乐女神 被写进你的音乐
And let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body move your body
摇摆起来 魅惑迷人
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
You body’s poetry
你如诗般扣人心弦的身体
Move your body for me
热情似火地对我搔首弄姿
Your body’s poetry
你如诗般扣人心弦的身体
Move your body for me
热情似火地向我搔首弄姿
Me me me me me me me
对我搔首弄姿
Your body’s poetry, speak to me
你的身体如诗般地对我呼唤
Won’t you let me be your rhythm tonight
难道今夜不想让我与你共享节奏的欢愉
Move your body move your body
摇摆起来 魅惑迷人
I wanna be your muse, use my music
我想做你的音乐女神 被写进你的音乐
And let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body, move your body
摇摆起来 魅惑迷人
Your body’s poetry, speak to me
你的身体如诗般地对我呼唤
Won’t you let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body, move your body
摇摆起来 魅惑迷人
I wanna be your muse, use my music
我想做你的音乐女神 被写进你的音乐
And let me be your rhythm tonight
就让我成为今夜的主旋律
Move your body, move your body
摇摆起来 魅惑迷人
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢
Oh oh oh oh oh oh oh oh
噢噢 Oh oh oh oh oh oh oh oh 噢噢

通过清心醉

star sky

star sky

Here we are
我们在此地
Riding the sky
翱翔于天际
Painting the night with sun
绘夜空以晨旭
You and I, Mirrors of light
你和我 交相辉映
Twin flames of fire
如两团火焰
Lit in another time and place
闪亮在彼时彼地
I knew your name
我曾知你生名
I knew your face
也曾忆你音容
Your love and grace
与你爱和魅力
Past and present now embrace
过往与现在汇聚
Worlds collide in inner space
世界激荡于内心
Unstoppable, the song we play
我们奏响的歌 永不停息
(chorus)
(合唱)
Burn the page for me
忘记我的过去
I cannot erase the time of sleep
沉睡时光我无法抹去
I cannot be loved so set me free
我不能被爱 所以放我自由
I cannot deliver your love
我不能接受你的爱
Or caress your soul so
也无法抚慰你的灵魂
Turn that page for me
就让过往逝去
I cannot embrace the touch that you give
我不能接受你的拥抱
I cannot find solace in your words
也找不到安慰的话语
I cannot deliver you your love
我不能回应你的爱意
Or caress your soul
也不能抚慰你的灵魂
独唱(solo)
Age to age
年复一年
I feel the call
我感到那呼唤
Memory of future dreams
未来梦想的记忆
You and I, riding the sky
你和我 相依比翼
Keeping the fire bright
让火焰永不熄
From another time and place
在彼时彼地
I know your name
我知你生名
I know your face
将你容颜记
Your touch and grace
和你的怀抱和魅力
All of time can not erase
时间也无法抹去
What our hearts remember stays
我们记得要留在哪里
Forever on a song we play
永远留在 我们的那首歌里
Burn the page for me
忘记我的过去
I cannot erase the time of sleep
沉睡时光我无法抹去
I cannot be loved so set me free
我不能被爱 所以放我自由
I cannot deliver your love
我不能接受你的爱
Or caress your soul so
也无法抚慰你的灵魂
turn that page for me
就让过往逝去
I cannot embrace the touch that you give
我不能接受你的拥抱
I cannot find solace in your words
也找不到安慰的话语
I cannot deliver you your love
我不能回应你的爱意
or caress your soul
也不能抚慰你(的灵魂)

通过清心醉

PHP多线程开发的坑

说起多线程,一般的人都想到的是用C类语言,或者JAVA来开发

因为我是做PHP为主的,对JAVA了解的少,而用C实际开发项目的经验少,所以入坑了。

在这也简单的来和大家说下:

首先,我们会以CLI的方式来运行SERVER进程,在进程里,读取数据库的设备信息,实现线程的创建。

在这里,PHP基本使用的是Pthread的扩展Thread。

由于项目需要,我们在创建了线程之后,在线程里实现while(true)与设备通讯,获取设备的最新信息。

来说说重点吧:

1:服务器的环境配置,在这里大家一定要特别的注意,一定要用5.6+的ZTS-X64版本,建议使用W_PHP 7.0X或Linux 7.2.X版本,因为这两个版本网上都有最近的线程扩展模块。如果使用的是非ZTS-X64版本,那么很遗憾,线程永远开启不了超过200个。因为进行了多次的模拟测试,包括线程内执行死循环和跑完之后挂起,查看系统的资源使用,如果是X86系统下,因为内存的其他限制(详细的内存有得说了,不一一解释,自行翻资料查看86-64的内存使用哈);

2:系统版本,一般开发调试,系统的最低要求是Windows7 SP1,LINUX则无限制(但必须都是X64),因为在WINDOWS下跑Thread需要VC2015的扩展支持;如果开发则还使用Windows7的,cmd->winver里查看版本内核是否低于7001,是的话,升级为SP1解决问题;

3:线程安全:现在网上什么ZTS、NTS的说话一大堆,都是老过时的东西,现在的线程安全,都是被人抄来抄去的过期文章!

PHP的Pthread扩展,V2和V3版本有了很大的实际变更,更像多线程的操作优化了;

A:V2版本,虽然实现了多线程,但一样可以通过稀哈操作数据数组,导致频繁的线程操作,导致线程挂起

B:线程内的成员在执行的时候,已经分配了适当的内存空间,也就是说一个空变量,分配了值=int(1),这时候,是不可能进行=String的操作,更不可以变成数组等,所以在线程内获取的数据资源,需要使用其他TCP端口来接收或者其他更好的操作方法;(这才是更好的理解什么是线程安全ZTS,对内存中的所有分配好的资源,是不可以随意修改的,当然$i=0;$i=1之类的占用相同地址同类型的,还是可以的)

C:线程锁,如果多线程内需要对同一地址的数据进行操作,切忌使用锁,否则同一时间的操作导致线程的异常,也会导致线程中止退出。

D:就是线程的内存占用了,说真的,PHP的线程占用内存还真好,也许是因为我在线程内也有发起TCP请求其他的关系,导致1个线程使用内存都接近了1MB,所以我们能以行参的方式传递参数,就别用成员!数据的销毁也一定要记得!

来一段2000个的线程创建实例吧:

class ThreadMax extends thread{

private $id;

function __construct($id){

$this->id = $id;

}

function run(){

while(true){

//echo “ID=”.$this->id.”\n”; //不执行其他任务工作

sleep(1);

}

}

}

$thread = array();

for($i=1;$i<=2000;$i++){

$thread[$i] = new ThreadMax($i);

}

$default  =0;

while(true){

if($default==0){

for($i=1;$i<=2000;$i++){

$thread[$i]->start();

}

$default = 1;

}

echo “thread All is OK!”;

sleep(10);

}

return;

微信图片_20180427222654

通过清心醉

模块化第三方接口开发一,模块化的登陆

很多做WEB开发的人都知道,现在做WEB,都需要使用第三方比如支付宝、微信等 。拿国内的ecshop来说吧,我们在添加一个支付宝授权登陆、微信授权登陆,支付宝支付、微信支付的时候,都会需要对不同的模块进行频繁的修改,虽然说也有封装部分的接口,但也不能得尽人意。而且如果后续要对接比如PAYPAY支付、GOOGLE支付等其他第三方支付的时候,会显示出我们写的代码的质量是多么的脆弱,好吧,上正题,本文将从登陆开始,来实现系统化的调用。

该文章作者会大概的阐述自定义

首先我们来定个目标变量,假设支付宝=0,微信=1

//定义第三方接口参数注册
$api = array(
0=>array(
‘extend’=>’AlipayApi’, //接口类名
‘useragent’=>’AlipayClient’,//接口识别用户访问类型
),
1=>array(
‘extend’=>’Weixin’,
‘useragent’=>’MicroMessenger’,
),
);

在这里我们定义好了第三方的接口所需要的信息。

一维代表类型,当然也可以自身在数据库中用户表来进行捆绑识别

二维代表实际参数extend表示需要调用的第三方文件类库,useragent是针对HTML5里识别APP的访问类型。

好吧,我们先从访问开始。

用户在进行HTML登陆的时候,当然也可以对接帐号密码登陆,因为我们都是通过$_SESSION来进行;

class LoginAPI{
function getlogin($user_agent,$store_id){
for ($i=0;$i<count($api);$i++){
if (strpos($user_agent,$api[$i][‘useragent’])){
$login = new $api[$i][‘extend’]();
$url = $login->getLoginApi($store_id);
header(“Location:”.$url);
exit();
}
}
die(“<h1>ERROR</h1>”);
}
}

我们在需要使用的地方,直接实例化LoginAPI,调用方法,附加用户的标识,交由脚本执行。

由于作者实际写的系统是针对HTML5为主,授权登陆我们都知道,需要跳转到支付宝、微信的开放平台的接口,执行实现回调URL;

$url = $login->getLoginApi($store_id);

我们来看看目录结果:

/loginapi.php //授权类

/api/alipay.php  //支付宝类,包括登陆、支付、模板消息

/api/weixin.php //微信类,包括登陆、支付、模板消息

上文的代码中我们没有看到任何实际性的requirce,因为作者使用的是自己写的框架,里面对常用的接口进行过requcie,虽然浪费资源,但能更快效率的进行实例化调用,而且现在大内存时候,也不用去考虑这一块;

 

好了,回正题,我们来看看调用的实际登陆

/***
* 支付获取请求的URL
* @return string
*/
function getLoginApi($store_id){
$url=’https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?’;
$url.=’app_id=’.$this->appid;
$url.=’&scope=auth_userinfo’;
$url.=’&redirect_uri=’.HTTP_SERVER.’api/alipay.php’;
$url.=’&state=’.$store_id;
return $url;
}

 

/***
* 微信获取登陆授权
* @param unknown $store_id
* @return string
*/
public function getLoginApi($store_id){
$url =’https://open.weixin.qq.com/connect/oauth2/authorize?’;
$url.=’appid=’.$this->appid;
$url.=’&redirect_uri=’.HTTP_SERVER.’api/weixin.php’;
$url.=’&response_type=code&scope=snsapi_userinfo’;
$url.=’&state=’.$store_id;
$url.=’#wechat_redirect’;
return $url;
}

这样一来,我们如果要添加京东授权登陆,添加对应的class添加对应的功能,然后统一回调写入数据库即可。

至于添加的时候,需要注册到全局的API里面,以方便在for()里实现调用

如此我们打开支付宝、微信,调用的都是同一个方法名,实现同样的效果,不再需要频繁的写switch(),if()来判断用户的登陆类型了。

 

下文作者将讲解模块化的支付、回调,代码前瞻:

return $this->pay_class[$this->login_type]->Pay($this->store_id,$this->order_id,$this->store_system,$title,$this->money,$this->customer,$this->return_url);

 

 

 

通过清心醉

境外电商,如何更好的实现SEO

说起境外电商,无非就是对国内现有产品进行境外的一个销售。

现在主流的系统有轻量级的opencart、zencart、prestashop,而中量级因为功能没优势,便捷没优势就不说了,而重量级的首选magento

那么问题来了,我们做跨境电商前,就先明确我们要做到什么程度。

如果你只是想做英国、美国单一的国家的话,那么一个opencart、zencart、prestashop绝对足够满足单一语言的SEO标准,而且服务器配置成本低,关键是还轻量,随便找个2年开发经验的PHP就可以胜任修改成自己想要的。(别拿国内的什么ecshop等系列软件对比,国内不流行SEO)。如果要用做多个国家,比如法国、美国等,那么magento是必不可少的一个趋势。

结合作者多年的跨境电商的SEO开发及后端数据开发经验,整理下SEO的必须标准:

单语:

站点元标题、元描述、元关键字

站点图片标签化处理

然后就是语言化的产品名字、介绍等系列功能了

 

不过除了magento可以实现多语言的元标记、图片标记,其他系统上对这一块的抽象类操作并不是很友好

我们来假设有个中英双语言站

一个产品名为:iphone,中文苹果手机

那么我们上列的系统,都可以很好的支持产品的seo

但是,单纯的产品的文字匹配,利用元标记来实现,但如果是图片化的alt标记,却会让爬虫望尘莫及,因为爬虫不知道图片所属类型,更不知道代表什么。

 

我们都知道,SEO最大的特点,就是需要对页面上关键字的一个占有量控制,一般控制有5%基本就足够。

但就文字描述介绍,不能编写过多的关键字特性,又不能在全站的元标记内进行处理,否则会导致关键字泛滥,GOOGLE会以作弊形式直接K站。

图片alt+多语言文章站内url,引导更多的关键字流量。

 

时间有限,笔至此停!

如有需要做境外的可以联系我

公司地址:梅州市梅县区程江镇扶外路梅县扶外市场2楼-梅州市东发网络科技有限公司

联系电话:13823819185

 

 

通过清心醉

opencart规格积分无法增加的解决方案

需要的动作:
1:用户加入购物车,有其他的规格,增加其他规格的积分的显示
controller/checkout/cart.php里的index控制器里修改:

$jifennum=0; //重新定义积分 = 0 ;
foreach ($product[‘option’] as $option) {
if ($option[‘type’] != ‘file’) {
$value = $option[‘value’];
} else {
$upload_info = $this->model_tool_upload->getUploadByCode($option[‘value’]);

if ($upload_info) {
$value = $upload_info[‘name’];
} else {
$value = ”;
}
}

$option_data[] = array(
‘name’ => $option[‘name’],
‘value’ => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . ‘..’ : $value)
);
//新增判断语句,判断积分的增减
if (!empty($option[‘points_prefix’]) && !empty($option[‘points’])){
if ($option[‘points_prefix’]==’+’){
$jifennum = ($jifennum+$option[‘points’]);
} else {
$jifennum = ($jifennum-$option[‘points’]);
}
}
//判断结束
}
$jifennum = ($jifennum*$product_total); //购买的数量,同时增加积分的总值

$jifen=($product[‘reward’]+$jifennum);
#然后,$data[‘products’][]多维数组重新修改显示的值:

// Display prices
if (($this->config->get(‘config_customer_price’) && $this->customer->isLogged()) || !$this->config->get(‘config_customer_price’)) {
$price = $this->currency->format($this->tax->calculate($product[‘price’], $product[‘tax_class_id’], $this->config->get(‘config_tax’)));
} else {
$price = false;
}

// Display prices
if (($this->config->get(‘config_customer_price’) && $this->customer->isLogged()) || !$this->config->get(‘config_customer_price’)) {
$total = $this->currency->format($this->tax->calculate($product[‘price’], $product[‘tax_class_id’], $this->config->get(‘config_tax’)) * $product[‘quantity’]);
} else {
$total = false;
}

$recurring = ”;

if ($product[‘recurring’]) {
$frequencies = array(
‘day’ => $this->language->get(‘text_day’),
‘week’ => $this->language->get(‘text_week’),
‘semi_month’ => $this->language->get(‘text_semi_month’),
‘month’ => $this->language->get(‘text_month’),
‘year’ => $this->language->get(‘text_year’),
);

if ($product[‘recurring’][‘trial’]) {
$recurring = sprintf($this->language->get(‘text_trial_description’), $this->currency->format($this->tax->calculate($product[‘recurring’][‘trial_price’] * $product[‘quantity’], $product[‘tax_class_id’], $this->config->get(‘config_tax’))), $product[‘recurring’][‘trial_cycle’], $frequencies[$product[‘recurring’][‘trial_frequency’]], $product[‘recurring’][‘trial_duration’]) . ‘ ‘;
}

if ($product[‘recurring’][‘duration’]) {
$recurring .= sprintf($this->language->get(‘text_payment_description’), $this->currency->format($this->tax->calculate($product[‘recurring’][‘price’] * $product[‘quantity’], $product[‘tax_class_id’], $this->config->get(‘config_tax’))), $product[‘recurring’][‘cycle’], $frequencies[$product[‘recurring’][‘frequency’]], $product[‘recurring’][‘duration’]);
} else {
$recurring .= sprintf($this->language->get(‘text_payment_cancel’), $this->currency->format($this->tax->calculate($product[‘recurring’][‘price’] * $product[‘quantity’], $product[‘tax_class_id’], $this->config->get(‘config_tax’))), $product[‘recurring’][‘cycle’], $frequencies[$product[‘recurring’][‘frequency’]], $product[‘recurring’][‘duration’]);
}
}

$data[‘products’][] = array(
‘key’ => $product[‘key’],
‘thumb’ => $image,
‘name’ => $product[‘name’],
‘model’ => $product[‘model’],
‘option’ => $option_data,
‘recurring’ => $recurring,
‘quantity’ => $product[‘quantity’],
‘stock’ => $product[‘stock’] ? true : !(!$this->config->get(‘config_stock_checkout’) || $this->config->get(‘config_stock_warning’)),
//’reward’ => ($product[‘reward’] ? sprintf($this->language->get(‘text_points’), $product[‘reward’]) : ”),
‘reward’ => ($product[‘reward’] ? sprintf($this->language->get(‘text_points’), $jifen) : ”),
‘price’ => $price,
‘total’ => $total,
‘href’ => $this->url->link(‘product/product’, ‘product_id=’ . $product[‘product_id’])
);

这样,用户在购物车看到的赠送积分的规则就变了

然后是后台管理员

2: 后台管理员对订单的操作,首先是修改添加的积分值
sale/order/info方法内

$data[‘reward’] = $order_info[‘reward’]; //获取赠送积分,自然已经自动区分了不同的会员等级

然后该方法内还有个foreach ($products as $product) 循环

$product_num = $product[‘quantity’]; //获取产品的数量
$jifen = 0; //订单规格的积分增加
foreach ($options as $option) {
//嵌入开发规格积分
$guige = $this->model_sale_order->getOrderOptionsData($option[‘product_option_id’],$product[‘product_id’],$option[‘product_option_value_id’]);
if (!empty($guige[‘points_prefix’]) && !empty($guige[‘points’])){

if ($guige[‘points_prefix’]==’+’){
$jifen = ($jifen+($guige[‘points’]*$product_num)); //因为是按数量来计算的
} else {
$jifen = ($jifen-($guige[‘points’]*$product_num));
}
}
if ($option[‘type’] != ‘file’) {
$option_data[] = array(
‘name’ => $option[‘name’],
‘value’ => $option[‘value’],
‘type’ => $option[‘type’]
);
} else {
$upload_info = $this->model_tool_upload->getUploadByCode($option[‘value’]);

if ($upload_info) {
$option_data[] = array(
‘name’ => $option[‘name’],
‘value’ => $upload_info[‘name’],
‘type’ => $option[‘type’],
‘href’ => $this->url->link(‘tool/upload/download’, ‘token=’ . $this->session->data[‘token’] . ‘&code=’ . $upload_info[‘code’], ‘SSL’)
);
}
}
}
$data[‘reward’] =($data[‘reward’]+$jifen); //把对应的规格积分进行相加

在这里引用了一个model
方法原型为:
public function getOrderOptionsData($product_option_id,$product_id,$value,$quantity){
$option_query = $this->db->query(“SELECT po.product_option_id, po.option_id, od.name, o.type FROM ” . DB_PREFIX . “product_option po
LEFT JOIN `” . DB_PREFIX . “option` o ON (po.option_id = o.option_id)
LEFT JOIN ” . DB_PREFIX . “option_description od ON (o.option_id = od.option_id)
WHERE po.product_option_id = ‘” . (int)$product_option_id . “‘
AND po.product_id = ‘” . (int)$product_id . “‘”);
$option_data=array();
if ($option_query->num_rows) {
if ($option_query->row[‘type’] == ‘select’ || $option_query->row[‘type’] == ‘radio’ || $option_query->row[‘type’] == ‘image’) {
$option_value_query = $this->db->query(“SELECT pov.option_value_id, ovd.name, pov.quantity, pov.subtract, pov.price, pov.price_prefix, pov.points, pov.points_prefix, pov.weight, pov.weight_prefix FROM ” . DB_PREFIX . “product_option_value pov LEFT JOIN ” . DB_PREFIX . “option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN ” . DB_PREFIX . “option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_option_value_id = ‘” . (int)$value . “‘ AND pov.product_option_id = ‘” . (int)$product_option_id . “‘ AND ovd.language_id = ‘” . (int)$this->config->get(‘config_language_id’) . “‘”);

if ($option_value_query->num_rows) {
if ($option_value_query->row[‘price_prefix’] == ‘+’) {
$option_price += $option_value_query->row[‘price’];
} elseif ($option_value_query->row[‘price_prefix’] == ‘-‘) {
$option_price -= $option_value_query->row[‘price’];
}

if ($option_value_query->row[‘points_prefix’] == ‘+’) {
$option_points += $option_value_query->row[‘points’];
} elseif ($option_value_query->row[‘points_prefix’] == ‘-‘) {
$option_points -= $option_value_query->row[‘points’];
}

if ($option_value_query->row[‘weight_prefix’] == ‘+’) {
$option_weight += $option_value_query->row[‘weight’];
} elseif ($option_value_query->row[‘weight_prefix’] == ‘-‘) {
$option_weight -= $option_value_query->row[‘weight’];
}

if ($option_value_query->row[‘subtract’] && (!$option_value_query->row[‘quantity’] || ($option_value_query->row[‘quantity’] < $quantity))) {
$stock = false;
}

$option_data= array(
‘product_option_id’ => $product_option_id,
‘product_option_value_id’ => $value,
‘option_id’ => $option_query->row[‘option_id’],
‘option_value_id’ => $option_value_query->row[‘option_value_id’],
‘name’ => $option_query->row[‘name’],
‘value’ => $option_value_query->row[‘name’],
‘type’ => $option_query->row[‘type’],
‘quantity’ => $option_value_query->row[‘quantity’],
‘subtract’ => $option_value_query->row[‘subtract’],
‘price’ => $option_value_query->row[‘price’],
‘price_prefix’ => $option_value_query->row[‘price_prefix’],
‘points’ => $option_value_query->row[‘points’],
‘points_prefix’ => $option_value_query->row[‘points_prefix’],
‘weight’ => $option_value_query->row[‘weight’],
‘weight_prefix’ => $option_value_query->row[‘weight_prefix’]
);
}
} elseif ($option_query->row[‘type’] == ‘checkbox’ && is_array($value)) {
foreach ($value as $product_option_value_id) {
$option_value_query = $this->db->query(“SELECT pov.option_value_id, ovd.name, pov.quantity, pov.subtract, pov.price, pov.price_prefix, pov.points, pov.points_prefix, pov.weight, pov.weight_prefix FROM ” . DB_PREFIX . “product_option_value pov LEFT JOIN ” . DB_PREFIX . “option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN ” . DB_PREFIX . “option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_option_value_id = ‘” . (int)$product_option_value_id . “‘ AND pov.product_option_id = ‘” . (int)$product_option_id . “‘ AND ovd.language_id = ‘” . (int)$this->config->get(‘config_language_id’) . “‘”);

if ($option_value_query->num_rows) {
if ($option_value_query->row[‘price_prefix’] == ‘+’) {
$option_price += $option_value_query->row[‘price’];
} elseif ($option_value_query->row[‘price_prefix’] == ‘-‘) {
$option_price -= $option_value_query->row[‘price’];
}

if ($option_value_query->row[‘points_prefix’] == ‘+’) {
$option_points += $option_value_query->row[‘points’];
} elseif ($option_value_query->row[‘points_prefix’] == ‘-‘) {
$option_points -= $option_value_query->row[‘points’];
}

if ($option_value_query->row[‘weight_prefix’] == ‘+’) {
$option_weight += $option_value_query->row[‘weight’];
} elseif ($option_value_query->row[‘weight_prefix’] == ‘-‘) {
$option_weight -= $option_value_query->row[‘weight’];
}

if ($option_value_query->row[‘subtract’] && (!$option_value_query->row[‘quantity’] || ($option_value_query->row[‘quantity’] < $quantity))) {
$stock = false;
}

$option_data= array(
‘product_option_id’ => $product_option_id,
‘product_option_value_id’ => $product_option_value_id,
‘option_id’ => $option_query->row[‘option_id’],
‘option_value_id’ => $option_value_query->row[‘option_value_id’],
‘name’ => $option_query->row[‘name’],
‘value’ => $option_value_query->row[‘name’],
‘type’ => $option_query->row[‘type’],
‘quantity’ => $option_value_query->row[‘quantity’],
‘subtract’ => $option_value_query->row[‘subtract’],
‘price’ => $option_value_query->row[‘price’],
‘price_prefix’ => $option_value_query->row[‘price_prefix’],
‘points’ => $option_value_query->row[‘points’],
‘points_prefix’ => $option_value_query->row[‘points_prefix’],
‘weight’ => $option_value_query->row[‘weight’],
‘weight_prefix’ => $option_value_query->row[‘weight_prefix’]
);
}
}
} elseif ($option_query->row[‘type’] == ‘text’ || $option_query->row[‘type’] == ‘textarea’ || $option_query->row[‘type’] == ‘file’ || $option_query->row[‘type’] == ‘date’ || $option_query->row[‘type’] == ‘datetime’ || $option_query->row[‘type’] == ‘time’) {
$option_data= array(
‘product_option_id’ => $product_option_id,
‘product_option_value_id’ => ”,
‘option_id’ => $option_query->row[‘option_id’],
‘option_value_id’ => ”,
‘name’ => $option_query->row[‘name’],
‘value’ => $value,
‘type’ => $option_query->row[‘type’],
‘quantity’ => ”,
‘subtract’ => ”,
‘price’ => ”,
‘price_prefix’ => ”,
‘points’ => ”,
‘points_prefix’ => ”,
‘weight’ => ”,
‘weight_prefix’ => ”
);
}
}
return $option_data;
}
最后是对积分进行增加和减少的操作
sale/order/addReward()添加积分和removeReward()移除积分

我们来从写addReward()
public function addReward() {
$this->load->language(‘sale/order’);

$json = array();

if (!$this->user->hasPermission(‘modify’, ‘sale/order’)) {
$json[‘error’] = $this->language->get(‘error_permission’);
$json[‘error’]= ‘后台API错误4’;
} else {
if (isset($this->request->get[‘order_id’])) {
$order_id = $this->request->get[‘order_id’];
} else {
$order_id = 0;
}

$this->load->model(‘sale/order’);

$order_info = $this->model_sale_order->getOrder($order_id);
//嵌入开发添加积分开始
$data[‘products’] = array(); //订单产品集
$products = $this->model_sale_order->getOrderProducts($order_id); //获取订单的所有产品
foreach ($products as $product) {
$option_data = array(); //产品规格
$options = $this->model_sale_order->getOrderOptions($order_id, $product[‘order_product_id’]); //获取规格
$product_num = $product[‘quantity’]; //获取产品的数量
$jifen = 0; //订单规格的积分增加
foreach ($options as $option) {
$guige = $this->model_sale_order->getOrderOptionsData($option[‘product_option_id’],$product[‘product_id’],$option[‘product_option_value_id’],$product_num);
if (!empty($guige[‘points_prefix’]) && !empty($guige[‘points’])){
if ($guige[‘points_prefix’]==’+’){
$jifen = ($jifen+($guige[‘points’]*$product_num)); //因为是按数量来计算的
} else {
$jifen = ($jifen-($guige[‘points’]*$product_num));
}
}
}
}
$reward =($order_info[‘reward’]+$jifen); //把对应的规格积分进行相加
//嵌入开发添加积分结束
if ($order_info && $order_info[‘customer_id’] && ($reward > 0)) {
$this->load->model(‘sale/customer’);

$reward_total = $this->model_sale_customer->getTotalCustomerRewardsByOrderId($order_id);

if (!$reward_total) {
//$this->model_sale_customer->addReward($order_info[‘customer_id’], $this->language->get(‘text_order_id’) . ‘ #’ . $order_id, $order_info[‘reward’], $order_id);
$this->model_sale_customer->addReward($order_info[‘customer_id’], $this->language->get(‘text_order_id’) . ‘ #’ . $order_id, $reward, $order_id);
}
}
$json[‘success’] = $this->language->get(‘text_reward_added’);
}
$this->response->addHeader(‘Content-Type: application/json’);
$this->response->setOutput(json_encode($json));
}
removeReward()的话,是根据订单的ID来实现直接删除对应ID,这个不需要修改,但为了避免员工在后台进行到底积分赠送,用户购买之后又把积分移除从新生成积分的刷分过程
直接关闭移除功能

通过清心醉

开源一个微信公众号向关注用户下发消息的简单类库

$msg = new wxmsg();#实例化消息模板
$msg->setAccessToken($msg->getAccessToken()); #获取令牌并写入到类成员
$templatelist = $msg->getTemplateList();
if(count($templatelist)<=0){ #如果模板数量小于0,直接中止
return false;
}
for($i=0;$i<count($templatelist);$i++){
if($templatelist[$i][‘title’]==’订单支付成功’){ #如果消息模板中包含订单支付成功,下发通知信息
$openid=’ocbV9wGjFMbfGTUvh89Ro9J-ng7s’;
$productName=’测试的产品’;
$productDescription=’发送时间:’.date(‘Y-m-d H:i:s’);
$return_url = ‘http://www.qingxinzui.com/’;
$money = ‘123.45’;
$data = $msg->SendMsg($openid, $templatelist[$i][‘template_id’], $productName, $productDescription,$return_url,$money);
break;
}
}

 

然后是类的扩展::

<?php

/*******
*
* 本类库只提供小心模板下发,不进行模板配置
* 需要设置的模板库为:TM00015
*
* @author IPanYing
*
*/
class wxmsg{

private $appid;
private $appsecret;
private $access_token;

public function __construct(){
$this->appid = ”;
$this->appsecret = ”;
}

public function setAccessToken($access_token){
$this->access_token = $access_token;
}
public function getAccessToken(){
$url = “https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appid&secret=$this->appsecret”;
$AccessToken = $this->IPanYingGETCURL($url);
if (isset($AccessToken[‘access_token’]) && !empty($AccessToken[‘access_token’])){
return $AccessToken[‘access_token’];
} else {
return false;
}
}

public function getMsgModelName(){
$url = “https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=$this->access_token”;
return $this->IPanYingGETCURL($url);
}

public function getTemplateList(){
$url=”https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=$this->access_token”;
$list = $this->IPanYingGETCURL($url);
return $list[‘template_list’];
}

public function SendMsg($openid,$template_id,$producttext,$remarktext,$return_url,$money){
$return_url=’http://www.ipanying.com/’;
$data = array(
‘touser’=>”$openid”,
‘template_id’=>”$template_id”,
‘url’ =>”$return_url”,
‘topcolor’=>’#FF0000’,
‘data’=>array(
‘first’=>array(‘value’=>’尊敬的用户,你的支付订单信息如下:’,’color’=>’#173177′),
‘orderMoneySum’=>array(‘value’=>$money,’color’=>’#173177’),
‘orderProductName’=>array(‘value’=>$producttext,’color’=>’#173177’),
‘Remark’=>array(‘value’=>$remarktext,’color’=>’#173177’)
)
);
$url = “https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=$this->access_token”;
return $this->IPanYingPOSTCURL($url, $data);
}

private function IPanYingGETCURL($url){
$data = file_get_contents($url);
$data = (array)json_decode($data,true);
return $data;
}

private function IPanYingPOSTCURL($url, $data){
//$data = urldecode(json_encode($data));
$data = json_encode($data);
$post = array(
‘http’ =>array(
‘method’ => ‘POST’,
‘header’ => ‘Content-type: application/x-www-form-urlencoded’,
‘content’ => $data
)
);
$context = stream_context_create($post);
$data = file_get_contents($url, false, $context);
$data = (array)json_decode($data,true);
return $data;
}

}

?>

wxmsg-class

通过清心醉

Linux执行ASP.NET

由于作者一直都喜欢在LINUX系统下进行环境编译配置,为什么呢?肯定不用说,因为LINUX的开源,LANMP的开源组合,让我可以轻松的部署任意环境的WEB网站,包括APP的SERVER;

以前曾经在LINUX用APACHE跑过ASP,但非APSX这种编译类型的,好吧,说到编译,APP也算是了!

回到整题,LINUX执行ASP.NET程序,可以用XSP或者APACHE的扩展模块支持!

(尊重开源,使用开源,维护开源,从我做起!)

XSP

XSP是一个轻量级的Web服务器,它是用100%的C#代码写成的纯.Net应用程序。当然,它也是完全公开源代码的。XSP使用 System.Web命名空间下的类去完成Asp.Net的执行任务,它也可以运行在Windows上(使用Microsoft .Net Framework)。

相对的来说,XSP的安装和配制都比较简单,它的源码包下载地址是在:XSP web server 1.0

下载软件包后,执行:tar zxfv xsp-1.0.tar.gz来完成解压缩,会在当前目录下生成一个名称为xsp-1.0的目录,进入目录后,按照以下顺序进行编译:

./configuration
make
make install

完成编译后,进入server子目录下,你可以看见里面有一个名字叫xsp.exe的可执行文件,这个就是xsp的主程序。

接下来可以进行测试工作,在xsp-1.0的目录下有一个名字叫做test的子目录,下面有很多aspx文件,这些就是随包附带的测试页面,进入test目录后,执行:

mono /…xsp的目录…/server/xsp.exe

加入看见如下提示信息:
Adding applications ‘/:.’…
Registering application:
Host:          any
Port:          any
Virtual path:  /
Physical path: /
Listening on port: 8080
Listening on address: 0.0.0.0
Root directory: /
Hit Return to stop the server.
则表示 xsp已经在8080端口进行监听(默认是8080端口),如果想要关闭服务器的话直接敲回车键。
现在可以打开Web浏览器,直接输入:

http://你的服务器的地址:8080/

如果一切都正常的话,你可以看见测试首页。
XSP还有一些参数选项,输入–help的参数就可以看见这些选项的列表和说明。这里做一个简单的介绍:

–port
设置XSP服务器监听的端口号,默认是8080,如果XSP是你服务器上唯一的WEB服务器的话,你可以把它设置为80。

–adress
设置XSP服务器监听的IP地址,默认是0.0.0.0,表示在所有地址上接受请求。

–root
设置网站的根目录,默认是当前目录。

–appconfigfile
设置XSP的配置文件。配置文件是一个XML格式的文件,可以将这些参数选项进行“打包”配置。

–appconfigdir
设置XSP的配置文件目录。假如你在一个文件中写不完配置的话(几乎不可能吧),可以把配置信息写到多个文件中,xsp会读取这个目录下所有扩展名为.webapp的配置文件。

–applications
设置XSP的虚拟目录。一个XSP服务器可以设置多个虚拟目录,格式是:虚拟目录名:真实路径,如果有多个的话,中间用分号隔开。

–nonstop
敲回车键不关闭服务器。

–version
显示XSP的版本号。

–verbose
打印出一些附加信息,主要用来调试用。

Apache Mono module

前面介绍的XSP是一个轻量级的服务器,那么这个应该可以算做是一个重量级的了(其实也重不到哪里去,Apache在这里只是一个代理请求的功能,主要 处理其实都转到mod_mono去了),Apache Mono module是Apache服务器的一个外挂的模块,可以让Apache服务器支持Asp.Net应用程序。

mod_mono在Apache Mono module 1.0 处下载,下载后同样是:

./configuration
make
make install

编译完成后,就可以来配制apache服务器了,找到你的apache配置文件,一般是位于:/etc/httpd/conf/httpd.conf,使用vi编辑器打开这个文件,在文件里面加上:

LoadModule mono_module modules/libmod_mono.so
Alias /虚拟目录名 “真实路径”
MonoApplications “/虚拟目录名:真实路径”

SetHandler mono
假如你的mono和xsp没有安装在标准路径,还需要加上一些额外的参数:

MonoExecutablePath 设置mono的执行路径

MonoServerPath 设置mod-mono-server.exe文件的路径,注意这个文件是在XSP的软件包中的,所以这个要设置为XSP的路径。

一般设置了这些参数就可以了,其它的参数选项都设置为默认。

现在可以重启Apache服务器,找到你的apachectl命令的路径,一般是在/usr/sbin目录下,然后使用:

apachectl restart

这时你就可以打开浏览器输入服务器地址和虚拟目录来验证是否已经配置成功了。

通过清心醉

使用阿里云服务器进行配置微信支付导致无法回调的问题深思

最近在深度优化客户的微信支付,由于使用的是阿里云服务器做数据中转,结果发现,发起支付一直到支付完成,全部状态返回都是SUCCESS;

可是,在处理回调处理的时候,执行的方法里获取XML数据;始终都是FALSE;

你妹的,我写了无数个微信、支付宝登陆和支付接口,一直没出现过这个问题;

结果用了个自己私人的国内服务器,IP解析之后进行测试,一切问题解决了!

我想问问,是腾讯你不对回调数据下发回给支付宝?还是支付宝的母体主机限制了微信支付的回调POST的XML数据?

一个半斤一个八两,是否都算是废物?

通过清心醉

网站进阶-什么叫并发-什么叫访问量

首先一张图,来看看常规的WEB请求:

bingfa

 

以上规则,为每一个用户的请求,包括建立HTTP协议连接;

何为并发?并发其实就是短暂时间内进行访问,比如1-3秒内同时2000个用户执行以上操作,就是2000个实际并发;
何为访问量?访问量为非同一短暂时间内进行服务器的访问,比如有100个用户是17:00访问,又有100个用户是17:01分访问,实际2分钟内就有200个访问量,但实际并发量只有100;
注:高并发如果为真实用户访问即会消耗系统、带宽等资源;如果非法访问,就是所谓的DDOS攻击,即1秒内发起10000+的伪用户进行网站访问,消耗服务器所有资源,导致其他用户打不开,包括服务器宏机!

 

附:

针对高并发,吞吐量来说,大家都知道使用NGINX,因为占用内存资源少,如果是APACHE,会浪费过多的内存资源,基于带宽来说,消费的基本都是同等的!

通过清心醉

开源一个高德地图地理位置获取API

<?php
/***
*
#–地图位置计算类库
$ipanying = new ipanying(); //实例化地图类库

#–构造商家数据坐标集
$data =array(
0 =>array(
‘mid’=>’111’,
‘lng’=>’111.111’,
‘lat’=>’22.22’
),
1 =>array(
‘mid’=>’112’,
‘lng’=>’112.112’,
‘lat’=>’23.23’
)
);

#–数据回调URL,把计算出的用户与商家的实际距离进行AJAX请求该URL
$return_url = ‘http://’.$_SERVER[‘HTTP_HOST’].’/ipanying.php’;
echo $ipanyingmap->getUserDir($data, $return_url, ‘color:red’);
*/
class ipanying{

/***
*
* @param unknown $ipanying #–商家地理位置二维数组
* @param unknown $return_url #–计算出的距离的数据AJAX请求URL
* @param unknown $style #–INPUT样式
* @param string $text #–显示的文字,比如没获取之前可以说获取位置,获取成功之后可以是更新位置等
* @param string $key #–KEY密钥
* @return string #–返回一个JS代码的页面字符串
* 注:在return接收页,lng,lat实际为用户的坐标数据,type=’dir’,
* 获取数据之后,销毁POST的lng,lat,type
*/
function getUserDir($ipanying,$return_url,$style,$text=’获取位置’,$key=’您的KEY值’){
$html='<script type=”text/javascript” src=”ipanying.js”></script>’;
$html.=”
<script type=’text/javascript’ src=’http://webapi.amap.com/maps?v=1.3&key=”.$key.”‘></script>
<script>
var usermap, geolocation;
var ipanyingmap_url='”.$return_url.”‘;
function getAddress(){
usermap = new AMap.Map(‘container-ipanying’, {
resizeEnable: true
});

usermap.plugin(‘AMap.Geolocation’, function() {
var geolocation = new AMap.Geolocation({
enableHighAccuracy: true,
timeout: 10000,
buttonOffset: new AMap.Pixel(10, 20),
zoomToAccuracy: true,
buttonPosition:’RB’
});
usermap.addControl(geolocation);
geolocation.getCurrentPosition();
AMap.event.addListener(geolocation, ‘complete’, onComplete);
});
}
//解析定位结果
function onComplete(data) {
var lng = data.position.getLng();
var lat = data.position.getLat();
if(lng==null || lng==undefined || lat==null || lat==undefined){
alert(‘用户坐标为空,无法计算’);
return false;
}
var ipanying = new Array();
“;

#—循环输出商家数据到JS
for($k=0;$k<count($ipanying);$k++){
$html.=”ipanying[$k]=new Array();
ipanying[$k][‘mid’]=”.$ipanying[$k][‘mid’].”;
ipanying[$k][‘dir’] = [“.$ipanying[$k][‘lng’].”,”.$ipanying[$k][‘lat’].”];”;
}

$html.=”
shangjiamaps(ipanying,lng,lat);
} //onComplete结束

function shangjiamaps(lnglats,xdir,ydir){ //位置计算方法
var str =’lng=’+xdir+’&lat=’+ydir;
for (var i = 0; i < lnglats.length; i++) {
var marker = new AMap.Marker({
position: lnglats[i],
//map: map
});
if(xdir == ” || xdir == undefined || xdir==null || ydir == ” || ydir == undefined || ydir==null){
var isadd =’nulls’;
} else {
var islnglat = new AMap.LngLat(xdir,ydir);
var cl = islnglat.distance(lnglats[i][‘dir’]);
var isadd = cl.toFixed(0);
}
str +=’&’+lnglats[i][‘mid’]+’=’+isadd;
//alert(‘距离商家ID’+lnglats[i][‘mid’]+’有’+isadd+’米’);
}
qingxinzui_alert(ipanyingmap_url,str,’dir’);
//alert(str);
}
</script>”;
$html.='<input type=”submit” onclick=”getAddress();” value=”‘.$text.'” style=”‘.$style.'” />’;
return $html;
}
}

if(isset($_POST[‘type’]) && $_POST[‘type’]==’dir’){
//处理回调
unset($_POST[‘type’]; //销毁类型参数

$userlng=$_POST[‘lng’]; //提取用户经度
$userlat=$_POST[‘lat’]; //提取用户纬度
//在这里获取的用户经纬度信息自行保留至SESSION或者COOKIE或者SQL

unset($_POST[‘lng’]); //销毁POST经度
unset($_POST[‘lat’]); //销毁POST纬度
$ipanying = $_POST; //数据给予数组
$text = ”;
foreach($ipanying as $key => $value){
$text.=’用户距离商家ID’.$key.’的直线距离=’.$value.’米 <br \>’;
}
}

 

扩展类库下载:高德地图距离计算类库PHP版

请尊重开源,转发请注明出处!

通过清心醉

LANMP负载均衡之静态文件的分发

好久没看负载均衡了,以前自己的框架站点因为CSS和JS文件的集中分散在站内的多处目录,为了可以更好的兼容负载均衡,让CSS和JS以及GOOGLE字体和其他样式文件放在第二个服务器来实现网络带宽的分发负载,特写此文章!

我们要载入css文件的话,一般都会以目录形式,还有就是域名方式。而后者就是流量负载均衡常用的写法。

比如义个qingxinzui.css文件

我可以放在根目录内,

直接请求的URL为./qingxinzui.css

如果为域名请求,为qingxinzui.com/qingxinzui.css

很明显,如果域名替换成其他的域,就可以实现静态文件的负载调用!

由于是测试服务器,所以有时会出现“已阻止跨源请求:同源策略禁止读取“的错误请求信息,原因是头部进行请求的时候,文件所属的IP、域、地址都是相同的。

要解决也很简单,当然了这是静态文件负载均衡的重中之重了

<VirtualHost 127.0.0.1:1688>
DocumentRoot /var/www/qingxinzui
ServerName qingxinzui.com
</VirtualHost>
<Directory “/var/www/qingxinzui”>
Header set Access-Control-Allow-Origin *
Options Indexes FollowSymLinks ExecCGI Includes
AllowOverride All
Require all granted
</Directory>

由于作者的程序是在动态载入CSS/JS文件的,而服务器使用NGINX反响请求APACHE模式,所以修改后端的APAHCE就可以了,因为PHP解析完成之后仍然会生成伪静态文件。

如果你的是NGINX为前后服务器,直接修改NGINX的配置,语法转换下就可以了!

附带一提:Header set Access-Control-Allow-Origin *,这里的*表示服务器可以分发请求的所有域,建议实际线上服务器写上自己认为合法的域名!

通过清心醉

微信公众平台开发-redirect_uri参数错误

中国的IT技术难道真那么的菜吗?以前做微信开发的时候老是被redirect_uri 参数错误给困扰,百度、必应、GOOGLE搜索了下,全部都说哪设置哪设置,谁都知道是要怎么怎么的设置!口水多过茶。同时也鄙视下垃圾腾讯,一个简单的回调,就不能在你那边的服务端进行下301?

回到主题:redirect_uri在开发中,属于回调的URL地址,该地址的域必须和公众号后台设置是一样的没错。

但国内现在很多所谓的微信平台,就是你妹的小白!说你们强能开发出第三方管理,却没能力解决最基本的数据域回调问题!

微信设置授权域为:www.qingxinzui.com

然后如果请求为www.qingxinzui.com肯定没问题。

如果请求为qingxinzui.com,就出错了,可是国内垃圾微信第三方管理平台,却也不懂301的设置。

解决的方法是:在站点根目录

vi .htaccess  #如果文件存在就追加写入

RewriteEngine On

RewriteBase /

RewriteCond %{HTTP_HOST} ^qingxinzui.com [NC]

RewriteRule ^(.*)$ http://www.qingxinzui.com/$1 [L,R=301]

记得开启Rewrite模块,具体的看你的是NGINX还是APACHE来搜索!

别问哥是谁,哥是一个神话!在哥公布正确答案以前那些所谓的微信redirect_uri参数错误解决方案还没想到这个问题的!哥只能说,你们技术只能是这么点!

别只从程序的角度上考虑开发问题,一个好的程序员,是在系统为基础,I/O、数据为负载做前提!

2016-06-19 12:08:36

 

通过清心醉

开源一个B2B多域名独立SEO站点的伪静态规则

该多站多域名服务器集群独立SEO伪静态规则由作者“清心醉”独立编写,转发请注明出处!

您对开源的尊重,让更多一个人尊重源代码的原始作者!

function rewrite($link) {
$url_info = parse_url(str_replace(‘&amp;’, ‘&’, $link));
$url = ”;
$product_id=null; #–定义产品ID  //平台直接跳转
$data = array();
parse_str($url_info[‘query’], $data);
foreach ($data as $key => $value) {
if (isset($data[‘ipanying’])) {
if (($data[‘ipanying’] == ‘product/product’ && $key == ‘product_id’)
|| (($data[‘ipanying’] == ‘product/manufacturer/info’ || $data[‘ipanying’] == ‘product/product’) && $key == ‘manufacturer_id’)
|| ($data[‘ipanying’] == ‘information/information’ && $key == ‘information_id’)
|| ($data[‘ipanying’] == ‘ckz/word/word’ && $key==’word_id’ )  ) {

if ($data[‘ipanying’] == ‘product/product’ && $key == ‘product_id’ && STORE_ID==0){ #–如果为产品ID并且是平台的话
$product_id=$value;
}
$query = $db->query(“SELECT * FROM ” . DB_PREFIX . “url_alias WHERE `query` = ‘” . $db->escape($key . ‘=’ . (int)$value) . “‘”);

if ($query->num_rows && $query->row[‘keyword’]) {
$url = ‘/’ . $query->row[‘keyword’];

unset($data[$key]);
}
} elseif ($key == ‘path’) {
$categories = explode(‘_’, $value);

foreach ($categories as $category) {
$query = $db->query(“SELECT * FROM ” . DB_PREFIX . “url_alias WHERE `query` = ‘category_id=” . (int)$category . “‘”);

if ($query->num_rows && $query->row[‘keyword’]) {
$url = ‘/’ . $query->row[‘keyword’];
} else {
$url = ”;

break;
}
}

unset($data[$key]);

} elseif ($key == ‘ipanying’) {
$query = $db->query(“SELECT * FROM ” . DB_PREFIX . “url_alias WHERE `query` = ‘” . $db->escape($value) . “‘”);
if ($query->num_rows) {
$url = ‘/’ . $query->row[‘keyword’];
unset($data[$key]);
}
}
}
}

if ($url) {
unset($data[‘ipanying’]);

$query = ”;

if ($data) {
foreach ($data as $key => $value) {
$query .= ‘&’ . rawurlencode((string)$key) . ‘=’ . rawurlencode((string)$value);
}

if ($query) {
$query = ‘?’ . str_replace(‘&’, ‘&amp;’, trim($query, ‘&’));
}
}

//if (STORE_ID==0 && !empty($product_id)){
if (STORE_ID!=0){ #-如果非平台
$product_url=$model->getStoreUrl(STORE_ID); #-强制获取店铺URL
$url=str_replace(‘/’,”,$url);  #– 提取URL
return $product_url. $url . $query; #– 返回拼接URL
}  else if(STORE_ID==0 && !empty($product_id)){ #如果是平台并且有产品调用(因为产品是二级域名)
$store_id=$model->getProductAsStore($product_id); #– 获取产品对应的店铺ID
$product_url=$model->getStoreUrl($store_id); #– 根据店铺ID获取网站URL
$url=str_replace(‘/’,”,$url);  #– 因为店铺URL中已经存在‘/’符号,所以进行删除
return $product_url. $url . $query; #– 返回拼接URL
}  else {
return $url_info[‘scheme’] . ‘://’ . $url_info[‘host’] . (isset($url_info[‘port’]) ? ‘:’ . $url_info[‘port’] : ”) . str_replace(‘/index.php’, ”, $url_info[‘path’]) . $url . $query; #-否则就是平台而且无PRODUCT产品的时候的平台直属URL
}

} else {
return $link;
}
}

 

调用的模型类中其实就是对数据库的操作!

$store_id=$model->getProductAsStore($product_id); #– 获取产品对应的店铺ID
$product_url=$model->getStoreUrl($store_id); #– 根据店铺ID获取网站URL

根据自己定义的实际URL来进行

该处代码为平台显示二级域名的产品时所产生伪静效果