发表于 2024-8-27 15:17

申请会员ID:ymyuuu

1. **申请ID**:ymyuuu
2. **个人邮箱**:ymyuuu@qq.com
3. **原创技术文章**:

#### **逆向工程:凤鸟查询公司信息API的分析与实现**

**一、背景与动机:**
通过API接口获取企业信息,既能提高效率,也能保障数据的实时性和准确性。基于此,我对凤鸟查询公司信息的API进行了逆向工程研究,编写了一段代码,能够自动化完成企业信息的获取和处理。

**二、功能模块详解:**

1. **身份验证模块**:
   - **功能描述**:获取授权令牌是与API交互的第一步。此模块通过模拟用户登录操作,向API请求授权令牌(Token),该令牌将在后续的数据查询中用作认证凭据。
   - **代码实现**:
   ```javascript
   async function getAuthorizationToken() {
       try {
         const response = await fetch("https://riskbird.com/api/auth/login", {
         method: "POST",
         headers: { "Content-Type": "application/json" },
         body: JSON.stringify({
             captcha: "",
             inviteCode: null,
             mobile: "xx", //账号
             password: "xx",//密码
             smsCode: "",
             type: "password"
         }),
         });

         const data = await response.json();
         if (data.code === 20000) {
         return data.data.token;
         } else {
         throw new Error("查询失败");
         }
       } catch {
         throw new Error("查询失败");
       }
   }
   ```
   - **技术要点**:在发送POST请求时,附带必要的登录信息(如手机号和密码),API会在验证通过后返回一个授权令牌,用于后续的查询请求。

2. **查询数据模块**:
   - **功能描述**:通过授权令牌和用户提供的查询关键词,从API获取目标企业的详细信息。
   - **代码实现**:
   ```javascript
   async function fetchQueryData(token, appUuid, searchKey) {
       try {
         const response = await fetch("https://riskbird.com/riskbird-api/newSearch", {
         method: "POST",
         headers: {
             "Content-Type": "application/json",
             "Cookie": `app-uuid=${appUuid}; app-device=WEB; token=${token}`,
         },
         body: JSON.stringify({
             pageNo: 1,
             queryType: "1",
             range: 10,
             searchKey: searchKey,
             selectConditionData: "{\"regionid\":\"\",\"status\":\"\",\"nicid\":\"\",\"sort_field\":\"\"}"
         }),
         });

         const data = await response.json();
         if (!data.success) {
         throw new Error("查询失败");
         }

         return data.data.list.map((item) => {
         const formattedItem = {
             companyName: item.ENTNAME_SEARCH?.replace(/<\/?[^>]+(>|$)/g, ""),
             historicalNames: item.ENTNAME_history || undefined,
             status: item.ENTSTATUS || undefined,
             legalRepresentative: item.faren || undefined,
             unifiedSocialCreditCode: item.UNISCID || undefined,
             registrationNumber: item.REGNO || undefined,
             personId: item.personid || undefined,
             phoneNumber: item.tels?.join(", ") || undefined,
             email: item.emails?.join(", ") || undefined,
             registeredCapital: item.regConcat || undefined,
             establishmentDate: item.ESDATE || undefined,
             address: item.DOM || undefined,
             tags: item.tags || undefined,
             riskTags: item.risk_tag_names || undefined,
             website: item.WEBSITE || undefined
         };
         
         return Object.fromEntries(Object.entries(formattedItem).filter(() => v !== undefined));
         });
       } catch {
         throw new Error("查询失败");
       }
   }
   ```
   - **技术要点**:在这段代码中,授权令牌和UUID作为请求的必要凭据发送给API,返回的数据经过处理后,去除HTML标签及空字段,以简化和优化数据结构,便于前端展示。

3. **数据处理模块**:
   - **功能描述**:将API返回的复杂数据结构进行整理、清洗,提取出用户关心的核心信息,并以JSON格式返回前端。
   - **代码实现**:
   ```javascript
   function createSuccessResponse(data) {
       return new Response(JSON.stringify({
         status: "success",
         message: "逆向公司数据成功",
         coinfo: data
       }), {
         headers: { "Content-Type": "application/json; charset=utf-8" },
       });
   }
   ```
   - **技术要点**:通过提取API响应中的关键信息,如公司名称、法定代表人、注册资本等,确保数据的完整性和准确性。同时过滤掉空值字段,以减少不必要的信息冗余。

4. **错误处理机制**:
   - **功能描述**:在程序的各个关键环节加入了详细的错误处理逻辑,确保在任何异常情况下,程序都能给出明确的错误信息,避免程序崩溃。
   - **代码实现**:
   ```javascript
   function createErrorResponse(message, status) {
       return new Response(JSON.stringify({
         status: "error",
         message: message
       }), {
         status: status,
         headers: { "Content-Type": "application/json; charset=utf-8" },
       });
   }
   ```
   - **技术要点**:错误处理不仅确保了程序的稳定性,还能向用户明确反馈问题所在,便于后续的调试和修正。

**三、UUID生成的实现:**
   - **功能描述**:为确保每个请求的唯一性,我实现了一个UUID生成器,用于为每次查询生成一个随机的UUID。
   - **代码实现**:
   ```javascript
   function generateUUID() {
       return ( + -1e3 + -4e3 + -8e3 + -1e11).replace(//g, c =>
         (c ^ crypto.getRandomValues(new Uint8Array(1)) & 15 >> c / 4).toString(16)
       );
   }
   ```
   - **技术要点**:UUID生成采用了JavaScript的`crypto.getRandomValues`方法,确保每次生成的UUID都具有高度的随机性,防止重复请求导致的冲突。

**四、部署方式:**
1. **登录 Cloudflare 账号**:
   - 访问 (https://www.cloudflare.com/) 并登录到你的账号。如果还没有账号,请先注册一个免费的 Cloudflare 账户。

2. **创建一个新的 Worker**:
   - 登录后,点击左侧菜单中的“Workers”。
   - 在“Workers”页面中,点击“Create a Service”按钮。
   - 在弹出的窗口中,为你的服务起一个名称,比如“CompanyInfoAPI”,然后点击“Create Service”。
   - 在接下来的页面中,选择“Start from scratch”模板,这会给你一个空白的 JavaScript 文件来编写你的代码。

3. **粘贴代码**:
   - 删除编辑器中默认的代码。
   - 将以下完整代码粘贴到编辑器中:

   ```javascript
   async function handleRequest(request) {
       const url = new URL(request.url);

       // 验证路径和方法
       if (url.pathname !== "/api" || !["GET", "POST"].includes(request.method)) {
         return createErrorResponse("不许调皮o", 400);
       }

       // 获取查询参数
       const searchKey = request.method === "GET"
         ? url.searchParams.get("searchKey")
         : (await request.json()).searchKey;

       if (!searchKey) {
         return createErrorResponse("不许调皮o", 400);
       }

       try {
         const token = await getAuthorizationToken();
         const appUuid = generateUUID(); // 生成随机 UUID
         const queryData = await fetchQueryData(token, appUuid, searchKey);
         return createSuccessResponse(queryData);
       } catch {
         return createErrorResponse("查询失败", 500);
       }
   }

   async function getAuthorizationToken() {
       try {
         const response = await fetch("https://riskbird.com/api/auth/login", {
         method: "POST",
         headers: { "Content-Type": "application/json" },
         body: JSON.stringify({
             captcha: "",
             inviteCode: null,
             mobile: "xx", //账号
             password: "xx",//密码
             smsCode: "",
             type: "password"
         }),
         });

         const data = await response.json();
         if (data.code === 20000) {
         return data.data.token;
         } else {
         throw new Error("查询失败");
         }
       } catch {
         throw new Error("查询失败");
       }
   }

   async function fetchQueryData(token, appUuid, searchKey) {
       try {
         const response = await fetch("https://riskbird.com/riskbird-api/newSearch", {
         method: "POST",
         headers: {
             "Content-Type": "application/json",
             "Cookie": `app-uuid=${appUuid}; app-device=WEB; token=${token}`,
         },
         body: JSON.stringify({
             pageNo: 1,
             queryType: "1",
             range: 10,
             searchKey: searchKey,
             selectConditionData: "{\"regionid\":\"\",\"status\":\"\",\"nicid\":\"\",\"sort_field\":\"\"}"
         }),
         });

         const data = await response.json();
         if (!data.success) {
         throw new Error("查询失败");
         }

         // 提取和简化所需字段并过滤空字段
         return data.data.list.map((item) => {
         const formattedItem = {
             companyName: item.ENTNAME_SEARCH?.replace(/<\/?[^>]+(>|$)/g, ""),
             historicalNames: item.ENTNAME_history || undefined,
             status: item.ENTSTATUS || undefined,
             legalRepresentative: item.faren || undefined, // 添加 `faren` 字段
             unifiedSocialCreditCode: item.UNISCID || undefined,
             registrationNumber: item.REGNO || undefined,
             personId: item.personid || undefined,
             phoneNumber: item.tels?.join(", ") || undefined,
             email: item.emails?.join(", ") || undefined,
             registeredCapital: item.regConcat || undefined,
             establishmentDate: item.ESDATE || undefined,
             address: item.DOM || undefined,
             tags: item.tags || undefined,
             riskTags: item.risk_tag_names || undefined,
             website: item.WEBSITE || undefined
         };
         
         // 过滤掉值为 undefined 的字段
         return Object.fromEntries(Object.entries(formattedItem).filter(() => v !== undefined));
         });
       } catch {
         throw new Error("查询失败");
       }
   }

   // 生成随机 UUID
   function generateUUID() {
       return ( + -1e3 + -4e3 + -8e3 + -1e11).replace(//g, c =>
         (c ^ crypto.getRandomValues(new Uint8Array(1)) & 15 >> c / 4).toString(16)
       );
   }

   function createSuccessResponse(data) {
       return new Response(JSON.stringify({
         status: "success",
         message: "逆向公司数据成功",
         coinfo: data
       }), {
         headers: { "Content-Type": "application/json; charset=utf-8" },
       });
   }

   function createErrorResponse(message, status) {
       return new Response(JSON.stringify({
         status: "error",
         message: message
       }), {
         status: status,
         headers: { "Content-Type": "application/json; charset=utf-8" },
       });
   }

   addEventListener("fetch", (event) => {
       event.respondWith(handleRequest(event.request));
   });
   ```

4. **保存并部署**:
   - 确认代码已经正确粘贴到编辑器中,点击页面右上角的“Save and Deploy”按钮。
   - 部署完成后,Cloudflare 将为你的 Worker 生成一个唯一的 URL,你可以通过这个 URL 来访问你的 API。

5. **测试 API**:
   - 部署完成后,你可以通过访问生成的 URL 来测试 API。你可以在浏览器中直接访问,例如你可以访问我的示例:
   ```
    https://aged-cherry-0f81.ymyuuu.workers.dev/api?searchKey=公司名称
   ```
   - 也可以使用 Postman 等工具,发送 GET 或 POST 请求来查询公司信息。
   - **请注意,复制代码之前请讲账号密码替换成自己在凤鸟官网注册的账号密码。**

**四、总结**
   - 通过本次逆向工程,我成功实现了对凤鸟公司信息查询API的完整调用,掌握了API请求、身份认证、数据处理等关键技术点。
   - 此代码可以应用于多个场景,如企业信息自动化采集、商业调查分析等,为用户提供了便捷而高效的数据查询工具。
   - **本人郑重声明,以上代码及技术文章内容为本人原创,未有抄袭或冒用他人作品的行为。如有任何疑问或需进一步验证,本人愿意提供相关的开发记录和证明材料。请论坛管理团队予以审核,谢谢!**

Hmily 发表于 2024-8-27 17:51

你这是AI帮你写的吧?

发表于 2024-8-27 19:30

Hmily 发表于 2024-8-27 17:51
你这是AI帮你写的吧?

他就帮我改了一下md格式,看着稍微顺眼一点,代码绝对是我自己写的

Hmily 发表于 2024-8-28 11:19

游客 183.199.24.x 发表于 2024-8-27 19:30
他就帮我改了一下md格式,看着稍微顺眼一点,代码绝对是我自己写的

抱歉,未能达到申请要求,申请不通过,可以关注论坛官方微信(吾爱破解论坛),等待开放注册通知。
页: [1]
查看完整版本: 申请会员ID:ymyuuu