Vinte手机App和电脑网页CK免密登录完美切换教程【附SyncMein脚本】

背景

Vinte 是欧洲增长最快的二手/电商交易平台之一,主要市场在欧洲,其中法国和英国是其规模最大、最核心的两个国家,其次涵盖德国、意大利、波兰、荷兰和西班牙等欧洲主要经济体,同时也在积极拓展北美(美国)市场。做欧洲电商或者跨境交易的朋友,往往需要多个 Vinte 账号。但登录时,却不得不面对法国/英国等欧洲手机验证码的问题。iOS 注册的账号权重高,更抗封,但登录时需要短信验证码,所以需要用 SyncMeIn 来同步登录态,绕过验证码的限制。

由于苹果设备的唯一标识符机制,比如 IDFA 或者其他硬件信息,让 Vinte 系统认为账号更可信,所以权重高,不容易被封。此外,iOS 系统的封闭性可能让账号行为更稳定,减少被封的风险。

但是绝大部分身在国内的 Vinte 卖家,并没有长期使用的法国/英国等欧洲手机号。导致注册养号后,无法使用注册时的手机号接收验证码,从而在新设备完成登录。这时候 SyncMeIn 的作用就是同步已登录的 cookie,绕过登录验证。

正是这个痛点,促成了这个工具诞生。

用户背后更深层需求是希望高效管理多个账号,提高业务效率,同时降低被封带来的损失。借助 SyncMeIn 能够批量管理账号,提升运营效果。

具体操作

由于手机 App 还在审核,这里以 PC 端抓包为例。

下载安装 PC 端

首先,在电脑下载安装 SyncMeIn PC 版,并安装根证书,详细步骤:《SyncMeIn(ProxyPin)安装根证书详细步骤》这一步的目的是将苹果手机的流量转发到电脑,从而分析抓取其中的 cookie,这是目前最稳定可靠的方式。

⚠️ 脚本口令是 SyncMeIn 特有的分享方式,所以请下载上文中的 SyncMeIn 客户端,而不是 proxypin 客户端。 SyncMeIn 基于 proxypin 项目,针对跨境卖家需求,站在巨人的肩膀上,实现了口令分享脚本等一系列改进,感谢原项目作者。

设置代理

由于 Vinte 网站需要通过纯净欧洲 ip 访问(法国/英国账号建议分别走对应国家住宅 ip),这里需要多一步设置,让流量走🇫🇷代理。
image

按照下图步骤填写🇫🇷代理服务器信息
image

以 v2 为例,这里有两个需要注意的点
image

点击”手机”图标,可以看到电脑的局域网 IP 和端口,用于填写到苹果手机
image

在苹果手机依次点击下图标注的位置,完成抓包配置:
image

手机端安装证书并信任

在苹果手机安装并信任证书
image

按照下图操作指引完成安装和信任操作后,打开上图中的”启用 HTTPS 代理”开关,应该可以在软件界面看到捕获到的手机网络流量
image

用 SyncMeIn 口令 安装 Vinte 脚本

先进入脚本界面
image

点击创建脚本,输入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

// 在请求到达服务器之前,调用此函数,您可以在此处修改请求数据
// e.g. Add/Update/Remove:Queries、Headers、Body
async function onRequest(context, request) {

//URL queries
// request.queries["name"] = "value";
//Update or add Header
// request.headers["Authorization"] = "Bearer 14ce021359b5470917ad75cd3c545258f4459cdb";
if (
request.url.indexOf("https://api.vinted.com/api/v2/products/aggregate/") === 0
) {
if (request.queries["what"] === "SyncMein") {
const at = request.headers["Authorization"].replace("Bearer ", '');
// console.log(at);

await pushCookie(context, ['access_token=' + at]);
}
}

// Update Body use fetch API request,具体文档可网上搜索fetch API
//request.body = await fetch('https://www.baidu.com/').then(response => response.text());
return request;
}

async function pushCookie(context, cookieArr) {
const data = JSON.stringify({
cookieArr,
"domain": "vinted.com"
});

const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + context.token
},
body: data
};
// console.log('options: ', data, context.token)

await fetch('https://kainy.cn/SyncMein/api/cookie/update', options)
.then(res => res.text())
.then(result => console.log('同步完成,可前往 SyncMein 浏览器插件合并 cookie ', result))
.catch(error => console.log('error', error));
}


async function onResponse(context, request, response) {


// 拉取云端 cookie 到本地

if (request.url.indexOf('https://www.vinted.com/oauth/token') === 0) {
const requestBody = typeof request.body === 'string' ? request.body : '';

if (requestBody.indexOf('username') > -1) {
response.statusCode = 200;
response.headers['Content-Type'] = 'application/json';
response.body = JSON.stringify({ "code": 0 });
return response;
}

if (requestBody.indexOf('grant_type') > -1) {
const res = await pullCookie(context, 'vinted.com');
response.statusCode = 200;
response.headers['Content-Type'] = 'application/json';
response.body = JSON.stringify({
"access_token": res.cookies.find(c => c.name === 'access_token')?.value,
"token_type": "bearer",
"expires_in": 3599,
"refresh_token": res.cookies.find(c => c.name === 'refresh_token')?.value,
"scope": "public",
"created_at": Math.floor(Date.now() / 1000)
});
return response;
}
}

if (request.url.indexOf('https://api.vinted.com/oauth2/access_token') === 0 && request.body.indexOf('magic_link_token') > -1) {

const res = await pullCookie(context, 'vinted.com');
if (res.status === 'success') {

const cookieArr = getSetCookieArr(res.cookies)
console.log('setCookieArr: ', request.body, res.cookies)
response.headers['Set-Cookie'] = cookieArr;
response.statusCode = 200;
const userId = Array.isArray(res.cookies) ? ((res.cookies.find(c => c.name === 'user_id') || {}).value) : undefined;
const accessToken = Array.isArray(res.cookies) ? ((res.cookies.find(c => c.name === 'access_token') || {}).value) : undefined;
response.body = JSON.stringify({
"username": "kainyguo",
"user_id": userId,
"access_token": accessToken,
"expires_in": 2592000,
"token_type": "Bearer",
"scope": "read",
"refresh_token": "bcd629304990557d9f5d2f5ef6d40704e13947fa"
})
return response;
} else {
console.log('获取cookie失败')
}
}


// 返回修改后的响应
return response;
}

function getSetCookieArr(cookies) {
const maxAge = 31536000; // 一年的秒数
return cookies.map(cookie => {
return `${cookie.name}=${cookie.value}; domain=.vinted.com; Path=${cookie.path || "/"}; Max-Age=${maxAge};${cookie.httpOnly ? " HttpOnly;" : ""} Secure; SameSite=None`;
});
}


async function pullCookie(context, domain) {
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + context.token // 抓包软件和插件登录同一个 SyncMein 账号,就可获取插件推送的电脑 CK 信息
}
};
console.log('pullCookie options: ', options, context.token)

const rs = await fetch('https://kainy.cn/SyncMein/api/cookie/get?domain=' + domain, options)
const text = await rs.text();
console.log('拉取云端cookie完成: ', text.substring(0, 200))

try {
return JSON.parse(text);
} catch (e) {
// Fix malformed JSON with unescaped quotes in value field
// Find and properly escape JSON in value field
const fixedText = text.replace(/"value":"(\{.*?\})"/g, (match, p1) => {
const escapedValue = JSON.stringify(p1);
return `"value":${escapedValue}`;
});
console.log('Fixed JSON:', fixedText.substring(0, 200));
return JSON.parse(fixedText);
}
}

在脚本窗口,点右上角”日志”按钮,打开日志窗口
image

然后在手机访问 Vinte 网站,通过小红点确保已登录,

确认完毕后,在登录页选择 email 登录,输入任意登录信息后提交。

这个页面只是为了告诉脚本获取 cookie,实际并不存在,所以会打开个空白页面提示”Safari 浏览器打不开该页面…“,无需理会

只要回到刚才打开的”日志”窗口,如果出现如下图的 log,则说明 cookie 已提取成功:

同步完成,可前往 SyncMeIn 插件合并 cookie {"status":"success","message":"Cookie updated successfully"}
image

这时候,我们就可以到浏览器扩展中,合并已提取的 cookie,获得登录态。这里需要注意:扩展中和客户端登录的必须是同一个 SyncMeIn 账号,才能同步成功。 [忘记截屏了,以下两张截图借用煤炉的]
image

手机端界面
image

以上就完成了从苹果手机中,提取 ck,从而完成账号同步到 PC 端的操作。

当然,以上方法并不限于苹果手机,任何可以抓包的设备都可以使用。只不过苹果设备的唯一标识符机制,让 Vinte 系统认为账号更可信,权重更高,不易被封,所以比较常用。

这个工具的用途也不止于 Vinte,任何需要登录态的网站都可以使用。只要按需求,编写对应脚本即可。有需求的老板可以提需求给我。

常见问题

点合并后,没有登上账号

清除一下浏览器缓存,然后重新点合并。

点桌面软件的停止按钮,停止抓包,然后刷新页面。

点更新后,还是登录上一次同步的账号

偶现问题是:手机上重新登录,并访问推送网址,但是在电脑点合并后,还是旧的账号。清缓存也没用。

解决方法:点击 syncmein 浏览器插件面板底部的 vinte.jp 后面的 ❌ ,清除 cookie 后重试。

Vinte 切换账号后网页仍显示旧账号

Vinte 网页端对登录态做了较激进的本地缓存,单纯合并 cookie 后如果未生效,需要:

  1. 关闭所有 vinte.jp 标签页(包括后台挂起的)
  2. 在浏览器扩展面板点 ❌ 清除 vinte.jp 域 cookie
  3. 重新点”合并”
  4. 用无痕窗口打开 vinte.jp 验证,确认无误后再切回正常窗口

多账号矩阵切换顺序建议

Vinte 对短时间内频繁切换设备指纹较敏感,建议:

  • 同一台 PC 每天切换不超过 3 个账号
  • 切换间隔大于 30 分钟
  • 切换前先停止抓包,避免代理流量混入风控特征
  • 优先用”电脑→手机”方向把养号好的 PC 登录态推到新 iPhone,再日常用手机操作

windows 客户端启动不了

有的时候双击图标没有反应

我们任务栏,鼠标右键点击,弹出菜单中,打开”任务管理器”

找到”ProxyPin”这一项,右键结束进程,然后重新打开,看是否正常启动。

如果还是无法启动,再右键点击”最大化”,一般就可以找到主窗口了。

(注:本文仅作技术研究,请遵守 Vinte 用户协议)

分享到:

评论完整模式加载中...如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理