Skip to content

v2.0.0

Choose a tag to compare

@Aman-Aalam Aman-Aalam released this 17 Nov 04:48
· 4 commits to master since this release
17817b7

Trolley Java SDK Major Update (November 16, 2023)

With this update we're making some important changes to our Java SDK.
This update covers all the API endpoints our SDK didn't cover before, and makes some important updates to how our packages are organized.

To mark this milestone we're bumping up the MAJOR version 2.0.0.

Please read this Update Guide to understand what changed and how to adopt these changes.

Breaking Changes

1. Types have been moved to a different package

The Java SDK packages have been reorganized and all classes representing types have been moved to the types package.

This will throw compile time error in your code base, but reorganizing imports should solve this.

Here's an example of how it used to be before vs how it is now:

Old Package New Installation
import com.trolley.trolley.Payment import com.trolley.Payment
import com.trolley.trolley.Payments import com.trolley.type.Payments
import com.trolley.types.Meta import com.trolley.types.supporting.Meta

2. Method Parameters Changed

To conform with Java ways, all Gateway methods now accept only Objects as request bodies and not Strings.

As an example, here's how some methods worked earlier versus how they work now:

Old Way New Way
String body = "{\"firstName\": \"Bob\"}";
boolean response = client.recipient.update(recipient.getId(), body);
Recipient recipientUpdateRequest = new Recipient();
recipientUpdateRequest.setFirstName("Bob");
boolean response = client.recipient.update(recipient.getId(), recipientUpdateRequest);

3. Recipient Gateway Changes

1. Recipient.search() method

  1. The method now returns a Recipients object, instead of a List<Recipient> object.

    1. The Recipients object further contains a List of Recipient that you can access with List<Recipient> recipients.getRecipients() method to iterate over.
    2. That object also contains a Meta object that you can access with Meta recipients.getMeta() method. It allows you to paginate over the results.
  2. The Recipient class now also has an overloaded search() method that returns a RecipientsIterator object, which allows auto-pagination.

    1. You can use it in a while() loop to go over all pages in a result set without manually paginating. Every single page contains 10 items, and as soon as you reach the end of the page it automatically fetches a new page as long as there is one.
    2. For more details, refer to the documentation or tests/RecipientTest.java.

2. Recipient.findLogs() method renamed

  1. The method Recipient.findLogs() has been renamed to Recipient.getAllLogs().
    1. It also now returns an object of Logs class, with a List<Log> and Meta object for manual pagination.
    2. There's also an overloaded getAllLogs() method that returns an iterator (LogsIterator) for auto-pagination.
    3. For more details, refer to the documentation or tests/RecipientTest.java.

4. Batch Gateway Changes

1. Method Batch.query() replaced by Batch.search()

The method Batch.query() and many different versions of it have been replaced by two variants of Batch.search() method.

  1. Much like the Recipient class's version, Batches Batch.search(int page, int pageSize, String searchTerm) method lets you manually paginate and provide a search keyword.

    1. The Batches object further contains a List of Batches that you can access with List<Batch> Batches.getBatches() method to iterate over.
    2. That object also contains a Meta object that you can access with Meta batches.getMeta() method. It allows you to paginate over the results.
  2. Another overloaded version of the same method - BatchesIterator Batch.search(String searchTerm) - lets you search within a batch and paginate automatically.

    1. You can use it in a while() loop to go over all pages in a result set without manually paginating. Every single page contains 10 items, and as soon as you reach the end of the page it automatically fetches a new page as long as there is one.
    2. For more details, refer to the documentation or tests/RecipientTest.java.

2. Method Batch.create(String body) removed

As mentioned above, to conform with Java ways of accessing methods, the Batch.create(String body) method has been removed.

Please use Batch.create(Batch requestBody) instead, and refer test/BatchTest.java for an example.

3. Method Batch.update(String, String) replaced

As mentioned above, to conform with Java ways of accessing methods, the Batch.update(String batchId, String body) method has been replaced by Batch.update(String batchId, Batch updatedBatch).

Please look at the documentation or test/BatchTest.java for an example.

5. Payment Gateway Changes

1. Method Payment.query() replaced by Payment.search()

The method Payment.query() and many different versions of it have been replaced by two variants of Payment.search() method.

  1. Much like the Recipient class's version, Payments Payment.search(String batchId, int page, int pageSize, String searchTerm) method lets you manually paginate and provide a search keyword.

    1. The Payments object further contains a List of Payments that you can access with List<Payment> Payments.getPayments() method to iterate over.
    2. That object also contains a Meta object that you can access with Meta batches.getMeta() method. It allows you to paginate over the results.
  2. Another overloaded version of the same method - PaymentsIterator Payment.search(String, batchId, String searchTerm) - lets you search within a batch and paginate automatically.

    1. You can use it in a while() loop to go over all pages in a result set without manually paginating.
      Every single page contains 10 items, and as soon as you reach the end of the page it automatically fetches a new page as long as there is one.
    2. For more details, refer to the documentation or tests/BatchTest.java.

6. Balance Gateway Changes

1. Method Balances.find() replaced

The method Balance.find() has essentially been made private, and in it's place you now have individual methods to fetch Balances of your different accounts:

  1. List<Balances> Balances.getAllBalances() - Gets balances of all your accounts.
  2. List<Balances> Balances.getTrolleyAccountBalances() - Gets all balances of your Trolley account.
  3. List<Balances> Balances.getPaypalAccountBalances() - Gets all balances of your Paypal account.

Update to existing Methods

1. Support for Errors as Arrays

The API returns errors in a JSON array. To support this, we have added a way for you to access the errors as an Array as well.
This should make it easier for you to iterate through the array and process the errors.

The array can be accessed through the getErrorResponse() method available through all the Exceptions that Trolley SDK exposes.

Example: Consuming error Array

...
catch(MalformedException e){
      for (JsonNode node : e.getErrorResponse().get("errors")) {
          System.out.println("Error Message: "+node.get("message"));
      }
  }
...

2. Supply your own HtptClient object

While setting up the SDK, you can specify your own HttpClient object for the SDK to use.

This will be useful in cases where you have your own proxy and server setup, that you want to use through your own HttpClient object.

Configuration config = new Configuration("<YOUR_ACCESS_KEY>","<YOUR_SECRET_KEY>", customHttpClient);

Gateway client = new Gateway(config);

3. No need to specify environment now

The SDK now defaults to the production URL i.e. api.trolley.com.
Even while setting up a proxy you no longer need to provide an environment.

If you're running from the source and need to specify a server url, you now have to create a .env file in the project root and specify the BASE_URL there. Then, specify the environment as development for the SDK to start picking up the API url from .env file.

Old way

...
	Gateway client = new Gateway(new Configuration("<ACCESS_KEY>","<SECRET_KEY>","production"));
...

New way

...
	Gateway client = new Gateway(new Configuration("<ACCESS_KEY>","<SECRET_KEY>"));
...

New Methods/API Coverage

We have added support for more API endpoints that our Java SDK wasn't supporting earlier.

Here's a rundown of the new API endpoints covered:

Recipient

1. Get All Offline Payments

You can now fetch all offline payments belonging to a recipient.

You can choose to manually paginate through the results, or use the overloaded method which returns an iterator to auto-paginate through all the pages in the result set.

Gateway client = new Gateway(config);

String recipientId = getRecipientId();

//Manual pagination
OfflinePayments op = client.recipient.getAllOfflinePayments(recipientId, page, pageSize, "");

List<OfflinePayment> offlinePayments = op.getOfflinePayments();

for (OfflinePayment offlinePayment : offlinePayments) {
    System.out.println(offlinePayment.getId());
}
 
Meta meta = op.getMeta();

//Or, with auto-pagination
OfflinePaymentsIterator offlinePayments = client.recipient.getAllOfflinePayments(recipientId, "");

int itemCount = 0;
while(offlinePayments.hasNext()) {
    System.out.println(offlinePayments.next().getId());
}

2. Delete Multiple Recipients

A new overloaded method now lets you specify a list of Recipients to delete, instead of deleting just one.

Gateway client = new Gateway(config);

List<Recipient> recipients = getRecipientsToDelete();

boolean deleteResult = client.recipient.delete(recipients);

System.out.println(deleteResult);

Batch

1. Delete Multiple Batches

A new overloaded method now lets you specify a list of Batches to delete, instead of deleting just one.

Gateway client = new Gateway(config);

List<Batch> batches = getRecipientsToDelete();

boolean delResult = client.batch.delete(batches);

Invoices (covered since v1.1.0)

  • BREAKING: Invoice.Search() now returns an iterator, instead of only first 10 results

1. Create an Invoice

Gateway client = new Gateway(config);

Invoice invoice = new Invoice();
invoice.setRecipientId(recipient.getId());
invoice.setInvoiceNumber("invoice-123");

invoice = client.invoice.create(invoice);

2. Update an Invoice

Gateway client = new Gateway(config);

Invoice invoiceUpdateRequest = new Invoice();
invoiceUpdateRequest.setInvoiceNumber("invoice-321");

Invoice updatedInvoice = client.invoice.update(invoice.getId(), invoiceUpdateRequest);

3. Fetch an Invoice

Gateway client = new Gateway(config);
String invoiceId = getInvoiceId();
Invoice invoice = client.invoice.fetch(invoiceId);

4. Search for an Invoice

Gateway client = new Gateway(config);
List<String> recipientIds = getRecipientIDsToSearch()

// Search for Invoices by recipientId with pagination
int page = 1;
int pageSize = 10;
Invoices invoices = client.invoice.search(Invoice.SearchBy.RECIPIENT_ID, recipientIds, "<search_term>", page, pageSize);
List<Invoice> invoiceList = invoices.getInvoices();

for (Invoice i : invoiceList) {
    System.out.println(i.getRecipientId());
}
 
Meta meta = op.getMeta();

//Or, with auto-pagination
InvoicesIterator invoices = client.invoice.search(Invoice.SearchBy.RECIPIENT_ID, recipientIds, "<search_term>");

while(invoices.hasNext()) {
    System.out.println(invoices.next().getRecipientId());
}

5. Delete an Invoice

Gateway client = new Gateway(config);

String invoiceId = getInvoiceId();

//Delete a single invoice
boolean invoiceDelResult = client.invoice.delete(invoiceId);


// Or, delete multiple invoices
List<String> invoiceIds = getInvoiceIds();
boolean invoiceDelResult = client.invoice.delete(invoiceIds);

InvoiceLines (covered since v1.1.0)

1. Create an InvoiceLine

Gateway client = new Gateway(config);

String invoiceId = getInvoiceid();

InvoiceLine invoiceLine = new InvoiceLine();
invoiceLine.setUnitAmount(new Amount("100", "USD"));

//Create individual invoice line
Invoice invoice = client.invoiceLine.create(invoiceId, invoiceLine);

//Or, create multiple invoice lines at once
List<InvoiceLine> invoiceLines = getInvoiceLinesToCreate();
Invoice invoice = client.invoiceLine.create(invoiceId, invoiceLines);

//Or, create an invoice line with a Create Invoice request
Invoice invoice = new Invoice();
invoice.setLines(invoiceLines)

invoice = client.invoice.create(invoice);

2. Update an InvoiceLine

Gateway client = new Gateway(config);

String invoiceId = getInvoiceId();

//Update a single invoice line
InvoiceLine invoiceLine = getInvoiceLineToUpdate();
Invoice invoice = client.invoiceLine.update(invoiceId, invoiceLine);

//Or, update multiple invoice lines
List<InvoiceLine> invoiceLines = getInvoiceLinesToUpdate();
Invoice invoice = client.invoiceLine.update(invoiceId, invoiceLines);

3. Delete an InvoiceLine

Gateway client = new Gateway(config);

String invoiceId = getInvoiceId();
String invoiceLineId = getInvoiceLineId();

//Delete an invoice line
boolean deleteResult = client.invoiceLine.delete(invoiceId, invoiceLineId);

// Or, delete multiple invoices lines
List<String> invoiceLineIds = getInvoiceLineIds();
boolean deleteResult = client.invoiceLine.delete(invoiceId, invoiceLineIds);

InvoicePayments (covered since v1.1.0)

BREAKING: InvoicePayment.search() now returns an iterator. it also has an overloaded version accepting page arguments

1. Create an Invoice Payment

Gateway client = new Gateway(config);

String invoiceId = getInvoiceId();
String invoiceLineId = getInvoiceLineId();

InvoicePaymentPart paymentPart = new InvoicePaymentPart();
paymentPart.setInvoiceId(invoiceId);
paymentPart.setInvoiceLineId(invoiceLineId);
paymentPart.setAmount(new Amount("50", "USD"));

// Create a single payment in a new batch
InvoicePayment invoicePayment = client.invoicePayment.create(null, paymentPart);

//Or, create a single payment in an existing batch
String batchId = getBatchId();
InvoicePayment invoicePayment = client.invoicePayment.create(batchId, paymentPart);

//Or similarly, create multiple payments in an existing batch
List<InvoicePaymentPart> invoicePaymentParts = getInvoicePaymentParts();
InvoicePayment invoicePayment = client.invoicePayment.create(batchId, invoicePaymentParts);

2. Update an Invoice Payment

Gateway client = new Gateway(config);

String invoiceId = getInvoiceId();
String invoicePaymentId = getInvoicePaymentId();
String invoiceLineId = getInvoiceLineId();

InvoicePaymentPart paymentPart = new InvoicePaymentPart();
paymentPart.setPaymentId(invoicePaymentId);
paymentPart.setInvoiceId(invoiceId);
paymentPart.setInvoiceLineId(invoiceLineId);
paymentPart.setAmount(new Amount("10","USD"));

boolean paymentUpdateResult = client.invoicePayment.update(paymentPart);

3. Search for an Invoice Payment

Gateway client = new Gateway(config);

List<String> invoiceIds = getInvoiceIds();
List<String> paymentIds = getInvoicePaymentIds();
int page = 1;
int pageSize = 10;

//Search for invoicePayments with paymentIds with manual pagination
InvoicePayments invoicePayments = client.invoicePayment.search(paymentIds, null, page, pageSize);
for(InvoicePayment p : invoicePayments){
    System.out.println(p.getInvoiceId());
}

//Or, with with invoiceIds and auto-pagination
InvoicePaymentsIterator invoicePayments = client.invoicePayment.search(null, invoiceIds);

while (invoicePayments.hasNext()) {
    System.out.println(invoicePayments.next().getInvoiceId());
}

4. Delete an Invoice Payment

Gateway client = new Gateway(config);

String invoicePaymentId = getInvoicePaymentId();
String invoiceLineId = getInvoiceLineId();

// Remove connection of one invoice line with a payment
boolean deleteResult = client.invoicePayment.delete(invoicePaymentId, invoiceLineId);

// Remove connection of multiple invoice lines with a payment
List<String> invoiceLineIds = getInvoiceLineIds();
boolean deleteResults = client.invoice.delete(invoicePaymentId, invoiceLineIds);

Balances

1. Get All Accounts' Balances

Gateway client = new Gateway(config);

List<Balances> balances = client.balances.getAllBalances();

for (Balances balance : balances) {
    System.out.println(balance.getAmount());
}

2. Get Trolley Account's Balances

Gateway client = new Gateway(config);

List<Balances> balances = client.balances.getTrolleyAccountBalances();

for (Balances balance : balances) {
    System.out.println(balance.getAmount());
}

3. Get PayPal Account's Balances

Gateway client = new Gateway(config);

List<Balances> balances = client.balances.getPaypalAccountBalances();

for (Balances balance : balances) {
    System.out.println(balance.getAmount());
}

Offline Payment

1. Create an Offline Payment

Gateway client = new Gateway(config);

String recipientId = getRecipientId();

OfflinePayment opRequest = new OfflinePayment();
opRequest.setCurrency("CAD");
opRequest.setAmount("10.00");

OfflinePayment op = client.offlinePayment.create(recipientId,opRequest);

2. Update an Offline Payment

Gateway client = new Gateway(config);

String recipientId = getRecipientId();
String offlinePaymentId = getOfflinePaymentId();

OfflinePayment opRequest = new OfflinePayment();
opRequest.setAmount("20.00");

boolean updateResult = client.offlinePayment.update(recipientId, offlinePaymentId, opRequest);

3. List All Offline Payment

Gateway client = new Gateway(config);

int page = 1;
int pageSize = 10;

// Get all offline payments with a search term and manual pagination
List<OfflinePayments> offlinePayments = client.offlinePayment.listAllOfflinePayments(page, pageSize, "<search_term>");
for (OfflinePayment offlinePayment : offlinePayments){
	System.out.println(offlinePayment.getId());
}

// Or, with auto-pagination
OfflinePaymentsIterator offlinePayments = client.offlinePayment.listAllOfflinePayments("<search_term>");
while(offlinePayments.hasNext()){
    System.out.println(offlinePayments.next().getId());
}

// Or, with no search term and auto-pagination
OfflinePaymentsIterator offlinePayments = client.offlinePayment.listAllOfflinePayments();
while(offlinePayments.hasNext()){
    System.out.println(offlinePayments.next().getId());
}

4. Delete an Offline Payment

Gateway client = new Gateway(config);

String recipientId = getRecipientId();
String offlinePaymentId = getOfflinePaymentId();

boolean opDelResult = client.offlinePayment.delete(recipientId, offlinePaymentId);

Housekeeping updates

Apart from covering new APIs, we also updated the dependencies to improve the functionality and security of the SDK:

  1. org.apache.httpcomponents.httpclient : 4.5.3 -> 4.5.13
  2. com.fasterxml.jackson.core.jackson-databind : 2.9.10.1 -> 2.12.7.1
  3. com.fasterxml.jackson.core.jackson-annotations: LATEST -> 2.15.2
  4. com.fasterxml.jackson.core.jackson-core : LATEST -> 2.15.2
  5. org.hamcrest.hamcrest-core : Removed
  6. junit : 4.13.1 -> 4.13.2

We hope these new updates help you build Trolley integration faster and more reliably.
If you have any questions or find any bugs, please open an issue or reach out to us at developers@trolley.com
Collaborations and PRs are welcome.