UNPKG

mpesa-mz-sdk

Version:

SDK para integração com a API M-Pesa de Moçambique

386 lines (305 loc) 10.7 kB
# M-Pesa SDK para Moçambique Um SDK robusto e completo para integração com a API M-Pesa da Vodacom em Moçambique, desenvolvido em TypeScript/JavaScript. Suporta todas as operações principais: C2B, B2C, B2B, Query e Reversal. ## 🚀 Características - **Autenticação Segura**: Criptografia RSA do apiKey com a publicKey - **Seleção de Ambiente**: Suporte automático para sandbox e produção - **Tratamento de Erros Robusto**: Classe MpesaError personalizada - **Logging Detalhado**: Para depuração e monitoramento - **TypeScript**: Tipagem completa para melhor experiência de desenvolvimento - **Testes Unitários**: Cobertura completa com Jest - **API Simplificada**: Métodos curtos e intuitivos - **Respostas Legíveis**: Formato de resposta limpo e organizado ## 📦 Instalação ```bash npm install mpesa-mz-sdk ``` ## ⚙️ Configuração ### Variáveis de Ambiente Crie um arquivo `.env` na raiz do seu projeto: ```env # Credenciais M-Pesa MPESA_API_KEY=sua_api_key_aqui MPESA_PUBLIC_KEY=sua_public_key_aqui MPESA_SERVICE_PROVIDER_CODE=seu_service_provider_code MPESA_ORIGIN=seu_origin_aqui # Ambiente (sandbox ou live) MPESA_ENV=sandbox ``` ### Configuração do SDK ```typescript import { MpesaService } from 'mpesa-sdk-mozambique'; const mpesa = new MpesaService({ apiKey: process.env.MPESA_API_KEY!, publicKey: process.env.MPESA_PUBLIC_KEY!, serviceProviderCode: process.env.MPESA_SERVICE_PROVIDER_CODE!, origin: process.env.MPESA_ORIGIN!, env: process.env.MPESA_ENV as 'sandbox' | 'live', // Define automaticamente o host timeout: 60000 // Timeout opcional em ms }); ``` ## 📚 Uso ### Formato de Resposta Todos os métodos retornam um objeto padronizado com a seguinte estrutura: ```typescript { status: 'success' | 'error', message: string, data?: T, // Dados específicos da operação code?: string, // Código de resposta da M-Pesa httpStatus?: number, transactionId?: string, conversationId?: string, thirdPartyReference?: string, timestamp?: string } ``` ### C2B (Customer to Business) ```typescript try { const response = await mpesa.c2b({ amount: 100.00, number: '25884xxxxxxx', // MSISDN (número) do cliente transactionReference: 'TXN123', thirdPartyReference: 'REF456' }); if (response.status === 'success') { console.log('Transação realizada com sucesso!'); console.log('Transaction ID:', response.data?.transactionId); console.log('Amount:', response.data?.amount); console.log('Customer:', response.data?.customerMsisdn); } else { console.error('Erro na transação:', response.message); } } catch (error) { console.error('C2B Error:', error.message); } ``` ### B2C (Business to Customer) ```typescript try { const response = await mpesa.b2c({ amount: 50.00, number: '25884xxxxxxx', // MSISDN (número) do destinatário transactionReference: 'TXN789', thirdPartyReference: 'REF101', paymentServices: 'BusinessPayBill' // Opcional, padrão: BusinessPayBill }); if (response.status === 'success') { console.log('Pagamento enviado com sucesso!'); console.log('Transaction ID:', response.data?.transactionId); console.log('Recipient:', `${response.data?.recipientFirstName || ''} ${response.data?.recipientLastName || ''}`.trim()); console.log('Settlement Amount:', response.data?.settlementAmount); } } catch (error) { console.error('B2C Error:', error.message); } ``` ### B2B (Business to Business) ```typescript try { const response = await mpesa.b2b({ amount: 1000.00, primaryPartyCode: 'COMPANY001', // Código da empresa que envia recipientPartyCode: 'COMPANY002', // Código da empresa que recebe transactionReference: 'TXN202', thirdPartyReference: 'REF303', paymentServices: 'BusinessToBusinessTransfer' // Opcional, padrão: BusinessToBusinessTransfer }); if (response.status === 'success') { console.log('Transferência B2B realizada!'); console.log('From:', response.data?.primaryPartyCode); console.log('To:', response.data?.recipientPartyCode); console.log('Amount:', response.data?.amount); console.log('Settlement:', response.data?.settlementAmount); } } catch (error) { console.error('B2B Error:', error.message); } ``` ### Query (Consulta de Status) ```typescript try { const response = await mpesa.query({ queryReference: 'TXN123', // Transaction ID ou Conversation ID thirdPartyReference: 'REF456' }); if (response.status === 'success') { console.log('Status da transação consultado!'); console.log('Transaction Status:', response.data?.transactionStatus); console.log('Payment Status:', response.data?.paymentStatusDesc); console.log('Payment Code:', response.data?.paymentStatusCode); } } catch (error) { console.error('Query Error:', error.message); } ``` ### Reversal (Reversão) ```typescript try { const response = await mpesa.reversal({ originalTransactionId: 'MPA_TRANS_ID_FROM_PREVIOUS_SUCCESSFUL_C2B', reversalAmount: 50.00, thirdPartyReference: 'REF789' }); if (response.status === 'success') { console.log('Reversão realizada com sucesso!'); console.log('Original Transaction:', response.data?.originalTransactionId); console.log('Reversal Amount:', response.data?.reversalAmount); console.log('New Transaction ID:', response.data?.transactionId); } } catch (error) { console.error('Reversal Error:', error.message); } ``` ## 🔐 Autenticação O SDK utiliza criptografia RSA para gerar o token Bearer: 1. **Criptografia**: O `apiKey` é criptografado usando a `publicKey` com RSA PKCS1_PADDING 2. **Formatação**: A `publicKey` é automaticamente formatada no padrão PEM 3. **Token**: O resultado criptografado é usado como Bearer token ```typescript // O SDK faz isso automaticamente: // 1. Formata a publicKey para PEM // 2. Criptografa o apiKey com a publicKey // 3. Usa o resultado como Bearer token ``` ## 🌍 Ambientes ### Sandbox - **Host**: `api.sandbox.vm.co.mz:18352` - **Uso**: Para testes e desenvolvimento - **Configuração**: `env: 'sandbox'` ### Produção - **Host**: `api.vm.co.mz:18352` - **Uso**: Para operações reais - **Configuração**: `env: 'live'` ## 🛡️ Tratamento de Erros O SDK inclui tratamento robusto de erros com mensagens descritivas baseadas na documentação oficial da M-Pesa API. Todos os códigos de erro oficiais estão mapeados para mensagens claras e compreensíveis. ### Classe MpesaError ```typescript class MpesaError extends Error { constructor( message: string, public code: string, public statusCode: number, public details?: any ) { super(message); this.name = 'MpesaError'; } } ``` ### Códigos de Erro Suportados O SDK inclui **todos os códigos de erro oficiais** da documentação da M-Pesa API: - **INS-0**: Request processed successfully - **INS-1**: Internal Error - **INS-2**: Invalid API Key - **INS-4**: User is not active - **INS-5**: Transaction cancelled by customer - **INS-6**: Transaction Failed - **INS-9**: Request timeout - **INS-10**: Duplicate Transaction - **INS-13**: Invalid Shortcode Used - **INS-14**: Invalid Reference Used - **INS-15**: Invalid Amount Used - **INS-16**: Unable to handle the request due to a temporary overloading - **INS-17**: Invalid Transaction Reference. Length Should Be Between 1 and 20. - **INS-18**: Invalid TransactionID Used - **INS-19**: Invalid ThirdPartyReference Used - **INS-20**: Not All Parameters Provided. Please try again. - **INS-21**: Parameter validations failed. Please try again. - **INS-22**: Invalid Operation Type - **INS-23**: Unknown Status. Contact M-Pesa Support - **INS-24**: Invalid InitiatorIdentifier Used - **INS-25**: Invalid SecurityCredential Used - **INS-26**: Not authorized - **INS-993**: Direct Debit Missing - **INS-994**: Direct Debit Already Exists - **INS-995**: Customer's Profile Has Problems - **INS-996**: Customer Account Status Not Active - **INS-997**: Linking Transaction Not Found - **INS-998**: Invalid Market - **INS-2001**: Initiator authentication error. - **INS-2002**: Receiver invalid. - **INS-2006**: Insufficient balance - **INS-2051**: Invalid number - **INS-2057**: Language code invalid. ### Exemplos de Tratamento de Erros ## 🧪 Testes Execute os testes unitários: ```bash npm test ``` ### Cobertura de Testes - ✅ C2B (Customer to Business) - ✅ B2C (Business to Customer) - ✅ B2B (Business to Business) - ✅ Query (Consulta de Status) - ✅ Reversal (Reversão) - ✅ Tratamento de Erros - ✅ Autenticação - ✅ Formato de Resposta Simplificado ## 🔧 Configuração Avançada ### Timeout Personalizado ```typescript const mpesa = new MpesaService({ // ... outras configurações timeout: 120000 // 2 minutos }); ``` ### Host Personalizado ```typescript const mpesa = new MpesaService({ // ... outras configurações apiHost: 'api.custom.vm.co.mz:18352' // Host personalizado }); ``` ## 🚨 Troubleshooting ### Erro INS-1 (Falha de Autenticação) 1. **Verifique as credenciais**: ```bash echo $MPESA_API_KEY echo $MPESA_PUBLIC_KEY ``` 2. **Confirme o ambiente**: ```bash echo $MPESA_ENV ``` 3. **Teste a criptografia**: ```typescript import { generateBearerToken, formatPublicKey } from 'mpesa-sdk-mozambique'; const token = generateBearerToken(apiKey, formatPublicKey(publicKey)); console.log('Generated Token:', token); ``` ### Erro de Timeout 1. **Aumente o timeout**: ```typescript const mpesa = new MpesaService({ // ... outras configurações timeout: 120000 // 2 minutos }); ``` 2. **Verifique a conectividade**: ```bash ping api.sandbox.vm.co.mz ``` ### Erro de Formato da Public Key O SDK formata automaticamente a public key, mas se houver problemas: ```typescript import { formatPublicKey } from 'mpesa-sdk-mozambique'; const formattedKey = formatPublicKey(publicKey); console.log('Formatted Key:', formattedKey); ``` ## 📄 Licença MIT License - veja o arquivo [LICENSE](LICENSE) para detalhes. ## 🤝 Contribuição Contribuições são bem-vindas! Por favor: 1. Fork o projeto 2. Crie uma branch para sua feature (`git checkout -b feature/AmazingFeature`) 3. Commit suas mudanças (`git commit -m 'Add some AmazingFeature'`) 4. Push para a branch (`git push origin feature/AmazingFeature`) 5. Abra um Pull Request ## 📞 Suporte Para suporte e dúvidas: - 📧 Email: abelbartolomeu06@gmail.com - 🐛 Issues: [GitHub Issues](https://github.com/abel-banze/mpesa-mz-sdk/issues) --- **Desenvolvido com ❤️ para a comunidade M-Pesa em Moçambique**