WPS本地镜像化在线文档操作以及样例

一个客户项目有引进在线文档操作需求,让我这边做一个demo调研下,给我的对接文档里有相关方法的说明,照着对接即可。但在真正对接过程中还是踩过不少坑,这儿对之前的对接工作做个记录。
按照习惯先来一个效果:

 Demo下载链接:https://download.csdn.net/download/qxyywy/88117444

接入指引


1. 申请授权证书并进行授权。
2. 登录系统后台页面
3. 创建、获取应用信息 access_key (简称ak)、 secret_key (简称 sk )。开发者在接口调用时,使用ak 、 sk 生成WPS-4签名进行鉴权。
4. 在线编辑、在线预览、格式转换接入按照对应开放能力文档接入。在线编辑、在线预览对接过程中需要设置回调地址。其中,在线编辑可通过配置开启历史版本功能。
5. 使用过程中需通过证书查询接口关注授权证书状态,若证书即将过期或者不可用,需进行更新证书操作。
6. 在线编辑或在线预览服务端对接完毕,对接方可使用JSSDK,调用API实现相关需求。

WPS-4签名算法

在对接时,耗费了一定时间在WPS-4签名处,对接文档中有WPS-4的说明和样例,自己在对接转换成NetCore的时候踩了一些坑,签名算法中最主要是:Wps-Docs-Authorization的计算方法
签名格式:WPS-4 {accessKey}:{signature}  注意WPS-4后面有空格。
signature:hmac-sha256(secret_key, Ver + HttpMethod + URI + Content-Type + WpsDocs-Date + sha256(HttpBody))
signature的样例如下:WPS-4POST/callback/path/demoapplication/jsonWed, 20 Apr 2022 01:33:07GMTfc005f51a6e75586d2d5d078b657dxxxdf9c1dfa6a7c0c0ba38c715daeb6ede9

这是文档中对签名算法的解释,对照着格式完成相关算法,具体算法如下:
signature的组装:

        /// /// 获取签名/// /// 请求方法,如:GET,POST/// 请求url,带querystring/// 请求body/// 日期/// 默认:application/json/// 应用SK/// public static string WPS4Signature(string secretKey,string method,string uri, byte[] body=null,DateTime? date=null,string contentType= "application/json"){//获取uri路径string path = uri;//日期格式化if (date == null)date = DateTime.Now;string dateStr = String.Format("{0:r}", date);//open不参与签名,做替换处理if (path.StartsWith("/open")){path = path.Replace("/open", "");}string sha256body;//body为空则为空,否则返回sha256(body)if (body != null && body.Length > 0){sha256body = Sha256(body);}else{sha256body = "";}String signature = null;signature = HmacSHA256Encrypt($"WPS-4{method.ToUpper()}{path}{contentType}{dateStr}{sha256body}", secretKey);return signature;}

HmacSHA256加密算法:

        /// /// HmacSHA256加密/// /// /// /// public static string HmacSHA256Encrypt(string secret, string signKey){string signRet = string.Empty;using (HMACSHA256 mac = new HMACSHA256(Encoding.UTF8.GetBytes(signKey))){byte[] hash = mac.ComputeHash(Encoding.UTF8.GetBytes(secret));//signRet = Convert.ToBase64String(hash);signRet = ToHexStrFromByte(hash); }return signRet;}

Sha256转换:

        /// /// Sha256转换/// /// The input./// A hash.public static string Sha256(this byte[] input){if (input == null){return null;}using (var sha = SHA256.Create()){var hash = sha.ComputeHash(input);return ToHexStrFromByte(hash);}}

字节数组转16进制字符串:

        /// /// 字节数组转16进制字符串:空格分隔/// /// /// public static string ToHexStrFromByte(this byte[] byteDatas){StringBuilder builder = new StringBuilder();for (int i = 0; i < byteDatas.Length; i++){builder.Append(string.Format("{0:X2}", byteDatas[i]));}return builder.ToString().Trim().ToLower();}

获取在线预览链接

        /// /// 获取在线预览链接/// /// /// [Route("api/wps/previewgenarate")][HttpPost]public Task GenarateWPSPreviewUrl(GenarateRequest request){return Task.Run(() =>{string wpsHost = "http://10.4.**.**";string uri = $"/api/preview/v1/files/{defaultFileId}/link?type=w&preview_mode=high_definition";string fullUrl = $"{wpsHost}/open{uri}";Dictionary headers = new Dictionary();DateTime now = DateTime.Now;headers.Add("Content-Type", "application/json");headers.Add("Wps-Docs-Date", String.Format("{0:r}", now));var signature = WPSLocalSIgnatureHelper.WPS4Signature("SKrpaxjdwoetijjv", "get", uri, null, now);string docsAuthorization = WPSLocalSIgnatureHelper.WPS4SignAuthorization("UOMYPEVAHWQLTKJF", signature);headers.Add("Wps-Docs-Authorization", docsAuthorization);HttpHelper httpHelper = new HttpHelper();var resultTemp = httpHelper.Get(fullUrl, headers);var result = JsonConvert.DeserializeObject>(resultTemp);string url = "";if (result != null && result.data != null){url = result.data.link;}return new GenarateResult { Url = url };});}

这儿比较坑的地方来了,方法参数都组装好了,通过HttpWebRequest后端发起请求获取WPS中台返回的在线预览地址时,始终提示401报错获取不到数据。迫不得已自己通过APIPost组装了相关请求和参数居然又能获取到相关数据。对照了下请求头,又差异后调整了程序的请求头,保证和apiPost里的完全一致,依然返回401,通过查阅相关资料找到一个处理办法,在发起的请求后手动捕获WebException,然后在WebException里解析数据流获取信息。
HttpWebRequest Get方式访问
 

        /// ///  Get方式访问/// /// /// /// /// /// public string Get(string url, string encode, string referer, Dictionary headers=null){int num = _tryTimes;HttpWebRequest request = null;HttpWebResponse response = null;StreamReader reader = null;while (num-- >= 0){try{DelaySomeTime();ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);//验证服务器证书回调自动验证request = (HttpWebRequest)WebRequest.Create(url);request.Headers.Add("accept", "*/*");request.Headers.Add("accept-encoding", "gzip, deflate, br");request.Headers.Add("accept-language", "zh-CN");request.Headers.Add("connection", "keep-alive");if (headers != null) {foreach (var item in headers){request.Headers.Add(item.Key, item.Value);}}//request.UserAgent = reqUserAgent;request.CookieContainer = _cookie;request.Referer = referer;request.Method = "GET";request.Timeout = _timeOut;if (_proxy != null && _proxy.Credentials != null){request.UseDefaultCredentials = true;}request.Proxy = _proxy;response = (HttpWebResponse)request.GetResponse();reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encode));return reader.ReadToEnd();}catch (WebException ex){response = (HttpWebResponse)ex.Response; //解析401等错误返回的有效信息var resultTemp = "";Stream stream = response.GetResponseStream();using (StreamReader readers = new StreamReader(stream, Encoding.UTF8)){resultTemp = readers.ReadToEnd();}return resultTemp;}catch (Exception ex){_logger.Error(url + "\r\n" + ex.ToString());continue;}finally{if (request != null){request.Abort();}if (response != null){response.Close();}if (reader != null){reader.Close();}}}return string.Empty;}

DemoHtml


到上面时后端的处理就基本完成,前端这边因为时临时demo就用了一个html来处理,真实项目中需要用VUE等处理也都类似。
以下为 html的代码:


WPS Web Office(iframe)接入指南课题名称:
课题申报单位:
课题负责人:
课题成员:
姓名所属部门年龄
姓名所属部门年龄
表格替换在第6页
图片上传:
图片替换在第7页


个人总结:需要在线编辑等相关操作,其实也可以用免费的组件组合,比如可以用onlyoffice+Aspose.Words去操作,仅个人见解。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部