0

我在一个非常旧的 J2EE/struts 站点上工作,并且由于 PayPal 最近停止支持 SSL 3 协议,我正在尝试实现一个新的托管结帐流程,其中支付网关接受带有订单详细信息的 POST,处理信用卡验证,并通过另一个 POST 返回响应代码(和一百万个其他值)。

我正在尝试利用 struts 中的现有操作,但由于未呈现 struts-config.xml (/store/order/confirmation.do)中指定的路径而被挂断;相反,在处理来自远程服务器的 POST 请求并调用 ActionMapping.findForward() 之后,应用程序只会呈现来自远程服务器的 POST 中请求的相同路径(/store/checkout/submitOrder.do) .

如果我尝试将 redirect="true" 添加到 struts-config.xml 中的转发,我会被重定向到正确的路径,但是会出现一个我无法调试的 pagecontext 异常,因为它没有被记录。

过去的工作方式是 submitOrder 表单是空的——只是一个提交输入。然后,来自基于会话的购物车和相关的客户帐单的结帐细节将被移交给一个特殊的威瑞信库以生成响应。我现在想使用来自新提供商的 POST 表单,但我被这个重定向失败困住了。

struts-config.xml 中的行如下所示:

<action path="/store/checkout/submitOrder" type="com.company.action.CheckoutAction" parameter="submitOrder" scope="request">
  <set-property property="secure" value="true"/>
  <forward name="success" path="/store/order/confirmation.do"/>
</action>

动作是这样的:

public ActionForward submitOrder(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
  String method = request.getMethod();
  if (method != null && method.equals("POST")) {
    ShoppingCart sc = (ShoppingCart) request.getSession(false).getAttribute("shoppingCart");
    if (sc == null) { throw new SessionExpiredException("Submit Order - Shopping Cart is not in session"); }
    ResourceBundle appConfig = ResourceBundle.getBundle("resources.application");

    PFProClient client = new PFProClient();

    /* THIS saveOrder() METHOD WAS RE-WRITTEN TO TAKE the httpservletrequest (form POST) instead of an instance of VerisignResponse, defined in another library. */

    client.saveOrder(sc, request);
    User user = (User)request.getSession(false).getAttribute(Globals.USER);
    if (user != null) { UserModel.saveUser(user, sc.getCustomer(), sc.getOrder()); }
    //Remove items from session
    request.getSession().setAttribute("customerBillingForm", null);
    request.getSession().setAttribute("customerShippingForm", null);
    request.getSession().setAttribute("customerCreditForm", null);
    request.getSession().setAttribute("cartForm", null);
    request.getSession().setAttribute("shoppingCart", null);
    //remove the shopping cart from the cookie & DB
    ShoppingCartUtils.deleteSavedCartFromCookie(response, request);
    //remove the CHECKING_OUT flag
    request.getSession().setAttribute(Globals.CHECKING_OUT, null);
    //remove the PAYING_WITH_PAYPAL flag
    request.getSession().setAttribute(Globals.PAYING_WITH_PAYPAL, null);
    // Set cart in request for order confirmation page
    request.setAttribute("shoppingCart", sc);
    return mapping.findForward("success");
  } else {
    // HTTP method was not POST
  }
  return mapping.findForward("success");
}

编辑

我已验证 submitOrder 操作正在作为 POST 请求进行处理。我想知道,由于以前的 POST 只是一个空表单,额外的 POST 参数是否会弄脏某些东西并阻止正确的路由。

在tiles-defs.xml 中,confirmation.do 视图的资源是:

<definition name="confirm.order" path="/templates/layouts/order-confirmation.jsp">
  ...
  <put name="content" value="/store/checkout/confirmOrder.jsp"/>
</definition>

该应用程序正在为confirmOrder.jsp视图提供服务,但没有路由到 /store/order/confirmation.do,因此任何重新加载页面的尝试都会提示用户重新提交表单,这显然是不可取的。

我还从 struts-config.xml 中的 submitOrder 操作定义中删除了对 name="emptyForm" 的引用(因为来自远程服务器的表单 POST 没有 emptyForm name 属性),它定义为:

<form-bean name="emptyForm" type="org.apache.struts.action.DynaActionForm"/>

我也不确定这会产生什么影响。

4

1 回答 1

0

使用转发,客户端将始终认为它仍在查看请求的资源 ( submitOrder.do),因为它无法更好地了解(即对资源进行了单个请求并返回了响应)。响应内容应该来自前向资源 ( confirmation.do)。

如果响应内容不是来自confirmation.do,那么我们正在寻找一个不同的问题。在这种情况下,很可能 PayPal 回调使用的请求方法与 POST 不同,这将绕过大部分submitOrder()代码 ( // HTTP method was not POST)。而后面的 Struts Action confirmation.do,缺少必要的会话或请求属性,可能会显示 submitOrder 页面。

于 2014-12-10T20:03:11.807 回答