Skip to content

Instantly share code, notes, and snippets.

@otikev
Created January 24, 2018 18:30
Show Gist options
  • Select an option

  • Save otikev/f6ad2bdbf91e486bdb383526b8565fff to your computer and use it in GitHub Desktop.

Select an option

Save otikev/f6ad2bdbf91e486bdb383526b8565fff to your computer and use it in GitHub Desktop.
A sample Parser for M-PESA SMSs. This works as of Jan 24th 2018. The format of the SMSs might/will change in future and this will not be relevant any more.
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 24 Jan, 2018
* Parses MPESA SMS String through simple String manipulation. And a tiny bit of regex :-D
*/
public class SillyMpesaMessageParser {
public Map<String,String> parse(final String message){
String[] exploded = message.toLowerCase().split(" ");
//Get Transaction code
String code = exploded[0];
//Get transaction type
String transactionType = getTransactionType(message.toLowerCase());
//Get sender/recipient
String participant = getParticipant(transactionType,message.toLowerCase());
//Get mpesa amount
String amount = "";
String balance = "";
String transactionCost = "";
int moneyCount = 0;
for(String str : exploded){
if(str.startsWith("ksh")){
String money = str.replace("ksh","");
if(moneyCount == 0){
amount = money;
}else if(moneyCount == 1){
balance = money.substring(0,money.length()-1);
}else if(moneyCount == 2){
transactionCost = money.substring(0,money.length()-1);
}
moneyCount++;
}
}
Map<String,String> parsed = new HashMap<>();
parsed.put("type",transactionType.trim());
parsed.put("code",code.trim());
parsed.put("amount",amount.trim());
parsed.put("balance",balance.trim());
parsed.put("cost",transactionCost.trim());
parsed.put("participant",participant.trim());
return parsed;
}
private String getTransactionType(String message){
String transactionType = "unknown";
if(message.toLowerCase().contains("you have received")){
transactionType = "received";
}else if(message.toLowerCase().contains("sent to")){
transactionType = "sent";
}else if(message.toLowerCase().contains("withdraw")){
transactionType = "withdraw";
}else if(message.toLowerCase().contains("paid to")){
transactionType = "paybill";
}else if(message.toLowerCase().contains("you bought")){
transactionType = "airtime";
}
return transactionType;
}
private String getParticipant(String transactionType, String msg){
if(transactionType.equals("received")){
Pattern findSubject = Pattern.compile("from(.*)on [1-9]");
Matcher matcher = findSubject.matcher(msg);
while (matcher.find()) {
return matcher.group(1);
}
}else if(transactionType.equals("withdraw")){
Pattern findSubject = Pattern.compile("from(.*)new m-pesa");
Matcher matcher = findSubject.matcher(msg);
while (matcher.find()) {
return matcher.group(1);
}
}else if(transactionType.equals("sent") || transactionType.equals("paybill")){
Pattern findSubject = Pattern.compile("to(.*)on [1-9]");
Matcher matcher = findSubject.matcher(msg);
while (matcher.find()) {
return matcher.group(1);
}
}
return "";
}
}
import org.junit.Before;
import org.junit.Test;
import java.util.Map;
import static org.junit.Assert.*;
public class SillyMpesaMessageParserTest {
SillyMpesaMessageParser parser;
@Before
public void setUp() throws Exception {
parser = new SillyMpesaMessageParser();
}
@Test
public void testReceivedMpesa(){
String msg = "MDDA561QDA Confirmed. You have received Ksh5,000.00 from JOHN DOE 0799654321 "+
"on 15/1/18 at 7:00 PM. New M-PESA balance is Ksh6,000.00. Pay bills via M-PESA.";
Map<String,String> response = parser.parse(msg);
assertEquals("received",response.get("type"));
assertEquals("MDDA561QDA".toLowerCase(),response.get("code"));// Gets the correct transaction code
assertEquals("JOHN DOE 0799654321".toLowerCase(),response.get("participant"));// Gets the correct sender
assertEquals("5,000.00",response.get("amount"));
assertEquals("6,000.00",response.get("balance"));
assertEquals("",response.get("cost"));
}
@Test
public void testSentMpesa(){
String msg = "MDDA561QDA Confirmed. Ksh5,000.00 sent to JOHN DOE 0799654321 "+
"on 15/1/18 at 7:00 PM. New M-PESA balance is Ksh500.00. Transaction cost, Ksh27.00.";
Map<String,String> response = parser.parse(msg);
assertEquals("sent",response.get("type"));
assertEquals("MDDA561QDA".toLowerCase(),response.get("code"));// Gets the correct transaction code
assertEquals("JOHN DOE 0799654321".toLowerCase(),response.get("participant"));// Gets the correct sender
assertEquals("5,000.00",response.get("amount"));
assertEquals("500.00",response.get("balance"));
assertEquals("27.00",response.get("cost"));
}
@Test
public void testWithdrawMpesa(){
String msg = "MDDA561QDA Confirmed.on 15/1/18 at 7:00 PMWithdraw Ksh2,000.00 from 99999 - Super Agent "+
"New M-PESA balance is Ksh900.00. Transaction cost, Ksh27.00.";
Map<String,String> response = parser.parse(msg);
assertEquals("withdraw",response.get("type"));
assertEquals("MDDA561QDA".toLowerCase(),response.get("code"));// Gets the correct transaction code
assertEquals("99999 - Super Agent".toLowerCase(),response.get("participant"));// Gets the correct sender
assertEquals("2,000.00",response.get("amount"));
assertEquals("900.00",response.get("balance"));
assertEquals("27.00",response.get("cost"));
}
@Test
public void testPaybillMpesa(){
String msg = "MDDA561QDA Confirmed. Ksh5,000.00 paid to AWESOME MARKET. on 15/1/18 at 7:00 PM. "+
"New M-PESA balance is Ksh900.00. Transaction cost, Ksh0.00.";
Map<String,String> response = parser.parse(msg);
assertEquals("paybill",response.get("type"));
assertEquals("MDDA561QDA".toLowerCase(),response.get("code"));// Gets the correct transaction code
assertEquals("AWESOME MARKET.".toLowerCase(),response.get("participant"));// Gets the correct sender
assertEquals("5,000.00",response.get("amount"));
assertEquals("900.00",response.get("balance"));
assertEquals("0.00",response.get("cost"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment