From c697be4e058112f3fd8140cb43b510fc1bfa5cf4 Mon Sep 17 00:00:00 2001 From: Alexandre Dumont aka Adlx Date: Sun, 24 Jun 2018 23:35:55 +0200 Subject: [PATCH 1/4] Update simyo.py: replace www. with api. API endpoint URL has changed. --- simyo/simyo.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/simyo/simyo.py b/simyo/simyo.py index fa0cccb..6f799ea 100755 --- a/simyo/simyo.py +++ b/simyo/simyo.py @@ -102,7 +102,7 @@ def api_request(url, data="", check=True): return result def api_logout(): - URL="https://www.simyo.es/api/logout?sessionId=" + str(sessionId) + URL="https://api.simyo.es/api/logout?sessionId=" + str(sessionId) result = api_request(URL,"",False) if VERBOSE: print result + "\n" @@ -110,7 +110,7 @@ def api_login(): global sessionId, customerId SIMYOPASS = simyopass() - URL="https://www.simyo.es/api/login?" + URL="https://api.simyo.es/api/login?" data = "user=" + USERNAME + "&password=" + SIMYOPASS + "&apiSig=null" result = api_request(URL,data) if VERBOSE: print result + "\n" @@ -121,7 +121,7 @@ def api_login(): def subscriptions(): global registerDate, mainProductId, billCycleType, msisdn, subscriberId, payType - URL="https://www.simyo.es/api/subscriptions/" + str(customerId) + "?sessionId=" + str(sessionId) + URL="https://api.simyo.es/api/subscriptions/" + str(customerId) + "?sessionId=" + str(sessionId) result = api_request(URL) if VERBOSE: print result + "\n" @@ -144,7 +144,7 @@ def subscriptions(): sys.exit(0) def consumptionByCycle(billCycleCount=1): - URL="https://www.simyo.es/api/consumptionByCycle/" + str(customerId) + "?sessionId=" + str(sessionId) + "&msisdn=" + str(msisdn) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&billCycle=" + str(billCycle) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) + URL="https://api.simyo.es/api/consumptionByCycle/" + str(customerId) + "?sessionId=" + str(sessionId) + "&msisdn=" + str(msisdn) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&billCycle=" + str(billCycle) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) result = api_request(URL) if VERBOSE: print result + "\n" @@ -229,7 +229,7 @@ def consumptionByCycle(billCycleCount=1): print "\nConsumo total: " + str(chargeTotal) + " EUR\n" def consumptionDetailByCycle(billCycleCount=1): - URL="https://www.simyo.es/api/consumptionDetailByCycle/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) + URL="https://api.simyo.es/api/consumptionDetailByCycle/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) result = api_request(URL) if VERBOSE: print result + "\n" @@ -286,7 +286,7 @@ def consumptionDetailByCycle(billCycleCount=1): def frequentNumbers(): month=billCycle # Parameter month is mandatory - URL="https://www.simyo.es/api/frequentNumbers/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&month=" + str(month) + URL="https://api.simyo.es/api/frequentNumbers/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&month=" + str(month) result = api_request(URL) if VERBOSE: print result + "\n" @@ -299,7 +299,7 @@ def frequentNumbers(): def messages(): start=1 count=500 - URL="https://www.simyo.es/api/messages/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) + URL="https://api.simyo.es/api/messages/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) result = api_request(URL) if VERBOSE: print result + "\n" @@ -321,7 +321,7 @@ def messages(): def voiceCalls(): start=1 count=500 - URL="https://www.simyo.es/api/voiceCalls/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) + URL="https://api.simyo.es/api/voiceCalls/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) result = api_request(URL) if VERBOSE: print result + "\n" @@ -350,7 +350,7 @@ def rechargeHistory(): startDate=registerDate endDate = time() endDate = int(endDate) * 1000 - URL="https://www.simyo.es/api/rechargeHistory/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&startDate=" + str(startDate) + "&endDate=" + str(endDate) + URL="https://api.simyo.es/api/rechargeHistory/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&startDate=" + str(startDate) + "&endDate=" + str(endDate) result = api_request(URL) if VERBOSE: print result + "\n" @@ -365,7 +365,7 @@ def rechargeHistory(): print '{0}\t\t{1}'.format(date, fee) def mgmHistory(): - URL="https://www.simyo.es/api/mgmHistory/" + str(customerId) + "?sessionId=" + str(sessionId) + URL="https://api.simyo.es/api/mgmHistory/" + str(customerId) + "?sessionId=" + str(sessionId) result = api_request(URL) if VERBOSE: print result + "\n" @@ -379,7 +379,7 @@ def mgmHistory(): print "TOTAL DISPONIBLE: " + str(totalAvailablePoints) def invoiceList(): - URL="https://www.simyo.es/api/invoiceList/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + URL="https://api.simyo.es/api/invoiceList/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) result = api_request(URL) if VERBOSE: print result + "\n" @@ -408,7 +408,7 @@ def downloadInvoice(): print "Can't find invoice with id = " + str(reqInvoiceId) sys.exit(1) - URL="https://www.simyo.es/api/downloadInvoice?sessionId=" + str (sessionId) + "&invoiceNO=" + str(invoiceNO) + "&invoiceId=" + str(invoiceId) + URL="https://api.simyo.es/api/downloadInvoice?sessionId=" + str (sessionId) + "&invoiceNO=" + str(invoiceNO) + "&invoiceId=" + str(invoiceId) result = api_request(URL) if VERBOSE: print result + "\n" @@ -511,4 +511,4 @@ def parse_cmd(): sys.exit(0) #TODO: -#https://www.simyo.es/api/contact +#https://api.simyo.es/api/contact From 5ae8e5ccf96f86333df61bc96638f7327505480d Mon Sep 17 00:00:00 2001 From: Alexandre Dumont aka Adlx Date: Thu, 7 Mar 2019 00:45:32 +0100 Subject: [PATCH 2/4] API base url has changed again... --- simyo/simyo.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/simyo/simyo.py b/simyo/simyo.py index 6f799ea..f009d6e 100755 --- a/simyo/simyo.py +++ b/simyo/simyo.py @@ -29,6 +29,8 @@ USERNAME = "" PASSWORD = "" +BASE_URL = "https://api.simyo.es/simyo-api" + def getApiSig(url): dig = hmac.new(b'f25a2s1m10', msg='f25a2s1m10' + url.lower(), digestmod=hashlib.sha256).digest() return url + "&apiSig=" + dig.encode('hex') @@ -102,7 +104,7 @@ def api_request(url, data="", check=True): return result def api_logout(): - URL="https://api.simyo.es/api/logout?sessionId=" + str(sessionId) + URL=BASE_URL+"/logout?sessionId=" + str(sessionId) result = api_request(URL,"",False) if VERBOSE: print result + "\n" @@ -110,7 +112,7 @@ def api_login(): global sessionId, customerId SIMYOPASS = simyopass() - URL="https://api.simyo.es/api/login?" + URL=BASE_URL+"/login?" data = "user=" + USERNAME + "&password=" + SIMYOPASS + "&apiSig=null" result = api_request(URL,data) if VERBOSE: print result + "\n" @@ -121,7 +123,7 @@ def api_login(): def subscriptions(): global registerDate, mainProductId, billCycleType, msisdn, subscriberId, payType - URL="https://api.simyo.es/api/subscriptions/" + str(customerId) + "?sessionId=" + str(sessionId) + URL=BASE_URL+"/subscriptions/" + str(customerId) + "?sessionId=" + str(sessionId) result = api_request(URL) if VERBOSE: print result + "\n" @@ -144,7 +146,7 @@ def subscriptions(): sys.exit(0) def consumptionByCycle(billCycleCount=1): - URL="https://api.simyo.es/api/consumptionByCycle/" + str(customerId) + "?sessionId=" + str(sessionId) + "&msisdn=" + str(msisdn) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&billCycle=" + str(billCycle) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) + URL=BASE_URL+"/consumptionByCycle/" + str(customerId) + "?sessionId=" + str(sessionId) + "&msisdn=" + str(msisdn) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&billCycle=" + str(billCycle) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) result = api_request(URL) if VERBOSE: print result + "\n" @@ -229,7 +231,7 @@ def consumptionByCycle(billCycleCount=1): print "\nConsumo total: " + str(chargeTotal) + " EUR\n" def consumptionDetailByCycle(billCycleCount=1): - URL="https://api.simyo.es/api/consumptionDetailByCycle/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) + URL=BASE_URL+"/consumptionDetailByCycle/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType) result = api_request(URL) if VERBOSE: print result + "\n" @@ -286,7 +288,7 @@ def consumptionDetailByCycle(billCycleCount=1): def frequentNumbers(): month=billCycle # Parameter month is mandatory - URL="https://api.simyo.es/api/frequentNumbers/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&month=" + str(month) + URL=BASE_URL+"/frequentNumbers/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&month=" + str(month) result = api_request(URL) if VERBOSE: print result + "\n" @@ -299,7 +301,7 @@ def frequentNumbers(): def messages(): start=1 count=500 - URL="https://api.simyo.es/api/messages/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) + URL=BASE_URL+"/messages/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) result = api_request(URL) if VERBOSE: print result + "\n" @@ -321,7 +323,7 @@ def messages(): def voiceCalls(): start=1 count=500 - URL="https://api.simyo.es/api/voiceCalls/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) + URL=BASE_URL+"/voiceCalls/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&billCycle=" + str(billCycle) + "®isterDate=" + str(registerDate) + "&start=" + str(start) + "&count=" + str(count) result = api_request(URL) if VERBOSE: print result + "\n" @@ -350,7 +352,7 @@ def rechargeHistory(): startDate=registerDate endDate = time() endDate = int(endDate) * 1000 - URL="https://api.simyo.es/api/rechargeHistory/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&startDate=" + str(startDate) + "&endDate=" + str(endDate) + URL=BASE_URL+"/rechargeHistory/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + "&startDate=" + str(startDate) + "&endDate=" + str(endDate) result = api_request(URL) if VERBOSE: print result + "\n" @@ -365,7 +367,7 @@ def rechargeHistory(): print '{0}\t\t{1}'.format(date, fee) def mgmHistory(): - URL="https://api.simyo.es/api/mgmHistory/" + str(customerId) + "?sessionId=" + str(sessionId) + URL=BASE_URL+"/mgmHistory/" + str(customerId) + "?sessionId=" + str(sessionId) result = api_request(URL) if VERBOSE: print result + "\n" @@ -379,7 +381,7 @@ def mgmHistory(): print "TOTAL DISPONIBLE: " + str(totalAvailablePoints) def invoiceList(): - URL="https://api.simyo.es/api/invoiceList/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) + URL=BASE_URL+"/invoiceList/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "®isterDate=" + str(registerDate) result = api_request(URL) if VERBOSE: print result + "\n" @@ -408,7 +410,7 @@ def downloadInvoice(): print "Can't find invoice with id = " + str(reqInvoiceId) sys.exit(1) - URL="https://api.simyo.es/api/downloadInvoice?sessionId=" + str (sessionId) + "&invoiceNO=" + str(invoiceNO) + "&invoiceId=" + str(invoiceId) + URL=BASE_URL+"/downloadInvoice?sessionId=" + str (sessionId) + "&invoiceNO=" + str(invoiceNO) + "&invoiceId=" + str(invoiceId) result = api_request(URL) if VERBOSE: print result + "\n" From ccec9e49e5b4a67a75c93dc74f79637448d28468 Mon Sep 17 00:00:00 2001 From: Alexandre Dumont aka Adlx Date: Sun, 22 Sep 2019 20:26:37 +0200 Subject: [PATCH 3/4] Update README.md --- simyo/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/simyo/README.md b/simyo/README.md index fe3e12c..528caad 100644 --- a/simyo/README.md +++ b/simyo/README.md @@ -2,18 +2,18 @@ (reverse engineered from the com.simyo mobile app) - The password used by the API is your Simyo password encripted using -TripleDES with this key: `25d1d4cb0a08403e2acbcbe0f25a2` +TripleDES with this key: `TFq2VBDo3BizNAcPEw1vB7i5` - All requests to the API have a signature which is sent in the parameter "`apiSig=xxxx`", this signature is calculated like this: 1. convert to lowercase the complete request URL except the apiSig parameter - 2. concatenate the string "`f25a2s1m10`" + the lowercased URL + 2. concatenate the string "`BHqCzYg8BAmZ`" + the lowercased URL 3. the signature is obtained by computing the HMAC-SHA256 hash of the -string obtained in the previous step, using the key "`f25a2s1m10`". +string obtained in the previous step, using the key "`BHqCzYg8BAmZ`". - All api requests need the parameter "`publicKey=xxxx`", the value of -this public key is: `a654fb77dc654a17f65f979ba8794c34` +this public key is: `1SCOPDqVeSPjTKy` The rest is a piece of cake, make the request and parse the received json response. From b4b5d38476e7392fd8204bce4b9a4e1e095241bb Mon Sep 17 00:00:00 2001 From: Alexandre Dumont aka Adlx Date: Sun, 22 Sep 2019 20:28:34 +0200 Subject: [PATCH 4/4] Update simyo app keys in script --- simyo/simyo.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simyo/simyo.py b/simyo/simyo.py index f009d6e..aa1688b 100755 --- a/simyo/simyo.py +++ b/simyo/simyo.py @@ -32,11 +32,11 @@ BASE_URL = "https://api.simyo.es/simyo-api" def getApiSig(url): - dig = hmac.new(b'f25a2s1m10', msg='f25a2s1m10' + url.lower(), digestmod=hashlib.sha256).digest() + dig = hmac.new(b'BHqCzYg8BAmZ', msg='BHqCzYg8BAmZ' + url.lower(), digestmod=hashlib.sha256).digest() return url + "&apiSig=" + dig.encode('hex') def simyopass(): - k = pyDes.triple_des("25d1d4cb0a08403e2acbcbe0", pyDes.ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) + k = pyDes.triple_des("TFq2VBDo3BizNAcPEw1vB7i5", pyDes.ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5) d = urllib.quote(base64.b64encode(k.encrypt(PASSWORD)) + '\n') #print "Encrypted: %r" % d #print "Decrypted: %r" % k.decrypt(base64.b64decode(urllib.unquote(d))) @@ -63,7 +63,7 @@ def epoch2date(timestamp, format='%d/%m/%Y'): return datetime.datetime.fromtimestamp(int(timestamp)).strftime(format) def api_request(url, data="", check=True): - kPublicKey="a654fb77dc654a17f65f979ba8794c34" + kPublicKey="1SCOPDqVeSPjTKy" if url[-1:] == "?": url=url + "publicKey=" + kPublicKey