在Lotus Domino中应用webservice

Lotus Domino V7.0 在 Lotus Domino Designer 中引入了新的 Web 服务设计元素。因此在Lotus Domino应用开发中使用Web 服务变得更加容易。其中Lotus Domino 负责处理所有的 WSDL 创建和 SOAP 操作,我们所要做的事情就是在 Web 服务设计元素中编写代码,设计Web 服务。Lotus Domino 就可以发布 WSDL 文件、将引入的 SOAP 请求转换为类上的方法调用以及返回方法的结果(如果有的话)作为 SOAP 响应。Lotus Domino Web 服务可以用lotus script,java两种语言编写。而调用Web 服务的方法却有很多。
一、设计Web 服务。

 

点新建Web 服务。设计自己的Web 服务。

 Web Service Properties 框中的 Basics 附签
对 Basic 附签上的字段说明如下:
Name(必需的): Web 服务的名称,是客户机访问 WSDL 文件或服务的方法时所使用的名称。
Alias:除 Name 之外的另一名称,用户使用该名称可以访问服务。
Comment:有关 Web 服务的信息数据的字段(通常,该字段的信息不超过一句话;有关 Web 服务的较长描述或信息应写在代码的注释中)。
Warn if the WSDL interface is modified:该选项警告您对代码所做的更改是否修改了由 Web 服务产生的 WSDL 文件。这对于确保 WSDL 文件的一致很有用,但是应该意识到,如果选中了该选项,则您将无法保存带有已修改的 WSDL 文件的服务。
PortType class(必需的):用作 Web 服务接口的类的名称。换句话说,它就是 Web 服务代码中带有用户可访问的 public 方法的类。
框中的第二个附签是 Security 附签(参见图 4)。
对 Security 附签上的字段说明如下:
Run as web user:该选项使 Web 服务代码能够在调用 Web 服务的用户的安全性上下文中运行(默认情况下,它将在 Lotus Domino Designer 中最后签名 Web 服务的那个 ID 的安全性上下文中运行)。
Run on behalf of:该字段允许指定用户,如果想让 Web 服务代码运行在特定用户的安全性上下文中,而不是 Lotus Domino Designer 中最后签名 Web 服务的那个 ID 的安全性上下文中。
Allow remote debugging:该选项允许远程调试 Web 服务(有关远程调试的信息,请参阅 Lotus Domino Designer 帮助主题 “Using the Remote Debugger”)。
Profile this web service:该选项将在 Web 服务运行时使其生成分析信息(有关分析的信息,请参阅 Lotus Domino Designer 帮助主题 “Profiling agents and Web services”)。
Set runtime security level:设置为 1,允许大多数 LotusScript 和 Java 操作正确运行;对于读/写文件、创建 COM 对象或执行网络操作等,根据需要,设置为 2 或 3(有关更多信息,请参阅 Lotus Domino Designer 帮助主题 “Restricted LotusScript and Java agent operations”)。
Default access for this web service:该选项允许控制哪些用户可以访问 Web 服务,并超出了使用数据库 ACL 所能进行的控制(如果 Anonymous 用户无法访问 Web 服务,则当用户尝试进行连接时,将收到错误 401 Access Denied 或 404 Not Found)。
Allow Public Access users to use this web service:该选项使得仅拥有数据库 ACL 中 “Read Public Documents” 访问权的用户可以使用该 Web 服务,当不想为大量用户授予完全的 Reader 访问权限(或更高级别)时,这点很有用。
框中的第三个附签是 Options 附签(参见图 5)。
对 Options 附签上的字段说明如下:
Programming model:可用选项是 RPC 或 Message(大多数情况下使用 RPC)。
SOAP message format:在该字段中,为此 Web 服务选择 SOAP 消息格式,Lotus Domino V7.0 中的默认格式是 RPC/encoded。
Include operation name in SOAP action:该选项要求操作名称存在于外来请求的 SOAP 动作标头中(很少需要)。
Port type name:默认情况下,该字段值与 Basics 附签上 PortType class 字段的值相同(尽管您可以使用任何想用的名称)。生成 WSDL 文件时使用该值。
Service element name:默认情况下,该字段值是 PortType 名称加上单词 Service(尽管您可以使用任何想用的名称)。生成 WSDL 文件时使用该值。
Service port name:默认情况下,该字段值是 Domino(尽管您可以使用任何想用的名称)。生成 WSDL 文件时使用该值。

 
可以选择是用lotus script 或 JAVA语言编辑你的Web 服务。以下是lotus script编写的一个简单的例子。
%INCLUDE "lsxsd.lss"
Class saveworkflow
    Sub NEW
       
    End Sub
    Function saveworkflowxml(xmlfilename As String,xmltext As String) As String
        On Error Goto errhandle
        Dim outputStream As NotesStream
        Dim session As New NotesSession
        Set outputStream = session.CreateStream
       
        Dim outputFile As String
        outputFile=Curdir$()+"datadominohtmlworkflow"+xmlfilename
        If outputStream.Open(outputFile) Then
            Call outputStream.WriteText(xmltext, EOL_CRLF)
            Call outputStream.Close
        End If
        saveworkflowxml="1"
        Exit Function
errhandle: 
        Msgbox Str(Err)+"行号: "+Str(Erl)+"错误信息saveworkflow:saveworkflowxml"+Error$   
        Resume Next
    End Function
   
   
End Class
一、Web 服务的调用。
1、 lotus script代理中调用 webservice。在window平台上我们可以使用MSSOAP toolkit来调用。可以下载MSSOAP toolkit3.0,并在服务器上安装MSSOAP toolkit3.0。在代理中的代码如下:
Sub Initialize
    On Error Goto errhandle
    Dim ss As New NotesSession
    Dim doc As NotesDocument
    Set doc=ss.DocumentContext
    Dim client As Variant
    Dim xmlfilename As String
    Dim xmltext As String
    xmlfilename=doc.xmlfilename(0)
    xmltext=doc.xmltext(0)
    Set Client =CreateObject("MSSOAP.SoapClient30")
    Call Client.mssoapinit ("http://server/mis/flow.nsf/saveworkflow?WSDL")
    Dim result As String
    If Not Client Is Nothing Then
        result = Client.saveworkflowxml(xmlfilename,xmltext)
       
           
    Else
        result="no web"
    End If 
   
    Exit Sub
errhandle: 
    Msgbox Str(Err)+"行号: "+Str(Erl)+"错误信息saveworkflowxml:"+Error$   
    Resume Next
   
End Sub
2、 javascript中调用 webservice。
var xmlfilename=document.all.xmlfilename.value
var xmltext=document.all.xmltext.value
                        var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
                        var soapMessage, soapData, URL;
                        // Set the soap message
                        soapMessage = "<?xml version="1.0" encoding="utf-8"?>";
                        soapMessage += "<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance""
                        + " xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">";
                        soapMessage += "<soap:Body>";
                        // Set the data for soap body ---- begin ------
                        soapData = "<saveworkflowxml xmlns="http://tempuri.org/">";
                        soapData += "    <xmlfilename>" + xmlfilename + "</xmlfilename>";
 soapData += "     <xmltext>" + xmltext + "</xmltext>";
                        soapData += "</saveworkflowxml>";
                        // Set the data for soap body ---- end ------
                        soapMessage = soapMessage + soapData + "</soap:Body>";
                        soapMessage = soapMessage + "</soap:Envelope>";
var urlstr="http://server/mis/flow.nsf/saveworkflow?openwebservice"
 
                        xmlhttp.Open("POST",urlstr, false);
                        xmlhttp.SetRequestHeader ("Content-Type","text/xml; charset=utf-8");
                        xmlhttp.SetRequestHeader ("SOAPAction","http://tempuri.org/onlineandmsg");
                        xmlhttp.send(soapMessage);
                        var x =   xmlhttp.responseXML;
3、 FLASH 中调用 webservice。
import mx.services.WebService;
//定义 WebService的路径;
var ws_url:String = "http://server/mis/flow.nsf/saveworkflow?WSDL";
//定义 WebService对象;
var ws:WebService = new WebService(ws_url);
//调用 WebService方法;
var callObject = ws.SAVEWORKFLOWXML(_parent.workflowxml,_global.workxml.toString());
//设置返回结果对象;
callObject.onResult = function(result){
    trace(result);
      
}
//如果调用错误返回信息 (这个是可选的);
callObject.onFault = function(fault){
    trace("fault:"+fault.faultstring);
}
 
4、 java 代理中调用 webservice,首先在代理工程中引入相关的包。
import lotus.domino.*;
import java.io.*;
import java.util.*;
import java.net.*;
import org.w3c.dom.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.*;
import org.apache.soap.encoding.*;
import org.apache.soap.encoding.soapenc.*;
import org.apache.soap.rpc.*;
import org.apache.soap.transport.http.SOAPHTTPConnection;
public class JavaAgent extends AgentBase {
 
    public void NotesMain() {
 
        try {
            Session session = getSession();
            AgentContext agentContext = session.getAgentContext();
     Document doc = agentContext.getDocumentContext();
String xmlfilename=doc.getItemValueString("xmlfilename")
String xmltext=doc.getItemValueString("xmltext")
            // (Your code goes here)
        URL url = new URL ("http://server/mis/flow.nsf/saveworkflow?WSDL");
     SOAPMappingRegistry smr = new SOAPMappingRegistry ();
     StringDeserializer sd = new StringDeserializer ();
     smr.mapTypes (Constants.NS_URI_SOAP_ENC, new QName ("", "Result"), null, null, sd);
 
     // 创建传输路径和参数
     SOAPHTTPConnection st = new SOAPHTTPConnection();
 
     // 创建调用
     Call call = new Call ();
     call.setSOAPTransport(st);
     call.setSOAPMappingRegistry (smr);
 
     call.setTargetObjectURI ("http://tempuri.org/message/");
      call.setMethodName("saveworkflowxml");
     call.setEncodingStyleURI ("http://schemas.xmlsoap.org/soap/encoding/");
 
     Vector params = new Vector();
    params.addElement(new Parameter("xmlfilename", String.class, xmlfilename, null));
 params.addElement(new Parameter("xmltext", String.class,xmltext, null));
     call.setParams(params);
 
     Response resp = null;
 
     try {
       resp = call.invoke (url,"");
     }
     catch (SOAPException e) {
     System.err.println("Caught SOAPException (" + e.getFaultCode () + "): " + e.getMessage ());
     return;
     }
 
     // 检查返回值
     if (resp != null && !resp.generatedFault()) {
     Parameter ret = resp.getReturnValue();
     Object value = ret.getValue();
 
     System.out.println ("Answer--> " + value);
     }
     else {
         Fault fault = resp.getFault ();
         System.err.println ("Generated fault: ");
         System.out.println (" Fault Code = " + fault.getFaultCode());
         System.out.println (" Fault String = " + fault.getFaultString());
     }
 
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
Lotus Domino WEB 开发技术积累-DOC(313页) 1. 选取视图的列的内容 @Trim @DbColumn 6 2. 隐藏判断常用的命令 6 3. 判断当前用户是否是“某个组”的成员,然后来显示和隐藏 6 4. 在Lotus Domino 显示图 6 5. 链接JS文件 6 6. 删除文档的方法 7 7. $$return 域的使用 8 8. 将表单设计为视图或导航器模板 9 9. 为 Web 定制“表单已处理”确认信息 10 10. 定制出错信息 11 11. $$HtmlHead几种常用的技巧 11 12. Domino Designer 模板表 12 13. 角色判断 13 14. 判断文档是否正在被修改 13 15. 在只读的方式下返回($$return 13 16. 刷新表单 14 17. 怎样在文档里存照片? 14 18. 后台lotusscript如何取得前台表单复选框所选择的项目列表(b/s结构) 15 19. 试图的列公式:附件下载 15 20. 有没有好一点的分页处理代码 16 21. 同一用户重复登录 18 22. Return to sender 19 23. Agent to copy values from 1 form to another 在同一个数据库进行 22 24. 超越OLE – 通过COM结合MS Office与Notes应用 23 25. 读写关系数据库资料 28 26. 视图---excel,表单---word 32 27. 关于Web上的检索问题 35 28. 如何使用Notes与关系数据库进行信息交互? 37 29. 如何在IE里面实现notes的 对话框列表? 39 30. LotusDomino环境下编写Web浏览器多数据库检索程序 40 31. WINAPI函数 44 32. 用PowerBuilder访问Lotus Notes数据库 55 33. 如何在表单加入计数器 58 34. 实现两个数据库间的数据追加 C/S 结构 60 35. 如何防止他人使用旧id和旧口令访问Domino服务器? 61 36. 在你的WEB站点上使用DOMINO群集 62 37. 在你的DOMINO WEB站点插入.SWF文件 73 38. DOMINO R5的域搜索功能在WEB上的实现 77 39. Display Rich Text fields in a view 86 40. Auto-Launch a file attachment 87 41. Showing a response count without showing the responses 89 42. 常用的几个按钮收集 91 43. 在WEB上从视图删除文档技巧 93 44. 在Domino Designer使用XML数据 96 45. 在Domino Designer上执行XML 100 46. Show single category view, the next stage 107 47. Checkboxes in a list box 108 48. Formatting a Notes view in HTML table for WEB 109 49. Jump to the end of a view (web agent) 111 50. Disabling actions until a page finishes loading 114 51. Web-based, fully customizable search 115 52. 从复选框删除文档Deleting selected docs on Web 120 53. Debugging LotusScript Agents 121 54. Displays the contents of the Subject field in the first document in theExamples view. 124 55. Example: GetLastDocument method 125 56. Examples: GetNextDocument method 125 57. Example: GetFirstDocument method 126 58. Examples: FTSearch method 127 59. Examples: DeleteDocument method 128 60. Example: Deleting a document 129 61. Example: Creating a document 129 62. Examples: Locating documents within a view or folder 130 63. Example: Adding a document 135 64. Export to Excel 136 65. 连接ODBC 138 66. 特效 140 67. notes和Excel交换数据 141 68. NOTES的ODBC:(LS:DO) 142 69. Managing JavaScript "popup" windows 第一稿 144 70. HEAD元素使用集锦 147 71. 主页javascript特效19则 148 72. 关于创建、删除、编辑、打开和保存文档的 URL 命令 156 73. Domino URL 命令 158 74. 在打开有下面这段代码的页面时将会跳出一个468x60大小的小窗口 160 75. javascript的容错脚本 161 76. Web search with JavaScript 162 77. 如何防止他人使用旧id和旧口令访问Domino服务器 164 78. Fixing the Domino CheckBox Bug 165 79. Managing JavaScript "popup" windows 172 80. Quick, easy, foolproof field level help 175 81. Quick edit document link 176 82. Managing JavaScript "popup" windows 178 83. Svg: Pie-Eyed 181 84. Recebt Entries 182 85. Xin Calendar Mods 183 86. 答复文档 186 87. 公式语言 187 88. Resuable way to get URL parameters into fields 199 89. JSHeader 使用 201 90. JavaScript 帮助 201 91. Examples: Collecting documents by searching 207 92. 关于DOcumentContext 的属性 209 93. About data types 关于lotus Domino 的数据类型 210 94. CLng function 212 95. Using the DOM to replace "No documents found" 213 96. What you need and want to know about errors 217 97. Processing multiple documents from a view 221 98. Forcing attachments to always download 225 99. ODBCExample: GetValue method 247 100. ODBCResultSet class 248 101. Create a "Login" anchor link 251 102. 分类视图的开发技巧 253 103. 公式语言 255 104. Copy documents from one database to another 267 105. 定制搜索表单 268 106. UserName的属性及使用 275 107. Dynamic Content for Popup Windows 277 108. Shortcut when printing from a Java Agent 278 109. Lotus Script: Write # statement 279 110. Lotus Script: Input # statement 280 111. 使用代理生成 XML 284 112. 使用视图生成 XML 286 113. 执行算术运算 288 114. Keep URLs simple by making them relative 292 115. Quick, easy, foolproof field level help 294 116. Hiding attachments (without noscript tag!) 295 117. Listing search results in groups 296 118. 如何在表单加入计数器? 300 119. 怎样限制一个WEB用户只有登陆才能使用数据库 302 120. Complete control when printing HTML from an agent 304 121. Simple multi-lingual forms using Domino 306 122. Stop double form submissions 308
第1章 Domino Web开发综述 1 1.1 为什么使用Domino 1 1.2 Domino是怎样运行的 1 1.2.1 Domino与传统数据库的区别 1 1.2.2 DominoWeb 2 1.3 开发部件 2 1.4 其他工具 3 1.5 简单的Domino Web软件例子 10 参考信息 14 本章小结 14 第2章 使用表单 16 2.1 关于表单 16 2.2 在表单使用公式 17 2.2.1 数组和多值域 18 2.2.2 公式的类型 18 2.2.3 例子:一个组合框域 20 2.2.4 例子:$$Return域的公式 22 2.3 在表单使用Web元素 22 2.3.1 嵌入Web元素 22 2.3.2 创建特殊用途的模板表单 22 2.3.3 例子:在$$View Template Default 表单嵌入导航器 23 2.3.4 例子:动态嵌入式导航器 24 2.4 在表单和表单对象使用HTML属性 25 2.4.1 <META>标记的例子 26 2.4.2 例子:RTF文本域的属性 27 2.4.3 例子:cookie 27 2.5 使用表单操作按钮 28 2.6 使用热点 30 2.7 在表单内使用HTML 31 2.7.1 例子:单个类视图 31 2.7.2 例子:显示附属图形文件 36 2.7.3 例子:把文本域显示为文本区域 39 2.8 在表单使用CGI变量 40 2.9 表单和搜索 42 2.9.1 定制视图搜索表单 43 2.9.2 例子:定制搜索界面 44 2.9.3 定制Site Search表单 47 2.9.4 定制Search Results表单 47 2.9.5 例子:对搜索结果表单的定制 48 2.10 定制表单提交按钮 49 2.11 使用隐藏域 49 2.12 把RTF文本显示为一个小应用程序 50 参考信息 51 本章小结 51 第3章 使用视图进行工作 54 3.1 关于视图 54 3.2 视图和Web 55 3.3 使用选择公式 56 3.4 使用视图列公式 57 3.5 使用表单公式 57 3.6 使用视图图标 58 3.7 创建视图操作按钮 59 3.8 使用单个类视图 60 3.9 在视图使用HTML通用文本 62 3.9.1 改变行的格式 63 3.9.2 在视图显示Java小应用程序和图像 63 3.9.3 HTML通用文本 64 3.9.4 改变视图连接的动作 66 3.9.5 控制视图连接的另外一种方式 68 3.9.6 例子:在视图使用java Script 68 3.10 在表单使用视图 70 3.10.1 在表单嵌入视图 70 3.10.2 创建视图模板 70 3.10.3 例子:使用表单在视图添加 功能 71 3.10.4 例子:使用视图在表单添加 功能 73 3.10.5 例子:创建多个类的视图 76 3.11 在小应用程序表单显示一个视图 79 参考信息 80 本章小结 80 第4章 使用帧结构、大纲和其他设计 元素 82 4.1 简介 82 4.2 在帧结构设计 82 4.2.1 帧的不利之处 83 4.2.2 使用帧结构集设计元素 84 4.2.3 使用<FRAMESET>标签 88 4.3 使用大纲 94 4.3.1 同时使用帧和大纲 95 4.3.2 显示大纲小程序 97 4.4 使用其他的设计元素 97 参考信息 101 本章小结 101 第5章 编写JavaScript 103 5.1 简介 103 5.2 开始编写JavaScript 104 5.3 把JavaScript添加到Domino的表单 106 5.4 验证域:Expense Report表单 107 5.5 计算域的值:Expense Report表单(续) 109 5.6 显示域相关的帮助 110 5.7 控制帧的使用 112 5.8 填充动态列表框 114 5.9 例子:动态下载图像 117 5.10 例子:在一个滚动按钮预先下载 图片 119 5.11 例子:显示对话框 121 5.11.1 Order Form表单 123 5.11.2 Select Parts表单 124 5.11.3 Read-Only Order Form表单 127 5.11.4 Orders视图 127 5.12 例子:操纵cookie 127 5.13 例子:ActiveX对象脚本 128 5.14 例子:Domino产生的JavaScript 133 参考信息 137 本章小结 138 第6章 编写LotusScript 139 6.1 简介 139 6.2 关于LotusScript Web代理 140 6.3 激活一个代理的URL 141 6.4 在LotusScript编写WebQueryOpen 代理 142 6.4.1 简单的LotusScript WebQueryOpen 代理 142 6.4.2 查询数据库 144 6.5 在LotusScript编写WebQuerySave 代理 146 6.5.1 简单的LotusScript WebQuerySave 代理 146 6.5.2 在表显示ODBC搜索结果 147 6.6 在LotusScript代理使用CGI变量 150 6.6.1 QUERY_STRING代理 150 6.6.2 HTTP_COOKIE代理 154 6.7 在基于Web的工作流使用LotusScript 157 6.8 在LotusScript代理使用小应用程序 161 参考信息 170 本章小结 170 第7章 Java应用程序 171 7.1 使用Java语言 171 7.2 Domino 4.6及以上版本的Java应用程序 172 7.2.1 例子:SendMemo.java 173 7.2.2 例子:SendMemo2.java 175 7.2.3 Java接口 175 7.2.4 例子:SendMemo3.java 176 7.2.5 使用GUI组件 177 7.2.6 例子:Send Memo4.java 177 7.2.7 多线程的例子:ListGroups应用 程序 179 7.3 Domino 5的Java应用程序 185 7.3.1 简单例子:CorbaApplication.java 186 7.3.2 GUI例子:CorbaApplication2.java 186 参考信息 189 本章小结 189 第8章 Java代理 190 8.1 简介 190 8.2 关于Java Agents 190 8.3 编写4.6版的Java代理程序 191 8.3.1 简单Java代理:Simple Agent.Java 191 8.3.2 多线程代理程序:NotesGuiAgent. java 196 8.3.3 Java Web代理程序 199 8.4 在R5编写Java代理 226 参考信息 230 本章小结 231 第9章 使用Java小应用程序 232 9.1 简介 232 9.2 Java小应用程序和Domino 233 9.3 简单例子:HelloUser.java 234 9.4 声音例子:AudioApplet.java 236 9.5 使用 LiveConnect:Java_JS.java 241 9.6 LiveConnect和标准的Domino应用 程序 244 9.7 编写小应用程序更容易的方法: Lotus BeanMachine 245 9.8 使用eSuite 247 9.8.1 什么是eSuite 247 9.8.2 eSuite和Domino 248 9.8.3 eSuite Workplace Desktop 248 9.8.4 eSuite小应用程序 249 9.8.5 应用功能的局限性 251 9.8.6 eSuite InfoCenter简介 252 9.8.7 eSuite Devpak 252 9.8.8 DevPak组件 253 9.9 InfoBus技术介绍 253 9.9.1 InfoBus例子 254 9.9.2 eSuite/InfoBus例子 255 参考信息 257 本章小结 258 第10章 编写CORBA小应用程序 259 10.1 简介 259 10.2 什么是CORBA 259 10.3 关于lotus.domino软件包 259 10.4 例子:Corba Text 1.java 260 10.5 例子:ResumeApplet.java 264 10.6 显示数据图表:SalesChartApplet.java 270 10.7 使用两种方式发送数据: AgentControlPanel.java 274 10.8 CORBA小应用程序还不能实现的 功能 279 参考信息 280 本章小结 280 第11章 编写Java小服务程序 281 11.1 什么是小服务程序 281 11.2 为什么在Domino使用小服务程序 281 11.3 启用小服务程序支持 282 11.4 编写小服务程序 283 11.4.1 简单的HTTP GET小服务程序: StupidServlet 283 11.4.2 简单的HTTP POST小服务程序: JDBCQueryServlet 284 11.4.3 使用链接缓冲区的JDBC小服务 程序 289 11.4.4 Cookie-Setting Servlet 293 11.4.5 小服务程序和Netes Java类 298 11.4.6 最后一点说明 299 参考信息 300 本章小结 300 附录 Domino URL 301
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值