Hi, this topic is meant as a place for me to post updated on my progress on the Taler-Odoo Payment System add-on for the Odoo ERP.
The code can be found at https://codeberg.org/Nemael/tops/
This will be a moving document, mainly to keep my ideas in order that I will update with a new post when there is progress in the project. The Codeberg repository will also contain text files of each post.
Please don’t hesitate to reach out if anything I write piques your interest! ![]()
On the 5th of July 2025:
The first step for my project was to build a dummy Odoo add-on, that I could deploy and install on an Odoo instance.
I am working on a virtual machine setup, and my first few days were spent setting up a virtual machine running Linux, on VirtualBox, with a shared drive to my host OS
My goal was to have Odoo running on a Virtual Machine that I could bring up and tear down easily, and having my add-on code on the shared drive, so that I could use my IDE and code from my host OS.
After a few hours of trial-and-error, I managed to make it work, and after installing Odoo, I use the command ./odoo-bin --addons-path=./addons,/media/sf_VMSharedFolders/custom_addons -u tops -d odoo18_tops_0.1.1.1 to start Odoo
From this, I started building the dummy add-on.
On the 8th of July 2025:
For the dummy add-on, I started building a very simple “store some strings and have persistent data”.
Every tutorial on the internet is using a table of Students as a starting point, so I did as well.
Odoo works with a system of models, controllers and views. At the moment, I am only using models and views, to store and create new data, and to visualize it. My model represent a student with a few personal information fields (which will become Taler merchant information in the future)
I also have a view that displays this data and allows me to edit it.
I started the branch https://codeberg.org/Nemael/tops/src/branch/milestone_0.1 to upload the changes I make to the add-on
On the 13th of July 2025:
Next step for me is to start making a collection of the requests that I will have to use for communication to Taler.
For this I followed the great tutorial videos on 3.1. Merchant backend API — GNU Taler
After watching it all, and getting a good understanding of the structure, I installed Insomnia and reproduced the steps to make the collection of requests needed
After a few attempts, I realised the videos were outdated.
First, the test endpoint changed between the videos and the current setup. The videos are showing an endpoint as such https://backend.demo.taler.net/private/orders, but the actual endpoint I had to use was https://backend.demo.taler.net/instances/sandbox/private/orders.
After this, I had issues with the authentication. The videos are talking only about an authentication system that simply uses Bearing secret-tokens that contains the password (sandbox in this case), but in reality, to make any requests to the /private endpoints, I had to obtain a token, that I could get by first sending a request to https://backend.demo.taler.net/instances/sandbox/private/token. For this request, I had to also send a payload according to the documentation, which included a request for a scope for the tokens. For reason that I do not understand yet, out of the 7 scopes available according to the documentation 1.4. Merchant Backend RESTful API — GNU Taler, only the scopes “readonly” and “write” worked for me.
After fiddling some time with Insomnia and get a better understanding of the tool, I obtained the token. I spent a long time trying to reach the endpoint https://backend.demo.taler.net/instances/sandbox/private/orders, which I did not manage to make work. I was suspecting at first that my token was bad, but after spending quite some time wrestling with the different parameters available, and with different connection methods, I tried, on a whim, to use the endpoint https://backend.demo.taler.net/instances/sandbox/private/orders/$ORDERID (I used ORDERID = 2025.191-02D3GX2J9ME3M as an example), and it worked right away!
I was super excited to have working token and endpoints, and quite frustrated that the general /private/orders endpoint was not working for me. I will explore later why I could not get a response from it.
Next step for me is to continue to implement the different request
On the 14th of July 2025:
Today, I did not investigate the failing endpoint /private/orders further.
I read and listened through more documentation, and got the query to place a barebone order, as well as implemented previous queries in the Odoo add-on code.
I updated the Odoo models to include way more data, that I can edit from Odoo to place an order.
In the Odoo add-on, I added a lot of fields pertaining to the order data, and the ability to place an order (although, I have not implemented a management of orders yet), and I pushed this all in the repository.
I placed many orders from Odoo, but didn’t manage to pay for any of them from my Taler wallet. I keep getting an error saying Balance is not enough because merchant will just accept 399 KUDOS. To know more you can check which exchange and auditors the merchant trust. I currently have 399 KUDOS in my wallet, which I guess is where the number in the error comes from.
This is not a wallet version issue, because the Taler sandbox endpoint is in version 18:0:15 (compatible up to 3.0), and my wallet is in version 5.0.1 (although I should update my wallet firefox add-on I guess)
I also made a better logging system with colors to display the Taler-specific logs
Next objective is to actually complete an order that was placed from Odoo.
On the 15th of July 2025:
I investigated further on why I couldn’t pay for an order I created using my Taler Wallet
First, on the Taler Wallet Firefox add-on (that I re-installed from scratch for a better start), I get an error saying “Balance is not enough because merchant will just accept 150 KUDOS. To know more you can check which exchange and auditors the merchant trust.” (150 KUDOS is the amount I have in my wallet). I can hardly understand the error, I don’t know what “just accept” means in this context, or which auditors and merchant I should check for validity
I then tried with the Taler Wallet Android app, and I receive the error “Balance insufficient! Maximum is 0.00 KUDOS. Merchant doesn’t accept money from one or more providers in this wallet.” I have a balance of 50 KUDOS on this wallet.
The app’s error message does give me clearer information, but I still don’t understand why I wasn’t able to complete an order.
This is super frustrating because I would like to continue implement queries, and progress further, but this is blocking me.
I found this email exchange that seems related. This is talking about the wire fees not being setup correctly, but I didn’t understand yet if this is something that I can fix on my end. https://lists.gnu.org/archive/html/taler/2024-09/msg00007.html
Even when I create the order directly on https://backend.demo.taler.net/instances/sandbox/webui/#/orders, using the big blue “+” button, I receive the same errors when paying using either wallets.
For this issue and the one I was talking about in a previous post, I filled two bug reports, https://bugs.gnunet.org/view.php?id=10184 and https://bugs.gnunet.org/view.php?id=10185. One for the wallet payment not going through issue, and one for the /private/orders endpoint giving a bad response.
I also reached out to Christian Grothoff to let him know and ask for help, and will share his wisdom when I will get an answer ![]()
On the 16th of July 2025:
Not much time available to progress today. I didn’t get a straight response from Christian, but the tickets that I opened were assigned and fixed! I now can pay for an order using the Taler wallet, and I can display a list of orders using this URL https://backend.demo.taler.net/instances/sandbox/private/orders to send a request to (it’s fun to see my own test orders in the list
)
I cleaned up the code and made the requests work from within Odoo.
Tomorrow’s goal, going further in the video tutorial and implement more complex features.
On the 17th of July 2025:
Now that the Taler requests are working fine, I started working on a more permanent Odoo integration.
The first step for this is to make an actual settings page where a user can set a company-wide Taler url and password (later, I will look into how to securely ask a user’s password and store it)
Now that I think about it, I don’t think I should store the password, maybe storing only a hash of it is good for Taler (have to look into Taler’s documentation about their expected password), or maybe I should only store the requested token, and give it a long validity time? I will look into best practices. But if anyone is reading that, and would like to share advice on this “password managements stored in user settings” situation, please let me know ![]()
On the 20th of July 2025:
My next goal was to implement a “settings” page in Odoo, where I could set data, such as the endpoint you want to use for Taler (and maybe add a button to test the endpoint when adding it?)
This was (such as it is with everything) more complex than expected. It required to play with the Odoo view and understand more in-depth the inheritance process that Odoo uses to implement new functionalities in existing views.
I currently have a settings page that display some settings that you can change, but they don’t affect the code of the rest of the add-on for now, this will be next step!
Thank you for sharing your progress, this is very valuable, and not often done. I really appreciate your dedication to documenting your way on the path to developing a final product.
I have a question regarding the license, because I’ve seen that specific case before elsewhere and the final result was not free software: none of the four freedoms were granted, although the base was free software licensed under the GPL-2.0 and the module was LGPL-2.1. So my question is: why did you choose the LGPL-3.0 instead of some stronger copyleft license like the AGPL-3.0?
Thank you for bringing up this license thing,
So, this is the first time I work on a project where licenses actually matter to the work I do.
As such, I don’t have a full understanding of the differences in licenses.
Odoo’s open-source modules are made under the LGPL3 license. Their recommendation when making an add-on for the Odoo App Store (which is a requirement in the MoU with Taler) is to use LGPL3 as well.
Another thing is, the code of the add-on needs to be compatible with some proprietary modules from Odoo, for full functionality as proposed in the MoU. It is my understanding that AGPL proscribe the compatibility with proprietary code, and as such I think I do have to use LGPL3.
I fully intend to have the final code be free software (The resulting work will stay available, as it is now, in an open repository on Codeberg, and will be open to modifications.) With this, I believe freedom 0, 1 and 2 will be respected, and I don’t see why freedom 4 wouldn’t be fulfilled as well (but I could definitely be wrong on this).
I am also open to change the license if there is further discussion on this topic, and if changing the license is at all possible ![]()
On the 23rd of July 2025:
Today’s update is more of a brainstorming piece for me about the structure of the code and the password storing piece.
I made my settings page fully work! It is a little wonky visually, but I can change my Taler merchant URL from a settings page, which can either be global to every company, or it could also be specific for each company within this Odoo installation (this last part is not yet implemented.)
After setting it up during the first-time setup of the add-on, the value can be retrieved to make a request to the Taler server
Next step for me is making a structure for my code. I will have to restart the structure from scratch, but it is great to do it now, when I know more what to expect. I will type here the structure of models and records I am thinking about.
Within Odoo, a record is one instance of a model, which can hold data in a persistent manner, and you can apply methods to the record. You can create as many records as you’d like for one model
I will have one model for orders, and each record will have:
- Order_id on the server
- Current status of the order
- plus a button “refresh status” which displays “refreshed” when the refresh is complete)
- Order Summary
- Order amount
- Order currency
- Order creation time
- Order payment time
- Order refund time
- Merchant server it has been created on (this + the order ID together will allow precise request for this exact order)
- Person who made the order?
- URI to the payment, to have it handy?
This model’s purpose is mainly to display all the Taler orders you made. When paying something with Taler on Odoo (on a website made with Odoo for example), a record will be added to track the order you created, where you can see its status, the data you set and maybe have quick access to the payment URI, if it makes sense.
Another model will be created for the current merchant information, with only one record of it. I will make this one a singleton maybe? It will have:
- The current secret-token for access to the orders page, and being able to send request and create order (maybe, depending on the best practices for password-keeping and such)
- Storing the password to the merchant URL? (same warning as previous entry)
- Amount of days for the refund window
- Default values for the OrderFulfillmentMessage (maybe this one can be in the settings instead)
Now that I think about it more, the model for the current merchant information seems pretty useless. The refund days and the order OrderFulfillmentMessage data can be set in the setting page instead of having a dedicated model. I feel like it is more intuitive to the user as well. There is only “keeping the current secret-token and the password” that might be relevant for this model, but even then, it looks very far from best practice to keep this secret token and password handy in an open area like this.
I looked into that security aspect more, and the main tip I could find was to encrypt the password before storing it somewhere in Odoo. But I don’t understand, the key to decrypt it will be in Odoo as well, so storing it encrypted right next to the key seems kinda ineffective? There is definitely something I don’t understand with this password-storing thing. I read something about using Environment Variables to store the encryption key, but it seems weird to me.
The process for this would be, as I understand it now:
- Store the encrypted password, encrypted with data that is stored in the env variables.
- Check if secret-token is still valid. If not, decrypt the password using the encryption key in the env variables,
- If the decryption fails, ask for the password again to the user.
- If the secret-token request fails, ask for the password again to the user.
And even then, using the secret-token and storing it in plain is just giving free access to the password that lasts for 12 hours. Much to think about…
As a side note, I also implemented a utils method “talog”, which will display logs in the same way Odoo does, but in a different color that I can choose. This will help me differentiate between the regular Odoo logs, and the Taler add-on logs which are more interesting to me
It would be interesting to see a collaboration here with @vlada who is the new designer for @TSYS, is that right @grothoff? A unified UI for various Taler integrations would probably go a long way helping with adoption. Of course not all cases are the same, but working on common guidelines would certainly be useful. @Nemael you can already have a look at UI design in the Taler documentation for pointers.
I would for sure love to collaborate!
But I do not necessarily agree on the goal. I do think that a unified “data visualization” would be super useful (for example, making sure that most extension have a page to show all Taler-specific orders, and a settings page that contains the same settings for most implementations, and plenty of other things that I haven’t thought of.)
However, I thing having a visual style similar to the tool you are making the implementation in (for my example, using Odoo’s purple and page disposition) is less jarring to the users (while still being able to use Taler’s logo and distinct visual elements for recognizability).
It is also easier on the technical side for people developing the integrations, because the existing software will have various tools to facilitate making something that looks like what’s already there, and if the visual style of the tool (Odoo in my case) is updated, the integration will be updated as well automatically.
As of now, I will be integrating using Odoo’s visual style, and will implement Taler’s recognizable elements (logo, colors) everywhere I can think of ![]()
Happy to discuss this further!
On the 28th of July 2025:
Big update today! It starts bad, but gets good at the end.
I spent a few days refactoring the whole models of my add-on.
I had an infuriating evening a few days ago, where I spent 3-4 hours making a welcome model and a welcome page for my addon. I had the model and view working in about 30 minutes, but I could not make it display for HOURS. Whatever I tried, or refactored, the view would not appear.
After going to sleep and to my job for a full day, I came back refreshed, and in 5 literal minutes, I found the root cause of my issue being a typo in the access-rights file for my Odoo add-on. I mistakenly had written “welcome” as “welceme”, and none of my linters nor the odoo software raised an error with this.
Lesson learned, the access-rights files is a touchy file, and a typo in it is silent. It can be a huge loss of time, while looking anodyne. I will dedicate more focus on this file in the future.
Other than that, I pushed my changes to the milestone_0.1 branch, and I now have a proper structure and separation of access rights, at the scale that makes sens for the current state of the add-on, at least.
I now have two models as outlined in a previous message, and I have a welcome message with some proper display, and a proper storing of orders as they are created. I might, in the future, need to make two different modes “orders_paid_to_you” and “orders_you_paid”, depending on how the integration with other add-ons work, but I will look into this at a later time.
The current orders list does not show the order status yet, I will implement this later. This is tricky because I want to have an updated status for each of the orders (waiting for payment, paid, refunded, etc), and I want it to update automatically, but I don’t want the user to send many request at once every time they open this menu, so I’ll have to think of a smart way to update the status automatically (maybe only asking for updates on unpaid statuses? And giving the user a way to update the status manually?)
With this push, I believe I am getting close to Milestone 0.1 being completed. It needs some touch-up, but it is starting to look good. I also have a big chunk of Milestone 0.2 prepared, because I can place orders with Taler and pay them within Odoo, but all this logic is not yet integrated within another Odoo module. This part I am more blurry on, but I will try some options and see what’s best. Reaching a Milestone is quite a boon for the project and my motivation to continue on it, I’m excited to make a report on what I made for that Milestone.
The next steps for me are two-fold. I would like to implement some rudimentary Unit Testing, and I need to move forward of the actual implementation of the logic I made in the Odoo add-ons. I will probably work a bit on unit testing, and make a simple scaffolding setup for this, and then move forward in the implementation.
Conclusion of this update: I’m happy to reach a Milestone soon, and excited to continue!
On the 15th of August 2025:
This is the final preparation to get the completion of Milestone 0.1 for my project. I am excited for the completion of the first step!
I completed a few smaller tasks that are required for the Milestone completion.
I modified the logging system to implement logging integration with Odoo. I lost my cool terminal colors, but in exchange I now can store my add-ons logs within a directory in the Odoo install. This will allow storing some of the information exchanged with the Taler servers, which could be useful for potential audits? I have to explore if this feature is interesting, or if it is unneeded, and maybe privacy-destroying. With that, I implemented a rigorous timestamping of the logs, which is great when diving into the requests exchanges with Taler.
I also improved the readme and wrote down installation steps, if anyone would like to install this add-on on their Odoo, to test it.
I added a roadmap which displays the list of steps I have to complete for this add-on (they can be completed in any order). I will update this list according to the completed steps, and will detail the steps when I progress in them.
I also moved the code to the main branch, and tagged it properly for the review.
As a final note: I had a chat with Michiel, and requested an extension of 6 months for the project, which he granted me. I will continue updating him as the Milestones get completed.
On the 23rd of August 2025:
Turns out I did not properly submit my code for the completion of Milestone 1. I had sent an email, but I had to submit it online as well. This is now done.
Michiel did give me some early feedback as well, which implemented in full.
Among the many small changes, I added instructions to edit the addon’s settings from CLI, and investigated + merged the PR for Licensing from Gabriel Ku. This PR provides a good framework for licensing my different files, and I will build upon it with (probably) CC0 licenses on my devlog files.
After sending this, the next step is cyber-security focused, as I am lucky to soon meet with someone well-versed in this topic, whom I’ll be able to ask how I can protect the user’s data. So I have to read up to prepare this meeting! Other than that, it is time to actually integrate my currently-existing system to one of Odoo’s add-on, so I will have to shift to Odoo Enterprise edition for this purpose ![]()