Markets
View SourceThe Vodacom M-Pesa OpenAPI serves several countries from one host, distinguished by a URL context. Each market has its own credentials, its own country code and its own currency.
Supported markets
:market | Country | URL context | Country code | Currency |
|---|---|---|---|---|
:tanzania | Tanzania | vodacomTZN | TZN | TZS |
:lesotho | Lesotho | vodacomLES | LES | LSL |
:ghana | Ghana | vodafoneGHA | GHA | GHS |
:drc | DR Congo | vodacomDRC | DRC | CDF |
Note that Ghana's context is vodafoneGHA, not vodacomGHA — a common source of 404s.
Setting :market applies all three values at once:
config :elixir_mpesa, market: :tanzaniawhich is equivalent to, but harder to get wrong than:
config :elixir_mpesa,
url_context: "vodacomTZN",
country: "TZN",
currency: "TZS"ElixirMpesa.Config.markets/0 lists them at runtime, and
ElixirMpesa.Config.market/1 returns one preset.
Endpoints
Requests go to:
https://openapi.m-pesa.com/{api_type}/ipg/v2/{url_context}/{operation}where api_type is sandbox or openapi (production). So a Tanzanian production C2B
payment lands on:
https://openapi.m-pesa.com/openapi/ipg/v2/vodacomTZN/c2bPayment/singleStage/Serving more than one market
Configuration can be overridden per call, and sessions are cached per market, so one application can serve several countries at once without them interfering:
ElixirMpesa.c2b(tanzanian_attrs, market: :tanzania)
ElixirMpesa.c2b(ghanaian_attrs, market: :ghana)Each market needs its own API key and public key, so pass those too — or keep them in a map and merge:
@markets %{
tanzania: [market: :tanzania, api_key: {:system, "MPESA_TZ_KEY"}, ...],
ghana: [market: :ghana, api_key: {:system, "MPESA_GH_KEY"}, ...]
}
def pay(market, attrs), do: ElixirMpesa.c2b(attrs, @markets[market])A market without a preset
Vodacom adds markets from time to time, and Mozambique runs a separate platform altogether. You do not need to wait for a release — set the three values directly:
ElixirMpesa.c2b(attrs,
url_context: "vodacomMOZ",
country: "MOZ",
currency: "MZN"
)Everything else works unchanged. If you are using a market this library does not list,
a pull request adding it to ElixirMpesa.Config is welcome.
Phone number format
"input_CustomerMSISDN" is the full international number without a + or leading
zeros:
| Country | Dialling code | Example |
|---|---|---|
| Tanzania | 255 | "255700000000" |
| Lesotho | 266 | "26650000000" |
| Ghana | 233 | "233200000000" |
| DR Congo | 243 | "243800000000" |
A number in the wrong format is one of the most common causes of a rejected transaction. Normalise before sending.