如果只是想知道如何通过ip获取所在地城市信息,可直接看第三步.
如果搭建自己的支付平台,异地支付限制是必不可少的一环.因为市面上一些非法份子,会使用我们平台生成的付款码进行欺诈行为.这也是我们必须杜绝的一种现象.因此限制异地支付就是其中一种手段.
在上一篇文章【三方支付】java如何获取请求的来源ip 我们可以获取到用户发起支付时的ip,我们只需要再获取到用户扫码时的ip进行对比,即可知道当前是否为异地支付.当然我们不能直接对比ip,因为用户通常使用pc端发起支付获取付款码,而支付时采用的是移动端.两端未必处于同一个网络,因此ip也是不同的.
1. 引入 ip2region ,据ip2region官方给出的数据,ip准确率达到99.9%,而且查询速度也非常客观,可以满足我们的需求
org.lionsoul
ip2region
2.7.0
2. 导入ip2region的数据包
可以到官方进行下载xdb文件,并将文件放置到项目的resources下
3. 编写自己的工具类
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class Ip2Region {
protected static Searcher searcher;
static {
ClassPathResource resource = new ClassPathResource("ip2region/ip2region.xdb");
try (InputStream inputStream = resource.getInputStream()) {
byte[] cBuff = IoUtil.readBytes(inputStream);
searcher = Searcher.newWithBuffer(cBuff);
} catch (IOException e) {
log.error("获取ip文件失败", e);
}
}
/**
* 根据ip从 ip2region.db 中获取地理位置
*
* @param ip
* @return 地理位置
*/
public static Map getCityInfo(String ip) {
//数据格式: 国家|区域|省份|城市|ISP
//192.168.31.160 0|0|0|内网IP|内网IP
//47.52.236.180 中国|0|香港|0|阿里云
//220.248.12.158 中国|0|上海|上海市|联通
//164.114.53.60 美国|0|华盛顿|0|0
HashMap cityInfo = new HashMap<>(7);
try {
String searchIpInfo = searcher.search(ip);
log.info("ip查询:{},查询结果:{}", ip, searchIpInfo);
if (StrUtil.isNotBlank(searchIpInfo)) {
String[] splitIpInfo = searchIpInfo.split("\\|");
cityInfo.put("ip", ip);
cityInfo.put("searchInfo", searchIpInfo);
cityInfo.put("country", splitIpInfo[0]);
cityInfo.put("region", splitIpInfo[1]);
cityInfo.put("province", splitIpInfo[2]);
cityInfo.put("city", splitIpInfo[3]);
cityInfo.put("ISP", splitIpInfo[4]);
return cityInfo;
}
} catch (Exception e) {
log.info("failed to search({}): {}", ip, e);
}
return null;
}
/**
* 根据ip从 ip2region.db 中获取省份
*
* @param ip
* @return 地理位置
*/
public static String getProvince(String ip) {
Map cityInfo = getCityInfo(ip);
if (cityInfo != null) {
return cityInfo.get("province");
}
else {
return null;
}
}
}
4. 使用方式 这里我们获取的是省份,也可以通过实际情况进行调整
// 获取扫码时的ip
String clientIp = IpUtil.getClientIp();
String city1 = Ip2Region.getProvince(clientIp);
// 获取下单时的ip
String city2 = Ip2Region.getProvince(order.getClientIp());
log.info("订单校验ip,订单号:{},下单ip:{},支付ip:{}", id, order.getClientIp(), clientIp);
if (StrUtil.isNotBlank(city1) && StrUtil.isNotBlank(city2) && !city1.equals(city2)) {
return Result.res(ResultEnum.IP_ERROR);
}
以上就是通过ip对比省份,进行异地支付的限制