Download the PHP package brilliantmind/mkesh without Composer
On this page you can find all versions of the php package brilliantmind/mkesh. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download brilliantmind/mkesh
More information about brilliantmind/mkesh
Files in brilliantmind/mkesh
Package mkesh
Short Description PHP package for the MKESH (PagamKesh) mobile money integration over the Ericsson EWP Aggregator (XML over HTTP), with first-class Laravel support.
License MIT
Homepage https://github.com/osvaldogeraldo/mkesh
Informations about the package mkesh
brilliantmind/mkesh
Pacote PHP para a integração MKESH / PagamKesh através do Agregador Ericsson EWP (API "XML over HTTP"), com suporte nativo para Laravel.
O pacote constrói e interpreta todo o XML por si e expõe objectos tipados de pedido/resposta. Autenticação HTTP Basic, transporte PSR-18 (Guzzle por omissão).
| Operação | Método | Fluxo | Endpoint (por omissão) |
|---|---|---|---|
| Debit request | debit() |
C2B – cobrar um cliente | /DebitServlet/DebitSvlt |
| SP transfer | transfer() |
B2C – pagar a um cliente | /sptransfer/sptransfer |
| Get transaction status | getTransactionStatus() |
recuperar um resultado | /GetTransactionStatus/GetStatusSvlt |
| Debit completed | parseDebitCompleted() |
callback assíncrono C2B | (o seu webhook) |
| Transfer completed | parseInitiateTransferCompleted() |
callback assíncrono B2C | (o seu webhook) |
Acabou de instalar? Comece aqui
Não há ficheiros para copiar. Models, webhook, job de reconciliação e a própria rota vêm registados no pacote. Falta-lhe fazer três coisas:
1. Instalar e migrar
2. Preencher o .env (detalhe em 3.1)
3. Reagir ao pagamento — em AppServiceProvider::boot():
E já pode cobrar, de qualquer sítio:
O pacote grava o registo, agenda a reconciliação, recebe o callback, responde ao agregador e dispara o evento acima quando o pagamento fecha.
Falta ainda dar ao provedor o URL do webhook — POST /api/mkesh/callback, já
registado — e garantir que tem php artisan queue:work a correr.
Três coisas que poupam horas se as ler primeiro:
| 💸 | charge() devolve PENDING, não "pago". O dinheiro só se move quando o cliente aprova no telemóvel. Entregue o produto no evento MkeshTransactionSettled, nunca a seguir ao charge(). |
| 🔑 | MKESH_SP_FRI é uma FRI, não um URL nem o número do cliente. É a carteira do provedor que recebe. Ver Armadilhas. |
| ⚙️ | Sem queue:work a correr, uma transacção cujo callback se perca fica PENDING para sempre. |
Índice
- Requisitos
- Instalação
- As duas FRIs de um débito
- Como funciona o fluxo C2B
- Guia rápido Laravel — do zero ao primeiro pagamento
- Usar numa classe Laravel — controller, service, job, command
- Operações em detalhe — payloads completos
- Enums
- Erros
- Base de dados
- TLS, IP de origem e cliente HTTP
- Testes e resolução de problemas
examples/usage.phpé um guia anotado com tudo isto num só ficheiro de código.
1. Requisitos
- PHP 8.1+
- Extensões
ext-domeext-libxml - Um cliente HTTP PSR-18 (o Guzzle vem incluído)
- Laravel 10, 11 ou 12 (opcional — o pacote funciona em PHP puro)
2. Instalação
Em Laravel o MkeshServiceProvider e a facade Mkesh são registados
automaticamente. Publique a configuração:
As migrations vêm dentro do pacote e correm directamente com migrate. Só
precisa de as publicar se quiser alterar o schema:
3. Configuração
3.1 Variáveis de ambiente
Referência completa (ficheiro pronto a copiar em .env.example):
| Variável | Omissão | Descrição |
|---|---|---|
MKESH_USERNAME |
— | Utilizador HTTP Basic |
MKESH_PASSWORD |
— | Senha HTTP Basic |
MKESH_SP_FRI |
FRI:pagamKesh/USER |
FRI creditada num débito (C2B) |
MKESH_SP_TRANSFER_FRI |
(usa MKESH_SP_FRI) |
Carteira debitada num pagamento (B2C) |
MKESH_BASE_URL |
https://41.220.193.151 |
Host do agregador |
MKESH_CURRENCY |
MZN |
Moeda por omissão |
MKESH_TRANSACTION_PREFIX |
— | Prefixo forçado nos ids (ex.: ACME) |
MKESH_CALLBACK_URL |
— | O seu endpoint de callback |
MKESH_SEND_CALLBACK_URL |
false |
Emitir <callbackurl> dentro do débito |
MKESH_VERIFY_SSL |
true |
Verificar o certificado TLS |
MKESH_SSL_CA_BUNDLE |
— | Caminho para o CA de verificação |
MKESH_TIMEOUT |
30 |
Timeout por pedido (segundos) |
MKESH_DEBIT_PATH |
/DebitServlet/DebitSvlt |
Path do débito |
MKESH_SP_TRANSFER_PATH |
/sptransfer/sptransfer |
Path da transferência |
MKESH_STATUS_PATH |
/GetTransactionStatus/GetStatusSvlt |
Path da consulta |
3.2 Três regras rígidas do agregador
- O prefixo é obrigatório. Todo o
externaltransactionid/referenceidtem de começar pelo seu token de parceiro (ex.:ACME). Defina-o uma vez na configuração e passe ids simples — o pacote prefixa-os, de forma idempotente. - Os ids têm de ser únicos por service provider. Reutilizar um dá
REFERENCE_ID_ALREADY_IN_USE. Use$config->newTransactionId()e grave o valor antes de enviar o pedido. - O endpoint do callback é registado do lado do provedor, não vai em cada
pedido. Dê-lhes o URL; o pacote não coloca
<callbackurl>no payload do débito a não ser que activesendCallbackUrl: true.
3.3 Armadilhas na configuração
Estas seis já partiram integrações reais. Vale a pena lê-las antes de preencher
o .env.
1. Uma FRI nunca é um URL
Todos os campos *_FRI levam sempre a forma FRI:<valor>/<TIPO>. Nunca um
endereço. Os únicos campos que levam https:// são MKESH_BASE_URL e
MKESH_CALLBACK_URL.
Sintoma:
2. MKESH_SP_FRI é fixo, é do provedor, e não é o cliente
É a carteira que recebe o dinheiro — o <tofri> do débito. Vem do provedor
e não muda de transacção para transacção. Quem se engana aqui costuma pôr lá o
número do cliente, e depois todas as cobranças vão parar à conta errada (ou
falham com ACCOUNTHOLDER_WITH_FRI_NOT_FOUND).
3. O cliente não vai à configuração
O <fromfri> — quem paga — é construído automaticamente a partir do MSISDN
que passa ao pedido. Nunca está no .env:
4. Os *_PATH são caminhos, não URLs
Deixe-os vazios para usar os valores por omissão — só os altere se o seu agregador diferir.
5. O id tem de ser único por tentativa, não por encomenda
Se derivar o external_transaction_id de uma chave estável (nº de encomenda,
id de factura), a segunda tentativa de pagamento da mesma encomenda é rejeitada
com REFERENCE_ID_ALREADY_IN_USE. Junte sempre um sufixo aleatório:
6. Números mKesh começam por 82 ou 83
Em formato internacional: 2588 2… ou 2588 3…. Um número de outra operadora
dá ACCOUNTHOLDER_WITH_FRI_NOT_FOUND — valide antes de cobrar:
3.4 As duas FRIs de um débito
Um débito envolve duas contas, e trocá-las é o erro mais caro da lista acima. Só uma delas está na configuração:
| Elemento | Quem é | De onde vem |
|---|---|---|
<fromfri> |
o cliente que paga | do MSISDN passado ao pedido — automático |
<tofri> |
a sua carteira, que recebe | MKESH_SP_FRI — fixo na configuração |
Num pagamento B2C (sptransfer) o sentido inverte-se, e a carteira de origem é
outra configuração ainda — MKESH_SP_TRANSFER_FRI, que na folha do provedor é
uma FRI diferente da creditada num débito:
| Elemento | Quem é | De onde vem |
|---|---|---|
<sendingfri> |
a sua carteira, que paga | MKESH_SP_TRANSFER_FRI (ou MKESH_SP_FRI se vazia) |
<receivingfri> |
o cliente que recebe | do MSISDN passado ao pedido — automático |
3.5 PHP puro (sem Laravel)
Ou a partir de um array, com o mesmo formato do config/mkesh.php:
3.6 Checklist de onboarding
A folha do provedor deixa o bloco por ambiente em branco. Estes valores têm de ser acordados com eles separadamente para teste e produção:
| Valor | Direcção | Corresponde a |
|---|---|---|
| Endereço IP de origem | você → provedor | o IP de saída que eles autorizam |
| URL de callback | você → provedor | MKESH_CALLBACK_URL |
| Utilizador / senha | provedor → você | MKESH_USERNAME / MKESH_PASSWORD |
| Nr. de conta / MSISDN | provedor → você | MKESH_SP_FRI / MKESH_SP_TRANSFER_FRI |
| Prefixo de transacção | provedor → você | MKESH_TRANSACTION_PREFIX |
| URL base | provedor → você | MKESH_BASE_URL |
4. Como funciona o fluxo C2B
Cobrar um cliente é assíncrono. A resposta do débito só diz que o pedido foi aceite — o dinheiro ainda não se moveu.
Na prática:
debit()devolvePENDINGe umapprovalid. Grave os ids e pare.- O cliente aprova no telemóvel. Não há sinal síncrono deste passo.
- O agregador faz POST do
debitcompletedrequestpara o seu endpoint. Tem de responder<ResponseCode>SUCCESS</ResponseCode>— um200vazio não é aceite e o callback será reenviado. - Se o callback nunca chegar, consulte
getTransactionStatus($referenceId)até o estado ficar liquidado.
Os pagamentos B2C (transfer()) são mais simples: uma sptransferresponse com
sucesso significa que o dinheiro foi transferido.
5. Guia rápido Laravel
O que o pacote já faz por si
Não há ficheiros para copiar. Isto vem registado assim que instala:
| Models | MkeshTransaction e MkeshResponse, com as migrations |
| Rota do webhook | POST /api/mkesh/callback, sem middleware — o agregador não tem sessão nem token CSRF |
| Controller do webhook | valida, grava, liquida a transacção e responde <ResponseCode>SUCCESS</ResponseCode> |
| Job de reconciliação | agendado sozinho depois de cada débito |
| Eventos | MkeshTransactionSettled e MkeshCallbackReceived |
| Facade | Mkesh::charge() / Mkesh::payout() |
Sobram-lhe quatro passos.
Passo 1 — instalar e configurar
Preencha o .env conforme a secção 3.1.
Passo 2 — dar o URL do webhook ao provedor
https://a-sua-app.co.mz/api/mkesh/callback — já está registado, confirme com
php artisan route:list --name=mkesh. Eles configuram-no do lado deles.
Confirme também que o IP de saída do seu servidor está autorizado.
Para mudar o caminho, ou registar o seu próprio endpoint:
Passo 3 — cobrar
Ou injectando, se preferir não usar facades:
Passo 4 — saber que foi pago
Este é o passo que se esquece. charge() devolve PENDING: o dinheiro ainda
não se moveu e não há resposta síncrona a dizer que sim. O cliente ainda tem
de aprovar no telemóvel.
Ponha a lógica de "foi pago" num listener, não à volta do charge():
O evento dispara uma única vez por transacção, venha o resultado do callback ou do job de reconciliação. Um callback reenviado não volta a disparar — é essa a rede de segurança contra entregar a encomenda duas vezes.
Passo 5 — mostrar o estado ao utilizador
O browser não recebe nada do MKESH. Devolva 202 com a referência e deixe o
frontend consultar:
Isto consulta a sua base de dados, não o MKESH — o callback e o job já a
mantêm actualizada. Não chame getTransactionStatus() a cada polling do
browser.
Resumo do ciclo de vida
| Momento | O que a sua aplicação faz |
|---|---|
| Utilizador carrega em pagar | charge() → grava linha PENDING, devolve 202 |
| Cliente recebe SMS e aprova | nada — não há sinal síncrono |
Chega o debitcompletedrequest |
webhook liquida a linha e entrega o produto |
| O callback nunca chega | o job de reconciliação apanha o estado por polling |
| Frontend pergunta "já?" | lê a sua tabela, não o MKESH |
Antes de ir para produção
- [ ]
MKESH_SP_FRIé uma FRI, não um URL nem o número do cliente (3.3) - [ ] O IP de saída do servidor está autorizado pelo provedor
- [ ] O URL de callback está registado do lado deles e é acessível de fora
- [ ] O webhook devolve
<ResponseCode>SUCCESS</ResponseCode>(teste comcurl) - [ ] A fila está a correr (
php artisan queue:work) — sem ela o job de reconciliação nunca corre - [ ]
MKESH_VERIFY_SSL=truecom o CA do provedor - [ ] Os ids são únicos por tentativa, não por encomenda (3.3)
6. Usar numa classe Laravel
6.1 Injecção no construtor (recomendado)
MkeshClient está registado no container como singleton — basta declarar o tipo:
6.2 Facade
Métodos disponíveis na facade:
| Método | Devolve |
|---|---|
Mkesh::debit($request) |
DebitResponse |
Mkesh::transfer($request) |
SpTransferResponse |
Mkesh::getTransactionStatus($ref) |
TransactionStatusResponse |
Mkesh::parseDebitCompleted($xml) |
DebitCompletedNotification |
Mkesh::parseInitiateTransferCompleted($xml) |
InitiateTransferCompletedNotification |
Mkesh::acknowledgeCallback() |
CallbackResponse |
Mkesh::config() |
MkeshConfig |
6.3 Controller que inicia um pagamento
6.4 O webhook (já feito)
Não escreva um. O pacote regista o controller e a rota. Ele faz, dentro de uma transacção de base de dados:
- interpreta o corpo — se não der, grava-o na mesma e devolve
400 - bloqueia a linha correspondente com
lockForUpdate - grava o payload cru em
mkesh_responses, mesmo que não tenha correspondência - liquida a transacção e dispara
MkeshTransactionSettleduma única vez - devolve
<ResponseCode>SUCCESS</ResponseCode>
As três propriedades que isto garante, e que são fáceis de errar à mão:
- Reentrega não duplica. Duas entregas do mesmo callback dão dois registos de auditoria mas um só evento de negócio — a sua encomenda não é entregue duas vezes.
- Callback tardio não inverte o resultado. Um
FAILEDque chegue depois de umSUCCESSFULé registado e ignorado. - Acusa sempre a recepção quando consegue ler o corpo, mesmo sem correspondência local. Caso contrário o agregador reenvia para sempre.
Se precisar mesmo do seu próprio endpoint, desligue o do pacote e reutilize o handler — assim mantém as garantias acima:
6.5 Job de reconciliação (já agendado)
Cobre o ramo "sem resposta do MKESH". O Mkesh::charge() despacha-o sozinho —
não tem de fazer nada:
Faz polling ao gettransactionstatus com backoff progressivo (1, 2, 5, 10, 15,
30, 60 minutos) e pára assim que a linha estiver liquidada — seja pelo callback,
seja pelo próprio polling. Códigos retentáveis (ErrorCode::isRetryable(),
sobretudo TRANSACTION_NOT_FOUND, que aqui significa "ainda não registado")
libertam o job para nova tentativa.
Precisa de um worker. Sem
php artisan queue:worka correr, uma transacção cujo callback se perca ficaPENDINGpara sempre.
6.6 Command Artisan para reconciliar em lote
Agende-o em routes/console.php:
6.7 Testar sem tocar na rede
Injecte um cliente PSR-18 falso — não é preciso mais nada:
7. Operações em detalhe
Todos os ids mostrados já incluem o prefixo
ACME, que o pacote aplica automaticamente aexternaltransactionid/providertransactionid/referenceid.
7.1 Debit request — C2B (cobrar um cliente)
Pedido enviado (Content-Type: text/xml):
O referenceid assume por omissão o valor do id externo (como na folha do
provedor) e é por ele que o getTransactionStatus() procura a transacção.
Resposta (PENDING) → DebitResponse:
7.2 SP transfer — B2C (pagar a um cliente)
A carteira de origem vem de spTransferSendingFri, que é muitas vezes uma FRI
diferente da creditada num débito (FRI:47225552/MM vs FRI:pagamKesh/USER);
se não estiver definida, usa a serviceProviderFri.
Pedido enviado:
Resposta → SpTransferResponse:
7.3 Get transaction status (recuperar um resultado)
Use o referenceid de uma operação anterior quando não houve resposta nem
callback.
Pedido enviado:
Resposta (SUCESSO):
Resposta (FALHA) — repare que não traz providertransactionid:
7.4 Callback debit-completed
O agregador faz POST disto para o endpoint que registou junto do provedor.
Pedido recebido:
A resposta obrigatória. Um 200 vazio não é aceite e o callback será
reenviado:
7.5 Callback transfer-completed (B2C)
O equivalente B2C é entregue da mesma forma:
8. Enums
| Enum | Casos | Serve para |
|---|---|---|
Enum\TransactionStatus |
PENDING SUCCESSFUL FAILED UNKNOWN |
o estado de um débito/transferência |
Enum\ErrorCode |
22 códigos + UNKNOWN |
decidir o que fazer perante uma falha |
Enum\CallbackResponseCode |
SUCCESS FAILURE |
o corpo devolvido pelo seu webhook |
Enum\FriType |
MSISDN USER MM |
construir FRIs |
Todos interpretam defensivamente: um valor desconhecido dá UNKNOWN em vez de
lançar excepção, para que um valor novo da plataforma nunca parta o parsing.
8.1 TransactionStatus
Em Eloquent, faça cast directo para o enum:
8.2 ErrorCode
Cobre os códigos que mudam o que a aplicação faz, com a decisão já embutida em vez de ficar à mercê de comparações de strings:
Casos disponíveis, por família:
| Família | Casos |
|---|---|
| Pesquisa / idempotência | TRANSACTION_NOT_FOUND REFERENCE_ID_ALREADY_IN_USE AMBIGUOUS_REFERENCE_ID EXPIRED_OR_INVALID_TRANSACTION_ID |
| Contraparte | ACCOUNTHOLDER_WITH_FRI_NOT_FOUND ACCOUNTHOLDER_WITH_MSISDN_NOT_FOUND ACCOUNTHOLDER_NOT_ACTIVE AUTHORIZATION_ACCOUNTHOLDER_NOT_ACTIVE ACCOUNT_NOT_FOUND |
| Dinheiro | AUTHORIZATION_CURRENT_BALANCE_TOO_LOW AUTHORIZATION_MAX_TRANSFER_AMOUNT AUTHORIZATION_MAXIMUM_AMOUNT_ALLOWED_TO_SEND AUTHORIZATION_MAXIMUM_AMOUNT_ALLOWED_TO_RECEIVE AMOUNT_INVALID INVALID_CURRENCY CURRENCY_NOT_SUPPORTED |
| Aprovação | TRANSACTION_REQUEST_EXPIRED INCORRECT_PIN QUEUED_FOR_APPROVAL INVALID_APPROVAL_TRANSACTION_STATUS RETRY_FROM_BEGINNING |
| Acesso | AUTHORIZATION_FAILED |
O enum não lista os 670 códigos de propósito — seria uma segunda cópia do
ErrorCodes sem ganho nenhum. Qualquer código fora dele dá ErrorCode::UNKNOWN,
enquanto getErrorCode() e ErrorCodes::description() continuam a funcionar
sobre a string crua.
8.3 CallbackResponseCode
Na dúvida responda SUCCESS e reconcilie fora de banda com o
gettransactionstatus — o tratamento de FAILURE do lado da plataforma não
está especificado.
8.4 FriType e os value objects
9. Erros
Erros de negócio chegam como um envelope errorResponse e são lançados como
ErrorResponseException.
Hierarquia — todas implementam a interface marcadora MkeshException:
| Excepção | Lançada quando |
|---|---|
ErrorResponseException |
a plataforma devolveu um <errorResponse> |
TransportException |
falha de ligação/TLS/timeout, corpo vazio ou XML inválido |
ConfigurationException |
configuração em falta ou inválida |
InvalidArgumentException |
value object ou input de pedido inválido |
Catálogo completo de códigos
Os 670 códigos da referência da plataforma estão em
BrilliantMind\Mkesh\Error\ErrorCodes, e a descrição é acrescentada
automaticamente à mensagem da excepção:
Os três erros que vai mesmo encontrar
| Código | Significado | O que fazer |
|---|---|---|
REFERENCE_ID_ALREADY_IN_USE |
id repetido | O original quase de certeza passou. Consulte o estado — não reenvie com id novo. |
TRANSACTION_NOT_FOUND |
ainda não registado | Consultou cedo demais. Repita mais tarde. |
ACCOUNTHOLDER_WITH_FRI_NOT_FOUND |
número não é mKesh | Valide o MSISDN antes de cobrar. |
10. Base de dados
Duas migrations e dois models acompanham o pacote. As migrations correm com
php artisan migrate; os models estão em
BrilliantMind\Mkesh\Laravel\Models\ e não precisam de ser copiados.
Chaves primárias são UUID
Ambas as tabelas usam UUID ordenado (HasUuids) em vez de auto-incremento.
Estes ids saem da base de dados — vão em payloads de fila, logs e tickets de
suporte — e um inteiro sequencial revelaria o volume de transacções e
convidaria à enumeração. Sendo ordenados (ordenáveis no tempo), o índice não
fragmenta como aconteceria com UUID v4 puro.
Consequência prática: onde passar a chave, é string:
payable_id é string, de propósito
A ligação polimórfica usa colunas string, não nullableMorphs():
Um pacote não deve impor o tipo de chave aos models da aplicação.
nullableMorphs() forçaria unsignedBigInteger e partiria quem usa UUID ou
ULID — com o erro Data truncated for column 'payable_id' assim que
tentasse guardar uma chave não numérica. nullableUuidMorphs() teria o
problema simétrico: partiria quem usa auto-incremento. string aceita int,
UUID e ULID, sem o pacote precisar de saber qual deles usa.
Nomes de tabela e ligação
Migrations e models lêem os mesmos valores da config, por isso renomear num sítio chega:
mkesh_transactions — o livro-razão
A linha é criada antes do pedido sair, para reservar o id localmente.
| Coluna | Notas |
|---|---|
id |
UUID ordenado |
type |
debit (C2B) ou transfer (B2C) |
external_transaction_id |
enviado no débito, único por tipo |
provider_transaction_id |
enviado na transferência, único por tipo |
reference_id |
o que o getTransactionStatus() procura |
financial_transaction_id |
devolvido pela plataforma |
approval_id |
de um débito pendente |
msisdn, amount, currency |
contraparte e dinheiro |
status |
PENDING / SUCCESSFUL / FAILED / UNKNOWN |
error_code, error_message |
código da plataforma + descrição do catálogo |
payable_type, payable_id |
ligação polimórfica — payable_id é string, aceita qualquer chave (int, UUID, ULID) |
completed_at |
quando liquidou |
Métodos e scopes do model:
settle() devolver false é a rede de segurança contra callbacks reenviados:
o primeiro resultado nunca é sobrescrito.
mkesh_responses — a auditoria
Propositadamente não é única por transacção, porque os callbacks são reenviados. É precisamente isso que a torna útil: prova o que chegou, quando, e o que respondeu.
| Coluna | Notas |
|---|---|
id |
UUID ordenado |
direction |
inbound (callback recebido) / outbound (resposta a pedido nosso) |
operation |
debitcompletedrequest, sptransferresponse, errorResponse… |
mkesh_transaction_id |
ligação ao livro-razão, quando houve correspondência |
external_transaction_id, reference_id, financial_transaction_id |
desnormalizados para pesquisa |
status, error_code |
extraídos para consulta |
response_code |
o SUCCESS / FAILURE que devolvemos |
http_status |
código HTTP devolvido ou recebido |
payload |
o XML intacto |
Ao apagar uma transacção, o mkesh_transaction_id fica a null mas o registo
sobrevive — a prova do que chegou não se apaga com o livro-razão.
11. TLS, IP de origem e cliente HTTP
TLS
O agregador está publicado em HTTPS sobre um IP nu, por isso o certificado
não corresponde ao hostname e a verificação por omissão falha. A verificação
está ligada por omissão — aponte MKESH_SSL_CA_BUNDLE para o certificado
que o provedor fornecer e só desligue (MKESH_VERIFY_SSL=false) contra o
ambiente de testes.
IP de origem
O provedor faz whitelist do IP de origem: as chamadas têm de sair do host que registou junto deles. Uma máquina local ou um IP de saída diferente é rejeitado ao nível da rede, antes de qualquer XML ser interpretado.
Cliente HTTP personalizado
MkeshClient::create() liga o Guzzle por si. Para usar outro cliente PSR-18,
injecte-o (com as factories PSR-17) pelo construtor:
12. Testes e resolução de problemas
Teste manual pela linha de comandos
Imprime o XML enviado e a resposta interpretada — é a forma mais rápida de resolver um desacordo com o provedor.
Problemas comuns
| Sintoma / erro | Causa provável | Como resolver |
|---|---|---|
MKESH_SP_FRI … is not set |
Variável vazia ou em falta | Peça a FRI ao provedor. É FRI:<valor>/<TIPO>, não um URL — ver 3.3 |
FRI "https://…" is a URL |
Pôs um endereço num campo *_FRI |
Só MKESH_BASE_URL e MKESH_CALLBACK_URL levam https:// |
FRI "…" must start with "FRI:" |
Falta o prefixo FRI: |
FRI:pagamKesh/USER, não pagamKesh/USER |
FRI "…" is missing the "/<TYPE>" |
Falta o sufixo de tipo | /USER, /MSISDN ou /MM |
Data truncated for column 'payable_id' |
Migration antiga com payable_id em bigint e um payable com chave UUID/ULID |
Actualize as migrations — desde a 0.2.0 a coluna é string |
REFERENCE_ID_ALREADY_IN_USE |
Id reutilizado (típico: derivado do nº de encomenda, sem sufixo por tentativa) | newTransactionId(), ou junte um sufixo aleatório. Grave-o antes de enviar |
TRANSACTION_NOT_FOUND ao consultar |
Consultou cedo demais, ou usou o id errado | A procura é pelo referenceid. Repita mais tarde |
ACCOUNTHOLDER_WITH_FRI_NOT_FOUND |
Número não é mKesh, ou pôs o número do cliente no MKESH_SP_FRI |
Números mKesh começam por 82 ou 83. O <fromfri> sai do MSISDN, não da config |
AUTHORIZATION_FAILED |
Credenciais erradas ou IP de origem não autorizado | Confirme as duas coisas com o provedor |
| Erro de certificado TLS | Host publicado num IP nu, logo o certificado não bate com o hostname | MKESH_SSL_CA_BUNDLE com o CA do provedor; MKESH_VERIFY_SSL=false só em testes |
| O callback chega repetidamente | Não está a devolver <ResponseCode>SUCCESS</ResponseCode> |
Um 200 vazio não é aceite |
| Timeout sem resposta | Pode ter passado do lado deles | Consulte o estado antes de reenviar |
Débito fica sempre PENDING |
O cliente não aprovou | O pedido expira; veja TRANSACTION_REQUEST_EXPIRED |
Licença
MIT — © 2026 BrilliantMind. Ver LICENSE.
Suporte: [email protected]
All versions of mkesh with dependencies
ext-dom Version *
ext-libxml Version *
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
guzzlehttp/guzzle Version ^7.14.2