Has anyone had success using Twilio with Micropython on an 8266? I've tested the below in pyton3 and can get it to successfully send a text message. However, when I port it over to micropython (below), the message fails. I went back to the urequests library, which is where I'm getting the failure, and saw that its failing because its passing the data as a dictionary (it fails on row 79). I tried changing it to pass as a string, but then it seems the data isn't sent to Twilio.
Python3 Implementation
import requests
account_sid = "sid"
auth_token = "token"
url = "https://api.twilio.com/2010-04-01/Accounts/" + account_sid + "/Messages.json"
data = {'From': '+18005551234', 'To': '+18005551234', 'Body': 'Text Message'}
try:
resp = requests.post(url=url, data=data, auth=requests.auth.HTTPBasicAuth(account_sid, auth_token))
print(resp.status_code)
except Exception as exc:
print("\nException occured.")
sys.print_exceptin(exc)
Micropython Implementation
import urequests
import ubinascii
account_sid = "sid"
auth_token = "token"
url = "https://api.twilio.com/2010-04-01/Accounts/" + account_sid + "/Messages.json"
data = {'From': '+18005551234', 'To': '+18005551234', 'Body': 'Text Message'}
login = ubinascii.b2a_base64(account_sid.encode('utf8') + b':' + auth_token.encode('utf8'))
headers = {'Authorization': b'Basic ' + login, 'Content-Type': 'application/x-www-form-urlencoded', 'WWW - Authenticate': 'Basic realm = "Twilio API'}
try:
resp = urequests.post(url=url, data=data, headers=headers)
print(resp.status_code)
except Exception as exc:
print("\nException occured.")
sys.print_exceptin(exc)
EDIT: So it seems that its been answered here: Sending SMS in twilio returns 21603 : A 'From' number is required, but even modifying my data, I can't get the message to actually transmit. I've modified the data field to be "To=%2B18005551234&From=%2B18005551234&Body=Test", but that seems to fail as well.
Per the excellent support at Twilio, the one line that needs to be added is
login = login[:-1]
There is a newline character at the end of the base64 encoded login and this needs to be stripped out.
Related
I have a hobby Python/Flask web application on PythonAnywhere.com to develop functionality that Spotify doesn't natively support. My web app works as expected after manually reload the web app (via the "Web" tab on PythonAnywhere). However, the problem I'm encountering is that after a period of time, when API calls are made via the front-end web pages, an "Internal Server Error" is returned.
I traced the problem and found the calls to the Spotify APIs were returning a 401 error response after about an hour - and then found that Spotify access tokens only last 1 hour.
One troubleshooting theory was that maybe pythonanywhere.com was only running the code to refresh my access tokens once (when reloading the web app), so then they would expire after 60 minutes. So I tried making the access token refresh into a function, and then calling that function from other functions that make the API calls. But this didn't work, but here's below is my code to show what I did.
My only remaining theory now is that the web server only gets the access tokens once (when the web server is refreshed) - but I'm not quite sure how to troubleshoot that.
Any thoughts on that theory, or other avenues I should explore so that I don't need to manually restart the web server to get my app to work?
set variables
AUTH_URL = 'https://accounts.spotify.com/api/token'
BASE_URL = 'https://api.spotify.com/v1/'
Code to get access token and return headers for the API call
auth_response = requests.post(AUTH_URL, {
'grant_type': 'client_credentials',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
})
def setHeaders():
try:
auth_response.raise_for_status()
except requests.exceptions.HTTPError as e:
print("!!!Error setting auth_response. System detail:")
print(e)
raise
# convert the response to JSON
auth_response_data = auth_response.json()
# save the access token
access_token = auth_response_data['access_token']
headers = {
'Authorization': 'Bearer {token}'.format(token=access_token)
}
return headers
function that makes the call to Spotify API that returns all playlist for a user:
#API GET link: https://api.spotify.com/v1/users/{user_id}/playlists
def getRawPlaylistMetadata(username,offset_value=0):
headers = setHeaders()
r_list = []
result_limit = 50
#print(offset_value)
params = {'offset': offset_value,
'limit': result_limit}
r = requests.get(BASE_URL + 'users/' + username + '/playlists', \
headers=headers,params=params)
response_code = str(r.status_code)
sys.stderr.write("\nr response code=" + response_code + "\n\n")
r = r.json()
try:
r_list = r['items']
except KeyError:
print("Getting all of Spotify user's playlist metadata failed.")
if len(r_list) < result_limit:
#print(len(r_list))
return r_list
return r_list + getRawPlaylistMetadata(username,offset_value + len(r_list))
I'm not sure how running it in the terminal does not cause the same issue, as your function doesn't even refresh the session:
# REQUEST EXECUTED HERE
auth_response = requests.post(AUTH_URL, {
'grant_type': 'client_credentials',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
})
def setHeaders():
# Function ran here
# the request is not re-executed
...
So you should probably put it inside the function:
def setHeaders():
auth_response = requests.post(AUTH_URL, {
'grant_type': 'client_credentials',
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
})
...
Then, to keep re-authenticating while running the Flask server, I recommend using a Thread:
from time import sleep
def reauth():
while True:
setHeaders()
sleep(30 * 60) # Sleep for half an hour, then re-authenticate
t = Thread(target=reauth)
t.start()
This would keep it running in parallel with the Flask server, and would keep calling it to reauthenticate the client every half an hour (obviously configurable, but should be under the 1 hour limit for Spotify's authentication expiry).
I am trying to use twilio pay in python. I am able to call the pay function properly and the entire card sequence goes very well. However, we are unable to collect the post parameters. I have tried to create a new route and trying to gather the post data but it is coming empty.
#app.route('/payment', methods=['GET', 'POST'])
def payment():
resp = VoiceResponse()
print('paymentmethod')
shippingid = request.args['shippingnumber'] or 0
amount = request.args['pay'] or 0
print('shippingid',shippingid)
print('amount',amount)
resp.say('Calling Twilio Pay')
resp.pause(1)
resp.pay(charge_amount=amount,action='/confirmpayment')
return str(resp)
#app.route('/confirmpayment', methods=['GET', 'POST'])
def confirmpayment():
resp = VoiceResponse()
multi_dict = request.args
print(multi_dict)
print(resp)
resp.pause(1)
return str(resp)
'''
Any suggestions would be appreciated.
In Flask, request.args is the parsed URL parameters. When Twilio makes a webhook request to your application as a POST request, the parameters will be sent as part of the body.
Twilio sends webhook requests as form encoded URL parameters you can use request.form to retrieve this data. Like this:
#app.route('/confirmpayment', methods=['GET', 'POST'])
def confirmpayment():
resp = VoiceResponse()
multi_dict = request.form
print(multi_dict)
print(resp)
There are already topics on this topic, but I have not been able to solve the problem on my side.
I develop a driver of auth for AdonisJS Ally and Tumblr, I get this error after the callback. However, oAuthToken, requestToken.oAuthTokenSecret and oAuthVerifier are correct (at least, I think).
The response is:
error { statusCode: 401, data: 'oauth_signature does not match
expected value' }
The request token URL:
https://www.tumblr.com/oauth/request_token?oauth_consumer_key=Vv3XfKpkZAXAehLxk9h76cjPkUyq7iDnqMjmEKwqKrOriGSVoG&oauth_nonce=fd47a26a06ceb6ce20121bc98ac78a01&oauth_signature=Hkhvn1n5kgjg9P0IeKwvqKT9j3I%3D&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1323327331&oauth_version=1.0
var request = require("request");
var oauth ={
consumer_key: "****************************",
consumer_secret: "****************************"
};
var url = 'https://www.tumblr.com/oauth/request_token'
request.post({url:url, oauth:oauth}, function (e, r, body) {
var temp1 = body.split("&");
var auth_token=temp1[0].split("=")[1];
var auth_secret=temp1[1].split("=")[1];
var tokens=[auth_token,auth_secret];
console.log(temp1)
cb(undefined,{d:tokens});
})
this code worked to me, try this.
There is no proper documentation for tumblr, but from the doc what i understood is there are 3 ways to get authenticated in tumblr and receive auth_token and auth_token secret the above code might not work because there is change of auth_nonce and auth_signature and hence you receive the error as
oauth_signature does not match expected value so i would suggest to use my method to generate the auth_token and auth_token_secret. this code works without adding any signature and nonce
In a case i have to send SMS with two whitespaces at the beginning of the message content as like below
setparam 3003:70eac;
This is for some device configuration. But while receiving the SMS it is
setparam 3003:70eac;
The whitespaces are gone.
This is how i send the SMS with php helper library
$client = new Client($account_sid, $auth_token);
$client->messages->create(
'<to_number>',
array(
'from' => '<from_number>',
'body' => ' setparam 3003:70eac;'
)
);
I had also tried by sending as encoded like below
%20%20setparam%203003%3A70eac%3B
This results without parsing
%20%20setparam%203003%3A70eac%3B
Any help will be great support to me.
We couldn't use whitspaces normaly while sending SMS in Twilio or Plivo, as those were trimmed automatically. But can be send by escaping the unicode value of whitspace in the message.
Examples:
Python
from twilio.rest import Client
# Your Account SID from twilio.com/console
account_sid = "<twilio_sid>"
# Your Auth Token from twilio.com/console
auth_token = "<twilio_token>"
client = Client(account_sid, auth_token)
message = client.messages.create(
to="<to_number>",
from_="<from_number>",
body="\U00002001\U00002001Whitspace at front")
print(message.sid)
JSON
{
"src" : "<from_number>",
"dst" : "<to_number>",
"text" : "\u0020\u0020Whitspace at front",
"type" : "sms",
"method" : "POST"
}
PHP
<?php
// Required if your environment does not handle autoloading
require __DIR__ . '/vendor/autoload.php';
// Use the REST API Client to make requests to the Twilio REST API
use Twilio\Rest\Client;
// Your Account SID and Auth Token from twilio.com/console
$sid = 'ACfe1c3f0e87c51710e95e842f2e71922b';
$token = 'your_auth_token';
$client = new Client($sid, $token);
// Use the client to do fun stuff like send text messages!
$client->messages->create(
// the number you'd like to send the message to
'+15558675309',
array(
// A Twilio phone number you purchased at twilio.com/console
'from' => '+15017250604',
// the body of the text message you'd like to send
'body' => "\020\020Whitspace at front"
)
);
You can see the message body is denoted with double quotes(") . That is important in PHP. Denoting with single quote(') won't work. The different quote usages in PHP and Double quoted strings.
More reference links for PHP.
String Functions
Converting to and from ASCII
Result:
' Whitspace at front'
In twilio you will have to use Unicode 'Punctuation Space' which is '\2008'. '\0020' wont work.
Here is my url which i have to insert/make hyperlink of .
http://192.168.10.183:8080/xyzadsfgrghrh//Request?Key=eform_renderer&OwnerType=Prj&OwnerID=79061&ItemType=Aci&ItemID=20032785&ActionToPerform=View&PopupMode=Y&WindowOpenOnSave=Y&ALLOWREADACCESS=Y&FromECRGetUrl=Y&GetUrlReqParams=&ParentItemId=20032785&childProcessId=qq0k5l04Gd92FFB384jODPfA93D93D.
The limit is of 255 characters.So how can i insert such a long url in my Kingsoft Writer ?
To get the shortened url dynamically from google API, first go here create your key or alternatively you can create one from credentails page for authorization so that google can verify you can send the shortened url.
Here is the sample code in python as how to proceed:
import requests
url = "https://www.googleapis.com/urlshortener/v1/url?key=YOUR_KEY"
headers = { 'Content-Type': 'application/json'}
payload = {"longUrl": "YOUR URL"}
r = requests.post(url, headers= headers, json=payload)
After success you will receive response like as mentioned on google-
{
"kind": "urlshortener#url",
"id": "YOUR SHORTENED URL",
"longUrl": "YOUR LONG URL"
}
Hope it helps.