Forum Discussion
Create peer-to-peer PSTN call with service hosted media - Not working -Call source identity invalid
Hello,
I am working for a customer to implement Example 9: Create peer-to-peer PSTN call with service hosted media
The licenses we have purchased for Azure Intra user(email address removed for privacy reasons) are
1. Microsoft 365 E3
2.Teams Phone with Calling Plan (country zone 1 - US)
Also i have created a resource account in https://admin.teams.microsoft.com/
Username : email address removed for privacy reasons
Assigned license : Microsoft Teams Phone Resource Account
Already We have Purchased a number from https://admin.teams.microsoft.com/
Voice-->Phone --> i can see a number like +175xxxxx(But this is unassigned as of now)
My Questions :
1. To do a peer to Peer PSTN call do we really need a Resource Account user? or can i remove it? we are focused only on the outgoing call at the moment.
2. Should we assign the purchased Phone number to E3 licensee assigned user? or this Phone number should be assigned to Resource account user , i have waited for more than 24 hours and Phone number for some reason is not listing for the Resource user(But i have option to assign it to Teams Phone with Calling Plan User that i created)
The code doesnt work as well, so before digging into the code, i would like to ensure the configurations are setup properly . can someone help on this?
-
To make a peer-to-peer PSTN call, you don't necessarily need a Resource Account user. The Resource Account user is typically used for scenarios where you want to assign a phone number to a specific resource, such as a meeting room or a shared device. Since you are focused on outgoing calls at the moment, you can remove the Resource Account user if it's not required for your use case.
-
The purchased phone number can be assigned to either an E3 licensee assigned user or a Teams Phone with Calling Plan user. It depends on your specific requirements and how you want to manage the phone number. If you assign the phone number to an E3 licensee assigned user, that user will be able to make and receive calls using that number. On the other hand, if you assign the phone number to a Teams Phone with Calling Plan user, that user will have the calling plan associated with the phone number.
If you have waited for more than 24 hours and the phone number is not listing for the Resource Account user, it's possible that there might be some delay or issue with the assignment process. You can try assigning the phone number to the Teams Phone with Calling Plan user that you created and see if it gets listed for that user.
Thanks,
Prasad Das
------------------------------------------------------------------------------------------
If the response is helpful, please click "**Mark as Best Response**" and like it. You can share your feedback via Microsoft Teams Developer Feedback link.
-
- ChetanSharma-msftMicrosoft
Hello prasanth2023 - Thanks for raising your query.
We will look into it and let you know the updates.- prasanth2023Copper ContributorThanks ChetanSharma-msft looking forward for it.
The current state is like the phone number is assigned to Resource account, but still we are unable to make call via graph API via C#. we are getting the same error - call source identity Invalid- prasanth2023Copper Contributor
I am using the below PowerShell script to make the call. The calls are not receiving on the other end, But the call state shows as Established....
$TenantId = "bc2a8d6c-49d3-40ba-a541-XXXXXXX"$ClientId = "9cc48ef5-d9e7-40a7-8ed7-XXXXXXX"$ClientSecret = "Wm58Q~ecjJdkVWQzWKVSYoTsykcRvpmA67aXXXXXX"$TokenBody = @{Grant_Type = "client_credentials"Scope = "https://graph.microsoft.com/.default"Client_Id = $ClientIdClient_Secret = $ClientSecret}$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -Method POST -Body $TokenBody -ContentType "application/x-www-form-urlencoded"$AccessToken = $TokenResponse.access_token# Convert the AccessToken to a SecureString$SecureAccessToken = $AccessToken | ConvertTo-SecureString -AsPlainText -Force# Connect to Microsoft Graph using SecureStringConnect-MgGraph -AccessToken $SecureAccessToken$params = @{"@odata.type" = "#microsoft.graph.call"callbackUri = "https://bot.contoso.com/callback"source = @{"@odata.type" = "#microsoft.graph.participantInfo"identity = @{"@odata.type" = "#microsoft.graph.identitySet"applicationInstance = @{"@odata.type" = "#microsoft.graph.identity"displayName = "Calling Bot"id = "77c05ef4-9f20-4351-9590-XXXXXXXXX"}}countryCode = $nullendpointType = $nullregion = $nulllanguageId = $null}targets = @(@{"@odata.type" = "#microsoft.graph.invitationParticipantInfo"identity = @{"@odata.type" = "#microsoft.graph.identitySet"phone = @{"@odata.type" = "#microsoft.graph.identity"id = "+14086220061"}}})requestedModalities = @("audio")mediaConfig = @{"@odata.type" = "#microsoft.graph.serviceHostedMediaConfig"}tenantId = "bc2a8d6c-49d3-40ba-a541-XXXXXXXXXX"}New-MgCommunicationCall -BodyParameter $paramsHow to check and fix this issue? can you help?
- Prasad_Das-MSFTMicrosoft
-
To make a peer-to-peer PSTN call, you don't necessarily need a Resource Account user. The Resource Account user is typically used for scenarios where you want to assign a phone number to a specific resource, such as a meeting room or a shared device. Since you are focused on outgoing calls at the moment, you can remove the Resource Account user if it's not required for your use case.
-
The purchased phone number can be assigned to either an E3 licensee assigned user or a Teams Phone with Calling Plan user. It depends on your specific requirements and how you want to manage the phone number. If you assign the phone number to an E3 licensee assigned user, that user will be able to make and receive calls using that number. On the other hand, if you assign the phone number to a Teams Phone with Calling Plan user, that user will have the calling plan associated with the phone number.
If you have waited for more than 24 hours and the phone number is not listing for the Resource Account user, it's possible that there might be some delay or issue with the assignment process. You can try assigning the phone number to the Teams Phone with Calling Plan user that you created and see if it gets listed for that user.
Thanks,
Prasad Das
------------------------------------------------------------------------------------------
If the response is helpful, please click "**Mark as Best Response**" and like it. You can share your feedback via Microsoft Teams Developer Feedback link.
- prasanth2023Copper Contributor
Prasad_Das-MSFT yes the licenses are allotted as mentioned below. i am able to make calls from MS teams to my Phone number directly via MS teams . But not through Graph API.
- prasanth2023Copper Contributor
Prasad_Das-MSFT But the problem of establishing call is not yet solved
Poweshell code
# Securely storing the credentials $TenantId = "XXXXX-49d3-40ba-a541-4b63e8e0fdc5" $ClientId = "XXXXX-d9e7-40a7-8ed7-a915969a6833" $ClientSecret = ConvertTo-SecureString "XXXXXXXX" -AsPlainText -Force # Function to obtain an access token function Get-GraphAccessToken { param ( [Parameter(Mandatory = $true)][string]$TenantId, [Parameter(Mandatory = $true)][string]$ClientId, [Parameter(Mandatory = $true)][System.Security.SecureString]$ClientSecret ) $TokenBody = @{ Grant_Type = "client_credentials" Scope = "https://graph.microsoft.com/.default" Client_Id = $ClientId Client_Secret = [System.Net.NetworkCredential]::new("", $ClientSecret).Password } $TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -Method POST -Body $TokenBody -ContentType "application/x-www-form-urlencoded" return $TokenResponse.access_token } # Obtain Access Token $AccessToken = Get-GraphAccessToken -TenantId $TenantId -ClientId $ClientId -ClientSecret $ClientSecret # Convert the AccessToken to a SecureString $SecureAccessToken = $AccessToken | ConvertTo-SecureString -AsPlainText -Force # Connect to Microsoft Graph using SecureString Connect-MgGraph -AccessToken $SecureAccessToken # Prepare parameters for creating a call $params = @{ "@odata.type" = "#microsoft.graph.call" direction = "outgoing" subject = "call with application hosted media" callbackUri = "https://b744-14-142-211-86.ngrok-free.app/callback" source = @{ "@odata.type" = "#microsoft.graph.participantInfo" identity = @{ "@odata.type" = "#microsoft.graph.identitySet" applicationInstance = @{ "@odata.type" = "#microsoft.graph.identity" displayName = "PPCall" id = "525b3e87-1127-483a-bc43-0a99c51a8db0" } } } targets = @( @{ "@odata.type" = "#microsoft.graph.invitationParticipantInfo" identity = @{ "@odata.type" = "#microsoft.graph.identitySet" phone = @{ "@odata.type" = "#microsoft.graph.identity" id = "+14086220061" } } } ) requestedModalities = @("audio") mediaConfig = @{ "@odata.type" = "#microsoft.graph.serviceHostedMediaConfig" blob = "a.wav" } tenantId = $TenantId } # Error handling for creating a call try { $callResponse = New-MgCommunicationCall -BodyParameter $params $callId = $callResponse.Id Write-Host "Call created successfully. Call ID: $callId" } catch { Write-Error "Error in creating call: $_" }
Console Log:
The thread 0x5974 has exited with code 0 (0x0).
The thread 0x5c94 has exited with code 0 (0x0).
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:5001/callback application/json 406
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "OnIncomingBotCallUserRequestAsync", controller = "PlatformCall"}. Executing controller action with signature System.Threading.Tasks.Task OnIncomingBotCallUserRequestAsync() on controller Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController (VoiceRecorderAndPlaybackBot).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) - Validation state: Valid
VoiceRecorderAndPlaybackBot:Information: 2024-01-14T04:47:59.6223Z 526dabeb-988c-4177-ab2b-fa6f17766997 pid:16532 tid:60 (Bot.cs:270 NotificationProcessor_OnNotificationReceivedAsync):
{
"value": {
"$id": "1",
"$values": [
{
"changeType": "Updated",
"resourceUrl": "/communications/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resource": "/app/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resourceData": {
"callChainId": "526dabeb-988c-4177-ab2b-fa6f17766997",
"state": "Establishing",
"@odata.type": "#microsoft.graph.call"
},
"@odata.type": "#microsoft.graph.commsNotification"
}
]
}
}
{
"HttpLogData": {
"Method": "POST",
"Url": "https://localhost:5001/callback",
"Headers": [
"Scenario-Id: 526dabeb-988c-4177-ab2b-fa6f17766997",
"Client-Request-Id: e7ceecce-b081-4314-a1c7-7ab4358ffe45",
"X-Microsoft-Tenant: (redacted)"
],
"TransactionDirection": "Incoming",
"TraceType": "HttpRequest",
"TenantId": "00000000-0000-0000-0000-000000000000"
}
}Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot), returned result Microsoft.AspNetCore.Mvc.EmptyResult in 8.8178ms.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) in 11.6675ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 17.2779ms 202
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:5001/callback application/json 428
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "OnIncomingBotCallUserRequestAsync", controller = "PlatformCall"}. Executing controller action with signature System.Threading.Tasks.Task OnIncomingBotCallUserRequestAsync() on controller Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController (VoiceRecorderAndPlaybackBot).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) - Validation state: Valid
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:5001/callback application/json 792
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "OnIncomingBotCallUserRequestAsync", controller = "PlatformCall"}. Executing controller action with signature System.Threading.Tasks.Task OnIncomingBotCallUserRequestAsync() on controller Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController (VoiceRecorderAndPlaybackBot).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) - Validation state: Valid
VoiceRecorderAndPlaybackBot:Information: 2024-01-14T04:48:02.1600Z 526dabeb-988c-4177-ab2b-fa6f17766997 pid:16532 tid:49 (Bot.cs:270 NotificationProcessor_OnNotificationReceivedAsync):
{
"value": {
"$id": "1",
"$values": [
{
"changeType": "Updated",
"resourceUrl": "/communications/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resource": "/app/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resourceData": {
"callChainId": "526dabeb-988c-4177-ab2b-fa6f17766997",
"direction": "Outgoing",
"state": "Established",
"@odata.type": "#microsoft.graph.call"
},
"@odata.type": "#microsoft.graph.commsNotification"
}
]
}
}
{
"HttpLogData": {
"Method": "POST",
"Url": "https://localhost:5001/callback",
"Headers": [
"Scenario-Id: 526dabeb-988c-4177-ab2b-fa6f17766997",
"Client-Request-Id: 952cca9c-ac69-4901-9883-0c9836831c86",
"X-Microsoft-Tenant: (redacted)"
],
"TransactionDirection": "Incoming",
"TraceType": "HttpRequest",
"TenantId": "00000000-0000-0000-0000-000000000000"
}
}Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot), returned result Microsoft.AspNetCore.Mvc.EmptyResult in 9.2287ms.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) in 14.4217ms
VoiceRecorderAndPlaybackBot:Information: 2024-01-14T04:48:02.1637Z 526dabeb-988c-4177-ab2b-fa6f17766997 pid:16532 tid:63 (Bot.cs:270 NotificationProcessor_OnNotificationReceivedAsync):
{
"value": {
"$id": "1",
"$values": [
{
"changeType": "Updated",
"resourceUrl": "/communications/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resource": "/app/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resourceData": {
"callChainId": "526dabeb-988c-4177-ab2b-fa6f17766997",
"mediaState": {
"audio": "Active",
"@odata.type": "#microsoft.graph.callMediaState"
},
"state": "Established",
"@odata.type": "#microsoft.graph.call",
"meetingCapability": {
"@odata.type": "#microsoft.graph.meetingCapability",
"allowTranslatedCaptions": true,
"allowTranslatedTranscriptions": true,
"recorderAllowed": []
},
"meetingProperties": {
"@odata.type": "#microsoft.graph.meetingProperties",
"meetingLabel": "00000000-0000-0000-0000-000000000000"
},
"coOrganizers": []
},
"@odata.type": "#microsoft.graph.commsNotification"
}
]
}
}
{
"HttpLogData": {
"Method": "POST",
"Url": "https://localhost:5001/callback",
"Headers": [
"Scenario-Id: 526dabeb-988c-4177-ab2b-fa6f17766997",
"Client-Request-Id: c9944fa9-7eaf-4dfb-b54c-98c18c2778b7",
"X-Microsoft-Tenant: (redacted)"
],
"TransactionDirection": "Incoming",
"TraceType": "HttpRequest",
"TenantId": "00000000-0000-0000-0000-000000000000"
}
}Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 19.9873ms 202
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot), returned result Microsoft.AspNetCore.Mvc.EmptyResult in 9.9369ms.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) in 13.2163ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 17.533ms 202
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 POST https://localhost:5001/callback application/json 1057
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Route matched with {action = "OnIncomingBotCallUserRequestAsync", controller = "PlatformCall"}. Executing controller action with signature System.Threading.Tasks.Task OnIncomingBotCallUserRequestAsync() on controller Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController (VoiceRecorderAndPlaybackBot).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) - Validation state: Valid
VoiceRecorderAndPlaybackBot:Information: 2024-01-14T04:48:08.4273Z 526dabeb-988c-4177-ab2b-fa6f17766997 pid:16532 tid:49 (Bot.cs:270 NotificationProcessor_OnNotificationReceivedAsync):
{
"value": {
"$id": "1",
"$values": [
{
"changeType": "Deleted",
"resourceUrl": "/communications/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resource": "/app/calls/411f5700-550f-4cdb-a342-34f37a6ca70d",
"resourceData": {
"callChainId": "526dabeb-988c-4177-ab2b-fa6f17766997",
"resultInfo": {
"code": 200,
"message": "The conversation has ended. DiagCode: 200#1000003.@",
"subcode": 1000003,
"@odata.type": "#microsoft.graph.resultInfo"
},
"state": "Terminated",
"@odata.type": "#microsoft.graph.call",
"meetingCapability": {
"@odata.type": "#microsoft.graph.meetingCapability",
"allowTranslatedCaptions": true,
"allowTranslatedTranscriptions": true,
"recorderAllowed": []
},
"meetingProperties": {
"@odata.type": "#microsoft.graph.meetingProperties",
"meetingLabel": "00000000-0000-0000-0000-000000000000"
},
"coOrganizers": [],
"terminationSender": {
"application": {
"id": "56aa0a8f-4cd3-446b-8146-0023476a5ff2",
"@odata.type": "#microsoft.graph.identity"
},
"@odata.type": "#microsoft.graph.identitySet"
}
},
"@odata.type": "#microsoft.graph.commsNotification"
}
]
}
}
{
"HttpLogData": {
"Method": "POST",
"Url": "https://localhost:5001/callback",
"Headers": [
"Scenario-Id: 526dabeb-988c-4177-ab2b-fa6f17766997",
"Client-Request-Id: c7d98660-fe90-4948-a0cd-709a9d53ebf1",
"X-Microsoft-Tenant: (redacted)"
],
"TransactionDirection": "Incoming",
"TraceType": "HttpRequest",
"TenantId": "00000000-0000-0000-0000-000000000000"
}
}VoiceRecorderAndPlaybackBot:Information: 2024-01-14T04:48:08.4369Z 526dabeb-988c-4177-ab2b-fa6f17766997 pid:16532 tid:49 (Bot.cs:435 CleanupCall):
Cleaning up callVoiceRecorderAndPlaybackBot:Information: 2024-01-14T04:48:08.4397Z 526dabeb-988c-4177-ab2b-fa6f17766997 pid:16532 tid:49 (Bot.cs:449 CleanupCall):
File to be deleted does not exist.Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action method Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot), returned result Microsoft.AspNetCore.Mvc.EmptyResult in 18.4511ms.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sample.VoiceRecorderAndPlaybackBot.Controller.PlatformCallController.OnIncomingBotCallUserRequestAsync (VoiceRecorderAndPlaybackBot) in 21.3134ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 26.5816ms 202
The program '[16532] dotnet.exe' has exited with code 4294967295 (0xffffffff).
-