package com.yz.commons.settlement.channel.ali; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradeAppPayModel; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.request.AlipayTradeQueryRequest; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.util.HashMap; import java.util.Map; import java.util.Optional; @Slf4j @Service("ALI_APP_PAY") public class AliAppPay implements PayFacade { private final ApplicationProperties applicationProperties; private final ChargeOrderRepository chargeOrderRepository; private final PayAccountConfigRepository payAccountConfigRepository; private final StringRedisTemplate stringRedisTemplate; private final PackagePayAccountRepository packagePayAccountRepository; private final PackageInfoRepository packageInfoRepository; private final NotifyUtil notifyUtil; /** * 账号缓存key */ private final String configKey = "pay_config"; public AliAppPay (ApplicationProperties applicationProperties, ChargeOrderRepository chargeOrderRepository, PayAccountConfigRepository payAccountConfigRepository, StringRedisTemplate stringRedisTemplate, PackagePayAccountRepository packagePayAccountRepository, NotifyUtil notifyUtil, PackageInfoRepository packageInfoRepository) { this.applicationProperties = applicationProperties; this.chargeOrderRepository = chargeOrderRepository; this.payAccountConfigRepository = payAccountConfigRepository; this.stringRedisTemplate = stringRedisTemplate; this.packagePayAccountRepository = packagePayAccountRepository; this.notifyUtil = notifyUtil; this.packageInfoRepository = packageInfoRepository; } /** * 支付宝订单统一下单 * @param payPreParam * @return */ @Override public PayPreResult unifiedOrder(PayPreParam payPreParam) { PayPreResult payPreResult = new PayPreResult(); payPreResult.setOrderNo(payPreParam.getOrderNo()); payPreResult.setOrderStatus(GoldFlowStatus.SUCCESS); payPreResult.setPayChannel(payPreParam.getPayChannelCode()); PayAccountConfig payAccountConfig = payPreParam.getPayAccountConfig(); String orderNo = payPreParam.getOrderNo(); AttachParam attachParam = payPreParam.getAttachParam(); String body = attachParam.getBody(); // 分, 需要转换成元 Long orderAmount = payPreParam.getOrderAmount(); String amount = new BigDecimal(orderAmount).divide(new BigDecimal("100")).toString(); //1 实例化客户端 AlipayClient alipayClient = getAlipayClient(payAccountConfig); //2 实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); //3 SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setSubject(body); model.setOutTradeNo(orderNo); // 超时时间十五分钟 model.setTimeoutExpress("15m"); model.setTotalAmount(amount); model.setProductCode("QUICK_MSECURITY_PAY"); request.setBizModel(model); request.setNotifyUrl(notifyUtil.getNotifyUrl(payPreParam.getAttachParam().getPackageName(), ChargeOrderType.ALI_APP_PAY)); try { //这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request); payPreResult.setPayInfo(response.getBody()); } catch (AlipayApiException e) { e.printStackTrace(); payPreResult.setOrderStatus(GoldFlowStatus.REJECT); payPreResult.setPayInfo(""); } return payPreResult; } /** * 订单查询 * @param payQueryParam * @return */ @Override public PayQueryResult orderQuery(PayQueryParam payQueryParam) { PayQueryResult payQueryResult = new PayQueryResult(); payQueryResult.setOrderStatus(GoldFlowStatus.PROCESSING); payQueryResult.setPayMsg("请求状态未知"); String orderNo = payQueryParam.getOrderNo(); PayAccountConfig payAccountConfig = payQueryParam.getPayAccountConfig(); AlipayClient alipayClient = getAlipayClient(payAccountConfig); AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); request.setBizContent("{\"out_trade_no\": " + orderNo + "}"); try { AlipayTradeQueryResponse response = alipayClient.execute(request); if (response.isSuccess()) { String tradeStatus = response.getTradeStatus(); if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)){ payQueryResult.setOrderStatus(GoldFlowStatus.SUCCESS); } else if ("TRADE_CLOSED".equals(tradeStatus)) { payQueryResult.setOrderStatus(GoldFlowStatus.REJECT); } } } catch (AlipayApiException e) { e.printStackTrace(); } return payQueryResult; } /** * 支付宝回调 * @param verifyParam * @return */ @Override public VerifyResult orderVerify(VerifyParam verifyParam) { VerifyResult verifyResult = new VerifyResult(); verifyResult.setOrderStatus(GoldFlowStatus.PROCESSING); verifyResult.setResponseStr("failure"); Map<String, Object> parameterMap = verifyParam.getParameterMap(); Map<String,String> newMap = mapConvert(parameterMap); String orderNo = newMap.get("out_trade_no"); ChargeOrder repository = chargeOrderRepository.findByOrderNo(orderNo); String aliPublicKey = getAliPublicKey(repository.getPackageName(), repository.getCtype()); verifyResult.setOrderNo(orderNo); try { boolean isVerfied = AlipaySignature.rsaCheckV1(newMap, aliPublicKey, "UTF-8", SystemContants.ALI_SIGN_TYPE); if (isVerfied) { // 延签成功 String orderStatus = newMap.get("trade_status"); if ("TRADE_SUCCESS".equals(orderStatus) || "TRADE_FINISHED".equals(orderStatus)){ verifyResult.setOrderStatus(GoldFlowStatus.SUCCESS); verifyResult.setResponseStr("success"); // 支付包订单金额为元,转化成分 String totalAmount = newMap.get("total_amount"); Long orderAmount = new BigDecimal(totalAmount).multiply(new BigDecimal("100")).longValue(); verifyResult.setOrderAmount(orderAmount); } else if ("TRADE_CLOSED".equals(orderStatus)){ verifyResult.setOrderStatus(GoldFlowStatus.REJECT); verifyResult.setResponseStr("success"); } } else { log.error("ali order verify check sign append error : {}", orderNo); } } catch (AlipayApiException e) { e.printStackTrace(); } return verifyResult; } private AlipayClient getAlipayClient(PayAccountConfig payAccountConfig){ AlipayClient alipayClient = new DefaultAlipayClient(applicationProperties.getPay().getAliAppPayUrl(), payAccountConfig.getAppId(), payAccountConfig.getAliPrivateKey(), "json", "UTF-8", payAccountConfig.getAliPublicKey(), SystemContants.ALI_SIGN_TYPE); return alipayClient; } /** * 转换Map * @param map * @return */ private static Map<String, String> mapConvert(Map<String , Object> map){ Map<String, String> resultMap = new HashMap<>(); for (String key : map.keySet()) { resultMap.put(key, map.get(key)+""); } return resultMap; } private String getAliPublicKey(String packageName, String plant) { PayAccountConfig payAccountConfig; Object configObj = stringRedisTemplate.opsForHash().get(configKey, packageName + "." + plant); if (null != configObj) { payAccountConfig = JSONObject.parseObject(configObj.toString(), PayAccountConfig.class); return payAccountConfig.getAliPublicKey(); } else { PackageInfo packageInfo = packageInfoRepository.findByPackageName(packageName); PackagePayAccount packagePayAccount = packagePayAccountRepository.findByPackageIdAndPlant(packageInfo.getId(), plant); Optional<PayAccountConfig> optional = payAccountConfigRepository.findById(packagePayAccount.getAccountId()); payAccountConfig = optional.get(); payAccountConfig.setPlant(plant); payAccountConfig.setPackageName(packageName); return payAccountConfig.getAliPublicKey(); } } }