Packages

Vodacom M-Pesa OpenAPI client for Elixir — C2B, B2C, B2B, reversals, direct debit and transaction queries across Tanzania, Lesotho, Ghana and the DRC.

Current section

Files

Jump to
elixir_mpesa CHANGELOG.md
Raw

CHANGELOG.md

# Changelog
All notable changes to this project are documented here. This project adheres to
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## v0.2.0
A substantial release. **0.1.0 code keeps working** — every old function remains as a
deprecated shim, returning the shapes it always did, until 0.3.0.
### Security
- **TLS certificate verification is now on.** 0.1.0 passed `hackney: [:insecure]` on every
request, so the RSA-encrypted API key and the bearer session token travelled over
connections that were never authenticated. Certificates and hostnames are now verified
against the system trust store, and a regression test proves a known-bad certificate is
rejected.
- Request timeouts reduced from 500 seconds to 10s connect / 30s receive. The old value
meant a hung endpoint blocked the caller for over eight minutes.
- The library's own `config/config.exs` no longer carries credential-shaped placeholders,
and CI fails the build if anything resembling a real API key reaches the package.
### Fixed
- **HTTP 403, 404, 429, 502 and 504 raised `FunctionClauseError`** instead of returning an
error tuple. Only ten statuses were handled; everything else crashed the caller. All
statuses are handled now.
- **A non-JSON response body raised.** Gateway HTML error pages and empty bodies now
return `{:error, %ElixirMpesa.Error{reason: :invalid_json}}`.
- **`Base.decode64/1`'s bare `:error` escaped** through the encryption path and caused a
`WithClauseError` further up. Malformed public keys now return a proper error, and
whitespace in a key is tolerated.
- **The `direct_*` helpers encrypted the wrong value** — they called `encrypt_api_key/1`
where `encrypt_session_key/2` was meant, silently discarding the session ID if any
option was passed.
- `input_currency` and `input_country` were documented but **read by nothing**. They are
now `:currency` and `:country`, are actually applied, and are set together by `:market`.
- Missing configuration produced `nil`, which became a request to
`https://openapi.m-pesa.com//ipg/v2//getSession/`. Configuration is now validated up
front with an error naming the missing key.
- `mix compile --warnings-as-errors` and `mix format --check-formatted` both failed on
0.1.0. Both pass.
### Added
- **Automatic session management.** `ElixirMpesa.Session` obtains a session key on first
use, caches it per market, refreshes at 80% of its one-hour lifetime, collapses
concurrent cache misses into a single `getSession` call, and re-authenticates once if
M-Pesa rejects the key mid-flight.
- **`ElixirMpesa.Error`**, a single exception struct for every failure, with a documented
atom `reason` and a `category` (`:config`, `:crypto`, `:transport`, `:http`, `:api`)
that distinguishes "M-Pesa declined" from "the outcome is unknown".
- **`ElixirMpesa.Response`**, replacing raw string-keyed maps.
- **Market presets**`market: :tanzania | :lesotho | :ghana | :drc` sets the URL
context, country and currency together.
- **`reversal/2` is now reachable.** It existed in 0.1.0 but was never exposed on the
top-level module and was absent from the documentation.
- **`!` variants** for every operation, raising on failure.
- **`conversation_id/0`** for generating idempotency keys.
- **`@spec` and `@type` on every public function** — 0.1.0 had none at all — verified by
dialyzer.
- Eight guides, a real test suite (91 tests, 18 doctests, no network), credo, dialyzer and
a CI workflow that matches this project.
- `llms.txt` and `AGENTS.md` for coding assistants.
### Changed
- **HTTPoison replaced with [Req](https://hexdocs.pm/req)**, which verifies TLS by default
and makes the whole suite testable via `Req.Test` with no network.
- **A payment must now carry `"input_ThirdPartyConversationID"`.** The library will not
generate one for a payment: a generated ID would give each retry a fresh idempotency key
and defeat M-Pesa's duplicate detection. Read-only queries still get one generated.
- **Payments are never retried automatically.** Read-only queries are.
- `"input_Country"`, `"input_Currency"` and `"input_ServiceProviderCode"` are filled in
from configuration when omitted.
- Minimum Elixir raised to **1.15**, from a claimed 1.14 that was never tested and that
Req does not support.
- Source files moved from `lib/ex_mpesa/` to `lib/elixir_mpesa/`, matching the module
names since the 0.1.0 rename.
- Corrected the repository URL in the package metadata. It pointed at a GitHub user that
does not exist, so the "GitHub" link on Hex and every "Source" link in the published
docs were dead.
### Deprecated
Removal in 0.3.0. See the [upgrade guide](https://hexdocs.pm/elixir_mpesa/upgrading.html).
- `c2b_single_stage`, `b2c_single_stage`, `b2b_single_stage``c2b/2`, `b2c/2`, `b2b/2`
- `direct_c2b_single_stage`, `direct_b2c_single_stage`, `direct_query_transaction_status`
→ the plain function of the same operation
- Passing a session key to `query_transaction_status`, `query_beneficiary_name`,
`query_direct_debit`, `direct_debit_creation`, `direct_debit_payment` and
`direct_debit_cancel` → pass options instead
- `ElixirMpesa.GenerateSessionKey` and `encrypt_api_key/1`, `generate_session_key/2`,
`encrypt_session_key/2` → handled automatically; `ElixirMpesa.session_key/1` if needed
- `ElixirMpesa.HttpRequest` → removed, replaced by `ElixirMpesa.Client`
## v0.1.0
Initial release. Session key generation, C2B, B2C, B2B, transaction status queries,
direct debit operations and beneficiary name queries.