Subversion Repositories SmartDukaan

Rev

Rev 2391 | Rev 4421 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2391 chandransh 1
package in.shop2020.payment.service.handler;
2
 
3
import in.shop2020.config.ConfigException;
3010 chandransh 4
import in.shop2020.payment.domain.Payment;
2391 chandransh 5
import in.shop2020.thrift.clients.config.ConfigClient;
6
 
7
import java.io.BufferedReader;
8
import java.io.DataOutputStream;
9
import java.io.IOException;
10
import java.io.InputStreamReader;
11
import java.io.StringReader;
12
import java.net.MalformedURLException;
13
import java.net.URL;
14
import java.net.URLConnection;
15
import java.net.URLEncoder;
16
import java.util.HashMap;
17
import java.util.Map;
18
import java.util.Map.Entry;
19
 
20
import javax.xml.xpath.XPath;
21
import javax.xml.xpath.XPathConstants;
22
import javax.xml.xpath.XPathExpressionException;
23
import javax.xml.xpath.XPathFactory;
24
 
25
import org.apache.log4j.Logger;
26
import org.w3c.dom.Element;
27
import org.w3c.dom.NodeList;
28
import org.xml.sax.InputSource;
29
 
3010 chandransh 30
public class EbsPaymentHandler implements IPaymentHandler {
2391 chandransh 31
 
32
	private static Logger log = Logger.getLogger(Class.class);
33
 
34
	public static final String TXN_ID = "transactionId";
35
	public static final String PAYMENT_ID = "paymentId";
36
	public static final String AMOUNT = "amount";
37
	public static final String DATE_TIME = "dateTime";
38
	public static final String MODE = "mode";
39
	public static final String REF_NO = "referenceNo";
40
	public static final String TXN_TYPE = "transactionType";
41
 
42
    private static String accountId;
43
    private static String secretKey;
44
 
45
	static{
46
		try {
47
			accountId = ConfigClient.getClient().get("ebs_account_id");
48
			secretKey = ConfigClient.getClient().get("ebs_secret_key");
49
		} catch (ConfigException e) {
50
			log.error("Unable to get EBS payment configuration.", e);
51
		}
52
	}
53
 
54
	/**
55
	 * Capture the amount which was authorized for this payment Id. Makes
56
	 * requests over the network and so internet connectivity is must for it to
57
	 * succeed.
58
	 * 
59
	 * @param amount
60
	 *            The amount to be captured. Must be the same value which was
61
	 *            authorized for this payment.
62
	 * @param paymentId
63
	 *            The payment ID generated by the gateway.
64
	 * @return A Map. The Map will definitely have status and will have error
65
	 *         information in case of error and txn information in case of
66
	 *         success. In case there is an error in processing, the returned
67
	 *         result map will be empty.
68
	 */
3010 chandransh 69
	public static Map<String, String> capturePayment(Payment payment){
70
	    double amount = payment.getAmount();
71
	    String paymentId = payment.getGatewayPaymentId();
2391 chandransh 72
		System.out.println("Capturing amount: Rs " + amount + " for payment Id: " + paymentId);
73
		URL url = null;
74
	    URLConnection urlConn = null;
75
	    DataOutputStream printout;
76
	    BufferedReader reader;
77
	    Map<String, String> resultMap = new HashMap<String, String>();
78
 
79
	    //Prepare resultMap to elicit failure behaviour in case anything goes wrong.
80
	    resultMap.put(STATUS, "");
81
 
82
		/*
83
		 * HDFC Insanity
84
		 * 
85
		 * If we don't set this property, all payments through HDFC will fail if
86
		 * the first payment is made through EBS.
87
		 * 
88
		 * The JAR file provided by HDFC requires that the instances of
89
		 * HttpsURLConnection returned by a call to URL.openConnection be an
90
		 * instance of com.sun.net.ssl.HttpsURLConnection. Java versions before
91
		 * 1.4 used to return an instance of this class which goes against the
92
		 * current policy of using instances of undocumented internal classes of
93
		 * JDK since they can change at any time. This behaviour was changed in
94
		 * JAVA 1.4 to return instances of javax.net.ssl.HttpsURLConnection.
95
		 * However, it appears, that to allow clients with JDK 1.4 and earlier,
96
		 * HDFC favours the use of the deprecated class.
97
		 */
98
	    System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
99
 
100
	    try {
101
		    // URL of CGI-Bin script.
102
			url = new URL("https://secure.ebs.in/api/1_0");
103
		    // URL connection channel.
104
		    urlConn = url.openConnection();
105
		    //urlConn.setRequestMethod("POST");
106
	    } catch (MalformedURLException e1) {
107
	    	log.error(Errors.CONN_FAILURE.message, e1);
108
			resultMap.put(ERR_CODE, Errors.CONN_FAILURE.code);
109
			resultMap.put(ERROR, Errors.CONN_FAILURE.message);
110
			return resultMap;
111
		} catch (IOException e) {
112
			log.error("Unable to initialize connection to EBS API server", e);
113
			resultMap.put(ERR_CODE, Errors.CONN_FAILURE.code);
114
			resultMap.put(ERROR, Errors.CONN_FAILURE.message);
115
			return resultMap;
116
		}
117
 
118
	    // Let the run-time system (RTS) know that we want input.
119
	    urlConn.setDoInput (true);
120
	    // Let the RTS know that we want to do output.
121
	    urlConn.setDoOutput (true);
122
	    // No caching, we want the real thing.
123
	    urlConn.setUseCaches (false);
124
	    // Specify the content type.
125
	    urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
126
	    // Send POST output.
127
	    try {
128
			printout = new DataOutputStream (urlConn.getOutputStream ());
129
		    String content =
130
			    "Action=" + URLEncoder.encode("capture", "UTF-8") +
131
			    "&AccountID=" + URLEncoder.encode(accountId, "UTF-8") +
132
			    "&SecretKey=" + URLEncoder.encode(secretKey, "UTF-8") +
133
			    "&Amount=" + URLEncoder.encode(""+amount, "UTF-8") +
134
			    "&PaymentID=" + URLEncoder.encode(paymentId, "UTF-8") +
135
			    "&submitted=Submit";
136
		    printout.writeBytes (content);
137
		    printout.flush ();
138
		    printout.close ();
139
 
140
		    // Get response data.
141
		    reader = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
142
		    resultMap = parseCaptureOutput(reader);
143
		    reader.close ();
144
	    } catch (IOException e) {
145
	    	log.error(Errors.CAPTURE_FAILURE.message, e);
146
			resultMap.clear();
147
			resultMap.put(STATUS, "");
148
			resultMap.put(ERR_CODE, Errors.CAPTURE_FAILURE.code);
149
			resultMap.put(ERROR, Errors.CAPTURE_FAILURE.message);
150
		}
151
	    return resultMap;
152
	}
153
 
154
	/**
155
	 * Parses the given input stream and returns a map containing the
156
	 * transaction details
157
	 * 
158
	 * @param reader The reader containing the response of the capture request.
159
	 * @return A Map. The Map will definitely have status and will have error
160
	 *         information in case of error and txn information in case of
161
	 *         success.
162
	 */
163
	private static Map<String, String> parseCaptureOutput(BufferedReader reader){
164
		Map<String, String> resultMap = new HashMap<String, String>();
165
		resultMap.put(STATUS, "");
166
 
167
		String str = null;
168
		try {
169
			str = reader.readLine();
170
			log.info("Capture response: " + str);
171
		} catch (IOException e) {
172
			log.error("Error reading the capture response:", e);
173
			return resultMap;
174
		}
175
 
176
		InputSource inputSource = new InputSource(new StringReader(str));
177
		XPath xpath = XPathFactory.newInstance().newXPath();
178
		String expression = "/output";
179
		NodeList nodes = null;
180
		try {
181
			nodes = (NodeList) xpath.evaluate(expression, inputSource,	XPathConstants.NODESET);
182
		} catch(XPathExpressionException xpee) {
183
			log.error("Input couldn't be parsed. See capture response for more info.");
184
			return resultMap;
185
		}
186
 
187
		Element elem = (Element) nodes.item(0);
188
		String status = elem.getAttribute(STATUS);
189
		resultMap.put(STATUS, status);
190
		if("".equals(status) || !"Processing".equals(status)){
191
			//We've received an error. Retrieve the error values
192
			resultMap.put(ERR_CODE, elem.getAttribute(ERR_CODE));
193
			resultMap.put(ERROR, elem.getAttribute(ERROR));
194
		}else{
3010 chandransh 195
			resultMap.put(CAPTURE_TXN_ID, elem.getAttribute(TXN_ID));
2391 chandransh 196
			resultMap.put(PAYMENT_ID, elem.getAttribute(PAYMENT_ID));
197
			resultMap.put(AMOUNT, elem.getAttribute(AMOUNT));
3010 chandransh 198
			resultMap.put(CAPTURE_TIME, elem.getAttribute(DATE_TIME));
2391 chandransh 199
			resultMap.put(MODE, elem.getAttribute(MODE));
200
			resultMap.put(REF_NO, elem.getAttribute(REF_NO));
201
			resultMap.put(TXN_TYPE, elem.getAttribute(TXN_TYPE));
202
		}
203
 
204
		log.info("Parsed capture response:");
205
		for(Entry<String, String> entry : resultMap.entrySet()){
206
			log.info("Key: " + entry.getKey() + ", Value: " + entry.getValue());
207
		}
208
 
209
		return resultMap;
210
	}
211
 
212
	public static void main(String[] args){
3010 chandransh 213
	    //TODO: The following call has been deprecated now. Need to create a payment object to make this call now.
214
//		capturePayment(30450.00, "2412653");
2391 chandransh 215
 
216
//		<output  transactionId="4793507"  paymentId="2411078"  amount="25005"  dateTime="2011-05-16 09:03:15"  mode="TEST"  referenceNo="4"  transactionType="Captured"  status="Processing"  />";
217
 
218
//		<output  errorCode="2"  error="Invalid Account ID/Secret Key"  />
219
//		<output  errorCode="12"  error="This payment is failed"  />
220
//		<output  errorCode="13"  error="This payment is captured already"  />		
221
	}
222
}