• 微信支付 APP端 后端 第二弹 微信回调


    目录

    第二弹:支付回调

    成果展示

    1 订单设计思路

    1.1设计思路

    2.回调接口

    2.1controller

    2.2验证静态方法

    2.3缓存参数 常量

    2.4 service 校验金额

    2.4.1金额静态方法校验

    2.4.2总体校验

    3. 定时任务 查询处理特殊订单

    3.1 get请求 统一配置

    3.2 查询订单service

    3.3关闭订单

    3.4 定时任务 处理订单

    3.4.1 金额校验 (和微信回调处理金额校验相同)

    3.4.2 定时任务处理 


    第二弹:支付回调

    微信支付通过支付通知接口将用户支付成功消息通知给商户

    定时任务处理特殊订单

    (这些要根据直接项目的情况按需来安排)

    成果展示

    (只展示部分 这个设计到项目内容 不好全部展示)

    1 订单设计思路

    1.1设计思路

    2.回调接口

    2.1controller

    1. @PostMapping("/wechatPayCallback")
    2. @ApiOperation("支付回调给微信确认")
    3. @ApiIgnore
    4. public String wechatCallback(HttpServletRequest request) {
    5. ToolWxConfig wxConfig = iToolWxConfigService.find();
    6. log.info("微信退款回调通知调用=============================");
    7. Gson gson = new Gson();
    8. Map<String,String> result = new HashMap(SystemConstant.NUM_16);
    9. result.put("code", "FAIL");
    10. result.put("message","失败");
    11. try {
    12. //微信回调信息校验
    13. // 构建request,传入必要参数
    14. Notification notification = WxPayUtil.verifyBack(request, wxConfig);
    15. log.info("=================微信验证签名成功=======成功时间=={}=====",notification.getCreateTime());
    16. // 思路: 验证订单 订单号是否存在 订单状态 通过缓存来做到 一回调验证多订单的类型
    17. // 生成订单的时候 把订单信息放入缓存中 order:key key为订单号 30min 通过获取 订单消息做到 快速验证 插入操作 用if 进行
    18. if (iToolWxConfigService.verifyCreateOrder(notification.getDecryptData())) {
    19. log.info("==============================微信退款成功订单=====================================");
    20. result.put("code", WXOrderConstant.WX_BACK_OK);
    21. result.put("message", "支付回调成功");
    22. }
    23. } catch (ValidationException | ParseException | IOException e) {
    24. log.error("微信支付回调失败验证" + e);
    25. }
    26. log.info("微信返回结果"+result);
    27. return gson.toJson(result);
    28. }

    2.2验证静态方法

    1. /**
    2. *回调验证
    3. * @param request 微信回调请求
    4. * @param wxConfig 微信基本配置信息
    5. * @return String
    6. * @author zhangjunrong
    7. * @date 2022/4/21 15:02
    8. */
    9. public static Notification verifyBack(HttpServletRequest request, ToolWxConfig wxConfig) throws IOException, ValidationException, ParseException {
    10. //应答报文主体
    11. BufferedReader br = request.getReader();
    12. String str;
    13. StringBuilder builder = new StringBuilder();
    14. while ((str = br.readLine()) != null) {
    15. builder.append(str);
    16. }
    17. // 构建request,传入必要参数
    18. //参数 1.微信序列号 2.应答随机串 3.应答时间戳 4.应答签名 5.应答报文主体
    19. NotificationRequest notificationRequest = new NotificationRequest.Builder()
    20. .withSerialNumber(request.getHeader(WechatPayHttpHeaders.WECHATPAY_SERIAL))
    21. .withNonce(request.getHeader(WechatPayHttpHeaders.WECHATPAY_NONCE))
    22. .withTimestamp(request.getHeader(WechatPayHttpHeaders.WECHATPAY_TIMESTAMP))
    23. .withSignature(request.getHeader(WechatPayHttpHeaders.WECHATPAY_SIGNATURE))
    24. .withBody(builder.toString())
    25. .build();
    26. NotificationHandler handler = new NotificationHandler(WxPayUtil.getVerifier(wxConfig), wxConfig.getApiV3key().getBytes(StandardCharsets.UTF_8));
    27. // 验签和解析请求体
    28. log.info("验签和解析请求体==============================开始验证==============================");
    29. Notification notification = handler.parse(notificationRequest);
    30. Assert.assertNotNull(notification);
    31. return notification;
    32. }

    2.3缓存参数 常量

    1. package com.yqs.constant.wechatPay;
    2. /**
    3. * @Description 微信定时任务
    4. * @Author 小乌龟
    5. * @Date 2022/5/13 9:01
    6. */
    7. public class WxRedisKey {
    8. /**
    9. *微信支付订单 list<对象>=>(订单详细信息key+订单类型+下单时间+支付状态) 有效时间6分钟
    10. */
    11. public static final String WX_PAY_ORDER = "wxPayOrderList";
    12. /**
    13. *微信退款订单 存微信基础信息 有效时间3分钟 wxRefundOrder::
    14. */
    15. public static final String WX_REFUND_ORDER = "wxRefundOrder::";
    16. }

    2.4 service 校验金额

    2.4.1金额静态方法校验

    1. /**
    2. *验证用户支付金额 场景1.微信回调验证 2.定时任务核对订单
    3. * @param node 微信回调json 返回参数
    4. * @param redisTotal redis记录金额
    5. * @return Boolean
    6. * @author zhangjunrong
    7. * @date 2022/5/16 8:39
    8. */
    9. public static Boolean verifyMoney(JsonNode node,Integer redisTotal){
    10. //总金额计数值 用户支付计算
    11. int userPayTotal = SystemConstant.NUM_ZERO;
    12. //1.验证订单金额
    13. //用户支付金额
    14. int payerTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_PAYER_TOTAL).asInt();
    15. userPayTotal = userPayTotal + payerTotal;
    16. //CASH充值型代金券 要加上优惠金额 银行优惠 获取
    17. //排空 如果没有优惠则跳过
    18. if (!ObjectUtil.isEmpty(node.get(WXOrderConstant.PROMOTION_DETAIL))) {
    19. for (JsonNode objNode : node.get(WXOrderConstant.PROMOTION_DETAIL)) {
    20. //如果优惠类型为CASH 则要和 用户支付金额 累加
    21. if (WXOrderConstant.WX_DISCOUNT_TYPE.equals(objNode.get(WXOrderConstant.PROMOTION_DETAIL_TYPE).textValue())) {
    22. userPayTotal = userPayTotal + objNode.get(WXOrderConstant.AMOUNT).asInt();
    23. }
    24. }
    25. }
    26. //2.总金额 预支付时的 金额 与 total 用户支付金额
    27. //微信端返回的支付总金额
    28. int wxTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt();
    29. //redis缓存中的金额
    30. //校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。
    31. //缓存中存入的用户支付金额 totalRedisRO.getTicketOrder().getTotalMoney().movePointRight(SystemConstant.NUM_TWO).intValue()
    32. log.info("微信回调金额===比较=== "+"微信端返回的支付总金额"+node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt()+"==========redis缓存中的金额"+redisTotal+"================用户支付总金额计算"+userPayTotal);
    33. //只要缓存的金额小于用户实际付款金额 判定成功
    34. return wxTotal == userPayTotal && redisTotal == wxTotal;
    35. }

    2.4.2总体校验

    1. @Override
    2. public Boolean verifyCreateOrder(String decryptOrder) {
    3. //在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
    4. //实现: 加入一把可重入锁
    5. if (reentrantLock.tryLock()) {
    6. try {
    7. log.info("===================================进入微信支付回调核对订单中========================================");
    8. ObjectMapper objectMapper = new ObjectMapper();
    9. //微信回调 解密后 信息
    10. JsonNode node = objectMapper.readTree(decryptOrder);
    11. //获取订单商户号
    12. String orderNo = node.get(WXOrderConstant.OUT_TRADE_NO).textValue();
    13. //1.获取redis中的订单信息
    14. OrderTotalRedisRO totalRedisRO = (OrderTotalRedisRO) redisUtil.get(SystemConstant.ORDER_TOTAL + orderNo);
    15. //1.1微信 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
    16. //实现方法: 通过订单状态来 判定是否要进行判定 出未支付以外的 都返回 结果 通过缓存获取到支付状态 防止微信重复调用该方法
    17. //如果回调 缓存中记录清除说明 入库判定等等成功 直接返回true
    18. if (ObjectUtil.isEmpty(totalRedisRO)) {
    19. return true;
    20. }
    21. log.info(node.get(WXOrderConstant.OUT_TRADE_NO) + "订单回调信息记录:订单状态:" + orderNo);
    22. //2.如果回调 支付类型为成功 核对金额 入数据库
    23. //获取支付状态
    24. String tradeState = node.get(WXOrderConstant.TRADE_STATE).textValue();
    25. if (StrUtil.equals(WXOrderConstant.WX_BACK_OK, tradeState)) {
    26. //redis缓存中的金额
    27. int redisTotal = totalRedisRO.getTicketOrder().getPayMoney().movePointRight(SystemConstant.NUM_TWO).intValue();
    28. //校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。
    29. //缓存中存入的用户支付金额 totalRedisRO.getTicketOrder().getTotalMoney().movePointRight(SystemConstant.NUM_TWO).intValue()
    30. if (WxPayUtil.verifyMoney(node, redisTotal)) {
    31. //3.对应的数据入库
    32. log.info("redis入数据库信息======================" + totalRedisRO);
    33. if (!ObjectUtil.isEmpty(totalRedisRO)) {
    34. //缓存放入一个状态 表明已操作该订单 存放200秒
    35. // 支付成功就把redis中缓存记录清除
    36. totalRedisRO.getTicketOrder().setOrderStatus(SystemConstant.NUM_ONE);
    37. redisUtil.del(SystemConstant.ORDER_TOTAL + orderNo);
    38. //订单入库
    39. iTicketOrderService.createAllTicket(totalRedisRO, node.get(WXOrderConstant.TRANSACTION_ID).textValue());
    40. }
    41. }
    42. //为什么没有插入成功也返回true?
    43. //因为就算数据库没有入成功 但是金额 订单校验等等的都通过
    44. //说明数据库入库失败
    45. //如果入库失败 让用户联系客服接入管理 [钱一定要收下来]
    46. return true;
    47. }
    48. } catch (Exception e) {
    49. log.error("订单支付异常===>订单回调信息记录:订单状态:" + decryptOrder);
    50. }finally {
    51. //释放锁
    52. reentrantLock.unlock();
    53. }
    54. }
    55. return false;
    56. }

    3. 定时任务 查询处理特殊订单

    3.1 get请求 统一配置

    1. /**
    2. *构造HttpClient 实现 微信申请接口 调用功能
    3. * @param wxConfig 微信支付数据库参数
    4. * @param verifier 微信验签器
    5. * @return CloseableHttpClient
    6. * @author zhangjunrong
    7. * @date 2022/5/16 8:54
    8. */
    9. public static CloseableHttpClient getHttpClient(ToolWxConfig wxConfig, Verifier verifier) {
    10. PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(wxConfig.getPrivateKey().getBytes(StandardCharsets.UTF_8)));
    11. //通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签
    12. WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
    13. .withMerchant(wxConfig.getMchId(), wxConfig.getMchSerialNo(), merchantPrivateKey)
    14. .withValidator(new WechatPay2Validator(verifier));
    15. return builder.build();
    16. }
    1. /**
    2. * 调用微信支付 get请求 统一配置
    3. * 要微信签名认证
    4. * @param url
    5. * @return String
    6. * @author zhangjunrong
    7. * @date 2022/5/9 20:39
    8. */
    9. private String getHttpGet(ToolWxConfig wxConfig, String url) throws URISyntaxException, IOException {
    10. //1.构造httpGet请求
    11. URIBuilder uriBuilder = null;
    12. uriBuilder = new URIBuilder(url);
    13. HttpGet httpGet = new HttpGet(uriBuilder.build());
    14. httpGet.addHeader(WechatPayHttpHeaders.ACCEPT, WechatPayHttpHeaders.APPLICATION_JSON);
    15. //2.调起微信查询订单接口
    16. CloseableHttpResponse response = WxPayUtil.getHttpClient(wxConfig, WxPayUtil.getVerifier(wxConfig)).execute(httpGet);
    17. //3.返回结果信息
    18. return EntityUtils.toString(response.getEntity());
    19. }

    3.2 查询订单service

    1. /**
    2. * 查询订单
    3. * 使用场景:
    4. * 1.当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知。
    5. * 2.调用支付接口后,返回系统错误或未知交易状态情况。
    6. * 3.调用付款码支付API,返回USERPAYING(用户付费)的状态。
    7. * 4.调用关单或撤销接口API之前,需确认支付状态。
    8. * @param wxConfig 微信配置
    9. * @param outTradeNo 商户订单号 系统生成
    10. * @return String 订单交易状态
    11. * @author zhangjunrong
    12. * @date 2022/4/14 16:14
    13. *
    14. */
    15. @Override
    16. public JsonNode queryCreateOrder(ToolWxConfig wxConfig, String outTradeNo) {
    17. try {
    18. //1.查单 微信接口 编辑 微信订单号 + 商户号
    19. String url = StrFormatter.format(WxApiType.QUERY_CREATE_ORDER.getValue(), outTradeNo, wxConfig.getMchId());
    20. //2.调用微信接口
    21. String bodyAsString = getHttpGet(wxConfig, url);
    22. log.info("支付查单信息" + bodyAsString);
    23. //返回查单结果信息
    24. if (ObjectUtil.isNotEmpty(bodyAsString)){
    25. ObjectMapper objectMapper = new ObjectMapper();
    26. return objectMapper.readTree(bodyAsString);
    27. }
    28. } catch (Exception e) {
    29. log.error("支付查单失败" + outTradeNo);
    30. }
    31. return null;
    32. }

    3.3关闭订单

    1. /**
    2. * 关闭订单
    3. * 使用场景:
    4. * 1、商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
    5. * 2、系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
    6. * 注意:关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败
    7. *
    8. * @param wxConfig
    9. * @param outTradeNo
    10. * @return String
    11. * @author zhangjunrong
    12. * @date 2022/4/14 17:02
    13. */
    14. @Override
    15. public String closeOrder(ToolWxConfig wxConfig, String outTradeNo) {
    16. try {
    17. //1.微信接口编辑
    18. String url = StrFormatter.format(WxApiType.CLOSE_ORDER.getValue(), outTradeNo);
    19. HttpPost httpPost = new HttpPost(url);
    20. //格式配置
    21. httpPost.addHeader(WechatPayHttpHeaders.ACCEPT, WechatPayHttpHeaders.APPLICATION_JSON);
    22. httpPost.addHeader(WechatPayHttpHeaders.CONTENT_TYPE, WechatPayHttpHeaders.APPLICATION_JSON_UTF);
    23. ByteArrayOutputStream bos = new ByteArrayOutputStream();
    24. //2.添加商户id
    25. ObjectMapper objectMapper = new ObjectMapper();
    26. ObjectNode rootNode = objectMapper.createObjectNode();
    27. rootNode.put(WXOrderConstant.MCHID, wxConfig.getMchId());
    28. objectMapper.writeValue(bos, rootNode);
    29. //3.调起微信关单接口
    30. httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
    31. CloseableHttpResponse response = WxPayUtil.getHttpClient(wxConfig, WxPayUtil.getVerifier(wxConfig)).execute(httpPost);
    32. //无数据(Http状态码为204) 微信返回结果无数据 状态码为204 成功
    33. if (response.getStatusLine().getStatusCode() == MessageEnum.NO_CONTENT.getCode()) {
    34. return "关单成功";
    35. }
    36. } catch (Exception e) {
    37. log.error("关单失败" + outTradeNo + e);
    38. }
    39. return null;
    40. }

    3.4 定时任务 处理订单

    3.4.1 金额校验 (和微信回调处理金额校验相同)

    1. /**
    2. *验证用户支付金额 场景1.微信回调验证 2.定时任务核对订单
    3. * @param node 微信回调json 返回参数
    4. * @param redisTotal redis记录金额
    5. * @return Boolean
    6. * @author zhangjunrong
    7. * @date 2022/5/16 8:39
    8. */
    9. public static Boolean verifyMoney(JsonNode node,Integer redisTotal){
    10. //总金额计数值 用户支付计算
    11. int userPayTotal = SystemConstant.NUM_ZERO;
    12. //1.验证订单金额
    13. //用户支付金额
    14. int payerTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_PAYER_TOTAL).asInt();
    15. userPayTotal = userPayTotal + payerTotal;
    16. //CASH充值型代金券 要加上优惠金额 银行优惠 获取
    17. //排空 如果没有优惠则跳过
    18. if (!ObjectUtil.isEmpty(node.get(WXOrderConstant.PROMOTION_DETAIL))) {
    19. for (JsonNode objNode : node.get(WXOrderConstant.PROMOTION_DETAIL)) {
    20. //如果优惠类型为CASH 则要和 用户支付金额 累加
    21. if (WXOrderConstant.WX_DISCOUNT_TYPE.equals(objNode.get(WXOrderConstant.PROMOTION_DETAIL_TYPE).textValue())) {
    22. userPayTotal = userPayTotal + objNode.get(WXOrderConstant.AMOUNT).asInt();
    23. }
    24. }
    25. }
    26. //2.总金额 预支付时的 金额 与 total 用户支付金额
    27. //微信端返回的支付总金额
    28. int wxTotal = node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt();
    29. //redis缓存中的金额
    30. //校验通知的信息是否与商户侧的信息一致,防止数据泄露导致出现“假通知”,造成资金损失。
    31. //缓存中存入的用户支付金额 totalRedisRO.getTicketOrder().getTotalMoney().movePointRight(SystemConstant.NUM_TWO).intValue()
    32. log.info("微信回调金额===比较=== "+"微信端返回的支付总金额"+node.get(WXOrderConstant.AMOUNT).get(WXOrderConstant.AMOUNT_TOTAL).asInt()+"==========redis缓存中的金额"+redisTotal+"================用户支付总金额计算"+userPayTotal);
    33. //只要缓存的金额小于用户实际付款金额 判定成功
    34. return wxTotal == userPayTotal && redisTotal == wxTotal;
    35. }

    3.4.2 定时任务处理 

    1. /**
    2. * 清除过去票 恢复库存
    3. *
    4. * @param order 子订单信息
    5. * @return void
    6. * @author zhangjunrong
    7. * @date 2022/5/16 19:44
    8. */
    9. private void dealVoidTicket(WxPayListRO order) {
    10. //微信订单redis2 订单详情
    11. OrderTotalRedisRO orderTotalRedisRO = (OrderTotalRedisRO) redisUtil.get(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());
    12. orderTotalRedisRO.getTicketOrderItems().stream()
    13. .filter(Objects::nonNull)
    14. .forEach(ticketOrderItem -> {
    15. //恢复票相应的库存
    16. Boolean timeOrder = iTicketOrderService.updateTimeOrder(ticketOrderItem.getTicketId(), ticketOrderItem.getUseStart(), ticketOrderItem.getBranchStart(), ticketOrderItem.getBuyCount());
    17. log.info("订单恢复库存{}======订单信息{}===============", timeOrder, ticketOrderItem);
    18. }
    19. );
    20. //清除缓存 redis1
    21. long lRemove = redisUtil.lRemove(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ONE, order);
    22. log.info("清除redis1缓存" + lRemove);
    23. //清除缓存 redis2
    24. redisUtil.del(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());
    25. }
    26. /**
    27. * 对于下单定时任务核对 每间隔50秒查询5分钟前的订单
    28. * 1.防止微信付款成功 订单数据未入库 2.实现定期关单功能
    29. *
    30. * @return void
    31. * @author zhangjunrong
    32. * @date 2022/5/13 9:59
    33. */
    34. @Async
    35. @Scheduled(cron = "0/50 * * * * ? ")
    36. public void orderTimeCheck() {
    37. //redis1 key=>wxPay 设置7分钟有效 一直有效(4分钟更新一次)(redis2key+订单类型+下单时间+支付状态)list<对象>数组redis2 10分钟有效期订单详细信息
    38. //redis2 订单详细信息 8分钟有效时间
    39. //1.获取出redis1 微信支付订单list
    40. List<Object> orderList = redisUtil.lGet(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ZERO, SystemConstant.NUM_NEGATIVE_ONE);
    41. if (ObjectUtil.isNotEmpty(orderList)) {
    42. log.info("定时任务核销单====处理特殊订单开启====================");
    43. List<WxPayListRO> wxPayListROS = redisUtil.castList(orderList, WxPayListRO.class);
    44. wxPayListROS.stream()
    45. //2.获取 前5分钟的订单信息
    46. .filter(order -> DateUtil.between(order.getCreateOrderTime(), DateUtil.date(), DateUnit.MINUTE) >= SystemConstant.NUM_FIVE)
    47. //3.过滤掉已处理的订单 redis2中没有的订单 支付成功会删除redis2记录
    48. .filter(order ->
    49. {
    50. //如果redis2中没有该记录 则删除掉redis1对于该记录
    51. if (!redisUtil.hasKey(SystemConstant.ORDER_TOTAL + order.getOutTradeNo())) {
    52. log.info("定时任务判定是redis否拥有订单====" + order.getOutTradeNo());
    53. long lRemove = redisUtil.lRemove(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ONE, order);
    54. log.info("清除redis1记录" + lRemove);
    55. return false;
    56. }
    57. return true;
    58. })
    59. .forEach(order -> {
    60. //4.调微信接口判定
    61. log.info("定时任务核销单====微信定时任务开始核对订单未支付成功订单====" + order);
    62. ToolWxConfig wxConfig = iToolWxConfigService.find();
    63. //4.1查询微信那的订单状态
    64. JsonNode queryCreateOrder = iToolWxConfigService.queryCreateOrder(wxConfig, order.getOutTradeNo());
    65. //4.2如果查询结果为null 说明用户没有调启微信支付 直接清除订单redis
    66. if (ObjectUtil.isEmpty(queryCreateOrder.get(WXOrderConstant.TRADE_STATE))) {
    67. log.info("定时任务核销单====微信订单信息不存在==============");
    68. //恢复票务库存 清除库存
    69. dealVoidTicket(order);
    70. } else {
    71. //交易状态
    72. String tradeState = queryCreateOrder.get(WXOrderConstant.TRADE_STATE).textValue();
    73. String transactionId = queryCreateOrder.get(WXOrderConstant.TRANSACTION_ID).textValue();
    74. log.info("定时任务核销单====微信订单状态: 微信接口 对象" + queryCreateOrder + "redis缓存" + order.getOrderStatus());
    75. // 4.3核对支付 状态 如果未支付 关单 redis1和redis2清除缓存
    76. if (WxPayStatusEnum.NOTPAY.getValue().equals(tradeState)) {
    77. log.info("定时任务核销单====微信订单信息未支付==========");
    78. //关闭订单
    79. String closeOrder = iToolWxConfigService.closeOrder(wxConfig, order.getOutTradeNo());
    80. log.info("定时任务核销单====返回结果" + closeOrder);
    81. //恢复票务库存 清除库存
    82. dealVoidTicket(order);
    83. }
    84. // 4.4核对支付 状态 如果已支付 redis1未支付 数据库查单再次判定 如果不存在 则入数据库
    85. if (WxPayStatusEnum.SUCCESS.getValue().equals(tradeState)) {
    86. //数据库查单判定
    87. if (ObjectUtil.isEmpty(iTicketOrderService.queryOrderByTranId(transactionId))) {
    88. log.info("定时任务核销单====微信订单信息支付==========数据库未有数据");
    89. //获取redis2
    90. OrderTotalRedisRO orderTotalRedisRO = (OrderTotalRedisRO) redisUtil.get(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());
    91. log.info("微信redis2获取信息===" + orderTotalRedisRO.toString());
    92. //订单金额验证 等等 插入数据库
    93. //redis缓存中的金额
    94. int redisTotal = orderTotalRedisRO.getTicketOrder().getPayMoney().movePointRight(SystemConstant.NUM_TWO).intValue();
    95. //只有金额对等 方可入数据库
    96. if (WxPayUtil.verifyMoney(queryCreateOrder, redisTotal)) {
    97. iTicketOrderService.createAllTicket(orderTotalRedisRO, transactionId);
    98. }
    99. //清除缓存 redis1
    100. long lRemove = redisUtil.lRemove(WxRedisKey.WX_PAY_ORDER, SystemConstant.NUM_ONE, order);
    101. log.info("清除redis1缓存" + lRemove);
    102. //清除缓存 redis2
    103. redisUtil.del(SystemConstant.ORDER_TOTAL + order.getOutTradeNo());
    104. }
    105. }
    106. }
    107. });
    108. }
    109. }

  • 相关阅读:
    我用Axure制作了一款火影小游戏 | PM老猫
    web大作业 静态网页 HTML+CSS+JavaScript橙色的时尚服装购物商城
    Jprofiler的使用查看oom
    使用jenkins连接linux部署jar包
    【原创】非常详细!VMware安装Rocky Linux服务器系统并执行优化,包括修改安装镜像源、ssh免密等等
    Linux中常用的性能分析工具
    【性能】如何计算 Web 页面的 FP 指标
    Completed 404 NOT_FOUND,Whitelabel Error Page
    OpenGL中最简单的窗体创建和渲染(初始化GLFW、GLAD、定义视口大小和resize回调、双层缓冲、输入事件处理)
    9月19日学习记录
  • 原文地址:https://blog.csdn.net/Little___Turtle/article/details/125521581