今天是2022年最后一个工作日,就要跟2022年说再见了!提前祝大家新年快乐!
网易跨境收款chrome插件实战,介绍chrome插件的开发,调试和上架。
背景
根据中国外汇管理相关规定,贸易相关外汇收支均需要真实、合法的交易背景,因此跨境收款服务平台在给用户提供收款服务的时候,需要用户提供店铺订单,以满足合规的要求。但有些平台没有直联的API服务,目前需要用户自己从贸易平台上下载对应的订单,补充完数据信息,然后在跨境收款服务平台上传,但这种方式商户体验不够好:①部分平台需要人工补齐其他信息、②订单需要等待审核、③文件因为字段格式可能失败;另一方面因缺少平台的对接,订单可靠性欠缺。所以需要增加支持商户通过Chrome插件授权采集平台上的订单。
什么是 Chrome 插件
Chrome Extension 是一个小的软件程序,它可以用来定义浏览器的浏览体验,让用户可以根据个人需求或者偏好定制 Chrome 浏览器的功能和行为,主要使用的技术栈是 HTML、Javascript 和 CSS。
利用前端的技术栈,来定制浏览器的功能,改善用户体验。
所以只要你会写 JS、HTML、CSS,你就能开发 Chrome 插件。
Chrome 插件能干什么?
利用 Chrome 浏览器提供的已有功能和和各种 API,进行功能组合,从而增强浏览器网页的功能,改善浏览器体验,轻松实现属于自己的“定制版”浏览器。
一般来说,插件的原理是向页面中注入 javascript 脚本,对页面进行处理,比如我们这里就是利用注入的脚本在对应电商平台的订单页面上模拟用户发起request请求获取订单信息,并将订单信息发送到跨境收款服务平台
开发插件需要使用前端技术:html css javascript。
Chrome 插件核心概念

manifest.json
manifest.json 是每个 WebExtension 唯一必须包含的元数据文件。manifest.json 目前已经发展到了v3 :相比V2版本更安全、性能更好、隐私更强, 根据官方说明:manifest v2(MV2) 即将被废弃,在 2022 年逐步不接受更新,2023 年将会逐步不能运行。
通过使用 manifest.json,您可以指定扩展的基本元数据,例如名称和版本,还可以指定扩展各个方面的功能(例如后台脚本,内容脚本和某些浏览器行为)。
注意:manifest.json 文件必须放在项目根目录下
popup
popup 是点击扩展图标时打开的一个小窗口网页,焦点离开网页就立即关闭,一般用来做一些临时性的交互。本次需求主要是用来设置需要采集哪些电商平台。

popup 可以包含任意你想要的 HTML 内容,并且会自适应大小。
在 manifest.json 文件中,可以通过 default_popup 字段来指定 popup 页面,也可以调用 setPopup() 方法。
"action":
{
...,
// 指定 popup 页面
"default_popup": "popup.html",
// 图标
"default_icon": {
"16": "images/favicon.png",
"32": "images/favicon.png",
"48": "images/favicon.png",
"128": "images/favicon.png"
},
// 图标悬停时的标题,可选
"default_title": "这是一个示例Chrome插件",
...
},
background
background 是一个常驻的页面,它的生命周期是插件中所有类型页面中最长的,它随着浏览器的打开而打开,随着浏览器的关闭而关闭,所以通常把需要一直运行的、启动就运行的、全局的代码放在 background 里面。
background 的权限非常高,几乎可以调用所有的 Chrome 扩展 API(除了 devtools),而且它可以无限制跨域,也就是可以跨域访问任何网站而无需要求对方设置 CORS。
在 manifest.json 文件中,可以通过 service_worker 字段指定 background。
"background":
{
// 如果需要 background,则下面的配置必须要有,指定后台运行的脚本
"service_worker": "background.js"
},
注意:v3版本 background文件必须放在项目根目录下
content-scripts
content-scripts 是 Chrome 插件中向页面注入脚本的一种形式。
通过 content-scripts 我们可以以配置的方式轻松向指定页面注入 JS 和 CSS,实现一些脚本执行和 CSS 定制。
在 manifest.json 文件中,可以通过 content-scripts 字段配置:
"content_scripts": [ {
"all_frames": true,
"css": [ ],
"js": [ "scripts/lib/jquery.js", "scripts/lib/jquery.cookie.js", "scripts/lib/md5.min.js", "scripts/config.js", "scripts/util.js" ],
"matches": [ "http://*/*", "https://*/*" ],
"run_at": "document_end"
} ],
除了 content-scripts,另外还有一种注入的方式我们称之为动态注入,也就是在插件运行时,在任何你想要注入的时候进行注入,而不用提前指定。升级到V3版本之后,之前的动态注入已经不适合了,根据最新的要求,已经不支持远程托管代码的形式,虽然还可以利用chrome.runtime.getURL的方式加载本地资源后再动态加js, 但以这种方式上架的时候会被拒绝。并且这种方式加载到的js和 content-scripts 不是一个环境内的,无法与background.js 通信。
https://developer.chrome.com/docs/webstore/program_policies/#mv3-req
内容脚本是运行在一个孤立的环境,孤立的世界是页面或其他扩展无法访问的私有执行环境。这种隔离的实际后果是扩展内容脚本中的 JavaScript 变量对主机页面或其他扩展内容脚本不可见。
https://developer.chrome.com/docs/extensions/mv3/content_scripts/#isolated_world
插件功能实现
整体流程

本次插件会有一个option和popup页面,popup是用户点击扩展图标时打开的一个小窗口网页,让用户快捷设置需要采集的电商平台,option是一个完整的设置页面和说明页面,也是设置需要采集的电商平台,并展示了插件的使用说明。需要background实现一些插件启动就运行的功能比如这里的获取采集平台信息。
获取平台配置信息
插件启动时主动发起请求到跨境收款服务平台获取各个电商平台的配置信息, 包括电商平台的域名,订单页的地址,是否可以正常使用和对应电商平台的动态脚本地址,并将这些配置信息保存到本地,如果下次有变化就更新本地保存的信息。
const refreshPlatfroms = force => {
// let today = parseTime(new Date(), 'yyyy-MM-dd')
//发送请求获取平台列表
let promise = new Promise(function (resolve, reject) {
sendtoServer({
type: 'get',
url: Config.BASE_API + '/platformList',
needSignature: true
}).then(res => {
platforms = !res || !res.data || !res.data.result ? [] : res.data.result;
savePlatforms(platforms)
resolve(platforms)
});
});
return promise;
};
检查订单页面地址并注入对应的采集脚本
检查用户当前是否处在订单页面,如果不是则引导用户跳转到订单页面,到订单页面后再根据之前获取到的平台信息加载电商平台对应的采集脚本。
注:其实用API 的方式也不一定需要在订单页面,这么做的原因是尽量模拟真实的用户操作,避免风险。
/**
* 匹配平台主域名后加载js文件
* @param {Number} tabId
* @param {Object} changeInfo
* @param {Object} tab
*/
const checkForValidUrl = (tabId, changeInfo, tab) => {
// 是为了不重复执行
if (changeInfo.status == 'complete' && tab.status == 'complete' && tab.url != undefined) {
platformsStore
.iterate((value, key, iterationNumber) => {
if (value.isChecked && testDomainFromUrl(value.domain, tab.url)) {
// 注入js
// https://developer.chrome.com/docs/extensions/reference/scripting/#type-ExecutionWorld
chrome.scripting.insertCSS({
target: { tabId: tabId },
files: [ 'styles/notice.css' ]
});
chrome.scripting.executeScript({
target: { tabId: tabId, allFrames: true },
files: [ value.jsAddr ],
}).then(() => {
// 传递platformId
chrome.tabs.sendMessage(tabId, { platformId: value.id }, () => {});
})
}
})
.then(function () {
console.log('platformsStore iteration has completed');
})
.catch(function (err) {
console.log(err);
});
}
};
验证账户信息并开始采集
通过注入的脚本获取对应电商平台的用户id并到跨境服务平台上查询,如果无则直接提示失败,并展示失败原因,如果有则展示商户信息,让用户确认,确认之后则开始正式的采集, 采集的时候需要注意请求的间隔也需要尽量模拟用户的真实操作,将采集到的订单信息上传到跨境服务收款平台,从用户上次采集的最后一个订单开始,一直采集到最新的订单,如果中途有一个错误,则错误之后的所有订单都不上传。
插件的调试
开发中的插件可以在chrom 浏览器的管理扩展中打开开发者模式

然后点击“加载已解压的扩展程序”,选中插件项目的文件夹即可将插件添加到chrome浏览器中。

popup 页面调试
右键单击 Chrome 插件图标,点击审查元素内容,可打开调试界面,与 Chrome 的 Devtools 一样。

background 调试
background 的代码只可以调试,其页面无法查看。

content-script 调试
与普通页面调试一样,使用浏览器的开发者工具调试。
插件的发布
需要打包成.crx 文件,可以在插件管理页通过打包应用程序进行打包。

打包后会生成一个 .crx 文件,然后你就可以把这个 .crx 文件发布到 Chrome 应用商店啦~~
发布前,你可能需要做如下准备:
注册一个 Google 账号
注册为开发者
https://chrome.google.com/webstore/devconsole/07318783-69c8-40ec-b656-82f67428febf
-- End --
点击下方的公众号入口,关注「技术对话」微信公众号,可查看历史文章,投稿请在公众号后台回复:投稿




