微信的H5支付,网上似乎没有官方的DEMO,所以我这边自己写了一个,还是很好用的。
有需要的同学可以直接拿走,改一改就直接可以使用
首先,我们有两个必备文件 ,wxpay.php(支付页面),notify.php(回调页面),
上图为完整的H5支付代码
还需要附上个function
function http_post($url, $data)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
$res = curl_exec($ch);
curl_close($ch);
return $res;
}
get_client_ip为百度到的方法,大家可以自行百度一下即可。
最后结合上篇我发的JS长轮询,就可以轻松实现微信H5支付
本文将讲解如下内容:
PHP原生进程函数介绍PHP实现多进程代码
01PHP原生进程函数
虽然说PHP是世界上最好的语言,但是对于PHPer们来说,对多进程、进程管理还是相对陌生的。本文将讲解一下使用PHP原生代码如何实现多进程。
首先我们要了解PHP实现多进程的函数,如pcntl_fork、pcntl_wait、pcntl_waitpid等。
pcntl_fork ( void ) : int
这个函数的作用是创建子进程,并且返回 int 类型的进程ID,父进程和子进程都是从fork的位置开始向下继续执行。
子进程创建成功时,在父进程执行线程内返回产生的子进程的PID,在子进程执行线程内返回0。创建失败时,在父进程上下文返回-1,不会创建子进程,并且会引发一个PHP错误。
pcntl_wait ( int &$status [, int $options = 0 ] ) : int
这个函数的作用是等待或返回fork的子进程状态。此函数会挂起当前进程的执行,直到一个子进程退出或者受到一个信号要求中断当前进程或者调用一个信号处理函数。如果一个子进程在调用此函数时已经退出,此函数立刻返回。
此函数返回退出的子进程号,发生错误时返回-1,如果提供了WNOHANG作为option并且没有可用子进程时返回0。
pcntl_waitpid ( int $pid , int &$status [, int $options = 0 ] ) : int
这个函数的作用是等待或返回fork的子进程状态。调用这个函数会挂起当前进程的执行,直到参数pid指定的进程号的进程退出,或者接收到一个信号要求中断当前进程或调用一个信号处理函数。
pcntl_waitpid()返回退出的子进程进程号,发生错误时返回-1,如果提供了 WNOHANG作为option,并且没有可用子进程时返回0。
pcntl_signal ( int $signo , callback $handler [, bool $restart_syscalls = true ] ) : bool
这个函数的作用是安装信号处理器,为signo指定的信号安装一个新的信号处理器。
signo为信号编号。
handler为信号处理器,可以是用户创建的函数或方法,也可以是系统常亮SIG_IGN(忽略信号处理程序)或 SIG_DFL(默认信号处理程序)。
restart_syscalls 指定当信号到达时系统调用重启是否可用。
函数返回值为bool型,成功时返回true,失败时返回false。
02PHP实现多进程代码
如有疑问,可以留言相互讨论。
这里简要介绍一下在PHP语言中实现邮件发送的两种方法,分别是使用socket发送和使用mail()函数发送的方式。
1.使用socket发送原理:使用fsockopen函数打开一个Internet连接,函数的参数列表为fsockopen(string hostname,int port,int [errno],string [errstr],int [timeout]),这里由于要使用SMTP协议,所以端口号是25.在打开连接成功后,会返回一个socket句柄,使用它就可以像使用文件句柄一样,可使用的操作有fputs(),fgets(),feof(),fclose()等。该函数的返回值有以下几种:
220 服务就绪(在socket连接成功时,会返回此信息)221 正在处理250 请求邮件动作正确354 开始发送数据500 语法错误,命令不能识别550 命令不能执行,邮箱无效552 中断处理:用户超出文件空间但是,需要注意的是使用socket发送要保证开启php的fsockopen()函数,你可能需要:
php.ini文件中查找allow_url_fopen = On 确保该项值为Onphp.ini文件中查找;extension=php_openssl.dll 如果前面有分号,去掉分号重启web服务器,apache或IIS这里有个开源的发送邮件类可供直接发送邮件,使用的是socket发送原理,亲测可用,供大家参考:sendmail.zip
2.使用mail()函数发送:mail()函数是PHP语言自带的一个邮件发送函数,但是并不代表使用它可以直接进行邮件发送,需配置php.ini邮件信息、需要类似sendmail这样的组件支持。
(1)下载sendmail软件(如果你是用xampp,那里面直接就带了),下载地址:http://www.glob.com.au/sendmail/,解压到D盘,供下列步骤(2)中的sendmail.path填写
(2)配置php.ini,需配置内容如下:
[mail function]; For Win32 only.SMTP = localhostsmtp_port = 25; For Win32 only.sendmail_from = 417204900@qq.com; For Unix only. You may supply arguments as well (default: "sendmail -t -i").sendmail_path ="D:/sendmail/sendmail.exe -t -i" (3)配置sendmail.ini,需配置内容如下:
smtp_server=smtp.qq.comsmtp_port=25smtp_ssl=autoerror_logfile=error.logdebug_logfile=debug.logauth_username=yourname such as 12@qq.comauth_password=yourpassword such as 123456pop3_server=pop3_username=pop3_password=smtp_server=,这个需要填写你想选用的smtp服务器,可以选择本地搭建,也可以选择163、QQ、gmail(如果是gmail需要服务器启用ssl_module modules)的smtp或者pop3服务器。注意第一次使用建议把debug_logfile=debug.log前面的;去掉,这样可以记录每次发送邮件的具体信息了,如果发生错误可以在error.log里面找到。auth_username=、auth_password=需要填写你的stmp账户信息(具体可以Google一下),如果是pop3则对应填写。填写一类就可以了。
(4)测试代码
<?$now = date("Y-m-d h:i:s");$from_name='IECspace';$from_email ='417204900@qq.com';$to='764739533@qq.com';$headers = "From: <$from_name>";$message= "这是一封来自 <$from_email>的测试邮件.";$subject = "[$now] 邮件测试";if (mail($to, $subject,$message,$headers)) {echo "success!";} else {echo "fail…";}?>3.另一个开源邮件发送包:PHPMailer,下载地址:http://sourceforge.net/projects/phpmailer/files/。下载完成后,直接查看里面的example文件夹,有各种例子,很详细~~~赞一个
PHP生成不重复的唯一会员卡号,或者字符串。巧妙利用了36位进制生成,并且能够验证会员卡号或字符串的真伪。在 PHP 编程时会遇到生成一组数字或者是数字与字母组合不重复的字符串或会员卡号。生成的编号有位数限制,比如5位的车牌号、10位的某证件号码、订单流水号、短网址等等,我们可以使用36进制计算出符合位数的不重复的编号。 将 0-Z(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ)分别代表数值0-35,如字母Z代表35。这样如果要得到一个5位的编号,最大信息量就是36的5次方了,36^5 = 60466176,即最大的5位编号相当于10进制的数字:60466176。例如某俱乐部需要对会员发放会员卡,会员卡号由10位字符组成,卡号的组成由3位城市编号+5位卡号编码+2位校验码组成。城市编号用区号表示,如010代表北京,5位卡编号则由36进制的卡编号组成,后面两位校验码则是通过一定的算法生成的,校验码的用处是可以验证卡号的合法性。这样我们生成的10位卡号在每个城市可发放6000多万会员卡,并且是不重复唯一的卡号。使用PHP进行进制转换,将10进制转换成36进制。class Code{// 密码字典 private $dic = array( 0=>'0', 1=>'1', 2=>'2', 3=>'3', 4=>'4', 5=>'5', 6=>'6', 7=>'7', 8=>'8', 9=>'9', 10=>'A', 11=>'B', 12=>'C', 13=>'D', 14=>'E', 15=>'F', 16=>'G', 17=>'H', 18=>'I',19=>'J', 20=>'K', 21=>'L', 22=>'M', 23=>'N', 24=>'O', 25=>'P', 26=>'Q', 27=>'R',28=>'S', 29=>'T', 30=>'U', 31=>'V', 32=>'W', 33=>'X', 34=>'Y', 35=>'Z' ); public function encodeID($int, $format = 8) { $dics = $this->dic; // 进制数 $dnum = 36; $arr = array(); $loop = true; while ($loop) { $arr[] = $dics[bcmod($int, $dnum)]; $int = bcdiv($int, $dnum, 0); if ($int == '0') { $loop = false; } } if (count($arr) < $format) $arr = array_pad($arr, $format, $dics[0]); return implode('', array_reverse($arr)); } public function decodeID($ids) { $dics = $this->dic; // 进制数 $dnum = 36; // 键值交换 $dedic = array_flip($dics); // 去零 $id = ltrim($ids, $dics[0]); // 反转 $id = strrev($id); $v = 0; for ($i = 0, $j = strlen($id); $i < $j; $i ++) { $v = bcadd(bcmul($dedic[$id{$i}], bcpow($dnum, $i, 0), 0), $v, 0); } return $v; }}首先定义一个 Code 类,Code 类里面定义了密码字典,即 0-Z 分别对应的数值,方法 encodeID($int, $format) 中参数 $int 表示数字,$format 表示位数长度,例如:encodeID(111111,5) 表示将数字 111111 转换成5位的36进制编号,而方法 decodeID($ids) 用于将 36 进制的编号转换成 10 进制的编号。使用 Code 类生成卡号$code = new Code();$card_no = $code->encodeID(13171,5);通过上面的代码可以得到一个5位的编号:00A5V,其中数字 13171 代表会员数字编号,这个数字编号是唯一的,可以使用会员在数据库内的唯一数字标示,例如数据库自增的数字ID。下面添加3位城市编号和2位校验码。城市编号是已经定义好的,校验码则通过一定的算法取得,本例中,我们使用简单的算法:将前3位城市编号和5位卡编号进行md5加密,然后取md5值的前2位作为校验码,这样就得到了编号后面的两位校验码。$card_pre = '010';$card_vc = substr(md5($card_pre.$card_no),0,2);$card_vc = strtoupper($card_vc);echo $card_pre . $card_no . $card_vc;输出:01000A5VB0实际应用中,可以通过数据库得到10进制的编号,保证5位的编号唯一,再将上述代码组合,最终生成一个10位的不重复的会员卡号。
PHP在默认的情况下是不支持多线程的,通过安装pthreads扩展,让其参数来指定编译PHP的线程安全方式来使其支持多线程,但是使用的过程中要考虑到线程安全的问题
线程是操作系统中进行运算调度的最小单位。它被包含在进程中,是进程中的实际运作单位。今天将要分享的是线程知识是有关于PHP的,具有一定的参考价值,希望对大家有所帮助
多线程的理解
所谓多线程就是在在一个进程中可以并发多个线程,每条线程并行执行不同的任务。多线程大大提高了程序的执行效率,一个多线程比单线程被操作系统调度的概率更大。而且更高效。多个线程可以在多核CPU的多个核心同时运行,加快了运行效率。而且线程间的通信更加简单。
PHP多线程
在默认情况下PHP是不支持多线程的,要使用多线程需要安装 扩展,目前常用的扩展有pcnlt,POSIX ,pthreads,但是用的最多的还是pthreads扩展,它通过使用参数来指定来编译PHP时的线程安全方式,使其支持多线程
在使用线程之前首先要考虑到线程的安全问题,线程安全指的是某个函数或函数库在多线程环境中被调用时,能够正确的处理多线程之间的共享变量,使得程序的功能能够正确完成
例:
在多线程中由于存在共享变量,很有可能会导致出现以下问题:
存在一个全局数组:$arr = array('a');
A 线程获取数组长度为1;
B 线程获取数组长度为1;
A 线程pop出数组元素 $a = array_pop($arr); $a = 'a';
B 线程也pop数组元素 $b = array_pop($arr); $a = null;
但是此时B线程内就出现了错误事件,虽设置了数组长度大于0,但是没有 pop值来
PHP实现线程安全
PHP实现线程安全主要通过 TSRM 机制,通过此机制可以对全局变量和静态变量进行隔离,并且给每个线程都复制了一份全局变量和静态变量。各个线程使用的都是主线程的一个备份。这样就避免了变量冲突,也不会发生线程安全的问题。
PHP 对多线程的封装保证了线程安全,所以开发人员就不需要在考虑读写冲突的问题了,也使得代码更加安全。不过这样做也有不好的地方,例如当子线程开始运行时,主线程便再也无法对子线程运行细节进行调整了,失去了消息传递能力
以上就是php多线程是什么意思的详细内容,更多请关注php中文网其它相关文章!
所谓多语言网站,其实就是指:
服务器根据浏览器发出请求时的Accept-Language的信息,来对应返回给浏览器相应的语言内容的网页。
请求协议中,有如下一项:
详细代码如下:
其中zh.php语言包中的内容为:
en.php语言包中的内容为:
用文件的方式读写,一个文件是索引文件,另一个文件是真实的数据文件。
索引文件分为2部分,第一部分是所有的指针,记录第二部分的位置;第二部分是索引记录。所有的索引指针:是记录所有相同Hash值的key的指针,它是一个链表结构,记录在数据文件的位置和同key的下一个值。
索引记录中:每条记录有四部分,第一部分4个字节,是下一条索引的偏移量;第二部分是该记录的key,128字节;第三部分是数据偏移量,4个字节;第四部分是数据记录长度,4个字节。
我们设定文件的存储上限为262144个。
查找流程如下:
1、根据key算出hash值,获取该hash值的链表在索引文件的第一部分(所有指针区)的位置。
2、根据步骤一的位置,获取值,时间复杂度O(1);
3、根据步骤一中的值,找到索引文件中第二部分(索引记录)的位置,也就是和key相同hash值的所有指针的链表。顺着链表查找该key,获取该key在链表中存放的数据,数据只包含该key在索引文件中的位置,时间复杂度为O(n);
4、根据步骤二所获取的key在索引文件位置,得到索引文件中存放该key的信息。信息包含在真实数据文件中存放真实数据的位置。
5、根据步骤三所获取的位置,在真实数据文件中获取数据,并返回给应用程序。
测试结果:插入10000条耗时:793ms。查找10000条耗时:149ms。虽然这效率只有Redis的十分之一。。。但是请不要在意这些细节。
代码做了注释,上述文字有些乱。代码只实现三个方法,一个插入(如果存在则跳过),一个是查找,一个是删除。
基本图像处理技术
总体理解:
1,创建(得到)一个图像资源(resource)——它相当于一个“画板”(画布)
2,在该画板上进行“绘制图线”;
3,将该画布输出到网页上显示出来,或保存为图片文件。
图像处理技术,需要先到php.ini中,开启“gd”模块:
创建画布
操作画布:
将画布输出为图片
载入图片应用:
今天benny要跟大家说这个其实很简单,就是借用某一个平台的短信api接口实现短信验证,说简单呢,那是因为他的官网:http://www.ucpaas.com上有开发文档,它可以教会一个小白很快的运用它的接口,并开发自己的应用。这个官网还算人性化的,因为你一注册,就给了你10块钱的测试费用来尝试使用它的api,你要知道一条短信0.055元,10块钱给你拿来学习测试已经够多啦!
首先,你进入官网,注册,然后你就点击开发文档:
这里有详细的介绍你怎么用它的东西,我就不在这里bb啦,看完后我们就直接下载一个php的demo文件来试试!!
下载后,你就可以看到一个封装的类Ucpaas.class.php和一个index.php的文件:
上面的注释有详细的解释,要用到的参数啥的,你注册了账号后也就自然有了,多看几遍,有点基础的人几分钟内就可以看得懂的啦!
接着,你就开始阅读官网下面目录的内容:
这里有详细的介绍,我就只是做一个引导吧,具体的大家去阅读哦。
最后,我把这个短信验证功能在我的项目上实现了,你可以看下我的代码截图:
<?php
//载入ucpass类
require('library/Db.class.php');
require_once('library/Ucpaas.class.php');
//初始化必填
$options['accountsid']='******';(这个不能给大家看哦)
$options['token']='******';(这个不能给大家看哦)
//初始化 $options必填
$ucpass = new Ucpaas($options);
//开发者账号信息查询默认为json或xml
header("Content-Type:text/html;charset=utf-8");
//短信验证码(模板短信),默认以65个汉字(同65个英文)为一条(可容纳字数受您应用名称占用字符影响),超过长度短信平台将会自动分割为多条发送。分割后的多条短信将按照具体占用条数计费。
// 验证码短信:同一个手机号1分钟内不能超过2条,24小时内不能超过8条
$appId = "****";(这个不能给大家看哦)
$to=$_POST['to'];
$templateId = "244286";
$string='';
for ($i=0; $i <4 ; $i++) {
$string.=rand(0,9);
}
$param=$string;
$db = new DB();
$sql ="select * from mr_user where username = :username";
$user = $db->row($sql,array('username' =>$to));
//用户名存在
$id=$user['id'];
if ($user){
$password=md5($param);
$update_sql = "update mr_user set password ='$password' where id='$id'";
$result_id = $db->query($update_sql);
if ($result_id){
$data=$ucpass->templateSMS($appId,$to,$templateId,$param);
$re='';
$arr = json_decode($data,true);
foreach ($arr as $key => $value) {
if ($key=='resp') {
foreach ($value as $key2 => $value2) {
if ($key2=='respCode') {
$re=$value2;
}
}
}
}
if ($re=='000000') {
echo 1;//短信已发送!
}elseif ($re=='105147') {
echo 3;//短信发送太频繁
}else{
echo 2;//号码输入有误
}
exit(0);
}
else{
echo 0;//短信发送出错!
}
}else {
$data=$ucpass->templateSMS($appId,$to,$templateId,$param);
$re='';
$arr = json_decode($data,true);
foreach ($arr as $key => $value) {
if ($key=='resp') {
foreach ($value as $key2 => $value2) {
if ($key2=='respCode') {
$re=$value2;
}
}
}
}
if ($re=='000000') {
$addtime = time();
$insert_sql = "insert into mr_user(username,password,addtime) value(:username,:password,$addtime)";
$result_id = $db->query($insert_sql,array('username' =>$to,'password'=>md5($param)));
if ($result_id){
echo 1;//短信已发送!
}else{
echo 0;//短信发送出错!
}
}elseif($re='105147'){
echo 3;//短信发送太频繁
}else{
echo 2;//号码输入有误
}
}
图|来源截图
不当你的世界 只作你的肩膀
○
Benny
○
技术帖
主要介绍优先队列,通过优先队列引出堆, 然后写了一个类(php代码)实现了大根堆
优先队列
定义
优先队列是计算机科学中的一类抽象数据类型。优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;优先级相同的元素按照其在优先队列中的顺序得到服务。优先队列往往用堆来实现。
特点
普通队列:先进先出,后进后出优先队列:出队顺序和入队顺序无关,和优先级相关
.现实用途现实用途
动态任务处理中心(操作系统)
为什么使用优先队列
问题
在1000000个元素中选出前100名在N个元素中选出前M个元素
解决方法
排序,时间复杂度O(NlogN)使用优先队列:时间复杂度(NlogM)
优先队列的实现对比
堆
定义
堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质。
任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
用数组存储二叉堆
代码实现
<?phprequire('../Library/SortTestHelper.php');/** * 最大堆 */class MaxHeap{ private $data; private $count; public function __construct(){ $this->data = array(); $this->count = 0; } // public function __construct($arr){ // } public function insert($item){ //从1开始 $this->data[$this->count + 1] = $item; $this->_shiftUp($this->count+1); $this->count++; } public function extractMax(){ $ret = $this->data[1]; swap( $this->data, 1 , $this->count); $this->count--; $this->_shiftDown(1); return $ret; } public function getMax(){ return $this->data[1]; } public function isEmpty(){ return $this->count == 0; } public function getData(){ return $this->data; } /** * [_shiftUp 新加入到堆中的元素直接放在数组后面,再与父元素比较后交换位置,直到根节点] * @param [type] $k [description] * @return [type] [description] */ private function _shiftUp($k){ //如果叶子节点的值比父元素大交换位置,并更新k的值 while( $k > 1 && $this->data[(int)($k/2)] < $this->data[$k] ){ // swap( $this->data[(int)($k/2)], $this->data[$k] ); swap( $this->data, (int)($k/2) , $k); $k = (int)($k/2); } } /** * [_shiftDown 元素出堆的时候,需要维护此时的堆依然是一个大根堆, 此时将数组元素的最后一个值与第一个值交换,后从上往下维护堆的性质] * @param [type] $k [description] * @return [type] [description] */ private function _shiftDown($k){ //2k代表该节点的左子节点 while( 2*$k <= $this->count ){ $j = 2*$k; //判断右节点是否存在,并且右节点大于左节点 if( $j+1 <= $this->count && $this->data[$j+1] > $this->data[$j] ) $j ++; if( $this->data[$k] >= $this->data[$j] ) break; // swap( $this->data[$k] , $this->data[$j] ); swap( $this->data, $k , $j ); $k = $j; } } } $head_obj = new MaxHeap(); $n = 10; for ($i=0; $i < $n; $i++) { $head_obj -> insert(rand(0, 1000)); } print_r($head_obj -> getData()); while (!$head_obj -> isEmpty()) { echo $head_obj -> extractMax()." "; } ?>
结果
生成的堆为: Array ( [1] => 916 [2] => 776 [3] => 590 [4] => 615 [5] => 764 [6] => 539 [7] => 95 [8] => 167 [9] => 23 [10] => 374 ) 打印大根堆为: 916 776 764 615 590 539 374 167 95 23
作者:吴小琪