一、开发准备

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 java.net.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);
    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐