【支付平台】java springboot 通过ip获取所在地城市信息

         如果只是想知道如何通过ip获取所在地城市信息,可直接看第三步.

        如果搭建自己的支付平台,异地支付限制是必不可少的一环.因为市面上一些非法份子,会使用我们平台生成的付款码进行欺诈行为.这也是我们必须杜绝的一种现象.因此限制异地支付就是其中一种手段.

        在上一篇文章【三方支付】java如何获取请求的来源ip 我们可以获取到用户发起支付时的ip,我们只需要再获取到用户扫码时的ip进行对比,即可知道当前是否为异地支付.当然我们不能直接对比ip,因为用户通常使用pc端发起支付获取付款码,而支付时采用的是移动端.两端未必处于同一个网络,因此ip也是不同的.

  •         第一步,如果我们接入是三方支付,通常三方支付会返回给我们一个二维码地址,或者收银台地址,这时候用户扫码时进入的就是三方支付的支付页面,我们是无法获取到用户ip的,这时候我们需要做的便是生成自己的二维码,用户扫描二维码进入是我们自己的页面(也可以是接口,获取ip之后直接跳转到三方支付,通常是制作一个移动端的页面,展示一些订单信息和风险提示等),只要经过我们的服务就可以拿到用户扫码时的ip了.

  •         第二步,对比ip所在城市的信息.通过上面的步骤,我们拿到发起支付时的ip和扫码时的ip.我们就可以通过ip对应的城市进行对比了.目前市面上通过ip获取城市的开放接口有很多,基本都是收费的,免费的通常ip库不全,有可能查不到地址.类似 百度地图,高德地图 都有响应的接口供大家使用.也可以到阿里云市场进行购买(相对优惠很多).

  •         第三步, 如何通过ip获取这里我们介绍一种免费的,内置在我们自己系统的一种获取ip城市信息的方式,这种方式既省钱又不需要担心网络问题

1. 引入 ip2region ,据ip2region官方给出的数据,ip准确率达到99.9%,而且查询速度也非常客观,可以满足我们的需求

        
            org.lionsoul
            ip2region
            2.7.0
        

2. 导入ip2region的数据包

可以到官方进行下载xdb文件,并将文件放置到项目的resources下

【支付平台】java springboot 通过ip获取所在地城市信息_第1张图片

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对比省份,进行异地支付的限制

你可能感兴趣的:(支付平台,tcp/ip,网络协议,网络,java,spring,boot)