Input struct for a B2C payment request.
Required fields:
originator_conversation_idinitiator_namesecurity_credentialcommand_idamountparty_aparty_bremarksqueue_timeout_urlresult_url
Optional fields:
occasion
security_credential
security_credential accepts either a pre-encrypted Base64 string or a
{initiator_password, pem} tuple. When a tuple is provided, encryption is
handled internally via Daraja.SecurityCredential.encrypt/2:
# Pre-encrypted (useful when you encrypt once at deploy time):
%{security_credential: "base64-encoded-credential", ...}
# Auto-encrypt (convenient for sandbox/dev):
%{security_credential: {"my-initiator-password", File.read!("sandbox.cer")}, ...}The tuple form is sugar over calling Daraja.SecurityCredential.encrypt/2
inside PaymentRequest.new/1. In production, prefer pre-encrypting with
Daraja.SecurityCredential.encrypt/2 and storing only the resulting Base64
string — so plaintext passwords never live in application state at runtime.
When a tuple is supplied via application env, it is encrypted as soon as
the env fallback is read; the tuple nevertheless remains in
Application env until you replace it with a pre-encrypted string.
Application env fallbacks
initiator_name, security_credential, queue_timeout_url, and result_url
fall back to the :daraja application env when not supplied in params.
security_credential can be a pre-encrypted string or a {password, pem} tuple
in config; per-call params always take precedence:
config :daraja,
b2c_initiator_name: "testapi",
b2c_security_credential: "base64-credential",
b2c_queue_timeout_url: "https://example.com/b2c/timeout",
b2c_result_url: "https://example.com/b2c/result"
# Or in runtime.exs to read the cert file at boot:
config :daraja,
b2c_security_credential: {"my-initiator-password", File.read!("priv/sandbox.cer")}Per-call params always take precedence over env values, which is handy for multi-tenant callers that need to override defaults per request.
Summary
Types
@type command_id() :: String.t()
@type t() :: %Daraja.B2C.PaymentRequest{ amount: pos_integer(), command_id: command_id(), initiator_name: String.t(), occasion: String.t() | nil, originator_conversation_id: String.t(), party_a: String.t(), party_b: String.t(), queue_timeout_url: String.t(), remarks: String.t(), result_url: String.t(), security_credential: String.t() }
Functions
@spec new(map()) :: {:ok, t()} | {:error, :invalid_request, [ atom() | {:command_id, String.t()} | {:security_credential, Daraja.SecurityCredential.encrypt_error() | :invalid_format} ]}