在常见的商城类平台,一般会接入微信,支付宝等支付方式.同时为了避免支付通道出现问题导致无法支付的情况,也会介入一些其他支付公司的通道.在程序里我们该如何分辨,和调用不同公司的支付通道呢?
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 操作.这样只要添加一个支付平台,就只需要添加一个实现类即可.该文章省略了前端页面如何获取通道信息的,通常后端加一个支付平台,也需要在数据库中加一条对应的信息,并把这个支付平台的唯一标识存到库里.前端拿到数据库里的通道信息后,用户点击传到后端,具体根据实际业务来