Overview of manipulating data in Ballerina with different APIs (PayPal API and randomuser.me)
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
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.
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 asurl
, 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 theConfig.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 👇
we get this output 👇
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.!