Skip to content

Commit de6b08c

Browse files
committed
Adding bambora payment service
1 parent f0571d5 commit de6b08c

File tree

13 files changed

+353
-0
lines changed

13 files changed

+353
-0
lines changed

src/bambora-payment-starter/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Read Me First
2+
The following was discovered as part of building this project:
3+
4+
* The original package name 'ca.bc.gov.open.bambora-payment-starter' is invalid and this project uses 'ca.bc.gov.open.bamborapaymentstarter' instead.
5+
6+
# Getting Started
7+
8+
### Reference Documentation
9+
For further reference, please consider the following sections:
10+
11+
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
12+
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/maven-plugin/reference/html/)
13+
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/maven-plugin/reference/html/#build-image)
14+

src/bambora-payment-starter/pom.xml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>ca.bc.gov.open</groupId>
7+
<artifactId>bambora-payment-starter</artifactId>
8+
<version>0.0.1-SNAPSHOT</version>
9+
10+
<properties>
11+
<java.version>1.8</java.version>
12+
<spring-boot.version>2.2.4.RELEASE</spring-boot.version>
13+
</properties>
14+
15+
<dependencies>
16+
<dependency>
17+
<groupId>org.springframework.boot</groupId>
18+
<artifactId>spring-boot-starter-web-services</artifactId>
19+
<exclusions>
20+
<exclusion>
21+
<groupId>org.springframework.boot</groupId>
22+
<artifactId>spring-boot-starter-tomcat</artifactId>
23+
</exclusion>
24+
</exclusions>
25+
</dependency>
26+
27+
<dependency>
28+
<groupId>org.springframework.boot</groupId>
29+
<artifactId>spring-boot-starter-test</artifactId>
30+
<scope>test</scope>
31+
<exclusions>
32+
<exclusion>
33+
<groupId>org.junit.vintage</groupId>
34+
<artifactId>junit-vintage-engine</artifactId>
35+
</exclusion>
36+
</exclusions>
37+
</dependency>
38+
39+
<dependency>
40+
<groupId>org.apache.commons</groupId>
41+
<artifactId>commons-lang3</artifactId>
42+
</dependency>
43+
44+
</dependencies>
45+
46+
<dependencyManagement>
47+
<dependencies>
48+
<dependency>
49+
<groupId>org.springframework.boot</groupId>
50+
<artifactId>spring-boot-dependencies</artifactId>
51+
<version>${spring-boot.version}</version>
52+
<type>pom</type>
53+
<scope>import</scope>
54+
</dependency>
55+
<dependency>
56+
<groupId>ca.bc.gov.open</groupId>
57+
<artifactId>spring-starters-bom</artifactId>
58+
<version>0.1.5</version>
59+
<type>pom</type>
60+
<scope>import</scope>
61+
</dependency>
62+
</dependencies>
63+
</dependencyManagement>
64+
65+
<build>
66+
<plugins>
67+
<plugin>
68+
<groupId>org.apache.maven.plugins</groupId>
69+
<artifactId>maven-compiler-plugin</artifactId>
70+
<version>3.5.1</version>
71+
<configuration>
72+
<source>${java.version}</source>
73+
<target>${java.version}</target>
74+
</configuration>
75+
</plugin>
76+
</plugins>
77+
</build>
78+
79+
</project>
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package ca.bc.gov.open.bambora.payment.starter;
2+
3+
import ca.bc.gov.open.bambora.payment.starter.managment.BamboraCardService;
4+
import ca.bc.gov.open.bambora.payment.starter.managment.BamboraCardServiceImpl;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
6+
import org.springframework.context.annotation.Bean;
7+
8+
public class AutoConfiguration {
9+
10+
private final BamboraProperties bamboraProperties;
11+
12+
public AutoConfiguration(BamboraProperties bamboraProperties) {
13+
this.bamboraProperties = bamboraProperties;
14+
}
15+
16+
@Bean
17+
@ConditionalOnMissingBean(BamboraCardService.class)
18+
public BamboraCardService bamboraCardService() {
19+
return new BamboraCardServiceImpl(bamboraProperties);
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package ca.bc.gov.open.bambora.payment.starter;
2+
3+
public class BamboraConstants {
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package ca.bc.gov.open.bambora.payment.starter;
2+
3+
public class BamboraException extends RuntimeException {
4+
5+
public BamboraException(String message, Throwable cause) {
6+
super(message, cause);
7+
}
8+
9+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package ca.bc.gov.open.bambora.payment.starter;
2+
3+
import org.springframework.boot.context.properties.ConfigurationProperties;
4+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
5+
import org.springframework.context.annotation.Configuration;
6+
7+
@Configuration
8+
@EnableConfigurationProperties(BamboraProperties.class)
9+
@ConfigurationProperties(prefix = "bambora")
10+
public class BamboraProperties {
11+
private String merchantId;
12+
private String hostedProfileUrl;
13+
private String hostedProfileServiceVersion;
14+
private String key;
15+
16+
public String getMerchantId() {
17+
return merchantId;
18+
}
19+
20+
public void setMerchantId(String merchantId) {
21+
this.merchantId = merchantId;
22+
}
23+
24+
public String getHostedProfileUrl() {
25+
return hostedProfileUrl;
26+
}
27+
28+
public void setHostedProfileUrl(String hostedProfileUrl) {
29+
this.hostedProfileUrl = hostedProfileUrl;
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package ca.bc.gov.open.bambora.payment.starter.managment;
2+
3+
import ca.bc.gov.open.bambora.payment.starter.managment.models.RecurringPaymentDetails;
4+
import com.sun.jndi.toolkit.url.Uri;
5+
6+
public interface BamboraCardService {
7+
Uri setupRecurringPayment(RecurringPaymentDetails recurringPaymentDetails);
8+
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package ca.bc.gov.open.bambora.payment.starter.managment;
2+
3+
import ca.bc.gov.open.bambora.payment.starter.BamboraException;
4+
import ca.bc.gov.open.bambora.payment.starter.BamboraProperties;
5+
import ca.bc.gov.open.bambora.payment.starter.managment.models.RecurringPaymentDetails;
6+
import com.sun.jndi.toolkit.url.Uri;
7+
8+
import java.net.MalformedURLException;
9+
10+
public class BamboraCardServiceImpl implements BamboraCardService {
11+
12+
private final BamboraProperties bamboraProperties;
13+
14+
public BamboraCardServiceImpl(BamboraProperties bamboraProperties) {
15+
this.bamboraProperties = bamboraProperties;
16+
}
17+
18+
@Override
19+
public Uri setupRecurringPayment(RecurringPaymentDetails recurringPaymentDetails) {
20+
try {
21+
return buildRecurringPaymentUrl(recurringPaymentDetails);
22+
} catch (MalformedURLException e) {
23+
throw new BamboraException("Url construction failed", e.getCause());
24+
}
25+
}
26+
27+
28+
private Uri buildRecurringPaymentUrl(RecurringPaymentDetails recurringPaymentDetails) throws MalformedURLException {
29+
String paramString = BeanstreamConstants.PARAM_PPRDIR_SERVICE_VERSION +
30+
"=" + this.hostedProfileServiceVersion +
31+
"&" + BeanstreamConstants.PARAM_PPRDIR_MERCHANT_ID +
32+
"=" + this.merchantId +
33+
"&" + BeanstreamConstants.PARAM_PPRDIR_LANGUAGE +
34+
"=" + BeanstreamConstants.LanguageType.eng.toString() +
35+
"&" + BeanstreamConstants.PARAM_PPRDIR_OPERATION_TYPE +
36+
"=" + opType.toString() +
37+
"&" + BeanstreamConstants.PARAM_PPRDIR_REF1 +
38+
"=" + echoData +
39+
"&" + BeanstreamConstants.PARAM_PPRDIR_RETURN_URL +
40+
"=" + redirectURL +
41+
"&" + BeanstreamConstants.PARAM_PPRDIR_ORDER_NUMBER +
42+
"=" + orderNumber;
43+
44+
// if doing an update, supply tyhe customer code.
45+
if ( (null != opType) && (opType == BeanstreamConstants.OperationTypes.M) ) {
46+
paramString = paramString + "&" + BeanstreamConstants.PARAM_PPRDIR_CUSTOMER_CODE +
47+
"=" + endUserId;
48+
}
49+
50+
//replace spaces with "%20" (do not do a full URL encoding. Doesn't work with beanstream.
51+
paramString = paramString.replace(" ", "%20");
52+
53+
//add hash key at end of params
54+
paramString = paramString + this.key;
55+
56+
// Calculate the MD5 value using the Hash Key set on the Order Settings page (Within Beanstream account).
57+
// How:
58+
// Place the hash key after the last parameter.
59+
// Perform an SHA-1 hash on the text up to the end of the key, then
60+
// Replace the hash key with hashValue=[hash result].
61+
// Add the result to the hosted service url.
62+
// Note: Hash is calculated on the params ONLY.. Does NOT include the hosted payment page url.
63+
// See http://support.beanstream.com/#docs/about-hash-validation.htm?Highlight=hash for more info.
64+
log.log(Level.INFO, "Calculating MD5 on paramString " + paramString);
65+
String hashed = getHash(paramString);
66+
67+
// Calculate the expiry based on the minutesToExpire value.
68+
SimpleDateFormat sdfDate = new SimpleDateFormat(BeanstreamConstants.PARAM_TRANS_HASH_EXPIRY_FORMAT);
69+
Calendar cal = Calendar.getInstance();
70+
cal.setTime(new Date());
71+
cal.add(Calendar.MINUTE, this.minutesToExpire);
72+
String expiry = sdfDate.format(cal.getTime());
73+
74+
// Add hash and expiry to the redirect
75+
paramString = paramString.replace(this.key,
76+
"&" + BeanstreamConstants.PARAM_TRANS_HASH_VALUE + "=" + hashed +
77+
"&" + BeanstreamConstants.PARAM_TRANS_HASH_EXPIRY + "=" + expiry);
78+
79+
String redirect = this.hostedProfileURL + "?" + paramString;
80+
return new Uri("blarg");
81+
}
82+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package ca.bc.gov.open.bambora.payment.starter.managment.models;
2+
3+
public class RecurringPaymentDetails {
4+
private String orderNumber;
5+
private String endUserId;
6+
private String echoData;
7+
private String redirectURL;
8+
9+
public String getOrderNumber() {
10+
return orderNumber;
11+
}
12+
13+
public String getEndUserId() {
14+
return endUserId;
15+
}
16+
17+
public String getEchoData() {
18+
return echoData;
19+
}
20+
21+
public String getRedirectURL() {
22+
return redirectURL;
23+
}
24+
25+
protected RecurringPaymentDetails(Builder builder) {
26+
this.orderNumber = builder.orderNumber;
27+
this.endUserId = builder.endUserId;
28+
this.echoData = builder.echoData;
29+
this.redirectURL = builder.redirectURL;
30+
}
31+
32+
public static class Builder {
33+
34+
private String orderNumber;
35+
private String endUserId;
36+
private String echoData;
37+
private String redirectURL;
38+
39+
public Builder orderNumber(String orderNumber) {
40+
this.orderNumber = orderNumber;
41+
return this;
42+
}
43+
44+
public Builder endUserId(String endUserId) {
45+
this.endUserId = endUserId;
46+
return this;
47+
}
48+
49+
public Builder echoData(String echoData) {
50+
this.echoData = echoData;
51+
return this;
52+
}
53+
54+
public Builder redirectURL(String redirectURL) {
55+
this.redirectURL = redirectURL;
56+
return this;
57+
}
58+
59+
public RecurringPaymentDetails create() {
60+
return new RecurringPaymentDetails(this);
61+
}
62+
63+
}
64+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
2+
ca.bc.gov.open.bambora.payment.starter.AutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package ca.bc.gov.open.bambora.payment.starter;
2+
3+
import ca.bc.gov.open.bambora.payment.starter.managment.BamboraCardService;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.DisplayName;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.TestInstance;
8+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
9+
10+
import static org.assertj.core.api.Assertions.assertThat;
11+
12+
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
13+
@DisplayName("Test AutoConfiguration")
14+
public class AutoConfigurationTest {
15+
ApplicationContextRunner context = new ApplicationContextRunner();
16+
17+
@Test
18+
@DisplayName("Test Beans Exist")
19+
public void testConfigure() {
20+
21+
context.run(it -> {
22+
Assertions.assertNotNull(assertThat(it).getBean(BamboraCardService.class));
23+
});
24+
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package ca.bc.gov.open.bambora.payment.starter.managment;
2+
3+
public class BamboraCardServiceTest {
4+
}

src/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<module>spring-bceid-starter</module>
2424
<module>spring-starters-bom</module>
2525
<module>spring-clamav-starter</module>
26+
<module>bambora-payment-starter</module>
2627
</modules>
2728
</profile>
2829

@@ -50,6 +51,13 @@
5051
</modules>
5152
</profile>
5253

54+
<profile>
55+
<id>payment</id>
56+
<modules>
57+
<module>bambora-payment-starter</module>
58+
</modules>
59+
</profile>
60+
5361
</profiles>
5462

5563
</project>

0 commit comments

Comments
 (0)