Overview of manipulating data in Ballerina with different APIs (PayPal API and randomuser.me)
By: Dulaj Dilshan
Tags: PayPal, Swan Lake, Ballerinalang, Json, API

Overview of manipulating data in Ballerina with different APIs (PayPal API and randomuser.me) Dulaj Dilshan Follow Sep 7 · 6 min read

With this article, I’m going to show you how to use Ballerina to convert the data we have to send as requests to an API and convert data that are retrieved as a result of an API call. To demonstrate this, I’m writing an implementation of HTTP Client for PayPal developer APIs. I’m using Ballerina Swan Lake Beta2 throughout this article. The following are the other APIs I’m using for this.

RandomUser.me API : Generate random user PayPal developer API: Invoice, Payment and Auth APIs

First, let’s have a look at what kind of data we can retrieve from the RandomUser.me can generate with their API

Sample of data generated with randomuser.me

Now we need a function to retrieve the data and some data structures to keep manage the data.

Ballerina HTTP client provides good supports for this. Here I’m creating an HTTP Client object with the randomuser.me base URL. Since we need data of person from the US, we call the get method with a configuration passing through the API as a query param.

https://randomuser.me/api?api?nat=us

We get the JSON response by defining the expected type of the get() as json (Single Line Payload). Here the client’s get() method is able to infer the expected payload type. Here we return the value of the results field of the resp (JSON payload).

We need to prepare some data structures in order to use convert and use them with the PayPal API.

Now let’s write the utility function to convert the data retrieved from the randomuser.me to a Person record object. You can learn more about “from json to other types conversion” with this article: JSON to record conversion

Note: ensureType() is used as a trick to cast a value to a type in the same way as a type cast expression, but returns an error if the cast cannot be done, rather than panicking.

As you can see, Since PayPal API only supports the plain only-numeric format of the phone number (Ex: 4085551234), I have written another function: convertPhoneNumber to convert the phone number into the only-numeric format.

Now everything is in good shape for the implementation of the client for the PayPal API.

(>‿◠)✌

Before moving to coding, we need to set up few things. First, you need to create a developer PayPal account (sandbox account) and create an App in your dashboard (please refer to these steps).

After you have done creating your sandbox account, go to the Default Application. You will be able to see your Client ID and Client Secret on the page.

Client ID and Secret

Now, let’s use ClientID and Secret to generate an access token to use with our client endpoint.

Generating an access token for our endpoint

We are going to use this access token to authorize our API calls to the PayPal REST API server. We need to send an API call to retrieve this access token. This is the cURL command which PayPal has been supplied to us.

Let’s write a ballerina function to retrieve the new access token. Here we are creating a new client with the given URL and the client_id , and client_secret . We use basic authentication and x-www-form-urlencoded as the data format.

First, we define AuthResp as our data structure that our post() returns. In the function, we create the client-endpoint using the params: base URL as url , client_id and client_secret .

You can get the access token by calling this function.

As you can see in the PayPal documentation, we need two kinds of authentication for the API

Basic Authentication (A username and password) to generate an access token Bearer Token for the other APIs

Therefore, we need to maintain a configuration file within our source files to store these keys and values. For this, we use Ballerina’s configuration management feature. We create a Config.bal to maintain the configurations as environment variables.

Let’s create a ballerina project and add Config.bal file to it.

bal new paypal_ballerina

Following is the file structure of the project. I have used generate_token.bal to keep the code for the access-token generation function and user.bal to keep relevant data structures related the Person and the random user generation function

└── paypal_ballerina

├── generate_token.bal

├── Ballerina.toml

├── Config.toml

├── Dependencies.toml

├── user.bal

└── main.bal

Let’s define configurable variables in the main.bal to catch the environmental values in the Config.toml file.

We are now good to go with writing the implementation for the PayPal API client.

Setting the main.bal

Since now we communicate with the API using the bearer token, we need to set up the HTTP client object in the main.bal file. Here we use the access token we got from the Config.toml .

Now let’s try out the implementations for different PayPal APIs.

Invoice API

First, we need to get the next-invoice-id, before creating a draft invoice. So, we need to write a function to call /v2/invoicing/generate-next-invoice-number and get the value. Since we use the same client, here, we define the client as a parameter.

We use the number returning from this function to create draft invoices.

Creating a draft invoice

We have already prepared few data structures to denote Person . We need some more data structures that we will be used for invoicing. Please have a look at the following source code. Here, we are creating a sample draft invoice. We write these data structures to match with the structure of the json provided by the API documentation.

As you can see in the above code, in createSampleDraftInvoice() function, we

Create two items with the unit amounts

Generate a random US person

Create the invoice details with the next invoice ID

I create invoiceDetails using expression-embodied functions since it's easy to map values to a record type.

After creating the invoice, we directly call the post() method. with the URL and the invoice . In the terminal, if you get an output like the following the response doesn't have any errors.

{"rel":"self","href":"https://api.sandbox.paypal.com/v2/invoicing/invoices/INV2-GCP3-LXR4-EU7A-WXLQ","method":"GET"}

Here INV2-GCP3-LXR4-EU7A-WXLQ is the ID of the invoice we have just created. Now let’s write other functions: get-all invoices, get an invoice by the ID and delete an invoice.

Furthermore, with /v2/invoicing/invoices/{invoice_id}/send POST request, you can write functions to send the invoice to the relevant party.

Order API

Now let’s write the functions for the Order API. Here we will be manipulating the data that came as a result of the APIs.

Create and Authorize Orders

Here we add another function createOrder() to create orders through the API. First, we define the data structures we need: Order , Amount , PurchaseUnit .

We define an enum in order to restrict the user to only put two values from ORDER_INTENT which represents the intent to either capture payment immediately or authorize payment for an order after order creation.

The following is an implementation we can write for the create-order function.

If we create an order using this function 👇

Code for creating a sample order

we get this output 👇

Result of creating sample order

We can extract order_id and the URL to approve the order from the returning json with a line of code. You can see [Ballerina] Working with JSON blog for more information for converting json values into other types.

The payer who is willing to pay can go to the approve-URL and authorize the payment.

Payment API

Likewise, we did in earlier APIs, we can write function for Payment API as well.

You can follow these steps which are demonstrated with cURL to write the implementation for Ballerina to authorize and execute payments.

Github code: https://github.com/dulajdilshan/ballerina-paypal-client-impl

More about JSON in ballerina: https://ballerina.io/learn/by-example/json-type

This is it. Ballerina has many features that we can use easily with network interactions and manipulating data. Happy coding with Ballerina.!