精华内容
下载资源
问答
  • 防止订单重复提交

    2019-09-29 22:41:37
    这时有一点需要我们考虑到:防止订单重复提交。 也就是说,我下单成功后,刷新页面,再次生成订单就会产生误会了。用户明明下了一次单,你却给人家发两次货,给人家收两次钱。 那么我们分析一下造成订单重复提交的...

    电商项目中,用户可能经常要下订单。这时有一点需要我们考虑到:防止订单重复提交。

    也就是说,我下单成功后,刷新页面,再次生成订单就会产生误会了。用户明明下了一次单,你却给人家发两次货,给人家收两次钱。


    那么我们分析一下造成订单重复提交的原因有哪些?

    一是转发引起的。

    我们知道页面跳转有两种方式:转发和重定向。所谓转发是在服务器端进行跳转,对用户时透明的,这时,浏览器中的地址是不会改变的。所以,如果此时刷新页面,会再次对服务器请求一次,造成多次下单;

    而重定向,是在客户端发生跳转,跳转时浏览器中的地址会发生改变。也就是说,我下单成功后,会马上重定向到一个新页面,浏览器地址栏改变,这是刷新,只会请求显示的地址,而不会请求上一次的地址。


    *注:重定向如果需要传递参数,可以采用下面方式

    ?
    1
    2
    3
         <result name= "success" type= "redirect" >/test/addSuccess.action?productId=${productId}</result>
    </action>



    二是服务器响应慢引起的。

    当用户点击下订单后,由于服务器反应时间过长没能及时看到响应信息,或者出于其它目的,多次点击“提 交”按钮,从而导致在服务器端接收到两条或多条相同的信息。如果信息需要存储到后台数据库中,如此以来就会产生数据库操作异常提示信息,以至于给用户带来 错误信息提示,从而给用户的使用带来不便。


    如何解决?

    以下思路,可以当个参考:

    1、下单成功后,重定向到其他页面

    这种方式,只能解决刷新时,生成订单的可能,但是不能防止多次点击的情况。

    2、利用struts2的token拦截器


    原理:

    Struts 2已经内置了能够防止用户重复提交同一个HTML表单的功能。它的工作原理:让服务器生成一个唯一标记,并在服务器和表单里各保存一份这个标记的副本。此 后,在用户提交表单的时候,表单里的标记将随着其他请求参数一起发送到服务器,服务器将对他收到的标记和它留存的标记进行比较。如果两者匹配,这次提交的 表单被认为是有效的,服务器将对之做出必要的处理并重新设置一个新标记。随后,提交相同的表单就会失败,因为服务器上的标记已经重置。

    Struts 2标签中的token标签,可以用来生成一个独一无二的标记。这个标记必须嵌套在form标签中使用,它会在表单里插入一个隐藏字段并把标记保存到 HttpSession对象里。toke标签必须与Token或Token Session拦截器配合使用,两个拦截器都能对token标签进行处理。Token拦截器遇到重复提交表单的情况,会返回一 个"invalid.token"结果并加上一个动作级别的错误。Token Session拦截器扩展了Token拦截器并提供了一种更复杂的服务,它采取的做法与Token拦截器不同,它只是阻断了后续的提交,这样用户不提交多 少次,就好像只是提交了一次。


    附Struts2的token拦截器demo一个:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <%@ page language= "java" contentType= "text/html; charset=UTF-8"
         pageEncoding= "UTF-8" %>
            <%
         String path = request.getContextPath();
         String basePath = request.getScheme()+ "://" +request.getServerName()+ ":" +request.getServerPort
     
    ()+path+ "/" ;
    %>
    <% @taglib uri= "/struts-tags" prefix= "s" %>
     
     
         
    <meta charset= "utf-8"
     
     
     
         <s:form id= "payFrm" action= "" >
             <s:hidden type= "hidden" name= "bankCardsId" id= "bankCardsId" value= "'0'/" >
             <s:hidden type= "hidden" name= "productId" value= "%{#request.productId}" >
             <s:token></s:token>
         </s:hidden></s:hidden></s:form>
         <span class = "sureBuy" >确认订单</span>
     
    <script type= "text/javascript" src= "<%=basePath %>weixin/js/fx.js" ></script>
      <script type= "text/javascript" src= "<%=basePath %>weixin/js/fx_methods.js" ></script>
    <script>
    $(function(){
    $( ".sureBuy" ).click(function(){
         var form = document.getElementById( "payFrm" );           
             form.action = "<%=path%>" +/test/sureOrder.action;
             form.method = "post" ;
             form.submit();
    });
         
    </script>


    struts2配置文件:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    < package name= "mallOrderAction" extends = "json-default" namespace= "/test" >
             
                 <interceptor-ref name= "defaultStack" >
                 <interceptor-ref name= "token" >
                 <result name= "invalid.token" type= "redirect" >/test/payRepeat.action</result>
                 <result name= "error" >/test/payError.jsp</result>
                 <result name= "success" type= "redirect" >/test/orderSuccess.action?productId=${productId}</result>
             </interceptor-ref></interceptor-ref></action>
             
                 <result name= "success" >/test/payRepeat.jsp</result>
             </action>
             
                 <result name= "success" >/test/orderSuccess.jsp</result>
             </action>
     
    </ package >


    action类文件:

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class orderAction extends ActionSupport{
         /**
          * @MethodName  : sureOrder
          * @Description : 添加订单
          * @return
          * @throws Exception
          */
         public String sureOrder() throws Exception{
             
             //………下单的各种步骤…………………
             return SUCCESS;
             
         }
         
         /**
          * @MethodName  : payRepeat
          * @Description : 重复提交
          * @return
          */
         public String payRepeat(){
             return SUCCESS;
         }
         
         /**
          * @MethodName  : addSuccess
          * @Description : 下单成功
          * @return
          */
         public String addSuccess(){
             HttpServletRequest request = ServletActionContext.getRequest();
             Product product = product.getproductId(productId);
             request.setAttribute( "product" , product);
             return SUCCESS;
         }
    }


    转载于:https://www.cnblogs.com/jpfss/p/8072484.html

    展开全文
  • 首先我们分析下原因:1、在网络延迟的情况下让用户有时间点击多次提交按钮导致表单重复提交。2、表单提交后用户点击浏览器的刷新导致表单重复提交3、用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行...

    首先我们分析下原因:

    1、在网络延迟的情况下让用户有时间点击多次提交按钮导致表单重复提交。

    2、表单提交后用户点击浏览器的刷新导致表单重复提交

    3、用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交

    1、用JavaScript的方式在客户端处理。

    a、设置一个标识,让他只能提交一次

    var isCommitted = false;//表单是否已经提交标识,默认为false

    function dosubmit(){

    if(isCommitted==false){

    isCommitted = true;//提交表单后,将表单是否已经提交标识设置为true

    return true;//返回true让表单正常提交

    }else{

    return false;//返回false那么表单将不提交

    }

    }

    b、表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮

    2、在jsp页面中的form表单中隐藏域来存储Token(令牌)

    3、或者在数据库设置一个字段,每次提交上去的时候去随机修改这个字段,每次在提交操作之前去比较这个值,如果相同就允许提交,不同就不允许提交。

    4、采用重定向

    5、使用ajax遮罩层,当点击一次提交后打开一个遮罩层,或者直接禁用你的按钮。当提交完成就取消遮罩层。

    展开全文
  • 来源:cnblogs.com/cjsblog/p/14516909.html概述为了防止掉单,这里可以这样处理:为了防止订单重复提交,可以这样处理:附上微信支付最佳实践:概述如图是一个简化...

    来源:cnblogs.com/cjsblog/p/14516909.html

    • 概述

    • 为了防止掉单,这里可以这样处理:

    • 为了防止订单重复提交,可以这样处理:

    • 附上微信支付最佳实践:


    概述

    如图是一个简化的下单流程,首先是提交订单,然后是支付。

    支付的话,一般是走支付网关(支付中心),然后支付中心与第三方支付渠道(微信、支付宝、银联)交互。

    支付成功以后,异步通知支付中心,支付中心更新自身支付订单状态,再通知业务应用,各业务再更新各自订单状态。

    这个过程中经常可能遇到的问题是掉单,无论是超时未收到回调通知也好,还是程序自身报错也好。

    总之由于各种各样的原因,没有如期收到通知并正确的处理后续逻辑等等,都会造成用户支付成功了,但是服务端这边订单状态没更新。

    这个时候有可能产生投诉,或者用户重复支付。

    由于③⑤造成的掉单称之为外部掉单,由④⑥造成的掉单我们称之为内部掉单

    为了防止掉单,这里可以这样处理:

    1、支付订单增加一个中间状态“支付中”,当同一个订单去支付的时候,先检查有没有状态为“支付中”的支付流水,当然支付(prepay)的时候要加个锁。支付完成以后更新支付流水状态的时候再讲其改成“支付成功”状态。

    2、支付中心这边要自己定义一个超时时间(比如:30秒),在此时间范围内如果没有收到支付成功回调,则应调用接口主动查询支付结果,比如10s、20s、30s查一次,如果在最大查询次数内没有查到结果,应做异常处理

    3、支付中心收到支付结果以后,将结果同步给业务系统,可以发MQ,也可以直接调用,直接调用的话要加重试(比如:SpringBoot Retry)

    4、无论是支付中心,还是业务应用,在接收支付结果通知时都要考虑接口幂等性,消息只处理一次,其余的忽略

    5、业务应用也应做超时主动查询支付结果

    对于上面说的超时主动查询可以在发起支付的时候将这些支付订单放到一张表中,用定时任务去扫

    为了防止订单重复提交,可以这样处理:

    1、创建订单的时候,用订单信息计算一个哈希值,判断redis中是否有key,有则不允许重复提交,没有则生成一个新key,放到redis中设置个过期时间,然后创建订单。

    其实就是在一段时间内不可重复相同的操作

    附上微信支付最佳实践:

    往期推荐

    应用卡死的bug竟然是因为Redis使用不当?

    SpringBoot+webSocket实现扫码登录功能

    7000+字,30+张图!Java线上故障排查思路全部总结在这里了

    TCP3次握手为啥挥手却要4次,这下解释明白了

    SpringCloud微服务的熔断机制和熔断的意义?

    java项目线上JVM调优实践,FullGC大大减少

    非常nice的分布式事务方案总结

    【干货】6500字全面字讲解 Redis 性能优化点!

    精髓!深入浅出剖析12个Zookeeper知识点

    Spring+SpringMVC+Mybatis分布式敏捷开发系统架构(附源码)

    Java大文件HTTP断点续传到服务器该怎么做?

    面试官:请你讲讲Thread.sleep(0) 的作用?

    展开全文
  • 如何防止订单重复提交

    千次阅读 热门讨论 2019-07-31 20:17:47
    在做电商系统中,如何防止用户在提交订单的时候,后端生成两笔订单呢?因为订单号是后端生成的,所以数据库的唯一索引还起不到作用。 方案 看了网上很多人说的,方案很多,下面来说说自己的想法。 1.用户每次进入...

    背景

    在做电商系统中,如何防止用户在提交订单的时候,后端生成两笔订单呢?因为订单号是后端生成的,所以数据库的唯一索引还起不到作用。

    方案

    看了网上很多人说的,方案很多,下面来说说自己的想法。

    1.用户每次进入提交订单页面的时候,调用发号器接口,在提交订单页面生成唯一的序号
    2.用户提交订单的时候,传递该序号,然后后端通过redis的原子方法++,做判断,如何大于2,则代表请求重复,对该请求不做处理即可。
    3.这样就可以防止用户重复提交订单。
    4.并且整个流程中,不是很影响性能。

    有其他好的方案,欢迎讨论

    展开全文
  • 电商中防止订单重复提交

    千次阅读 多人点赞 2019-01-08 19:01:59
    1、在网络延迟的情况下让用户有时间点击多次提交按钮导致表单重复提交。 2、表单提交后用户点击浏览器的刷新导致表单重复提交 3、用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交   1、...
  • 防止订单重复提交或者缓存数据时使用Redis的一些基本用法和配置 ​ redis作为一种非关系型数据库,它有很多用法,这次就简单说下spring boot集成redis时简单的配置并简单介绍防止订单重复提交的做法和缓存的用法. 首先...
  • 1、在第一次进入页面是生成令牌 createToken( "Paytoken" , 30 *60 ); 2、添加拦截器,在下一个Controller前添加 @Before ( SubmitValidator . class ) ..."请不要重复提交" ); } }
  • 防止订单重复提交的几种方法

    千次阅读 2018-10-31 18:07:52
    // 在提交函数外面定义个变量防止重复提交   //提交函数 function sublimit() {  if(flag){  return; // 如果存在就返回  }  flag = true;    $.post(url, {'data':id}, function(res){  ...
  • 出现这种问题的原因主要在于短时间内...解决这种问题的方法一般是从解决订单重复提交+防止高并发情况下账户余额为负数的情况解决方案。(类似于商品库存超卖的解决方案) 一般完整的订单支付流程是这样的 1.后端生成...
  • 在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就...
  • 防止表单重复提交订单

    千次阅读 2016-11-24 19:15:33
    在分布式项目维护中遇到了表单重复提交的问题 第一次出现这个bug时我用了最简单的方式,就是在前台js中控制提交按钮,防止重复点击如下这种方式,依然没有解决问题。 var btnFlag = true;  $("#createOrder").click...
  • 使用lua脚本防止1key多用 防止黑客并发订单攻击(主要原理:在验证交易码正确的同时,在缓存中删除交易码) 代码实现 public String checkTradeCode(String memberId, String tradeCode) { Jedis jedis = null; ...
  • 利用redis+token+拦截器+注解(只在需要防止重复的接口上添加该注解即可)实现防止重复订单.
  • 防止表单重复提交有很多种方法,其不外乎,客户端脚本防止刷新,服务端token验证等等,thinkphp内置了表单token验证,可以方便的防止表单重复提交
  • 点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐] 点击领取全栈资料:全栈资料 概述为了防止掉单,这里可以这样处理:为了防止订单重复提交,可以这样处理:附上微信支付最佳实践:概...
  • 通过自定义注解来标识哪些方法需要防止重复提交,比如下订单时保存订单数据只需要保存一次,但由于用户连续点击两次可能会造成多次保存,所以需要防止表单重复提交。 /** * 自定义注解防止表单重复提交 * */ @...
  • 在用户递交订单后,使用Redis的incr设置一个递增的KEY(KEY根据自己的需要设定但是要保证每一个人的唯一,个人感觉这里可以使用“cart_用户ID”,并设定其生存时间),来判断该KEY的数值,如果等于1说明这是第一次...
  • Java防止表单重复提交

    2014-06-30 12:05:14
    WAP商城订单重复提交解决方法,步骤: 1.

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,490
精华内容 5,396
关键字:

防止订单重复提交