private String renderByTemplate(
      T_Transaction transaction, T_AppInfo appInfo, int userID, HttpServletRequest request)
      throws TemplateException {
    TemplateLoader templateLoader = TemplateResourceLoader.create("view/");
    Template template = templateLoader.getTemplate("m_layout");
    TemplateDataDictionary dic = TemplateDictionary.create();
    dic.setVariable("PAYTITLE", Configuration.SYSTEM_REQUESTFORM_TITLE);
    dic.setVariable("PAYURL", Configuration.SYSTEM_URL);
    dic.setVariable("STATIC_URL", Configuration.STATIC_URL);
    dic.setVariable("APPICON", appInfo.getIconPath());
    dic.setVariable("APPID", appInfo.getAppID());
    dic.setVariable("APPNAME", appInfo.getAppName());
    dic.setVariable("REFID", transaction.getRefID());
    dic.setVariable("USERID", userID + "");
    dic.setVariable("USERNAME", request.getAttribute("zme.viewerName").toString());
    dic.setVariable("DATA", request.getParameter("data"));
    dic.setVariable("PTOKEN", request.getAttribute("pToken").toString());

    String[] arrItemID = transaction.getItemIDs().split(ITEM_SEPARATE);
    String[] arrItemNames = transaction.getItemNames().split(ITEM_SEPARATE);
    String[] arrQty = transaction.getItemQuantities().split(ITEM_SEPARATE);
    String[] arrPrice = transaction.getItemPrices().split(ITEM_SEPARATE);
    String[] arrAmount = (transaction.getAmount() + "").split(ITEM_SEPARATE);
    double total = 0.0;
    for (int i = 0; i < arrItemID.length; i++) {
      double childamount = Double.parseDouble(arrAmount[i]);
      total += childamount;
      TemplateDataDictionary itemDic = dic.addSection("ITEM");
      itemDic.setVariable("ITEMNAME", arrItemNames[i]);
      itemDic.setVariable("QUANTITY", arrQty[i]);
      itemDic.setVariable("PRICE", arrPrice[i]);
      itemDic.setVariable("AMOUNT", Utils.removeDouble(childamount));
    }
    dic.setVariable("PAYTOTAL", Utils.removeDouble(total));
    dic.showSection("m_top");
    dic.showSection("m_header");
    dic.addSection("BILLING_REQUEST_FORM");
    dic.showSection("m_billing");

    TemplateDataDictionary footer = dic.addSection("m_footer");
    footer.setVariable("APPURL", Utils.removeHTTP(appInfo.appURL));
    return template.renderToString(dic);
  }
  protected void processRequest(HttpServletRequest request, HttpServletResponse response)
      throws TException, TemplateException {
    long startTime = System.nanoTime();
    String stats = request.getParameter(PARAM_STATS);
    if (stats != null && stats.equals(PARAM_STATS)) {
      this.echo(this.readStats.dumpHtmlStats(), response);
      return;
    }
    if (!this.validUser(request, response)) {
      return;
    }
    int userID = Integer.parseInt(request.getAttribute("zme.viewerId").toString());

    if (!this.validateParams(request)) {
      this.redirectMobileError(request, response);
      return;
    }

    ScriberPayment.sendLogStep1(
        userID,
        request.getParameter("appID"),
        getClientIP(request),
        Configuration.SYSTEM_URL,
        Config.getParam("system", "host"));
    T_AppInfo appInfo = getAppInfo(request.getParameter("appID"));
    if (appInfo == null) {
      this.redirectMobileError(request, response);
      return;
    }
    T_Transaction transaction = null;
    try {
      transaction = this.parseTransaction(appInfo, request, response);
    } catch (Exception e) {
      this.redirectMobileError(request, response);
      return;
    }
    if (transaction == null || transaction.getUserName() == null) {
      this.redirectMobileError(request, response);
      return;
    }
    if (!transaction.getUserName().equals(userID + "")) {
      request.setAttribute("code", -4);
      this.redirectMobileError(request, response);
      return;
    }
    ScriberPayment.sendLogStep2(
        userID,
        request.getParameter("appID"),
        transaction.getRefID(),
        getClientIP(request),
        Configuration.SYSTEM_URL,
        Config.getParam("system", "host"));

    boolean isUnFinish = this.generateToken(userID, transaction, request);
    if (!isUnFinish) {
      request.setAttribute("code", -5); // giao dich da duoc thuc hien roi
      this.redirectMobileError(request, response);
      return;
    }
    PaymentGatewayHandler.getMainInstance(
            Configuration.PAYMENT_GATEWAY_HOST, Configuration.PAYMENT_GATEWAY_PORT)
        .warmupCache(userID);
    Object userAppCache = this.getUserAppMemCache(userID, appInfo.getAppID());
    if (userAppCache != null && ((Integer) (userAppCache)).intValue() == 1) {
      request.setAttribute("refID", transaction.getRefID());
      _billController.processRequest(request, response);
    } else {
      echoAndStats(
          startTime, this.renderByTemplate(transaction, appInfo, userID, request), response);
    }
  }