C# 使用C通过PlumVoice IVR创建出站活动#

C# 使用C通过PlumVoice IVR创建出站活动#,c#,ivr,C#,Ivr,我使用PlumVoice IVR系统已经有一段时间了,现在需要利用它们的出站呼叫功能。我需要在C#中完成这项工作,但由于缺乏文档化的C#支持,我很难确定如何进行。以下是我的项目的细节: 我解析文件中的数据(比如电话号码),然后用文件的数据拨打这些号码 它不是一个MVC项目(你可以看到,如果它是MVC项目,它会变得多么容易) 现在我需要: 使用queuecall web服务创建呼叫[Campaign] 创造 呼叫后处理的报告功能 我已经为我的项目编译并测试了必要的代码,它完全按照预期工作(显然

我使用PlumVoice IVR系统已经有一段时间了,现在需要利用它们的出站呼叫功能。我需要在C#中完成这项工作,但由于缺乏文档化的C#支持,我很难确定如何进行。以下是我的项目的细节:

  • 我解析文件中的数据(比如电话号码),然后用文件的数据拨打这些号码
  • 它不是一个MVC项目(你可以看到,如果它是MVC项目,它会变得多么容易)
现在我需要:

  • 使用queuecall web服务创建呼叫[Campaign]
  • 创造 呼叫后处理的报告功能

  • 我已经为我的项目编译并测试了必要的代码,它完全按照预期工作(显然,直到客户更新需求)


    WebRequest方法

    public static void PlumOutboundQueuecall(ObjectModel model)
    {
        // Create a request for the URL.        
        WebRequest request = WebRequest.Create(Settings.IvrOutboundApi); //ease of editing/reusability //http://outbound.plumvoice.com/webservice/queuecall.php
        request.Method = "POST";
        //request.ContentType = "multipart/form-data"; //This is only if I choose to upload a [.csv] file of phone numbers
        request.ContentType = "application/x-www-form-urlencoded";
    
        // I used http://stackoverflow.com/questions/14702902/post-form-data-using-httpwebrequest as reference for proper encoding
        StringBuilder postData = new StringBuilder();
        postData.Append(HttpUtility.UrlEncode("login") + "=" +              HttpUtility.UrlEncode("<MY_EMAIL_FOR_PLUM>") + "&");
        postData.Append(HttpUtility.UrlEncode("pin") + "=" +                HttpUtility.UrlEncode("<MY_PIN_FOR_PLUM>") + "&");
        postData.Append(HttpUtility.UrlEncode("phone_number") + "=" +       HttpUtility.UrlEncode(model.PhoneNumber) + "&");
        postData.Append(HttpUtility.UrlEncode("start_url") + "=" +          HttpUtility.UrlEncode("<MY_vXML_AS_ASPX_PAGE_SHOWN_BELOW>") + "&"); //"http://ip_address/MY_ASPX_PAGE.aspx"
        postData.Append(HttpUtility.UrlEncode("call_parameters") + "=" +    HttpUtility.UrlEncode("<THE_PHONE_MESSAGE_TEXT_TO_BE_READ>") + "&"); //includes 'model' properties
        postData.Append(HttpUtility.UrlEncode("result_url") + "=" +         HttpUtility.UrlEncode("<MY_RESULT_URL_AS_ASMX_PAGE_SHOWN_BELOW>")); //"http://ip_address/MY_ASMX_PAGE.asmx/PlumOutboundCallback"
    
        ASCIIEncoding ascii = new ASCIIEncoding();
        byte[] postBytes = ascii.GetBytes(postData.ToString());
    
        // add post data to request
        Stream postStream = request.GetRequestStream();
        postStream.Write(postBytes, 0, postBytes.Length);
        postStream.Flush();
        postStream.Close();
    
        // Get response
        // Used Fiddler to deconstruct/reverse-engineer
        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
        {
            StreamReader reader = new StreamReader(response.GetResponseStream()); // Get the response stream  
            string result = reader.ReadToEnd(); // Read the contents and return as a string  
    
            if (result.Contains("failed"))
            {
                // Whatever error handling you want to do if your "result_url" page throws an error. I used this extensively while testing the proper way to set this up
            }
        }
    }
    
    publicstaticvoid PlumOutboundQueuecall(ObjectModel模型)
    {
    //为URL创建一个请求。
    WebRequest=WebRequest.Create(Settings.ivroutbundapi);//易于编辑/重用//http://outbound.plumvoice.com/webservice/queuecall.php
    request.Method=“POST”;
    //request.ContentType=“multipart/form data”;//仅当我选择上载电话号码的[.csv]文件时才使用此选项
    request.ContentType=“application/x-www-form-urlencoded”;
    //我曾经http://stackoverflow.com/questions/14702902/post-form-data-using-httpwebrequest 作为正确编码的参考
    StringBuilder postData=新建StringBuilder();
    postData.Append(HttpUtility.UrlEncode(“登录”)+“=”+HttpUtility.UrlEncode(“”+“&”);
    postData.Append(HttpUtility.UrlEncode(“pin”)+“=”+HttpUtility.UrlEncode(“”+“&”);
    postData.Append(HttpUtility.UrlEncode(“电话号码”)+“=”+HttpUtility.UrlEncode(model.PhoneNumber)+“&”);
    postData.Append(HttpUtility.UrlEncode(“start_url”)+“=”+HttpUtility.UrlEncode(“+”&”);/”http://ip_address/MY_ASPX_PAGE.aspx"
    postData.Append(HttpUtility.UrlEncode(“调用_参数”)+“=”+HttpUtility.UrlEncode(“+”&”);//包括“模型”属性
    postData.Append(HttpUtility.UrlEncode(“结果url”)+“=”+HttpUtility.UrlEncode(”);/“http://ip_address/MY_ASMX_PAGE.asmx/PlumOutboundCallback"
    ascienceoding ascii=新的ascienceoding();
    byte[]postBytes=ascii.GetBytes(postData.ToString());
    //将post数据添加到请求
    Stream postStream=request.GetRequestStream();
    postStream.Write(postBytes,0,postBytes.Length);
    postStream.Flush();
    postStream.Close();
    //得到回应
    //使用Fiddler解构/逆向工程
    使用(HttpWebResponse=request.GetResponse()作为HttpWebResponse)
    {
    StreamReader=新的StreamReader(response.GetResponseStream());//获取响应流
    string result=reader.ReadToEnd();//读取内容并作为字符串返回
    if(result.Contains(“failed”))
    {
    //如果你的“result\u url”页面抛出错误,无论你想做什么错误处理。我在测试正确的设置方法时广泛使用了这个方法
    }
    }
    }
    

    My.vxml文件为.aspx页面。这将被发布并放在服务器上(“ip地址/MY\u ASPX\u PAGE.ASPX”)

    
    
    我知道这似乎是写错了,但请忽略它(“请求”将显示为红色)


    我的“结果url”是一个.asmx页面。它被发布并放在服务器上(“ip地址/MY\u ASMX\u页面.ASMX/PlumOutboundCallback”)

    //
    ///OutboundResultUrl的摘要说明
    /// 
    [WebService(命名空间=”http://tempuri.org/")]
    [WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    //要允许使用ASP.NET AJAX从脚本调用此Web服务,请取消注释以下行。
    //[System.Web.Script.Services.ScriptService]
    公共类OutboundResultUrl:System.Web.Services.WebService
    {
    [网络方法]
    公共字符串PlumOutboundCallback()
    {
    bool heartbeat=string.IsNullOrEmpty(HttpContext.Current.Request.Form[“phone_number”]);//Plum实现心跳并检查此“result_url”是否工作。“phone_number”必须存在,以便我处理呼叫(duh)的数据,因此我检查它是否为null或空
    如果(!心跳)
    {
    //BusinessLayer.OutboundCallback model=new BusinessLayer.OutboundCallback{phone_number=HttpContext.Current.Request.Form[“phone_number”]、message_reference=HttpContext.Current.Request.Form[“call_id”]、message_reference=HttpContext.Current.Request.Form[“result”],callee_type=HttpContext.Current.Request.Form[“callee_type”],truments=Convert.ToInt32(HttpContext.Current.Request.Form[“truments”]),last_-trument_-timestamp=HttpContext.Current.Request.Form[“duration”],//如果你喜欢这样的话
    BusinessLayer.OutboundCallback model=新建BusinessLayer.OutboundCallback();
    model.phone_number=HttpContext.Current.Request.Form[“phone_number”];
    model.message_reference=HttpContext.Current.Request.Form[“message_reference”];
    model.call_id=Convert.ToInt32(HttpContext.Current.Request.Form[“call_id”]);
    model.result=HttpContext.Current.Request.Form[“result”];
    model.callee_type=HttpContext.Current.Request.Form[“callee_type”];
    model.attempts=Convert.ToInt32(HttpContext.Current.Request.Form[“attempts”]);
    model.last\u trunt\u timestamp=HttpContext.Current.Request.Form[“last\u trunt\u timestamp”];
    model.duration=转换
    
    <%Response.ContentType = "text/xml"%>
    <?xml version="1.0" ?>
    <vxml version="2.0">
        <form>
            <block>
                <prompt>
                    <%-- Set the "Custom Call Parameters" to be THE_PHONE_MESSAGE_TEXT_TO_BE_READ --%>
                    <%=request.form("call_parameters") %>  <%-- This says "Cannot resolve symbol 'request'" but just ignore it --%>
                </prompt>
            </block>
        </form>
    </vxml> 
    
    /// <summary>
    /// Summary description for OutboundResultUrl
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class OutboundResultUrl : System.Web.Services.WebService
    {
        [WebMethod]
        public string PlumOutboundCallback()
        {
            bool heartbeat = string.IsNullOrEmpty(HttpContext.Current.Request.Form["phone_number"]); //Plum implements a heartbeat and checks that this 'result_url' is working. A 'phone_number' has to exist in order for me to process the data FOR a call (duh) so I check to see if it is null or empty
    
            if (!heartbeat)
            {
                //BusinessLayer.OutboundCallback model = new BusinessLayer.OutboundCallback { phone_number = HttpContext.Current.Request.Form["phone_number"], message_reference = HttpContext.Current.Request.Form["message_reference"], call_id = Convert.ToInt32(HttpContext.Current.Request.Form["call_id"]), result = HttpContext.Current.Request.Form["result"], callee_type = HttpContext.Current.Request.Form["callee_type"], attempts = Convert.ToInt32(HttpContext.Current.Request.Form["attempts"]), last_attempt_timestamp = HttpContext.Current.Request.Form["last_attempt_timestamp"], duration = Convert.ToInt32(HttpContext.Current.Request.Form["duration"]) }; //if you're into this sort of thing
                BusinessLayer.OutboundCallback model = new BusinessLayer.OutboundCallback();
                model.phone_number = HttpContext.Current.Request.Form["phone_number"];
                model.message_reference = HttpContext.Current.Request.Form["message_reference"];
                model.call_id = Convert.ToInt32(HttpContext.Current.Request.Form["call_id"]);
                model.result = HttpContext.Current.Request.Form["result"];
                model.callee_type = HttpContext.Current.Request.Form["callee_type"];
                model.attempts = Convert.ToInt32(HttpContext.Current.Request.Form["attempts"]);
                model.last_attempt_timestamp = HttpContext.Current.Request.Form["last_attempt_timestamp"];
                model.duration = Convert.ToInt32(HttpContext.Current.Request.Form["duration"]);
    
                string stringResultData = string.Format("Collecting parameters posted into here. <br />Phone Number = {0}, <br />Message Reference = {1}, <br />Call ID = {2}, <br />Result = {3}, <br />Callee Type = {4}, <br />Attempts = {5}, <br />Last Attempt Timestamp = {6}, <br />Duration = {7}",
                                        model.phone_number, model.message_reference, model.callee_type, model.result, model.callee_type, model.attempts, model.last_attempt_timestamp, model.duration); //this is for debugging/testing purposes
    
                try
                {
                    // Whatever you want to do with this data! Send it in an email, Save it to the database, etc.
                }
                catch (Exception error)
                {
                    Console.WriteLine("Error: " + error);
                }
            }
    
            return "Plum Outbound API has posted back to this 'result_url' successfully.";
        }
    }