整体流程

创建套件 - 配置协议 - 上架协议 - 创建第三方系统适配器 - 创建第三方系统参数要求 - 适配协议 - 编写脚本 - 上架适配器
业务集成 - 上架应用 - 安装应用 - 配置协议及适配器 - 使用

适配厂商信息

定义阶段

创建API套件

套件名称:IP地址查询
套件简介:提供快速精准的IP地址查询能力

添加状态码

我的套件 > 查看协议 > 状态码

代码 描述
200 查询成功
1001 无效的IP

添加API协议

我的套件 > 查看协议 > 创建API协议

基本信息:
协议名称:IP地址查询
请求类型:POST
接口类型:同步
协议URL:/ip/query
协议说明:通过IP地址查询返回具体的地理位置信息

请求头:

名称 必填 类型 默认值 备注
- - - - -

请求参数:

名称 必填 类型 默认值 备注
ip string - 目标IP地址

返回参数:

名称 必填 类型 默认值 备注
code number 状态码
msg string 信息描述
sucess string 成功标识(true 成功 false 失败)
data object 数据
data -> ip string 目标IP地址
data -> address string 物理位置
  • API套件上架

适配阶段

API模型适配

  • 创建适配器

我的套件 > 查看适配器 > 创建适配器

基本信息

适配器名称: 淘宝IP查询
适配器说明:由淘宝提供的的IP查询服务

适配器参数

注意:这里的参数只是为了演示用,真实不应该是这两个参数

参数名称 参数标识 说明
服务器地址 server 在线工具服务器地址(如:https://ip.taobao.com/
查询路由 router 在线工具ip查询路由(如:outGetIpInfo)

适配代码

import cn.hutool.http.HttpRequest
import cn.hutool.json.JSONObject
import cn.hutool.json.JSONUtil
import cn.hutool.log.StaticLog
import cn.flyrise.pai.apistore.util.GroovyScriptUtil

String main(){
    // 淘宝:https://ip.taobao.com/outGetIpInfo
    // 太平洋电脑网:http://whois.pconline.com.cn/ipJson.jsp
    server = param.getStr("server");
    result = HttpRequest.get(server + param.getStr("router"))
            .header("Referer", param.getStr("server"))
            .timeout(3000)
            .form("ip", data.getStr("ip"))
            .form("json", "true") //兼容太平洋电脑网
            .execute().body()

    if (JSONUtil.isJson(result)) {
        JSONObject json = JSONUtil.parse(result);
        StaticLog.error("在线调试信息: {} ", JSONUtil.toJsonPrettyStr(json))
        // 淘宝
        if (server.contains("taobao") && json.getInt("code") == 0 ) {
            json = json.getObj("data")
            return JSONUtil.createObj().set("ip", data.getStr("ip"))
                    .set("address", json.getStr("country") + " " + json.getStr("region") + " " + json.getStr("city") + " " + json.getStr("isp"))
                    .set("common-login", GroovyScriptUtil.invokeMethod("login"))
        } 
        // 太平洋电脑网
        else if ( server.contains("pconline") && json.getStr("err") == "" ) {
            return JSONUtil.createObj().set("ip", data.getStr("ip"))
                    .set("address", json.getStr("addr"))
                    .set("common-login", GroovyScriptUtil.invokeMethod("login"))
        }
        // 错误
        else {
            return JSONUtil.createObj().set("ip", data.getStr("ip")).set("address","查询失败").set("result", json)
                    .set("common-login", GroovyScriptUtil.invokeMethod("login"))
        }
    }


    return JSONUtil.createObj().set("ip", data.getStr("ip")).set("address","解析失败").set("result", result)
}

main()

在线调试

淘宝(有QPS限制)

  • 适配器参数:
    server: https://ip.taobao.com
    router: /outGetIpInfo

  • 请求参数:
    ip => 219.131.197.178

太平洋电脑网

集成阶段

API模型集成

  • 申请授权并添加API套件

我的套件 > API权限 > 申请开通 > 添加API套件 > IP地址查询

业务集成

后端接口

配置参数:

bootstrap-dev.yml

pai:
  apistore:
    config:
      api-server: http://pai.flyrise.cn/apistore-api
      ip-router: /open/v1/1/ip/query
      client-id: kysK******K4zqdf
      secret-key: 3ylsWI******daWTOSNj

ApiProperties.java

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties("pai.apistore.config")
public class ApiProperties {

    /**
     * APIStore 服务地址
     */
    private String apiServer;

    /**
     * APIStore 接入ID
     */
    private String clientId;
    /**
     * APIStore 接入Key
     */
    private String secretKey;
    /**
     * IP查询路由地址
     */
    private String ipRouter;

    public String getApiServer() {
        return apiServer;
    }

    public void setApiServer(String apiServer) {
        this.apiServer = apiServer;
    }

    public String getIpRouter() {
        return ipRouter;
    }

    public void setIpRouter(String ipRouter) {
        this.ipRouter = ipRouter;
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }
}

IpAddressVO.java

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

@ApiModel("IP地址信息")
public class IpAddressVO {

    @ApiModelProperty("目标IP地址")
    String ip;

    @ApiModelProperty("物理地址")
    String address;

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

IIpAddressService.java

import cn.flyrise.pai.attendancestd.model.vo.IpAddressVO;

/**
 * IP查询服务
 */
public interface IIpAddressService {

    /**
     * 根据IP查询出实际的物理地址
     *
     * @param ip 目标IP地址
     * @return 物理地址
     */
    IpAddressVO query(String ip);
}

IpAddressServiceImpl.java

签名方式为:md5(body + configId + timestamp + secureKey)

import cn.flyrise.common.core.exception.CommonException;
import cn.flyrise.pai.attendancestd.config.ApiProperties;
import cn.flyrise.pai.attendancestd.model.vo.IpAddressVO;
import cn.flyrise.pai.attendancestd.service.IIpAddressService;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Service
public class IpAddressServiceImpl implements IIpAddressService {
    @Autowired
    ApiProperties apiProperties;

    @Override
    public IpAddressVO query(String ip) {
        final String jsonBody = JSONUtil.createObj().set("ip", ip).toString();
        final String timestamp = String.valueOf(System.currentTimeMillis());
        final String configId = getConfigId();
        final String sign = SecureUtil.md5(jsonBody + configId + timestamp + apiProperties.getSecretKey());
        final String result = HttpRequest.post(apiProperties.getApiServer().concat(apiProperties.getIpRouter()))
                .header("X-Client-Id", apiProperties.getClientId())
                .header("X-Timestamp", timestamp)
                .header("X-Config-Id", configId)
                .header("X-Sign", sign)
                .body(jsonBody)
                .timeout(3000).execute().body();
        if (JSONUtil.isJson(result)) {
            JSONObject json = JSONUtil.parseObj(result);
            if (json.getBool("success")) {
                return JSONUtil.toBean(json.getJSONObject("data"), IpAddressVO.class);
            }
        }
        throw new CommonException("1001", "无效的IP");
    }

    private String getConfigId() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String result = HttpRequest.get(apiProperties.getApiServer().concat("/adapter/param/config/list"))
                .header("Authorization", request.getHeader("Authorization"))
                .form("appCode", "cn.flyrise.attendance.std")
                .timeout(3000).execute().body();
        if (JSONUtil.isJson(result)) {
            JSONObject json = JSONUtil.parseObj(result);
            if (json.getBool("success") && json.getJSONArray("data").size() > 0) {
                return json.getJSONArray("data").getJSONObject(0).getStr("id");
            }
        }
        return null;
    }
}

IpAddressController.java


import cn.flyrise.common.core.domain.Reply;
import cn.flyrise.pai.attendancestd.model.vo.IpAddressVO;
import cn.flyrise.pai.attendancestd.service.IIpAddressService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/ip")
@Api(tags = "IP地址接口")
public class IpAddressController {

    @Autowired
    IIpAddressService service;

    @GetMapping("query")
    @ApiOperation("查询IP物理地址")
    @ApiImplicitParam(name = "ip", value = "目标IP地址", required = true, example = "xxx.xxx.xxx.xxx")
    public Reply<IpAddressVO> query(String ip) {
        return Reply.success(service.query(ip));
    }
}

前端页面

nuxt.config.js

const LOCAL_PROXY_OPTIONS = {
  enable: true, // 是否启用
  target: 'http://127.0.0.1:8080',
  proxies: [
    {
      path: 'attendance-std-api', // 替换成业务后端api
    },
  ]
}

pages/ip.vue

<template>
  <el-form ref="form" label-width="80px" style="margin:100px auto;width: 300px">
    <el-form-item label="IP地址">
      <el-input v-model="ip"></el-input>
    </el-form-item>
    <el-form-item label="物理地址">
      <div v-text="address"></div>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">查询</el-button>
    </el-form-item>
  </el-form>
</template>


<script>
import request from "~/plugins/request";

export default {
  data() {
    return {
      ip: "",
      address: "",
    };
  },
  methods: {
    onSubmit() {
      request({
        url: "/attendance-std-api/ip/query",
        method: "GET",
        params: { ip: this.ip },
      }).then((res) => {
        this.address = res.data.address
      });
    },
  },
};
</script>

安装阶段

业务上架安装

开发者后台 > 应用中心 > 飞智云考勤(标准版)> 添加版本 > 配置 微应用(IP地址查询 /pages/ip)
开发者后台 > 我的套件 > 飞智云考勤(标准版)> 沙箱 > 一键更新

配置适配器及参数

控制台 > 应用 > 飞智云考勤(标准版) > 协议配置 > 添加适配器
server: https://ip.taobao.com/
router: outGetIpInfo

使用阶段

业务使用演示

工作台 > 应用 > 飞智云考勤(标准版) > IP地址查询
183.45.175.222
219.131.197.178

文档更新时间: 2023-05-19 11:35   作者:管理员