- Introduction
- Contributing
- Minimum Requirements
- Dependency
- Quick Start
- Configuration
- Client Creation
- Correlation ID
- Full Examples
- Individual API Call Examples
This SDK allows merchants with Java-based e-commerce site to integrate with Blink PayNow (for one-off payments) and Blink AutoPay (for recurring payments).
This SDK internally uses WebClient, a reactive Web client introduced in Spring Framework 5, for making API calls.
We welcome contributions from the community. Your pull request will be reviewed by our team.
This project is licensed under the MIT License.
- Maven 3 or Gradle 7
- Java 8 or higher
- Lombok 1.18 (for development only)
For:
- Java 8 or higher using plain java
- or with Spring versions less than 6 (i.e. including Spring Boot 2)
use
blink-debit-api-client-java
<dependency>
<groupId>nz.co.blinkpay</groupId>
<artifactId>blink-debit-api-client-java</artifactId>
<version>${version}</version>
</dependency>
For Spring 6 (i.e. including Spring Boot 3), use blink-debit-api-client-java-spring6
<dependency>
<groupId>nz.co.blinkpay</groupId>
<artifactId>blink-debit-api-client-java-spring6</artifactId>
<version>${version}</version>
</dependency>
implementation "nz.co.blinkpay:blink-debit-api-client-java:$version"
implementation "nz.co.blinkpay:blink-debit-api-client-java-spring6:$version"
String blinkpayUrl = "https://sandbox.debit.blinkpay.co.nz";
String clientId = "...";
String clientSecret = "...";
String profile = "local";
BlinkDebitClient client = new BlinkDebitClient(blinkpayUrl, clientId, clientSecret, profile);
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri("https://www.blinkpay.co.nz/sample-merchant-return-page")))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total("0.01"))
.pcr(new Pcr()
.particulars("particulars")
.code("code")
.reference("reference"));
CreateQuickPaymentResponse qpCreateResponse = client.createQuickPayment(request);
logger.info("Redirect URL: {}", qpCreateResponse.getRedirectUri()); // Redirect the consumer to this URL
UUID qpId = qpCreateResponse.getQuickPaymentId();
QuickPaymentResponse qpResponse = client.awaitSuccessfulQuickPaymentOrThrowException(qpId, 300); // Will throw an exception if the payment was not successful after 5min
- Customise/supply the required properties in your
blinkdebit.yaml
orblinkdebit.properties
. This file should be available in your classpath, i.e. normally placed insrc/main/resources
. - The BlinkPay Sandbox debit URL is
https://sandbox.debit.blinkpay.co.nz
and the production debit URL ishttps://debit.blinkpay.co.nz
. - The client credentials will be provided to you by BlinkPay as part of your on-boarding process.
- Properties can be supplied using environment variables.
Warning Take care not to check in your client ID and secret to your source control.
Properties will be detected and loaded according to the heirarcy -
- As provided directly to client constructor
- Environment variables e.g.
export BLINKPAY_CLIENT_SECRET=...
- System properties e.g.
-Dblinkpay.client.secret=...
blinkdebit.properties
blinkdebit.yaml
- Default values
export BLINKPAY_DEBIT_URL=<BLINKPAY_DEBIT_URL>
export BLINKPAY_CLIENT_ID=<BLINKPAY_CLIENT_ID>
export BLINKPAY_CLIENT_SECRET=<BLINKPAY_CLIENT_SECRET>
# for non-Spring consumer as an alternative to spring.profiles.active property. Debugging profiles are local, dev or test. Any other value will behave in a production-like manner.
export BLINKPAY_ACTIVE_PROFILE=test
# Optional configuration values below
export BLINKPAY_MAX_CONNECTIONS=10
export BLINKPAY_MAX_IDLE_TIME=PT20S
export BLINKPAY_MAX_LIFE_TIME=PT60S
export BLINKPAY_PENDING_ACQUIRE_timeout=PT10S
export BLINKPAY_EVICTION_INTERVAL=PT60S
export BLINKPAY_RETRY_ENABLED=true
Substitute the correct values to your blinkdebit.properties
file.
blinkpay.debit.url=<BLINKPAY_DEBIT_URL>
blinkpay.client.id=<BLINKPAY_CLIENT_ID>
blinkpay.client.secret=<BLINKPAY_CLIENT_SECRET>
# for non-Spring consumer as an alternative to spring.profiles.active property. Debugging profiles are local, dev or test. Any other value will behave in a production-like manner.
blinkpay.active.profile=test
# Optional configuration values below
blinkpay.max.connections=10
blinkpay.max.idle.time=PT20S
blinkpay.max.life.time=PT60S
blinkpay.pending.acquire.timeout=PT10S
blinkpay.eviction.interval=PT60S
blinkpay.retry.enabled=true
The property placeholders below will only work for Spring consumers by substituting the corresponding environment variables.
blinkpay.debit.url=${BLINKPAY_DEBIT_URL}
blinkpay.client.id=${BLINKPAY_CLIENT_ID}
blinkpay.client.secret=${BLINKPAY_CLIENT_SECRET}
# for non-Spring consumer as an alternative to spring.profiles.active property. Debugging profiles are local, dev or test. Any other value will behave in a production-like manner.
blinkpay.active.profile=${BLINKPAY_ACTIVE_PROFILE:test}
# Optional configuration values below
blinkpay.max.connections=${BLINKPAY_MAX_CONNECTIONS:10}
blinkpay.max.idle.time=${BLINKPAY_MAX_IDLE_TIME:PT20S}
blinkpay.max.life.time=${BLINKPAY_MAX_LIFE_TIME:PT60S}
blinkpay.pending.acquire.timeout=${BLINKPAY_PENDING_ACQUIRE_TIMEOUT:PT10S}
blinkpay.eviction.interval=${BLINKPAY_EVICTION_INTERVAL:PT60S}
blinkpay.retry.enabled=${BLINKPAY_RETRY_ENABLED:true}
The property placeholders below will only work for Spring consumers by substituting the corresponding environment variables.
blinkpay:
debit:
url: ${BLINKPAY_DEBIT_URL}
client:
id: ${BLINKPAY_CLIENT_ID}
secret: ${BLINKPAY_CLIENT_SECRET}
# Optional configuration values below
max:
connections: ${BLINKPAY_MAX_CONNECTIONS:10}
idle:
time: ${BLINKPAY_MAX_IDLE_TIME:PT20S}
life:
time: ${BLINKPAY_MAX_LIFE_TIME:PT60S}
pending:
acquire:
timeout: ${BLINKPAY_PENDING_ACQUIRE_TIMEOUT:PT10S}
eviction:
interval: ${BLINKPAY_EVICTION_INTERVAL:PT60S}
retry:
enabled: ${BLINKPAY_RETRY_ENABLED:true}
Plain Java client code can use the no-arg constructor which will attempt to populate the properties according to the hierarchy above.
BlinkDebitClient client = new BlinkDebitClient();
Another way is to supply the required properties on object creation:
BlinkDebitClient client = new BlinkDebitClient(blinkpayUrl, clientId, clientSecret, "production");
Spring-based client code can simply autowire/inject the API client when properties are supplied as above.
@Autowired
BlinkDebitClient client;
An optional correlation ID can be added as the last argument to API calls. This is also the idempotency key for Blink API calls.
It will be generated for you automatically if it is not provided.
A quick payment is a one-off payment that combines the API calls needed for both the consent and the payment.
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri("https://www.blinkpay.co.nz/sample-merchant-return-page")))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total("0.01"))
.pcr(new Pcr()
.particulars("particulars")
.code("code")
.reference("reference"));
CreateQuickPaymentResponse qpCreateResponse = client.createQuickPayment(request);
logger.info("Redirect URL: {}", qpCreateResponse.getRedirectUri()); // Redirect the consumer to this URL
UUID qpId = qpCreateResponse.getQuickPaymentId();
QuickPaymentResponse qpResponse = client.awaitSuccessfulQuickPaymentOrThrowException(qpId, 300); // Will throw an exception if the payment was not successful after 5min
SingleConsentRequest consent = new SingleConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri("https://www.blinkpay.co.nz/sample-merchant-return-page")
.flowHint(new RedirectFlowHint()
.bank(Bank.BNZ)))) // Optional, bank will be preselected
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total("0.01"))
.pcr(new Pcr()
.particulars("particulars"));
CreateConsentResponse createConsentResponse = client.createSingleConsent(consent);
String redirectUri = createConsentResponse.getRedirectUri(); // Redirect the consumer to this URL
PaymentRequest payment = new PaymentRequest().consentId(createConsentResponse.getConsentId());
PaymentResponse paymentResponse = client.createPayment(payment);
logger.info("Payment Status: {}", client.getPayment(paymentResponse.getPaymentId()).getStatus());
// TODO inspect the payment result status
Supplies the supported banks and supported flows on your account.
List<BankMetadata> bankMetadataList = client.getMeta();
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateQuickPaymentResponse createQuickPaymentResponse = client.createQuickPayment(request);
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)
.flowHint(new RedirectFlowHint()
.bank(bank))))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateQuickPaymentResponse createQuickPaymentResponse = client.createQuickPayment(request);
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)
.flowHint(new DecoupledFlowHint()
.identifierType(identifierType)
.identifierValue(identifierValue)
.bank(bank))))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateQuickPaymentResponse createQuickPaymentResponse = client.createQuickPayment(request);
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new RedirectFlow()
.bank(bank)
.redirectUri(redirectUri)))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateQuickPaymentResponse createQuickPaymentResponse = client.createQuickPayment(request);
QuickPaymentRequest request = (QuickPaymentRequest) new QuickPaymentRequest()
.flow(new AuthFlow()
.detail(new RedirectFlow()
.bank(bank)
.identifierType(identifierType)
.identifierValue(identifierValue)
.callbackUrl(callbackUrl)))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateQuickPaymentResponse createQuickPaymentResponse = client.createQuickPayment(request);
QuickPaymentResponse quickPaymentResponse = client.getQuickPayment(quickPaymentId);
client.revokeQuickPayment(quickPaymentId);
SingleConsentRequest request = new SingleConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateConsentResponse createConsentResponse = client.createSingleConsent(request);
SingleConsentRequest request = new SingleConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)
.flowHint(new RedirectFlowHint()
.bank(bank))))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateConsentResponse createConsentResponse = client.createSingleConsent(request);
SingleConsentRequest request = new SingleConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)
.flowHint(new DecoupledFlowHint()
.identifierType(identifierType)
.identifierValue(identifierValue)
.bank(bank))))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateConsentResponse createConsentResponse = client.createSingleConsent(request);
Suitable for most consents.
SingleConsentRequest request = new SingleConsentRequest()
.flow(new AuthFlow()
.detail(new RedirectFlow()
.bank(bank)
.redirectUri(redirectUri)))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateConsentResponse createConsentResponse = client.createSingleConsent(request);
This flow type allows better support for mobile by allowing the supply of a mobile number or previous consent ID to identify the customer with their bank.
The customer will receive the consent request directly to their online banking app. This flow does not send the user through a web redirect flow.
SingleConsentRequest request = new SingleConsentRequest()
.flow(new AuthFlow()
.detail(new DecoupledFlow()
.bank(bank)
.identifierType(identifierType)
.identifierValue(identifierValue)
.callbackUrl(callbackUrl)))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference));
CreateConsentResponse createConsentResponse = client.createSingleConsent(request);
Get the consent including its status
Consent consent = client.getSingleConsent(consentId);
client.revokeSingleConsent(consentId);
Request an ongoing authorisation from the customer to debit their account on a recurring basis.
Note that such an authorisation can be revoked by the customer in their mobile banking app.
EnduringConsentRequest request = new EnduringConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)))
.maximumAmountPeriod(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.period(period)
.fromTimestamp(startDate)
.expiryTimestamp(endDate);
CreateConsentResponse createConsentResponse = client.createEnduringConsent(request);
EnduringConsentRequest request = new EnduringConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)
.flowHint(new RedirectFlowHint()
.bank(bank))))
.maximumAmountPeriod(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.period(period)
.fromTimestamp(startDate)
.expiryTimestamp(endDate);
CreateConsentResponse createConsentResponse = client.createEnduringConsent(request);
EnduringConsentRequest request = new EnduringConsentRequest()
.flow(new AuthFlow()
.detail(new GatewayFlow()
.redirectUri(redirectUri)
.flowHint(new DecoupledFlowHint()
.identifierType(identifierType)
.identifierValue(identifierValue)
.bank(bank))))
.maximumAmountPeriod(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.period(period)
.fromTimestamp(startDate)
.expiryTimestamp(endDate);
CreateConsentResponse createConsentResponse = client.createEnduringConsent(request);
EnduringConsentRequest request = new EnduringConsentRequest()
.flow(new AuthFlow()
.detail(new RedirectFlow()
.bank(bank)
.redirectUri(redirectUri)))
.maximumAmountPeriod(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.period(period)
.fromTimestamp(startDate)
.expiryTimestamp(endDate);
CreateConsentResponse createConsentResponse = client.createEnduringConsent(request);
EnduringConsentRequest request = new EnduringConsentRequest()
.flow(new AuthFlow()
.detail(new DecoupledFlow()
.bank(bank)
.identifierType(identifierType)
.identifierValue(identifierValue)
.callbackUrl(callbackUrl)))
.maximumAmountPeriod(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.period(period)
.fromTimestamp(startDate)
.expiryTimestamp(endDate);
CreateConsentResponse createConsentResponse = client.createEnduringConsent(request);
Consent consent = client.getEnduringConsent(consentId);
client.revokeEnduringConsent(consentId);
The completion of a payment requires a consent to be in the Authorised status.
PaymentRequest request = new PaymentRequest()
.consentId(consentId);
PaymentResponse paymentResponse = client.createPayment(request);
If you already have an approved consent, you can run a Payment against that consent at the frequency as authorised in the consent.
PaymentRequest request = new PaymentRequest()
.consentId(consentId)
.enduringPayment(new EnduringPaymentRequest()
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference)));
PaymentResponse paymentResponse = client.createPayment(request);
Payment payment = client.getPayment(paymentId);
AccountNumberRefundRequest request = (AccountNumberRefundRequest) new AccountNumberRefundRequest()
.paymentId(paymentId);
RefundResponse refundResponse = client.createRefund(request);
FullRefundRequest request = (FullRefundRequest) new FullRefundRequest()
.consentRedirect(redirectUri)
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference))
.paymentId(paymentId);
RefundResponse refundResponse = client.createRefund(request);
PartialRefundRequest request = (PartialRefundRequest) new PartialRefundRequest()
.consentRedirect(redirectUri)
.pcr(new Pcr()
.particulars(particulars)
.code(code)
.reference(reference))
.amount(new Amount()
.currency(Amount.CurrencyEnum.NZD)
.total(total))
.paymentId(paymentId);
RefundResponse refundResponse = client.createRefund(request);
Refund refund = client.getRefund(refundId);