Bladeren bron

feature: 微信充值
1.自助机二维码充值

luoyb 1 jaar geleden
bovenliggende
commit
a0802dde41

+ 105 - 9
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/payments/ThirdPayBusiness.java

@@ -1,6 +1,7 @@
 package org.dromara.backstage.business.payments;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
@@ -13,14 +14,14 @@ import org.dromara.backstage.config.ThirdPayConfig;
 import org.dromara.backstage.payment.domain.bo.PayOrderBo;
 import org.dromara.backstage.payment.domain.bo.PurseInOutBo;
 import org.dromara.backstage.payment.domain.vo.PayOrderVo;
+import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.backstage.payment.service.IPayOrderService;
+import org.dromara.backstage.payment.service.IPtUserAccountService;
 import org.dromara.common.core.domain.R;
-import org.dromara.common.core.enums.BalanceUpdateEnum;
-import org.dromara.common.core.enums.CreditStatusEnum;
-import org.dromara.common.core.enums.CreditTypeEnum;
-import org.dromara.common.core.enums.PayStatusEnum;
+import org.dromara.common.core.enums.*;
 import org.springframework.stereotype.Service;
 
+import java.math.BigDecimal;
 import java.text.MessageFormat;
 import java.util.HashMap;
 import java.util.Map;
@@ -42,14 +43,21 @@ public class ThirdPayBusiness {
     private final IPayOrderService payOrderService;
     private final PayOrderBusiness payOrderBusiness;
     private final ThirdPayConfig thirdPayConfig;
+    private final IPtUserAccountService userAccountService;
 
     /**
-     * 生成充值收款二维码
-     *
-     * @param bo 充值订单
-     * @return 二维码信息
+     * 创建二维码支付的收款码
+     * @param mapParams 三维码参数
+     * @return 二维信息
      */
-    public R<Map<String, String>> createCollectQrCode(PayOrderBo bo) throws Exception {
+    public R<Map<String, String>> createCollectQrCode(Map<String, String> mapParams) {
+        Long userId = Long.valueOf(mapParams.get("userId"));
+        BigDecimal dealValue =  new BigDecimal(mapParams.get("dealValue"));
+        R<PayOrderBo> resultBo = createPayOrderBo(userId, dealValue);
+        if (R.isError(resultBo)) {
+            return R.fail(resultBo.getMsg());
+        }
+        PayOrderBo bo = resultBo.getData();
         R<PayOrderVo> result = createThirdPayOrder(bo);
         if (R.isError(result)) {
             return R.fail(result.getMsg());
@@ -61,6 +69,26 @@ public class ThirdPayBusiness {
         return createWechatQrCode(result.getData());
     }
 
+    public R<String> createDirectPayment(Map<String, String> mapParams){
+        Long userId = Long.valueOf(mapParams.get("userId"));
+        BigDecimal dealValue =  new BigDecimal(mapParams.get("dealValue"));
+        R<PayOrderBo> resultBo = createPayOrderBo(userId, dealValue);
+        if (R.isError(resultBo)) {
+            return R.fail(resultBo.getMsg());
+        }
+        PayOrderBo bo = resultBo.getData();
+        R<PayOrderVo> result = createThirdPayOrder(bo);
+        if (R.isError(result)) {
+            return R.fail(result.getMsg());
+        }
+        PayOrderVo vo = result.getData();
+        String orderSn = result.getData().getOrderId().toString();
+        String callBackUrl = result.getData().getBackUrl() + orderSn;
+        bo.setBackUrl(callBackUrl);
+
+        //请求支付
+        return requestForPpayment(vo, mapParams);
+    }
     /**
      * 第三方支付回调处理
      * 1.更新订单的支付状态
@@ -116,6 +144,43 @@ public class ThirdPayBusiness {
         return R.fail(MessageFormat.format("[{0}]-[订单创建失败]", CreditTypeEnum.getMessage(bo.getCreditType())));
     }
 
+    public R<PayOrderVo> createThirdPayOrder(Map<String, String> mapParams) {
+        Long userId = Long.valueOf(mapParams.get("userId"));
+        BigDecimal dealValue =  new BigDecimal(mapParams.get("dealValue"));
+        R<PayOrderBo> result = createPayOrderBo(userId, dealValue);
+
+        if (R.isError(result)) {
+            return R.fail(result.getMsg());
+        }
+        PayOrderBo bo = result.getData();
+        return createThirdPayOrder(bo);
+    }
+
+    public R<PayOrderBo> createPayOrderBo(Long userId, BigDecimal dealValue) {
+        PtUserAccountVo userAccountVo = userAccountService.queryById(userId);
+        if (ObjectUtil.isEmpty(userAccountVo)) {
+            return R.fail(String.format("[无此充值账户信息]-[userId:%s]", userId));
+        }
+        String callBackUrl = thirdPayConfig.getRechargeBackUrl() + "/result/";
+        PayOrderBo payOrderBo = new PayOrderBo();
+        payOrderBo.setCreditTime(DateUtil.date());
+        payOrderBo.setCreditType(CreditTypeEnum.WECHAT_RECHARGE.code().toString());
+        payOrderBo.setPayStyle(PayStyleEnum.WECHAT.code().toString());
+        payOrderBo.setPayStatus(PayStatusEnum.UNPAID.code().toString());
+        payOrderBo.setReceiptMoney(dealValue);
+        payOrderBo.setCreditStatus(CreditStatusEnum.CREATE.code().toString());
+        payOrderBo.setTitle(CreditTypeEnum.WECHAT_RECHARGE.message());
+        payOrderBo.setBackUrl(callBackUrl);
+        payOrderBo.setUserId(userAccountVo.getUserId());
+        payOrderBo.setPhone(userAccountVo.getPhone());
+        payOrderBo.setDeptName(userAccountVo.getDeptName());
+        payOrderBo.setDeptId(userAccountVo.getDeptId());
+        payOrderBo.setCreateBy(userAccountVo.getUserId());
+        payOrderBo.setCreateTime(DateUtil.date());
+
+        return R.ok(payOrderBo);
+    }
+
     /**
      * 第三方支付订单入账
      *
@@ -210,6 +275,37 @@ public class ThirdPayBusiness {
         }
     }
 
+    public R<String> requestForPpayment(PayOrderVo vo,Map<String, String> mapParams){
+        String sendUrl = thirdPayConfig.getPayApi() + "toPay";
+        vo.setBackUrl(thirdPayConfig.getRechargeBackUrl() + vo.getOrderId());
+        HttpRequest req = HttpUtil.createPost(sendUrl);
+        PayOrderBo bo = new PayOrderBo();
+        bo.setOrderId(vo.getOrderId());
+        bo.setReceiptMoney(vo.getReceiptMoney());
+        bo.setTitle(CreditTypeEnum.getMessage(Integer.parseInt(vo.getCreditType())));
+        bo.setBackUrl(vo.getBackUrl());
+        bo.setSsoId(mapParams.get("ssoId"));
+        bo.setUserAgent(mapParams.get("userAgent"));
+
+        req.body(JSONUtil.toJsonStr(bo));
+        try (HttpResponse res = req.execute()) {
+            JSONObject object = JSONUtil.parseObj(res.body());
+            //String resCode = object.getStr("code");
+            //String resData = object.getStr("data");
+            //if (ObjectUtil.equals(resCode, "200")) {
+            //    Map<String, String> map = new HashMap<>();
+            //    map.put("orderSn", vo.getOrderId().toString());
+            //    map.put("qrCode", resData);
+            //
+            //    return R.ok();
+            //}
+            //return R.fail(String.format("[生成微信收款码错误]-[%s]", object));
+            return R.ok();
+        } catch (Exception e) {
+            log.error("[微信支付错误]-[{0}]", e);
+            return R.fail("[微信支付错误]");
+        }
+    }
     public R<Void> queryOrderPayResult(String orderSn) {
         PayOrderVo vo = payOrderService.queryById(Long.valueOf(orderSn));
         if (ObjectUtil.isEmpty(vo)) {

+ 53 - 69
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/business/self/SelfBusiness.java

@@ -1,7 +1,5 @@
 package org.dromara.backstage.business.self;
 
-import cn.hutool.core.date.DateUtil;
-
 import cn.hutool.core.codec.Base64;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.ObjectUtil;
@@ -22,7 +20,9 @@ import org.dromara.backstage.payment.service.IPayOrderService;
 import org.dromara.backstage.task.AsyncTaskService;
 import org.dromara.common.core.api.ReturnResult;
 import org.dromara.common.core.domain.R;
-import org.dromara.common.core.enums.*;
+import org.dromara.common.core.enums.CreditStatusEnum;
+import org.dromara.common.core.enums.CreditTypeEnum;
+import org.dromara.common.core.enums.ResultCodeEnum;
 import org.dromara.common.core.exception.ApiException;
 import org.dromara.common.redis.utils.RedisUtils;
 import org.springframework.beans.factory.annotation.Value;
@@ -77,14 +77,14 @@ public class SelfBusiness {
 
         String loginUrl = smsApi + "sms/api/v1/login";
         HttpRequest req = HttpUtil.createPost(loginUrl);
-        try(HttpResponse res = req.body(JSONUtil.toJsonStr(mapAccount)).execute()) {
+        try (HttpResponse res = req.body(JSONUtil.toJsonStr(mapAccount)).execute()) {
             ReturnResult result = JSONUtil.toBean(res.body(), ReturnResult.class);
             log.info("[短信平台登录]-{}", JSONUtil.toJsonStr(result));
-            if(result.isSuccess()){
+            if (result.isSuccess()) {
                 RedisUtils.deleteObject("yktSmsToken");
                 RedisUtils.setCacheObject("yktSmsToken", result.getData().toString(), Duration.ofHours(24));
             }
-        } catch (Exception e){
+        } catch (Exception e) {
             log.error("登录短信平台失败,{}", e.getMessage());
         }
 
@@ -92,11 +92,12 @@ public class SelfBusiness {
 
     /**
      * 发送短信
-      * @param phone 电话号码
+     *
+     * @param phone   电话号码
      * @param message 发送内容
      */
     public void sendSms(String phone, String message) {
-        if(!RedisUtils.hasKey("yktSmsToken")){
+        if (!RedisUtils.hasKey("yktSmsToken")) {
             loginSms();
         }
         asyncTaskService.asyncSendSms(phone, message);
@@ -104,92 +105,73 @@ public class SelfBusiness {
 
     /**
      * 发送有房间信息的入住信息
-     * @param phone 电话
-     * @param realName 姓名
+     *
+     * @param phone     电话
+     * @param realName  姓名
      * @param className 班级名
-     * @param roomCode 房间号
+     * @param roomCode  房间号
      */
-    public void sendSmsHasRoom(String phone,String realName,String className,String roomCode){
-        sendSms(phone, String.format(messageHasRoom.replace("rn", "\r\n"), realName, className,roomCode));
+    public void sendSmsHasRoom(String phone, String realName, String className, String roomCode) {
+        sendSms(phone, String.format(messageHasRoom.replace("rn", "\r\n"), realName, className, roomCode));
     }
 
     /**
      * 发送没有房间的入住信息
-     * @param phone 电话
-     * @param realName 姓名
+     *
+     * @param phone     电话
+     * @param realName  姓名
      * @param className 班级名
      */
-    public void sendSmsNoRoom(String phone,String realName,String className){
+    public void sendSmsNoRoom(String phone, String realName, String className) {
         sendSms(phone, String.format(messageNoRoom.replace("rn", "\r\n"), realName, className));
     }
+
     public R<Map<String, String>> getWechatRechargeQrCode(Map<String, String> mapParams) throws Exception {
-        int workStationNumb = Integer.parseInt(mapParams.get("workStationNumb"));
-        String userId = mapParams.get("userId");
-        String userXm = mapParams.get("userXm");
-        String deptName = mapParams.get("deptName");
-        String deptId = mapParams.get("deptId");
-        String mobile = mapParams.get("mobile");
-        BigDecimal dealValue = new BigDecimal(mapParams.get("dealValue"));
-
-        String callBackUrl = rechargeBackUrl + "/result/";
-        PayOrderBo payOrderBo = new PayOrderBo();
-        payOrderBo.setCreditTime(DateUtil.date());
-        payOrderBo.setCreditType(CreditTypeEnum.WECHAT_RECHARGE.code().toString());
-        payOrderBo.setPayStyle(PayStyleEnum.WECHAT.code().toString());
-        payOrderBo.setPayStatus(PayStatusEnum.UNPAID.code().toString());
-        payOrderBo.setReceiptMoney(dealValue);
-        payOrderBo.setCreditStatus(CreditStatusEnum.CREATE.code().toString());
-        payOrderBo.setTitle(CreditTypeEnum.WECHAT_RECHARGE.message());
-        payOrderBo.setBackUrl(callBackUrl);
-        payOrderBo.setRealName(userXm);
-        payOrderBo.setUserId(Long.parseLong(userId));
-        payOrderBo.setPhone(mobile);
-        payOrderBo.setDeptName(deptName);
-        payOrderBo.setDeptId(Long.parseLong(deptId));
-        payOrderBo.setCreateBy(Long.parseLong(userId));
-        payOrderBo.setCreateTime(DateUtil.date());
-
-        R<Map<String,String>> getResult = thirdPayBusiness.createCollectQrCode(payOrderBo);
+        R<Map<String, String>> getResult = thirdPayBusiness.createCollectQrCode(mapParams);
         if (R.isSuccess(getResult)) {
             return getResult;
         }
         return R.fail(getResult.getMsg());
+
+
         //return createQrCode(creditType, userId, userXm, deptId, deptName, mobile, dealValue, callBackUrl);
     }
 
     /**
      * 根据人员Id和部门Id查询第三方支付订单的支付情况
+     *
      * @param deptId 部门Id
      * @param userId 人员Id
      * @return 支付结果
      */
-    public ReturnResult queryPayResultByUserAndDept(Long deptId,Long userId){
+    public ReturnResult queryPayResultByUserAndDept(Long deptId, Long userId) {
         PayOrderBo bo = new PayOrderBo();
         bo.setUserId(userId);
         bo.setDeptId(deptId);
 
         List<PayOrderVo> vos = wxOrderService.queryList(bo);
-        if(CollectionUtil.isEmpty(vos)){
+        if (CollectionUtil.isEmpty(vos)) {
             return ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND,
-                                        MessageFormat.format("无对应的支付订单,部门Id:{0},人员Id:{1}", deptId, userId));
+                MessageFormat.format("无对应的支付订单,部门Id:{0},人员Id:{1}", deptId, userId));
         }
         String errMsg = String.format("[支付结果查询]-[deptId:%s,userId:%s]-[订单尚未支付成功]", deptId, userId);
-        PayOrderVo vo = vos.stream().filter(p-> ObjectUtil.equals(p.getCreditStatus(),"Y")).findFirst()
-                           .orElseThrow(() -> new ApiException(errMsg));
+        PayOrderVo vo = vos.stream().filter(p -> ObjectUtil.equals(p.getCreditStatus(), "Y")).findFirst()
+            .orElseThrow(() -> new ApiException(errMsg));
 
-       return ReturnResult.success(YcVoConvert.ycWxOrderConvert(vo));
+        return ReturnResult.success(YcVoConvert.ycWxOrderConvert(vo));
     }
 
     /**
      * 根据第三方订单号查询订单入账结果
+     *
      * @param orderSn 订单号
      * @return 入账结果
      */
-    public ReturnResult getCreditBackByOrderSn(String orderSn){
+    public ReturnResult getCreditBackByOrderSn(String orderSn) {
         XfCreditAccountBackBo bo = new XfCreditAccountBackBo();
         bo.setOriginalId(orderSn);
         List<XfCreditAccountBackVo> vos = creditAccountBackService.queryList(bo);
-        if(CollectionUtil.isEmpty(vos)){
+        if (CollectionUtil.isEmpty(vos)) {
             return ReturnResult.failure(ResultCodeEnum.DATA_NOT_FOUND);
         }
         if (ObjectUtil.notEqual((vos.get(0).getCreditStatus()), CreditStatusEnum.SUCCESS.code())) {
@@ -197,31 +179,33 @@ public class SelfBusiness {
         }
         return ReturnResult.success();
     }
+
     /**
-     *  请求生成微信收款二维码
-     * @param creditType 交易类型
-     * @param userId 人员Id
-     * @param userXm 人员姓名
-     * @param deptId 部门Id
-     * @param deptName 部门名称
-     * @param mobile 手机号
-     * @param dealValue 充值金额
+     * 请求生成微信收款二维码
+     *
+     * @param creditType  交易类型
+     * @param userId      人员Id
+     * @param userXm      人员姓名
+     * @param deptId      部门Id
+     * @param deptName    部门名称
+     * @param mobile      手机号
+     * @param dealValue   充值金额
      * @param callBackUrl 回调地址
      * @return 二维码
      */
-    private ReturnResult createQrCode(CreditTypeEnum creditType, String userId, String userXm, String deptId, String deptName, String mobile, BigDecimal dealValue, String callBackUrl){
+    private ReturnResult createQrCode(CreditTypeEnum creditType, String userId, String userXm, String deptId, String deptName, String mobile, BigDecimal dealValue, String callBackUrl) {
         String sendUrl = payApi + "?title=" + CreditTypeEnum.WECHAT_RECHARGE.message() + "&userId=" + userId
-                             + "&name=" + userXm
-                             + "&deptName=" + deptName
-                             + "&deptId=" + deptId
-                             + "&mobile=" + Base64.encode(mobile)
-                             + "&amount=" + dealValue
-                             + "&dealType=" + creditType.code()
-                             + "&callBackUrl=" + callBackUrl;
+            + "&name=" + userXm
+            + "&deptName=" + deptName
+            + "&deptId=" + deptId
+            + "&mobile=" + Base64.encode(mobile)
+            + "&amount=" + dealValue
+            + "&dealType=" + creditType.code()
+            + "&callBackUrl=" + callBackUrl;
         HttpRequest req = HttpUtil.createGet(sendUrl);
-        try(HttpResponse res = req.execute()){
+        try (HttpResponse res = req.execute()) {
             return JSONUtil.toBean(res.body(), ReturnResult.class);
-        }catch (Exception e){
+        } catch (Exception e) {
             throw new ApiException("生成微信收款码错误", ResultCodeEnum.INTERFACE_OUTER_INVOKE_ERROR.code());
         }
     }

+ 10 - 0
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/payment/domain/bo/PayOrderBo.java

@@ -115,4 +115,14 @@ public class PayOrderBo extends BaseEntity {
      * 订单入账流水号,对应 t_xf_consumeDetailOriginal 表中的original_id
      */
     private String originalId;
+
+    /**
+     * 第三方支付绑定Id
+     */
+    private String ssoId;
+
+    /**
+     * 第三方支付请求头
+     */
+    private String userAgent;
 }

+ 24 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/wx/contorller/WxController.java

@@ -1,6 +1,8 @@
 package org.dromara.backstage.wx.contorller;
 
+import jakarta.servlet.http.HttpServletRequest;
 import lombok.RequiredArgsConstructor;
+import org.dromara.backstage.business.payments.ThirdPayBusiness;
 import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.backstage.wx.domain.vo.WxCreditAccountVo;
 import org.dromara.backstage.wx.service.IWxService;
@@ -10,9 +12,14 @@ import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 import org.dromara.common.satoken.utils.LoginHelper;
 import org.dromara.common.web.core.BaseController;
+import org.dromara.system.api.model.LoginUser;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * 微信
  */
@@ -22,11 +29,12 @@ import org.springframework.web.bind.annotation.*;
 @ResponseResult
 @RequestMapping("/wx")
 public class WxController extends BaseController {
-
     private final IWxService wxService;
+    private final ThirdPayBusiness thirdPayBusiness;
 
     /**
      * 查询用户账户信息
+     *
      * @return
      */
     @GetMapping("/getUserInfo")
@@ -37,6 +45,7 @@ public class WxController extends BaseController {
 
     /**
      * 查询账单明细
+     *
      * @param type 1 消费,2 充值
      * @return
      */
@@ -49,6 +58,7 @@ public class WxController extends BaseController {
 
     /**
      * 卡片挂失解挂
+     *
      * @param cardStatus
      * @return
      */
@@ -69,6 +79,7 @@ public class WxController extends BaseController {
 
     /**
      * 获取身份码
+     *
      * @return
      */
     @GetMapping("/getIdCode")
@@ -76,4 +87,16 @@ public class WxController extends BaseController {
         Long userId = LoginHelper.getUserId();
         return wxService.getIdCode(userId);
     }
+
+    @GetMapping("/pay")
+    public R<String> wxPay(HttpServletRequest request, @RequestParam String ssoId, @RequestParam String transValue) {
+        String userAgent = request.getHeader("user-agent");
+        Long userId = LoginHelper.getUserId();
+        Map<String, String> mapParams = new HashMap<>();
+        mapParams.put("userId", userId.toString());
+        mapParams.put("ssoId", ssoId);
+        mapParams.put("dealValue", transValue);
+        mapParams.put("userAgent", userAgent);
+        return thirdPayBusiness.createDirectPayment(mapParams);
+    }
 }

+ 1 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/wx/service/IWxService.java

@@ -6,7 +6,7 @@ import org.dromara.common.core.domain.R;
 import org.dromara.common.mybatis.core.page.PageQuery;
 import org.dromara.common.mybatis.core.page.TableDataInfo;
 
-import java.util.Date;
+import java.math.BigDecimal;
 
 /**
  * 微信Service接口

+ 6 - 1
ruoyi-modules/ruoyi-backstage/src/main/java/org/dromara/backstage/wx/service/impl/WxServiceImpl.java

@@ -16,10 +16,13 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.time.DateFormatUtils;
+import org.dromara.backstage.business.payments.ThirdPayBusiness;
 import org.dromara.backstage.cardCenter.domain.PtCard;
 import org.dromara.backstage.cardCenter.mapper.PtCardMapper;
+import org.dromara.backstage.config.ThirdPayConfig;
 import org.dromara.backstage.consumption.mapper.XfCreditAccountMapper;
 import org.dromara.backstage.payment.domain.PtUserAccount;
+import org.dromara.backstage.payment.domain.bo.PayOrderBo;
 import org.dromara.backstage.payment.domain.bo.PtUserAccountBo;
 import org.dromara.backstage.payment.domain.vo.PtUserAccountVo;
 import org.dromara.backstage.payment.mapper.PtUserAccountMapper;
@@ -27,6 +30,9 @@ import org.dromara.backstage.wx.domain.vo.WxCreditAccountVo;
 import org.dromara.backstage.wx.service.FaceEngineService;
 import org.dromara.backstage.wx.service.IWxService;
 import org.dromara.common.core.domain.R;
+import org.dromara.common.core.enums.CreditTypeEnum;
+import org.dromara.common.core.enums.PayStatusEnum;
+import org.dromara.common.core.enums.PayStyleEnum;
 import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.ByteArrayUtilByYC;
 import org.dromara.common.core.utils.MapstructUtils;
@@ -58,7 +64,6 @@ import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
 @Service
 @Slf4j
 public class WxServiceImpl implements IWxService {
-
     private final PtUserAccountMapper accountMapper;
     private final XfCreditAccountMapper creditAccountMapper;
     private final PtCardMapper cardMapper;