lsw 11 months ago
parent
commit
57c065cafe

+ 101 - 47
admin-ui/src/views/work/money/recharge/edit.vue

@@ -1,6 +1,19 @@
 <template>
   <div class="cmain">
-    <div class="bos">
+    <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
+      <el-tab-pane label="微信充值" name="微信充值"></el-tab-pane>
+      <el-tab-pane label="转账充值" name="转账充值"></el-tab-pane>
+    </el-tabs>
+    <div class="bos" v-if="activeName == '微信充值'">
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="充值金额" prop="money">
+          <el-input type="number" v-model="form.money" placeholder="请输入充值金额" clearable>
+            <template slot="append">元</template>
+          </el-input>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="bos" v-if="activeName == '转账充值'">
       <el-form ref="platform" disabled :model="platform" label-width="120px">
         <el-steps :active="1" align-center class="cg">
           <el-step title="充值信息"></el-step>
@@ -33,62 +46,103 @@
       <el-button type="primary" @click="submitForm">确 定</el-button>
       <el-button @click="$layer.close(layerid)">取 消</el-button>
     </div>
+    <!--扫码支付-->
+    <el-dialog title="扫码支付" :visible.sync="open" :width="'500px'" @close="close()" :close-on-click-modal="false" append-to-body>
+      <div class="pcontents">
+        <div id="qrcode"></div>
+        <div class="sm">请用微信扫码,完成支付</div>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-  export default {
-    data() {
-      return {
-        platform: {},
-        form: {},
-        rules: {
-          money: [{ required: true, message: '充值金额不能为空', trigger: 'blur' }],
-          certificate: [{ required: true, message: '充值凭证不能为空', trigger: 'blur' }]
-        }
-      };
-    },
-    props: {
-      param: {
-        type: Object,
-        default: () => {
-          return {};
-        }
-      },
-      layerid: {
-        type: String
+let timer = null;
+import QRCode from 'qrcodejs2';
+export default {
+  data() {
+    return {
+      activeName: '微信充值',
+      open: false,
+      platform: {},
+      form: {},
+      rules: {
+        money: [{ required: true, message: '充值金额不能为空', trigger: 'blur' }],
+        certificate: [{ required: true, message: '充值凭证不能为空', trigger: 'blur' }]
+      }
+    };
+  },
+  props: {
+    param: {
+      type: Object,
+      default: () => {
+        return {};
       }
     },
-    mounted() {
-      this.ajax({ url: '/work/platform/detail' }).then((response) => {
-        this.platform = response.data;
+    layerid: {
+      type: String
+    }
+  },
+  mounted() {
+    this.ajax({ url: '/work/platform/detail' }).then((response) => {
+      this.platform = response.data;
+    });
+    if (this.param.id) {
+      this.ajax({ url: '/work/recharge/detail/' + this.param.id }).then((response) => {
+        this.form = response.data;
       });
-      if (this.param.id) {
-        this.ajax({ url: '/work/recharge/detail/' + this.param.id }).then((response) => {
-          this.form = response.data;
+    }
+  },
+  methods: {
+    //取消支付
+    close() {
+      this.open = false;
+      clearInterval(timer);
+      this.$modal.msgError('取消支付');
+    },
+    //每3秒获取一次支付结果
+    refresh() {
+      timer = setInterval(() => {
+        this.ajax({ url: '/work/wxPay/payState', data: { ident: this.form.ident }, loading: 'false' }).then((response) => {
+          if (response.data) {
+            clearInterval(timer);
+            this.$modal.msgSuccess('充值成功');
+            this.$layer.close(this.layerid);
+          }
         });
-      }
+      }, 3000);
     },
-    methods: {
-      submitForm() {
-        this.$refs['form'].validate((valid) => {
-          if (valid) {
-            if (this.form.id) {
-              this.ajax({ method: 'post', url: '/work/recharge/edit', data: this.form }).then((response) => {
-                this.$modal.msgSuccess('修改成功');
-                this.$layer.close(this.layerid);
-                this.$parent.getList();
+    submitForm() {
+      this.$refs['form'].validate((valid) => {
+        if (valid) {
+          if (this.activeName == '微信充值') {
+            this.form.ident = Date.now().toString() + Math.floor(Math.random() * 1000).toString();
+            this.ajax({ method: 'post', url: '/work/wxPay/pay', data: this.form }).then((response) => {
+              this.open = true;
+              this.refresh();
+              this.$nextTick(() => {
+                //生成二维码
+                document.getElementById('qrcode').innerHTML = '';
+                new QRCode('qrcode', {
+                  width: 250,
+                  height: 250,
+                  text: JSON.parse(response.data).code_url
+                });
               });
-            } else {
-              this.ajax({ method: 'post', url: '/work/recharge/add', data: this.form }).then((response) => {
-                this.$modal.msgSuccess('提交成功');
-                this.$layer.close(this.layerid);
-                this.$parent.getList();
-              });
-            }
+            });
+          } else {
+            this.ajax({ method: 'post', url: '/work/recharge/add', data: this.form }).then((response) => {
+              this.$modal.msgSuccess('提交成功');
+              this.$layer.close(this.layerid);
+              this.$parent.getList();
+            });
           }
-        });
-      }
+        }
+      });
     }
-  };
+  },
+  destroyed() {
+    clearInterval(timer);
+  }
+};
 </script>

+ 3 - 3
app/common/http.js

@@ -1,6 +1,6 @@
-//const ip = 'http://127.0.0.1:9191';
-const ip = 'https://chenglantimes.com/prod-api';
-//const ip = 'http://192.168.0.102:9191';
+const ip = 'http://127.0.0.1:9191';
+//const ip = 'https://chenglantimes.com/prod-api';
+//const ip = 'http://192.168.0.104:9191';
 /**
  * 封装的http请求
  */

+ 6 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/Recharge.java

@@ -54,9 +54,15 @@ public class Recharge extends BaseData {
     @Excel(name = "充值状态", readConverterExp = "0=待充值,1=充值成功,2=充值失败", sort = 3)
     private Integer state;
 
+    @ApiModelProperty(value = "充值渠道")
+    private Integer type;
+
     @ApiModelProperty(value = "充值无效原因")
     private String msg;
 
+    @ApiModelProperty(value = "通知标识")
+    private String ident;
+
     @Excel(name = "申请人", sort = 4)
     private String opBy;
 

+ 19 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/CompanyPayDto.java

@@ -0,0 +1,19 @@
+package com.ruoyi.web.work.domain.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.Digits;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+@Data
+public class CompanyPayDto {
+
+    @NotNull(message = "充值金额不能为空")
+    @Digits(integer = 10, fraction = 2, message = "充值金额只能包含最多两位小数")
+    private BigDecimal money;
+
+    @NotBlank(message = "参数不能为空")
+    private String ident;
+}

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/PayDto.java

@@ -9,7 +9,7 @@ import java.math.BigDecimal;
 @Data
 public class PayDto {
 
-    @NotNull(message = "捐赠金额不能为空")
-    @Digits(integer = 10, fraction = 2, message = "金额只能包含最多两位小数")
+    @NotNull(message = "充值金额不能为空")
+    @Digits(integer = 10, fraction = 2, message = "充值金额只能包含最多两位小数")
     private BigDecimal money;
 }

+ 15 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/domain/dto/PayStateDto.java

@@ -0,0 +1,15 @@
+package com.ruoyi.web.work.domain.dto;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+@Accessors(chain = true)
+public class PayStateDto {
+
+    @NotBlank(message = "参数不能为空")
+    private String ident;
+
+}

+ 8 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/work/mapper/RechargeMapper.java

@@ -1,8 +1,10 @@
 package com.ruoyi.web.work.mapper;
 
-import java.util.List;
-import com.ruoyi.web.work.domain.Recharge;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.web.work.domain.Recharge;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * @author lsw
@@ -10,4 +12,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface RechargeMapper extends BaseMapper<Recharge> {
     List<Recharge> selectList(Recharge recharge);
+
+    Recharge selectByNums(@Param("nums") String nums);
+
+    Recharge selectByIdent(@Param("ident") String ident);
 }

+ 4 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/service/IRechargeService.java

@@ -18,4 +18,8 @@ public interface IRechargeService extends IService<Recharge>{
     AjaxResult add(Recharge recharge);
 
     AjaxResult edit(RechargeDto dto) throws ServerException;
+
+    Recharge selectByNums(String nums);
+
+    Recharge selectByIdent(String ident);
 }

+ 14 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/work/service/impl/RechargeServiceImpl.java

@@ -47,10 +47,10 @@ public class RechargeServiceImpl extends ServiceImpl<RechargeMapper, Recharge> i
         recharge.setNums(StringUtils.generateNumber());
         recharge.setState(0);
         recharge.setVersion(System.currentTimeMillis());
-        if (save(recharge)) {
-            return AjaxResult.success();
+        if (!save(recharge)) {
+            return AjaxResult.error("充值失败,请联系平台");
         }
-        return AjaxResult.error("提交申请失败,请联系平台");
+        return AjaxResult.success();
 
     }
 
@@ -79,7 +79,7 @@ public class RechargeServiceImpl extends ServiceImpl<RechargeMapper, Recharge> i
             if (!companyService.updateById(company)) {
                 throw new ServerException("更新企业余额失败,请联系管理员");
             }
-            Record record=new Record();
+            Record record = new Record();
             record.setType(0);
             record.setCompanyId(recharge.getCompanyId());
             record.setOpId(recharge.getId());
@@ -90,4 +90,14 @@ public class RechargeServiceImpl extends ServiceImpl<RechargeMapper, Recharge> i
         }
         return AjaxResult.success();
     }
+
+    @Override
+    public Recharge selectByNums(String nums) {
+        return rechargeMapper.selectByNums(nums);
+    }
+
+    @Override
+    public Recharge selectByIdent(String ident) {
+        return rechargeMapper.selectByIdent(ident);
+    }
 }

+ 164 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/work/wxpay/CompanyPayController.java

@@ -0,0 +1,164 @@
+package com.ruoyi.web.work.wxpay;
+
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.ContentType;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.ijpay.core.IJPayHttpResponse;
+import com.ijpay.core.enums.AuthTypeEnum;
+import com.ijpay.core.enums.RequestMethodEnum;
+import com.ijpay.core.kit.HttpKit;
+import com.ijpay.core.kit.PayKit;
+import com.ijpay.core.kit.WxPayKit;
+import com.ijpay.core.utils.DateTimeZoneUtil;
+import com.ijpay.wxpay.WxPayApi;
+import com.ijpay.wxpay.enums.WxDomainEnum;
+import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
+import com.ijpay.wxpay.model.v3.Amount;
+import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.web.work.domain.Company;
+import com.ruoyi.web.work.domain.Recharge;
+import com.ruoyi.web.work.domain.dto.CompanyPayDto;
+import com.ruoyi.web.work.domain.dto.PayStateDto;
+import com.ruoyi.web.work.service.ICompanyService;
+import com.ruoyi.web.work.service.IRechargeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/work/wxPay")
+public class CompanyPayController extends BaseController {
+    @Resource
+    WxPayBean wxPayV3Bean;
+
+    private String serialNo;
+
+    @Autowired
+    private IRechargeService rechargeService;
+
+    @Autowired
+    private ICompanyService companyService;
+
+    @PreAuthorize("@ss.hasPermi('work:recharge:add')")
+    @Log(title = "微信充值", businessType = BusinessType.PAY)
+    @PostMapping("/pay")
+    public AjaxResult pay(@Validated @RequestBody CompanyPayDto dto) {
+        try {
+            String orderNum = PayKit.generateStr();
+            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel();
+            unifiedOrderModel.setAppid(wxPayV3Bean.getAppId());
+            unifiedOrderModel.setMchid(wxPayV3Bean.getMchId());
+            unifiedOrderModel.setDescription("企业账户充值");
+            unifiedOrderModel.setOut_trade_no(orderNum);
+            unifiedOrderModel.setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3));
+            unifiedOrderModel.setAttach("企业账户充值");
+            unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/work/wxPay/notify"));
+            unifiedOrderModel.setAmount(new Amount().setTotal(dto.getMoney().multiply(new BigDecimal(100)).intValue()));
+            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.NATIVE_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel), AuthTypeEnum.RSA.getCode());
+            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
+            if (response.getStatus() == 200 && verifySignature) {
+                //保存订单信息
+                Recharge recharge = new Recharge();
+                recharge.setCompanyId(SecurityUtils.getLoginUser().getUser().getCompanyId());
+                recharge.setState(0);
+                recharge.setType(1);
+                recharge.setIdent(dto.getIdent());
+                recharge.setNums(orderNum);
+                recharge.setMoney(dto.getMoney());
+                recharge.setVersion(System.currentTimeMillis());
+                recharge.setOpBy(SecurityUtils.getLoginUser().getUser().getNickName());
+                recharge.setUserId(SecurityUtils.getLoginUser().getUser().getUserId());
+                if (!rechargeService.save(recharge)) {
+                    return AjaxResult.error("充值失败,请联系平台或者转账充值");
+                }
+                return AjaxResult.success(response.getBody());
+            }
+            return AjaxResult.error("支付异常,请联系平台或者转账充值");
+        } catch (Exception e) {
+            throw new ServiceException(e.getMessage());
+        }
+    }
+
+    @PreAuthorize("@ss.hasPermi('work:recharge:add')")
+    @GetMapping("/payState")
+    public AjaxResult payState(@Validated PayStateDto dto) {
+        return AjaxResult.success(rechargeService.selectByIdent(dto.getIdent()) == null ? false : true);
+    }
+
+    @PostMapping(value = "/notify")
+    @Transactional(rollbackFor = Exception.class)
+    public void notify(HttpServletRequest request, HttpServletResponse response) {
+        Map<String, String> map = new HashMap<>(12);
+        try {
+            String timestamp = request.getHeader("Wechatpay-Timestamp");
+            String nonce = request.getHeader("Wechatpay-Nonce");
+            String serialNo = request.getHeader("Wechatpay-Serial");
+            String signature = request.getHeader("Wechatpay-Signature");
+            String result = HttpKit.readData(request);
+            // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
+            JSONObject res = JSONObject.parseObject(WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()));
+            System.out.println("支付通知明文:" + res.toJSONString());
+            if (res != null && res.getString("trade_state").equals("SUCCESS")) {
+                //业务处理,更新订单信息
+                Recharge recharge = rechargeService.selectByNums(res.getString("out_trade_no"));
+                if (recharge != null && recharge.getState() == 0) {
+                    recharge.setState(1);
+                    Company company = companyService.getById(recharge.getCompanyId());
+                    company.setId(0l);
+                    company.setMoney(company.getMoney().add(recharge.getMoney()));
+                    if (!rechargeService.updateById(recharge)) {
+                        throw new ServiceException("更新充值订单失败");
+                    }
+                    if (!companyService.updateById(company)) {
+                        throw new ServiceException("更新企业账户金额失败");
+                    }
+                    response.setStatus(200);
+                    map.put("code", "SUCCESS");
+                    map.put("message", "SUCCESS");
+                }
+            } else {
+                response.setStatus(500);
+                map.put("code", "ERROR");
+                map.put("message", "签名错误");
+            }
+            response.setHeader("Content-type", ContentType.JSON.toString());
+            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
+            response.flushBuffer();
+        } catch (Exception e) {
+            throw new ServiceException(e.getMessage());
+        }
+    }
+
+    /**
+     * 获取证书序列号
+     *
+     * @return
+     */
+    private String getSerialNumber() {
+        if (StrUtil.isEmpty(serialNo)) {
+            X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath());
+            if (certificate != null) {
+                serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
+            }
+        }
+        return serialNo;
+    }
+}

+ 82 - 102
ruoyi-admin/src/main/java/com/ruoyi/web/work/wxpay/WxPayController.java

@@ -2,13 +2,11 @@ package com.ruoyi.web.work.wxpay;
 
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.http.ContentType;
-import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson2.JSONObject;
 import com.ijpay.core.IJPayHttpResponse;
 import com.ijpay.core.enums.AuthTypeEnum;
 import com.ijpay.core.enums.RequestMethodEnum;
-import com.ijpay.core.kit.AesUtil;
 import com.ijpay.core.kit.HttpKit;
 import com.ijpay.core.kit.PayKit;
 import com.ijpay.core.kit.WxPayKit;
@@ -16,21 +14,25 @@ import com.ijpay.core.utils.DateTimeZoneUtil;
 import com.ijpay.wxpay.WxPayApi;
 import com.ijpay.wxpay.enums.WxDomainEnum;
 import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
-import com.ijpay.wxpay.enums.v3.CertAlgorithmTypeEnum;
 import com.ijpay.wxpay.model.v3.Amount;
 import com.ijpay.wxpay.model.v3.Payer;
 import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
 import com.ruoyi.common.annotation.Log;
-import com.ruoyi.common.config.RuoYiConfig;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.web.work.api.config.BaseController;
+import com.ruoyi.web.work.domain.Company;
 import com.ruoyi.web.work.domain.Pay;
+import com.ruoyi.web.work.domain.Recharge;
 import com.ruoyi.web.work.domain.User;
+import com.ruoyi.web.work.domain.dto.CompanyPayDto;
 import com.ruoyi.web.work.domain.dto.PayDto;
+import com.ruoyi.web.work.domain.dto.PayStateDto;
 import com.ruoyi.web.work.service.ICompanyService;
 import com.ruoyi.web.work.service.IPayService;
+import com.ruoyi.web.work.service.IRechargeService;
 import com.ruoyi.web.work.service.IUserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -40,14 +42,10 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileWriter;
 import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.security.cert.X509Certificate;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 @RestController
@@ -62,115 +60,63 @@ public class WxPayController extends BaseController {
     private IUserService userService;
 
     @Autowired
-    private ICompanyService companyService;
+    private IRechargeService rechargeService;
 
     @Autowired
     private IPayService payService;
 
+    @Autowired
+    private ICompanyService companyService;
+
     /**
      * PC扫码支付
      *
      * @param dto
      * @return
      */
-    @Log(title = "在线扫码支付", businessType = BusinessType.PAY)
-    @PostMapping("/pay")
+    @Log(title = "微信充值", businessType = BusinessType.PAY)
+    @PostMapping("/companyPay")
     @Transactional(rollbackFor = Exception.class)
-    public AjaxResult pay(@Validated @RequestBody PayDto dto) {
+    public AjaxResult companyPay(@Validated @RequestBody CompanyPayDto dto) {
         try {
             String orderNum = PayKit.generateStr();
             UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel();
             unifiedOrderModel.setAppid(wxPayV3Bean.getAppId());
             unifiedOrderModel.setMchid(wxPayV3Bean.getMchId());
-            unifiedOrderModel.setDescription("测试支付");
+            unifiedOrderModel.setDescription("企业账户充值");
             unifiedOrderModel.setOut_trade_no(orderNum);
             unifiedOrderModel.setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3));
-            unifiedOrderModel.setAttach("爱心捐款");
-            unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/payNotify"));
-            unifiedOrderModel.setAmount(new Amount().setTotal(1));
+            unifiedOrderModel.setAttach("企业账户充值");
+            unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/companyNotify"));
+            unifiedOrderModel.setAmount(new Amount().setTotal(dto.getMoney().multiply(new BigDecimal(100)).intValue()));
             IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.NATIVE_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel), AuthTypeEnum.RSA.getCode());
             boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
             if (response.getStatus() == 200 && verifySignature) {
                 //保存订单信息
-               /* Donate donate = new Donate();
-                BeanUtils.copyProperties(dto, donate);
-                donate.setState(0);
-                donate.setOrderNum(orderNum);
-                donateService.save(donate);*/
-                return AjaxResult.success("成功", response.getBody());
+                Recharge recharge = new Recharge();
+                recharge.setCompanyId(SecurityUtils.getLoginUser().getUser().getCompanyId());
+                recharge.setState(0);
+                recharge.setType(1);
+                recharge.setIdent(dto.getIdent());
+                recharge.setNums(orderNum);
+                recharge.setMoney(dto.getMoney());
+                recharge.setVersion(System.currentTimeMillis());
+                recharge.setOpBy(SecurityUtils.getLoginUser().getUser().getNickName());
+                recharge.setUserId(SecurityUtils.getLoginUser().getUser().getUserId());
+                if (!rechargeService.save(recharge)) {
+                    return AjaxResult.error("充值失败,请联系平台或者转账充值");
+                }
+                return AjaxResult.success(response.getBody());
             }
-            return AjaxResult.error("系统异常");
+            return AjaxResult.error("支付异常,请联系平台或者转账充值");
         } catch (Exception e) {
-            throw new ServiceException("系统异常");
+            throw new ServiceException(e.getMessage());
         }
     }
-
-    @GetMapping("/get")
-    public AjaxResult v3Get() {
-        // 获取平台证书列表
-        try {
-            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), CertAlgorithmTypeEnum.getCertSuffixUrl(CertAlgorithmTypeEnum.RSA.getCode()), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), "", AuthTypeEnum.RSA.getCode());
-            Map<String, List<String>> headers = response.getHeaders();
-            String timestamp = response.getHeader("Wechatpay-Timestamp");
-            String nonceStr = response.getHeader("Wechatpay-Nonce");
-            String serialNumber = response.getHeader("Wechatpay-Serial");
-            String signature = response.getHeader("Wechatpay-Signature");
-
-            String body = response.getBody();
-            int status = response.getStatus();
-
-            int isOk = 200;
-            if (status == isOk) {
-                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
-                JSONArray dataArray = jsonObject.getJSONArray("data");
-                // 默认认为只有一个平台证书
-                cn.hutool.json.JSONObject encryptObject = dataArray.getJSONObject(0);
-                cn.hutool.json.JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
-                String associatedData = encryptCertificate.getStr("associated_data");
-                String cipherText = encryptCertificate.getStr("ciphertext");
-                String nonce = encryptCertificate.getStr("nonce");
-                String algorithm = encryptCertificate.getStr("algorithm");
-                String serialNo = encryptObject.getStr("serial_no");
-                final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, algorithm, new File(RuoYiConfig.getUploadPath() + "/platformCert.pem").toString());
-                // 根据证书序列号查询对应的证书来验证签名结果
-                boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
-                System.out.println("verifySignature:"+verifySignature);
-            }
-            return AjaxResult.success(body);
-        } catch (Exception e) {
-            System.out.println("asd:" + e.getMessage());
-            e.printStackTrace();
-            return AjaxResult.error();
-        }
+    @GetMapping("/payState")
+    public AjaxResult payState(@Validated PayStateDto dto) {
+        return AjaxResult.success(rechargeService.selectByIdent(dto.getIdent()) == null ? false : true);
     }
-
-    private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) {
-        try {
-            String key3 = wxPayV3Bean.getApiKey3();
-            String publicKey;
-            if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
-                publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData);
-            } else {
-                AesUtil aesUtil = new AesUtil(wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8));
-                // 平台证书密文解密
-                // encrypt_certificate 中的  associated_data nonce  ciphertext
-                publicKey = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), cipherText);
-            }
-            if (StrUtil.isNotEmpty(publicKey)) {
-                System.out.println("publicKey:" + publicKey);
-                // 保存证书
-                FileWriter writer = new FileWriter(certPath);
-                writer.write(publicKey);
-                // 获取平台证书序列号
-                X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
-                return certificate.getSerialNumber().toString(16).toUpperCase();
-            }
-            return "";
-        } catch (Exception e) {
-            return e.getMessage();
-        }
-    }
-
     /**
      * @param dto
      * @return
@@ -189,11 +135,9 @@ public class WxPayController extends BaseController {
             unifiedOrderModel.setAmount(new Amount().setTotal(dto.getMoney().multiply(new BigDecimal(100)).intValue()));
             unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/payNotify"));
             unifiedOrderModel.setPayer(new Payer().setOpenid(getUser().getOpenId()));
-            System.out.println("asd:" + getSerialNumber());
             IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.JS_API_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel));
             System.out.println("统一下单响应:" + response);
             boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
-            System.out.println("verifySignature:" + verifySignature);
             if (response.getStatus() == 200 && verifySignature) {
                 String body = response.getBody();
                 JSONObject jsonObject = JSONObject.parseObject(body);
@@ -212,7 +156,6 @@ public class WxPayController extends BaseController {
             }
             return AjaxResult.error("支付异常,请联系平台");
         } catch (Exception e) {
-            e.printStackTrace();
             throw new ServiceException(e.getMessage());
         }
     }
@@ -227,12 +170,6 @@ public class WxPayController extends BaseController {
             String serialNo = request.getHeader("Wechatpay-Serial");
             String signature = request.getHeader("Wechatpay-Signature");
             String result = HttpKit.readData(request);
-            System.out.println("timestamp:" + timestamp);
-            System.out.println("nonce:" + nonce);
-            System.out.println("serialNo:" + serialNo);
-            System.out.println("serialNo2:" + getSerialNumber());
-            System.out.println("signature:" + signature);
-            //serialNo=getSerialNumber();
             // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
             JSONObject res = JSONObject.parseObject(WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()));
             System.out.println("支付通知明文:" + res.toJSONString());
@@ -251,6 +188,51 @@ public class WxPayController extends BaseController {
                         response.setStatus(500);
                         map.put("code", "ERROR");
                         map.put("message", "支付失败");
+
+                    }
+                }
+            } else {
+                response.setStatus(500);
+                map.put("code", "ERROR");
+                map.put("message", "签名错误");
+            }
+            response.setHeader("Content-type", ContentType.JSON.toString());
+            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
+            response.flushBuffer();
+        } catch (Exception e) {
+            throw new ServiceException(e.getMessage());
+        }
+    }
+
+    @Transactional
+    @PostMapping(value = "/companyNotify")
+    public void companyNotify(HttpServletRequest request, HttpServletResponse response) {
+        Map<String, String> map = new HashMap<>(12);
+        try {
+            String timestamp = request.getHeader("Wechatpay-Timestamp");
+            String nonce = request.getHeader("Wechatpay-Nonce");
+            String serialNo = request.getHeader("Wechatpay-Serial");
+            String signature = request.getHeader("Wechatpay-Signature");
+            String result = HttpKit.readData(request);
+            // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
+            JSONObject res = JSONObject.parseObject(WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()));
+            System.out.println("支付通知明文:" + res.toJSONString());
+            if (res != null && res.getString("trade_state").equals("SUCCESS")) {
+                //业务处理,更新订单信息
+                Recharge recharge = rechargeService.selectByNums(res.getString("out_trade_no"));
+                if (recharge != null && recharge.getState() == 0) {
+                    recharge.setState(1);
+                    Company company = companyService.getById(recharge.getCompanyId());
+                    company.setMoney(company.getMoney().add(recharge.getMoney()));
+                    if (rechargeService.updateById(recharge) && companyService.updateById(company)) {
+                        response.setStatus(200);
+                        map.put("code", "SUCCESS");
+                        map.put("message", "SUCCESS");
+                    } else {
+                        response.setStatus(500);
+                        map.put("code", "ERROR");
+                        map.put("message", "支付失败");
+
                     }
                 }
             } else {
@@ -262,9 +244,7 @@ public class WxPayController extends BaseController {
             response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
             response.flushBuffer();
         } catch (Exception e) {
-            e.printStackTrace();
-            System.out.println("msg:" + e.getMessage());
-            throw new ServiceException("系统异常");
+            throw new ServiceException(e.getMessage());
         }
     }
 

+ 8 - 0
ruoyi-admin/src/main/resources/mapper/work/RechargeMapper.xml

@@ -20,4 +20,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </where>
     </select>
 
+    <select id="selectByNums" resultType="com.ruoyi.web.work.domain.Recharge">
+        SELECT * FROM tb_recharge WHERE nums=#{nums}
+    </select>
+
+    <select id="selectByIdent" resultType="com.ruoyi.web.work.domain.Recharge">
+        SELECT * FROM tb_recharge WHERE ident=#{ident}
+    </select>
+
 </mapper>

+ 1 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -110,6 +110,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 .authorizeRequests()
                 // 对于登录login 注册register 验证码captchaImage 允许匿名访问
                 .antMatchers("/login", "/register", "/captchaImage").anonymous()
+                .antMatchers("/work/wxPay/notify").permitAll()
                 .antMatchers("/app/**").permitAll()
                 // 静态资源,可匿名访问
                 .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()