Skip to content

Commit 0304d40

Browse files
authored
Merge pull request #93 from CyberSource/future
PR from future to master
2 parents 3ed9f56 + 8f8d0a9 commit 0304d40

File tree

15 files changed

+439
-40
lines changed

15 files changed

+439
-40
lines changed

.travis.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
language: java
2+
"dist": "precise"
23
jdk:
4+
- oraclejdk8
35
- oraclejdk7
46
- openjdk7
5-
- openjdk6
7+
- openjdk6

README.md

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ You do not need to download and build the source to use the SDK but if you want
6666
- Number of retry parameter should be set between 1 to 5. Any other value will throw an Error Message.
6767
- Refer to the [Retry Pattern](README.md#retry-pattern) section below.
6868
- Please refer to the accompanying documentation for the other optional properties that you may wish to specify.
69-
69+
- Set customHttpClassEnabled to true to make use of Custom Http Library.
70+
- Enter the custom class name in customHttpClass field. Provide the full package name along with the class name.
71+
example customHttpClass= <packagename.customHttpClass>
72+
- The custom HTTP Class must have a three argument constructor which accepts MerchantConfig, DocumentBuilder and LoggerWrapper as argument. Then it should call the constructor of the parent class.
7073
- Build this project using Maven.
7174
- `mvn clean` - Cleans the Project
7275
- `mvn install` - Builds the project and creates a jar file of client SDK. Includes running all unit tests and integration tests
@@ -93,6 +96,7 @@ Unix or Linux: runSample.sh <service_name>
9396
- If you make any changes to the `RunSample.java` sample, you must rebuild the sample before using it. Use the `compileSample` batch file or shell script provided in the sample directory.
9497

9598
### Using samples and maven tool
99+
96100
- Clone/Download the code from GitHub.
97101
- Choosing which sample to test:
98102
- If you want to test Name-Value Pair, `cd` to the `cybersource-sdk-java-master/samples/nvp` directory.
@@ -106,17 +110,17 @@ Unix or Linux: runSample.sh <service_name>
106110
## JKS creation
107111

108112
- To convert the p12 file to JKS follow the steps mentioned below.
109-
- These commands will take out all the certs from the p12 file. 
110-
```
111-
openssl pkcs12 -in <Merchant_ID>.p12 -nocerts -out <Merchant_ID>.key
112-
openssl pkcs12 -in <Merchant_ID>.p12 -clcerts -nokeys -out <Merchant_ID>.crt
113-
openssl pkcs12 -in <Merchant_ID>.p12 -cacerts -nokeys -out CyberSourceCertAuth.crt
114-
openssl pkcs12 -in <Merchant_ID>.p12 -cacerts -nokeys -out CyberSource_SJC_US.crt
115-
```
116-
- Create a new p12. Here `Identity.p12` is the new p12 file
113+
- These commands will take out all the certs from the p12 file.
114+
1. `openssl pkcs12 -in <Merchant_ID>.p12 -nocerts -out <Merchant_ID>.key`
115+
2. `openssl pkcs12 -in <Merchant_ID>.p12 -clcerts -nokeys -out <Merchant_ID>.crt`
116+
3. `openssl pkcs12 -in <Merchant_ID>.p12 -cacerts -nokeys -out CyberSourceCertAuth.crt`
117+
4. `openssl pkcs12 -in <Merchant_ID>.p12 -cacerts -nokeys -out CyberSource_SJC_US.crt`
118+
119+
- Create a new p12. Here Identity.p12 is the new p12 file
117120
```
118121
openssl pkcs12 -export -certfile CyberSourceCertAuth.crt -in <Merchant_ID>.crt -inkey <Merchant_ID>.key -out identity.p12 -name "<Merchant_ID>"
119122
```
123+
120124
- Create JKS from p12 using keytool
121125
```
122126
keytool -importkeystore -destkeystore <Your_keystore_name> -deststorepass <your_password> -srckeystore identity.p12 -srcstoretype PKCS12 -srcstorepass <Merchant_ID>
@@ -127,11 +131,11 @@ keytool -importcert -trustcacerts -file CyberSource_SJC_US.crt -alias CyberSourc
127131
```
128132
- List the entries of your keystore
129133
```
130-
keytool -list -v -keystore <Your_keystore_name>
134+
keytool -list -v -keystore <Your_keystore_name>`
131135
```
132136
- It should have two entries.
133137
- The first entry should contain a chain of two certificates - `CyberSourceCertAuth` and <Merchant_ID> with alias name <Merchant_ID>
134-
- Second entry should be for `CyberSource_SJC_US` certificate with alias name as `CyberSource_SJC_US`
138+
- Second entry should be for `CyberSource_SJC_US` certificate with alias name as CyberSource_SJC_US
135139

136140
## Message Level Encryption
137141
CyberSource supports Message Level Encryption (MLE) for Simple Order API. Message level encryption conforms to the SOAP Security 1.0 specification published by the OASIS standards group.
@@ -151,7 +155,7 @@ CyberSource supports Message Level Encryption (MLE) for Simple Order API. Messag
151155
## Retry Pattern
152156

153157
Retry Pattern allows to retry sending a failed request and it will only work with `useHttpClient=true`. `allowRetry` flag enables the retry mechanism.
154-
- Set the value of `allowRetry` parameter to "TRUE/FALSE". Then the system will retry the failed request as many times as configured by the merchant in the config parameter 'numberOfRetries'.
158+
- Set the value of `allowRetry` parameter to "TRUE/FALSE". Then the system will retry the failed request as many times as configured by the merchant in the config parameter 'numberOfRetries'.
155159
- numberOfRetries parameter value should be set between 0 to 5. By default the value for numberOfRetries will be 5. User can set a delay in between the retry attempts.
156160
- Config parameter for this property is 'retryInterval' in `cybs.property` file. The default value for 'retryInterval' parameter is 5 which means a delay of 5 seconds.
157161

@@ -175,7 +179,49 @@ Retry Pattern allows to retry sending a failed request and it will only work wit
175179
9. org.mockito:mockito-all:1.10.19
176180
Mock objects library for java
177181

182+
## Changes
183+
184+
Version Cybersource-sdk-java 6.2.5 (OCT,2017)
185+
_______________________________
186+
1) Merchant cert to be read from JAVA key store. Flag is added to enable reading cert from Java keystore.
187+
2) Added Custom HttpClient feature. Merchants can use there own http client instead of defaults which comes with SDK.
188+
3) Http Client connection reuse issue.
189+
4) Changed clientLibrary version to 6.2.5; in 6.2.4 release it was missed. So, in 6.2.4 release, clientLibrary version was pointing to 6.2.3.
190+
_______________________________
191+
Version Cybersource-sdk-java 6.2.4 (Dec 15, 2016)
192+
_______________________________
193+
1) RetryPattern config for http client.
194+
2) Code review comments.
195+
3) Added timers to log the method execution time.
196+
4) Sample added to support other services.
197+
_______________________________
198+
Version Cybersource-sdk-java 6.2.3 (Oct 17, 2016)
199+
_______________________________
200+
1) Fixed performance issue; in case of multiple merchantIDs, p12 was getting loaded for every request.
201+
2) p12 will be loaded once per merchantId.
202+
_______________________________
203+
Version Cybersource-sdk-java 6.2.2 (Sep 15, 2016)
204+
_______________________________
205+
1)Upgraded 3rd party dependencies jars including wss4j.
206+
_______________________________
207+
Version Cybersource-sdk-java 6.2.1 (Aug 4, 2016)
208+
_______________________________
209+
1) AkamaiSureroute config parameter introduced
210+
2) i18n fix for NVP sample.
211+
3) In `Sample/cybs.properties` file, `targetAPIVersion` changed to latest 1.129.
212+
_______________________________
213+
Version Cybersource-sdk-java 6.2.0 (Jul 28, 2016)
214+
_______________________________
215+
1) MLE[Message Level Encryption] is enabled.
216+
2) published zip file with samples and packaged compiled cybersoruce-sdk-java jar file.
217+
3) `Bouncycastle` jar issue; changed scope from provided to default"scope"
218+
_______________________________
219+
Version Cybersource-sdk-java 6.1.0 (Feb 24,2016)
220+
_______________________________
221+
1) SHA256 changes which are required to signed the request with SHA256.
222+
178223
## Documentation
179224
- For more information about CyberSource services, see <http://www.cybersource.com/developers/documentation>.
180225
- For all other support needs, see <http://www.cybersource.com/support>.
181226

227+

java/src/main/java/com/cybersource/ws/client/Client.java

100644100755
Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.io.FileInputStream;
3535
import java.io.IOException;
3636
import java.io.StringReader;
37+
import java.lang.reflect.InvocationTargetException;
3738
import java.security.KeyStore;
3839
import java.security.cert.PKIXParameters;
3940
import java.security.cert.TrustAnchor;
@@ -90,14 +91,16 @@ public static Map runTransaction(Map<String,String> request, Properties props)
9091
* @throws FaultException if a fault occurs.
9192
* @throws ClientException if any other exception occurs.
9293
*/
93-
public static Map runTransaction(
94+
@SuppressWarnings("unchecked")
95+
public static Map runTransaction(
9496
Map<String, String> request, Properties props,
9597
Logger _logger, boolean prepare, boolean logTranStart)
9698
throws FaultException, ClientException {
9799
MerchantConfig mc;
98100
LoggerWrapper logger = null;
99101
Connection con = null;
100102

103+
101104
try {
102105
setVersionInformation(request);
103106

@@ -122,8 +125,39 @@ public static Map runTransaction(
122125
// FileWriter writer = new FileWriter(new File("signedDoc.xml"));
123126
// writer.write(XMLUtils.PrettyDocumentToString(signedDoc));
124127
// writer.close();
125-
126-
con = Connection.getInstance(mc, builder, logger);
128+
if(mc.isCustomHttpClassEnabled()){
129+
Class<Connection> customConnectionClass;
130+
try {
131+
customConnectionClass = (Class<Connection>) Class.forName(mc.getcustomHttpClass());
132+
Class[] constructor_Args = new Class[] {com.cybersource.ws.client.MerchantConfig.class, javax.xml.parsers.DocumentBuilder.class, com.cybersource.ws.client.LoggerWrapper.class};
133+
con=customConnectionClass.getDeclaredConstructor(constructor_Args).newInstance(mc, builder, logger);
134+
135+
} catch (InstantiationException e) {
136+
logger.log(Logger.LT_INFO, "Failed to Instantiate the class "+e);
137+
throw new ClientException(e, false, null);
138+
} catch (IllegalAccessException e) {
139+
logger.log(Logger.LT_INFO, "Could not Access the method invoked "+e);
140+
throw new ClientException(e, false, null);
141+
} catch (ClassNotFoundException e) {
142+
logger.log(Logger.LT_INFO, "Could not load the custom HTTP class ");
143+
throw new ClientException(e, false, null);
144+
} catch (IllegalArgumentException e) {
145+
logger.log(Logger.LT_INFO, "Method invoked with Illegal Argument list "+e);
146+
throw new ClientException(e, false, null);
147+
} catch (SecurityException e) {
148+
logger.log(Logger.LT_INFO, "Security Exception "+e);
149+
throw new ClientException(e, false, null);
150+
} catch (InvocationTargetException e) {
151+
logger.log(Logger.LT_INFO, "Exception occured while calling the method "+e);
152+
throw new ClientException(e, false, null);
153+
} catch (NoSuchMethodException e) {
154+
logger.log(Logger.LT_INFO, "Method not found ");
155+
throw new ClientException(e, false, null);
156+
}
157+
}
158+
else{
159+
con = Connection.getInstance(mc, builder, logger);
160+
}
127161
Document wrappedReply = con.post(signedDoc);
128162
Map<String, String> replyMap = soapUnwrap(wrappedReply, mc, logger);
129163
logger.log(Logger.LT_INFO, "Client, End of runTransaction Call ",false);

java/src/main/java/com/cybersource/ws/client/Connection.java

100644100755
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,15 @@ abstract class Connection {
4747
final MerchantConfig mc;
4848
private final DocumentBuilder builder;
4949
final LoggerWrapper logger;
50-
51-
Connection(MerchantConfig mc, DocumentBuilder builder,
50+
51+
/**
52+
* It initializes three arguments MerchantConfig, DocumentBuilder and Logger
53+
* Any class extending this class must implement three argument constructor
54+
* @param mc
55+
* @param builder
56+
* @param logger
57+
*/
58+
protected Connection(MerchantConfig mc, DocumentBuilder builder,
5259
LoggerWrapper logger) {
5360
this.mc = mc;
5461
this.builder = builder;

java/src/main/java/com/cybersource/ws/client/HttpClientConnection.java

100644100755
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,13 @@ void postDocument(Document request)
6060
throws IOException, TransformerConfigurationException,
6161
TransformerException, MalformedURLException,
6262
ProtocolException {
63-
HttpClient httpClient = new HttpClient();
63+
64+
/*
65+
* SimpleHttpConnectionManager(boolean alwaysClose) :
66+
* alwaysClose - if set true, the connection manager will always close connections upon release.
67+
*/
68+
69+
HttpClient httpClient = new HttpClient(new SimpleHttpConnectionManager(true));
6470
setTimeout(httpClient, mc.getTimeout() * 1000);
6571
setProxy(httpClient);
6672

java/src/main/java/com/cybersource/ws/client/MerchantConfig.java

100644100755
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ public class MerchantConfig {
6464
private String proxyUser;
6565
private String proxyPassword;
6666
private String cacertPassword;
67-
private String useClientHttpFactory;
68-
private boolean useClientHttpFactoryFlag;
67+
private String customHttpClass;
68+
private boolean customHttpClassEnabled;
6969

70-
public String getUseClientHttpFactory() {
71-
return useClientHttpFactory;
70+
public String getcustomHttpClass() {
71+
return customHttpClass;
7272
}
73-
public boolean getUseClientHttpFactoryFlag() {
74-
return useClientHttpFactoryFlag;
73+
public boolean isCustomHttpClassEnabled() {
74+
return customHttpClassEnabled;
7575
}
7676
// computed values
7777
private String effectiveServerURL;
@@ -261,7 +261,7 @@ public MerchantConfig(Properties _props, String _merchantID)
261261
logFilename = getProperty(merchantID, "logFilename");
262262
logMaximumSize = getIntegerProperty(merchantID, "logMaximumSize", 10);
263263
useHttpClient = getBooleanProperty(merchantID, "useHttpClient", ConnectionHelper.getDefaultUseHttpClient());
264-
useClientHttpFactory = getProperty(merchantID, "useClientHttpFactory");
264+
customHttpClass = getProperty(merchantID, "customHttpClass");
265265
timeout = getIntegerProperty(merchantID, "timeout", DEFAULT_TIMEOUT);
266266
proxyHost = getProperty(merchantID, "proxyHost");
267267
proxyPort = getIntegerProperty(merchantID, "proxyPort", DEFAULT_PROXY_PORT);
@@ -270,7 +270,7 @@ public MerchantConfig(Properties _props, String _merchantID)
270270
enableJdkCert = getBooleanProperty(merchantID, "enableJdkCert", false);
271271
enableCacert=getBooleanProperty(merchantID, "enableCacert", false);
272272
cacertPassword=getProperty(merchantID,"cacertPassword","changeit");
273-
useClientHttpFactoryFlag=getBooleanProperty(merchantID,"useClientHttpFactoryFlag",false);
273+
customHttpClassEnabled=getBooleanProperty(merchantID,"customHttpClassEnabled",false);
274274
// compute and store effective namespace URI
275275

276276
if (namespaceURI == null && targetAPIVersion == null) {
@@ -473,8 +473,8 @@ public String getLogString() {
473473
appendPair(sb, "logDirectory", logDirectory);
474474
appendPair(sb, "logFilename", logFilename);
475475
appendPair(sb, "logMaximumSize", logMaximumSize);
476-
appendPair(sb, "useClientHttpFactory", useClientHttpFactory);
477-
appendPair(sb, "useClientHttpFactoryFlag", useClientHttpFactoryFlag);
476+
appendPair(sb, "customHttpClass", customHttpClass);
477+
appendPair(sb, "customHttpClassEnabled", customHttpClassEnabled);
478478
appendPair(sb, "useHttpClient", useHttpClient);
479479
appendPair(sb, "enableJdkCert", enableJdkCert);
480480
appendPair(sb, "enableCacert", enableCacert);

java/src/main/java/com/cybersource/ws/client/Utility.java

100644100755
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ private Utility() {
4848
/**
4949
* Version number of this release.
5050
*/
51-
public static final String VERSION = "6.2.3";
51+
public static final String VERSION = "6.2.5";
5252

5353
/**
5454
* If in the Request map, a key called "_has_escapes" is present and is set

java/src/main/java/com/cybersource/ws/client/XMLClient.java

100644100755
Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import java.io.ByteArrayOutputStream;
3636
import java.io.IOException;
3737
import java.io.StringReader;
38+
import java.lang.reflect.InvocationTargetException;
3839
import java.util.Properties;
3940

4041
/**
@@ -64,7 +65,8 @@ public class XMLClient {
6465

6566
private static Document soapEnvelope;
6667
private static Exception initException = null;
67-
68+
69+
6870
static {
6971
try {
7072
// load the SOAP envelope document.
@@ -137,7 +139,8 @@ public static Document runTransaction(Document request, Properties props)
137139
* @throws FaultException if a fault occurs.
138140
* @throws ClientException if any other exception occurs.
139141
*/
140-
public static Document runTransaction(
142+
@SuppressWarnings("unchecked")
143+
public static Document runTransaction(
141144
Document request, Properties props,
142145
Logger _logger, boolean prepare, boolean logTranStart)
143146
throws FaultException, ClientException {
@@ -177,8 +180,39 @@ public static Document runTransaction(
177180

178181
Document signedDoc
179182
= soapWrapAndSign(request, mc, builder, logger);
180-
181-
con = Connection.getInstance(mc, builder, logger);
183+
if(mc.isCustomHttpClassEnabled()){
184+
Class<Connection> customConnectionClass;
185+
try {
186+
customConnectionClass = (Class<Connection>) Class.forName(mc.getcustomHttpClass());
187+
Class[] constructor_Args = new Class[] {com.cybersource.ws.client.MerchantConfig.class, javax.xml.parsers.DocumentBuilder.class, com.cybersource.ws.client.LoggerWrapper.class};
188+
con=customConnectionClass.getDeclaredConstructor(constructor_Args).newInstance(mc, builder, logger);
189+
190+
} catch (InstantiationException e) {
191+
logger.log(Logger.LT_INFO, "Failed to Instantiate the class "+e);
192+
throw new ClientException(e, false, null);
193+
} catch (IllegalAccessException e) {
194+
logger.log(Logger.LT_INFO, "Could not Access the method invoked "+e);
195+
throw new ClientException(e, false, null);
196+
} catch (ClassNotFoundException e) {
197+
logger.log(Logger.LT_INFO, "Could not load the custom HTTP class ");
198+
throw new ClientException(e, false, null);
199+
} catch (IllegalArgumentException e) {
200+
logger.log(Logger.LT_INFO, "Method invoked with Illegal Argument list "+e);
201+
throw new ClientException(e, false, null);
202+
} catch (SecurityException e) {
203+
logger.log(Logger.LT_INFO, "Security Exception "+e);
204+
throw new ClientException(e, false, null);
205+
} catch (InvocationTargetException e) {
206+
logger.log(Logger.LT_INFO, "Exception occured while calling the method "+e);
207+
throw new ClientException(e, false, null);
208+
} catch (NoSuchMethodException e) {
209+
logger.log(Logger.LT_INFO, "Method not found ");
210+
throw new ClientException(e, false, null);
211+
}
212+
}
213+
else{
214+
con = Connection.getInstance(mc, builder, logger);
215+
}
182216
Document wrappedReply = con.post(signedDoc);
183217

184218
Document doc = soapUnwrap(wrappedReply, mc, builder, logger);

java/src/main/resources/cybs.properties

100644100755
Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,6 @@ sendToProduction=false
1515
sendToAkamai=true
1616
#serverURL=https://ics2wstesta.ic3.com/commerce/1.x/transactionProcessor
1717

18-
#To use your own Http library set useClientHttpFactoryFlag to true
19-
# set useClientHttpFactory field with the class name which has Http implementation
20-
#useClientHttpFactory=AmazonHttpConnection
21-
#useClientHttpFactoryFlag=true
22-
2318
#useHttpClient=false
2419

2520
# Following configure parameters will only work with useHttpClient=true
@@ -32,6 +27,11 @@ allowRetry=true
3227
numberOfRetries=5
3328
retryInterval=5
3429

30+
#To use your own Http library set customHttpClassEnabled to true
31+
# set customHttpClass field with the class name which has Http implementation. Provide the full class with package name.
32+
#customHttpClassEnabled=
33+
#customHttpClass=
34+
3535
# If This property is set to true then the p12 certificate must be stored in JKS format
3636
# program will read it from there. If it is set to false then the certificate will be read from
3737
# the location specified above from the key directory location
@@ -42,6 +42,7 @@ enableJdkCert=false
4242
enableCacert=false
4343
# Enter the password for cacert file. Default password for JDK cacert is changeit
4444
cacertPassword=
45+
4546
# Mechanism to differentiate whether Payload is encrypted or not
4647
useSignAndEncrypted=false
4748

0 commit comments

Comments
 (0)