Jimmychoo商城系统总结

一、需求

1.游戏模块

①在进入H5之前,首先有一个动态的探照灯的动效,然后由“淡出”效果到H5首页。

②在点击“开始游戏”之后会有一段动画演示游戏内容,然后滑动开启游戏,开始计时。

③成功找到目标短语之后,进入下一关。总共5关,难度递增。

④滑错之后,会提示滑错惩罚,第一次计时加2秒,后面每次递增1秒。

⑤有“提示”按钮,有两次提示的机会,点击确定使用后会将正确的短语亮起荧光,两次机会用完提示按钮消失。

⑥5关全部成功之后,显示游戏成绩以及击败对手的百分数。可以查看排行榜,会显示前10名+个人成绩。

2.商城模块

I、打开首页,会有一段文字描述商城以及销售条款。点击“即刻拥有”开始购物流程。

II、点击“即刻拥有”之后,跳转到商品列表页面,会显示商品的品名,类型,图片。商品列表是下滑类型的页面。

III、点击每个商品可以查看商品详情,可以左右滑动查看3个视角的产品图片。鞋类的商品有选择尺码和尺码参考这两个功能,包类的没有。点击查看产品详情可以查看商品介绍,可以加入购物袋。

IV、选择尺码的时候列出所有的尺码,并且当这个码数只有一双的时候提示,仅剩一双。

V、点击“加入购物袋”,如果商品售罄会跳转至售罄页面,如果没有跳转至购物袋。

VI、购物袋页面,以列表的形式把购物袋内容显示出来,并且可以删除。如果其中某款商品无货,则该商品的背景成为灰色。可以点击“结算”按钮,如果结算成功跳转至支付页面。

VII、结算的过程中要实时的计算商品的库存,如果库存不足则不能结算成功,有多人同时结算同款产品的压力。

VIII、支付页面  分为配送方式、发票信息、支付方式三部分,配送方式是必填,支付方式固定是微信支付,发票信息选填。点击“支付”按钮,调起微信支付,支付成功跳转至订单页面。

IX、支付失败  会检测支付订单是否超时,如果超时跳转至首页。

X、订单页面,按照每个订单的商品分开显示,未支付的订单会有“付款”、“取消”两个按钮,支付的订单会有“收货地址”、“查看物流”、“申请售后”三个按钮。

XI、“取消”或者订单超时订单都会显示交易关闭,“付款”会跳转至付款页面,“收货地址”会显示用户的收货地址,“查看物流”会显示用户订单的真实物流信息,“申请售后”会显示售后电话。

 二、设计

1.游戏模块

 动画、效果方面主要由前端来实现,这里不做解释。后端在游戏部分主要包括三个方面:

①玩家在通关游戏之后的分数记录

②排行榜的计算

③游戏通关之后的分享和分享页面的显示

2.商城模块

 商城模块除了一些页面的排版、显示需要前端来实现,其他的功能全部交由后端。主要功能包括:

①商品列表的显示,以及从个kol进来之后各产品和导航的隐藏与显示

②商品单品页商品的各项属性显示,如价格、图片、模特图、产品介绍等

③购物袋页面,要显示客户购买的东西 ,可以删除商品,添加商品,结算购物袋

④结算页面,要显示与修改客户的收货地址、发票信息、以及折扣信息(后来加的)、微信H5内公众号支付

⑤结算成功后,跳到成功页面;结算失败后,跳到订单页面。

⑥订单页面,显示客户的所有订单号、订单状态,以及订单内的各个单品信息、收货地址、物流信息等

三、实现以及问题

1.游戏模块

  游戏部分是一个类似图案滑动解锁的游戏,在你触摸那些单词划过“I want choo”这几个单词的时候,就会过关。连续闯过5关,游戏结束。每一关的难度会有提升,每关游戏的图案是随机生成的,其中用到的技术(我知道的,因为我不是前端,只负责后端以及交互的 部分)有下面这些:

①图案解锁

  图案解锁用的是一个patternlock.js的插件,在已有插件的情况要考虑的就是这个游戏难度的事情。一开始应客户要求,最少要有50个以上的图案供玩家玩,结果一开始客户代表还准备傻傻的去画50种图案放上去。后来考虑到这个图案可能真的会画死人,最后决定用随机生成一个图案里面所有需要的字母,然后用canvas画在页面上。最后用patternlock.js这个js触摸解锁这个答案。效果如下:

在触摸滑动这些单词错误的时候会有错误的音效提示,在点击“提示”后会在正确的“i want choo”上面呈现粉色。

 ②计时器

  问题:

  1.香港客户反应,计时器走的很慢,不是正常的一个秒数转换,而且越走越慢。

  2.会出现完了00:00.00的用户

  原因:

  计时器的话,一开始用的是setinterval,让他1000毫秒的时候,秒数位置上加1;60秒的时候分钟上面+1;听起来是不是很合理没有一点毛病,然后只要计算出开始时间和结束时间,获得他们的差值就是这个人游戏时间。其实这是错误的。

  1.setinterval和settimeout的机制是把你要执行的代码在你设定的那个时间点插入js引擎维护的一个代码队列中,但是插入队列代码并不意味着马上执行,因为js解释引擎是单线程运行的。他会等到前面的代码先执行完之后才会来执行这个队列中的代码,因为平时页面代码很少,js执行很快,所以平时我们感觉到定时器在你设置的那一刻他就开始运行了,运行的很平稳,这是一种错觉。在你设置定时器的时候获取开始时间只是代码设置的时间,并不是定时器任务开始的时间。并且setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在setInterval回调函数执行完毕之后才开始计时,所以如果setInterval内执行的计算过于耗时,或者有其他耗时任务在执行,setInterval的计时会越来越不准,延迟很厉害.

  2.获取时间这里也是有漏洞的,我们平时用的Date.now()获取到的是从1970年1月1日00:00:00 UTC开始经过的毫秒数,他会根据系统时间来检索当前的时间戳。非常不幸的是,这个函数会因为用户代理不同而不一样,精度非常不可靠,在同一时间不同地方获取到的时间戳是不同的。

  3.说起来第一次看到出现00:00.00秒的用户,我的第一反应是我提交游戏数据的接口被攻击了,别人肯定是利用了其他的非法手段给我提交数据,我一点都没怀疑前端。我检查了后端的代码,有微信授权不太可能在微信之外的浏览器打开,但是微信授权是可以使用模拟器模拟出来的,我当时想的是他肯定是用模拟器抓包,然后提交到了我的接口导致了00:00.00的记录。后来去查看了当时记录数据的方法,结果真的有一点漏洞,虽然我验证了cookie和提交方式post,但是还是有漏洞的,cookie可以伪造,post也可以模拟提交。我以为我发现了真正的原因,并向他们保证肯定不会有问题。结果第二天测试的人一玩,又出现了00:00.00,瞬间打脸。我有点不知所措,这个时候才开始认真思考真正的漏洞在哪里,是我一开始想的太多了。出现这种情况无非原因有两种:①我的接口记录这一块出了问题导致记录成了00:00.00②前端传过来的时间就是00:00.00接口我仔细检查了代码是没有问题的,那就只有一种可能前端传过来的值就有问题。后来经过努力好不容易搞到了那台出问题手机的型号,系统版本号和微信版本号,我们拿相同的版本号测试发现,计时器他居然不走,一直是00:00.00所以才导致了这种事情。后面会写为什么出现这种情况,下面是后端的记录代码(tp5)

  解决方案

  1.时间精度不准的情况下,采用了H5的新接口Performance接口。Performance接口提供当前时间在毫秒级的分辨率,使他不受系统时间的偏斜或者调整,在2012年10月23日成为了W3C的推荐。Performance.now()获取到的是当前时间的毫秒数,他精确到了千分之一毫秒。这个新接口拥有这诸多好处,但是新生事物有一个缺点就是兼容性,支持该API的浏览器很少,IE10,firefox15+以及谷歌浏览器,ios系统必须在9以上,安卓必须在4.0以上。就是因为低版本系统不支持的原因,所以会有部分手机根本就没获取到开始时间导致了00:00.00的发生。后来我们提出建议,做一个补偿机制,就是在客户手机不支持这个最新接口的情况下,才用new Date().getTime()来获取时间,然后在计算他们之间的时间差,最后统一返回一个计算好的时间差。但是当时项目已经上线,客户表示这个修改很大怕影响在线的效果,才用了另外一种办法。如果客户的手机不支持最新接口,那么提示他升级系统之后再来玩,下面是测试支持情况的代码。

如果这个接口不被支持,那么就会返回null。

  2.针对setinterval机制的问题,我们采用了requestAnimationFrame。requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。他不会去等待其他任务执行完才执行,有效的提高了计时的精度。

2.商城部分

  相信大部分人都做过商城,像商品列表,单品这种是肯定没有问题的,这里就不做介绍了,只介绍一些可能出问题的功能。

  1.购物袋功能

   问题

  在通过按钮加入购物袋这个操作,我们一般会用ajax提交到购物袋之后跳转到购物袋页面,但是对这个按钮的点击没有做限制,导致有时候客户感觉只点击了一次,但是却是加入了两件商品到购物车,客户体验很差。

  解决方案

  1.在提交到购物车页面这里,点击提交到购物车按钮才用同步提交到后台,等待后台返回的时候在进行下一步跳转到购物袋页面。2.就是用一个flag来控制提交,在提交的时候变成false,只有等待提交成功了变成true,才可以再次提交,但是这个只能在正常情况下使用。

  2.结算功能

  问题

  在购物袋页面,点击结算跳转到结算页面,然后在返回购物袋页面,这个时候购物袋页面应该是空的。这个操作在安卓上面是没有问题的,但是在iphone上面就有问题,在结算页面的时候,点击返回到上一页的时候,他读取了栈中的缓存,并没有重新加载那个页面。结果就成了点击返回,上一页被结算的那些商品还摆在那里,但是点击结算结算的数据也为空,点击删除的数据也是空的。

  解决方案

  这个问题就是在于iphone点击返回的时候,让他刷新返回的页面。在这里页面写js刷新是没用的,因为在点击返回的时候读取的是缓存,相当于在页面刚进来的刷新了,这个时候再返回它是不会刷新的。关键在于怎么捕捉iphone手机的返回事件。这里我采用的是H5的另外一个新接口history,在页面跳到下一个页面的时候在堆栈中replacestate替换掉这个页面,然后在用户点击返回的时候会触发popstate事件。这个时候因为在堆栈的history中页面已经被替换了,所以再返回的时候就会刷新这个页面。代码如下:

 

  3.支付页面

  问题

  在支付页面,用户填写了打折的手机号码的时候,会有一个优惠价给到客户,然后客户可以用优惠价来支付,但是支付的那些信息在页面加载的时候已经生成好了,里面包含了金额,如果有优惠价格的时候修改不了

  解决方案

  微信支付在生成prepay_id的时候,会涉及到商户订单号,价钱。这些东西在页面加载的时候已经生成并且显示到了页面上,如果这个人不是优惠客户,那么使用这个已经生成好的jsapi支付是可以的。如果这个人是优惠客户的时候,因为要修改价格,如果拿以前的订单号和价格去生成prepay_id,去调起微信的jsapi支付,就会报错商户订单号重复。这个时候我们可以重新生成一个订单号,然后用新的订单号和价格重新生成一个prepay_id来调起微信支付,代码如下

这里要注意的是返回的json信息要转换为json对象才可以成功的调起微信支付。

  4.支付回调

  问题

  在支付成功的时候,会触发微信的回调,这个时候才算真正的完成这个订单。但是有的时候回调成功,有些时候回调不成功,但是真实存在付款。

  解决方案

  微信支付回调的时候,回调的链接一定不能携带任何参数,不然就会导致回调失败。有时候回调成功,有时候回调不成功,可能的原因是你有构造函数或者其他验证的东西,微信在通过这些东西的时候被拦截了,并且跳到了其他的页面,我就是因为下面原因导致回调有时不成功:

  

  后来,我在另外一个单独的控制器中做了回调验证,这个问题就解决了。

  5.库存问题

  问题

  在商城中的很多商品是有库存的,他们不能超卖,因为没有那么多货品,要在售卖的时候保证出售的数量不能超过库存

  解决方案

  一般情况下是不会发生超卖这种事情的,因为在并发不是很高的情况下,mysql这类的关系型数据库也可以完全支撑。但是在高并发的情况下,数据库的读写速度太快的时候,会导致锁表。很多操作都在等待前面的执行完毕释放了之后才能执行,结果可能会导致数据库挂掉。这个时候就用到了我们的nosql。我在这里使用的是redis,他可以支撑10W的并发,足以应付很多场景。redis有两种办法可以控制库存,string和list,我推荐使用list。因为虽然redis的string也是原子性的操作,比如现在的库存是5,六个人同时买了之后,他肯定是-1,而不可能是其他数字。redis的string虽然可以当成数字来计算,可以使用incr和decr进行原子性的递增递减操作,但是它是可以见到负数的,你可以想象一下你的库存已经是负数了,它还在减是什么样的情况。这种情况很有可能发生。

  所以我用了list,在用户点击商品的时候,把该商品的对应信息加载到redis缓存list中。每次有人购买了商品,就用lpop弹出一个队列元素,如果队列的长度为0了,他就会返回false而不会继续减下去,很好的避免了在库存已经为0的情况下超卖出去。

  这里还有一个问题是如果购物车中的商品有很多种,每种商品的库存是不一样的,如果在结算的过程中,在没有结算完毕的情况下,某种商品没有库存了,这个结算不成功。这个时候需要告知客户那样商品没有了,并且分别返回他们各自的库存,因为有的结算了,有的没结算。这里大家可以使用事务来控制,逐条来结算购物车商品,如果有没有的商品就回滚,保证了数据库数据的完整性。但是redis这边没有这么完整的事务支持的,如果有某几件商品已经操作reidis减去库存了,这个时候怎么办呢?

  我在循环开始前,定义了一个数组$command。在循环操作redis的时候,每操作成功一条就把操作的这个key加入到$command这个数组中。一旦某件商品没有库存了,我就循环这个数组,把减去的库存全部加回来,比用数据库事务要方便点。

 

  

 

 

  小弟才疏学浅,文笔不精,哪里有写的不对的或者不好的地方,欢迎大家指正!

  

  

需求->设计->实现->测试->交付

posted on 2017-11-06 16:13  顶级手法  阅读(947)  评论(10编辑  收藏  举报