package com.bao.lc.site.s3.commands;
import java.net.URI;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import com.bao.lc.bean.BasicIDValuePair;
import com.bao.lc.bean.IDValuePair;
import com.bao.lc.bean.ResultCode;
import com.bao.lc.client.RequestBuilder;
import com.bao.lc.client.impl.PostRedirectStrategy;
import com.bao.lc.client.utils.HttpClientUtils;
import com.bao.lc.common.URI2NameBuilder;
import com.bao.lc.httpcommand.BasicHttpCommand;
import com.bao.lc.httpcommand.params.HttpCommandPNames;
import com.bao.lc.httpcommand.params.HttpCommandParams;
import com.bao.lc.site.s3.TdUtils;
import com.bao.lc.site.s3.bean.TrainTicketInfo;
import com.bao.lc.site.s3.params.TdPNames;
import com.bao.lc.site.s3.params.TdParams;
import com.bao.lc.util.MapOperation;
import com.bao.lc.util.MapRelation;
import com.bao.lc.util.MapXorResult;
import com.bao.lc.util.MiscUtils;
public class SubmitOrder extends BasicHttpCommand
{
private static Log log = LogFactory.getLog(SubmitOrder.class);
public SubmitOrder()
{
super();
}
protected IDValuePair preExecute(Context context) throws Exception
{
// Remove the response if it exists
HttpCommandParams.purgeResponseParams(context);
// Request
IDValuePair rc = buildCurrRequest(context);
if(rc != ResultCode.RC_OK)
{
return rc;
}
// Referrer
String referer = MapUtils.getString(context, TdPNames.PARAM_SUBMIT_ORDER_REFERER);
context.put(HttpCommandPNames.TARGET_REFERER, referer);
return ResultCode.RC_OK;
}
protected IDValuePair postExecute(Context context) throws Exception
{
HttpResponse rsp = HttpCommandParams.getResponse(context);
String charset = HttpCommandParams.getCharset(rsp, context);
// Login page content
URI2NameBuilder ub = new URI2NameBuilder();
ub.uri(HttpCommandParams.getTargetRequestURI(context));
ub.addParamName("method").encoding(charset);
String submitOrderPage = HttpClientUtils.saveToString(rsp.getEntity(), charset, ub);
IDValuePair rc = checkRedirect(context, submitOrderPage, charset);
if(rc != ResultCode.RC_OK)
{
return rc;
}
// parse the content
context.put(TdPNames._CONFIRM_PASSENGER_CONTENT, submitOrderPage);
context.put(TdPNames._CONFIRM_PASSENGER_ENCODING, charset);
Command parseCommand = new ParseSubmitOrderPage();
parseCommand.execute(context);
rc = HttpCommandParams.getResultCode(context);
return rc;
}
private IDValuePair buildCurrRequest(Context context)
{
String url = MapUtils.getString(context, TdPNames.PARAM_SUBMIT_ORDER_URL);
Map<String, String> paramMap = new HashMap<String, String>();
IDValuePair rc = getCurrParamMap(context, paramMap);
if(rc != ResultCode.RC_OK)
{
return rc;
}
String encoding = HttpCommandParams.getDefaultResponseCharset(context);
RequestBuilder rb = new RequestBuilder();
rb.method(HttpPost.METHOD_NAME).uriStr(url);
rb.paramMap(paramMap).encoding(encoding);
context.put(HttpCommandPNames.TARGET_REQUEST, rb.create());
return ResultCode.RC_OK;
}
private IDValuePair getCurrParamMap(Context context, Map<String, String> paramMap)
{
// Refer from:
// submitRequest@https://dynamic.12306.cn/otsweb/js/order/query_single_bindevent.js?version=2.4
/**
* var selectStr_arr = selectStr.split("#"); var
* station_train_code=selectStr_arr[0]; var lishi=selectStr_arr[1]; var
* starttime=selectStr_arr[2]; var trainno=selectStr_arr[3]; var
* from_station_telecode=selectStr_arr[4]; var
* to_station_telecode=selectStr_arr[5]; var
* arrive_time=selectStr_arr[6]; var from_station_name=selectStr_arr[7];
* var to_station_name=selectStr_arr[8]; var
* ypInfoDetail=selectStr_arr[9];
*
* $('#station_train_code').val(station_train_code);
* $('#lishi').val(lishi); $('#train_start_time').val(starttime);
* $('#trainno').val(trainno);
* $('#from_station_telecode').val(from_station_telecode);
* $('#to_station_telecode').val(to_station_telecode);
* $('#arrive_time').val(arrive_time);
* $('#from_station_name').val(from_station_name);
* $('#to_station_name').val(to_station_name);
* $('#ypInfoDetail').val(ypInfoDetail); $('#orderForm').attr("action",
* ctx+"/order/querySingleAction.do?method=submutOrderRequest");
* $('#orderForm').submit();
*/
String[] trainParams = { "station_train_code", "lishi", "train_start_time", "trainno2",
"from_station_telecode", "to_station_telecode", "arrive_time", "from_station_name",
"to_station_name", "ypInfoDetail", "mmStr" };
TrainTicketInfo ticketInfo = TdParams.getOrderTicketInfo(context);
String bookButtonParamStr = ticketInfo.getBookButtonParameter();
String[] bookButtonParams = bookButtonParamStr.split("#");
if(bookButtonParams.length != trainParams.length)
{
log.error("Book Button Parameter length is unexpected. bookButtonParams.length="
+ bookButtonParams.length);
return ResultCode.RC_TD_SUBMIT_ORDER_BOOK_PARAMETER_UNEXPECTED;
}
for(int i = 0; i < trainParams.length; i++)
{
paramMap.put(trainParams[i], bookButtonParams[i]);
}
// Other parameters
/**
* from_station_telecode_name 上海 to_station_telecode_name 北京 train_date
* 2012-04-09 start_time_str 00:00--24:00
*
* round_start_time_str 00:00--24:00 round_train_date 2012-03-30 //Today
*
* single_round_type 1 train_class_arr QB#D#Z#T#K#QT# train_pass_type QB
*
* include_student 00 seattype_num
*/
String fromStation = MapUtils.getString(context, TdPNames.PARAM_FROM_STATION);
String toStation = MapUtils.getString(context, TdPNames.PARAM_TO_STATION);
String ticketDate = MapUtils.getString(context, TdPNames.PARAM_TICKET_DATE);
String ticketTimeRange = MapUtils.getString(context, TdPNames.PARAM_TICKET_TIME_RANGE);
paramMap.put("from_station_telecode_name", fromStation);
paramMap.put("to_station_telecode_name", toStation);
paramMap.put("train_date", ticketDate);
paramMap.put("start_time_str", ticketTimeRange);
paramMap.put("round_start_time_str", ticketTimeRange);
paramMap.put("round_train_date", MiscUtils.getDatePart(Calendar.getInstance()));
paramMap.put("single_round_type", "1");
paramMap.put("train_class_arr", "QB#D#Z#T#K#QT#");
paramMap.put("train_pass_type", "QB");
paramMap.put("include_student", "00");
paramMap.put("seattype_num", "");
// Try to do a check
Map<String, String> submitFormParamMap = TdParams.getOrderFormParamMap(context);
MapOperation<String, String> mapOper = new MapOperation<String, String>(paramMap,
submitFormParamMap);
MapXorResult<String, String> xorResult = mapOper.xor(MapOperation.XOR_KEY_ONLY);
if(xorResult.getRelation() != MapRelation.EQUALS)
{
log.warn("SubmitOrder parameter is unexpected: " + xorResult.toString());
}
return ResultCode.RC_OK;
}
private IDValuePair checkRedirect(Context context, String submitOrderPage, String charset)
{
// error url: http://www.12306.cn/mormhweb/logFiles/error.html
PostRedirectStrategy redirectStrategy = HttpCommandParams.getRedirectStrategy(context);
HttpUriRequest finalReq = redirectStrategy.getFinalRequest();
if(finalReq == null || finalReq.getURI() == null)
{
log.error("Can't find redirect req or uri when submit order.");
IDValuePair rc = null;
String jsErrorMsg = TdUtils.getJsErrorMsg(submitOrderPage, charset);
if(jsErrorMsg != null)
{
TdParams.getUI(context).error(jsErrorMsg);
rc = new BasicIDValuePair(ResultCode.RC_CANT_FIND_REDIRECTS, jsErrorMsg);
}
else
{
rc = new BasicIDValuePair(ResultCode.RC_CANT_FIND_REDIRECTS, "submit order");
}
return rc;
}
URI redirectURI = finalReq.getURI();
String expectedURI = MapUtils.getString(context, TdPNames.PARAM_CONFIRM_PASSENGER_INIT_URL);
if(!StringUtils.equals(expectedURI, redirectURI.toString()))
{
String info = String.format("SubmitOrder error: Exptected redirect URI=%s, actual=%s",
expectedURI, redirectURI.toString());
log.error(info);
return new BasicIDValuePair(ResultCode.RC_UNEXPECTED_REDIRECTS, info);
}
return ResultCode.RC_OK;
}
}