某平台登录和支付接口分析与脚本实现
字数 1937 2025-08-10 16:34:34
某平台登录和支付接口分析与脚本实现教学文档
1. 目标概述
本文档详细分析某平台的登录和支付接口流程,重点在于获取支付码(一串20位数字)的实现方法。支付码用于生成条形码和二维码,是支付过程中的关键数据。
2. 数据获取流程
- 用户登录:访问
https://xxx/plat/login?synAccessSource=h5&loginFrom=h5&type=logout - 跳转主界面:登录成功后跳转到
https://xxx/plat/shouyeUser - 进入支付页面:点击付款按钮,访问
https://xxx/plat/pay?nodeId=15&loginFrom=h5 - 获取支付码:最终目标是获取20位数字的支付码(如40778129653692506121)
3. 关键数据包分析
3.1 认证包 (ID:37)
- 请求类型:POST
- URL:
https://xxx/berserker-auth/oauth/token - 请求头:
Authorization: Basic bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm06bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm1fc2VjcmV0Content-Type: application/x-www-form-urlencoded
- 请求体:
username=XXXXXX&password=XXXXXX&grant_type=password&scope=all&loginFrom=h5&logintype=sno&device_token=h5&synAccessSource=h5 - 响应:包含关键参数
access_token
3.2 支付码请求包
- 请求类型:GET
- URL:
https://xxx/berserker-app/ykt/tsm/batchGetBarCodeGet?account=95633&payacc=%23%23%23&paytype=1&synAccessSource=h5 - 请求头:
synjones-auth: bearer [access_token]
- 响应:包含支付码数组
barcode
3.3 WebSocket通讯包 (ID:68)
- URL:
wss://xxx/websocket/mobile_service_platform/qrcode_ykt/payCode - 通讯内容:
{ "appCode": "mobile_service_platform", "module": "qrcode_ykt", "userId": "40778129653692506121" } - 作用:将支付码发送给服务器进行登记
4. 前端代码分析
4.1 支付码存储机制
支付码存储在本地存储(localStorage)中,键名为barcode,结构如下:
{
expires: 172800,
barcode: [
"40556116680367244682",
"40427500396723912935",
// ...更多支付码
],
time: 1692168476261,
icon: "cardpay",
id: 1
}
4.2 关键代码位置
- 支付码赋值逻辑位于
chunk-fa993c88.cf44569d.js文件中 - 主要处理流程:
- 从localStorage读取
barcode - 处理支付码数组(过滤、删除首元素等)
- 将处理后的支付码赋值给
this.qrcode
- 从localStorage读取
5. Python脚本实现
5.1 依赖库
import requests
import json
import time
import websockets
import asyncio
5.2 认证函数
def get_token():
url = "https://xxx/berserker-auth/oauth/token"
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm06bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm1fc2VjcmV0",
# 其他请求头...
}
data = "username=XXXXXX&password=XXXXXX&grant_type=password&scope=all&loginFrom=h5&logintype=sno&device_token=h5&synAccessSource=h5"
response = requests.post(url, headers=headers, data=data, verify=False)
return json.loads(response.content)["access_token"]
5.3 获取支付码
def get_qrcode(token):
url = "https://xxx/berserker-app/ykt/tsm/batchGetBarCodeGet?account=95633&payacc=%23%23%23&paytype=1&synAccessSource=h5"
headers = {
"synjones-auth": f"bearer {token}",
# 其他请求头...
}
response = requests.get(url, headers=headers, verify=False)
return json.loads(response.content)["data"]["barcode"][0]
5.4 WebSocket通讯
async def send_qrcode(qrcode):
async with websockets.connect(
"wss://xxx/websocket/mobile_service_platform/qrcode_ykt/payCode"
) as ws:
ws_data = {
"appCode": "mobile_service_platform",
"module": "qrcode_ykt",
"userId": qrcode,
}
await ws.send(json.dumps(ws_data))
5.5 主流程
if __name__ == "__main__":
token = get_token()
qrcode = get_qrcode(token)
asyncio.run(send_qrcode(qrcode))
6. JavaScript油猴脚本实现
6.1 脚本元信息
// ==UserScript==
// @name example.com
// @namespace http://tampermonkey.net/
// @version 0.1
// @description 获取支付码并生成二维码
// @author BrokenClient
// @match *://example.com/*
// @match *://*.example.com/*
// @grant GM_xmlhttpRequest
// @require https://cdn.jsdelivr.net/npm/qrcodejs2@0.0.2/qrcode.min.js
// @connect xxx
// ==/UserScript==
6.2 获取Token
function get_token() {
return new Promise((resolve) => {
GM_xmlhttpRequest({
method: "POST",
url: "https://xxx/berserker-auth/oauth/token",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm06bW9iaWxlX3NlcnZpY2VfcGxhdGZvcm1fc2VjcmV0",
// 其他请求头...
},
data: "username=xxxxxx&password=xxxxxx&grant_type=password&scope=all&loginFrom=h5&logintype=sno&device_token=h5&synAccessSource=h5",
onload: (response) => {
resolve(JSON.parse(response.responseText).access_token);
}
});
});
}
6.3 获取支付码
function get_qrcode(token) {
return new Promise((resolve) => {
GM_xmlhttpRequest({
method: "GET",
url: "https://xxx/berserker-app/ykt/tsm/batchGetBarCodeGet?account=95633&payacc=%23%23%23&paytype=1&synAccessSource=h5",
headers: {
"synjones-auth": "bearer " + token,
// 其他请求头...
},
onload: (response) => {
resolve(JSON.parse(response.responseText).data.barcode[0]);
}
});
});
}
6.4 WebSocket通讯
function setup_websocket(qrcode) {
let ws_data = {
appCode: "mobile_service_platform",
module: "qrcode_ykt",
userId: qrcode,
};
let ws = new WebSocket(
"wss://xxx/websocket/mobile_service_platform/qrcode_ykt/payCode"
);
ws.onopen = () => {
ws.send(JSON.stringify(ws_data));
};
}
6.5 主函数
(async function() {
'use strict';
// 创建二维码显示区域
document.getElementsByTagName("div")[0].remove();
let div_qrcode = document.createElement("div");
div_qrcode.id = "qrcode";
div_qrcode.style = "position:absolute;width:80%;height:60wh;top:5rem;";
document.body.appendChild(div_qrcode);
// 初始化二维码生成器
const qrcode_img = new QRCode("qrcode", {
width: 0.8 * window.innerWidth,
height: 0.8 * window.innerWidth,
});
// 获取token和支付码
let token = await get_token();
let qrcode = await get_qrcode(token);
// 生成二维码并建立WebSocket连接
qrcode_img.makeCode(qrcode);
setup_websocket(qrcode);
})();
7. 移动端实现注意事项
- 浏览器选择:普通浏览器如Via、X浏览器可能无法运行油猴脚本,推荐使用狐猴浏览器安装油猴插件管理器
- 脚本兼容性:确保脚本在移动端的显示效果,调整二维码大小等参数
- 权限问题:移动端可能需要额外授权才能访问WebSocket和跨域请求
8. 安全注意事项
- 敏感信息保护:在实际使用中,应妥善保管用户名、密码和access_token
- HTTPS验证:生产环境应启用SSL证书验证,避免中间人攻击
- 频率限制:避免频繁请求,防止被服务器封禁
- 本地存储:注意清理localStorage中的敏感数据
9. 排错指南
-
认证失败:
- 检查用户名密码是否正确
- 验证Authorization头是否正确
- 确认grant_type和scope参数
-
支付码获取失败:
- 检查access_token是否有效
- 验证请求URL和参数是否正确
- 检查响应数据结构是否变化
-
WebSocket连接失败:
- 检查URL是否正确
- 验证网络环境是否支持WebSocket
- 检查发送的数据格式是否符合要求
-
油猴脚本不执行:
- 检查@match规则是否正确
- 确认浏览器支持油猴脚本
- 检查是否有其他脚本冲突
10. 优化建议
- 错误处理:添加更完善的错误处理机制
- 自动刷新:实现支付码过期自动刷新功能
- UI改进:优化二维码显示界面
- 缓存机制:合理利用localStorage缓存token和支付码
- 日志记录:添加操作日志记录功能
通过本文档的详细分析,开发者可以全面了解该平台的登录和支付接口流程,并能够实现自动获取支付码的功能。