概要
假设项目背景支付微服务中对接了支付宝支付和微信支付两个第三方支付平台.
那么在不做设计模式的情况下,在接收前端传来的支付渠道后,要进行一系列的if判断如果是支付宝走支付宝的支付,如果是微信走微信的支付,如此拓展性很差,业务后期添加新的支付渠道耦合大.
引入标题:如何动态的根据前端传来的支付方式选择对应的支付实现呢?
整体架构流程
/**
* Handler工厂,用于获取指定类型的具体渠道的实例对象
*/
public class HandlerFactory {
private HandlerFactory() {
}
public static <T> T get(PayChannelEnum payChannel, Class<T> handler) {
// ioc容器中获取指定类型的所有对象 装进一个map集合
Map<String, T> beans = SpringUtil.getBeansOfType(handler);
// 本系统里会获得两个对象 alipay 和wechatpay
for (Map.Entry<String, T> entry : beans.entrySet()) {
// 获取对象上的注解
PayChannel payChannelAnnotation = entry.getValue().getClass().getAnnotation(PayChannel.class);
// 判断传来的支付渠道与集合中的支付方式进行匹配
if (ObjectUtil.isNotEmpty(payChannelAnnotation) && ObjectUtil.equal(payChannel, payChannelAnnotation.type())) {
// 匹配实现类对象 如果传来的是Ali_Pay ,与Ali_Pay匹配上 ,返回Ali_Pay的支付实现
return entry.getValue();
}
}
return null;
}
public static <T> T get(String payChannel, Class<T> handler) {
//方法重载 : 如果传来的是 "支付宝支付" 字符串就转换成枚举对象 再调用get方法
return get(PayChannelEnum.valueOf(payChannel), handler);
}
}
/**
* @ClassName NativePayHandler.java
* @Description Native支付方式Handler:商户生成二维码,用户扫描支付
*/
public interface NativePayHandler {
/***
* @description 统一收单线下交易预创建
* 收银员通过收银台或商户后台调用此接口,生成二维码后,展示给用户,由用户扫描二维码完成订单支付。
* @param tradingEntity 交易单
*/
void createDownLineTrading(TradingEntity tradingEntity) throws XXException;
}
/**
* 支付宝的扫描支付的具体实现
*/
@Slf4j
@Component("aliNativePayHandler")
@PayChannel(type = PayChannelEnum.ALI_PAY)
public class AliNativePayHandler implements NativePayHandler {
@Override
public void createDownLineTrading(TradingEntity tradingEntity) throws XXException {
//查询配置
Config config = AlipayConfig.getConfig(tradingEntity.getEnterpriseId());
//Factory使用配置
Factory.setOptions(config);
AlipayTradePrecreateResponse response;
try {
//调用支付宝API面对面支付
response = Factory
.Payment
.FaceToFace()
.preCreate(tradingEntity.getMemo(),
Convert.toStr(tradingEntity.getTradingOrderNo()),
Convert.toStr(tradingEntity.getTradingAmount()));
} catch (Exception e) {
log.error("支付宝统一下单创建失败:tradingEntity = {}", tradingEntity, e);
throw new XXException(TradingEnum.NATIVE_PAY_FAIL, e);
}
//受理结果【只表示请求是否成功,而不是支付是否成功】
boolean isSuccess = ResponseChecker.success(response);
//6.1、受理成功:修改交易单
if (isSuccess) {
String subCode = response.getSubCode();
String subMsg = response.getQrCode();
tradingEntity.setPlaceOrderCode(subCode);
tradingEntity.setPlaceOrderMsg(subMsg);
tradingEntity.setPlaceOrderJson(JSONUtil.toJsonStr(response));
tradingEntity.setTradingState(TradingStateEnum.FKZ);
return;
}
throw new XXException(JSONUtil.toJsonStr(response), TradingEnum.NATIVE_PAY_FAIL.getCode(), TradingEnum.NATIVE_PAY_FAIL.getStatus());
}
}
技术名词解释
- FactoryHandler Handler工厂,用于获取指定类型的具体渠道的实例对象
- IOC 容器
- 反射
技术细节
1.首先抽取出来一个支付接口NativePayHandler,接口定义了预创建交易单的方法
2.该接口可以有多个实现方案,例如支付宝的交易单生成实现和微信的或者其他三方平台的实现
3.在这些实现类上加上@Component 将对象加入到ioc容器,再自定义注解(文中采用了支付渠道的枚举类)
4.设计一个工厂,在该类中实现根据传参的支付渠道(方法重载:字符串or枚举对象)皆可获取对应的支付申请实现
5. 用这个获取到的实现类对象生成交易订单
小结
以此工厂模式+ioc+反射 实现动态根据支付方式选择对应的支付实现!