项目演示
包括三个系统:商城前台系统、平台管理系统、商家管理系统
项目目标
初识分布式架构
系统架构
到时候会画图
服务架构
SOA架构和微服务架构
业务场景解决方案
业务场景
解决方案
商城首页
CMS系统去实现
站内搜索
ElasticSearch
商品详情页
Freemarker、Redis实现动静结合方式
前台商城登录
CAS、自定义SSO登录实现
购物车页
Cookie、Redis共同存储
下单场景
订单ID(雪花算法)、库存扣减
订单支付
对接微信支付接口
秒杀
Redis + ActiveMQ + AB
后台登录
Shiro实现
项目分类
传统企业项目:企业内部人员使用的系统,比如OA、CRM、ERP、银行系统。
页面(layUI、easyUI、Jquery)-----需要Java程序员去实现的。
开发框架:SSH(数据结构和需求都不是经常变换的)、SSM(需求变换比较多,表结构都有可能变更)
互联网项目:互联网人群使用的项目,比如京东、阿里、携程、58转转。
前后端分离:前端技术(JS、VUE、AngularJS、React)---不需要Java程序员去关心。
前后端分离的开发方式:如何设计rest风格的API(http url);
开发框架:SSM、Springboot(SpringCloud)
分布式、集群等概念。
技术应用实现
技术
项目中的应用
SSM
开发框架
Maven
项目管理工具、项目构建工具
Git
项目代码版本管理管理、团队协作工具
MySQL
关系型数据库,主要持久化存储业务数据
Vue(angularjs)
前端JS框架,主要应用于商城系统的前端页面开发
Dubbo(x)
分布式服务框架(RPC),主要应用于业务服务的监控、管理。
ZooKeeper
分布式协调服务器,主要是用来进行分布式服务的发现和注册的。
Nginx
反向代理服务器、负载均衡服务器、HTTP服务器
FastDFS\NFS
分布式文件系统,主要用来存储商城中的商品图片\商品详情页的存储
Redis
NoSQL数据库,是一个非关系型的内存数据库,可作为缓存服务器使用。
ElasticSearch
分布式搜索引擎服务,它有很多使用场景,我们目前只是用来搜索页面的实现。
ActiveMQ
消息中间件,消息模型是P2P和Topic方式
Shiro
登录认证和权限验证框架,主要应用于后台管理系统,不包括前台商城系统。
CAS
实现SSO单点登录,除了这种实现方式,也会讲解自定义实现SSO的方式
阿里云短信
短信服务
微信支付
项目计划
人员分组
每5个人分一组,选出一个人作为组长。
组长负责组织组内人员制定前后端分离开发模式下的统一RESTful api接口。。
组员负责按照统一的RESTful接口,分别实现对应的后台服务。实现过程中,可以互相讨论实现思路。
虽然组内5个人的开发实现不一致,但是相对前端页面来说,都应该是能调通的。在这个基础之上,我们可以找到最优的实现方案,分享出来,共同学习。
分组的目的是为了一起进行需求分析和技术讨论。每个人虽然做的需求都是一样的,但是在实现方案的细节处理部分还是可以有很多火花碰撞和互相借鉴的点的。通过最终的最佳方案展示,最终每个人都可以了解并掌握一套最佳的实现方案。
服务器
通过系统架构,分析需要多少服务器。
服务器的搭建需要大家自己去准备,是选择云服务(如果是这个,最好每组一套云服务就可以),还是本地虚拟机?
课程计划
第一讲:项目搭建和架构介绍
第二讲:需求分析和数据库设计
第三讲:后台登录实现和CMS实现 12月23日
第四讲:首页实现和搜索页实现 12月25日
第五讲:详情页实现和SSO实现 12月27日
第六讲:购物车实现和下单实现 12月29日
第七讲:支付实现和秒杀实现 1月3日
后续由孙玄老师给大家讲解那些百万年薪的事
第一讲:项目和架构介绍
1.项目演示
2.项目架构介绍
讲解一些建构的演变
画一下系统架构图
第二讲:项目搭建和数据库设计
1.需求分析
功能性需求分析-----非功能性需求[性能、并发、PV、UV]
需求设计文档
前台商城
首页
如何显示首页(静态HTML页面、动态jsp页面+缓存)?
分析广告位有哪些?
分析广告包含的数据有哪些信息?
搜索页
搜索条件
分析有哪些搜索筛选条件
如何动态展示搜索筛选条件
搜索结果包含哪些字段
详情页
如何显示详情页(静态HTML页面、动态jsp页面+缓存)
详情页中商品信息都有哪些?
购物车页
购物车数据存储在哪?(登录前和登录后这两种场景)
购物车数据如何分店铺显示?
如何考虑购物车中的商品数据和数据库中的商品数据的一致性问题?
促销相关处理是如何实现的?
登录页
验证码(防黑客,不防好人)
前端和后端验证
SSO登录问题(商城前台按照SOA架构拆分为多个子系统)?
注册页
手机短信如何发生与验证
前端和后端验证
订单确认页
算钱(订单金额、实付金额、运费)
提交订单功能实现(验证价格是否一致、减库存的时机和减库存的数据安全问题)
正向订单处理流程(下单--->妥投或者确认收货)
逆向订单处理流程(退货、换货)
退款流程
支付页
微信二维码如何生成
如何使用微信支付
分布式事务(最终一致性)
平台管理系统
商家管理系统
业务流程图分析
商品创建流程
商品上架流程
前台商城下单流程
订单处理流程
商家入驻流程
2.数据库设计
数据库设计文档(PowderDesigner)
关系数据库设计的范式理解
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
第一范式(1NF):列不可再分
在前面我们已经介绍了属性值的概念,我们说,它是“不可分的”。而第一范式要求属性也不可分。那么它和属性值不可分有什么区别呢?给一个例子:
Ps:这个表中,属性 “分”了。
不满足第一范式的数据库,不是关系数据库!所以,我们在任何关系数据库管理系统中,做不出这样的“表”来。
第二范式(2NF):表的唯一性
符合1NF,并且,非主属性完全依赖于码。
听起来好像很神秘,其实真的没什么。
一 个候选码中的主属性也可能是好几个。如果一个主属性,它不能单独做为一个候选码,那么它也不能确定任何一个非主属性。给一个反例:我们考虑一个小学的教务 管理系统,学生上课指定一个老师,一本教材,一个教室,一个时间,大家都上课去吧,没有问题。那么数据库怎么设计?(学生上课表)
学生
课程
老师
老师职称
教材
教室
上课时间
小明
一年级语文(上)
大宝
副教授
《小学语文1》
101
14:30
一个学生上一门课,一定在特定某个教室。所以有(学生,课程)->教室
一个学生上一门课,一定是特定某个老师教。所以有(学生,课程)->老师
一个学生上一门课,他老师的职称可以确定。所以有(学生,课程)->老师职称
一个学生上一门课,一定是特定某个教材。所以有(学生,课程)->教材
一个学生上一门课,一定在特定时间。所以有(学生,课程)->上课时间
因此(学生,课程)是一个码。
然而,一个课程,一定指定了某个教材,一年级语文肯定用的是《小学语文1》,那么就有课程->教材。(学生,课程)是个码,课程却决定了教材,这就叫做不完全依赖,或者说部分依赖。出现这样的情况,就不满足第二范式!
有什么不好吗?你可以想想:
1、校长要新增加一门课程叫“微积分”,教材是《大学数学》,怎么办?学生还没选课,而学生又是主属性,主属性不能空,课程怎么记录呢,教材记到哪呢? ……郁闷了吧?(插入异常)
2、下学期没学生学一年级语文(上)了,学一年级语文(下)去了,那么表中将不存在一年级语文(上),也就没了《小学语文1》。这时候,校长问:一年级语文(上)用的什么教材啊?……郁闷了吧?(删除异常)
3、校长说:一年级语文(上)换教材,换成《大学语文》。有10000个学生选了这么课,改动好大啊!改累死了……郁闷了吧?(修改异常)
那应该怎么解决呢?投影分解,将一个表分解成两个或若干个表
学生
课程
老师
老师职称
教室
上课时间
小明
一年级语文(上)
大宝
副教授
101
14:30
学生上课表新
课程
教材
一年级语文(上)
《小学语文1》
课程的表
第三范式(3NF):消除字段冗余
符合2NF,并且,消除传递依赖
上面的“学生上课表新”符合2NF,可以这样验证:两个主属性单独使用,不用确定其它四个非主属性的任何一个。但是它有传递依赖!
在哪呢?问题就出在“老师”和“老师职称”这里。一个老师一定能确定一个老师职称。
有什么问题吗?想想:
1、老师升级了,变教授了,要改数据库,表中有N条,改了N次……(修改异常)
2、没人选这个老师的课了,老师的职称也没了记录……(删除异常)
3、新来一个老师,还没分配教什么课,他的职称记到哪?……(插入异常)
那应该怎么解决呢?和上面一样,投影分解:
学生
课程
老师
教室
上课时间
小明
一年级语文(上)
大宝
101
14:30
老师
老师职称
大宝
副教授
数据库设计的一些技巧分析
考量需求情况,作出取舍(第一范式必须满足,其他范式都可以不满足),比如说建立很多字段的表。
表字段设计的时候,要考虑三种分类:业务字段,流程字段(状态字段),系统字段(创建时间、创建人、是否删除)
表设计的时候,要考虑业务场景:比如说统计类的场景,一般要建立统计表(定时统计多张表的数据到一张表中)
表设计的时候,考虑水平分表,按照ID进行分表。
表设计的时候,适当的冗余是必须的。
互联网项目的表设计,一定不要加上外键约束。(业务关联)
3.项目结构规划
我们的项目是使用Maven搭建的。Maven有两个重要的特性:继承、聚合。
Maven的继承目的是:为了消除重复依赖和统一管理依赖版本。
Maven的聚合目的是:为了一键构建。方便项目构建(compile、test、package、deploy、install)
|--huike-mall(POM):聚合工程、继承工程(统一管理项目的依赖版本)
|--huike-common(POM)---聚合工程 提供通用模块(比如POJO类,DAO类、Utils类)
|--huike-pojo (jar)---将mybatis逆向工程生成的pojo类,拷贝到该工程中
|--huike-dao (jar)---将mybatis逆向工程生成的mapper类和映射文件,拷贝到该工程中
|--huike-utils (jar)
---------------------------以下是表现层代码----------------------------------------
|--huike-manager-web (war)----平台管理系统的web
|--huike-business-web (war)----商家管理系统的web
|--huike-portal-web (war)(待定---如果采用静态页面方式,就不需要此工程了)
|--huike-search-web (war)
|--huike-item-web (war) (待定---如果采用静态页面方式,就不需要此工程了)
|--huike-sso-web (war)
|--huike-cart-web (war)
|--huike-order-web (war)
|--huike-pay-web (war)
|--huike-usercenter-web (war) (待定---不需要实现)
----------------------------以下是业务层代码-------------------------------------
|--huike-cms(待定---如果采用静态页面方式,需要将该工程的功能集成到manager服务中)
|--huike-cms-interface
|--huike-cms-service
|--huike-item(待定---如果采用静态页面方式,需要将该工程的功能集成到manager服务中)
|--huike-item-interface
|--huike-item-service
|--huike-search (POM)----聚合工程
|--huike-search-interface(jar)----为了dubbo使用(dubbo使用时,需要面向interface)
|--huike-search-service (war)----为了在web容器中发布dubbo服务
|--huike-sso(POM)
|--huike-sso-interface(jar)
|--huike-sso-service(war)
|--huike-cart(POM)
|--huike-cart-interface(jar)
|--huike-cart-service(jar)
|--huike-order(POM)
|--huike-order-interface(jar)
|--huike-order-service(war)
|--huike-manager(POM)
|--huike-manager-interface(jar)
|--huike-manager-service(war)
|--huike-business(POM)
|--huike-business-interface(jar)
|--huike-business-service(war)
4.项目搭建
使用maven搭建,重点需要了解maven的继承和聚合。
使用dubbo作为分布式服务框架,zookeeper作为服务注册和发现的中心。
1、SSM框架搭建及整合(spring配置文件的处理)
2、表现层和业务层使用Dubbo进行拆分(分为服务提供者和服务消费者)
服务消费者在使用dubbo配置时,一定要注意我们的dubbo配置文件一定由DispatcherServlet进行加载。
3、dubbo的相关处理(dubbo配置文件、dubbo注解[@Service、@Reference])
4、maven的相关处理(maven jar工程修改完了代码一定记得maven install)
5.服务器规划和搭建
MySQL搭建(主从、读写分离、双主、分库分表)
Maven私服搭建
ZooKeeper搭建(选择集群搭建,最少三台)
Nginx反向代理服务器搭建
第三讲:首页分析和静态化技术
1.项目代码问题
第三方依赖包的问题:一般来说,直接从中央仓库下载不下来的。
问题:如何将第三方jar包,安装到本地仓库或者私服?
启动项目是使用maven中的tomcat 7插件启动的。
这个项目是有bug的。
这里边需要连接的服务器有:redis、ES(solr)、ActiveMQ、Zookeeper、Mysql,将相关的连接配置信息,改为本地的。
2.首页分析
1.首页展示可能存在的问题是什么?
图片加载问题---Nginx(做缓存)---CDN静态访问加速。
图片压缩问题---Nginx(动态压缩)
尺寸压缩---尺寸压缩一般都是等比压缩
大小压缩---是尺寸不变的情况下,图片的大小变小了,带宽占用的就少了。
图片延迟加载问题---一屏一屏的去加载图片,而不是一次性将整个首页的图片进行加载。(lazy-load)
首页都是由很多个部分组成的。每个部分就是一个广告位,每个广告位中都会有广告。那么因此带来的问题和特点就是:局部快速更新的问题。
- 第一种方式:动态读取广告数据,只是将所有的广告都缓存到Redis中。
Redis中如何设计key,如何选择合适的数据类型(五种数据类型)。
一般key的设计,都是使用分隔符来分隔的,每一个部分都表示一个含义,比如:index:big:ad
缓存一致性问题。
查询缓存逻辑问题
- 第二种方式:静态展示,每个广告位,都是一段HTML片段,我们后台维护完广告之后,会重新生成对应的HTML页面。
需要使用freemarker或者velocity去进行页面静态化。
思路:平台管理系统--CMS---维护广告数据----页面静态化处理。
HTML对应freemarker模板文件,一般都是由前端人员写好,我们去改造HTML原页面为模板文件。
HTML-- 改为--JSP
3.静态化技术
4.实现首页静态化和动态化
后端CMS功能实现
广告位管理
广告位需要设计(唯一的标识[使用英文])—是通过功能增加的数据,那么id就是不固定的。
页面加载指定的广告位,需要通过该英文标识【比如:首页大轮播图广告位----index_big_lunbo】去加载。
广告管理
不同种类的广告位的广告【有可能广告字段也不一样】维护功能不一样。
有哪些广告位种类(每个页面都有广告)
图片广告
资讯广告
商品广告
广告都要有时间段(要根据时间段去定时替换对应的广告)
静态化实现
模板分析
按页面布局拆分
按广告位拆分
定时生成静态页
实时生成静态页
模板修改
使用freemarker的模块语法,去修改html文件为ftl文件
按照上面的模板分析,去拆分ftl文件
静态页生成
要指定对生成首页的位置(因为该位置需要通过Nginx去访问)
定时任务编写
动态化实现
缓存设计
key的设计
原先是根据【什么信息】查找数据库中的记录的
合理的设计:item:1 index:biglunbo:1
注意事项:同一个redis中的同一个key会发生数据覆盖。所以说key的设计一定要唯一且有意义。
value类型的选择
原先是从数据库中查询到哪些信息
根据【查询出的信息】的数据特点,选择对应的类型进行存储,一般使用string、hash、list
string和hash都可以存储对象数据,但是string存储的时候,值应该是对象对应的json字符串,而hash就不是了,区别在于如果只是查询的话,那么string类型更加方便。而如果修改频繁的话,使用hash类型更加方便。
一般list类型更多的是去实现请求队列等场景
有效期设计
缓存是将数据存储到内存中,而内存的使用率需要合理设计
考虑活动不频繁的数据,使用有效期,将它从内存中移除
缓存加载
页面加载时,动态去读取后台的redis缓存
不要一次性将首页的所有广告数据读取出来,要分屏读取。
要考虑数据从redis中读取,页面从Nginx缓存中读取。
第四讲:搜索页实现
1.搜索功能分析
站内搜索技术选型:solr和es都可以。
搜索功能实现注意事项:
搜索框的联想词功能。(可以从数据库查询,也可以从es库查询)
筛选条件的动态展示。(需要使用到搜索技术的聚合查询功能)
通过es的查询功能查询出来结果,在通过es的聚合功能,按照分类字段进行统计。
选出统计结果数最高的那个分类。
根据该分类ID,去动态获取分类模板信息。(必须要了解后台的数据表的关系)
同义词(根扩展词是一种玩法,需要一个单独的同义词页面)-- 待定
搜索页面需求分析
搜索条件有哪些字段信息?
针对规格参数筛选条件,使用动态域 dynamicField
搜索结果有哪些字段信息?
商品ID
商品名称
商品价格
商品图片地址
商品评论(不是直接和其他查询结果一起从es中动态查询的,可以理解这一部分需要单独搜索)
定义mapping
考虑哪些字段需要中文分词
2.搜索导入功能
考虑索引同步
考虑扩展词库和同义词的维护
实现全量导入(一次性将所有数据从数据库中导入到索引库)
实现增量导入(需要考虑索引同步问题)
3.搜索功能实现
组装搜索条件
聚合分析搜索结果中的分类,找出出现频率最高的分类。
第五讲:详情页实现和SSO实现
详情页展示方式
实现方式
动静结合方式
静态方式(使用freemarker生成):将不经常变的部分或者说不影响购买的部分信息,使用freemarker生成静态页。
制作模板(先有html页面)
使用专门的存储服务器来存储HTML页面。
动态方式(直接根据商品ID,去后台数据库或者缓存中,获取数据):将商品价格、商品配送地址是否有货等关键数据,要动态获取。
价格和库存可以放到redis缓存中。
要保证redis缓存和数据库之间的双写一致性(数据库写入数据的时候,一定也要保证缓存也写入数据)
注意事项:
浏览器对于HTML解析,可以理解为是逐行解析。
如果异步加载回来的数据是HTML片段,那么HTML片段不会再被浏览器继续解析,比如商品详情页中的[商品介绍]就是一大段HTML片段:
<font style="color:red" >商品属性信息</font>
SKU和SPU,SKU表示最小库存单位,表示可卖的真正商品。而SPU理解为是一种概念或者是对商品的一种抽象。
SSO登录
HTTP协议下的登录流程分析
互联网中的登录都是通过HTTP协议完成的。
HTTP协议是服务端和客户端交互时的一种通讯协议。主要作用是规范通讯格式。
HTTP协议:无状态的应用层协议。也就是说,无法让HTTP帮我们记录登录状态。
需要客户端和服务器端都提供一种技术来支持登录的实现。
客户端:
客户端要保存从服务器端返回的令牌。
保证每次请求服务端的时候,都会自动带上该令牌。
服务器端:
针对第一次请求,需要产生一个标识,或者叫令牌(token),或者叫票据。
该令牌在服务器端保存一份。
将令牌返回给客户端。
浏览器客户端和服务器交互流程分析
第一次客户端访问服务器端的时候,是没有令牌的。
服务器端会检测客户端是否带着令牌,如果没有,服务器端会针对该客户端产生一个令牌。
第二次同一个客户端访问服务器端的时候,是带着令牌的。
服务器端会检测客户端是否带着令牌,如果有,则取出该令牌,在服务器端的众多令牌中,进行匹配。如果匹配不上,重新生成一个令牌返回给客户端。
问题分析?
浏览器客户端是通过什么技术去存储令牌的?
Cookie技术(默认)
name为JSESSIONID
value为服务器端生成的jsessionid的唯一值。
JSP中的hidden标签
令牌是如何产生的?
UUID
服务器端是通过什么技术存储令牌的?setAttribute(key\value)
Session(默认)
String jsessionId(令牌)
Map<String,Object> attributes
很多对象都可以实现存储令牌的功能。
登录流程分析
第一次客户端带着【用户名和密码】访问服务器端的时候,是没有令牌的。
服务器端会检测客户端是否带着令牌,如果没有,服务器端会针对该客户端产生一个令牌。
服务器端进行用户认证成功之后,会将用户登录信息,存储在服务器端,具体是存储到该令牌对应的数据结构(Map结构)中。
第二次同一个客户端访问服务器端的时候,是带着令牌的。
服务器端会检测客户端是否带着令牌,如果有,则取出该令牌,在服务器端的众多令牌中,进行匹配。如果匹配不上,重新生成一个令牌返回给客户端。
从令牌对应的数据结构中,取出对应的登录信息,进行后续的操作处理。
互联网登录问题分析
互联网登录问题解决方案:
使用SSO系统解决登录问题
需要使用Redis统一存储session信息。
Redis(分布式环境下存储用户信息)如何替代session(单应用中存储用户信息)
Session的作用
生成令牌
存储令牌
存储登录信息
设置有效期
Redis模拟session
生成令牌(Java UUID的api生成,不是redis干的)
UUID.random()
存储令牌(将令牌作为redis的key)
token:uuid的值
jsessionid:uuid的值
tickets:uuid的值
存储登录信息(使用hash结构存储登录信息---本质上就是一种map结构)
field:对应的attribute中的key
value:对应的attribute中的value
设置有效期(redis使用expire命令对key设置有效期)
expire(key,3600)
第六讲:购物车和下单实现
购物车
数据如何存储?
都有哪些存储方案?
Cookie
Session
Redis
数据库
登录前:不要占用服务器资源
Cookie(如果禁用cookie,则不使用该浏览器)
浏览器对于Cookie有一些限制,比如说整个浏览器的Cookie不能超过40个;单个域名下,Cookie不能超过多少个?单个Cookie的value值不能大于几百K?
基于以上问题的思考,将购物车存储的Cookie中,一定要合理设计哪些数据存储到Cookie。
还有限制一下购物车的商品项(包含N件商品)数量。
登录后
Redis(内存大小问题)
Redis设置有效期(根据业务进行设置,一般都是大于一个月)
合并Cookie和Redis的购物车数据
登录后,需要取出当前用户的Redis中的购物车数据,再取出Cookie的购物车数据,进行合并
合并逻辑:Redis中没有的商品,再添加该商品,Redis中有该商品,则修改商品的数量。合并之后,清楚Cookie中的购物车数据。
购物车要按照店铺进行分店铺展示
购物车数据如果要计算促销哪种促销活动会显示?
购物车的信息要和数据库中的信息一致。
可以每次添加购物车的时候,去数据库中校验商品价格、有无库存
也可以不处理,等下单的时候,再去校验
下单
需要登录拦截
需要计算各种金额(订单金额、实付金额、运费、折扣、优惠、京豆)
页面
后台下单逻辑
提交订单(非秒杀、抢购模式下的订单提交)
请求响应速度要快(一些解耦操作等)
可以将同步处理的逻辑,使用MQ解耦。
校验(价格校验、库存校验等)
生成订单(会进行拆单)
B2B2C
按照店铺拆单(订单主表和子表)
订单配送地址表
扣减库存(扣减库存的时机,如何保证扣减的线程安全)
一般来说,扣减库存的时机有两个:下单扣减库存、支付扣减库存。
非秒杀、抢购场景下,扣减库存的时机,可以选择下单扣减也可以是支付扣减。
秒杀场景下,最好是下单就扣减库存。
如何保证扣减的线程安全,其实在非秒杀、抢购场景下,可以不解决,虽然可能会产生超卖现象。如果要解决,可以参考后面要降价的秒杀系统进行处理。
订单处理
正向订单状态(已下单待支付、已支付待发货、已发货待收货、确认收货\妥投、拒收、订单取消)
逆向订单
退货
退款(可能需要客服介入)
换货
订单号生成规则
年月日时分秒毫秒(17位) + 组合几位随机数(考虑并发数量,使用redis的incr去生成)
雪花算法
第七讲:支付和秒杀实现
支付
需要使用哪种支付方式,就需要对应的【支付接口文档】和【开发文档】,比如说我们要使用微信支付方式,那么我们可以去微信的官网,找到对应的【支付接口文档】和【开发文档】。
微信支付的开发文档地址:https://pay.weixin.qq.com/wiki/doc/api/index.html
微信二维码支付。
二维码如何生成
qrcode.js:专门用来生成二维码的。
二维码设置一个有效期。
二维码的内容:某个商品或者说某个订单对应的支付链接。
调用微信【支付API】去完成支付。
调用微信【查看支付状态API】去微信系统查看支付状态。
秒杀