1.1、请先在支付宝开发者平台创建app应用并获取APPID,配置密钥等。
1.2、详细可参照蚂蚁金服官方文档:https://open.alipay.com
2.maven在pom.xml中引入对应的jar依赖
<!--支付宝-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.7.26.ALL</version>
</dependency>
————————————————
版权声明:本文为CSDN博主「zxkCode」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/java_file_style/article/details/97613337
3.application.yml文件的配置如下
#支付宝支付配置
alipayconfig:
#商户APPID
appId: 122334444
#私钥 pkcs8格式的
rsaPrivateKey: qwertyuiop
#请求网关地址
url: https://openapi.alipay.com/gateway.do
#编码
charset: UTF-8
#返回格式
format: JSON
#支付宝公钥
alipayPublicKey: asdfghjkl
#签名方式
signType: RSA2
4.配置文件对应的AlipayConfig,若没集成lombok请自行生成get/set方法
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
/**
* 支付包支付配置类
* @author: zengXianKang
*/
@Data
@Component
@ConfigurationProperties(prefix = "alipayconfig")
public class AlipayConfig {
//appId
private String appId;
//私钥
private String rsaPrivateKey;
//请求网关地址
private String url;
//编码格式
private String charset;
//返回格式
private String format;
//支付宝公钥
private String alipayPublicKey;
//签名方式
private String signType;
}
4.1新建一个AliPayVO
import lombok.Data;
/**
* @Description: AliPayVO
* @Param:
* @return:
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@Data
public class AliPayVO {
//商户订单号
private String outTradeNo;
//交易状态
private String tradeStatus;
//交易流水号
private String tradeNo;
//资金总额
private String totalAmount;
//卖家支付宝账户
private String sellerId;
//买家支付宝账户
private String buyerLogoinId;
//签名方式
private String signType;
//签名
private String sign;
}
5.请求支付宝支付
在很多电商的项目中都有类似保存订单,充值等一系列支付宝支付场景;我们需要发起支付返回给前端支付sdk;该篇博文为支付宝支付的博文,稍后我会更新微信支付的博文
5.1发起支付请求
/**
* @Description: 支付请求
* @Param: [payType, outTradeNo, totalAmount]
* @return: java.util.Map<java.lang.String,java.lang.String>
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@Override
public Map<String, String> payRequest(String payType, String outTradeNo, BigDecimal totalAmount) throws Exception {
Map<String, String> map = new HashMap<String, String>();
switch (PayTypeEnum.valueOf(payType)) {
case ALIPAY://支付宝
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppId(),
alipayConfig.getRsaPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
alipayConfig.getAlipayPublicKey(), alipayConfig.getSignType());
AlipayTradeAppPayRequest aliPayRequest = new AlipayTradeAppPayRequest();
AlipayTradePayModel model = new AlipayTradePayModel();
//支付编号
model.setOutTradeNo(outTradeNo);
//订单名称
model.setSubject("某某平台订单支付");
//支付总金额
model.setTotalAmount(totalAmount.toString());
//超时则关闭订单
model.setTimeoutExpress("30m");
aliPayRequest.setBizModel(model);
//异步回调地址
aliPayRequest.setNotifyUrl(ConstantInfo.ALIPAY_ORDER_CALLBACK);AlipayTradeAppPayResponse response = alipayClient.sdkExecute(aliPayRequest);
map.put("aliPaySdk", response.getBody());
break;
default:
break;
}
return map;
}
5.1.1ConstantInfo中的内容为
/**
* 常量
*/
public class ConstantInfo {//订单支付支付宝回调地址
public static String ALIPAY_ORDER_CALLBACK = "http://mall.gzmhyj.com:8085/huakuEComBuyer/pay/aliPayOrderCallBack";
}
5.2订单支付宝支付回调
该接口为为支付宝异步回调提供的接口
/**
* @Description: 订单支付宝支付回调
* @Param: [request]
* @return: java.util.Map<java.lang.String,java.lang.String>
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@RequestMapping(value = "/aliPayOrderCallBack", method = RequestMethod.POST)
@ResponseBody
public Map<String, String> aliPayOrderCallBack(HttpServletRequest request){
Map<String, String> map = new HashMap<String, String>();
try {
AliPayVO aliPayVo = payService.aliPayCallBack(request);
payService.aliPayOrderCallBack(aliPayVo);
map.put("msg", "SUCCESS");
} catch (Exception e) {
e.printStackTrace();
logger.error("aliPayOrderCallBack Error.",e);
}
return map;
}
5.2.1payService的aliPayCallBack,用于解析回调的信息,拼接AliPayVO
/**
* @Description: 支付宝支付回调
* @Param: [request]
* @return: com.huaku.ecom.system.model.vo.AliPayVO
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@Override
public AliPayVO aliPayCallBack(HttpServletRequest request) throws Exception {
//获取支付宝反馈信息
Map<String, String> params = new HashMap<String, String>();
Map<String, String[]> requestParams = request.getParameterMap();
for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
//调用SDK验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType());
//校验签名
if (!signVerified) {
logger.error("支付宝支付回调签名不正确");
throw new RRException(AppWSConstant.RS_MSG_ALIPAY_FALL);
}
//校验支付状态
if (!request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
logger.error("支付宝支付回调支付状态不正确");
throw new RRException(AppWSConstant.RS_MSG_ALIPAY_FALL);
}
AliPayVO aliPayVo = new AliPayVO();
//商户订单号
String outTradeNo = request.getParameter("out_trade_no");
aliPayVo.setOutTradeNo(outTradeNo);
//交易状态
String tradeStatus = request.getParameter("trade_status");
aliPayVo.setTradeStatus(tradeStatus);
//资金总额
String totalAmount = request.getParameter("total_amount");
aliPayVo.setTotalAmount(totalAmount);
//卖家支付宝账户
String sellerId = request.getParameter("seller_id");
aliPayVo.setSellerId(sellerId);
//买家支付宝账户
String buyerLogonId = request.getParameter("buyer_logon_id");
aliPayVo.setBuyerLogoinId(buyerLogonId);
//签名方式
aliPayVo.setSignType(alipayConfig.getSignType());
//签名
String sign = request.getParameter("sign");
aliPayVo.setSign(sign);
return aliPayVo;
}
5.2.2payService的aliPayOrderCallBack,用于自己的回调完成的业务逻辑,如修改订单状态,存支付宝支付交易表等操作
/**
* @Description: 支付宝订单支付回调业务处理
* @Param: [aliPayVo]
* @return: void
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@Transactional
@Override
public void aliPayOrderCallBack(AliPayVO aliPayVo) throws Exception {
if (aliPayVo != null && Convert.isNotEmpty(aliPayVo.getOutTradeNo())) {
//根据交易编号加锁,处理高并发
synchronized (aliPayVo.getOutTradeNo()) {
TOrder order = orderMapper.getOneOrderByPayNo(aliPayVo.getOutTradeNo());
if (order.getOrderStatus().equals(OrderStatusEnum.PENDING_PAYMENT.toString())) {
if (aliPayVo.getTradeStatus().equals("TRADE_FINISHED")) {
//交易创建,等待买家付款
logger.info("TRADE_FINISHED");
} else if (aliPayVo.getTradeStatus().equals("WAIT_BUYER_PAY")) {
//未付款交易超时关闭,或支付完成后全额退款
logger.info("WAIT_BUYER_PAY");
} else if (aliPayVo.getTradeStatus().equals("TRADE_CLOSED")) {
//交易结束,不可退款
logger.info("TRADE_CLOSED");
} else if (aliPayVo.getTradeStatus().equals("TRADE_SUCCESS")) {
//交易支付成功
logger.info("TRADE_SUCCESS");
//订单需支付金额总和
BigDecimal payNumSum = this.getPayNumSumByPayNo(aliPayVo.getOutTradeNo());
//资金总额
BigDecimal totalAmount = new BigDecimal(aliPayVo.getTotalAmount());
String orderStatus = "";
//以防万一,再次校验金额
if (payNumSum.compareTo(totalAmount) != 0) {
logger.error("***订单号: " + aliPayVo.getOutTradeNo() + "***支付宝支付金额与订单需支付金额总和不一致***支付宝支付金额为:" + totalAmount + " ***订单需支付金额总为:" + payNumSum + "***日期:" + new Date());
//金额异常,订单状态为支付金额异常
orderStatus = OrderStatusEnum.ABNORMAL_PAYMENT_AMOUNT.toString();
} else {
//金额正常,订单状态为已付款(待发货)
orderStatus = OrderStatusEnum.WAIT_FOR_DELIVERY.toString();
}
//修改订单状态
int orderFlag = orderMapper.updatePayOrderStatusByPayNo(orderStatus, aliPayVo.getOutTradeNo());
//支付宝交易记录表
TAlipayTradeLog alipayTradeLog = new TAlipayTradeLog();
alipayTradeLog.setTradeLogId(Convert.createUniqueId(idWorker));
//签名方式
alipayTradeLog.setSignType(alipayConfig.getSignType());
//订单号
alipayTradeLog.setOutTradeNo(aliPayVo.getOutTradeNo());
//支付状态
alipayTradeLog.setTradeStatus(aliPayVo.getTradeStatus());
//卖家支付宝账户
alipayTradeLog.setSellerId(aliPayVo.getSellerId());
//买家支付宝账户
alipayTradeLog.setBuyerId(aliPayVo.getBuyerLogoinId());
//支付金额
alipayTradeLog.setTotalFee(totalAmount);
//交易创建时间
alipayTradeLog.setGmtCreate(new Date());
//交易付款时间
alipayTradeLog.setGmtPayment(new Date());int payFlag = alipayTradeLogMapper.insertSelective(alipayTradeLog);
//若有一个操作出错,抛错回滚
if (!(orderFlag > 0 && payFlag == 1)) {
logger.error("支付宝支付订单回调失败");
throw new RRException(AppWSConstant.RS_MSG_ALIPAY_FALL);
}
}
} else {
logger.info("该订单已支付处理,交易编号为: " + aliPayVo.getOutTradeNo());
}
}
}
}
5.3定时任务主动查询支付宝支付回调,一般支付宝发起的异步回调都是无序不定时的,所以一般保险起见都会写一个自己的定时任务主动查询支付宝支付回调
/**
* 定时任务:每十五分钟触发一次主动调用订单支付回调
*/
@Scheduled(cron = "0 */15 * * * ?")
public void initiativeOrderPayCallBack(){
//主动调用订单支付回调
try {
payService.initiativeOrderPayCallBack();
} catch (Exception e) {
logger.error("timer initiativeOrderPayCallBack Error.", e);
e.printStackTrace();
}
}
5.3.1payService的initiativeOrderPayCallBack,用于主动查询支付宝支付回调与回调业务逻辑处理
/**
* @Description: 主动调用订单支付回调
* @Param: []
* @return: void
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@Override
public void initiativeOrderPayCallBack() throws Exception {
//查询订单表里订单状态为待付款的支付编号
List<Map<String, String>> payNoList = orderMapper.getPayNoByStatus(OrderStatusEnum.PENDING_PAYMENT.toString());
for (Map<String, String> map : payNoList) {
try {
switch (PayTypeEnum.valueOf(map.get("payType"))) {
case ALIPAY://支付宝
AliPayVO aliPayVO = this.aliPayQueryCallBack(map.get("payNo"));
//订单回调处理
this.aliPayOrderCallBack(aliPayVO);
break;
default:
break;
}
} catch (Exception e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
}
5.3.2payService的aliPayQueryCallBack,用于主动查询支付宝支付回调,拼接AliPayVO
/**
* @Description: 支付宝支付主动查询回调
* @Param: [payNo]
* @return: com.huaku.ecom.system.model.vo.AliPayVO
* @Author: zengXianKang
* @Date: 2019/7/28
*/
@Override
public AliPayVO aliPayQueryCallBack(String payNo) throws Exception {
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppId(),
alipayConfig.getRsaPrivateKey(), alipayConfig.getFormat(), alipayConfig.getCharset(),
alipayConfig.getAlipayPublicKey(), alipayConfig.getSignType());AlipayTradeQueryRequest aliPayRequest = new AlipayTradeQueryRequest();
AlipayTradePayModel model = new AlipayTradePayModel();
model.setOutTradeNo(payNo);
aliPayRequest.setBizModel(model);
AlipayTradeQueryResponse response = alipayClient.execute(aliPayRequest);
AliPayVO aliPayVO = new AliPayVO();
if (response.isSuccess()) {
//logger.info("支付包支付主动调用请求成功");
//支付状态
aliPayVO.setTradeStatus(response.getTradeStatus());
//支付金额
aliPayVO.setTotalAmount(response.getTotalAmount());
//买家支付宝账户
aliPayVO.setBuyerLogoinId(response.getBuyerLogonId());
//订单号
aliPayVO.setOutTradeNo(response.getOutTradeNo());
}
return aliPayVO;
}