Skip to content

Commit 9b89587

Browse files
committed
merchant key validity check and optional caching implementation while executing loadMerchantP12File method.
1 parent a30f03d commit 9b89587

20 files changed

Lines changed: 119 additions & 45 deletions

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CyberSource Simple Order API for Java
22

3-
[![Build Status](https://travis-ci.org/CyberSource/cybersource-sdk-java.png?branch=future)](https://travis-ci.org/CyberSource/cybersource-sdk-java)
3+
[![Build Status](https://travis-ci.org/CyberSource/cybersource-sdk-java.png?branch=master)](https://travis-ci.org/CyberSource/cybersource-sdk-java)
44

55
## Package Managers
66

@@ -10,7 +10,7 @@ To install the `cybersource-sdk-java` from central repository, add dependency to
1010
<dependency>
1111
<groupId>com.cybersource</groupId>
1212
<artifactId>cybersource-sdk-java</artifactId>
13-
<version>6.2.5</version>
13+
<version>6.2.6</version>
1414
</dependency>
1515
```
1616
Run `mvn install` to install dependency
@@ -19,7 +19,7 @@ Run `mvn install` to install dependency
1919
Add the dependency to your build.gradle
2020
```java
2121
dependencies {
22-
compile 'com.cybersource:cybersource-sdk-java:6.2.5'
22+
compile 'com.cybersource:cybersource-sdk-java:6.2.6'
2323
}
2424
```
2525
## Requirements
@@ -61,6 +61,7 @@ You do not need to download and build the source to use the SDK but if you want
6161
- if `enablejdkcert` parameter is set to true, certificates will be read from the JKS file specified at keysDirectory location. The JKS file should be of the same name as specified in keyFilename.
6262
- To know how to convert p12 to JKS refer the JKS creation section of this document.
6363
- `enableCacerts` property is considered only if `enablejdkcert` is set to true. If `enableCacerts` is set to true, certificates will be read from the cacerts folder under the JDK.
64+
- if `certificateCacheEnabled` parameter is set to false (default is true), the p12 certificate of a merchant will be reloaded from filesystem every time a transaction is made
6465
- `allowRetry` config parameter will only work for HttpClient. Set `allowRetry` config parameter to "true" to enable retry mechanism and set merchant specific values for the retry.
6566
- Set integer values for config parameter `numberOfRetries` *and* `retryInterval`. Retry Interval is time delay for next retry in seconds.
6667
- Number of retry parameter should be set between 1 to 5. Any other value will throw an Error Message.
@@ -181,12 +182,12 @@ Retry Pattern allows to retry sending a failed request and it will only work wit
181182

182183
## Changes
183184

184-
Version Cybersource-sdk-java 6.2.5 (OCT,2017)
185+
Version Cybersource-sdk-java 6.2.6 (OCT,2017)
185186
_______________________________
186187
1) Merchant cert to be read from JAVA key store. Flag is added to enable reading cert from Java keystore.
187188
2) Added Custom HttpClient feature. Merchants can use there own http client instead of defaults which comes with SDK.
188189
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+
4) Changed clientLibrary version to 6.2.6; in 6.2.4 release it was missed. So, in 6.2.4 release, clientLibrary version was pointing to 6.2.3.
190191
_______________________________
191192
Version Cybersource-sdk-java 6.2.4 (Dec 15, 2016)
192193
_______________________________

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class Identity {
4141

4242
private static final String SERVER_ALIAS = "CyberSource_SJC_US";
4343

44-
Logger logger = new LoggerImpl(merchantConfig);
44+
private Logger logger = null;
4545

4646

4747

@@ -55,9 +55,12 @@ public class Identity {
5555
* @param x509Certificate
5656
* @throws SignException
5757
*/
58-
public Identity(MerchantConfig merchantConfig,X509Certificate x509Certificate) throws SignException {
58+
public Identity(MerchantConfig merchantConfig,X509Certificate x509Certificate,Logger logger) throws SignException {
5959
this.merchantConfig = merchantConfig;
6060
this.x509Cert=x509Certificate;
61+
if(this.logger == null){
62+
this.logger=logger;
63+
}
6164
if(merchantConfig.isJdkCertEnabled()){
6265
setupJdkServerCerts();
6366
}
@@ -98,26 +101,38 @@ else if (subjectDNrray.length == 2 && subjectDNrray[1].contains(SERVER_ALIAS)) {
98101
* @param privateKey
99102
* @throws SignException
100103
*/
101-
public Identity(MerchantConfig merchantConfig,X509Certificate x509Certificate, PrivateKey privateKey) throws SignException {
104+
public Identity(MerchantConfig merchantConfig,X509Certificate x509Certificate, PrivateKey privateKey,Logger logger) throws SignException {
102105
this.merchantConfig = merchantConfig;
103106
this.x509Cert = x509Certificate;
104107
this.privateKey = privateKey;
108+
if(this.logger == null){
109+
this.logger=logger;
110+
}
105111
try {
106112
this.lastModifiedDate=merchantConfig.getKeyFile().lastModified();
107113
} catch (ConfigException e) {
108114

109115
logger.log(Logger.LT_EXCEPTION,
110116
"Identity object ,cannot instantiate with key file lastModifiedDate. "
111117
+ e.getMessage());
112-
throw new SignException(e.getMessage());
118+
throw new SignException("Exception While initializing the merchant identity constructor with keyfile last modified date"+e.getMessage());
113119
}
114120
setUpMerchant();
115121
}
116122

117123
public boolean isValid(File keyFile)
118124
{
119125

120-
return this.lastModifiedDate == keyFile.lastModified();
126+
if(this.lastModifiedDate == keyFile.lastModified()){
127+
128+
logger.log(Logger.LT_INFO, "key files not yet changed");
129+
}
130+
//boolean b=this.lastModifiedDate == keyFile.lastModified();
131+
//String p=String.valueOf(b);
132+
//logger.log(Logger.LT_INFO,"Check the merchant certificate is new " +p);
133+
//return b;
134+
//logger.log(Logger.LT_INFO, "Could not load the custom HTTP class ");
135+
return this.lastModifiedDate == keyFile.lastModified();
121136
}
122137

123138
private void setUpMerchant() throws SignException {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class MerchantConfig {
6666
private String cacertPassword;
6767
private String customHttpClass;
6868
private boolean customHttpClassEnabled;
69+
private boolean certificateCacheEnabled;
6970

7071
public String getcustomHttpClass() {
7172
return customHttpClass;
@@ -83,6 +84,8 @@ public boolean isCustomHttpClassEnabled() {
8384
private int numberOfRetries = 0;
8485
private long retryInterval = 0;
8586
private boolean allowRetry=true;
87+
88+
8689

8790

8891
// getter methods
@@ -183,6 +186,10 @@ public String getProxyPassword() {
183186
return proxyPassword != null ? proxyPassword : "";
184187
}
185188

189+
public boolean isCertificateCacheEnabled() {
190+
return certificateCacheEnabled;
191+
}
192+
186193
/**
187194
* Returns the effective server URL to which the request will be sent.
188195
* If a serverURL is specified, then that is what is returned.
@@ -271,6 +278,7 @@ public MerchantConfig(Properties _props, String _merchantID)
271278
enableCacert=getBooleanProperty(merchantID, "enableCacert", false);
272279
cacertPassword=getProperty(merchantID,"cacertPassword","changeit");
273280
customHttpClassEnabled=getBooleanProperty(merchantID,"customHttpClassEnabled",false);
281+
certificateCacheEnabled=getBooleanProperty(merchantID,"certificateCacheEnabled",true);
274282
// compute and store effective namespace URI
275283

276284
if (namespaceURI == null && targetAPIVersion == null) {
@@ -495,6 +503,7 @@ public String getLogString() {
495503
}
496504
}
497505
appendPair(sb, "useSignAndEncrypted", useSignAndEncrypted);
506+
appendPair(sb, "certificateCacheEnabled", certificateCacheEnabled);
498507
return (sb.toString());
499508
}
500509

@@ -580,4 +589,5 @@ public boolean isJdkCertEnabled() {
580589
public String getCacertPassword(){
581590
return cacertPassword;
582591
}
592+
583593
}

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.security.UnrecoverableKeyException;
2424
import java.security.cert.CertificateException;
2525
import java.security.cert.X509Certificate;
26-
import java.util.ArrayList;
2726
import java.util.Collections;
2827
import java.util.Enumeration;
2928
import java.util.concurrent.ConcurrentHashMap;
@@ -81,13 +80,13 @@ private static void initKeystore() throws KeyStoreException, CredentialException
8180
*/
8281
public static void loadMerchantP12File(MerchantConfig merchantConfig, Logger logger) throws SignException, SignEncryptException, ConfigException {
8382

84-
// Load the KeyStore and get the signing key and certificate do this once only
83+
// Load the KeyStore and get the signing key and certificate
8584
// This change is made based on the assumptions that at point of time , a merchant will have only one P12 Key
8685

8786

8887

8988
Identity identity=identities.get(merchantConfig.getMerchantID());
90-
if(identity == null || !(identity.isValid(merchantConfig.getKeyFile()))){
89+
if(!merchantConfig.isCertificateCacheEnabled() || identity == null || !(identity.isValid(merchantConfig.getKeyFile()))){
9190
try {
9291
if (localKeyStoreHandler == null)
9392
initKeystore();
@@ -164,12 +163,12 @@ private static void readAndStoreCertificateAndPrivateKey(MerchantConfig merchant
164163
throw new SignException(e);
165164
}
166165

167-
Identity identity = new Identity(merchantConfig,(X509Certificate) keyEntry.getCertificate(),keyEntry.getPrivateKey());
166+
Identity identity = new Identity(merchantConfig,(X509Certificate) keyEntry.getCertificate(),keyEntry.getPrivateKey(),logger);
168167
localKeyStoreHandler.addIdentityToKeyStore(identity, logger);
169168
identities.put(identity.getName(), identity);
170169
continue;
171170
}
172-
Identity identity = new Identity(merchantConfig, (X509Certificate) merchantKeyStore.getCertificate(merchantKeyAlias));
171+
Identity identity = new Identity(merchantConfig, (X509Certificate) merchantKeyStore.getCertificate(merchantKeyAlias),logger);
173172
localKeyStoreHandler.addIdentityToKeyStore(identity, logger);
174173
identities.put(identity.getName(), identity);
175174
}
@@ -312,12 +311,12 @@ public static void readJdkCert(MerchantConfig merchantConfig, Logger logger) thr
312311
throw new SignException(e);
313312
}
314313

315-
Identity identity = new Identity(merchantConfig,(X509Certificate) keyEntry.getCertificate(),keyEntry.getPrivateKey());
314+
Identity identity = new Identity(merchantConfig,(X509Certificate) keyEntry.getCertificate(),keyEntry.getPrivateKey(),logger);
316315
localKeyStoreHandler.addIdentityToKeyStore(identity, logger);
317316
identities.put(identity.getName(), identity);
318317
continue;
319318
}
320-
Identity identity = new Identity(merchantConfig, (X509Certificate) keystore.getCertificate(merchantKeyAlias));
319+
Identity identity = new Identity(merchantConfig, (X509Certificate) keystore.getCertificate(merchantKeyAlias),logger);
321320
localKeyStoreHandler.addIdentityToKeyStore(identity, logger);
322321
identities.put(identity.getName(), identity);
323322
}
@@ -358,13 +357,13 @@ private static void loadJavaKeystore(String keystore_location, MerchantConfig me
358357
if (merchantConfig.getKeyAlias().equals(
359358
keystore.getCertificateAlias(cert[i]))) {
360359
identity = new Identity(merchantConfig,
361-
(X509Certificate) cert[i], key);
360+
(X509Certificate) cert[i], key,logger);
362361
localKeyStoreHandler
363362
.addIdentityToKeyStore(identity, logger);
364363
identities.put(identity.getName(), identity);
365364
} else {
366365
identity = new Identity(merchantConfig,
367-
(X509Certificate) cert[i]);
366+
(X509Certificate) cert[i],logger);
368367
localKeyStoreHandler
369368
.addIdentityToKeyStore(identity, logger);
370369
identities.put(identity.getName(), identity);
@@ -375,7 +374,7 @@ private static void loadJavaKeystore(String keystore_location, MerchantConfig me
375374
throw new SignException("Missing Server Certificate ");
376375
}
377376
identity = new Identity(merchantConfig,
378-
(X509Certificate) serverCert);
377+
(X509Certificate) serverCert,logger);
379378
localKeyStoreHandler
380379
.addIdentityToKeyStore(identity, logger);
381380
identities.put(identity.getName(), identity);

java/src/main/resources/cybs.properties

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ enableLog=true
5454
logDirectory=../../logs
5555
logMaximumSize=10
5656

57+
# If this property is set to false then the p12 certificate of a merchant will be reloaded
58+
# every time a transaction is made
59+
60+
certificateCacheEnabled=true
61+
5762
# Optional proxy server settings
5863
#proxyHost=<-- Set the Proxy Host-->
5964
#proxyPort=< -- Set the Proxy port-->

java/src/test/java/com/cybersource/ws/client/IdentityTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@ public void testSetUpMerchant() throws InstantiationException, IllegalAccessExce
3434
X509Certificate x509Cert = Mockito.mock(X509Certificate.class);
3535
Principal principal = Mockito.mock(Principal.class);
3636
PrivateKey pkey = Mockito.mock(PrivateKey.class);
37+
Logger logger = Mockito.mock(Logger.class);
3738
Mockito.when(x509Cert.getSubjectDN()).thenReturn(principal);
3839
Mockito.when(principal.getName()).thenReturn(keyAlias);
39-
Identity identity = new Identity(config,x509Cert,pkey);
40+
Identity identity = new Identity(config,x509Cert,pkey,logger);
4041
assertEquals(identity.getName(), config.getMerchantID());
4142
assertEquals(identity.getSerialNumber(), "400000009910179089277");
4243
assertNotNull(identity.getPrivateKey());
@@ -47,9 +48,10 @@ public void testsetUpServer() throws InstantiationException, IllegalAccessExcept
4748
String keyAlias = "CN=CyberSource_SJC_US,SERIALNUMBER=400000009910179089277";
4849
X509Certificate x509Cert = Mockito.mock(X509Certificate.class);
4950
Principal principal = Mockito.mock(Principal.class);
51+
Logger logger = Mockito.mock(Logger.class);
5052
Mockito.when(x509Cert.getSubjectDN()).thenReturn(principal);
5153
Mockito.when(principal.getName()).thenReturn(keyAlias);
52-
Identity identity = new Identity(config,x509Cert);
54+
Identity identity = new Identity(config,x509Cert,logger);
5355
assertEquals(identity.getName(), "CyberSource_SJC_US");
5456
assertEquals(identity.getSerialNumber(), "400000009910179089277");
5557
assertNull(identity.getPrivateKey());

0 commit comments

Comments
 (0)