Rev 2334 | Rev 2899 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
package in.shop2020.serving.services;import in.shop2020.config.ConfigException;import in.shop2020.payments.Attribute;import in.shop2020.payments.Payment;import in.shop2020.payments.PaymentStatus;import in.shop2020.payments.PaymentService.Client;import in.shop2020.serving.services.IPaymentService.Errors;import in.shop2020.thrift.clients.PaymentServiceClient;import in.shop2020.thrift.clients.config.ConfigClient;import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.StringReader;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.net.URLEncoder;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Map.Entry;import javax.xml.xpath.XPath;import javax.xml.xpath.XPathConstants;import javax.xml.xpath.XPathExpressionException;import javax.xml.xpath.XPathFactory;import org.apache.log4j.Logger;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import org.xml.sax.InputSource;public class EbsPaymentService implements IPaymentService{private static Logger log = Logger.getLogger(Class.class);public static final String TXN_ID = "transactionId";public static final String PAYMENT_ID = "paymentId";public static final String AMOUNT = "amount";public static final String DATE_TIME = "dateTime";public static final String MODE = "mode";public static final String REF_NO = "referenceNo";public static final String TXN_TYPE = "transactionType";private static String accountId;private static String secretKey;static{try {accountId = ConfigClient.getClient().get("ebs_account_id");secretKey = ConfigClient.getClient().get("ebs_secret_key");} catch (ConfigException e) {log.error("Unable to get EBS payment configuration.");}}private static int gatewayId=2;private long paymentId;@Overridepublic long createPayment(long currentCartId, long userId, long txnId, String paymentOption){log.info("Creating payment for the txn#: " + txnId + " for the user: " + userId + " for processing through EBS");CommonPaymentService cps = new CommonPaymentService();if(!cps.createPayment(currentCartId, userId, txnId, gatewayId)){log.error("Error while creating the basic payment");return PAYMENT_NOT_CREATED;}paymentId = cps.getPaymentId();if(paymentOption != null){List<Attribute> attributes = new ArrayList<Attribute>();attributes.add(new Attribute(IPaymentService.PAYMENT_METHOD, paymentOption));try {PaymentServiceClient paymentServiceClient = new PaymentServiceClient();paymentServiceClient.getClient().updatePaymentDetails(paymentId, null, null, null, null, null, null, null, null, PaymentStatus.INIT, null, attributes);} catch (Exception e) {log.error("Error while saving payment option attribute", e);// TODO: We've already created the payment. We could allow the// payment to go through. The customer will be a little// annoyed to have to select from a host of options again but// will be better than completely disallowing him.return PAYMENT_NOT_CREATED;}}return paymentId;}/*** Capture the amount which was authorized for this payment Id. Makes* requests over the network and so internet connectivity is must for it to* succeed.** @param amount* The amount to be captured. Must be the same value which was* authorized for this payment.* @param gatewayPaymentId* The payment ID generated by the gateway.* @return A Map. The Map will definitely have status and will have error* information in case of error and txn information in case of* success. In case there is an error in processing, the returned* result map will be empty.*/public static Map<String, String> capturePayment(Payment payment, String gatewayPaymentId){String amount = "" + payment.getAmount();log.info("Capturing amount: Rs " + amount + " for payment Id: " + gatewayPaymentId);Map<String, String> resultMap = new HashMap<String, String>();//Prepare resultMap to elicit failure behaviour in case anything goes wrong.resultMap.put(STATUS, "");try {PaymentServiceClient paymentServiceClient = new PaymentServiceClient();Client paymentClient = paymentServiceClient.getClient();resultMap = paymentClient.captureEbsPayment(payment.getPaymentId());} catch (Exception e) {log.error("Unable to capture payment", e);resultMap.put(ERR_CODE, Errors.CONN_FAILURE.code);resultMap.put(ERROR, "Unable to capture transaction.");}return resultMap;// /*// * HDFC Insanity// *// * If we don't set this property, all payments through HDFC will fail if// * the first payment is made through EBS.// *// * The JAR file provided by HDFC requires that the instances of// * HttpsURLConnection returned by a call to URL.openConnection be an// * instance of com.sun.net.ssl.HttpsURLConnection. Java versions before// * 1.4 used to return an instance of this class which goes against the// * current policy of using instances of undocumented internal classes of// * JDK since they can change at any time. This behaviour was changed in// * JAVA 1.4 to return instances of javax.net.ssl.HttpsURLConnection.// * However, it appears, that to allow clients with JDK 1.4 and earlier,// * HDFC favours the use of the deprecated class.// */// System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");//// try {// // URL of CGI-Bin script.// url = new URL("https://secure.ebs.in/api/1_0");// // URL connection channel.// urlConn = url.openConnection();// //urlConn.setRequestMethod("POST");// } catch (MalformedURLException e1) {// log.error(Errors.CONN_FAILURE.message, e1);// resultMap.put(ERR_CODE, Errors.CONN_FAILURE.code);// resultMap.put(ERROR, Errors.CONN_FAILURE.message);// return resultMap;// } catch (IOException e) {// log.error("Unable to initialize connection to EBS API server", e);// resultMap.put(ERR_CODE, Errors.CONN_FAILURE.code);// resultMap.put(ERROR, Errors.CONN_FAILURE.message);// return resultMap;// }//// // Let the run-time system (RTS) know that we want input.// urlConn.setDoInput (true);// // Let the RTS know that we want to do output.// urlConn.setDoOutput (true);// // No caching, we want the real thing.// urlConn.setUseCaches (false);// // Specify the content type.// urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");// // Send POST output.// try {// printout = new DataOutputStream (urlConn.getOutputStream ());// String content =// "Action=" + URLEncoder.encode("capture", "UTF-8") +// "&AccountID=" + URLEncoder.encode(accountId, "UTF-8") +// "&SecretKey=" + URLEncoder.encode(secretKey, "UTF-8") +// "&Amount=" + URLEncoder.encode(""+amount, "UTF-8") +// "&PaymentID=" + URLEncoder.encode(paymentId, "UTF-8") +// "&submitted=Submit";// printout.writeBytes (content);// printout.flush ();// printout.close ();//// // Get response data.// reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));// resultMap = parseCaptureOutput(reader);// reader.close ();// } catch (IOException e) {// log.error(Errors.CAPTURE_FAILURE.message, e);// resultMap.clear();// resultMap.put(STATUS, "");// resultMap.put(ERR_CODE, Errors.CAPTURE_FAILURE.code);// resultMap.put(ERROR, Errors.CAPTURE_FAILURE.message);// }// return resultMap;}/*** Parses the given input stream and returns a map containing the* transaction details** @param reader The reader containing the response of the capture request.* @return A Map. The Map will definitely have status and will have error* information in case of error and txn information in case of* success.*/private static Map<String, String> parseCaptureOutput(BufferedReader reader){Map<String, String> resultMap = new HashMap<String, String>();resultMap.put(STATUS, "");String str = null;try {str = reader.readLine();log.info("Capture response: " + str);} catch (IOException e) {log.error("Error reading the capture response:", e);return resultMap;}InputSource inputSource = new InputSource(new StringReader(str));XPath xpath = XPathFactory.newInstance().newXPath();String expression = "/output";NodeList nodes = null;try {nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);} catch(XPathExpressionException xpee) {log.error("Input couldn't be parsed. See capture response for more info.");return resultMap;}Element elem = (Element) nodes.item(0);String status = elem.getAttribute(STATUS);resultMap.put(STATUS, status);if("".equals(status) || !"Processing".equals(status)){//We've received an error. Retrieve the error valuesresultMap.put(ERR_CODE, elem.getAttribute(ERR_CODE));resultMap.put(ERROR, elem.getAttribute(ERROR));}else{resultMap.put(CAPTURE_TXN_ID, elem.getAttribute(TXN_ID));resultMap.put(PAYMENT_ID, elem.getAttribute(PAYMENT_ID));resultMap.put(AMOUNT, elem.getAttribute(AMOUNT));resultMap.put(CAPTURE_TIME, elem.getAttribute(DATE_TIME));resultMap.put(MODE, elem.getAttribute(MODE));resultMap.put(REF_NO, elem.getAttribute(REF_NO));resultMap.put(TXN_TYPE, elem.getAttribute(TXN_TYPE));}log.info("Parsed capture response:");for(Entry<String, String> entry : resultMap.entrySet()){log.info("Key: " + entry.getKey() + ", Value: " + entry.getValue());}return resultMap;}public static void main(String[] args){//capturePayment(30450.00, "2412653");// <output transactionId="4793507" paymentId="2411078" amount="25005" dateTime="2011-05-16 09:03:15" mode="TEST" referenceNo="4" transactionType="Captured" status="Processing" />";// <output errorCode="2" error="Invalid Account ID/Secret Key" />// <output errorCode="12" error="This payment is failed" />// <output errorCode="13" error="This payment is captured already" />}}