/** 利用chrome的fetch来避免跨域 **/ import {getSign} from "@/api/aliExpress"; import qs from "query-string" /** * 根据图片URL获取Blob对象 * @param imageUrl * @returns {Promise} */ function getImageBlob(imageUrl) { return new Promise((resolve) => { fetch(imageUrl).then((response) => response.blob()) // 将响应转换为Blob对象 .then((blobData) => { const fileName = imageUrl.match(/\/([^/]+)$/).at(-1) const reader = new FileReader(); // 读取Blob对象的内容 reader.onloadend = function () { const image = {blobData, fileName} resolve({image}); }; reader.readAsArrayBuffer(blobData); // 将Blob对象作为参数传递给FileReader的readAsArrayBuffer()方法 }) }); } /** * 将cookie字符串转换为对象 * @param cookieString * @returns {{}} */ function cookie2Obj(cookieString) { const cookieArray = cookieString.split(';'); const cookieObj = {}; for (let i = 0; i < cookieArray.length; i++) { const [key, value] = cookieArray[i].split('='); cookieObj[key] = value; } return cookieObj; } chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request.type == 'api') { let headers = {}, data; new Promise((resolve) => { if (request.needMallId) { headers.Mallid = request.mallId; } if (request.anti) { headers["Anti-Content"] = request.anti } if (!request.isFormData) { headers['Content-Type'] = 'application/json'; data = JSON.stringify(request.data) } else { const formData = new FormData(); Object.keys(request.data).forEach(key => { const value = request.data[key] if (Array.isArray(value)) { value.forEach((subValue, i) => { formData.append(key + `[${i}]`, subValue) }) } else { if (key == "image") { //跳过image的处理 } else formData.append(key, request.data[key]) } }) data = formData } headers.cookie = getCookie(); if (request.isFormData && !!request.data.image) {//针对图片上传特殊的处理办法 getImageBlob(request.data.image).then(res => data.append('image', res.image.blobData)).then(resolve) } else resolve() }).then(() => fetch(request.url, { headers, 'method': 'POST', 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': data, 'mode': 'cors' })).then(res => res.json()).then(sendResponse); } else if (request.type == 'temuApi') { new Promise((resolve) => { let headers = {}; if (request.anti) { headers["Anti-Content"] = request.anti } headers['Content-Type'] = 'application/json'; headers.cookie = getTemuCookie(); Promise.resolve().then(() => fetch(request.url, { 'headers': headers, 'method': 'POST', 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': JSON.stringify(request.data), 'mode': 'cors' })).then((res) => { resolve(res.json()); }).catch(() => { resolve({success: false, errorCode: -1}) }); }).then(sendResponse); } else if (request.type == 'temu') { new Promise((resolve) => { let headers = {}; headers['Content-Type'] = 'text/html'; //headers.cookie = getTemuCookie(); Promise.resolve().then(() => fetch(request.url, { 'headers': headers, 'method': 'GET', 'referrerPolicy': 'no-referrer', //'credentials': 'include', 'mode': 'cors' })).then((res) => { // 创建了一个数据读取器 const reader = res.body.getReader(); // 创建了一个文本解码器 const decoder = new TextDecoder(); let text = "" reader.read().then(function processText({done, value}) { // Result 对象包含了两个属性: // done - 当 stream 传完所有数据时则变成 true // value - 数据片段。当 done 为 true 时始终为 undefined if (done) { resolve(text); return; } // 将字节流转换为字符 text = text + decoder.decode(value) // 再次调用这个函数以读取更多数据 return reader.read().then(processText); }); }); }).then(sendResponse); } else if (request.type == 'aliexpress') { new Promise(async (resolve) => { let headers = {}; headers['Content-Type'] = 'text/html'; const cookie = await getAliexpressCookie(request.url); const {_m_h5_c, _m_h5_tk} = cookie2Obj(cookie) const {query: {data, appKey}} = qs.parseUrl(request.url) const {formData = data} = request const {sign, t} = getSign(_m_h5_c || _m_h5_tk, appKey, formData) const url = qs.stringifyUrl({url: request.url, query: {sign, t}}) headers.cookie = await getAliexpressCookie(url); Promise.resolve().then(() => fetch(url, { 'headers': headers, 'method': 'POST', 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'mode': 'cors' })).then((res) => { // 创建了一个数据读取器 const reader = res.body.getReader(); // 创建了一个文本解码器 const decoder = new TextDecoder(); let text = "" reader.read().then(function processText({done, value}) { // Result 对象包含了两个属性: // done - 当 stream 传完所有数据时则变成 true // value - 数据片段。当 done 为 true 时始终为 undefined if (done) { resolve(text); return; } // 将字节流转换为字符 text = text + decoder.decode(value) // 再次调用这个函数以读取更多数据 return reader.read().then(processText); }); }); }).then(sendResponse); } else if (request.type == 'sheinApi') { new Promise((resolve) => { let headers = {}; headers['Content-Type'] = 'application/json'; headers.cookie = getSheinCookie() request.params = formatParams(request.params) let _url = request.url + (request.params ? ('?' + request.params) : '') Promise.resolve().then(() => fetch(_url, { 'headers': headers, 'method': request.method, 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': JSON.stringify(request.data), 'mode': 'cors' })).then((res) => { resolve(res.json()); }); }).then(sendResponse); } else if (request.type == 'geiwohuoApi') { new Promise((resolve) => { let headers = {}; headers['Content-Type'] = 'application/json'; headers['X-Req-Zone-Id'] = 'Asia/Shanghai'; headers['X-Lt-Language'] = 'CN'; Promise.resolve().then(() => fetch(request.url, { 'headers': headers, 'method': request.method, 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': JSON.stringify(request.data), 'mode': 'cors' })).then((res) => { resolve(res.json()); }).catch(() => { resolve({success: false, errorCode: -1}) }); }).then(sendResponse); } else if (request.type == 'goodcangApi') { new Promise((resolve) => { let headers = {}; headers['Content-Type'] = 'application/json'; Promise.resolve().then(() => fetch(request.url, { 'headers': headers, 'method': request.method, 'referrerPolicy': 'no-referrer', 'credentials': 'include', 'body': JSON.stringify(request.data), 'mode': 'cors' })).then((res) => { resolve(res.json()); }).catch(() => { resolve({success: false, errorCode: -1}) }); }).then(sendResponse); } else if (request.type == 'xcApi') { new Promise(async (resolve) => { let headers = {}, data; headers.cookie = await getXcCookie(); console.log(headers) if (!request.isFormData) { headers['Content-Type'] = 'application/json'; data = JSON.stringify(request.data) } else { const formData = new FormData(); Object.keys(request.data).forEach(key => { const value = request.data[key] if (Array.isArray(value)) { value.forEach((subValue, i) => { formData.append(key + `[${i}]`, subValue) }) } else { if (key == "image") { //跳过image的处理 } else formData.append(key, request.data[key]) } }) data = formData } Promise.resolve().then(() => fetch(request.url, { 'headers': headers, 'method': request.method, 'referrerPolicy': 'strict-origin-when-cross-origin', 'credentials': 'include', 'body': data, 'mode': 'cors' })).then((res) => { resolve(res.json()); }).catch(() => { resolve({success: false, errorCode: -1}) }); }).then(sendResponse); } else if (request.type == 'notify') { chrome.notifications.create("" + Math.random(), { type: "basic", title: "TEMU助手", message: "您店铺【" + request.mallName + "】的商品【" + request.productName + "】成功加入发货台,请尽快处理", iconUrl: "./icons/48.png" }, null) } return true; }); chrome.action.onClicked.addListener(function () { chrome.tabs.create({ url: "./popup.html" }, function (tab) { console.log('tab is:' + tab); }); }); chrome.webRequest.onSendHeaders.addListener(details => { if (details.url && (details.url.indexOf('joinDeliveryGoodsOrderPlatform') != -1)) { details.requestHeaders.push({ name: 'Referer', value: 'https://seller.kuajingmaihuo.com/main/order-manage' }) for (let i = 0; i < details.requestHeaders.length; i++) { if (details.requestHeaders[i].name == 'Origin') { details.requestHeaders[i].value = 'https://seller.kuajingmaihuo.com' break; } } } else if (details.url && (details.url.indexOf('mms/userInfo') != -1)) { details.requestHeaders.push({ name: 'Referer', value: 'https://seller.kuajingmaihuo.com/main/order-manage' }) for (let i = 0; i < details.requestHeaders.length; i++) { if (details.requestHeaders[i].name == 'Origin') { details.requestHeaders[i].value = 'https://seller.kuajingmaihuo.com' break; } } } }, {urls: [""]}, ["requestHeaders", "extraHeaders"]); function getCookie() { const url = new URL("https://seller.kuajingmaihuo.com/"); let cStr = ''; chrome.cookies.getAll({domain: url.host}, (cookie) => { cookie.map((c) => { cStr += c.name + '=' + c.value + ';'; }); }); return cStr; } function getTemuCookie() { const url = new URL("https://www.temu.com/"); let cStr = ''; chrome.cookies.getAll({domain: url.host}, (cookie) => { cookie.map((c) => { cStr += c.name + '=' + c.value + ';'; }); }); return cStr; } function getSheinCookie() { const url = new URL("https://www.shein.com/"); let cStr = ''; chrome.cookies.getAll({domain: url.host}, (cookie) => { cookie.map((c) => { cStr += c.name + '=' + c.value + ';'; }); }); return cStr; } function getAliexpressCookie(link = "https://csp.aliexpress.com/") { let cStr = ''; return new Promise((resolve, reject) => { chrome.cookies.getAll({url: link}, (cookie) => { cookie.map((c) => { cStr += c.name + '=' + c.value + ';'; }); resolve(cStr); }); }) } function getXcCookie(link = "http://xc.rqlis.com:888/") { let cStr = ''; return new Promise((resolve, reject) => { chrome.cookies.getAll({url: link}, (cookie) => { cookie.map((c) => { cStr += c.name + '=' + c.value + ';'; }); resolve(cStr); }); }) } function formatParams(data) { const arr = [] for (let name in data) { arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name])) } return arr.join("&") }