v2.0.0
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
-
The method now returns a
Recipientsobject, instead of aList<Recipient>object.- The
Recipientsobject further contains a List of Recipient that you can access withList<Recipient> recipients.getRecipients()method to iterate over. - That object also contains a
Metaobject that you can access withMeta recipients.getMeta()method. It allows you to paginate over the results.
- The
-
The Recipient class now also has an overloaded
search()method that returns aRecipientsIteratorobject, which allows auto-pagination.- 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. - For more details, refer to the documentation or
tests/RecipientTest.java.
- You can use it in a
2. Recipient.findLogs() method renamed
- The method
Recipient.findLogs()has been renamed toRecipient.getAllLogs().- It also now returns an object of
Logsclass, with aList<Log>andMetaobject for manual pagination. - There's also an overloaded
getAllLogs()method that returns an iterator (LogsIterator) for auto-pagination. - For more details, refer to the documentation or
tests/RecipientTest.java.
- It also now returns an object of
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.
-
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.- The
Batchesobject further contains a List of Batches that you can access withList<Batch> Batches.getBatches()method to iterate over. - That object also contains a
Metaobject that you can access withMeta batches.getMeta()method. It allows you to paginate over the results.
- The
-
Another overloaded version of the same method -
BatchesIterator Batch.search(String searchTerm)- lets you search within a batch and paginate automatically.- 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. - For more details, refer to the documentation or
tests/RecipientTest.java.
- You can use it in a
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.
-
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.- The
Paymentsobject further contains a List of Payments that you can access withList<Payment> Payments.getPayments()method to iterate over. - That object also contains a
Metaobject that you can access withMeta batches.getMeta()method. It allows you to paginate over the results.
- The
-
Another overloaded version of the same method -
PaymentsIterator Payment.search(String, batchId, String searchTerm)- lets you search within a batch and paginate automatically.- 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. - For more details, refer to the documentation or
tests/BatchTest.java.
- You can use it in a
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:
List<Balances> Balances.getAllBalances()- Gets balances of all your accounts.List<Balances> Balances.getTrolleyAccountBalances()- Gets all balances of your Trolley account.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:
org.apache.httpcomponents.httpclient:4.5.3->4.5.13com.fasterxml.jackson.core.jackson-databind:2.9.10.1->2.12.7.1com.fasterxml.jackson.core.jackson-annotations:LATEST->2.15.2com.fasterxml.jackson.core.jackson-core:LATEST->2.15.2org.hamcrest.hamcrest-core: Removedjunit: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.