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


285月/160

Linux中几个在备份中常用的命令(cp,scp,rsync)

发布在 邵珠庆

在备份的操作中,拷贝,过期文件的删除是经常要做的事情。
拷贝也有本机拷贝,拷贝到别的服务器等。常用的操作有cp,scp,rsync等命令。
1、 cp(copy)命令

功能说明:复制文件或目录。

语  法:cp [-abdfilpPrRsuvx][-S <备份字尾字符串>][-V <备份方式>][--help][--spares=<使用时机>][--version][源文件或目录][目标文件或目录] [目的目录]

补充说明:cp指令用在复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定的所有文件或目录复制到该目录中。若同时指定多个文件或目录,而最后的目的地并非是一个已存在的目录,则会出现错误信息。

参  数:
 -a或--archive  此参数的效果和同时指定"-dpR"参数相同。
 -b或--backup  删除,覆盖目标文件之前的备份,备份文件会在字尾加上一个备份字符串。
 -d或--no-dereference  当复制符号连接时,把目标文件或目录也建立为符号连接,并指向与源文件或目录连接的原始文件或目录。
 -f或--force  强行复制文件或目录,不论目标文件或目录是否已存在。
 -i或--interactive  覆盖既有文件之前先询问用户。
 -l或--link  对源文件建立硬连接,而非复制文件。
 -p或--preserve  保留源文件或目录的属性。
 -P或--parents  保留源文件或目录的路径。
 -r  递归处理,将指定目录下的文件与子目录一并处理。
 -R或--recursive  递归处理,将指定目录下的所有文件与子目录一并处理。
 -s或--symbolic-link  对源文件建立符号连接,而非复制文件。
 -S<备份字尾字符串>或--suffix=<备份字尾字符串>  用"-b"参数备份目标文件后,备份文件的字尾会被加上一个备份字符串,预设的备份字尾字符串是符号"~"。
 -u或--update  使用这项参数后只会在源文件的更改时间较目标文件更新时或是 名称相互对应的目标文件并不存在,才复制文件。
 -v或--verbose  显示指令执行过程。
 -V<备份方式>或--version-control=<备份方式>  用"-b"参数备份目标文件后,备份文件的字尾会被加上一个备份字符串,这字符串不仅可用"-S"参数变更,当使用"-V"参数指定不同备份方式时,也会产生不同字尾的备份字串。
 -x或--one-file-system  复制的文件或目录存放的文件系统,必须与cp指令执行时所处的文件系统相同,否则不予复制。
 --help  在线帮助。
 --sparse=<使用时机>  设置保存稀疏文件的时机。
 --version  显示版本信息。

2. SCP
scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。linux的scp命令可以在linux服务器之间复制文件和目录.
scp命令的用处:
scp在网络上不同的主机之间复制文件,它使用ssh安全协议传输数据,具有和ssh一样的验证机制,从而安全的远程拷贝文件。
scp命令基本格式:
scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-S program] [[user@]host1:]file1 [...] [[user@]host2:]file2

例子:scp -r /home/soft/ root@www.mydomain.com:/home/others/

3. rsync

rysnc是一个数据镜像及备份工具,具有可使本地和远程两台主机的文件,目录之间,快速同步镜像,远程数据备份等功能。在同步过程中,rsync是根据自己独特的算法,只同步有变化的文件,甚至在一个文件里只同步有变化的部分,所以可以实现快速的同步数据的功能。
1. rsync用法
NAME
rsync - faster, flexible replacement for rcp

用法:
rsync [OPTION]... SRC [SRC]... DEST

rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST

rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST

rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST

rsync [OPTION]... SRC

rsync [OPTION]... [USER@]HOST:SRC [DEST]

rsync [OPTION]... [USER@]HOST::SRC [DEST]

rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
参数是非常多,用man可以查询。
--delete 删除传送端已经不存在,而目的端存在的档案
--delete-excluded 除了把传送端已经不存在, 而目的端存在的档案删除之外, 也删除 --exclude 参数所包含的档案
使用例子,把192.168.1.2的/home/下的文件同步到本地的/home/下面:rsync -aSvH --delete /home/ root@192.168.1.2:/home/
主要SCR目录的写法、比如 rsync src/ 和 src 是有区别的。 src/是src文件夹下的所有文件作为传送对象。没有/的src的话是,src这个文件夹整体拷贝传送。
rsync执行中需要ssh认证等,可以实现配置,然后在cron中定时执行同步就好了。在备份的操作中,拷贝,过期文件的删除是经常要做的事情。
拷贝也有本机拷贝,拷贝到别的服务器等。常用的操作有cp,scp,rsync等命令。
1、 cp(copy)命令

功能说明:复制文件或目录。

语  法:cp [-abdfilpPrRsuvx][-S <备份字尾字符串>][-V <备份方式>][--help][--spares=<使用时机>][--version][源文件或目录][目标文件或目录] [目的目录]

补充说明:cp指令用在复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定的所有文件或目录复制到该目录中。若同时指定多个文件或目录,而最后的目的地并非是一个已存在的目录,则会出现错误信息。

参  数:
 -a或--archive  此参数的效果和同时指定"-dpR"参数相同。
 -b或--backup  删除,覆盖目标文件之前的备份,备份文件会在字尾加上一个备份字符串。
 -d或--no-dereference  当复制符号连接时,把目标文件或目录也建立为符号连接,并指向与源文件或目录连接的原始文件或目录。
 -f或--force  强行复制文件或目录,不论目标文件或目录是否已存在。
 -i或--interactive  覆盖既有文件之前先询问用户。
 -l或--link  对源文件建立硬连接,而非复制文件。
 -p或--preserve  保留源文件或目录的属性。
 -P或--parents  保留源文件或目录的路径。
 -r  递归处理,将指定目录下的文件与子目录一并处理。
 -R或--recursive  递归处理,将指定目录下的所有文件与子目录一并处理。
 -s或--symbolic-link  对源文件建立符号连接,而非复制文件。
 -S<备份字尾字符串>或--suffix=<备份字尾字符串>  用"-b"参数备份目标文件后,备份文件的字尾会被加上一个备份字符串,预设的备份字尾字符串是符号"~"。
 -u或--update  使用这项参数后只会在源文件的更改时间较目标文件更新时或是 名称相互对应的目标文件并不存在,才复制文件。
 -v或--verbose  显示指令执行过程。
 -V<备份方式>或--version-control=<备份方式>  用"-b"参数备份目标文件后,备份文件的字尾会被加上一个备份字符串,这字符串不仅可用"-S"参数变更,当使用"-V"参数指定不同备份方式时,也会产生不同字尾的备份字串。
 -x或--one-file-system  复制的文件或目录存放的文件系统,必须与cp指令执行时所处的文件系统相同,否则不予复制。
 --help  在线帮助。
 --sparse=<使用时机>  设置保存稀疏文件的时机。
 --version  显示版本信息。

2. SCP
scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。linux的scp命令可以在linux服务器之间复制文件和目录.
scp命令的用处:
scp在网络上不同的主机之间复制文件,它使用ssh安全协议传输数据,具有和ssh一样的验证机制,从而安全的远程拷贝文件。
scp命令基本格式:
scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] [-o ssh_option] [-P port] [-S program] [[user@]host1:]file1 [...] [[user@]host2:]file2

例子:scp -r /home/soft/ root@www.mydomain.com:/home/others/

3. rsync

rysnc是一个数据镜像及备份工具,具有可使本地和远程两台主机的文件,目录之间,快速同步镜像,远程数据备份等功能。在同步过程中,rsync是根据自己独特的算法,只同步有变化的文件,甚至在一个文件里只同步有变化的部分,所以可以实现快速的同步数据的功能。
1. rsync用法
NAME
rsync - faster, flexible replacement for rcp

用法:
rsync [OPTION]... SRC [SRC]... DEST

rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST

rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST

rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST

rsync [OPTION]... SRC

rsync [OPTION]... [USER@]HOST:SRC [DEST]

rsync [OPTION]... [USER@]HOST::SRC [DEST]

rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
参数是非常多,用man可以查询。
--delete 删除传送端已经不存在,而目的端存在的档案
--delete-excluded 除了把传送端已经不存在, 而目的端存在的档案删除之外, 也删除 --exclude 参数所包含的档案
使用例子,把192.168.1.2的/home/下的文件同步到本地的/home/下面:rsync -aSvH --delete /home/ root@192.168.1.2:/home/
主要SCR目录的写法、比如 rsync src/ 和 src 是有区别的。 src/是src文件夹下的所有文件作为传送对象。没有/的src的话是,src这个文件夹整体拷贝传送。
rsync执行中需要ssh认证等,可以实现配置,然后在cron中定时执行同步就好了。

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,进行深入了解。  
95月/160

微信公众平台开发 OAuth2.0网页授权认证

发布在 邵珠庆

一、什么是OAuth2.0

官方网站:http://oauth.net/   http://oauth.net/2/

权威定义:OAuth is An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications. 

OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。

OAuth 2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。

OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。

新浪微博API目前也使用OAuth 2.0。

二、微信公众平台OAuth2.0授权

微信公众平台OAuth2.0授权详细步骤如下:

1. 用户关注微信公众账号。
2. 微信公众账号提供用户请求授权页面URL。
3. 用户点击授权页面URL,将向服务器发起请求
4. 服务器询问用户是否同意授权给微信公众账号(scope为snsapi_base时无此步骤)
5. 用户同意(scope为snsapi_base时无此步骤)
6. 服务器将CODE通过回调传给微信公众账号
7. 微信公众账号获得CODE
8. 微信公众账号通过CODE向服务器请求Access Token
9. 服务器返回Access Token和OpenID给微信公众账号
10. 微信公众账号通过Access Token向服务器请求用户信息(scope为snsapi_base时无此步骤)
11. 服务器将用户信息回送给微信公众账号(scope为snsapi_base时无此步骤)

如果用户在微信中(Web微信除外)访问公众号的第三方网页,公众号开发者可以通过此接口获取当前用户基本信息(包括昵称、性别、城市、国家)。利用用户信息,可以实现体验优化、用户来源统计、帐号绑定、用户身份鉴权等功能。请注意,“获取用户基本信息接口是在用户和公众号产生消息交互时,才能根据用户OpenID获取用户基本信息,而网页授权的方式获取用户基本信息,则无需消息交互,只是用户进入到公众号的网页,就可弹出请求用户授权的界面,用户授权后,就可获得其基本信息(此过程甚至不需要用户已经关注公众号。)”

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

在微信公众号请求用户网页授权之前,开发者需要先到公众平台网站的我的服务页中配置授权回调域名。请注意,这里填写的域名不要加http://

关于配置授权回调域名的说明:

授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com  无法进行OAuth2.0鉴权。

具体而言,网页授权流程分为四步:

  1. 引导用户进入授权页面同意授权,获取code
  2. 通过code换取网页授权access_token(与基础支持中的access_token不同)
  3. 如果需要,开发者可以刷新网页授权access_token,避免过期
  4. 通过网页授权access_token和openid获取用户基本信息

目录

[隐藏]

第一步:用户同意授权,获取code

在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认带有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
参考链接(请在微信客户端中打开此链接体验) Scope为snsapi_base https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=http%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect Scope为snsapi_userinfo https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

参数说明

参数 是否必须 说明
appid 公众号的唯一标识
redirect_uri 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
response_type 返回类型,请填写code
scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值
#wechat_redirect 无论直接打开还是做页面302重定向时候,必须带此参数

下图为scope等于snsapi_userinfo时的授权页面:

网页授权

用户同意授权后

如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE

code说明 : code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。

第二步:通过code换取网页授权access_token

首先请注意,这里通过code换取的网页授权access_token,与基础支持中的access_token不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。

请求方法

获取code后,请求以下链接获取access_token:  https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数 是否必须 说明
appid 公众号的唯一标识
secret 公众号的appsecret
code 填写第一步获取的code参数
grant_type 填写为authorization_code

返回说明

正确时返回的JSON数据包如下:

{    "access_token":"ACCESS_TOKEN",    "expires_in":7200,    "refresh_token":"REFRESH_TOKEN",    "openid":"OPENID",    "scope":"SCOPE" }
参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
scope 用户授权的作用域,使用逗号(,)分隔

错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

全局返回码说明

第三步:刷新access_token(如果需要)

由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。

请求方法

获取第二步的refresh_token后,请求以下链接获取access_token:  https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
参数 是否必须 说明
appid 公众号的唯一标识
grant_type 填写为refresh_token
refresh_token 填写通过access_token获取到的refresh_token参数

返回说明

正确时返回的JSON数据包如下:

{    "access_token":"ACCESS_TOKEN",    "expires_in":7200,    "refresh_token":"REFRESH_TOKEN",    "openid":"OPENID",    "scope":"SCOPE" }
参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
expires_in access_token接口调用凭证超时时间,单位(秒)
refresh_token 用户刷新access_token
openid 用户唯一标识
scope 用户授权的作用域,使用逗号(,)分隔

错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

全局返回码说明

第四步:拉取用户信息(需scope为 snsapi_userinfo)

如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。

请求方法

http:GET(请使用https协议) https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数说明

参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid 用户的唯一标识
lang 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语

返回说明

正确时返回的JSON数据包如下:

{    "openid":" OPENID",    " nickname": NICKNAME,    "sex":"1",    "province":"PROVINCE"    "city":"CITY",    "country":"COUNTRY",     "headimgurl":    "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",  "privilege":[ "PRIVILEGE1" "PRIVILEGE2"     ] }
参数 描述
openid 用户的唯一标识
nickname 用户昵称
sex 用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
province 用户个人资料填写的省份
city 普通用户个人资料填写的城市
country 国家,如中国为CN
headimgurl 用户头像,最后一个数值代表正方形头像大小(有0、46、64、96、132数值可选,0代表640*640正方形头像),用户没有头像时该项为空
privilege 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom)

错误时微信会返回JSON数据包如下(示例为openid无效):

{"errcode":40003,"errmsg":" invalid openid "}

全局返回码说明

附:检验授权凭证(access_token)是否有效

请求方法

http:GET(请使用https协议) https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID

参数说明

参数 描述
access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
openid 用户的唯一标识

返回说明

正确的Json返回结果:

{ "errcode":0,"errmsg":"ok"}

错误时的Json返回示例:

{ "errcode":40003,"errmsg":"invalid openid"}

 案例代码:

请求授权页面的构造方式

url在线编码工具:http://tool.oschina.net/encode?type=4

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

前端代码


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd";><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><meta name="viewport" content="width=device-width,height=device-height,inital-scale=1.0,maximum-scale=1.0,user-scalable=no;"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><meta name="format-detection" content="telephone=no"><title>会员注册</title><script type="text/JavaScript" src="jQuery.js"></script>

 <script type="text/javascript"> 
  function callback(result) {  
        alert('cucess');         
  alert(result);  //输出openid    
  } 
  
  function getQueryString(name) {  
   var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");   
   var r = window.location.search.substr(1).match(reg);    
   if (r != null) return unescape(r[2]); return null;   
  }
  var code = getQueryString("code");
  
  $.ajax({ 
  async: false,       url: "http://atest.sinaapp.com/oauth2.php", //这是我的服务端处理文件php的     
  type: "GET",       //下面几行是jsoup,如果去掉下面几行的注释,后端对应的返回结果也要去掉注释      
  // dataType: 'jsonp',      
  // jsonp: 'callback', //jsonp的值自定义,如果使用jsoncallback,那么服务器端,要返回一个jsoncallback的值对应的对象.       
  // jsonpCallback:'callback',      
  data: {code:code}, //传递本页面获取的code到后台,以便后台获取openid      
  timeout: 5000,       
  success: function (result) { 
        callback(result);     
  },       
  error: function (jqXHR, textStatus, errorThrown) {
  alert(textStatus);       }   
  });
  
  </script>
  
  </head><body></body> 


后端代码


<?php
$code = $_GET['code'];//前端传来的code值
$appid = "wx468622291a1e99d6";
$appsecret = "98566dc38863aa4395fabebb0de6ecc1";//获取openid
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$appsecret&code=$code&grant_type=authorization_code";
$result = https_request($url);
$jsoninfo = json_decode($result, true);
$openid = $jsoninfo["openid"];//从返回json结果中读出openid
$access_token = $jsoninfo["access_token"];//从返回json结果中读出openid
$callback=$_GET['callback'];  // echo $callback."({result:'".$openid."'})";

$url1 = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
$result1 = https_request($url1);
$jsoninfo1 = json_decode($result1, true);
$nickname=$jsoninfo1["nickname"];
echo $openid.":".$access_token.":".$nickname; //把openid 送回前端

 function https_request($url,$data = null){
  $curl = curl_init();   
  curl_setopt($curl, CURLOPT_URL, $url);   
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);   
  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);    
  if (!empty($data)){    
  curl_setopt($curl, CURLOPT_POST, 1);  
  curl_setopt($curl, CURLOPT_POSTFIELDS, $data);   
  }    
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
  $output = curl_exec($curl);    
  curl_close($curl);    
  return $output;
 }
?> 

 
 
65月/160

phpredis中文手册 《redis中文手册》 php版

发布在 邵珠庆

phpredis是php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系

很有用;以下是redis官方提供的命令使用技巧:

下载地址如下:

https://github.com/owlient/phpredis(支持redis 2.0.4)
Redis::__construct构造函数
$redis = new Redis();

connect, open 链接redis服务
参数
host
: string,服务地址
port
: int,端口号
timeout
: float,链接时长 (可选, 默认为 0 ,不限链接时间)
注: 在redis.conf中也有时间,默认为300

pconnect, popen 不会主动关闭的链接
参考上面

setOption 设置redis模式

getOption 查看redis设置的模式

ping 查看连接状态

get 得到某个key的值(string值)
如果该key不存在,return false

set 写入key 和 value(string值)
如果写入成功,return ture

setex 带生存时间的写入值
$redis->setex('key', 3600, 'value'); // sets key → value, with 1h TTL.

setnx 判断是否重复的,写入值
$redis->setnx('key', 'value');
$redis->setnx('key', 'value');

delete  删除指定key的值
返回已经删除key的个数(长整数)
$redis->delete('key1', 'key2');
$redis->delete(array('key3', 'key4', 'key5'));

ttl
得到一个key的生存时间

persist
移除生存时间到期的key
如果key到期 true 如果不到期 false

mset (redis版本1.1以上才可以用)
同时给多个key赋值
$redis->mset(array('key0' => 'value0', 'key1' => 'value1'));

multi, exec, discard
进入或者退出事务模式
参数可选Redis::MULTI或Redis::PIPELINE. 默认是 Redis::MULTI
Redis::MULTI:将多个操作当成一个事务执行
Redis::PIPELINE:让(多条)执行命令简单的,更加快速的发送给服务器,但是没有任何原子性的保证
discard:删除一个事务
返回值
multi(),返回一个redis对象,并进入multi-mode模式,一旦进入multi-mode模式,以后调用的所有方法都会返回相同的对象,只到exec()方法被调用。

watch, unwatch (代码测试后,不能达到所说的效果)
监测一个key的值是否被其它的程序更改。如果这个key在watch 和 exec (方法)间被修改,这个 MULTI/EXEC 事务的执行将失败(return false)
unwatch  取消被这个程序监测的所有key
参数,一对key的列表
$redis->watch('x');

$ret = $redis->multi() ->incr('x') ->exec();

subscribe *
方法回调。注意,该方法可能在未来里发生改变

publish *
发表内容到某一个通道。注意,该方法可能在未来里发生改变

exists
判断key是否存在。存在 true 不在 false

incr, incrBy
key中的值进行自增1,如果填写了第二个参数,者自增第二个参数所填的值
$redis->incr('key1');
$redis->incrBy('key1', 10);

decr, decrBy
做减法,使用方法同incr

getMultiple
传参
由key组成的数组
返回参数
如果key存在返回value,不存在返回false
$redis->set('key1', 'value1'); $redis->set('key2', 'value2'); $redis->set('key3', 'value3'); $redis->getMultiple(array('key1', 'key2', 'key3'));
$redis->lRem('key1', 'A', 2);
$redis->lRange('key1', 0, -1);

list相关操作
lPush
$redis->lPush(key, value);
在名称为key的list左边(头)添加一个值为value的 元素

rPush
$redis->rPush(key, value);
在名称为key的list右边(尾)添加一个值为value的 元素

lPushx/rPushx
$redis->lPushx(key, value);
在名称为key的list左边(头)/右边(尾)添加一个值为value的元素,如果value已经存在,则不添加

lPop/rPop
$redis->lPop('key');
输出名称为key的list左(头)起/右(尾)起的第一个元素,删除该元素

blPop/brPop
$redis->blPop('key1', 'key2', 10);
lpop命令的block版本。即当timeout为0时,若遇到名称为key i的list不存在或该list为空,则命令结束。如果timeout>0,则遇到上述情况时,等待timeout秒,如果问题没有解决,则对keyi+1开始的list执行pop操作

lSize
$redis->lSize('key');
返回名称为key的list有多少个元素

lIndex, lGet
$redis->lGet('key', 0);
返回名称为key的list中index位置的元素

lSet
$redis->lSet('key', 0, 'X');
给名称为key的list中index位置的元素赋值为value

lRange, lGetRange
$redis->lRange('key1', 0, -1);
返回名称为key的list中start至end之间的元素(end为 -1 ,返回所有)

lTrim, listTrim
$redis->lTrim('key', start, end);
截取名称为key的list,保留start至end之间的元素

lRem, lRemove
$redis->lRem('key', 'A', 2);
删除count个名称为key的list中值为value的元素。count为0,删除所有值为value的元素,count>0从头至尾删除count个值为value的元素,count<0从尾到头删除|count|个值为value的元素

lInsert
在名称为为key的list中,找到值为pivot 的value,并根据参数Redis::BEFORE | Redis::AFTER,来确定,newvalue 是放在 pivot 的前面,或者后面。如果key不存在,不会插入,如果 pivot不存在,return -1
$redis->delete('key1'); $redis->lInsert('key1', Redis::AFTER, 'A', 'X'); $redis->lPush('key1', 'A'); $redis->lPush('key1', 'B'); $redis->lPush('key1', 'C'); $redis->lInsert('key1', Redis::BEFORE, 'C', 'X');
$redis->lRange('key1', 0, -1);
$redis->lInsert('key1', Redis::AFTER, 'C', 'Y');
$redis->lRange('key1', 0, -1);
$redis->lInsert('key1', Redis::AFTER, 'W', 'value');

rpoplpush
返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
$redis->delete('x', 'y');
$redis->lPush('x', 'abc'); $redis->lPush('x', 'def'); $redis->lPush('y', '123'); $redis->lPush('y', '456'); // move the last of x to the front of y. var_dump($redis->rpoplpush('x', 'y'));
var_dump($redis->lRange('x', 0, -1));
var_dump($redis->lRange('y', 0, -1)); 

string(3) "abc" 
array(1) { [0]=> string(3) "def" } 
array(3) { [0]=> string(3) "abc" [1]=> string(3) "456" [2]=> string(3) "123" }

SET操作相关
sAdd
向名称为key的set中添加元素value,如果value存在,不写入,return false
$redis->sAdd(key , value);

sRem, sRemove
删除名称为key的set中的元素value
$redis->sAdd('key1' , 'set1');
$redis->sAdd('key1' , 'set2');
$redis->sAdd('key1' , 'set3');
$redis->sRem('key1', 'set2');

sMove
将value元素从名称为srckey的集合移到名称为dstkey的集合
$redis->sMove(seckey, dstkey, value);

sIsMember, sContains
名称为key的集合中查找是否有value元素,有ture 没有 false
$redis->sIsMember(key, value);

sCard, sSize
返回名称为key的set的元素个数

sPop
随机返回并删除名称为key的set中一个元素

sRandMember
随机返回名称为key的set中一个元素,不删除

sInter
求交集

sInterStore
求交集并将交集保存到output的集合
$redis->sInterStore('output', 'key1', 'key2', 'key3')

sUnion
求并集
$redis->sUnion('s0', 's1', 's2');
s0,s1,s2 同时求并集

sUnionStore
求并集并将并集保存到output的集合
$redis->sUnionStore('output', 'key1', 'key2', 'key3');

sDiff
求差集

sDiffStore
求差集并将差集保存到output的集合

sMembers, sGetMembers
返回名称为key的set的所有元素

sort
排序,分页等
参数
'by' => 'some_pattern_*',
'limit' => array(0, 1),
'get' => 'some_other_pattern_*' or an array of patterns,
'sort' => 'asc' or 'desc',
'alpha' => TRUE,
'store' => 'external-key'
例子
$redis->delete('s'); $redis->sadd('s', 5); $redis->sadd('s', 4); $redis->sadd('s', 2); $redis->sadd('s', 1); $redis->sadd('s', 3);
var_dump($redis->sort('s')); // 1,2,3,4,5
var_dump($redis->sort('s', array('sort' => 'desc'))); // 5,4,3,2,1
var_dump($redis->sort('s', array('sort' => 'desc', 'store' => 'out'))); // (int)5
 
string命令
getSet
返回原来key中的值,并将value写入key
$redis->set('x', '42');
$exValue = $redis->getSet('x', 'lol'); // return '42', replaces x by 'lol'
$newValue = $redis->get('x')' // return 'lol'

append
string,名称为key的string的值在后面加上value
$redis->set('key', 'value1');
$redis->append('key', 'value2');
$redis->get('key');

getRange (方法不存在)
返回名称为key的string中start至end之间的字符
$redis->set('key', 'string value');
$redis->getRange('key', 0, 5);
$redis->getRange('key', -5, -1);

setRange (方法不存在)
改变key的string中start至end之间的字符为value
$redis->set('key', 'Hello world');
$redis->setRange('key', 6, "redis");
$redis->get('key');

strlen
得到key的string的长度
$redis->strlen('key');

getBit/setBit
返回2进制信息

zsetsorted set)操作相关
zAdd(key, score, member):向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。
$redis->zAdd('key', 1, 'val1');
$redis->zAdd('key', 0, 'val0');
$redis->zAdd('key', 5, 'val5');
$redis->zRange('key', 0, -1); // array(val0, val1, val5)

zRange(key, start, end,withscores):返回名称为key的zset(元素已按score从小到大排序)中的index从start到end的所有元素
$redis->zAdd('key1', 0, 'val0');
$redis->zAdd('key1', 2, 'val2');
$redis->zAdd('key1', 10, 'val10');
$redis->zRange('key1', 0, -1); // with scores $redis->zRange('key1', 0, -1, true);

zDelete, zRem
zRem(key, member) :删除名称为key的zset中的元素member
$redis->zAdd('key', 0, 'val0');
$redis->zAdd('key', 2, 'val2');
$redis->zAdd('key', 10, 'val10');
$redis->zDelete('key', 'val2');
$redis->zRange('key', 0, -1); 

zRevRange(key, start, end,withscores):返回名称为key的zset(元素已按score从大到小排序)中的index从start到end的所有元素.withscores: 是否输出socre的值,默认false,不输出
$redis->zAdd('key', 0, 'val0');
$redis->zAdd('key', 2, 'val2');
$redis->zAdd('key', 10, 'val10');
$redis->zRevRange('key', 0, -1); // with scores $redis->zRevRange('key', 0, -1, true);

zRangeByScore, zRevRangeByScore
$redis->zRangeByScore(key, star, end, array(withscores, limit ));
返回名称为key的zset中score >= star且score <= end的所有元素

zCount
$redis->zCount(key, star, end);
返回名称为key的zset中score >= star且score <= end的所有元素的个数

zRemRangeByScore, zDeleteRangeByScore
$redis->zRemRangeByScore('key', star, end);
删除名称为key的zset中score >= star且score <= end的所有元素,返回删除个数

zSize, zCard
返回名称为key的zset的所有元素的个数

zScore
$redis->zScore(key, val2);
返回名称为key的zset中元素val2的score

zRank, zRevRank
$redis->zRevRank(key, val);
返回名称为key的zset(元素已按score从小到大排序)中val元素的rank(即index,从0开始),若没有val元素,返回“null”。zRevRank 是从大到小排序

zIncrBy
$redis->zIncrBy('key', increment, 'member');
如果在名称为key的zset中已经存在元素member,则该元素的score增加increment;否则向集合中添加该元素,其score的值为increment

zUnion/zInter
参数
keyOutput
arrayZSetKeys
arrayWeights
aggregateFunction
 Either "SUM", "MIN", or "MAX": defines the behaviour to use on duplicate entries during the zUnion.
对N个zset求并集和交集,并将最后的集合保存在dstkeyN中。对于集合中每一个元素的score,在进行AGGREGATE运算前,都要乘以对于的WEIGHT参数。如果没有提供WEIGHT,默认为1。默认的AGGREGATE是SUM,即结果集合中元素的score是所有集合对应元素进行SUM运算的值,而MIN和MAX是指,结果集合中元素的score是所有集合对应元素中最小值和最大值。

Hash操作
hSet
$redis->hSet('h', 'key1', 'hello');
向名称为h的hash中添加元素key1—>hello

hGet
$redis->hGet('h', 'key1');
返回名称为h的hash中key1对应的value(hello)

hLen
$redis->hLen('h');
返回名称为h的hash中元素个数

hDel
$redis->hDel('h', 'key1');
删除名称为h的hash中键为key1的域

hKeys
$redis->hKeys('h');
返回名称为key的hash中所有键

hVals
$redis->hVals('h')
返回名称为h的hash中所有键对应的value

hGetAll
$redis->hGetAll('h');
返回名称为h的hash中所有的键(field)及其对应的value

hExists
$redis->hExists('h', 'a');
名称为h的hash中是否存在键名字为a的域

hIncrBy
$redis->hIncrBy('h', 'x', 2);
将名称为h的hash中x的value增加2

hMset
$redis->hMset('user:1', array('name' => 'Joe', 'salary' => 2000));
向名称为key的hash中批量添加元素

hMGet
$redis->hmGet('h', array('field1', 'field2'));
返回名称为h的hash中field1,field2对应的value

redis 操作相关
flushDB
清空当前数据库

flushAll
清空所有数据库

randomKey
随机返回key空间的一个key
$key = $redis->randomKey();

select
选择一个数据库
move
转移一个key到另外一个数据库
$redis->select(0); // switch to DB 0
$redis->set('x', '42'); // write 42 to x
$redis->move('x', 1); // move to DB 1
$redis->select(1); // switch to DB 1
$redis->get('x'); // will return 42

rename, renameKey
给key重命名
$redis->set('x', '42');
$redis->rename('x', 'y');
$redis->get('y'); // → 42
$redis->get('x'); // → `FALSE`

renameNx
与remane类似,但是,如果重新命名的名字已经存在,不会替换成功

setTimeout, expire
设定一个key的活动时间(s)
$redis->setTimeout('x', 3);

expireAt
key存活到一个unix时间戳时间
$redis->expireAt('x', time() + 3);

keys, getKeys
返回满足给定pattern的所有key
$keyWithUserPrefix = $redis->keys('user*');

dbSize
查看现在数据库有多少key
$count = $redis->dbSize();

auth
密码认证
$redis->auth('foobared');

bgrewriteaof
使用aof来进行数据库持久化
$redis->bgrewriteaof();

slaveof
选择从服务器
$redis->slaveof('10.0.1.7', 6379);

save
将数据同步保存到磁盘

bgsave
将数据异步保存到磁盘

lastSave
返回上次成功将数据保存到磁盘的Unix时戳

info
返回redis的版本信息等详情

type
返回key的类型值
string: Redis::REDIS_STRING
set: Redis::REDIS_SET
list: Redis::REDIS_LIST
zset: Redis::REDIS_ZSET
hash: Redis::REDIS_HASH
other: Redis::REDIS_NOT_FOUND

35月/160

有意思的面试题

发布在 邵珠庆

1、有十筐苹果,每筐里有十个,共100个,每筐里苹果的重量都是一样,其中有九筐每个苹果的重量都是1斤,
另一筐中每个苹果的重量都是0.9斤,但是外表完全一样,用眼看或用手摸无法分辨。
现在要你用一台普通的大秤一次把这筐重量轻的找出来。
答案:从第一筐中拿出一个,第二筐中拿出两个,第十筐拿出十个,一起放在称上称。
如果每个苹果一斤重,就应该是55斤。假设称出是54.9斤,则说明,从第一筐中拿出那个苹果是九两的,也就是说第一筐的苹果是九两重的。
如果称出是54.8斤,也就是说差2两,而又只有一筐苹果中的每个都是九两重的,所以一定是第二筐中拿出两个是9两重,也就是说第二筐的苹果是九两重的。
按这样推理下去,应该明白吧!!
2、我有一堆绳子,这些绳子之间粗细长短各不相同,每一条绳子本身各处的粗细长短也各不相同。
但是每条绳子的燃烧时间都是60秒,试问我要测量15秒的时间,我该如何做?
答案:
1.同时点燃任意两根绳子,第一根绳子点两头,第二根绳子点一头;
2.等第一根绳子烧完后,点燃第二根绳子的另一头,让两头同时燃烧,并开始计时;
3.在第二根绳子烧尽时停止计时,即可得15秒的时间。
因为题目中给出一个条件:一堆绳子,长短粗细各不相同,也不均匀。
也就是说每根绳子从头到尾都是不均匀的,并非只是绳子与绳子不同。
那么~~虽然单根绳子总的燃烧时间为60秒,但若取半根则未必是30秒,四分之一根未必是15秒啊~~~~~~~
若假定了一个默认的条件:就是单根绳子是均匀的。因此,必然会导致错误的结果。
3、有一堆垃圾,规定要由张王李三户人家清理。张户因外出没能参加,留下9元钱做代劳费。
王户上午起早干了5小时,李户下午接着干了4小时刚好干完。问王户和李户应怎样分配这9元钱?
答案:不能简单地认为王户应得5元,李户应得4元。不加分析而想当然办事往往搞错。
应该知道,王李两户所做的工作中,除帮张户外,还有他们自己的任务。
很明显,每户的工作量为3小时。王帮张干了2小时,李帮张干了1小时,王帮张的工作量是李帮张的2倍,得到的报酬当然也应该是李的2倍。
因此,王应得6元,李应得3元。
4、一天有个年轻人来到王老板的店里买了一件礼物这件礼物成本是18元,标价是21元。
结果是这个年轻人掏出100元要买这件礼物。王老板当时没有零钱,用那100元向街坊换了100元的零钱,找给年轻人79元。
但是街坊後来发现那100元是假钞,王老板无奈还了街坊100元。现在问题是:王老板在这次交易中到底损失了多少钱?
答案:年轻人掏出100元假钞买这件礼物,王老板进0元!
王老板当时没有零钱,用那100元假钞向街坊换了100元的零钱,王老板进100元!
街坊後来发现那100元是假钞,王老板无奈还了街坊100元。王老板出100元!找给年轻人79元。王老板出79元!
年轻人到王老板的店里买了一件礼物礼物成本是18元,标价是21元。王老板出18元!
总计损失:97元!
5、有13个零件,外表完全一样,但有一个是不合格品,其重量和其它的不同,且轻重不知。请你用天平称3次,把它找出来。
答案:先在天平的两边各放4个零件。
一、如果天平平衡,说明坏的在另外的5个里。拿出3个好的放在天平左端,再从坏的5个中拿出3个,放在天平右端(如果不平衡,此时要记住右端是高是低,高说明坏的零件比好的轻,反之相反)。
1、如果天平平衡,则坏的在剩下的两个中,随便拿1个和好的称,则答案很明显。
2、如果天平不平衡,则坏的在那3个里面,随便拿出2个,分别放到天平两端。如果平衡,答案很明显。
如果不平衡,则可以根据(一)判断零件是轻点还是重点,答案也很明显。
二、如果天平不平衡,说明坏的在这8个中,此时要记住哪端是轻的,哪端是重的。然后把5个合格的放在天平的左端,取2个轻端的,3个重端的放在右端。
1、如果天平平衡,则拿剩下的两个轻端的,放到天平两端,如果平衡,答案很明显。如果不平衡,则说明坏的在这两个里面,而且坏的是较轻的,因为它们是从轻端取出来的。
2、如果右端低,说明坏的在重的3个里,而且坏的零件较重,再称一次就知道答案。如果右端高,说明坏的在轻的2个里面,而且坏的较轻,再称一次答案很明显。
6、1~50号运动员按顺序排成一排。
教练下令:“单数运动员出列!”剩下的运动员重新排队编号。
教练又下令:“单数运动员出列!”如此下去,最后只剩下一个人,他是几号运动员?
如果教练下的令是“双数运动员出列!”最后剩下的又是谁?
答案:单数出列最后剩下32号双数出列最后剩下1号
1、第一次单数出列,
1/3/5/7/9/11/13/15/17/19/21/23/25...../49
剩下的为
2/4/6/8/10/12/14/16/18/20/22/24/....../50
2、第二次单数出列,
2/6/10/14/18/22/26/30/34/38/42/46/50
剩下的为
4/8/12/16/20/24/28/32/36/40/44/48
3、第三次单数出列
4/12/20/28/36/44
剩下的为
8/16/24/32/40/48
4、第四次单数出列
8/24/40
剩下的为
16/32/48
5、第五次单数出列
16/48
剩下的为
32
如果教练下的令是“双数运动员出列!”最后剩下的是1。
7、一死刑犯就要执行。
行刑官对死刑犯说:“你知道我将怎样处决你吗?猜对了,我可以让你死得好受些,给你吃个枪子。要是你猜错了,那就对不起了,请你尝尝上绞刑架的滋味。”
行刑官想:“反正我说了算,说你对你就对,说你错你就错”没想到由于死刑犯聪明的回答,使得行刑官无法执行死刑,这个死刑犯绝处逢生。这个死刑犯是怎样回答的?
答案:死刑犯说:"我将要上绞刑架".这是一个不对不错的答案,行刑官要是说错了,那犯人将上绞刑架,那犯人就说对了,行刑官要是说对了,那犯人要被吃枪子,那犯人就说错了。
8、从前,有个很有钱的人家。正当全家为新的小生命即将降临而欢喜之际,丈夫突然得了不治之症。
临终前留下遗嘱:“如果生的是男孩,妻子和儿子各分家产的一半。如果是女孩,女孩分得家产的三分之一,其余归妻子。”
丈夫死后不久,妻子就临产了。出乎意料的是,妻子生下一男一女双胞胎!这下妻子为难了,这笔财产该怎样分呢?
答案:按法律的规定继承。
丈夫的遗嘱是附条件的,但其条件并没有实现,所以不按遗嘱继承,而应当按照法律的规定继承:家产先分给妻子一半(夫妻共同财产),剩余的一半,由妻子和一双子女平均继承。
即妻子得家产的三分之二,子女各得家产的六分之一。
9、有两个封闭式的小火车站,每天从甲站开到乙站的车次总是比从乙站开到甲站的车次多,时间长了,火车会不会都集中到乙站呢?
答案:不会,因为从乙站开出的车的车厢比甲站开出的车的车厢要多!
10、回到原地?
一个人从点M出发步行,前进20米就向右转15度,再前进20米,又向右转15度,......,照这样走下去,他能不能回到M点?如果能,他回到M点时,一共走了多少米?
答案:这么走下去,他可以回到M点,且他走完一圈的路线形成一个正N边形,每边都为20米。由于每次都转15度且正N边形外角和
11、我有两只桶,一只可以盛3升水,另一只可以盛5升水,试问我想要四升水,我应该用什么办法?
答案:将5升桶装满,倒入3升桶;将3升桶的水倒掉,将5升桶的剩余的(2升)水倒入3升桶;
将5升桶装满,用5升桶中的水将3升桶(此时3升桶中有2升水)装满,则5升桶中剩余4升水。
12、现在小明一家过一座桥,过桥时候是黑夜,所以必须有灯。现在小明过桥要1秒,小明的弟弟要3秒,小明的爸爸要6秒,小明的妈妈要8秒,小明的爷爷要12秒。每次此桥最多可过两人,而过桥的速度依过桥最慢者而定,而且灯在点燃后30秒就会熄灭。问小明一家如何过桥?
答案:这类智力题目,其实是考察应聘者在限制条件下解决问题的能力。
具体到这道题目来说,很多人往往认为应该由小明持灯来来去去,这样最节省时间,但最后却怎么也凑不出解决方案。
但是换个思路,我们根据具体情况来决定谁持灯来去,只要稍稍做些变动即可:
第一步,小明与弟弟过桥,小明回来,耗时4秒;
第二步,小明与爸爸过河,弟弟回来,耗时9秒;
第三步,妈妈与爷爷过河,小明回来,耗时13秒;
最后,小明与弟弟过河,耗时4秒,总共耗时30秒,多么惊险!
专家意见:这类题目多出现于跨国企业的招聘面试中,对考察一个人的思维方式及思维方式转变能力有极其明显的作用,
而据一些研究显示,这样的能力往往也与工作中的应变与创新状态息息相关。
所以回答这些题目时,必须冲破思维定式,试着从不同的角度考虑问题,不断进行逆向思维,
换位思考,并且把题目与自己熟悉的场景联系起来,切忌思路混乱。
13、过桥
有一家四口人要走过一座窄桥,窄桥一次最多只可容许两个人一起过桥,由于天色很暗,同时他们又只有一只手电筒,
过桥时必须持有手电筒,以防止跌落水中,因此就得有人把手电筒带来带去,来回桥两端,四个人得步行速度各不相同,
已知每人过桥所需要使用的时间分别为:哥哥1分钟爸爸2分钟妈妈5分钟爷爷10分钟
若两人同行则以较慢者的速度为准,请问他们最少要花多少分钟才能过桥。
答案:第一步,哥哥与爸爸过桥,哥哥回来,耗时3分钟;第二步,妈妈与爷爷过河,爸爸回来,耗时12分钟;第三步,哥哥与爸爸过桥,耗时2分钟;总共耗时17分钟。
14、卖胡萝卜
一个商人骑一头驴要穿越1000公里长的沙漠,去卖3000根萝卜。
已知驴一次性最多可驮1000根萝卜,但每走一公里又要吃掉一根萝卜。
问:商人一共可卖出多少根胡萝卜?(他可以把萝卜卸在半路上,回去再驮,假设萝卜丢不了也烂不了。)
答案:要卖出最多胡萝卜,也就是驴的共走过的路程要最短第一步,当胡萝卜数大于2000时,
路程必须来回三趟,第三趟不用回去,共走路程X,消耗胡萝卜1000根,X=1000/5,也就是走200公里,
放下1000-(200*2)=600根,
第二次1000-(200*2)=600根,第三次1000-200=800根,走了200公里,刚好共运到2000根第二步,胡萝卜数大于1000时,
路程必须来回二趟,第二趟不用回去,共走路程y,消耗胡萝卜1000根,1000/3不是整数,
而胡萝卜必须整根搬运第一种方法,y=333公里,留一根在路上,即在剩下的路程(1000-200-333=467),共有1000根胡萝卜,能运到1000-467=533根第二种方法,y=334公里,即在剩下的路程(1000-200-334=466),
共有998根胡萝卜,能运到998-466=532根所以,最多可以运到533根。
15、三个年轻人去一家旅店投宿,每人拿出十元钱交给老板。老板由于喜得贵子,决定少收5元钱,于是让服务员将5元钱转交给三个年轻人。
服务员从中扣下了2元钱,将剩余3元钱还给三人,每人分得1元。现在三个年轻人每人相当于拿出9元钱,3*9=27,加上服务员扣下的2元钱,27+2=29。
与三人最初拿出的30元钱相差1元。问这一元钱到哪儿去了?
答案:这个问题的逻辑是错误的。准确的描述是,3个人各出了10元钱,后又还回1元钱,因此共出钱27元。这27元中,2元被服务员扣下了,25元为房费。因此不存在27+2=29。
16、考考你的逻辑能力已知公式:DONALD+GERALD=ROBERT
以上共有10个字母,每一个字母都代表阿拉伯数字中0--9中的一个,已知D=5,请您在5分钟之内计算出其余9个字母代表的数字。
答案:526485+197485=723970
G=10=2B=3A=4D=5N=6R=7L=8E=9T=0步骤:
1、首先D=5,得知T=0
2、因为2L+1=R,所以R是奇数,并且由于D=5,D+G=R,所以R=7或R=9
3、因为O+E=O,所以E=0或E=9,因为T=0,所以E=9,R=7,G=1
4、因为2L+1=R,所以L=3或L=8,因为E=9,2A+1=E,所以A=4,L=8
5、剩下N、B、O还未确定,即2、3、6未知。
N+7=B或N+7=10+B所以B=3,N=6,O=2