一、开发准备
1、申请服务商
2、接入方式
接入方式分为文件预览、文件编辑和文件新建 3 种。
以文件预览为例,文件预览适用于文件已存在公网服务器的场景。
例如接入 Word(文字)预览:https://wwo.wps.cn/office/w/471eba5030?_w_fname=会议纪要.docx&_w_userid=33&_w_appid=d8f99da
之后只要对接方服务端实现相关的接口,就可以开启在线预览的接入:
回调地址 方法 功能 描述
/v1/3rd/file/info GET 获取文件元数据 在预览或编辑的时候,通过接口校验权限并获取文件信息
/v1/3rd/onnotify POST 通知 打开文件时返回通知的接口
关于更详细的文件预览、文件编辑和文件新建可以参考:接入方式
3、服务端接入
服务端快速接入可以查看:服务端
4、前端接入
前端快速接入可以查看:前端
二、逻辑说明
wps开放平台在线编辑只是提供了单纯的网页编辑,并没有存储文件。所有的文件以及数据都是需要对接方通过回调方法进行存储,所有返回文件的地址都是需要通过外网能够访问。所有的参数都必须以_w_为开头。
1、对接方数据库表说明
所有文件信息都需要对接方服务端生成,包括文件id。
a、文件存储表
CREATE TABLE zc_wps_files (id bigint(20) NOT NULL COMMENT ‘主键’,name varchar(100) DEFAULT NULL COMMENT ’ 文件名(必须带文件后缀) (必填)’,version int(11) DEFAULT NULL COMMENT ‘当前版本号,必须大于 0,同时位数小于 11 (必填)’,size bigint(20) DEFAULT NULL COMMENT ‘文件大小,单位为B(文件真实大小,否则会出现异常) (必填)’,download_url varchar(255) DEFAULT NULL COMMENT ‘文档下载地址 (必填)’,preview_pages int(11) DEFAULT NULL COMMENT ‘限制预览页数 (非必填)’,created datetime DEFAULT NULL COMMENT ‘创建时间’,creator bigint(20) DEFAULT NULL COMMENT ‘创建人’,updated datetime DEFAULT NULL COMMENT ‘修改时间’,updater bigint(20) DEFAULT NULL COMMENT ‘修改人’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘wps文件存储’;
b、文件历史存记录表
CREATE TABLE zc_wps_files_history (id bigint(20) NOT NULL COMMENT ‘主键’,file_id bigint(20) DEFAULT NULL COMMENT ‘文件id(对应a表的id)’,name varchar(100) DEFAULT NULL COMMENT ’ 文件名(必须带文件后缀) (必填)’,version int(11) DEFAULT NULL COMMENT ‘当前版本号,必须大于 0,同时位数小于 11 (必填)’,size bigint(20) DEFAULT NULL COMMENT ‘文件大小,单位为B(文件真实大小,否则会出现异常) (必填)’,download_url varchar(255) DEFAULT NULL COMMENT ‘文档下载地址 (必填)’,preview_pages int(11) DEFAULT NULL COMMENT ‘限制预览页数 (非必填)’,created datetime DEFAULT NULL COMMENT ‘创建时间’,creator bigint(20) DEFAULT NULL COMMENT ‘创建人’,updated datetime DEFAULT NULL COMMENT ‘修改时间’,updater bigint(20) DEFAULT NULL COMMENT ‘修改人’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=‘wps文件历史版本’;
2、前端初始化wps在线编辑说明
window.onload = function() {
const jssdk = WebOfficeSDK.config({
url: '在线文档预览地址', // 该地址需要后端提供,https://wwo.wps.cn/office/p/xxx
});
// 如果需要对 iframe 进行特殊的处理,可以通过以下方式拿到 iframe 的 dom 对象
console.log(jssdk.iframe);
// 打开文档结果
jssdk.on('fileOpen', (data) => {
console.log(data.success);
});
};在线文档预览地址是通过对接方服务端通过签名等操作返回给前端。
url 规范:https://wwo.wps.cn/office/<:type>/<:fileid>?_w_appid=xxx&_w_signature=xxx&…(对接模块需要的自定义参数)
url 示例:https://wwo.wps.cn/office/w/471eba5030?_w_fname=会议纪要.docx&_w_userid=33&_w_appid=d8f99da
3、签名说明
返回的路径https://wwo.wps.cn/office/<:type>/<:fileid>?_w_appid=xxx&_w_signature=xxx&…(对接模块需要的自定义参数) ,其中的签名(getSignature)需要把返回的参数全部参与签名,要不然会不通过。
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import .URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.\*;
import static org.apache.tomcat.util.codec.binary.Base64.encodeBase64String;
public class Signature {
public static void main(String args[]) throws UnsupportedEncodingException {
Map < String, String > paramMap= new HashMap<>();
paramMap.put("_w_appid", "123456");
paramMap.put("_w_fname", "222.docx");
paramMap.put("_w_userid", "id1000");
String signature = getSignature(paramMap, "7890");
System.out.println(getUrlParam(paramMap) + "&_w_signature=" + signature);
}
private static String getUrlParam(Map < String, String > params) throws UnsupportedEncodingException {
StringBuilder builder = new StringBuilder();
for (Map.Entry < String, String > entry : params.entrySet()) {
if (builder.length() > 0) {
builder.append('&');
}
builder.append(URLEncoder.encode(entry.getKey(), "utf-8")).append('=').append(URLEncoder.encode(entry.getValue(), "utf-8"));
}
return builder.toString();
}
private static String getSignature(Map < String, String > params, String appSecret) {
List < String > keys=new ArrayList();
for (Map.Entry < String, String > entry : params.entrySet()) {
keys.add(entry.getKey());
}
// 将所有参数按 key 的升序排序
Collections.sort(keys, new Comparator<String>() {
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
});
// 构造签名的源字符串
StringBuilder contents = new StringBuilder("");
for (String key : keys) {
if (key == "_w_signature") {
continue;
}
contents.append(key + "=").append(params.get(key));
System.out.println("key:" + key + ",value:" + params.get(key));
}
contents.append("_w_secretkey=").append(appSecret);
// 进行 hmac sha1 签名
byte[] bytes = hmacSha1(appSecret.getBytes(), contents.toString().getBytes());
// 字符串经过 Base64 编码
String sign = encodeBase64String(bytes);
try {
sign = URLEncoder.encode(sign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(sign);
return sign;
}
public static byte[] hmacSha1(byte[] key, byte[] data) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = Mac.getInstance(signingKey.getAlgorithm());
mac.init(signingKey);
return mac.doFinal(data);
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
}4、Java服务回调说明
说明参考官网
a、token说明
token是对接方自己的用户登录生成的,需要前端对接传入
- 方式一:
可以通过 jssdk 的方式接入前端,通过 jssdk 的 setToken 接口设置 token,具体细节可以看 jssdk 相关的接入文档。
url 参数带上 _w_tokentype=1(此参数同样需要签名)
jssdk = WebOfficeSDK.config({
url: 'your signature url' // url 参数带上_w_tokentype=1,通过 jssdk 方式传入 token
});
// 首次设置 token 和后续刷新 token 都是通过调用此 API
jssdk.setToken({token: 'your token'});- 方式二:
通过 WebView 注入 WPS_GetToken 全局函数来传入 token,WebOffice 前端如果检测到有 window.WPS_GetToken 函数,会直接调用该函数获取 token,注意需要 return 回来一个 Object 对象 {token: “your token”}
// 注入WPS_GetToken
function WPS_GetToken(){
return {
token: "your token"
};
};b、回调接口说明
一般按官网的说明编写回调接口。
上传新版本文件:/v1/3rd/file/save 传参稍微注意点
file官网给的是 body形式传参,其实Java代码则跟query一致
@ApiOperation("上传文件新版本")
@PostMapping("file/save")
public Map<String, Object> save(HttpServletRequest request, @RequestParam(name = "_w_tenderId") String tenderId, @RequestParam("file") MultipartFile file) {
String fileId = request.getHeader("x-weboffice-file-id");
String token = request.getHeader("x-wps-weboffice-token");
token = "Bearer " + token;
Integer version = Integer.parseInt(request.getHeader("x-weboffice-save-version"));
WPSFileSaveDTO wpsFileSaveDTO = new WPSFileSaveDTO();
wpsFileSaveDTO.setId(fileId);
wpsFileSaveDTO.setTenderId(tenderId);
wpsFileSaveDTO.setVersion(version);
wpsFileSaveDTO.setFile(file);
return wpsService.save(wpsFileSaveDTO, token);
}
















