How not to API: Telebirr

?

TL;DR

The Telebirr API implementation is severely flawed, please fix. Developers facing issues, go ahead and read. If you face any of the issues I did, DM me and I can share some source code.

____

?(Telebirr api for web)

Building/designing APIs certainly requires insight into how they might be used by other developers. We cannot possibly test against all possible scenarios in which an API can be used, which would be ideal. That is why we should instead strive for simple, plain, and quick to comprehend implementations. I hope I don't offend anyone here, but to put it bluntly Telebirr's api is anything but simple, plain or quick to comprehend. In fact, it goes against most standard principles of API implementation.

I write this short article with three aims: to describe my experience working with the API, to help guide other developers that might run into the same set of issues and to appeal to any managers at Ethiotelecom to correct course.

It all started when I was tasked with integrating Telebirr into one of the web applications I built. I was put in contact with an Ethiotelecom employee (let's call her L, like in the anime) whose main job was to help me implement this payment method. She sent me the APPID , APIKEY, short-code, public key and VPN credentials all in an excel via email and a telegram group. I asked for the API documentation and one was provided in a word document.

I'll try avoiding all the frustrating issues with L's support after all it wasn't her fault, no one understood this api, instead I'll focus on the technical aspects of the implementation.

The first issue I encountered was understanding the documentation, a poorly written Huawei document (probably app translated) that described an intricate request->verification->response sequence. (Image below shows the? sequence, sorry for the poor quality, this was what was given to me)

No alt text provided for this image

It took me some time but with the help of L I was able to understand that the application had 3 layers of encryption: the VPN used to connect to the telebirr api servers, the payload that was asymmetrically encrypted and SSL/TLS. "Impressive security" I thought at the time.

I could start attempting the implementation. Contacting the api gateway was not a task for the faint of heart, making the fortigate soft-vpn work was a headache and neither me nor L could make it work. A couple of escalations later it was agreed that we would ditch the VPN. I don't understand why it was needed in the first place, for a public API of all things (then L explained that it was strictly for testing purposes and that we wouldn't need a VPN for production).

Next we started the actual integration, I was given a test endpoint and off we went.?

The first step was sending a trade-request, basically a json in the request body containing 6 parameters in a very specific order or else it wouldn't work (I didn't think the order in which the parameters were placed in a JSON object would matter).

Then the api required I encrypt the json generated above using RSA2048 with the public key provided. That's pretty straightforward but wait! RSA2048 only allows encrypting data that is no larger than 200 bytes (since the key is 2048 bits) and the JSON the api requires is definitely bigger. L didn't know anything about this issue, or how to solve it. By the way, her response to every inquiry I had was basically "it worked for other developers" we'll get back to that joke later.

After another round of escalation to a senior engineer at tele, it was recommended that I use a non-optimal definitely not best practice solution which involved "????? ????? ?????? ?????" nowhere in the document was this mentioned. So I decoded the data into bytes, divided the data into chunks of 200 bytes, encrypted each chunk, reassembled it encoded it to utf-8 and sent it. I was grumpy at this point, the frustration had set in, but job had to be done and no matter how poor this implementation was we needed to deliver. I kept my opinions to myself and implemented their solution. (I use python for all of my projects)

After I successfully implemented their weird encryption step I made a first request to the api and got a response. It had a few parameters but the main bit I needed was encrypted. That was expected I guess, if I encrypted mine they should do the same. So I kindly asked L for a private key for decrypting the response I had received. She said it was sent with all of the other parameters in the same email and in the telegram group. The API KEY was too short to be an RSA2048 key, and also it's an API key. I looked everywhere and nothing. L insisted that she sent me the key and I insisted that she hadn't. This went on for a couple of days and a third escalation ensued. The senior engineer joined the zoom call and with a straight face he said "use the public key to decrypt, the public key is also the private key". This must be a bad Spanish telenovela where they announce that the killer was the "abuela that pretended to be in a coma for 24 years". I had two questions for the engineer:

1. Why use an ASYmmetric cypher and force it to be SYMmetric? Why make these beautifully thought through algorithms have identity issues? Why not use a symmetric cypher? We could've avoided the 200bytes dilemma and symmetric ciphers are relatively more time-efficient when compared to asymmetric ciphers.

2. Why did we need yet another layer of encryption on top of SSL/TLS? (It's rare but sometimes we add another layer of encryption if we don't trust intermediary services like firewalls, load balancers etc. But this is TELE's app using TELE's services. Trusting themselves shouldn't be an issue, or should it? And if trust is an issue then using the public key for both encryption and decryption gives a false sense of security. It is in the name, the key IS PUBLIC, it was shared in emails and telegram groups. Where is the security?)

Unfortunately, or fortunately, python is opinionated and it wouldn't let me use the same key with RSA. At this point there were only two options: to attempt a low level implementation of RSA without the safety check in python or compile my own version of python from source. Both of which I wasn't about to do, I didn’t have the skills to do so and acquiring the necessary knowledge requires time I didn’t have. So I put everything on pause and continued with my other projects. But I was curious about how "it worked for other developers" so I asked L for some of their contacts. Funny enough, they had used JAVA, and it let them have their way with RSA. The api itself was implemented in native java. Figures. I wasn't willing to change my entire toolchain and re-learn Java just to humor a badly implemented payment api.

I was annoyed to have wasted my time with the badly written, incomplete documentation (I repeat, a word document) and the untrained first line support who was oblivious to every question and answered in one of two ways "It worked for other developers" and the classic "it's in the documentation".

Last week, a year or so after the events I described, a colleague told me someone he knows implemented a solution for Python. We set up a meeting online and he described a way to achieve this by installing nodejs locally and exposing an api for a? microservice that does all the sketchy encryption stuff. It's a great way to make it work, but is it the right way? Making it work no matter what shouldn’t be standard practice, we enforce bad habits in those giving us essential tools to improve our applications. This wasn't my first time integrating a payment gateway, had a stint with Yenepay, Safaricom's MPESA and one Kenyan bank's custom payment gateway all of which took less than a week each to go live. I don't understand why Ethiotelecom can't replicate widely accepted international standards. I can only describe Telebirr as their attempt to reinvent the proverbial wheel, and they came up with a rectangular one. That’s about it folks, hope my questionable English wasn’t a drag.?

Mike Shiferaw

Software Development Advisor

3 个月

Great article Yafet. So, have you finally implemented the solution? If you did, then it'll be nice if you can share it as a library or just a source code on GitHub

回复
Natnael Biruk

Backend Developer | DevOps | Software Engineer

9 个月

A year later, and the problem's persist. Had to go through a similar frustrating process. But gotta say, the article was really well written!

回复
Amanuel Gulelat

Mobile Application Developer Flutter | Django | ReactJs | UI&UX | Graphics Designer

1 年

hi Yafet how are you my name is Amanuel i am a flutter developer so i thought to integrate my app with tele birr(built in flutter) so can i integrate with tele birr?,,, if its yes pls tell me the steps what going i do.

回复
Bruktawit (Brukty) Tigabu

Educational TV shows creator, Children's books writer, Educator, Filmmaker, Innovative Social Entrepreneur

1 年

Any update on this?

回复
BINIYAM ABERA

Co-Founder and Chief Technology Officer at IBEX Technologies and Promotion PLC.

1 年

Yo, great article thanks for sharing this <3<3<3. I Appreciate it!

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了