|  |  |  | 
|---|
|  |  |  | package com.ruoyi.web.controller.api; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import com.alibaba.fastjson2.JSONObject; | 
|---|
|  |  |  | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | 
|---|
|  |  |  | import com.fasterxml.jackson.core.type.TypeReference; | 
|---|
|  |  |  | import com.ruoyi.common.core.domain.AjaxResult; | 
|---|
|  |  |  | import com.ruoyi.common.core.domain.R; | 
|---|
|  |  |  | import com.ruoyi.common.utils.CodeGenerateUtils; | 
|---|
|  |  |  | import com.ruoyi.framework.web.service.TokenService; | 
|---|
|  |  |  | 
|---|
|  |  |  | import com.ruoyi.system.service.TSysInspectionService; | 
|---|
|  |  |  | import com.ruoyi.system.service.TSysOtherConfigService; | 
|---|
|  |  |  | import com.ruoyi.system.service.TSysPayRecordService; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.enums.RefundEnum; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.enums.TradeStateEnum; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.model.WeixinPayProperties; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.model.WxPaymentRefundModel; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.utils.WxTimeUtils; | 
|---|
|  |  |  | import com.ruoyi.system.wxPay.utils.WxV3Pay; | 
|---|
|  |  |  | import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; | 
|---|
|  |  |  | import io.swagger.annotations.Api; | 
|---|
|  |  |  | import io.swagger.annotations.ApiOperation; | 
|---|
|  |  |  | import lombok.extern.slf4j.Slf4j; | 
|---|
|  |  |  | 
|---|
|  |  |  | import org.springframework.web.bind.annotation.*; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import javax.servlet.http.HttpServletRequest; | 
|---|
|  |  |  | import java.io.IOException; | 
|---|
|  |  |  | import javax.servlet.http.HttpServletResponse; | 
|---|
|  |  |  | import java.io.BufferedReader; | 
|---|
|  |  |  | import java.io.PrintWriter; | 
|---|
|  |  |  | import java.math.BigDecimal; | 
|---|
|  |  |  | import java.nio.charset.StandardCharsets; | 
|---|
|  |  |  | import java.util.Map; | 
|---|
|  |  |  | import java.util.Objects; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | 
|---|
|  |  |  | String userId = tokenService.getLoginUserApplet().getUserId(); | 
|---|
|  |  |  | TSysAppUser sysAppUser = sysAppUserService.getById(userId); | 
|---|
|  |  |  | // 价格 | 
|---|
|  |  |  | Integer totalPrice = sysOtherConfig.getAiPrice().multiply(new BigDecimal(100)).intValue(); | 
|---|
|  |  |  | Long totalPrice = sysOtherConfig.getAiPrice().multiply(new BigDecimal(100)).longValue(); | 
|---|
|  |  |  | // 生成订单号 | 
|---|
|  |  |  | String orderNo = CodeGenerateUtils.generateOrderSn(); | 
|---|
|  |  |  | // 查询用户信息 用户openid | 
|---|
|  |  |  | 
|---|
|  |  |  | // 存储支付记录 | 
|---|
|  |  |  | sysPayRecordService.saveData(orderNo, userId, sysOtherConfig.getAiPrice(), 1); | 
|---|
|  |  |  | // 调用支付方法 | 
|---|
|  |  |  | Map<String, Object> result = wxV3Pay.jsApi(orderNo, totalPrice, openId,"AI检测报告支付"); | 
|---|
|  |  |  | Map<String, Object> result = wxV3Pay.jsApi(orderNo, totalPrice, openId,"AI检测报告支付",""); | 
|---|
|  |  |  | log.info("支付参数:{}", result); | 
|---|
|  |  |  | return R.ok(result); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 微信v3支付-订单退款 | 
|---|
|  |  |  | * | 
|---|
|  |  |  | * @return | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @ApiOperation("订单退款") | 
|---|
|  |  |  | @PostMapping(value = "refund-order") | 
|---|
|  |  |  | public AjaxResult<String> refundOrder() { | 
|---|
|  |  |  | Map<String, Object> result = wxV3Pay.refund(new WxPaymentRefundModel()); | 
|---|
|  |  |  | log.info("退款结果:{}", result); | 
|---|
|  |  |  | // 微信支付退款单号 | 
|---|
|  |  |  | String refund_id = result.get("refund_id").toString(); | 
|---|
|  |  |  | // 商户退款单号 | 
|---|
|  |  |  | String out_refund_no = result.get("out_refund_no").toString(); | 
|---|
|  |  |  | // 微信支付订单号 | 
|---|
|  |  |  | String transaction_id = result.get("transaction_id").toString(); | 
|---|
|  |  |  | // 商户订单号 tradeNo | 
|---|
|  |  |  | String out_trade_no = result.get("out_trade_no").toString(); | 
|---|
|  |  |  | // 退款成功时间 | 
|---|
|  |  |  | String success_time = Objects.nonNull(result.get("success_time")) ? result.get("success_time").toString() : null; | 
|---|
|  |  |  | // 退款状态 RefundEnum | 
|---|
|  |  |  | String status = result.get("status").toString(); | 
|---|
|  |  |  | // TODO 退款业务处理 | 
|---|
|  |  |  | return AjaxResult.success(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 支付回调 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @PostMapping("pay/notify") | 
|---|
|  |  |  | @ApiOperation("订单回调") | 
|---|
|  |  |  | public void payNotify(HttpServletRequest request) throws Exception { | 
|---|
|  |  |  | public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | Map<String, Object> params = wxV3Pay.verifyNotify(request, new TypeReference<Map<String, Object>>() {}); | 
|---|
|  |  |  | log.info("支付回调:{}", params); | 
|---|
|  |  |  | // 商户订单号 | 
|---|
|  |  |  | String tradeNo = params.get("out_trade_no").toString(); | 
|---|
|  |  |  | // 交易状态 | 
|---|
|  |  |  | String trade_state = params.get("trade_state").toString(); | 
|---|
|  |  |  | // 交易状态描述 | 
|---|
|  |  |  | String trade_state_desc = params.get("trade_state_desc").toString(); | 
|---|
|  |  |  | // 微信支付订单号 | 
|---|
|  |  |  | String transaction_id = params.get("transaction_id").toString(); | 
|---|
|  |  |  | // 支付完成时间 | 
|---|
|  |  |  | // 时间不对的话,可以调用  WxTimeUtils.toRfc3339Date(success_time)转换一下 | 
|---|
|  |  |  | String success_time = params.get("success_time").toString(); | 
|---|
|  |  |  | // 附加数据 | 
|---|
|  |  |  | Integer attach = Integer.parseInt(params.get("attach").toString()); | 
|---|
|  |  |  | System.err.println("微信回调"); | 
|---|
|  |  |  | BufferedReader reader = request.getReader(); | 
|---|
|  |  |  | StringBuilder requestBody = new StringBuilder(); | 
|---|
|  |  |  | String line; | 
|---|
|  |  |  | while ((line = reader.readLine()) != null) { | 
|---|
|  |  |  | requestBody.append(line); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | System.err.println("全部请求体" + requestBody); | 
|---|
|  |  |  | JSONObject jsonObject = JSONObject.parseObject(requestBody.toString()); | 
|---|
|  |  |  | JSONObject resource = jsonObject.getJSONObject("resource"); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | AesUtil aesUtil = new AesUtil(weixinPayProperties.getV3().getApiKey().getBytes(StandardCharsets.UTF_8)); | 
|---|
|  |  |  | String decryptedData = aesUtil.decryptToString(resource.getString("associated_data").getBytes(StandardCharsets.UTF_8), resource.getString("nonce").getBytes(StandardCharsets.UTF_8), | 
|---|
|  |  |  | resource.getString("ciphertext")); | 
|---|
|  |  |  | System.err.println("微信解密的字符串信息" + decryptedData); | 
|---|
|  |  |  | JSONObject jsonInfo = JSONObject.parse(decryptedData); | 
|---|
|  |  |  | String out_trade_no = jsonInfo.getString("out_trade_no"); | 
|---|
|  |  |  | String transaction_id = jsonInfo.getString("transaction_id"); | 
|---|
|  |  |  | String trade_state = jsonInfo.getString("trade_state"); | 
|---|
|  |  |  | String success_time = jsonInfo.getString("success_time"); | 
|---|
|  |  |  | // 查询订单 | 
|---|
|  |  |  | TSysPayRecord sysPayRecord = sysPayRecordService.getOne(Wrappers.lambdaQuery(TSysPayRecord.class) | 
|---|
|  |  |  | .eq(TSysPayRecord::getOrderNo, tradeNo).last("LIMIT 1")); | 
|---|
|  |  |  | // 处理订单 | 
|---|
|  |  |  | .eq(TSysPayRecord::getOrderNo, out_trade_no).last("LIMIT 1")); | 
|---|
|  |  |  | if (trade_state.equals(TradeStateEnum.SUCCESS.name())) { | 
|---|
|  |  |  | log.info("回调成功"); | 
|---|
|  |  |  | // 订单号查询订单 | 
|---|
|  |  |  | 
|---|
|  |  |  | sysInspection.setIsPay(1); | 
|---|
|  |  |  | sysInspectionService.updateById(sysInspection); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | wxV3Pay.ack(); | 
|---|
|  |  |  | PrintWriter out = response.getWriter(); | 
|---|
|  |  |  | out.print("SUCCESS"); | 
|---|
|  |  |  | out.flush(); | 
|---|
|  |  |  | out.close(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | wxV3Pay.ack(); | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | log.error("支付回调异常:{}", e, e); | 
|---|
|  |  |  | wxV3Pay.ack(false, e.getMessage()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 支付回调成功后 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @PostMapping("pay/ack") | 
|---|
|  |  |  | public void ack(){ | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | wxV3Pay.ack(); | 
|---|
|  |  |  | } catch (IOException e) { | 
|---|
|  |  |  | throw new RuntimeException(e); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * 退款回调 | 
|---|
|  |  |  | */ | 
|---|
|  |  |  | @PostMapping("refund/notify") | 
|---|
|  |  |  | public void refundNotify(HttpServletRequest request) throws IOException { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | Map<String, Object> params = wxV3Pay.verifyNotify(request, new TypeReference<Map<String, Object>>() { | 
|---|
|  |  |  | }); | 
|---|
|  |  |  | // 商户订单号 | 
|---|
|  |  |  | String out_trade_no = params.get("out_trade_no").toString(); | 
|---|
|  |  |  | // 商户退款单号 | 
|---|
|  |  |  | String out_refund_no = params.get("out_refund_no").toString(); | 
|---|
|  |  |  | // 微信支付订单号 | 
|---|
|  |  |  | String transaction_id = params.get("transaction_id").toString(); | 
|---|
|  |  |  | // 微信支付退款单号 | 
|---|
|  |  |  | String refund_id = params.get("refund_id").toString(); | 
|---|
|  |  |  | // 退款状态 | 
|---|
|  |  |  | String tradeState = params.get("refund_status").toString(); | 
|---|
|  |  |  | // 退款成功时间 | 
|---|
|  |  |  | // 时间不对的话,可以调用  WxTimeUtils.toRfc3339Date(success_time)转换一下 | 
|---|
|  |  |  | String success_time = params.get("success_time").toString(); | 
|---|
|  |  |  | if (tradeState.equals(RefundEnum.SUCCESS.name())) { | 
|---|
|  |  |  | wxV3Pay.ack(); | 
|---|
|  |  |  | } else { | 
|---|
|  |  |  | wxV3Pay.ack(false, "不是成功的退款状态"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (Exception e) { | 
|---|
|  |  |  | e.printStackTrace(); | 
|---|
|  |  |  | wxV3Pay.ack(false, e.getMessage()); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } | 
|---|