一、preauth基本概念
preauth是指在用户购物时,商家在支付前对用户所持资金进行一定的预先授权,以保证用户支付能成功完成。在授权期内,用户的资金将不会被扣除,直到商家确认订单后才会进行正式的支付操作。preauth的主要作用是保护商家的利益,减少恶意购买行为的发生。 在preauth中,商家会向支付网关请求对用户资金进行一定数量的冻结,从而确保订单的货款能在未来支付成功,而不会因为余额不足等原因支付失败。
二、preauth的实现方法
在实现preauth时,主要有以下几种方法:
1. 基于信用卡的预授权
这是最常见的一种preauth实现方式,商家会在用户信用卡上授权一定的金额。当确认订单后,商家会再次向支付网关提交授权确认,并扣除相应的资金。
2. 基于银行账户的预授权
这种方式是在用户银行账户中进行资金冻结,和信用卡方式类似。不同之处在于,用户银行账户还需要额外开通一些支持预授权的服务,如国内的“代扣代缴”功能。
3. 基于第三方支付账户的预授权
目前像支付宝、微信等大型的第三方支付平台也开始支持preauth功能,商家可以通过这些平台进行资金的冻结和确认。不过,这种方式的可用性和安全性需要商家自行权衡。
三、preauth的优点和注意事项
1. 优点
a. 提高商家利润率:通过preauth方式,商家可以提高交易成功率,减少因为拍单行为等原因造成的不良影响。 b. 提高用户购买体验:授权期内用户的资金不会被扣除,冻结期结束后即可完成正常的支付操作。 c. 更高的交易安全性:以资金冻结的方式来完成授权,确保交易双方的权益。
2. 注意事项
a. 商家需要根据具体需求选择授权方式,并确保预授权服务的开通和使用。 b. 订单确认前,商家需要对用户资金情况进行严格地审核和确认,保证授权资金数量和订单金额一致。 c. 在授权期内,商家需要保证订单的及时确认,确保资金能够及时解冻。
四、代码示例
//基于信用卡的preauth实现
//授权请求
public void preauthRequest(CreditCard creditCard, Double amount) {
// 发送授权请求至银行
Bank bank = new Bank();
PreauthResponse response = bank.preauthRequest(creditCard, amount);
// 接收银行反馈结果,并进行处理
AppResponse appResponse = new AppResponse();
if (response.isSuccess()) {
appResponse.setCode("0000");
appResponse.setMsg("授权请求成功");
// 将授权信息存入数据库
Preauth preauth = new Preauth();
preauth.setPreauthId(response.getPreauthId());
preauth.setPreauthAmount(amount);
preauth.setCreditCard(creditCard);
preauthRepository.save(preauth);
} else {
appResponse.setCode("9999");
appResponse.setMsg("授权请求失败");
}
// 返回授权结果
return appResponse;
}
//确认订单
public void confirmOrder(Long orderId) {
// 从数据库中查询授权信息
Order order = orderRepository.findByOrderId(orderId);
Preauth preauth = preauthRepository.findByPreauthId(order.getPreauthId());
// 发送确认请求至银行
Bank bank = new Bank();
PreauthResponse response = bank.confirmRequest(preauth.getPreauthId(), preauth.getPreauthAmount());
// 根据银行反馈结果进行处理
if (response.isSuccess()) {
// 扣款成功,将订单状态改为已支付状态
order.setStatus(PAID);
orderRepository.save(order);
// 将授权信息从预授权表中删除
preauthRepository.deleteById(preauth.getPreauthId());
} else {
// 扣款失败,将订单状态改为支付失败状态
order.setStatus(FAILED);
orderRepository.save(order);
}
}