支持的 Web 服务

SOAP

Snippet 语言通过生成代理的流程支持基于 SOAP 的 Web 服务。必须使用 Studio 来生成代理,然后将代理作为 .NET DLL 保存至 CXone 文件系统中。所有 Web 服务代理必须保存至即将使用此代理的业务单位的根文件夹中。系统管理员可在业务单位 3 下创建一个代理以供共享使用,尽管到目前为止还没有在生产中这样操作。

基于 SOAP 的 Web 服务正在衰落,因为 RESTful Web 服务正在取而代之。我们的 SOAP Web 服务代理生成流程可能会在某个时候停止。在可预见的未来没有新的增强计划。

在代理生成过程中,某些功能被新增到代理对象中,以便它能够很好地配合 CXone 工作。其中一项新增功能是序列化成二进制流的能力。所有类型(包括代理)都必须能够序列化,以便 VC 冗余和脚本编组功能能够运转。因此 Studio 代理生成流程必不可少。

除序列化功能以外,还配置了代理,以便 VC 执行引擎在等待 Web 服务调用完成时能够正确地利用线程池。没有此项功能,VC 线程池将不能正确使用,结果可能导致客户受到负面影响。 使用正确的线程池非常关键。

Studio 流程新增的最后一项功能是跟踪 Web 服务使用情况的能力。当调用代理进行外部 Web 服务调用时,计数器和时间跟踪器会被用来记录使用情况和影响。每天,这些指标会数次保存到数据库表中,以供管理使用。

Uses

在 Snippet 中,USES 命令可以让 Snippet 包含 Web 服务代理 DLL 以便在 Snippet 中使用。此 DLL 文件必须位于文件服务器上当前业务单位的根文件夹中,或者位于业务单位 3 根文件夹中(供共享使用)。语法:

USES "<proxy>.dll"

示例:

USES "sf.dll" cStart="{now}" sforce=new SforceService() session=new SessionHeader() loginResult=sforce.login("demo@ucn.net",password6") sforce.sessionheadervalue=session session.sessionid=loginResult.sessionid sforce.url=loginresult.serverUrl t=new Task() t.ActivityDate=#"8/20/2050" t.Description="Call placed by {first }{Last}."t.Subject="Call @{cStart}" t.Status="Completed" t.CallType="Outbound" t.OwnerId=SF_Agent_ID t.ReminderDateTime="{cStart}" SWITCH Type { CASE "CON" { t.WhoId=SF_Obj_ID } CASE "LEA" { t.WhoId=SF_Obj_ID } CASE "ACC" { t.WhatId=SF_Obj_ID } CASE "OPP" { t.WhatId=SF_Obj_ID } CASE "CAS" { t.WhatId=SF_Obj_ID } } SaveResult=sforce.create(t)

注意:在平台上使用任何 Web 服务代理 DLL 之前(Studio 测试以外),必须首先对其进行授权。目前的授权流程涉及到将 DLL 名称添加到位于 COR 服务器(VC 运行的位置)上的授权文本文件。使用“Web 管理员摘要”页面并检查 AuthorizedAssemblies 配置设置以验证位置。该条目的格式为 BUS<busno>\<proxy>.dll。例如 BUS4\LCWS.dll。每个不同的 DLL 必须另起一行。如果某个 DLL 在脚本中被使用后被更新,唯一的方法就是重新启动 VC。

RESTful

Snippet 语言通过几个内置服务与 RESTful Web 服务一起工作。第一个是 RestProxy 服务,可以用如下方式创建一个新实例来使用它:

proxy = GetRESTProxy()

RestProxy 提供了一些与远程 Web 服务器交互的属性和方法。发出请求的关键方法称为 MakeRestRequest。以下是所有属性和方法的完整描述。与 RESTful Web 服务交换信息时,RestProxy 支持称为 DynamicData 类型的动态结构化数据定义格式。DynamicData 类型可以接收 XML 和 JSON 格式的数据,并提供面向对象的访问模式来读取数据。它还允许动态生成可以转换为 XML 或 JSON 的对象。

如需创建新的 DynamicData 对象,请使用 DYNAMIC 命令:

DYNAMIC <name> [FROM'<string>' | <var>]

<name>是新脚本变量的名称,并且必须与 inControl 脚本规范兼容(不包含除下划线“_”之外的任何前置数字或特殊符号,可以选择以美元符号“$”结尾)。如果使用可选的 FROM 子句,则文本可以是显式 JSON 或 XML 字符串(用单引号括起来)或包含 JSON 或 XML 的脚本变量的名称。初始化只是为了简化测试,而不是作为初始化动态变量的一般方法。只允许一行文本。如果在结束单引号之前遇到换行字符,将引发错误。

成员和子成员

此语言内的动态变量是专门设计的实体,具有广泛的有用功能。从表面上看,它们是可以具有动态创建成员的对象。例如,在 Snippet 中,可以声明一个动态变量并创建几个成员:

DYNAMIC employee employee.Name = "John Smith" employee.Phone = "8005551212" employee.Address = "1234 Clay Street

每个成员被寻址时,就会被自动创建。因此姓名电话地址成员现在将作为“员工”变量的属性。

动态变量成员区分大小写。因此,employee.Name 不同于 employee.name。这与 CXone 平台的正常行为不同。然而,由于需要与外部系统进行互操作(大多数取决于正确的大小写),这个决定最终确定,并且只适用于动态变量。

子成员也可以即时创建:

employee.Department.Code = 942 employee.Department.Location = "Olive City"

同样地,在子成员被处理时,它们会自动添加到结构中。现在,使用单个表达式,可将对该结构的引用分配给另一个动态脚本变量:

John = employee

需要注意的一点是,“employee”和“John”将引用相同的物理数据。如果您改变其中一个成员,也将同时改变二者。如需复制数据,请使用内置函数复制。以下 Snippet 示例演示了这一点:

DYNAMIC x x.Name = "John" y = x y.Name = "Sam"

其结果如下所示:

内置复制函数的示例。

有了复制函数,y 获得了唯一的副本,并且可在不影响 x 的情况下修改它:

DYNAMIC x x.Name = "John" y = copy(x) y.Name = "Sam"

显示复制函数示例的图像。

您还可以复制子成员:

DYNAMIC x x.Name.First = "John" x.Name.Last = "Smith" y = copy(x.Name) y.First = "Sam"

显示子成员示例的图像。

关于复制函数:它通过将对象转换为文本表示形式,然后再转换回对象来执行深度复制。在平台资源上,这比简单地复制引用更为昂贵。非常庞大的对象可能产生大量开销,并可能降低执行脚本的速度。必要时可以使用,但不要滥用。

动态变量也可以处理数组。对象本身可以被视为顶级数组,或者成员也可以被视为数组:

DYNAMIC employees employees[1] = john or employees.Person[1] = john

重要提醒!!! 所有数组都从索引 1 开始。如果您引用一个不存在的数组索引,则会创建此索引。如果新引用索引下的元素不存在,也将创建新元素。因此请务必谨慎,因为不小心指定索引 100 将为索引 1 到 99 创建空元素。如需获取数组中元素的个数,可使用 count() 函数:x = count(employees.Person)。

以下是 StudioSnippet 属性编辑器中的“检查器”选项卡。它显示了一个带有顶级数组的动态变量。

显示带有顶级数组的动态变量的图像。

通过将元素移动至称之为“Name”的子成员中,它的外观如下所示:

显示子元素示例的图像。

作为顶级数组的动态变量与作为动态变量数组的常规脚本变量之间存在差异。下面的例子说明了这一点:

DYNAMIC a DYNAMIC b DYNAMIC c a.Name = "John" b.Name = "Sam" c.Name = "Arnold" x[1] = a x[2] = b x[3] = c DYNAMIC y y[1] = a y[2] = b y[3] = c

要检查的 2 个变量是 x 和 y。首先,x 是一个包含一组动态变量的常规脚本变量。其次,y 是一个作为顶级数组的动态变量。二者在检查器中看起来非常相似:

显示动态变量示例的图像。

虽然看起来相似,但二者并非完全一样。下一节讨论动态变量的序列化概念。重要的一点是在上面的示例中,X 不能像 Y 那样用于与远程系统进行互操作。X 不可序列化,而 Y 可以序列化。

序列化

在讨论序列化之前,说明与普通脚本变量相比如何与动态变量进行交互会很有帮助。常规变量拥有很长的内置方法列表,用于进行字符串解析、转换为日期、排序等操作。点击下面的下拉菜单,查看如何与动态变量进行交互的众多示例。

使用动态变量的其中一个优势就是序列化的力量。这是将对象转换为适合在 Web 上传输的文本格式的能力。当前支持 2 种格式:XML 和 JSON。若使用 RestProxy(本节前面讨论过),序列化流程将自动进行。如果您需要手动生成序列化字符串,则提供 2 个字符串方法:

<var>.asjson() <var>.asxml()

在字符串上下文中使用,以生成对象的序列化版本:

text = "{y.asjson()}"

以下是假设 y 的值与前面的示例类似,text 可能包含的内容:

{"Name":[{"First":"Sam","Last":"Smith"},{"First":"Bill","Last":"Smith"}]}

同样,.asxml 方法产生如下输出:

<?xml version="1.0" encoding="utf-16" standalone="yes"?> <DynamicDataObject><Name><First>Sam</First<Last>Smith</Last></Name> <Name><First>Bill</First><Last>Smith</Last></Name></DynamicDataObject>

RestProxy 成员

通过调用 GetRestProxy() 获得的 RestProxy 提供使用 RESTful Web 服务约定与远程 Web 服务器进行通信的服务。在使用 Studio Snippet 编辑器时,可在键入时查看可用的属性和方法。只需声明一个新的代理实例:

proxy = GetRESTProxy()

然后在新一行中输入 proxy,后跟句号 (.):

显示 RESTProxy 示例的图像。

Intelli-Prompt 系统会自动显示包含可用成员的列表框。一旦选择一个方法,输入左括号将再次激活 Intelli-Prompt 系统,显示参数:

显示 Intelli-Prompt 系统的图像,系统展示了一个包含可用成员的 litbox。

属性

属性 详细信息
StatusCode 包含调用 MakeRestRequest() 后的 HTTP 状态代码。
StatusDescription 包含调用 MakeRestRequest() 后的 HTTP 状态描述。
ContentType 允许覆盖默认的内容类型标题。默认为“Form-urlencoded”。例如,如果发送 JSON,您将需要将此项更改为“application/json”
ProxyTimeoutSeconds 允许更改默认请求超时。默认为 10 秒。

方法

方法 详细信息
string urlencode(string value)
描述 Helper 方法将字符串编码为 Url 编码格式。
MakeRestRequest 向指定 URL 执行 HTTP 请求。
ClearHeaders 清除使用 AddHeader 添加的任何自定义标题。
AddHeader 向 HTTP 请求添加自定义标题。
MakeTwitterOauthRequest 构造一个与 Twitter 通信的特殊请求。
GetSalesForceOAuthToken 生成 SalesForce.com 所需的特殊授权令牌。