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; } }