路一步一步走,事一件一件办
1.文档阅读
自己已有博客文档,和网上所有的资料,这里就暂时不列出了。
2.整理输出 Note
这里的内容,并一定是正确的,都是我基于当下的学习思考得出的答案,并且回一直保持更新,验证,迭代
请谨慎参考,思考,保持自己的判断力,同时欢迎交流探讨。
2.1) 20220928 之前
问题汇总-临时 1. php:require_once与require的区别 解答: 框架中入口脚本以及其他地方使用 require而不是require_once 的原因,应该是因为框架开发者,知道这是第一次加载,所以使用require, 使用require_o反而会有多余的性能开销,因为要检测是否已经加载。
而且,有些地方是需要利用两者之间的区别,故意为之,不是说,多加载一次就是有问题,有时候就是需要多加载一次, require相当于复制代码到当前文件中,而且不需要每次都检查是否已经引入。
另外,当混合使用require和require_once时,第三个文件,使用require_once会失效,本质上还是因为使用require代表复制代码的含义.
2. 当两个类,在第一个类中使用第二个类的构造函数,如下: 「Component::__construct($config); // 构造函数还能这么使用?TBD」 在第二个类的构造函数中调用$this->init方法,会依次调用第二个类的init和第一个类的init ? --- TBD --------- 从Yii框架中看,似乎是这样,需要使用PHP原生语法来实践验证一下
3. PHP的配置优化 -------------- 与框架的优化,存在交叉,而且这是必然的 Yii 1. 请尽量不要注册太多引导组件【框架启动时】。只有他需要在 HTTP 请求处理的全部生命周期中都作用时才需要使用它。 2. 在生产环境中,可以开启字节码缓存,比如 APC, 来进一步最小化加载和解析 PHP 文件所需的时间。 3. 一些大型应用都包含有非常复杂的应用配置, 它们会被分割到许多更小的配置文件中。 「文件放到一个文件中和放到多个文件中的差别,和性能开销?TBD」 此时,可以考虑将整个配置数组缓存起来, 并在入口脚本创建应用实例之前直接从缓存中加载 「意思是放到内存中,如:redis?但是会存在网络开销吧」
Laravel中的配置生成缓存的方式,是怎样的?TBD
4. TBD
4. url中%2F代表着什么,有什么影响?
https://www.jianshu.com/p/c458b5c6c280
因为有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,
那么就要使用他们的编码了。 编码的格式为:%加字符的ASCII码,即一个百分号%,后面跟对应字符的ASCII(16进制)码值。
例如 空格的编码值是"%20"。 如果不使用转义字符,这些编码就会当URL中定义的特殊字符处理。
下表中列出了一些URL特殊符号及编码 十六进制值 1.+ URL 中+号表示空格 %2B 2.空格 URL中的空格可以用+号或者编码 %20 3./ 分隔目录和子目录 %2F 4.? 分隔实际的 URL 和参数 %3F 5.% 指定特殊字符 %25 6.# 表示书签 %23 7.& URL 中指定的参数间的分隔符 %26 8.= URL 中指定参数的值 %3D
urlencode是一个函数,可将字符串以URL编码,用于编码处理。
URL编码(URL encoding),也称作百分号编码(Percent-encoding), 是特定上下文的统一资源定位符 (URL)的编码机制。
适用于统一资源标识符(URI)的编码,也用于为"application/x-www-form-urlencoded" MIME准备数据, 因为它用于通过HTTP的请求操作(request)提交HTML表单数据。
5. 相对路径和绝对路径的区别?
相对路径和绝对路径可相互转换,转换时候注意正确路径即可,作用在于有效链接路径。
通常
对于外部资源,稳定资源使用绝对路径。如:CSN上的静态资源,html/css/js等
对于内部资源,内部项目的文件引用等,推荐使用相对路径,可以达到项目整体的完整性,容易迁移,打包,跨设备/平台。
6. 关于省略入口脚本的原理 Yii: 注意: 如果你想在URL中隐藏入口脚本名称,除了要设置 showScriptName 为 false,
同时应该配置 Web 服务,处理当请求 URL 没有特殊指定入口脚本时确定要执行哪个PHP文件,
如果你使用 Apache Web server,你可以参考安装中推荐的配置。
可以知道,本质上还是web http server来控制的,因为所有的请求第一站都是web server,
所以一定要指定默认的缺省脚本,web server才知道接下来怎么走,
接下来就到了框架的入口脚本里面。
接下来的url的路由匹配规则,则由框架来控制的,毕竟框架已经拿到了url,
你想按照什么规则进行解析都行,而且即便切换解析规则,也无所谓。
这就是yii支持的默认 url格式,/index.php?r=post%2Fview&id=100 美化url格式 -- /posts/100
Yii这里美化的url格式的规则rule,本质上跟laravel的路由匹配规则没多大区别 只不过yii是可选项,laravel是必须项
7. 为什么在写PHP框架,以及使用框架时,用到命令空间,要用到// ?
因为拼接字符串,/存住转义的特殊含义,想要使用/字符串,就必须转义该字符/,也就是//
$controllerClass = '/htttp/controllers//' . $IndexController;
new $controllerClas; // 1. 正确实例化,2. 可以实现自动加载
8. 二级域名的原理和实现?在本机电脑上实践
参考下:
🔥二级域名的创建、配置和解析,买一个域名,有无限个域名可以使用的方案。 - 掘金
CN为顶级域 abc.cn为一级域 www.abc.cn 、mail.abc.cn、help.zzy.cn为二级域
简单说:
配置步骤
1. 到域名服务商那里配置/增加二级域名,txt记录类型「按照步骤指导进行即可,具体细节这里不展开」
2. 服务器开始配置使用该子域名,即创建站点「Http web server 创建新的站点,配置文件放新的子域名, 就把该二级域名当成一个独立的域名处理即可, 这里面涉及到同一台服务器,配置虚拟主机的问题,如何区分不同的站点,关键点就在与请求头中的host字段值」
本机Mac + Docker 模拟实现
1). 配置Mac中host文件,虚拟域名
2). 配置docker容器中虚拟主机,记得重启Nginx服务「 几乎所有的服务,修改了配置文件,都要重启,当然,如果支持了热重载,热更新另言」
3). 放置项目
4). 访问二级域名站点
可以看到正常输出~~
代码:-- 上下翻翻
https://github.com/william_ning/docker-lnmp-dev-env-sh/blob/96b115fc65a3d9d036b0c1c237b92a5016b2d175/etc/nginx/conf.d/admin.yapf.test.conf
9. Yii中 -- 你可以设置URL后缀为 / 让所有的 URL 以斜线结束。 当你配置 URL 后缀时,如果请求的 URL 没有此后缀,系统将认为此 URL 无法识别。
这是 SEO(搜索引擎优化)的最佳实践。
Yii,从 2.0.10 版开始Url管理器可以配置用URL规范器来处理,相同URL的不同格式,
例如是否带结束斜线。
因为技术上来说 https://example.com/path 和 https://example.com/path/ 是完全不同的 URL,
两个地址返回相同的内容会导致SEO排名降低。
10. docker容器开发环境,在物理机中创建文件成功,但是挂载到容器中,却只能看到文件存在,
但是文件内容看不了,提示文件不存在 ls: cannot access 'BlogController.php': No such file or directory
原因未知,临时解决办法: 到容器中指定位置,在容器中手动创建该文件,可以编辑,或者到物理机中编辑。
11. 如何判断请求是一个Ajax请求的? -- Yii/Laravel/PHP
判断一个请求是否是Ajax异步请求_ajax_爱写Bug的麦洛_InfoQ写作社区
PHP如何判断是否为AJAX请求?-php教程-PHP中文网
可利用请求头中的Accept和X-Requested-With头信息来做判断。
虽然大部分 JavaScript 框架「JQuery会在请求头加一个 X-Requested-With 信息,信息内容为XMLHttpRequest,这样PHP可以使用$_SERVER这个全局数组来判别是否为Ajax请求」会自动加上X-Requested-With,特殊情况下,还是需要自定义标头。
如,可以在请求头中,手动添加:__ajax: true or false
TP里面了一个判断是ajax请求的常量IS_AJAX
这个常量定义方式:
在ThinkPHP(3.2.2)中在ThinkPHP/Library/Think/APP.class.php(Line:49)
至于TP6同Laravel -- 看过框架组织结构和源码应有判断
「TP6在判断isAjax请求上似乎存在bug -- TBD」
tp6.test/Index.php at 16ac656ff31bd5a3022b3f3493d517f90c2fca93 · ningxiaofa/tp6.test · GitHub
// http://0.0.0.0:8000/index/test?name=tp public function test($name = 'ThinkPHP6') { $request = new Request(); $ret = $request->isAjax(); var_dump($ret); return 'hello,' . $name; // Browser: // bool(false) hello,tp }
isAjax方法实现:
https://github.com/ningxiaofa/tp6.test/blob/main/vendor/topthink/framework/src/think/Request.php
/** * 当前是否Ajax请求 * @access public * @param bool $ajax true 获取原始ajax请求 * @return bool */ public function isAjax(bool $ajax = false): bool { $value = $this->server('HTTP_X_REQUESTED_WITH'); $result = $value && 'xmlhttprequest' == strtolower($value) ? true : false;
if (true === $ajax) { return $result; }
return $this->param($this->varAjax) ? true : $result; }
这里补充:
原生ajax的实现方式
JavaScript - 手写实现ajax 以及 ajax封装_穿素白衫的中少年的博客-CSDN博客
额外的话,很多时候的程序/服务实现,都可以前后端约定实现,这也是常常说的约定大于规范的表现之一。
12. _csrf token是每次请求都会变的吗?
另外,如果不是web应用,而是App应用,或者Restful api还有必要使用csrf吗?
Laravel - CSRF - 学习/实践_穿素白衫的中少年的博客-CSDN博客
第一个问题:
_csrf token是根据会话/session来改变的,一个会话/一个session文件,则有一个_csrf token,value存储在session文件中 --- 一对一关系
至于什么是会话,可以自行定义,不过个人的想法:
会话的定义: 不同的设备「mac/windows/iOS/Android/ipad等」,用户代理「chrome/firefox/postman」,
或者,相同的设备,但是cookie/session不同,也是不同的会话.
上面说的有点表面,因为他们有个前提是默认会话信息「cookie/session」不会共享「-- 限制多设备登陆,或许就是利用这个原理,TBD」
其实本质上,就是一句话,http本身无状态,状态通过cookie/session来维护,
如果请求/响应没有cookie/session的信息,那么laravel或者其他开发语言/框架,就会认为这是一个新的会话/新生产一个会话。反过来,如果cookie/session信息共享,在不同设备上,浏览器上,使用那么不会产生新的会话。
laravel中应是这样来做代码定义的。
详情参见:
Laravel - CSRF - 问题2: 如果不是web应用,而是App应用,或者Restful Api还有必要使用csrf吗?原因呢
13. 服务端获取客户端的host和ip是准确的吗? 正常来说,直接获取主机和 IP 地址等用户信息即可。
这将在正常设置中开箱即用,其中使用单个网络服务器为网站提供服务。
然而,如果您的 Yii 应用程序「不单单是Yii框架,任何的web程序都是如此」在反向代理后面运行,
则需要添加其他配置来检索此信息, 因为直接客户端【这里就是nginx】现在是代理, 并且用户 IP【客户端的用户设备的出口公网IP】 地址通过代理【Nginx】设置的报头传递给 Yii 应用程序。 也就是说,这种情况,获取到的是代理的host和ip,并不是用户的,但是代理是可以获取到用户的host和ip【主要是IP】 那么通过对代理的设置可以传递报头给应用。
除非您明确信任代理,否则不应盲目信任代理提供的报头。
从 2.0.13 开始,Yii 支持通过 request 组件的 trustedHosts, secureHeaders,
ipHeaders 和 secureProtocolHeaders 属性配置可信代理。
参见: https://www.yiiframework.com/doc/guide/2.0/zh-cn/runtime-requests#trusted-proxies ----------------------------- 不是很明白
延展问题: 获取的这个IP是公网IP还是私有IP,还是两者都可以获取?
应该具体结合情况分析,一般如果没有配置DHCP/或者不需要DHCP的话,应该是没有私有IP的,
服务器一般只要使用公网IP即可,所以,通常获取的是公网IP,尤其是web server 和 应用程序server部署在同一台主机。
14. 如果您的 Yii 应用程序在反向代理后面运行,这个怎么实现?
我们平时搭建的LNMP架构,运行的应用程序就是运行在Nginx的后面,通过fastcgi_proxy进行配置的
fastcgi「指令fastcgi_pass」反向代理,简单的代理服务器,可以通过proxy_pass指令。
server {
location / {
proxy_pass http://localhost:8080;
}
location /images/ {
root /data;
}
}
Beginner’s Guide -- 其中有详细说到,可以认真看下
不,突然,意识到,似乎并不是这样,还需要求证。
似乎又是这样。
What is a Reverse Proxy vs. Load Balancer? - NGINX
2.2) 20220928
1. PHP的错误/异常处理机制
参见
PHP - 异常/错误 - 学习/实践_穿素白衫的中少年的博客-CSDN博客
2. 之前csdn网友评论 --- 高性能服务器模式的解答
TBD
正在解决中,但是在回答中又出现不少的问题,还在学习实践当中
20221011
3. Go的项目开发 -- 学习实践
Go - 项目布局/Layout - 学习/实践_穿素白衫的中少年的博客-CSDN博客
开发一个demo项目 -- 推荐使用go将自己的idea之一实现
4. swoole & hyperf, mongodb -- 简单地使用
TBD
开发一个demo项目 -- 推荐使用go将自己的idea之一实现
5. 负载均衡的搭建
负载均衡器/LB - 学习/实践_穿素白衫的中少年的博客-CSDN博客_lb负载均衡器
本机上使用Docker进行搭建 -- TBD
6. 回顾HTML+CSS+JS Vue/React/Angular的区别,主要是Vue,以及uni-app的开发 「至少要知道开发流程,以及评估开发难度和工作量,学习成本」
TBD
7. 还有之前的各种尾巴
之前的尾巴即最上面的各种问题,已解决
8. route+mvc如何快速实现一个php框架
已完成,参见
下面的两个框架,其实是一个
GitHub - ningxiaofa/yapf: Create your own php framework from zero [Practice]
GitHub - ningxiaofa/new_framework: Learning & practice
最好记住/思考实现的思路。
9. 小游戏开发的整个流程以及目前的状况调查。
TBD
10. 从从0-1的项目设计开发的整个流程 -- 再次梳理一遍,如果拿到一个新的项目,
如何快速开发完毕【尤其是数据库设计这块,可能还要系统快速地回顾学习一遍】 「这是作为技术负责人必须要掌握的,能够解决的」
整理出文档,链接放到这里
11. 游戏开发与普通的web开发的区别?
游戏后端开发与普通web应用的后端开发的区别?
对于PHP呢?
TBD
目前看来,区别如下:TBD
游戏开发: 尽管游戏种类很多,但本质上都是C/S架构,
Client端程序App...
通常C/C++,Java,Go,Python,Lua进行开发,
TBD
普通的web开发
12. 支付功能如何实现?
TBD
13. App开发到上线「上架」的整个流程?
TBD
14. SDK本质是什么?如何实现/发布自己的SDK工具包?
SDK,Software Develop Kit // 软件开发工具包
「个人理解」从名字就知道,用户软件开发/编程中,而且是工具包,也就意味着,很多工作都提供SDK的服务商/提供商已经都处理好了,通常开发时,只要关注SDK提供的基础API列表「当然也有可能有基础的API封装的高级API」,只要自己引入SDK「对应编程语言的SDK」,结合自己的业务逻辑,合理正确使用SDK的API,实现功能即可。
如何实现/发布自己的SDK工具包?
SDK通常由软件服务商来提供,主要用来更好地提供自己的软件服务,让用户/客户愿意使用,并可能为此付出费用,SDK本身本质上就是用各种各种的编程语言编写的软件包,通常表现为很多类文件,当然也可能不只是OOP,而是面向过程编程的方式组织的很多脚本文件「这只是编程思想和方式的区别,实现上,本质上是一样的」,从而提供对外的API列表「也是类方法,或者 函数」,当然,服务提供商也要提供对应服务的API服务,否则,肯定是不行的。
举例子:
你想使用某些云服务商的数据库服务,需要下载他们的SDK工具包
然后引入到项目中,并查看SDK提供的API「通常有连接(验证和授权),关于数据表的CRUD的API」,当然,云服务商的数据库要提供这些对外暴露的API接口,来接收请求,从而完成操作。
其他的场景本质上也是相同的。
2.3) 难解的问题 -- 时间不定
MySQL
1. MySQL读取数据的磁盘IO次数,开销是怎样的? 那么在实际的应用中,到底应该构建多少叉树呢?是不是树的节点越多,即 n 越大越好?我们知道,操作系统对磁盘的访问是以页为单位读取的,每页的大小通常是 4KB,也就是说我们只需要将 n 叉树的每个节点存储为一页大小左右,这样每次访问都能够整页读取,不会进行多余的磁盘 IO 操作。
针对这种数据存储的方式,如果我们还是用上述的那种二叉树结构的话,每访问一层节点就对应着一次磁盘 IO,那这样的查询速度还是太慢了。
MySQL每次读取数据的数据页是16KB,缓存页也是16KB--内存
在计算机中,磁盘存储数据最小单元是扇区,一个扇区的大小是512字节。 文件系统中,最小单位是块,一个块大小就是4k; InnoDB存储引擎最小储存单元是页,一页大小就是16k。
因为B+树叶子存的是数据,内部节点存的是键值+指针。索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中,进而再去数据页中找到需要的数据;
假设B+树的高度为2的话,即有一个根结点和若干个叶子结点。这棵B+树的存放总记录数为=根结点指针数*单个叶子节点记录行数。 如果一行记录的数据大小为1k,那么单个叶子节点可以存的记录数 =16k/1k =16. 非叶子节点内存放多少指针呢?我们假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,所以就是8+6=14字节,16k/14B =16*1024B/14B = 1170
因此,一棵高度为2的B+树,能存放1170 * 16=18720条这样的数据记录。同理一棵高度为3的B+树,能存放1170 *1170 *16 =21902400,也就是说,可以存放两千万左右的记录。B+树高度一般为1-3层,已经满足千万级别的数据存储。
Note: 如果一行记录为1KB,数据量超过2千万,则会突破B索引树高度3,为4,磁盘IO增加。而且页增加了比较计算的时间【参考于原来的操作】
每次查找数据时把磁盘IO次数控制在一个很小的数量级,最好是3次。
2. 页分裂是什么?触发页分裂的场景有哪些?
场景: 1. 个问题似乎不难理解,当我们不断插入数据的时候,B+ 树中的节点肯定会越来越多,
直到大于了页大小,这时,为了维护查询的效率,不产生多余的 IO 操作,我们不得不进行节点的重构。 假如叶子节点的数量是 m,当节点数量大于 m 的时候,该节点就会分裂。
3. 数据表行记录的大小会影响磁盘IO吗,如何影响的?
Redis
1. 17 | 跳表:为什么Redis一定要用跳表来实现有序集合? https://time.geekbang.org/column/article/42896
2. AVL树简介 AVL树的名字来源于它的发明作者G.M. Adelson-Velsky 和 E.M. Landis。-- 苏联数学家 AVL树是最先发明的自平衡二叉查找树(Self-Balancing Binary Search Tree, 简称平衡二叉树)。-- BST
2.4) 20221002 国庆第二天,周日 这是自己默写PHP 开发框架时的疑惑。 下面的两个框架,其实是一个 GitHub - ningxiaofa/yapf: Create your own php framework from zero [Practice] GitHub - ningxiaofa/new_framework: Learning & practice 最好记住/思考实现的思路。
1. composer的autoload是干嘛用的? 用来解决composer组件加载使用的
2. 文件路径【绝对路径和相对路径】的正确使用 均可
3. spl_autoload_register的正确用法 参数是一个闭包函数,可以是一个匿名函数,也可以是/namespace/class::load这样的类静态方法,具体实现,即引入文件,不需要一遍遍手动引入
4. MVC如何分割, 其中model层是怎么实现的? 可以借助已有数据库框架来实现,如:Medoo 底层还是借助,PDO,ORM, 以及拼接SQL语句来实现,只不过过程繁琐,需要花费比较多的时间去做.
5. 数据库连接一直报错的原因和解决办法,同时如何将连接独立出来? 数据库连接报错,可能的原因有: 客户端 --> 客户端配置缺失,信息不正确 网络 --> 网络连接不通,网络不稳定 服务端 --> 服务端服务不正常 每个环节都有可能,逐一排查即可.
如何将连接独立出来: 单独写一个数据库连接类,而且推荐做成单例模式, 全局可访问.
2.5) 20221002 国庆第二天,周日
1. php中exit()与die()的区别
PHP: exit - Manual
PHP: die - Manual
可以看到,两者是相同的。
但,个人推荐使用exit();
而且要合理使用exit($status);中的$status,是使用int还是string
int: 0-254之间,表示状态,通常只要使用0,1即可,0: 成功终止,1: 失败,出现异常错误
string: 就是为了输出信息。
2. PHP 一个请求处理的完整流程?
「前端发起一个请求,请求到达网关层,经过负载均衡达到应用层,然后到达缓存层,没有缓存该数据,到达数据库层,最后查询到数据,经过应用层业务处理后,然后给网关,最后返回给前端」尤其是连接,进程/线程,并发模型是怎样的?
是不是这个过程中,一个请求就必然对应着一个连接,必然对应着一个进程/线程?
答案参见:
网络/Network - 网络编程 - 网络连接,请求,进程/线程的关系 - 学习/实践_穿素白衫的中少年的博客-CSDN博客_连接和线程的关系
详细文档阅读:
基于 Nginx + PHP 驱动 Web 应用(上):配置文件与虚拟主机篇
基于 Nginx + PHP 驱动 Web 应用(下):请求处理与响应发送篇
计算机网络协议系列 - HTTP 协议篇:Nginx + PHP-FPM 请求处理与响应发送完整流程 | 张凌宇
这个请求的过程中,两个组件之间都有连接,「同时记住,这个网络连接并不是一个真实的通道,就是一个虚拟的概念,本质上只是一个一堆数据结构,初始化的操作,为了接下来的数据传输做准备」
而且,一个连接「长链接」是可以承载多个相同或者不相同的请求的,即便是短链接,如果达到了最大的连接数,那么请求被阻塞等待,直到有空闲的连接,继续下去。
应用服务器与数据库之间的连接,通常使用TCP连接,当然也支持unix连接「但是不常用,只能支持同一主机内通信」可以使用短连接 或 长链接 以及连接池。
是的,这个过程中,一个请求就必然对应着一个连接,必然对应着一个进程/线程。
我们要解决的是使用有限的资源发挥最大的价值,也就是合适的进程/线程「通常根据业务场景来决定,如果是CPU密集型,那么设置为CPU物理核心数*2即可,如果是IO密集型,那么比这个数字大一点即可,有个公式:连接数 = ((核心数 * 2) + 有效磁盘数)」去处理大量的请求,至于并发同一时刻下的连接数,有多少,未必很少也未必很多,合适自己的业务就好。
3. 您好,抛个问题:
日常开发中,应用服务器与数据库服务器之间的连接使用的是哪种连接方式呢?如果查看确认呢? PHP如何实现数据库长链接,以及连接池?
4. HTTP的版本使用,是由谁来决定的?
比如,有时候请求的是http 1.0, 1.1, 2.0 甚至是3.0
TBD
「个人此刻想法,待验证:应该是由客户端和服务端共同来支持的,主流的HTTP服务器,如Nginx,Apache,应该是都是支持的,当然关于http 3.0可能还不支持,至于客户端支持哪些HTTP版本,则是由客户端来决定的,如,浏览器,所以,也是由客户端来决定采用哪种版本,而且应该有缺省版本。」
5. HTTP长连接和短连接是由谁来控制的?
「应该是客户端来决定,比如浏览器,chrome,有些低版本的chrome就只能支持短链接,
高版本可以同时支持短连接和长连接」
2.5) 20221015 周六 1. PHP的回调函数,回调通知是什么?回调函数,匿名函数,闭包的区别?
回调函数-- 产生的原因/应用场景:
工程中,我们做服务化、模块化,经常会考虑某一个模块该做什么、不该做什么。 在同一系统内部不同模块之间的沟通,大多数情况下,是通过变量来传递的。
但是变量本身不包含逻辑处理的,那我们就会希望能够把函数逻辑作为一个变量传递。 这时我们说,可以传一个回调或者闭包。
回调通知
最近听到是在看微信支付,使用到PHP SDK时。
当用户完成支付,微信「微信支付系统」会把相关支付结果将通过异步回调的方式通知商户「即回调通知」,商户需要接收处理,并按文档规范返回应答。
个人理解:
---------------- start
就是商户服务端与微信支付系统按照预定/规范设置了一个notify_url「商户服务端的一个接收请求的脚本程序」,专门用来接收微信支付系统的请求「通知」,然后商户可以根据请求的内容进行接下里业务操作。
这里为什么使用回调通知的方式:
前提有:
1. 涉及到三方:商户,用户,微信支付系统,
2. 其中有两方通信,要通知第三方:用户直接支付,向微信支付系统发请求,微信支付系统响应用户请求,但是要通知商户用户已完成支付「毕竟本质上是用户与商户之间的交易,只不过这里引入了微信支付这个第三方工具」,在这个时间段中,商户并没有请求微信支付系统,而且通过开发经验知道,应该优先使用推送的方式,性能更好「就是微信支付系统主动请求/推送内容到商户服务端」,当然商户服务端也可以主动拉取/请求微信支付系统「需要微信支付系统提供api」,获取自己想要的内容。
经过上面的分析,也可以知道其他的技术问题,
1. 不论拉取还是推送「Pull/Push」本质上都是请求「请求&响应-模型」,只不过pull通常是针对Client而言的,Push是针对Server端而言的,比较方便进行技术交流「前提是你懂」
---------------- end
衍生问题:
1. 这和Js中通过Jsonp通过传递回调函数「js函数」来解决跨域问题,本质上是一致的吗?
TBD
2. 这里回调通知,怎么知道是对应的那个交易的?另外,商户服务端如何响应用户的请求呢?
通过订单ID和第三方存储服务,如,数据库/Redis来查询,会存储订单的状态「未支付,已支付」
商户服务端如何响应用户的请求呢?
下面的流程:还需要确认
结合12306,提交订单,选择微信支付,用户手机微信扫码支付,12306给用户弹出提示框:支付完成,支付遇到问题 按钮。
如果选择了支付完成,... 应该是发送请求,向12306服务端请求,根据订单ID查询确认是否真的支付完成,如果是,显示支付订单成功的页面,会显示订单信息。
如果选择了支付遇到问题,应依然会发送请求,进行查询,是否真的异常,如果是,那么会提示重新下单,停留在提交订单页面。
回调通知是什么? TBD 回调函数,匿名函数,闭包的区别? 从理解层面,完全可以把回调理解为一个变量,只是这个变量指向的是函数的入口地址。 PHP层面,可以不用过分纠结如何区分回调和闭包,语言的关键在于使用,而不在于概念的纠缠。 回调函数,可以使用匿名函数,也可以使用有名函数。 不过优先使用匿名函数去实现,除非不能,或者导致代码重复。 2. 闭包的本质,以及PHP,Js的闭包有什么不同? TBD 3. curl能够实现同步请求,和异步请求吗?分别的应用场景? TBD 后续补充 ... |