【支付系统】接入多家支付之策略模式

        在常见的商城类平台,一般会接入微信,支付宝等支付方式.同时为了避免支付通道出现问题导致无法支付的情况,也会介入一些其他支付公司的通道.在程序里我们该如何分辨,和调用不同公司的支付通道呢?

        1. 首先用户在页面上下单,会给服务器传递多个必要的参数, 支付方式(微信,支付宝),和支付通道(支付平台).首先页面上的支付方式,一定是动态查询出来的,当用户选择下单,一定要把通道信息发送给服务器.

        2. 在第一步中后端已经拿到通道信息,我们会根据传递的通道信息觉得调用哪一家支付平台的接口

        当然,是可以使用if判断是哪个支付平台,但这样既不美观 也不方便维护


if(通道==支付平台1){
    平台1.下单
}else if(通道==支付平台2){
    平台2.下单
}

        设计模式之策略模式

1. 定义支付平台的公共接口:这里面最主要的就是 getType(),相当于给每个平台定义唯一标识

public interface PayService {

	/**
	 * 获取当前通道类型标识
	 *
	 */
	String getType();

	/**
	 * 支付
	 *
	 */
	PayResult pay(Order order) throws Exception;

	/**
	 * 退款
	 *
	 */
	RefundResult refund(Order order);

	/**
	 * 支付订单查询
	 *
	 */
	Result<Object> orderSearch(Order order) throws InterruptedException;


}

2. 定义上下文类,由于spring的机制 ,它会将所有实现 PayService接口的实体类封装到一个集合中,我们通过将集合转换为map,同时将type作为map的key

@Component
public class PayContext {

	@Resource
	private Set<PayService> payServices;

	private static Map<String, PayService> payServiceMap;

	@PostConstruct
	public void init() {
		payServiceMap = payServices.stream().collect(Collectors.toMap(PayService::getType, a -> a));
	}

	public static PayService getInstance(String type) {
		return payServiceMap.get(type);
	}

}

3. 编写PubService的实现类 下面最重要的是设置通道标识 

@Component
public class PingTai1Service implements PayService {


	/**
	 * 获取当前通道类型标识
	 *
	 */
	@Override
	public String getType() {
		return "PINGTAI1";
	}

	/**
	 * 支付
	 *
	 */
	@Override
	public PayResult pay(Order order) throws Exception {

        // 调用平台的支付接口,返回二维码供用户支付

	}

	/**
	 * 退款
	 *
	 */
	@Override
	public RefundResult refund(Order order) {
		throw new ServiceException("当前通道不支持退款");
	}

	/**
	 * 支付订单查询
	 *
	 */
	@Override
	public Result<Object> orderSearch(Order order) {
		throw new ServiceException("当前通道不支持查询支付订单");
	}

}

4. 使用 

public Result<Object> pay(@RequestBody Dict data) throws Exception {
		log.info("收到支付请求 , 请求信息为:{}", data);
        // 模拟前端传进来通道的唯一标识
		String key= data.getStr("key");
        // 通过key 获取对应的实现类对象
		PayService instance = PayContext.getInstance(key);
        // 调用下单 传递必要参数,此处为模拟请根据实际业务传递参数
        PayResult pay = instance.pay(order);
	}

总结: 以上就是通过策略模式优化 if 操作.这样只要添加一个支付平台,就只需要添加一个实现类即可.该文章省略了前端页面如何获取通道信息的,通常后端加一个支付平台,也需要在数据库中加一条对应的信息,并把这个支付平台的唯一标识存到库里.前端拿到数据库里的通道信息后,用户点击传到后端,具体根据实际业务来

猜你喜欢

转载自blog.csdn.net/qq_39078783/article/details/131322339