package com.dtb.portal.service.impl; import com.dtb.portal.config.WxPayAppConfig; import com.dtb.portal.config.WxPayMiniprogramConfig; import com.dtb.portal.config.interceptor.TokenUtils; import com.dtb.portal.controller.view.response.ResultMap; import com.dtb.portal.entity.AppPayData; import com.dtb.portal.entity.MiniprogramPayData; import com.dtb.portal.entity.VipGoodsData; import com.dtb.portal.entity.VipOrderData; import com.dtb.portal.entity.VipUserData; import com.dtb.portal.entity.SysUser; import com.dtb.portal.mapper.SysUserMapper; import com.dtb.portal.service.VipGoodsService; import com.dtb.portal.service.WxPayService; import com.dtb.portal.util.DateUtils; import com.dtb.portal.util.PrimaryIdUtils; import com.github.wxpay.sdk.WXPay; import com.github.wxpay.sdk.WXPayConstants; import com.github.wxpay.sdk.WXPayUtil; import com.wechat.pay.java.core.Config; import com.wechat.pay.java.core.RSAAutoCertificateConfig; import com.wechat.pay.java.core.cipher.SignatureResult; import com.wechat.pay.java.service.payments.app.AppService; import com.wechat.pay.java.service.payments.app.AppServiceExtension; import com.wechat.pay.java.service.payments.app.model.*; import com.wechat.pay.java.service.payments.jsapi.JsapiService; import com.wechat.pay.java.service.payments.jsapi.model.*; import com.wechat.pay.java.service.payments.jsapi.model.Payer; import com.wechat.pay.java.service.payments.model.Transaction; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.IOException; import java.time.LocalDateTime; import java.util.*; import static java.util.Objects.requireNonNull; @Service public class WxPayServiceImpl implements WxPayService { private final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class); @Value("${wxpay.app.v3-key}") private String v3Key; @Autowired private SysUserMapper sysUserMapper; /* private HttpClient httpClient; private WxPayServiceImpl(HttpClient httpClient) { this.httpClient = httpClient; }*/ @Autowired private WxPayAppConfig wxPayAppConfig; @Autowired private WxPayMiniprogramConfig wxPayMiniprogramConfig; @Autowired private VipGoodsService vipGoodsService; /** * @param vipGoodsId : 订单编号 * @return */ @Override public ResultMap unifiedOrder(String vipGoodsId) { Map returnMap = new HashMap<>(); Map responseMap = new HashMap<>(); Map requestMap = new HashMap<>(); String orderNo = ""; try { VipGoodsData vipGoodsData = vipGoodsService.getById(vipGoodsId); if (Objects.isNull(vipGoodsData)) { throw new RuntimeException("商品不存在"); } String vipMoney = vipGoodsData.getVipMoney(); double amount = Double.parseDouble(vipMoney); orderNo = PrimaryIdUtils.getId().toString(); WXPay wxpay = new WXPay(wxPayAppConfig); requestMap.put("body", vipGoodsData.getName()); // 商品描述 requestMap.put("out_trade_no", orderNo); // 商户订单号 requestMap.put("total_fee", String.valueOf((int) (amount * 100))); // 总金额 //requestMap.put("spbill_create_ip", HttpContextUtils.getIpAddr()); // 终端IP requestMap.put("trade_type", "APP"); // App支付类型 requestMap.put("notify_url", wxPayAppConfig.getPayNotifyUrl()); // 接收微信支付异步通知回调地址 Map resultMap = wxpay.unifiedOrder(requestMap); logger.info("下单返回的信息是:{}", resultMap); //获取返回码 String returnCode = resultMap.get("return_code"); //String returnMsg = resultMap.get("return_msg"); //若返回码为SUCCESS,则会返回一个result_code,再对该result_code进行判断 if ("SUCCESS".equals(returnCode)) { String resultCode = resultMap.get("result_code"); String errCodeDes = resultMap.get("err_code_des"); if ("SUCCESS".equals(resultCode)) { responseMap = resultMap; } } if (responseMap.isEmpty()) { return ResultMap.error("获取预支付交易会话标识失败"); } // 3、签名生成算法 Long time = System.currentTimeMillis() / 1000; String timestamp = time.toString(); returnMap.put("appid", wxPayAppConfig.getAppID()); returnMap.put("partnerid", wxPayAppConfig.getMchID()); returnMap.put("prepayid", responseMap.get("prepay_id")); returnMap.put("noncestr", responseMap.get("nonce_str")); returnMap.put("timestamp", timestamp); returnMap.put("package", "Sign=WXPay"); returnMap.put("sign", responseMap.get("sign")); returnMap.put("out_trade_no", orderNo); String signMD5 = WXPayUtil.generateSignature(returnMap, wxPayAppConfig.getKey(), WXPayConstants.SignType.MD5); String signSHA256 = WXPayUtil.generateSignature(returnMap, wxPayAppConfig.getKey(), WXPayConstants.SignType.HMACSHA256); returnMap.put("signMD5", signMD5); returnMap.put("signSHA256", signSHA256); returnMap.put("base64SignMD5", Base64.getEncoder().encodeToString(signMD5.getBytes())); returnMap.put("base64SignSHA256", Base64.getEncoder().encodeToString(signSHA256.getBytes())); returnMap.put("key", wxPayAppConfig.getKey()); logger.info("返回的信息是:{}", returnMap); return ResultMap.ok().put("data", returnMap); } catch (Exception e) { logger.error("订单号:{},错误信息:{}", orderNo, e.getMessage()); return ResultMap.error("微信支付统一下单失败"); } finally { //生成订单在数据库 VipOrderData data = new VipOrderData(); data.setId(PrimaryIdUtils.getId().toString()); data.setOutTradeNo(orderNo); data.setStatus("1"); data.setVipGoodsId(vipGoodsId); data.setCreateTime(LocalDateTime.now()); data.setUpdateTime(LocalDateTime.now()); vipGoodsService.insertVipOrderData(data); } } @Override public String notify(String notifyStr) { String xmlBack = " "; try { // 转换成map Map resultMap = WXPayUtil.xmlToMap(notifyStr); WXPay wxpayApp = new WXPay(wxPayAppConfig); if (wxpayApp.isPayResultNotifySignatureValid(resultMap)) { String returnCode = resultMap.get("return_code"); //状态 String outTradeNo = resultMap.get("out_trade_no");//商户订单号 String transactionId = resultMap.get("transaction_id"); if (returnCode.equals("SUCCESS")) { if (StringUtils.isNotBlank(outTradeNo)) { /** * 注意!!! * 请根据业务流程,修改数据库订单支付状态,和其他数据的相应状态 * */ logger.info("微信手机支付回调成功,订单号:{}", outTradeNo); xmlBack = ""; } } } } catch (Exception e) { e.printStackTrace(); } return xmlBack; } @Override public ResultMap refund(String orderNo, double amount, String refundReason) { if (StringUtils.isBlank(orderNo)) { return ResultMap.error("订单编号不能为空"); } if (amount <= 0) { return ResultMap.error("退款金额必须大于0"); } Map responseMap = new HashMap<>(); Map requestMap = new HashMap<>(); WXPay wxpay = new WXPay(wxPayAppConfig); requestMap.put("out_trade_no", orderNo); requestMap.put("out_refund_no", UUID.randomUUID().toString().replaceAll("-", "")); requestMap.put("total_fee", "订单支付时的总金额,需要从数据库查"); requestMap.put("refund_fee", String.valueOf((int) (amount * 100)));//所需退款金额 requestMap.put("refund_desc", refundReason); try { responseMap = wxpay.refund(requestMap); } catch (Exception e) { e.printStackTrace(); } String return_code = responseMap.get("return_code"); //返回状态码 String return_msg = responseMap.get("return_msg"); //返回信息 if ("SUCCESS".equals(return_code)) { String result_code = responseMap.get("result_code"); //业务结果 String err_code_des = responseMap.get("err_code_des"); //错误代码描述 if ("SUCCESS".equals(result_code)) { //表示退款申请接受成功,结果通过退款查询接口查询 //修改用户订单状态为退款申请中或已退款。退款异步通知根据需求,可选 return ResultMap.ok("退款申请成功"); } else { logger.info("订单号:{}错误信息:{}", orderNo, err_code_des); return ResultMap.error(err_code_des); } } else { logger.info("订单号:{}错误信息:{}", orderNo, return_msg); return ResultMap.error(return_msg); } } /** * @param vipGoodsId 商品主键 * @return */ @Override public AppPayData unifiedOrder2(String vipGoodsId) { logger.info("微信APP支付基础信息:{}", wxPayAppConfig); //查询商品是否存在,存在则下单,不存在则不下单 VipGoodsData data = vipGoodsService.getById(vipGoodsId); if (Objects.isNull(data)) { throw new RuntimeException("VIP商品不存在"); } // 使用自动更新平台证书的RSA配置 // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错 Config config = new RSAAutoCertificateConfig.Builder() .merchantId(wxPayAppConfig.getMchID()) .privateKeyFromPath(wxPayAppConfig.getCertPath()) .merchantSerialNumber(wxPayAppConfig.getMerchantSerialNumber()) //.apiV3Key(wxPayAppConfig.getKey()) .apiV3Key(v3Key) .build(); // 构建service AppService service = new AppService.Builder().config(config).build(); String orderNo = PrimaryIdUtils.getId().toString(); com.wechat.pay.java.service.payments.app.model.PrepayRequest request = new com.wechat.pay.java.service.payments.app.model.PrepayRequest(); com.wechat.pay.java.service.payments.app.model.Amount amount = new com.wechat.pay.java.service.payments.app.model.Amount(); //金额计算 ,乘以100 String money = data.getVipMoney(); //int orderAmount = Integer.parseInt(money) * 100; int orderAmount = (int) (Double.parseDouble(money) * 100); amount.setTotal(orderAmount); request.setAmount(amount); request.setAppid(wxPayAppConfig.getAppID()); request.setMchid(wxPayAppConfig.getMchID()); request.setDescription(data.getName()); request.setNotifyUrl(wxPayAppConfig.getPayNotifyUrl()); request.setOutTradeNo(orderNo); // 调用下单方法,得到应答 com.wechat.pay.java.service.payments.app.model.PrepayResponse response = service.prepay(request); logger.info("调用微信app下单返回的信息是:{}", response); String prepayId = response.getPrepayId(); AppPayData appPayData = new AppPayData(); appPayData.setAppid(wxPayAppConfig.getAppID()); appPayData.setPrepayid(prepayId); appPayData.setPartnerid(wxPayAppConfig.getMchID()); String noncestr = UUID.randomUUID().toString().replaceAll("-", ""); appPayData.setNoncestr(noncestr); //appPayData.setTimestamp(String.valueOf(System.currentTimeMillis())); //生成签名 Map returnMap = new HashMap<>(); Long time = System.currentTimeMillis() / 1000; String timestamp = time.toString(); returnMap.put("appid", wxPayAppConfig.getAppID()); returnMap.put("timestamp", timestamp); returnMap.put("noncestr", noncestr); returnMap.put("prepayid", prepayId); //returnMap.put("package", "Sign=WXPay"); //returnMap.put("package", "prepay_id="+prepayId); AppServiceExtension appServiceExtension = new AppServiceExtension.Builder().config(config).build(); com.wechat.pay.java.service.payments.app.model.PrepayRequest prepayRequest = new com.wechat.pay.java.service.payments.app.model.PrepayRequest(); prepayRequest.setAmount(amount); prepayRequest.setAppid(wxPayAppConfig.getAppID()); prepayRequest.setMchid(wxPayAppConfig.getMchID()); prepayRequest.setDescription(data.getName()); prepayRequest.setNotifyUrl(wxPayAppConfig.getPayNotifyUrl()); prepayRequest.setOutTradeNo(orderNo); com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse prepayWithRequestPaymentResponse = appServiceExtension.prepayWithRequestPayment(prepayRequest); appPayData.setPrepayWithRequestPaymentResponse(prepayWithRequestPaymentResponse); SignatureResult signatureResult = config.createSigner().sign(wxPayAppConfig.getAppID() + "\n" + timestamp + "\n" + noncestr + "\n" + "prepay_id=" + prepayId + "\n"); String sign = signatureResult.getSign(); logger.info("签名值是:{}", sign); appPayData.setSign(sign); appPayData.setBase64Sign(Base64.getEncoder().encodeToString(sign.getBytes())); try { String signMD5 = WXPayUtil.generateSignature(returnMap, v3Key, WXPayConstants.SignType.MD5); String signSHA256 = WXPayUtil.generateSignature(returnMap, v3Key, WXPayConstants.SignType.HMACSHA256); //生成微信签名 appPayData.setSignMD5(signMD5); appPayData.setBase64SignMD5(Base64.getEncoder().encodeToString(signMD5.getBytes())); appPayData.setSignSHA256(signSHA256); appPayData.setBase64SignSHA256(Base64.getEncoder().encodeToString(signSHA256.getBytes())); appPayData.setTimestamp(timestamp); } catch (Exception e) { logger.error("生成微信签名失败:", e); throw new RuntimeException("生成微信签名失败"); } finally { } return appPayData; } /** * APP支付成功后调用,主要计算VIP时长 * * @param vipGoodsId 商品主键 * @param out_trade_no * @return */ @Override public SysUser success(String vipGoodsId, String out_trade_no) { //查询商品是否存在,存在则下单,不存在则不下单 VipGoodsData data = vipGoodsService.getById(vipGoodsId); if (Objects.isNull(data)) { throw new RuntimeException("VIP商品不存在"); } VipOrderData vipOrderData = vipGoodsService.getOrderByOutTradeNo(out_trade_no); if (Objects.isNull(vipOrderData)) { throw new RuntimeException("订单不存在"); } //查询订单是否支付成功,支付成功:生成VIP时长,失败异常 /* QueryOrderByOutTradeNoRequest queryOrderByOutTradeNoRequest = new QueryOrderByOutTradeNoRequest(); queryOrderByOutTradeNoRequest.setOutTradeNo(out_trade_no); queryOrderByOutTradeNoRequest.setMchid(wxPayAppConfig.getMchID()); Transaction transaction = queryOrderByOutTradeNo(queryOrderByOutTradeNoRequest);*/ Transaction transaction = queryOrderByOutTradeNo(out_trade_no); Transaction.TradeStateEnum tradeState = transaction.getTradeState(); //logger.info("支付返回的信息是:{}", transaction); //logger.info("根据订单号查询是否支付成功:{}", tradeState.name()); if ("SUCCESS".equals(tradeState.name())) { logger.info("支付成功:{}", transaction); //查询用户是否已经开通过,开通过则续费,没有开通过怎插新数据 String userId = TokenUtils.getUserId(); VipUserData vipUserData = vipGoodsService.selectByUserId(userId, vipGoodsId); //VIP时长 String vipStartDate = ""; String vipEndDate = ""; String vipDate = data.getVipDate(); if (Objects.isNull(vipUserData)) { //没有开通过,新开通,开始时间=当天时间,结束时间=会员时长+当前时间 vipStartDate = DateUtils.toStringYMD(new Date()); vipEndDate = DateUtils.getAfterDate(Integer.parseInt(vipDate)); } else { //开通过,查看有没有过期,过期:新开通,不过期,续费 String vipEndDateStr = vipUserData.getVipEndDate(); Date vipEndDate1 = DateUtils.toDateYMDHMS(vipEndDateStr); Date todayDate = DateUtils.toDateYMDHMS(DateUtils.toStringYMD(new Date())); int compareTo = todayDate.compareTo(vipEndDate1); //0:到当天 1:过期 -1:不过期 if (compareTo == 0 || compareTo == -1) { //不过期,续费,计算VIP结束时间 vipEndDate = DateUtils.getDesignDateStr(vipEndDate1, DateUtils.sdfyyyyMMdd, Integer.parseInt(vipDate)); vipStartDate = vipUserData.getVipStartDate(); } else { //过期,删除原来的数据,在重新添加 vipGoodsService.deleteVipUser(vipUserData.getId()); //过期重新开通,设置新的开始和结束时间 vipStartDate = DateUtils.toStringYMD(new Date()); vipEndDate = DateUtils.getAfterDate(Integer.parseInt(vipDate)); } } VipUserData saveVipUserData = new VipUserData(); saveVipUserData.setId(PrimaryIdUtils.getId().toString()); saveVipUserData.setUserId(userId); saveVipUserData.setVipGoodsId(vipGoodsId); saveVipUserData.setVipStartDate(vipStartDate); saveVipUserData.setVipEndDate(vipEndDate); saveVipUserData.setCreateTime(LocalDateTime.now()); saveVipUserData.setUpdateTime(LocalDateTime.now()); vipGoodsService.saveVipUserData(saveVipUserData); //修改用户表,添加是VIP用户,VIP最后时间,剩余时长 Long vipResidueDate = DateUtils.getDifferenceTime(DateUtils.toDateYMDHMS(vipStartDate), DateUtils.toDateYMDHMS(vipEndDate)); SysUser sysUser = sysUserMapper.selectOne(userId); sysUser.setIsVip(true); sysUser.setVipResidueDate(vipResidueDate); sysUser.setVipEndDate(vipEndDate); sysUser.setUpdateTime(new Date()); sysUserMapper.update(sysUser); //更新订单状态为已支付 vipOrderData.setStatus("2"); // 1:待支付 2:已支付 3:已取消 vipOrderData.setUpdateTime(LocalDateTime.now()); vipGoodsService.updateVipOrderData(vipOrderData); logger.info("VIP支付成功处理完成,用户ID:{},订单号:{},VIP结束时间:{}", userId, out_trade_no, vipEndDate); return sysUser; } else { throw new RuntimeException("订单支付失败"); } } @Override public Transaction queryOrderByOutTradeNo(String out_trade_no) { return queryOrderByOutTradeNo(out_trade_no, "app"); } /** * 根据订单号和支付类型查询订单状态 * @param out_trade_no 订单号 * @param payType 支付类型:app 或 miniprogram * @return 交易信息 */ public Transaction queryOrderByOutTradeNo(String out_trade_no, String payType) { Config config; if ("miniprogram".equals(payType)) { // 使用小程序配置 config = new RSAAutoCertificateConfig.Builder() .merchantId(wxPayMiniprogramConfig.getMchID()) .privateKeyFromPath(wxPayMiniprogramConfig.getCertPath()) .merchantSerialNumber(wxPayMiniprogramConfig.getMerchantSerialNumber()) .apiV3Key(wxPayMiniprogramConfig.getV3Key()) .build(); } else { // 使用APP配置 config = new RSAAutoCertificateConfig.Builder() .merchantId(wxPayAppConfig.getMchID()) .privateKeyFromPath(wxPayAppConfig.getCertPath()) .merchantSerialNumber(wxPayAppConfig.getMerchantSerialNumber()) .apiV3Key(v3Key) .build(); } // 构建service - 对于查询订单,使用JsapiService即可(小程序和APP都支持) JsapiService service = new JsapiService.Builder().config(config).build(); com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest queryOrderByOutTradeNoRequest = new com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest(); queryOrderByOutTradeNoRequest.setOutTradeNo(out_trade_no); queryOrderByOutTradeNoRequest.setMchid("miniprogram".equals(payType) ? wxPayMiniprogramConfig.getMchID() : wxPayAppConfig.getMchID()); Transaction transaction = service.queryOrderByOutTradeNo(queryOrderByOutTradeNoRequest); Transaction.TradeStateEnum tradeState = transaction.getTradeState(); logger.info("{}支付订单查询结果 - 订单号:{},状态:{}", payType, out_trade_no, tradeState.name()); if ("SUCCESS".equals(tradeState.name())) { logger.info("支付成功:{}", transaction); } return transaction; } // ============= 小程序支付相关实现 ============= @Override public Object miniprogramUnifiedOrder(String vipGoodsId, String openid) { logger.info("小程序支付基础信息:{}", wxPayMiniprogramConfig); logger.info("用户openid:{}", openid); //查询商品是否存在,存在则下单,不存在则不下单 VipGoodsData data = vipGoodsService.getById(vipGoodsId); if (Objects.isNull(data)) { throw new RuntimeException("VIP商品不存在"); } if (StringUtils.isBlank(openid)) { throw new RuntimeException("用户openid不能为空"); } try { // 使用自动更新平台证书的RSA配置 Config config = new RSAAutoCertificateConfig.Builder() .merchantId(wxPayMiniprogramConfig.getMchID()) .privateKeyFromPath(wxPayMiniprogramConfig.getCertPath()) .merchantSerialNumber(wxPayMiniprogramConfig.getMerchantSerialNumber()) .apiV3Key(wxPayMiniprogramConfig.getV3Key()) .build(); // 构建service JsapiService service = new JsapiService.Builder().config(config).build(); String orderNo = PrimaryIdUtils.getId().toString(); // 构建小程序支付请求 com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest(); com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount(); //金额计算,乘以100转换为分 String money = data.getVipMoney(); int orderAmount = (int) (Double.parseDouble(money) * 100); amount.setTotal(orderAmount); request.setAmount(amount); request.setAppid(wxPayMiniprogramConfig.getAppID()); request.setMchid(wxPayMiniprogramConfig.getMchID()); request.setDescription(data.getName()); request.setNotifyUrl(wxPayMiniprogramConfig.getPayNotifyUrl()); request.setOutTradeNo(orderNo); // 设置支付者信息 Payer payer = new Payer(); payer.setOpenid(openid); request.setPayer(payer); // 调用下单方法,得到应答 com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse response = service.prepay(request); logger.info("调用微信小程序下单返回的信息是:{}", response); String prepayId = response.getPrepayId(); // 构建小程序支付参数 MiniprogramPayData payData = new MiniprogramPayData(); // 生成时间戳 long timestamp = System.currentTimeMillis() / 1000; String timeStamp = String.valueOf(timestamp); // 生成随机字符串 String nonceStr = UUID.randomUUID().toString().replaceAll("-", ""); // 构建package参数 String packageParam = "prepay_id=" + prepayId; // 生成签名 String signStr = wxPayMiniprogramConfig.getAppID() + "\n" + timeStamp + "\n" + nonceStr + "\n" + packageParam + "\n"; SignatureResult signatureResult = config.createSigner().sign(signStr); String paySign = signatureResult.getSign(); // 设置小程序支付参数 payData.setTimeStamp(timeStamp); payData.setNonceStr(nonceStr); payData.setPackage_(packageParam); payData.setPackageParam(packageParam); // 设置用于uni.requestPayment的package字段 payData.setSignType("MD5"); payData.setPaySign(paySign); payData.setOut_trade_no(orderNo); payData.setPrepay_id(prepayId); payData.setDescription(data.getName()); payData.setTotal(orderAmount); payData.setRawData(response); logger.info("小程序支付参数:{}", payData); // 通过openid查询用户ID String userId = null; try { SysUser user = sysUserMapper.selectByOpenId(openid); if (user != null) { userId = user.getId(); } } catch (Exception e) { logger.warn("根据openid查询用户失败: {}", openid, e); } // 生成订单记录 VipOrderData orderData = new VipOrderData(); orderData.setId(PrimaryIdUtils.getId().toString()); orderData.setOutTradeNo(orderNo); orderData.setStatus("1"); orderData.setVipGoodsId(vipGoodsId); orderData.setUserId(userId); // 记录用户ID orderData.setOpenid(openid); // 记录openid orderData.setCreateTime(LocalDateTime.now()); orderData.setUpdateTime(LocalDateTime.now()); vipGoodsService.insertVipOrderData(orderData); return payData; } catch (Exception e) { logger.error("小程序支付下单失败 - vipGoodsId: {}, openid: {}", vipGoodsId, openid, e); String errorMsg = e.getMessage(); if (errorMsg == null || errorMsg.trim().isEmpty()) { errorMsg = e.getClass().getSimpleName() + ": " + e.toString(); } throw new RuntimeException("小程序支付下单失败: " + errorMsg); } } @Override public String miniprogramNotify(String notifyStr) { String xmlBack = ""; try { // 转换成map Map resultMap = WXPayUtil.xmlToMap(notifyStr); WXPay wxpayMiniprogram = new WXPay(wxPayMiniprogramConfig); if (wxpayMiniprogram.isPayResultNotifySignatureValid(resultMap)) { String returnCode = resultMap.get("return_code"); //状态 String outTradeNo = resultMap.get("out_trade_no");//商户订单号 String transactionId = resultMap.get("transaction_id"); if ("SUCCESS".equals(returnCode)) { if (StringUtils.isNotBlank(outTradeNo)) { logger.info("小程序支付异步通知成功,订单号:{}", outTradeNo); try { // 查询订单信息 VipOrderData vipOrderData = vipGoodsService.getOrderByOutTradeNo(outTradeNo); if (vipOrderData != null && "1".equals(vipOrderData.getStatus())) { // 订单状态为待支付,进行VIP处理 String vipGoodsId = vipOrderData.getVipGoodsId(); String userId = vipOrderData.getUserId(); if (StringUtils.isNotBlank(userId)) { // 有用户ID,执行完整的VIP处理逻辑 logger.info("开始处理小程序支付异步通知VIP逻辑 - 用户ID: {}, 订单号: {}", userId, outTradeNo); // 查询VIP商品信息 VipGoodsData vipGoodsData = vipGoodsService.getById(vipGoodsId); if (vipGoodsData != null) { // 处理VIP逻辑(复用success方法的逻辑) handleVipLogic(userId, vipGoodsId, vipGoodsData, outTradeNo); logger.info("小程序支付异步通知VIP处理完成 - 用户ID: {}, 订单号: {}", userId, outTradeNo); } else { logger.warn("VIP商品不存在 - vipGoodsId: {}, 订单号: {}", vipGoodsId, outTradeNo); } } else { logger.warn("订单中缺少用户ID,无法处理VIP逻辑 - 订单号: {}", outTradeNo); } // 更新订单状态为已支付 vipOrderData.setStatus("2"); // 已支付 vipOrderData.setUpdateTime(LocalDateTime.now()); vipGoodsService.updateVipOrderData(vipOrderData); logger.info("小程序支付异步通知处理完成,订单号:{}", outTradeNo); } else { logger.info("小程序支付异步通知 - 订单已处理或不存在,订单号:{}", outTradeNo); } } catch (Exception e) { logger.error("小程序支付异步通知业务处理失败,订单号:{}", outTradeNo, e); // 即使业务处理失败,也要返回SUCCESS,避免微信重复通知 } xmlBack = ""; } } } else { logger.warn("小程序支付异步通知签名验证失败"); } } catch (Exception e) { logger.error("小程序支付通知处理失败", e); } return xmlBack; } @Override public SysUser miniprogramSuccess(String vipGoodsId, String out_trade_no) { //查询商品是否存在,存在则下单,不存在则不下单 VipGoodsData data = vipGoodsService.getById(vipGoodsId); if (Objects.isNull(data)) { throw new RuntimeException("VIP商品不存在"); } VipOrderData vipOrderData = vipGoodsService.getOrderByOutTradeNo(out_trade_no); if (Objects.isNull(vipOrderData)) { throw new RuntimeException("订单不存在"); } //查询订单是否支付成功,支付成功:生成VIP时长,失败异常 Transaction transaction = queryOrderByOutTradeNo(out_trade_no, "miniprogram"); Transaction.TradeStateEnum tradeState = transaction.getTradeState(); logger.info("小程序支付订单查询结果 - 订单号:{},状态:{}", out_trade_no, tradeState.name()); if ("SUCCESS".equals(tradeState.name())) { logger.info("小程序支付成功:{}", transaction); //查询用户是否已经开通过,开通过则续费,没有开通过怎插新数据 String userId = TokenUtils.getUserId(); VipUserData vipUserData = vipGoodsService.selectByUserId(userId, vipGoodsId); //VIP时长 String vipStartDate = ""; String vipEndDate = ""; String vipDate = data.getVipDate(); if (Objects.isNull(vipUserData)) { //没有开通过,新开通,开始时间=当天时间,结束时间=会员时长+当前时间 vipStartDate = DateUtils.toStringYMD(new Date()); vipEndDate = DateUtils.getAfterDate(Integer.parseInt(vipDate)); } else { //开通过,查看有没有过期,过期:新开通,不过期,续费 String vipEndDateStr = vipUserData.getVipEndDate(); Date vipEndDate1 = DateUtils.toDateYMDHMS(vipEndDateStr); Date todayDate = DateUtils.toDateYMDHMS(DateUtils.toStringYMD(new Date())); int compareTo = todayDate.compareTo(vipEndDate1); //0:到当天 1:过期 -1:不过期 if (compareTo == 0 || compareTo == -1) { //不过期,续费,计算VIP结束时间 vipEndDate = DateUtils.getDesignDateStr(vipEndDate1, DateUtils.sdfyyyyMMdd, Integer.parseInt(vipDate)); vipStartDate = vipUserData.getVipStartDate(); } else { //过期,删除原来的数据,在重新添加 vipGoodsService.deleteVipUser(vipUserData.getId()); //过期重新开通,设置新的开始和结束时间 vipStartDate = DateUtils.toStringYMD(new Date()); vipEndDate = DateUtils.getAfterDate(Integer.parseInt(vipDate)); } } VipUserData saveVipUserData = new VipUserData(); saveVipUserData.setId(PrimaryIdUtils.getId().toString()); saveVipUserData.setUserId(userId); saveVipUserData.setVipGoodsId(vipGoodsId); saveVipUserData.setVipStartDate(vipStartDate); saveVipUserData.setVipEndDate(vipEndDate); saveVipUserData.setCreateTime(LocalDateTime.now()); saveVipUserData.setUpdateTime(LocalDateTime.now()); vipGoodsService.saveVipUserData(saveVipUserData); //修改用户表,添加是VIP用户,VIP最后时间,剩余时长 Long vipResidueDate = DateUtils.getDifferenceTime(DateUtils.toDateYMDHMS(vipStartDate), DateUtils.toDateYMDHMS(vipEndDate)); SysUser sysUser = sysUserMapper.selectOne(userId); sysUser.setIsVip(true); sysUser.setVipResidueDate(vipResidueDate); sysUser.setVipEndDate(vipEndDate); sysUser.setUpdateTime(new Date()); sysUserMapper.update(sysUser); //更新订单状态为已支付 vipOrderData.setStatus("2"); // 1:待支付 2:已支付 3:已取消 vipOrderData.setUpdateTime(LocalDateTime.now()); vipGoodsService.updateVipOrderData(vipOrderData); logger.info("小程序VIP支付成功处理完成,用户ID:{},订单号:{},VIP结束时间:{}", userId, out_trade_no, vipEndDate); return sysUser; } else { throw new RuntimeException("小程序订单支付失败,状态:" + tradeState.name()); } } /** * 处理VIP逻辑(抽取的公共方法,供success和异步通知使用) * @param userId 用户ID * @param vipGoodsId VIP商品ID * @param vipGoodsData VIP商品信息 * @param outTradeNo 订单号 */ private void handleVipLogic(String userId, String vipGoodsId, VipGoodsData vipGoodsData, String outTradeNo) { try { //查询用户是否已经开通过,开通过则续费,没有开通过则插新数据 VipUserData vipUserData = vipGoodsService.selectByUserId(userId, vipGoodsId); //VIP时长 String vipStartDate = ""; String vipEndDate = ""; String vipDate = vipGoodsData.getVipDate(); if (Objects.isNull(vipUserData)) { //没有开通过,新开通,开始时间=当天时间,结束时间=会员时长+当前时间 vipStartDate = DateUtils.toStringYMD(new Date()); vipEndDate = DateUtils.getAfterDate(Integer.parseInt(vipDate)); } else { //开通过,查看有没有过期,过期:新开通,不过期,续费 String vipEndDateStr = vipUserData.getVipEndDate(); Date vipEndDate1 = DateUtils.toDateYMDHMS(vipEndDateStr); Date todayDate = DateUtils.toDateYMDHMS(DateUtils.toStringYMD(new Date())); int compareTo = todayDate.compareTo(vipEndDate1); //0:到当天 1:过期 -1:不过期 if (compareTo == 0 || compareTo == -1) { //不过期,续费,计算VIP结束时间 vipEndDate = DateUtils.getDesignDateStr(vipEndDate1, DateUtils.sdfyyyyMMdd, Integer.parseInt(vipDate)); vipStartDate = vipUserData.getVipStartDate(); } else { //过期,删除原来的数据,在重新添加 vipGoodsService.deleteVipUser(vipUserData.getId()); //过期重新开通,设置新的开始和结束时间 vipStartDate = DateUtils.toStringYMD(new Date()); vipEndDate = DateUtils.getAfterDate(Integer.parseInt(vipDate)); } } VipUserData saveVipUserData = new VipUserData(); saveVipUserData.setId(PrimaryIdUtils.getId().toString()); saveVipUserData.setUserId(userId); saveVipUserData.setVipGoodsId(vipGoodsId); saveVipUserData.setVipStartDate(vipStartDate); saveVipUserData.setVipEndDate(vipEndDate); saveVipUserData.setCreateTime(LocalDateTime.now()); saveVipUserData.setUpdateTime(LocalDateTime.now()); vipGoodsService.saveVipUserData(saveVipUserData); //修改用户表,添加是VIP用户,VIP最后时间,剩余时长 Long vipResidueDate = DateUtils.getDifferenceTime(DateUtils.toDateYMDHMS(vipStartDate), DateUtils.toDateYMDHMS(vipEndDate)); SysUser sysUser = sysUserMapper.selectOne(userId); if (sysUser != null) { sysUser.setIsVip(true); sysUser.setVipResidueDate(vipResidueDate); sysUser.setVipEndDate(vipEndDate); sysUser.setUpdateTime(new Date()); sysUserMapper.update(sysUser); logger.info("VIP处理完成 - 用户ID: {}, 订单号: {}, VIP结束时间: {}", userId, outTradeNo, vipEndDate); } else { logger.warn("用户不存在,无法更新VIP状态 - 用户ID: {}", userId); } } catch (Exception e) { logger.error("VIP逻辑处理失败 - 用户ID: {}, 订单号: {}", userId, outTradeNo, e); throw e; } } public static void main(String[] args) throws IOException { /** Native 支付下单为例 */ /* *//** 商户号 *//* String merchantId = "1659536133"; *//** 商户API私钥路径 *//* String privateKeyPath = "D:\\soft\\WXCertUtil\\WXCertUtil\\cert\\1659536133_20240224_cert\\apiclient_key.pem"; *//** 商户证书序列号 *//* String merchantSerialNumber = "2C9364545EF9C4C82700563B8C398451E14743B3"; *//** 商户APIV3密钥 *//* String apiV3Key = "A123456789B123456789C1234567890D"; // 使用自动更新平台证书的RSA配置 // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错 Config config = new RSAAutoCertificateConfig.Builder() .merchantId(merchantId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(merchantSerialNumber) .apiV3Key(apiV3Key) .build(); // 构建service AppService service = new AppService.Builder().config(config).build(); // request.setXxx(val)设置所需参数,具体参数可见Request定义 String orderNo = PrimaryIdUtils.getId().toString(); PrepayRequest request = new PrepayRequest(); Amount amount = new Amount(); amount.setTotal(100); request.setAmount(amount); request.setAppid("wx8fdb27b97ed17533"); request.setMchid("1659536133"); request.setDescription("VIP一个月商品"); request.setNotifyUrl("http://120.46.40.61:18885/api/swagger-ui.html"); request.setOutTradeNo(orderNo); // 调用下单方法,得到应答 PrepayResponse response = service.prepay(request); // 使用微信扫描 code_url 对应的二维码,即可体验Native支付 System.out.println(">>>>>>>>>>>:" + response);*/ String noncestr = UUID.randomUUID().toString().replaceAll("-", ""); long currentTimeMillis = System.currentTimeMillis() / 1000; System.out.println(currentTimeMillis); // System.out.println(noncestr.length()); /* Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, 2); int year = calendar.get(Calendar.YEAR); int month = calendar.get(Calendar.MONTH) + 1; int day = calendar.get(Calendar.DAY_OF_MONTH); System.out.println("7天后的日期为:" + year + "-" + month + "-" + day);*/ //Base64.getDecoder().decode("NDU1ODAwNjk2M0QyOTE2QTMwNjBGNUQwMTEwNkU4ODA0OTcyQTkyOTVDRkJGRTYzQUMzOUYyRkE5Q0RGQ0Y1Qg=="); String vipEndDateStr = "2024-03-3"; Date vipEndDate = DateUtils.toDateYMDHMS(vipEndDateStr); Date date = DateUtils.toDateYMDHMS(DateUtils.toStringYMD(new Date())); int compareTo = vipEndDate.compareTo(date); System.out.println(compareTo); } /* public Transaction queryOrderByOutTradeNo(QueryOrderByOutTradeNoRequest request) { String requestPath = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}"; QueryOrderByOutTradeNoRequest realRequest = request; // 添加 path param requestPath = requestPath.replace("{" + "out_trade_no" + "}", urlEncode(realRequest.getOutTradeNo())); // 添加 query param QueryParameter queryParameter = new QueryParameter(); if (realRequest.getMchid() != null) { queryParameter.add("mchid", urlEncode(realRequest.getMchid())); } requestPath += queryParameter.getQueryStr(); HttpHeaders headers = new HttpHeaders(); headers.addHeader(Constant.ACCEPT, MediaType.APPLICATION_JSON.getValue()); headers.addHeader(Constant.CONTENT_TYPE, MediaType.APPLICATION_JSON.getValue()); HttpRequest httpRequest = new HttpRequest.Builder() .httpMethod(HttpMethod.GET) .url(requestPath) .headers(headers) .build(); HttpResponse httpResponse = httpClient.execute(httpRequest, Transaction.class); return httpResponse.getServiceResponse(); }*/ }