Subversion Repositories SmartDukaan

Rev

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

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