直观,先上代码:
public interface:
public interface ChannelsPayService {
<T extends Serializable> T tradeCreate(TradeOrderDto order);
<R extends Serializable> NotifyHandleResultDto<R> notifyHandle(TradeOrderDto order, Map<String, String> params);
TradePaymentChannelsEntity getCurrentChannels();
}
public abstract class:
public abstract class AbsChannelsPayService implements ChannelsPayService {
protected Logger logger = LoggerFactory.getLogger(getClass());
private volatile PayChannel payType;
@Autowired
private PaymentChannelDao paymentChannelDao;
@Autowired
protected CommonMqInfoSender commonMqInfoSender;
@Override
public TradePaymentChannelsEntity getCurrentChannels() {
PayChannel payeChannelType = getOrderPayType();
TradePaymentChannelsEntity paymentChannels = paymentChannelDao.queryByChannelsCode(payeChannelType.name());
TipAssert.notNull(paymentChannels, "系统尚未配置该支付渠道:" + payeChannelType.name());
return paymentChannels;
}
/**
* 获取key文件信息
*
* @param filePath
* @return
*/
public String readKeyFileContent(String filePath) {
TipAssert.hasLength(filePath, getOrderPayType() + "密钥文件地址不能为空");
try {
Path path = Paths.get(getClass().getResource("/").toURI()).resolve(filePath);
List<String> lines = Files.readAllLines(path);
StringBuilder stringBuilder = new StringBuilder();
if (lines != null) {
lines.forEach(i -> stringBuilder.append(i));
}
return stringBuilder.toString();
} catch (Exception e) {
logger.error("读取文件失败,filePath={}", filePath, e);
TipAssert.isTrue(false, "读取支付渠道配置密钥文件失败,filePath" + filePath);
}
return null;
}
/**
* 获取支付类型
*
* @return
*/
public PayChannel getOrderPayType() {
if (null == payType) {
synchronized (this) {
if (null == payType) {
Class<? extends AbsChannelsPayService> current = getClass();
ChannelsFlag channelsFlag = current.getAnnotation(ChannelsFlag.class);
TipAssert.isTrue(null != channelsFlag && null != channelsFlag.value(),
current.getSimpleName() + ",支付渠道未指定渠道标识");
payType = channelsFlag.value();
}
}
}
return payType;
}
}
@ChannelsFlag(PayChannel.ALI_PAY)
public class AliChannelsPayService extends AbsChannelsPayService implements InitializingBean {
private static final String ORDER_NOT_EXIST_CODE = "ACQ.TRADE_NOT_EXIST";// 订单不存在
private static final String REFUND_NOT_ALLOW = "ACQ.TRADE_NOT_ALLOW_REFUND";// 不允许退款
private static final String ORDER_FINISHED = "ACQ.TRADE_HAS_FINISHED";// 订单已完结
private static final String INVALID_PARAMETER = "ACQ.INVALID_PARAMETER"; // 参数非法
@Value("${payment.callback.notify.url}")
private String callbackNotifyUrl;
private AliPayConfig aliPayConfig;
@Override
public <T extends Serializable> T tradeCreate(TradeOrderDto order) {
AlipayClient alipayClient = build();
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
String billNo = order.getBillNo();
request.setNotifyUrl(
buildOrderNotifyUrl(order.getPayChannel().getValue(), billNo, aliPayConfig.getNotifyUrl()));
model.setSubject(order.getSubject());
String body = order.getBody();
if (StringUtils.isNotBlank(body)) {
model.setBody(body);
}
model.setOutTradeNo(billNo);
model.setTimeoutExpress(aliPayConfig.getTimeoutExpress());
model.setTotalAmount(order.getRealPayment().setScale(2, RoundingMode.HALF_UP) + "");
model.setProductCode(aliPayConfig.getProductCode());
request.setBizModel(model);
try {
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
logger.info("发起支付宝[创建交易]请求,serverUrl={},orderNo={},返回信息={}", aliPayConfig.getServerUrl(),
order.getOrderNo(), JsonUtils.toJson(response));
TipAssert.isTrue(response.isSuccess(), response.getMsg());
return (T) response.getBody();
} catch (Exception e) {
logger.error("发起支付宝[创建交易]请求,处理异常OrderNo={},exception:", order.getOrderNo(), e);
TipAssert.isTrue(false, "调用支付宝支付请求失败");
}
return null;
}
}
@ChannelsFlag(PayChannel.WE_CHAT_PAY)
public class WxChannelsPayService extends AbsChannelsPayService implements InitializingBean {
private WxpayProperties wxpayProperties;
private WXPay wxPayClient;
@SuppressWarnings("unchecked")
@Override
public <T extends Serializable> T tradeCreate(TradeOrderDto order) {
String requestBody = "";
String responseBody = "";
String payBody = "";
String billNo = order.getBillNo();
String clientIp = order.getClientIp();
try {
WxPayCreateRequest wxPayCreateRequest = new WxPayCreateRequest();
wxPayCreateRequest.setBody(order.getSubject());
wxPayCreateRequest.setOutTradeNo(billNo);
wxPayCreateRequest.setSpbillCreateIp(clientIp);
wxPayCreateRequest.setTotalFee(
order.getRealPayment().multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP).longValue()
+ "");
requestBody = JsonUtils.toJson(wxPayCreateRequest);
WXPay wxPay = new WXPay(DefaultWeChatConfig.getInstance(wxpayProperties),
buildOrderNotifyUrl(order.getPayChannel().name(), billNo, wxpayProperties.getNotifyUrl()), true,
false);
Map<String, String> unifiedResult = wxPay.unifiedOrder(JsonUtils.formatFiledtoMap(wxPayCreateRequest));
responseBody = JsonUtils.toJson(unifiedResult);
Map<String, String> tradeMap = Maps.newHashMap();
tradeMap.put("appid", wxpayProperties.getAppid());
tradeMap.put("partnerid", wxpayProperties.getMerchantId());
tradeMap.put("prepayid", unifiedResult.get("prepay_id"));
tradeMap.put("package", "Sign=WXPay");
tradeMap.put("noncestr", RandomStringUtils.randomNumeric(32));
tradeMap.put("timestamp", System.currentTimeMillis() / 1000 + "");
tradeMap.put("sign",
WXPayUtil.generateSignature(tradeMap, wxpayProperties.getMerchantKey(), SignType.HMACSHA256));
payBody = JsonUtils.toJson(tradeMap);
return (T) payBody;
} catch (Exception e) {
logger.error("单号={},发起微信支付发生异常", billNo, e);
} finally {
logger.info("请求微信APP支付,单号={},请求报文={},响应报文={},发起支付请求体={}", billNo, requestBody, responseBody, payBody);
}
return null;
}
}
在Java语言中,abstract class和interface是支持抽象类定义的两种机制。
不能创建abstract类的实例,然而可以创建一个变量,其类型是一个抽象类,并让它指向具体子类的一个实例。
不能有抽象构造函数或抽象静态方法。
Abstract 类的子类为它们父类中的所有抽象方法提供实现,否则它们也是抽象类。
接口(interface)是抽象类的变体。
在接口中,所有方法都是抽象,公开的。多继承性可通过实现这样的接口而获得。
接口中的所有方法都没有一个有程序体。接口只可以定义staticfinal成员变量。
接口的实现与子类相似,除了该实现类不能从接口定义中继承行为。
当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。然后,它可以在实现了该接口的类的任何对象上调用接口的方法。
由于有抽象类,它允许使用接口名作为引用变量的类型。通常的动态联编将生效。
引用可以转换到接口类型或从接口类型转换,instanceof运算符可以用来决定某对象的类是否实现了接口。
接口可以继承接口。抽象类可以实现(implements)接口,抽象类是可以继承实体类,但前提是实体类必须有明确的构造函数。接口更关注“能实现什么功能”,而不管“怎么实现的”。
1.相同点
A. 两者都是抽象类,都不能实例化。
B. interface实现类及abstrctclass的子类都必须要实现已经声明的抽象方法。
2. 不同点
A. interface需要实现,要用implements,而abstract class需要继承,要用extends。
B. 一个类可以实现多个interface,但一个类只能继承一个abstract class。
C. interface强调特定功能的实现,而abstractclass强调所属关系。
D. 尽管interface实现类及abstrct class的子类都必须要实现相应的抽象方法,但实现的形式不同。interface中的每一个方法都是抽象方法,都只是声明的(declaration,没有方法体),实现类必须要实现。而abstractclass的子类可以有选择地实现。
这个选择有两点含义:
一是Abastract class中并非所有的方法都是抽象的,只有那些冠有abstract的方法才是抽象的,子类必须实现。那些没有abstract的方法,在Abstrct class中必须定义方法体。
二是abstract class的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以通过再次声明其方法为抽象的方式,无需实现,留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。
E. abstract class是interface与Class的中介。
interface是完全抽象的,只能声明方法,而且只能声明pulic的方法,不能声明private及protected的方法,不能定义方法体,也不能声明实例变量。然而,interface却可以声明常量变量,并且在JDK中不难找出这种例子。但将常量变量放在interface中违背了其作为接口的作用而存在的宗旨,也混淆了interface与类的不同价值。如果的确需要,可以将其放在相应的abstractclass或Class中。
abstract class在interface及Class中起到了承上启下的作用。一方面,abstract class是抽象的,可以声明抽象方法,以规范子类必须实现的功能;另一方面,它又可以定义缺省的方法体,供子类直接使用或覆盖。另外,它还可以定义自己的实例变量,以供子类通过继承来使用。
3. interface的应用场合
A. 类与类之前需要特定的接口进行协调,而不在乎其如何实现。
B. 作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。
C. 需要将一组类视为单一的