Skip to content

Commit

Permalink
Merge pull request #17 from bcgov/feature/payment-services
Browse files Browse the repository at this point in the history
Adding Bambora Implementation
  • Loading branch information
TayGov authored Aug 25, 2020
2 parents f0571d5 + 47e5074 commit ebde3c3
Show file tree
Hide file tree
Showing 13 changed files with 482 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/bambora-payment-starter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Read Me First
The following was discovered as part of building this project:

* The original package name 'ca.bc.gov.open.bambora-payment-starter' is invalid and this project uses 'ca.bc.gov.open.bamborapaymentstarter' instead.

# Getting Started

### Reference Documentation
For further reference, please consider the following sections:

* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/2.3.3.RELEASE/maven-plugin/reference/html/#build-image)

84 changes: 84 additions & 0 deletions src/bambora-payment-starter/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>ca.bc.gov.open</groupId>
<artifactId>bambora-payment-starter</artifactId>
<version>0.1.5</version>

<properties>
<java.version>1.8</java.version>
<spring-boot.version>2.2.4.RELEASE</spring-boot.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>

<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>

</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>ca.bc.gov.open</groupId>
<artifactId>spring-starters-bom</artifactId>
<version>0.1.5</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ca.bc.gov.open.bambora.payment.starter;

import ca.bc.gov.open.bambora.payment.starter.managment.BamboraCardService;
import ca.bc.gov.open.bambora.payment.starter.managment.BamboraCardServiceImpl;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(BamboraProperties.class)
public class AutoConfiguration {

private final BamboraProperties bamboraProperties;

public AutoConfiguration(BamboraProperties bamboraProperties) {
this.bamboraProperties = bamboraProperties;
}

@Bean
@ConditionalOnMissingBean(BamboraCardService.class)
public BamboraCardService bamboraCardService() {
return new BamboraCardServiceImpl(bamboraProperties);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ca.bc.gov.open.bambora.payment.starter;

public class BamboraConstants {
public static final String PARAM_PPRDIR_SERVICE_VERSION = "serviceVersion";
public static final String PARAM_PPRDIR_MERCHANT_ID = "merchantId";
public static final String PARAM_PPRDIR_LANGUAGE = "trnLanguage";
public static final String PARAM_PPRDIR_OPERATION_TYPE = "operationType";
public static final String PARAM_PPRDIR_RETURN_URL = "trnReturnURL";
public static final String PARAM_PPRDIR_ORDER_NUMBER = "trnOrderNumber";
public static final String PARAM_PPRDIR_CUSTOMER_CODE = "customerCode";
public static final String PARAM_PPRDIR_REF1 = "ref1";
public static final String LANGUAGE_TYPE = "eng";
public static final String PARAM_TRANS_HASH_VALUE = "hashValue";
public static final String PARAM_TRANS_HASH_EXPIRY = "hashExpiry";
public static final String PARAM_TRANS_HASH_EXPIRY_FORMAT = "yyyyMMddkkmm";


public enum OperationTypes {
N, M
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ca.bc.gov.open.bambora.payment.starter;

public class BamboraException extends RuntimeException {

public BamboraException(String message, Throwable cause) {
super(message, cause);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package ca.bc.gov.open.bambora.payment.starter;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(BamboraProperties.class)
@ConfigurationProperties(prefix = "bambora")
public class BamboraProperties {
private String merchantId;
private String hostedProfileUrl;
private String hostedProfileServiceVersion;
private String hashKey;
private int minutesToExpiry;

public String getMerchantId() {
return merchantId;
}

public void setMerchantId(String merchantId) {
this.merchantId = merchantId;
}

public String getHostedProfileUrl() {
return hostedProfileUrl;
}

public void setHostedProfileUrl(String hostedProfileUrl) {
this.hostedProfileUrl = hostedProfileUrl;
}

public String getHostedProfileServiceVersion() {
return hostedProfileServiceVersion;
}

public void setHostedProfileServiceVersion(String hostedProfileServiceVersion) {
this.hostedProfileServiceVersion = hostedProfileServiceVersion;
}

public String getHashKey() {
return hashKey;
}

public void setHashKey(String hashKey) {
this.hashKey = hashKey;
}

public int getMinutesToExpiry() {
return minutesToExpiry;
}

public void setMinutesToExpiry(int minutesToExpiry) {
this.minutesToExpiry = minutesToExpiry;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ca.bc.gov.open.bambora.payment.starter.managment;

import ca.bc.gov.open.bambora.payment.starter.managment.models.RecurringPaymentDetails;
import com.sun.jndi.toolkit.url.Uri;

public interface BamboraCardService {
Uri setupRecurringPayment(RecurringPaymentDetails recurringPaymentDetails);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package ca.bc.gov.open.bambora.payment.starter.managment;

import ca.bc.gov.open.bambora.payment.starter.BamboraConstants;
import ca.bc.gov.open.bambora.payment.starter.BamboraException;
import ca.bc.gov.open.bambora.payment.starter.BamboraProperties;
import ca.bc.gov.open.bambora.payment.starter.managment.models.RecurringPaymentDetails;
import com.sun.jndi.toolkit.url.Uri;
import org.apache.commons.codec.digest.DigestUtils;

import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class BamboraCardServiceImpl implements BamboraCardService {

private final BamboraProperties bamboraProperties;

public BamboraCardServiceImpl(BamboraProperties bamboraProperties) {
this.bamboraProperties = bamboraProperties;
}

@Override
public Uri setupRecurringPayment(RecurringPaymentDetails recurringPaymentDetails) {
try {
return buildRecurringPaymentUrl(recurringPaymentDetails);
} catch (MalformedURLException e) {
throw new BamboraException("Url construction failed", e.getCause());
}
}


private Uri buildRecurringPaymentUrl(RecurringPaymentDetails recurringPaymentDetails) throws MalformedURLException {

String operationType = (recurringPaymentDetails.getEndUserId() != null ? BamboraConstants.OperationTypes.M.toString() : BamboraConstants.OperationTypes.N.toString());

StringBuilder paramString = new StringBuilder();

paramString.append(formatBamboraParam("", BamboraConstants.PARAM_PPRDIR_SERVICE_VERSION, bamboraProperties.getHostedProfileServiceVersion()));

paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_MERCHANT_ID, bamboraProperties.getMerchantId()));

paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_LANGUAGE, BamboraConstants.LANGUAGE_TYPE));

paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_OPERATION_TYPE, operationType));

paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_REF1, recurringPaymentDetails.getEchoData()));

paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_RETURN_URL, recurringPaymentDetails.getRedirectURL()));

paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_ORDER_NUMBER, recurringPaymentDetails.getRedirectURL()));

if (operationType.equals(BamboraConstants.OperationTypes.M.toString()))
paramString.append(formatBamboraParam("&", BamboraConstants.PARAM_PPRDIR_CUSTOMER_CODE, recurringPaymentDetails.getEndUserId()));

paramString.append(MessageFormat.format("&{0}={1}&{2}={3}", BamboraConstants.PARAM_TRANS_HASH_VALUE, getHash(paramString.toString()), BamboraConstants.PARAM_TRANS_HASH_EXPIRY, getExpiry()));

return new Uri(MessageFormat.format("{0}?{1}", bamboraProperties.getHostedProfileUrl(), paramString.toString()));

}

private String getExpiry() {
SimpleDateFormat sdfDate = new SimpleDateFormat(BamboraConstants.PARAM_TRANS_HASH_EXPIRY_FORMAT);
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.MINUTE, bamboraProperties.getMinutesToExpiry());
return sdfDate.format(cal.getTime());
}

private String formatBamboraParam(String prefix, String key, String value) {
return MessageFormat.format("{0}{1}={2}", prefix, key, value).replace(" ", "%20");
}

private String getHash(String message) {
String digest = DigestUtils.md5Hex(MessageFormat.format("{0}{1}", message, bamboraProperties.getHashKey()));
return digest.toUpperCase();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package ca.bc.gov.open.bambora.payment.starter.managment.models;

public class RecurringPaymentDetails {
private String orderNumber;
private String endUserId;
private String echoData;
private String redirectURL;

public String getOrderNumber() {
return orderNumber;
}

public String getEndUserId() {
return endUserId;
}

public String getEchoData() {
return echoData;
}

public String getRedirectURL() {
return redirectURL;
}

protected RecurringPaymentDetails(Builder builder) {
this.orderNumber = builder.orderNumber;
this.endUserId = builder.endUserId;
this.echoData = builder.echoData;
this.redirectURL = builder.redirectURL;
}

public static RecurringPaymentDetails.Builder builder() {
return new RecurringPaymentDetails.Builder();
}

public static class Builder {

private String orderNumber;
private String endUserId;
private String echoData;
private String redirectURL;

public Builder orderNumber(String orderNumber) {
this.orderNumber = orderNumber;
return this;
}

public Builder endUserId(String endUserId) {
this.endUserId = endUserId;
return this;
}

public Builder echoData(String echoData) {
this.echoData = echoData;
return this;
}

public Builder redirectURL(String redirectURL) {
this.redirectURL = redirectURL;
return this;
}

public RecurringPaymentDetails create() {
return new RecurringPaymentDetails(this);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
ca.bc.gov.open.bambora.payment.starter.AutoConfiguration
Loading

0 comments on commit ebde3c3

Please sign in to comment.