日期:2014-05-17  浏览次数:20458 次

input button 一个很严重的问题
我在一个退款页面里面,有个按钮<input name="btn_cancel" type="submit" value="Cancel Order">
按下这个按钮,会执行sql,就是把别人付过钱的总数退还到他们的网站账户里去。

问题就是,如果按一下这个cancel order是没问题的,浏览器需要1,2秒反应。但是连续按,发现退还的钱会叠加啊!

比如一个用户应该退10块钱,他点cancel order连续点了10下,那么他账户里就会多100块钱,应该不管他们点几下,退还的都是10块才对。

这应该怎么解决?

------解决方案--------------------
提交完,就黑了那个按钮。另外,使用session变量控制。提交的时候,对照一下,确定是否重复提交。
------解决方案--------------------
要是一般涉及到现金的支付页面的话,肯定是在表单里隐藏了一个订单ID,重复提交的问题是不会存在的,因为数据库做事务了。

这里如果你的应用是很普通的,就是为了防止重复留言,那么还是有点办法来实现的。因为PHP自身是做不了这个事务的,也就是检查ID是否被支付与之标记为支付这两个操作只有数据库可以保证事务原子性,另外一种办法就是memcache的原子加法属于一个巧妙手法。

这里id不借助session存储了,因为session_start之后session变量都是本地化的,php进程之间无法共享,所以只借助session_id把表单隐藏id存在memcache里。

刷新表单应该引发memcache里的id放在隐藏域里,提交表单应该引发memcache对该id原子加1,判断原子加的返回值是否为表单id+1,如果是就提交成功,否则提交失败。这是变相的借助memcache原子加法实现事务,因为原子加法避免了我们先取后加,而是原子的加1并返回结果,只要判断-1之后是否等于id即可,也是一门奇淫巧计了,这和幂等性什么的很类似,一些分布式无锁操作都是这么干的。
------解决方案--------------------
浏览器里面可以用disabled来禁用
建议服务端加个判断,不然别人模拟重复提交你就完了