竹磬网-邵珠庆の日记 生命只有一次,你可以用它来做些更多伟大的事情–Make the world a little better and easier


65月/180

Redis内存分析方法

发布在 邵珠庆

一般会采用 bgsave 生成 dump.rdb 文件,再结合 redis-rdb-tools 和 sqlite 来进行静态分析。

BGSAVE:在后台异步(Asynchronously)保存当前数据库的数据到磁盘。

BGSAVE 命令执行之后立即返回 OK ,然后 Redis fork 出一个新子进程,原来的 Redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。

生成内存快照:redis-rdb-tools 是一个 python 的解析 rdb 文件的工具,在分析内存的时候,主要用它生成内存快照。

redis-rdb-tools 安装:

使用 PYPI 安装:

pip install rdbtools

使用 源码安装:

git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
sudo python setup.py install

使用 redis-rdb-tools 生成内存快照:

rdb -c memory dump.rdb > memory.csv

生成 CSV 格式的内存报告。包含的列有:数据库 ID,数据类型,key,内存使用量(byte),编码。内存使用量包含 key、value 和其他值。

内存使用量是理论上的近似值,在一般情况下,略低于实际值。

[ares:~/Desktop$head memory.csv
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,string,trade.coupon.id:653601465,112,string,8,8
0,string,trade.coupon.id:631354838,112,string,8,8
0,string,trade.coupon.id:632477800,112,string,8,8
0,string,trade.coupon.id:620802294,112,string,8,8
0,string,trade.coupon.id:631432959,112,string,8,8
0,string,trade.coupon.id:632933399,112,string,8,8
0,string,trade.coupon.id:632117725,112,string,8,8
0,string,trade.coupon.id:634240609,112,string,8,8
0,string,trade.coupon.id:646317603,112,string,8,8

注:若csv文件不大,可直接用相关软件打开,以size_in_bytes列排序,可以看到大致内存使用。

使用SQLite分析内存快照:

SQLite版本必须是3.16.0以上。

导入memory.csv数据库:

$sqlite3 memory.db
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
sqlite> create table memory(database int,type varchar(128),key varchar(128),size_in_bytes int,encoding varchar(128),num_elements int,len_largest_element varchar(128));
sqlite> .mode csv memory
sqlite> .import memory.csv memory

数据导入后,可以随处理:

查询key总数:

sqlite> select count(*) from memory;
31143847

查询key总占用内存:

sqlite> select sum(size_in_bytes) from memory;
17391950414.0

查询内容占用最高的几个key:

sqlite> select key,size_in_bytes from memory order by size_in_bytes desc limit 10;
key,size_in_bytes
public.xx.xx:xx,7860169636
public.xx.xx:xx,3043206524
public.xx.xx:xx,1866022916
public.xx.xx:xx,420931316
public.xx.xx:idxx171118172
xx,162984940
xx,133443892
public.xx.xx:xx,80925132
public.xx.xx:xx,28340356
171月/170

PHP生成随机红包高级方法

发布在 邵珠庆

/** 传输数字必须为正整数,需要小数通过$bonus_float传值进行换算
* @param $bonus_total (必填) 红包总额
* @param $bonus_count (必填) 红包个数
* @param $bonus_max   (选填) 每个小红包的最大额 最大值要大于平均值
* @param $bonus_min   (选填) 每个小红包的最小额
* @param $bonus_float (选填 Y元J角F分) 红包传入单位
* @return 存放生成的每个小红包的值的一维数组
*/
function getBonus($bonus_total, $bonus_count=20, $bonus_max=0, $bonus_min=1, $bonus_float='Y') {
    $total_money  = 0;
    $arr1         = array();
    $arr2         = array();
    $res          = array();
    // 转换传入金额单位 Y元 J角 F分
    $tmp_float    = $bonus_float;
    if($bonus_float=='Y'){ $bonus_float = 1;   $num_fmt  = 0;}
    if($bonus_float=='J'){ $bonus_float = 10;  $num_fmt  = 1;}
    if($bonus_float=='F'){ $bonus_float = 100; $num_fmt  = 2;}
    // 每人红包平均值
    $average = $bonus_total / $bonus_count;
    // 防止传入参数越界
    if($average > $bonus_max){ echo $bonus_max = round(($bonus_total-$average)/$bonus_count,0)+round($average,0);   }
    if($average < $bonus_min){ echo $bonus_min = 1; }
    $range1  = ($average - $bonus_min)*($average - $bonus_min);
    $range2  = ($bonus_max - $average)*($bonus_max - $average);
    // 生成随机红包逻辑
    for ( $i = 0; $i < $bonus_count; $i++) {         if (rand($bonus_min, $bonus_max) > $average) {
            $temp         = $bonus_min + intval(sqrt(rand(0, (intval($range1)-1))));
            $arr1[$i]   = $temp;
            $bonus_total -= $temp;
        } else {
            $temp         = $bonus_max - intval(sqrt(rand(0, (intval($range2)-1))));
            $arr1[$i]   = $temp;
            $bonus_total -= $temp;
        }
    }
    while ($bonus_total > 0) {
        for ($i = 0; $i < $bonus_count; $i++) {             if ($bonus_total > 0 && $arr1[$i] < $bonus_max) {
                $arr1[$i]++;
                $bonus_total--;
            }
        }
    }
    while ($bonus_total < 0) {
        for ($i = 0; $i < $bonus_count; $i++) {
            if ($bonus_total < 0 && $arr1[$i] > $bonus_min) {
                $arr1[$i]--;
                $bonus_total++;
            }
        }
    }
    // 输出格式化数据结果
    for ($i = 0; $i < $bonus_count; $i++) {
        $arr1[$i]     = number_format($arr1[$i]/$bonus_float,$num_fmt,'.','');
        //统计每个钱数的红包数量,检查是否接近正态分布
        $total_money += $arr1[$i];
        if(isset($arr2[$arr1[$i]])){  $arr2[$arr1[$i]] += 1; }else{ $arr2[$arr1[$i]]  = 1; }
    }
    ksort($arr2);

    $res["total"] = $total_money."(Y)";
    $res["bnmax"] = $bonus_max."(".$tmp_float.")";
    $res["bnmin"] = $bonus_min."(".$tmp_float.")";
    $res["money"] = $arr1;
    $res["count"] = $arr2;

    return $res;
}

$bonus_total  = 2000;
$bonus_count  = 30;
$bonus_max    = 90;  //最大值要大于平均值
$bonus_min    = 1;
$bonus_float  = "Y"; //
$result_bonus = getBonus($bonus_total, $bonus_count,$bonus_max);

echo "

";
print_r($result_bonus);
 
Array
(
    [total] => 2000(Y)
    [bnmax] => 90(Y)
    [bnmin] => 1(Y)
    [money] => Array
        (
            [0] => 74
            [1] => 24
            [2] => 67
            [3] => 73
            [4] => 67
            [5] => 47
            [6] => 69
            [7] => 75
            [8] => 63
            [9] => 44
            [10] => 77
            [11] => 76
            [12] => 70
            [13] => 76
            [14] => 76
            [15] => 72
            [16] => 73
            [17] => 85
            [18] => 68
            [19] => 72
            [20] => 76
            [21] => 68
            [22] => 55
            [23] => 67
            [24] => 65
            [25] => 75
            [26] => 70
            [27] => 71
            [28] => 65
            [29] => 40
        )

    [count] => Array
        (
            [24] => 1
            [40] => 1
            [44] => 1
            [47] => 1
            [55] => 1
            [63] => 1
            [65] => 2
            [67] => 3
            [68] => 2
            [69] => 1
            [70] => 2
            [71] => 1
            [72] => 2
            [73] => 2
            [74] => 1
            [75] => 2
            [76] => 4
            [77] => 1
            [85] => 1
        )

)
38月/160

PHP下SSL加密解密、验证、签名方法(很简单)

发布在 邵珠庆

RSA超级简单,依赖于OpenSSL扩展,这里就不多废话了,直接奉上代码

 

签名:
function sign($data) {
//读取私钥文件(签名一定是商户自己本地生成的私钥)
$priKey = file_get_contents('key/rsa_private_key.pem');

//转换为openssl密钥,必须是没有经过pkcs8转换的私钥(不要使用这个私钥rsa_private_key_pkcs8.pem)

$res = openssl_get_privatekey($priKey);

//调用openssl内置签名方法,生成签名$sign
openssl_sign($data, $sign, $res);

//释放资源
openssl_free_key($res);

return $sign;
}
验证:
function verify($data, $sign) {
//读取支付宝公钥文件(一定是阿里后台生成提供的公钥)
$pubKey = file_get_contents('key/alipay_public_key.pem');

//转换为openssl格式密钥
$res = openssl_get_publickey($pubKey);

//调用openssl内置方法验签,返回bool值
$result = (bool)openssl_verify($data, $sign, $res);

//释放资源
openssl_free_key($res);

return $result;

解密
function decrypt($content) {

//读取商户私钥(商户自己生成的私钥)
$priKey = file_get_contents('key/rsa_private_key.pem');

//转换为openssl密钥,必须是没有经过pkcs8转换的私钥
$res = openssl_get_privatekey($priKey);

//声明明文字符串变量
$result = '';

//循环按照128位解密
for($i = 0; $i < strlen($content)/128; $i++ ) {
$data = substr($content, $i * 128, 128);

//拆分开长度为128的字符串片段通过私钥进行解密,返回$decrypt解析后的明文
openssl_private_decrypt($data, $decrypt, $res);

//明文片段拼接
$result .= $decrypt;
}

//释放资源
openssl_free_key($res);

//返回明文
return $result;
}

 

AES密钥是什么

高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是目前对称密钥加密中比较通用的一种加密方式。

AES密钥有什么用

支付宝开放平台所有OpenAPI均支持对接口的请求内容和响应内容进行AES加密,部分OpenAPI(芝麻信用等)强制要求AES加密。加密后,在网络上传输的接口报文内容将会由明文内容变为密文内容,可以大大提升接口内容传输的安全性。

AES密钥与RSA密钥的关系

  • AES密钥是对接口请求和响应内容进行加密,密文无法被第三方识别,从而防止接口传输数据泄露。
  • RSA密钥是对接口请求和响应内容进行签名,开发者和支付宝开放平台分别加签验签,以确认接口传输的内容没有被篡改。不论接口内容是明文还是密文,RSA均可正常签名。
  • 开发者可对请求参数先做AES加密,然后对密文进行RSA签名。
257月/160

Bootstrap表单验证插件bootstrapValidator使用方法整理

发布在 邵珠庆

文档首页 :
http://bv.doc.javake.cn/api/





 
 
$(document).ready(function() {
   
// 原价、现价同时双验证
$("#original_price").blur(function () {
    $("#form_yanzheng").data('bootstrapValidator').resetForm().validateField('price');
});
$("#price").blur(function () {
    $("#form_yanzheng").data('bootstrapValidator').resetForm().validateField('original_price');
});
 
//表单验证
$('#form_yanzheng').bootstrapValidator({
    message: '值没有被验证',
    feedbackIcons: {
        valid: 'glyphicon glyphicon-ok',
        invalid: 'glyphicon glyphicon-remove',
        validating: 'glyphicon glyphicon-refresh'
    },
    fields: {
        subject: {
            message: 'The username is not valid',
            trigger: 'blur', //失去焦点就会触发
            validators: {
                notEmpty: {
                    message: '商品名称不能为空'
                },
                stringLength: {
                    min: 2,
                    max: 15,
                    message: '输入字符数量错误'
                },
                callback: {
                    message: '商品名称有非法内容',
                    callback: function () {
                        var filter = true;
                        var subject = $("#subject").val();
 
                        if (subject.indexOf("储值卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("充值卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("会员卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("vip卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("打折卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("年卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("美容卡") >= 0) {
                            filter = false;
                        }
                        if (subject.indexOf("健身卡") >= 0) {
                            filter = false;
                        }
 
                        return filter;
                    }
                }
            }
        },
        original_price: {
            trigger: 'blur', //失去焦点就会触发
            message: 'The username is not valid',
            validators: {
                notEmpty: {
                    message: '输入整数或者2位小数'
                },
                regexp: {
                    regexp: /^(\d+\.\d{1,2}|\d+)$/,
                    message: '输入整数或者2位小数'
                },
                callback: {
                    message: '原价要大于等于现价',
                    callback: function () {
                        var op = $('#original_price').val();
                        var pp = $('#price').val();
                        return parseFloat(op) >= parseFloat(pp);
                    }
                }
            }
        },
        price: {
            trigger: 'blur', //失去焦点就会触发
            message: 'The username is not valid',
            validators: {
                notEmpty: {
                    message: '输入整数或者2位小数'
                },
                regexp: {
                    regexp: /^(\d+\.\d{1,2}|\d+)$/,
                    message: '输入整数或者2位小数'
                },
                callback: {
                    message: '原价要大于等于现价',
                    callback: function () {
                        var op = $('#original_price').val();
                        var pp = $('#price').val();
                        return parseFloat(op) >= parseFloat(pp);
                    }
                }
            }
        },
        inventory: {
            trigger: 'blur', //失去焦点就会触发
            message: 'The username is not valid',
            validators: {
                notEmpty: {
                    message: '输入整数或者2位小数'
                },
                between: {
                    min: 0,
                    max: 999999,
                    message: '输入有效库存数量'
                }
            }
        },
        validity_period: {
            trigger: 'blur', //失去焦点就会触发
            message: 'The username is not valid',
            validators: {
                notEmpty: {
                    message: '请正确填写有效天数7-360天'
                },
                between: {
                    min: 7,
                    max: 360,
                    message: '请合理输入使用有效期'
                }
            }
        }
    }
}).on('success.form.bv', function (e) {
 
    var refertype = $('#refertype').val();
    var urlpath = "{:U('Index/" + refertype + "')}";
 
    $.ajax({
        type: "POST",
        url: urlpath,
        data: $('#form_yanzheng').serialize(),
        dataType: 'json',
        success: function (data, statusText, xhr, $form) {
            if (data.type == 'true') {
                swal({
                    title: data.info,
                    text: "",
                    type: "success",
                }, function () {
                    self.location = "{:U('Index/index')}";
                });
 
            } else {
                swal(data.info, "", "error");
                return false;
            }
        }
    });
});
});

235月/160

微信开发常见报错及解决方法

发布在 邵珠庆

小技巧:可能过ctrl+f 进行查找您遇到的问题。

支付方式 报错提示 解决方法  
热点问题 支付返回签名错误 注意签名参数的大小写,支付密钥key要到商户平台设置,设置的规则是32位数字与字母大小写的组合。以下链接为签名过程。
(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1)
 
 
支付回调 认证后的服务号之间支持跨号支付。  
支付失败 请检查商户号是否错误或支付密钥key设置错误。  
redirect——uri参数错误 请进入公众平台-开发者中心,找到填写商户的支付授权域名,填写的就是商户支付授权目录上的域名。  
paysinkey如何获取? 新版的微信支付是没有这个paysignkey参数的,具体的参数请查看文档  
(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1)  
mchid是指什么? MCHID参数指的是商户号  
openid的获取请参考文档 openid的获取请参考文档详细介绍  
(http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html)  
openid如何获取? openid的获取请参考文档查看详细介绍:  
(http://mp.weixin.qq.com/wiki/14/bb5031008f1494a59c6f71fa0f319c66.html)  
Appsecret如何获取? APPsecret参数可进入公众平台(https://mp.weixin.qq.com)开发者中心查看。  
调用报错
get_brand_wcpay_request:fail
签名错误,请仔细检查签名。  
spbill_create_ip 是指什么? spbill_create_ip 指的是终端ip,在APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。  
网页支付(JSAPI) “当前公众号没有权限支付本次交易“ 检查该公众帐号是否已经获取了支付资格。  
“公众帐号支付使用了无效的商户号,无法发起该笔交易” 检查商户号使用错误。  
“该公众号支付签名无效,无法发起该笔交易” 调起支付MD5签名的MD5签名错误,请检查相关签名。  
“Args Error” 提交JS时,josn传递参数必须与文档中名字一致,大小写匹配。  
“access:not_allow” 未设置白名单,添加位置:微信公众平台=》微信支付=》开发配置  
点击支付无反应 支付授权目录是否正确,如果使用的是支付测试目录,是否设置了白名单,需白名单帐号进行支付测试。  
ios系统可以正常支付,android系统支付失败 timestamp字段值需要加上“”,传递数据必须为字符串类型。  
调用报错
get_brand_wcpay_request:fail
签名错误,请仔细检查签名。  
调用报错:
zhgj-2014+中涵国际分销商城及“订单满送红包无法送”
商户设置有问题。  
IOS系统调用支付JSAPI报错
缺少参数:$key0$,android 没问题
提交的参数有问题,注意全部参数都得是字符串类型。  
支付验证签名失败 签名错误,仔细检查签名。  
jsapi 缺少参数 key0 问题出在网页端调起支付API接口中timeStamp参数,必须是string类型,但是php默认生成的时间戳是int类型。
解决方法:修改下lib/Wxpay.Data.php约2731行处SetTimeStamp方法,修改为$this->values['timestamp'] = (string)$value;
 
安卓手机可以收到满送红包 苹果的不行 红包虽然已经显示发送了红包但是实质资金流水没有扣除资金 参数错误,请仔细检查。  
调用报错:
传输参数错误
推测为提交的支付请求参数不正确;以下文档有详细的参考。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7  
调用报错:
没有获取到微信支付预支付ID,请管理员检查微信支付配置项
需要按照文档要求 ,先获取prepay_id。  
支付权限检查失败 商户所用的参数对应的APPID是APP支付;如果商户想要JSAPI支付,需要在公众平台申请公众号,公众号支付中才有此参数。  
原生支付(扫码支付) “获取商户数据失败” 请检查申请native支付时的回调URL地址是否正确,是否可以外网访问获取数据。  
“商户返回数据错误” native回调返回数据格式错误,非XML格式数据。  
“签名错误” 检查MD5签名中参数格式及值是否正确。  
调用报错:
获取商户订单信息超时或商户返回httpcode非200
签名错误,请仔细检查签名。  
错误返回:错误码:60 错误通过修改文件:WxPay.Api.php解决,具体如下:
第537行
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TURE);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,2);//严格校验
to
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);//严格校验2
微信支付错误两个问题的解决:curl出错,错误码:60
 
APP支付 错误返回“-1” 开放平台配置的报名和应用签名是否一致:(android);确认是否使用正式的keystore打包apk并安装调试;(android);提交订单部分需要在服务器端完成。  
下单报{"errcode":62621014,"errmsg":""} Package数据MD5签名错误,请参照文档检查。  
下单报"1001"错误 package里缺少必要参数;金额类型为证书,单位是分。  
android签名正常,ios签名错误 需要注意body如果是中文,需要编码,编码格式统一为“UTF-8”。  
支付授权地址没有经过ICP验证 域名需要是英文备案域名方可。(此情况针对备案域名中包含中文字符或其他)  
ios系统:订单成功,无法跳转到支付界面 请仔细查阅参考开发文档步骤。  
支付结果报错:errStr=null,code=-1 请检查开放平台配置的包名和签名是否跟APK安装后的包名签名一致,一致才会调用的。  
支付无法调起 请检查开放平台配置的包名和签名是否跟你的APK安装后的包名签名一致,一致才会调用的。  
需要V3版的app支付服务端demo,因获取prepayId失败,找不到app_key 新版的微信支付是没有这个参数的,请查看最新版文档。  
请求prepayid发生错误:
errcode":268497023,"errmsg
请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。  
支付返回报错:
:"errcode":268497023,"errmsg":"您已完成交易接口升级,老接口交易权限已关闭,请使用新接口进行交易。如有疑问请联系微信支付客服咨询"
请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。  
请求prepayid发生错误:
信息[{"errcode":268497023,"errmsg":"鎮ㄥ凡瀹屾垚浜ゆ槗鎺ュ彛鍗囩骇锛岃 鎺ュ彛浜ゆ槗鏉冮檺宸插叧闂紝璇蜂娇鐢ㄦ柊鎺ュ彛杩涜浜ゆ槗銆傚鏈夌枒闂鑱旂郴寰俊鏀粯瀹㈡湇鍜ㄨ"}]
请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。  
根据文档下订单,调用微信支付失败。调用微信支付的时候,微信为登录状态则无反应;微信未登录状态,会调用微信登录界面。 请将商户的APPID和商户号以及报错截图+请求参数详情,发送至wepayTS@tencent.com,进行深入了解。  
常见问题 申请正在审核中,如何可以提前调试测试? 只需要资料审核通过,收到通知邮件即可通过配置测试目录进行联调测试。未审核通过可下载文档进行开发,但不能联调测试。  
支付授权目录是什么? 支付授权目录是支付功能正式上线后,商户后台发起支付请求的页面所在的目录。  
支付测试目录是什么? 支付测试目录提供给开发者,在开发测试期间使用的临时目录。  
支付测试目录和授权目录有何区别? 支付授权目录将会在产品上线审核时,以及上线后长期使用的正式目录;测试目录只能配置白名单,才可以在公众号内发起支付。  
如何配置支付目录(授权、测试)? 登录微信公众平台-微信支付-开发配置-修改  
支付目录有什么规则? 头部需要包含http或https,须细化到二级或三级目录,字母小写,以左斜杠“/”结尾。  
如何配置授权回调页面域名? 登录微信公众平台=》开发者中心=》网页授权获取用户基本信息=》修改  
微信支付接口的签名规则是如何的? MD5签名,订单数据签名,所有传输的字段均需要参与签名,使用商户密钥key在签名字段排序后放入在最后组包签名。  
 “订单数据签名验证失败”如何解决? 检查参数是否一致;是否含有特殊字符;中文编码类型是否与所传参数一致;body参数是否含空格,若有空格URLencode的时需要转为%20。  
报40001错误,如何解决? accesstoken失效或者过期,accesstoken有效期为2小时,如果有系统或者人为重新获取,前一个accesstoken也会自动消失。请保证accesstoken为全局管理,避免重复获取。  
签名正常,却提示fail_invalid appid 查看支付授权目录是否设置正确,所支付页面路径是否在支付授权目录下。  
公众号是否可以跨号支付? 两个具有支付权限的服务号之间可以跨号支付,但不可混淆appid。  
支付完成,Notify URL无法接收回调通知 需要绝对路径,外网可访问,不支持非80端口,同时注意不要被防火墙拦截;可自行用fiddler模拟post访问是否正常。  
查询订单接口报“errcode":49001,"errmsg": 检查accesstoken是否为同一APPID获取;POST数据必须为JSON格式,  
"not same appid with appid of access_token"错误如何解决? 避免格式不对导致获取APPID不一致。  
支付提示“系统繁忙,请稍后再试” 检查签名及传入参数是否与文档要求一致;尤其是MD5签名部门的正确性。  
调用支付报错【特殊】 调用报错:
“chooseWXPay:fail”
此情况需要商户将提交的签名过程发送至邮箱:wepayTS@tencent.com,进行深入了解。  
调用报错:
“{return_msg=支付权限检查失败, return_code=FAIL}”
此情况需要将提交的xml发送至邮箱:wepayTS@tencent.com,进行深入了解。  
zhgj-2014+中涵国际分销商城及“订单满送红包无法送” 请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。  
微信支付完成后不能执行回调 请将商户的APPID和商户号以及报错截图发送至wepayTS@tencent.com,进行深入了解。  
报错:不允许跨号支付
ios上没这个问题,android上有些商品有这个问题
是否通过订阅号发出此请求,请将APPID,商户号,报错截图及请求参数发送至wepayTS@tencent.com,进行深入了解。  
264月/160

file_get_contents(“php://input”)的使用方法

发布在 邵珠庆

$data = file_get_contents("php://input");

    php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。 

    

 

1, php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据。但是,一般GET方法提交数据 时,http request entity body部分都为空。 

2,php://input 与$HTTP_RAW_POST_DATA读取的数据是一样的,都只读取Content-Type不为multipart/form-data的数据。

学习笔记

 1,Coentent-Type仅在取值为application/x-www-data-urlencoded和multipart/form-data两种情况下,PHP才会将http请求数据包中相应的数据填入全局变量$_POST 

 2,PHP不能识别的Content-Type类型的时候,会将http请求包中相应的数据填入变量$HTTP_RAW_POST_DATA 

 3, 只有Coentent-Type为multipart/form-data的时候,PHP不会将http请求数据包中的相应数据填入php://input,否则其它情况都会。填入的长度,由Coentent-Length指定。 

 4,只有Content-Type为application/x-www-data-urlencoded时,php://input数据才跟$_POST数据相一致。 

 5,php://input数据总是跟$HTTP_RAW_POST_DATA相同,但是php://input比$HTTP_RAW_POST_DATA更凑效,且不需要特殊设置php.ini 

 6,PHP会将PATH字段的query_path部分,填入全局变量$_GET。通常情况下,GET方法提交的http请求,body为空。

 

例子

 1.php用file_get_contents("php://input")或者$HTTP_RAW_POST_DATA可以接收xml数据

 比如:

  getXML.php;//接收XML地址

  

<?php 

     $xmldata = file_get_contents("php://input"); 

     $data = (array)simplexml_load_string($xmldata); 

?> 

 

  这里的$data就是包含xml数据的数组,具体php解析xml数据更新详细的方法

  sendXML.php

 

<?php 

     $xml = '<xml>xmldata</xml>';//要发送的xml 

     $url = 'http://localhost/test/getXML.php';//接收XML地址 

 

     $header = 'Content-type: text/xml';//定义content-type为xml 

     $ch = curl_init(); //初始化curl 

     curl_setopt($ch, CURLOPT_URL, $url);//设置链接 

     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置是否返回信息 

     curl_setopt($ch, CURLOPT_HTTPHEADER, $header);//设置HTTP头 

     curl_setopt($ch, CURLOPT_POST, 1);//设置为POST方式 

     curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);//POST数据 

     $response = curl_exec($ch);//接收返回信息 

     if(curl_errno($ch)){//出错则显示错误信息 

     print curl_error($ch); 

     } 

     curl_close($ch); //关闭curl链接 

     echo $response;//显示返回信息 

?> 

 

 2.一个手机上传图片到服务器的小程序

  上传文件

   

<?php 

     //@file phpinput_post.php 

     $data=file_get_contents('btn.png'); 

     $http_entity_body = $data; 

     $http_entity_type = 'application/x-www-form-urlencoded'; 

     $http_entity_length = strlen($http_entity_body); 

     $host = '127.0.0.1'; 

     $port = 80; 

     $path = '/image.php'; 

     $fp = fsockopen($host, $port, $error_no, $error_desc, 30); 

     if ($fp){ 

        fputs($fp, "POST {$path} HTTP/1.1\r\n"); 

        fputs($fp, "Host: {$host}\r\n"); 

        fputs($fp, "Content-Type: {$http_entity_type}\r\n"); 

        fputs($fp, "Content-Length: {$http_entity_length}\r\n"); 

        fputs($fp, "Connection: close\r\n\r\n"); 

        fputs($fp, $http_entity_body . "\r\n\r\n"); 

 

        while (!feof($fp)) { 

         $d .= fgets($fp, 4096); 

        } 

        fclose($fp); 

        echo $d; 

     } 

?> 

 

  接收文件

  

<?php 

        /** 

         *Recieve image data 

        **/    

        error_reporting(E_ALL); 

 

     function get_contents() {    

        $xmlstr= file_get_contents("php://input"); 

        $filename=time().'.png'; 

        if(file_put_contents($filename,$xmlstr)){ 

         echo 'success'; 

        }else

         echo 'failed'; 

        } 

        } 

        get_contents(); 

?>

 3.获取HTTP请求原文

  

/** 

     * 获取HTTP请求原文 

     * @return string 

     */ 

    function get_http_raw() { 

     $raw = ''; 

 

     // (1) 请求行 

     $raw .= $_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI'].' '.$_SERVER['SERVER_PROTOCOL']."\r\n"; 

 

     // (2) 请求Headers 

     foreach($_SERVER as $key => $value) { 

        if(substr($key, 0, 5) === 'HTTP_') { 

         $key = substr($key, 5); 

         $key = str_replace('_', '-', $key); 

 

         $raw .= $key.': '.$value."\r\n"; 

        } 

     } 

 

     // (3) 空行 

     $raw .= "\r\n"; 

 

     // (4) 请求Body 

     $raw .= file_get_contents('php://input'); 

 

     return $raw; 

}

185月/150

web页面快速生成二维码的两种实用方法

发布在 邵珠庆

二维码是桌面和移动端快速分享的高效手段之一,这里介绍两个不错的快速开发二维码的方法,和大家分享一下~~

方法1:使用新浪提供的服务

这种方式简单快速,在服务端生成一个二维码的图片,兼容性比较好,你无需自己处理任何相关二维码的生成,只需要提供一端文字或者url即可,方法如下:

生成效果如下:

大家扫一扫就可以访问极客标签主站了~~

方法2: 使用jQuery插件qrcode

QRcode是一个jQuery插件,可以使用javascript快速帮助你生成相关的二维码

 相关代码如下:

  1. var qrcode = new QRCode("qrcode", {
  2. text: "http://www.gbtags.com",
  3. width: 260,
  4. height: 260,
  5. colorDark: '#efb73e',
  6. colorLight: "#ffffff"
  7. });

生成效果如下:

如果对这个插件有兴趣,推荐阅读这节课程: QRcode的使用

以上是两种比较实用的生成二维码的方法, 懒人推荐使用第一种, 简单快速, 如果需要深度自定义的话,推荐自己使用JS来实现相关的二维码,具体看大家需求, 极客标签的代码分享使用的是第一种,大家可以参考一下,如下:

710月/140

linux下mysql的root密码忘记解决方法

发布在 邵珠庆

1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库。 
因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 
状态下,其他的用户也可以任意地登录和修改MySQL的信息。可以采用将MySQL对 
外的端口封闭,并且停止Apache以及所有的用户进程的方法实现服务器的准安全 
状态。最安全的状态是到服务器的Console上面操作,并且拔掉网线。 
2.修改MySQL的登录设置: 
# vi /etc/my.cnf 
在[mysqld]的段中加上一句:skip-grant-tables 
例如: 
[mysqld] 
datadir=/var/lib/mysql 
socket=/var/lib/mysql/mysql.sock 
skip-grant-tables 
保存并且退出vi。 
3.重新启动mysqld 
# /etc/init.d/mysqld restart 
Stopping MySQL: [ OK ] 
Starting MySQL: [ OK ] 
4.登录并修改MySQL的root密码 
# /usr/bin/mysql 
Welcome to the MySQL monitor. Commands end with ; or g. 
Your MySQL connection id is 3 to server version: 3.23.56 
Type 'help;' or 'h' for help. Type 'c' to clear the buffer. 
mysql> USE mysql ; 
Reading table information for completion of table and column names 
You can turn off this feature to get a quicker startup with -A 
Database changed 
mysql> UPDATE user SET Password = password ( 'new-password' ) WHERE User = 'root' ; 
Query OK, 0 rows affected (0.00 sec) 
Rows matched: 2 Changed: 0 Warnings: 0 
mysql> flush privileges ; 
Query OK, 0 rows affected (0.01 sec) 
mysql> quit 
Bye 
5.将MySQL的登录设置修改回来 
# vi /etc/my.cnf 
将刚才在[mysqld]的段中加上的skip-grant-tables删除 
保存并且退出vi。 
6.重新启动mysqld 
# /etc/init.d/mysqld restart 
Stopping MySQL: [ OK ] 
Starting MySQL: [ OK ]

Work for fun,Live for love!
MySQL远程连接ERROR 2003 (HY000):Can't connect to MySQL server on'XXXXX'(111) 的问题
1.查看配置文件:
skip-networking #注释掉 因为它是屏蔽掉一切TCP/IP连接
bind-address = 127.0.0.1 #它和上一个选项是异曲同工,要想远程连接,也得注释掉
2.如果以上工作都做过还是出现:
ERROR 2003 (HY000): Can't connect to MySQL server on '*.*.*.*' (113),那就得考虑防火墙的问题了,关掉防火墙/etc/rc.d/init.d/iptables stop
修改完后需要 restart mysql (/etc/init.d/mysql restart) 

278月/130

寻找纳什均衡点的方法

发布在 邵珠庆

相对于那本《写给中国人的经济学》,这本《妙趣横生博弈论》对纳什均衡的介绍显然更清楚,自然也更容易理解。原书第4章——美丽的均衡中第85页开始如此写到:“如果有这样的博弈结果,即,给定关于对方行动的信念,每个参与者的行动是其对其他人行动的最优反应,而且每个参与者的行动与对方关于其行动的信念是一致的,那么这类博弈结果就可以巧妙地解开‘我认为他认为’的循环。这样的结果有一个非常好的名号,叫参与人思维过程的静止点,或者叫做博弈的均衡。是的,这正是纳什均衡的定义。”

嗯,只看这段话根本不知道什么是纳什均衡,更具体的例子才能让人理解。这里不纠结什么是纳什均衡,只针对书中一例,说说怎么寻找纳什均衡点,因为我对于后文所介绍的“逐步剔除法”不是很理解,我喜欢的方法和再后面99页的连续数值的方法更相似一些。

原例如下(简化):

两个存在竞争关系的衬衫生产公司彩虹之巅(RE)和比比里恩(BB)要为自己生产的衬衫定价,他们生产一件衬衫的成本都是20元,当两家公司都定价42元时,分别可以销售出1960件,于是,他们分别可以获得的利润为(42-20)×1960=43120元。

现在开始,一家公司每降低1元,如果另外一家公司维持原价,降价的公司就可以多获得100个新客户,其中,20个是新增加的边际顾客,另外80个顾客是从维持原价的公司争取过来的;但是,如果另外一个公司也降低了1元,先降价的公司就没法争取到那80个顾客,取而代之的是,两家公司都分别增加20个边际顾客。

将两个公司的衬衫定价按照1元的减少量,从42元变动到38元,他们的博弈组合如下图所示:

如上图所示,每个单元格中,右上角是BB公司的利润,左下角是RE公司的利润。

其中填充蓝色的单元格就是纳什均衡点,在这里,两家公司的利润都是40000元,对两家公司而言都是一个稳定的结果,从这个点向四周改变,或者对两家公司或者都不利,或者对其中一家不利,只要有一方感觉不划算,就会调整价格,那个点就不会稳定,而只有这个点是很稳定的。

寻找的方法:

这里对纳什均衡点说不出更高深的解释,只是根据对纳什均衡点的理解,说说寻找它的方法吧,至少我试过几个例子,都没有发现错误。步骤如下:

  • 1.从BB的定价开始,在其定价确定的前提下,分别从每一列中寻找对RE公司而言,利润最高的单元格,然后将这些单元格连接起来,就是图中的紫色曲线;
  • 2.从RE的定价开始,在其定价确定的前提下,分别从每一行中寻找对BB公司而言,利润最高的单元格,然后将这些单元格连接起来,就是图中的黄色曲线;
  • 3.两条曲线的交点就是纳什均衡点。

最后,两条曲线的交点有多少个,该博弈就有多少个纳什均衡点,本章所介绍的石器时代猎人狩猎会合的博弈被称为“确信博弈”,按照书中的介绍,这不同于前章的“囚徒困境”博弈:因为“囚徒困境”对一方而言,无论对方的选择如何,自己始终存在“优势策略”;而“确定博弈”只有双方选择相同才是“优势策略”。

看上去,“囚徒困境”好像是“确信博弈”的特例,但是将博弈表列举出来才会发现,仅仅因为某些数字的变化,两者还是有着很大的区别。例如:对比58页“囚徒困境”案例中,同样是上述两家公司的处境,由于在对手公司不降价的前提下作出降价选择,会让降价公司获取巨大的利益,所以,追求利益的公司几乎不可能会对手保持不降价的一致选择。

结果,在“囚徒困境”中,按照上述寻找纳什均衡点的方法操作,同样会发现这样一个点(按照我的理解,这个点应该也是纳什均衡点!),一个双方都选择背叛后沦落的全部失利的下场,对于“确信博弈”而言,只有双方选择一直,哪怕是所谓的“背叛”,大家仍然可以获得最好的结果,唯一的区别恐怕只是,当存在多个纳什均衡点时,哪个才是“聚焦点”的问题。

————————

继续阅读本书发现,回味纳什均衡,其中“同时行动”的意味深长,倘若换成“序贯行动”,即后者可以根据前者的选择再决定行动,而前者无法针对后者的选择重新调整,这种情况下去找出的纳什均衡点,可并不是个好的选择(参见原书第6章策略行动中,晚上的自己设定闹钟叫醒清晨的自己,本应该用博弈树分析的例子换成博弈表之后,作者分析的过程和结果。)~甚至,我怀疑这种博弈是否存在纳什均衡点……继续读下去吧~

107月/130

项目经理问:我怎么有做不完的事情 – 事件篮方法

发布在 邵珠庆

如何管理好自己的时间

原创文章,如有转载,请注明出处:http://blog.csdn.net/yihui823/article/details/6826353

时间管理,本身就是一门艺术。时间是最公平的,每个人的时间都是一样的。如何在相同的时间里,做出不同的事业,这就是个人水平的体现。

一、     故事

这里先讲一个故事。故事是抄来的,我修改了其中的一部分,使其更贴近我要说的主题。

有两个和尚他们分别住在相邻的两座山上的庙里。左边的山上住着瘦和尚,右边山上住着胖和尚。这两座山之间有一条溪,于是这两个和尚每天都会在同一时间下山去溪边挑水,久而久之他么变成为了好朋友。两个和尚都喜欢游泳。胖和尚经常在挑水的时候,顺便游上那么一会儿,而瘦和尚却极少在溪水里游泳。

不知不觉五年过去了。有一天,瘦和尚竟然没有带扁担来挑水,而是直接在溪里面游泳。胖和尚很纳闷,就问瘦和尚,你今天不挑水,怎么有水喝啊。瘦和尚说,这五年来,我每天做完功课后都会抽空在庙后面挖一口井,即使有时很忙,能挖多少就算多少。如今终于让我挖出井水,我就不用再下山挑水。现在我终于可以放心的游泳了。

于是,每天瘦和尚都可以自在的游泳,而胖和尚还是只能游一会儿就得挑水回庙里。突然有一天,两座庙同时失火了。瘦和尚很快就用井水把火扑灭了。而胖和尚还得跑到溪里面去挑水灭火,结果火灭的时候,庙已经烧掉了一大半了。

接下来,胖和尚每天除了要安排时间挑水,还得花大部分时间去修补破庙。而瘦和尚在游泳之余,还潜心书画。故事完毕。

二、     重要度/紧急度

故事说完了,我们再来重头分析做事情的顺序。

根据重要度和紧急度来区分事件,是一个非常常用的方法。但是,到底什么叫重要,什么叫紧急呢?

重要的事情:对以后的工作生活、对以后的发展等,会产生明显的影响的事情,对目标的达成有显著推动的事情。

紧急的事情:需要立即处理的事情。

 

 

 

我们按照以上的象限图,来说一下事件的重要度和紧急度。

4:即不重要,又不紧急的事情。

即不对以后会产生重要的影响,又不是立即需要处理的事情。类似于和尚的游泳事情。此类事情,一般都是些兴趣爱好,或者受人之托,或者偶然的想法。

3:紧急不重要的事情

只是立即需要处理,但是并不会对将来产生重要影响的事情。类似于和尚的挑水,每天必须做,不做不行,但是做了也就是解决当前问题

2:重要不紧急的事情

不是当前必须要立即处理的,但是对以后会产生深远影响的事情。类似于瘦和尚的挖井,不挖也没事,但是一旦挖成功了,后面就可以不挑水了。如果当前有明确的目标,这类事情可以是对目标达成有明显帮助的事情。

1:重要紧急的事情

当前必须处理,不处理会立刻造成很严重的后果。类似于和尚们的庙失火,不立刻救火,就没有住的地方了。

三、     分类处理

以上的四类事件,该如何分别处理呢?

很显然,最优先做的,是做重要紧急的事情,我想这谁都知道。而且这类事件,一般都是很容易标识出来的,也是非做不可的,人们一般都不会忘掉。

但是,并不是所有的事件都是重要紧急的。重要紧急的事件,一般都是救火类的事件,也就是说,是因为工作不好,或者一些意外造成的。那么,我们的正常工作中,充满了其他三种类型的事件,又应该如何各自的时间分配呢?

同样很显然,不紧急不重要的事情,尽量不要做。但是这个说起来容易,做起来却不容易。因为这类事件既然列出来了,就会有其诱惑性。例如很多人喜欢看电视,喜欢打游戏,喜欢看小说等等。就算在工作中,这类事情也是每个人都喜欢做的事情。很多项目经理会安排自己去编码,就是因为技术出身的,往往就喜欢去编码。所以说,这类事情,需要克制住,一定要克制住自己去做不重要不紧急的事情的冲动。

那么,剩下的2和3,需要怎么处理呢?

一个很普遍也很正常的理解,就是先做紧急不重要的,再做重要不紧急的。

坦率来说,这个想法也很正常。既然事情很紧急,那么我当然需要马上处理。重要不紧急的事情,等有空再说吧。

其实,很不然!

紧急不重要的事情,往往都是些日常的工作,都是或者都是些助人为乐的工作,容易做,周期又短,对将来不会造成多大的影响。也就是说,做了最好,不做也影响不大。但是,重要不紧急的事情,一般都是对将来会造成影响的事情,这类事情,往往都是不愿意做、周期长、难做的事情。

打个比方吧。项目组的新人比较多。项目经理需要整理一份技术培训资料,给新人们集中培训。这个就是重要不紧急的。而新人们有时候碰到问题,就直接跑来找项目经理求助,项目经理需要去帮他们解决问题,这就是紧急不重要。

如果项目经理频繁的打断手头上的事情,去帮新人们解决问题,则技术培训资料迟迟无法做出来,那么新人们的问题就会层出不穷,绵绵不断。这个就是个恶性循环。

如果项目经理能够果断的先出培训资料,争取早日把培训做起来,则问题会逐渐减少,这就是个良性循环。

还有一个更生动的例子。假如你在洗澡,满身都是泡泡,这个时候听到来了一个电话。接电话就是紧急不重要的事情,如果你去做了,结果就是满地的肥皂泡泡要打扫,就造成了一堆的紧急不重要事件。

所以说,要想把时间控制在自己手上,最需要做的事情就是:

重要不紧急

这类事件,周期长,难度大,所以需要日积月累的去坚持。这才是解决问题的王道。

四、     疑点分析

很多人都会说,说起来容易做起来难。我们来分析几个疑点的地方。

1.      紧急不重要的事情层出不穷,怎么办?

还是用刚才那个例子,如果新人们的问题不断,我总不能放任不管吧。

其实,就算你不立即去帮他们解决问题,他们也只是郁闷一阵子而已。这种时候,可以让他们先把问题都整理出来,整理清楚,并尝试着自己解决。然后在某个固定的时间段内(例如每天下午2点到3点之间),你集中帮他们解决即可。或者可以把解决问题的事情分摊在项目的其他几个技术高手身上。

2.      一下子又做不完的事情,总是没有动力去做。

这类事件,一般都不是立马见效的。需要制定一个长期的计划,每天都安排固定的时间去做。不管多少,要保证每天都有进展。

3.      我喜欢做的事情,就没时间做了啊。

    相信我,只有把重要不紧急的事情做完备了,才会有更多的时间去做你喜欢做的事情。瘦和尚挖井成功了,就会有更多的时间游泳了。

4.      不做重要不紧急的事情,不也是一样的嘛。

    防火和救火的概念。如果只是做好当前的事情,每天做好紧急不重要的事情,那么一旦出现意外,则会造成更严重的后果,以后的事情都会变成重要紧急的。如果不把时间掌握在自己手上,那么就是每天都在救火状态。

五、     处理流程

以前有一种做法,是每天上午,把要做的事情都列出来,然后每天晚上再把工作都整理一下,看看哪些做了,哪些没做。现在信息化社会,每天都会面临大量临时发生的事情。所以,现在可以用“事件篮”的方式来做。

现在开始,你准备一个“篮子”。这个篮子,可以是一个便签,也可以是一个小软件。作者用的是outlook的“任务”工具,这个可以和windows mobile手机同步。其他的工具也一样,只要能随身带着就行。

一旦你接受到一个任务,或者发现要处理的事件,先扔进“事件篮”里面。这个就像编码的时候发送消息到消息队列一样,不是同步处理的,也就是说,不是立即处理,再紧急也不是立即处理。

扔进去之后,判断这个事件是不是“重要紧急”。如果是老板喊你,或者工厂失火等重要紧急的事件,那么立即放下自己手上的活,去处理。

如果不是“重要紧急”的事情,那么就先让它在“事件篮”里呆上一会儿吧,专心把你自己当前在处理的事情做完。

做完了当前的事件,回顾你的事件篮。如果还有未识别的事件,则识别一下,按重要度很紧急度标识上。然后,看看你今天的重要不紧急的事件有没有处理,如果没有处理,则优先处理重要不紧急的事情。

经常性的,例如每周,都回顾一下自己的事件篮,把各个事件的重要紧急度重新识别一下。

六、     经验

好记性不如烂笔头

不要以为自己的大脑有多狠,事情一多肯定会乱掉。设置合理的提醒机制,提醒你开会等定时的事情,会让你少很多心理负担。

不要同时做两件事情

    不要把自己当作CPU。同时做两件事情,结果是没有一件能做好。完整的做完一件事情之后,再去找其他事情做吧。不要总是被打断工作,有些事情不立即处理,是不会有什么坏处的。

要找出“重要不紧急”的事情

    很多需要被人推着走的人,是找不到“重要不紧急”的事情的。对于项目来说,经常的去识别风险,经常去想想项目可能会碰到的问题,提前预防,这都是“重要不紧急”的事情。千万不能任其自然发展,等到出事的时候,就是到处“重要紧急”的事件了,就疲于奔命了。

认准目标

识别“重要不紧急”的事件,最重要的标志,就是对终极目标是否有利。远大的目标,永远是大于眼前目标的。如果只是看准眼前目标,那么永远找不到“重要不紧急”的事情,或者永远找不对。

   下一页