I'm using Twilio Verify for React Native and I'm getting an error (log below) when using their snippet to create a Factor:
export async function createTwilioVerifyFactor(identity) {
const pushToken = await messaging().getToken()
const accessTokenResponse = await getTwilioVerifyAccessToken(identity)
const hashedIdentity = accessTokenResponse.identity
const accessToken = accessTokenResponse.token
try {
const factor = await TwilioVerify.createFactor(
new PushFactorPayload(
// factor name
Device.deviceName ?? 'Unknown Device',
Constants.manifest.extra.twilioVerifyServiceSid,
hashedIdentity,
pushToken,
accessToken
)
)
if (!factor.sid) throw new Error('Failed to create factor')
return factor
} catch (e) { console.log(JSON.stringify(e, null, 2) }
}
I made sure none of the required values are null
/undefined
, but I'm still getting an error.
Android devices give no trouble, but iOS devices do. The try / catch
block results in the following log:
{
"nativeStackAndroid": [
{
"lineNumber": 95,
"file": "FactorAPIClient.kt",
"methodName": "invoke",
"class": "com.twilio.verify.api.FactorAPIClient$create$2"
},
{
"lineNumber": 61,
"file": "FactorAPIClient.kt",
"methodName": "invoke",
"class": "com.twilio.verify.api.FactorAPIClient$create$2"
},
{
"lineNumber": 68,
"file": "NetworkAdapter.kt",
"methodName": "execute",
"class": "com.twilio.verify.networking.NetworkAdapter"
},
{
"lineNumber": 89,
"file": "FactorAPIClient.kt",
"methodName": "create",
"class": "com.twilio.verify.api.FactorAPIClient"
},
{
"lineNumber": 49,
"file": "FactorRepository.kt",
"methodName": "create",
"class": "com.twilio.verify.domain.factor.FactorRepository"
},
{
"lineNumber": 87,
"file": "PushFactory.kt",
"methodName": "create",
"class": "com.twilio.verify.domain.factor.PushFactory"
},
{
"lineNumber": 55,
"file": "FactorFacade.kt",
"methodName": "invoke",
"class": "com.twilio.verify.domain.factor.FactorFacade$createFactor$1"
},
{
"lineNumber": 43,
"file": "FactorFacade.kt",
"methodName": "invoke",
"class": "com.twilio.verify.domain.factor.FactorFacade$createFactor$1"
},
{
"lineNumber": 68,
"file": "Executor.kt",
"methodName": "run",
"class": "com.twilio.verify.threading.Task"
},
{
"lineNumber": 1167,
"file": "ThreadPoolExecutor.java",
"methodName": "runWorker",
"class": "java.util.concurrent.ThreadPoolExecutor"
},
{
"lineNumber": 641,
"file": "ThreadPoolExecutor.java",
"methodName": "run",
"class": "java.util.concurrent.ThreadPoolExecutor$Worker"
},
{
"lineNumber": 929,
"file": "Thread.java",
"methodName": "run",
"class": "java.lang.Thread"
}
],
"userInfo": null,
"message": "{60401} Exception while calling the API",
"code": "EUNSPECIFIED",
"line": 5737,
"column": 45,
"sourceURL": "http://localhost:8081/index.bundle?platform=android&dev=true&minify=false&app=my.app&modulesOnly=false&runModule=true"
}
Am I potentially doing something wrong?
I finally found an answer to why this code was not working on iOS. My mistake was that I was trying to use a FCM token where I should have used an APNs token. As for Android, the same implementation just worked all of a sudden so I'm updating my question's title.
I created a helper function to get the PNs token depending on the platform using the FCM token as fallback.
import { Platform } from 'react-native'
import messaging from '@react-native-firebase/messaging'
export default async function getPushNotificationsToken() {
if (Platform.OS === 'ios') {
const token = await messaging().getAPNSToken()
if (token) return token
}
return messaging().getToken()
}
And I replaced this line in my initial code:
const pushToken = await messaging().getToken()
const pushToken = await getPushNotificationsToken()