提交 6dd231be authored 作者: hzh's avatar hzh

Merge branch 'dev'

package org.dromara.order.api; package org.dromara.order.api;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder; import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder; import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.enums.OrderType;
import org.dromara.order.api.enums.Source;
import java.util.List; import java.util.List;
...@@ -18,7 +21,7 @@ public interface RemoteOrderService { ...@@ -18,7 +21,7 @@ public interface RemoteOrderService {
* @param order 订单信息 * @param order 订单信息
* @return 订单支付信息 * @return 订单支付信息
*/ */
String createOrder(RemoteSaveOrder order) throws Exception; OrderPay createOrder(RemoteSaveOrder order) throws Exception;
/** /**
* 查询订单列表 * 查询订单列表
...@@ -38,4 +41,14 @@ public interface RemoteOrderService { ...@@ -38,4 +41,14 @@ public interface RemoteOrderService {
*/ */
boolean autoUpdateOrGetCertificate(String serialNumber) throws Exception; boolean autoUpdateOrGetCertificate(String serialNumber) throws Exception;
/**
* 计算服务费
*
* @param source 来源
* @param orderType 订单类型
* @param feeList 费用列表
* @return 服务费
*/
RemoteSaveOrder.Fee calcServiceFee(Source source, OrderType orderType, List<RemoteSaveOrder.Fee> feeList);
} }
package org.dromara.order.api.domain; package org.dromara.order.api.domain;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/** /**
* @author hzh * @author hzh
* @date 2024-12-05 * @date 2024-12-05
**/ **/
@Data @Data
public class OrderPay { @Accessors(chain = true)
public class OrderPay implements Serializable {
/**
* 订单号
*/
private String orderNo;
/**
* 支付订单号
*/
private String orderPayNo;
/**
* 支付信息
*/
private String payInfo;
} }
...@@ -3,13 +3,15 @@ package org.dromara.order.api.domain; ...@@ -3,13 +3,15 @@ package org.dromara.order.api.domain;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.io.Serializable;
/** /**
* @author hzh * @author hzh
* @date 2024-12-09 * @date 2024-12-09
**/ **/
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class RemoteOrder { public class RemoteOrder implements Serializable {
/** /**
* 订单类型 * 订单类型
......
...@@ -10,7 +10,7 @@ import lombok.Getter; ...@@ -10,7 +10,7 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum Source { public enum Source {
YSH("ys", "云上"); YSH("YS", "云上");
private final String source; private final String source;
private final String desc; private final String desc;
......
package org.dromara.common.pay.config; package org.dromara.common.pay.config;
import lombok.Getter; import lombok.Data;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -19,9 +17,7 @@ import org.springframework.stereotype.Component; ...@@ -19,9 +17,7 @@ import org.springframework.stereotype.Component;
* *
* @author Javen * @author Javen
*/ */
@Getter @Data
@Setter
@ToString
@Component @Component
@ConfigurationProperties(prefix = "pay.wechat.v3") @ConfigurationProperties(prefix = "pay.wechat.v3")
public class WechatPayConfiguration { public class WechatPayConfiguration {
......
package org.dromara.common.pay.domain; package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.io.Serializable; import java.io.Serializable;
...@@ -13,9 +10,6 @@ import java.io.Serializable; ...@@ -13,9 +10,6 @@ import java.io.Serializable;
* @date 2024-12-10 * @date 2024-12-10
* @desc jsapi 回调参数 * @desc jsapi 回调参数
**/ **/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
@SuppressWarnings("all") @SuppressWarnings("all")
...@@ -104,9 +98,6 @@ public class JsapiNotifyModel implements Serializable { ...@@ -104,9 +98,6 @@ public class JsapiNotifyModel implements Serializable {
*/ */
private PromotionDetail promotion_detail; private PromotionDetail promotion_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class Payer implements Serializable { public static class Payer implements Serializable {
...@@ -118,9 +109,6 @@ public class JsapiNotifyModel implements Serializable { ...@@ -118,9 +109,6 @@ public class JsapiNotifyModel implements Serializable {
} }
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class Amount implements Serializable { public static class Amount implements Serializable {
...@@ -147,9 +135,6 @@ public class JsapiNotifyModel implements Serializable { ...@@ -147,9 +135,6 @@ public class JsapiNotifyModel implements Serializable {
} }
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class SceneInfo implements Serializable { public static class SceneInfo implements Serializable {
...@@ -161,9 +146,6 @@ public class JsapiNotifyModel implements Serializable { ...@@ -161,9 +146,6 @@ public class JsapiNotifyModel implements Serializable {
} }
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class PromotionDetail implements Serializable { public static class PromotionDetail implements Serializable {
...@@ -227,9 +209,6 @@ public class JsapiNotifyModel implements Serializable { ...@@ -227,9 +209,6 @@ public class JsapiNotifyModel implements Serializable {
*/ */
private GoodsDetail goods_detail; private GoodsDetail goods_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class GoodsDetail implements Serializable { public static class GoodsDetail implements Serializable {
......
package org.dromara.common.pay.domain; package org.dromara.common.pay.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.io.Serializable; import java.io.Serializable;
...@@ -14,9 +11,6 @@ import java.util.List; ...@@ -14,9 +11,6 @@ import java.util.List;
* @date 2024-12-13 * @date 2024-12-13
* @desc 退款退款对象 * @desc 退款退款对象
**/ **/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
@SuppressWarnings("all") @SuppressWarnings("all")
...@@ -108,9 +102,6 @@ public class RefundModel implements Serializable { ...@@ -108,9 +102,6 @@ public class RefundModel implements Serializable {
*/ */
private List<PromotionDetail> promotion_detail; private List<PromotionDetail> promotion_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class RefundAmount implements Serializable { public static class RefundAmount implements Serializable {
...@@ -165,9 +156,6 @@ public class RefundModel implements Serializable { ...@@ -165,9 +156,6 @@ public class RefundModel implements Serializable {
*/ */
private Integer refund_fee; private Integer refund_fee;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class From implements Serializable { public static class From implements Serializable {
...@@ -186,9 +174,6 @@ public class RefundModel implements Serializable { ...@@ -186,9 +174,6 @@ public class RefundModel implements Serializable {
} }
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class PromotionDetail implements Serializable { public static class PromotionDetail implements Serializable {
...@@ -230,9 +215,6 @@ public class RefundModel implements Serializable { ...@@ -230,9 +215,6 @@ public class RefundModel implements Serializable {
private List<GoodsDetail> goods_detail; private List<GoodsDetail> goods_detail;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public static class GoodsDetail implements Serializable { public static class GoodsDetail implements Serializable {
......
...@@ -48,11 +48,12 @@ public interface IWxPayService { ...@@ -48,11 +48,12 @@ public interface IWxPayService {
* *
* @param timestamp 时间搓 * @param timestamp 时间搓
* @param nonce nonce * @param nonce nonce
* @param serialNo serialNo
* @param signature 签名 * @param signature 签名
* @param result 支付通知密文 * @param result 支付通知密文
* @return 支付通知明文 * @return 支付通知明文
*/ */
JsapiNotifyModel notify(String timestamp, String nonce, String signature, String result); JsapiNotifyModel notify(String timestamp, String nonce, String serialNo, String signature, String result);
/** /**
* 退款 * 退款
......
...@@ -48,7 +48,7 @@ public class WxPayServiceImpl implements IWxPayService { ...@@ -48,7 +48,7 @@ public class WxPayServiceImpl implements IWxPayService {
/** /**
* 商户 API 证书序列号 * 商户 API 证书序列号
*/ */
private String serialNo; private String serialNo;
/** /**
* 获取证书序列号 * 获取证书序列号
...@@ -74,7 +74,7 @@ public class WxPayServiceImpl implements IWxPayService { ...@@ -74,7 +74,7 @@ public class WxPayServiceImpl implements IWxPayService {
unifiedOrderModel unifiedOrderModel
.setAppid(config.getAppId()) .setAppid(config.getAppId())
.setMchid(config.getMchId()) .setMchid(config.getMchId())
.setNotify_url(config.getNotify()); .setNotify_url(config.getDomain() + config.getNotify());
log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
IJPayHttpResponse response = WxPayApi.v3( IJPayHttpResponse response = WxPayApi.v3(
RequestMethodEnum.POST, RequestMethodEnum.POST,
...@@ -95,8 +95,9 @@ public class WxPayServiceImpl implements IWxPayService { ...@@ -95,8 +95,9 @@ public class WxPayServiceImpl implements IWxPayService {
String prepayId = jsonObject.getStr("prepay_id"); String prepayId = jsonObject.getStr("prepay_id");
Map<String, String> map = WxPayKit.jsApiCreateSign(config.getAppId(), prepayId, config.getKeyPath()); Map<String, String> map = WxPayKit.jsApiCreateSign(config.getAppId(), prepayId, config.getKeyPath());
return JSONUtil.toJsonStr(map); return JSONUtil.toJsonStr(map);
} else {
throw new RuntimeException("下单失败!");
} }
throw new RuntimeException("下单失败!");
} }
@Override @Override
...@@ -205,14 +206,13 @@ public class WxPayServiceImpl implements IWxPayService { ...@@ -205,14 +206,13 @@ public class WxPayServiceImpl implements IWxPayService {
} }
@Override @Override
public JsapiNotifyModel notify(String timestamp, String nonce, String signature, String result) { public JsapiNotifyModel notify(String timestamp, String nonce,String serialNo, String signature, String result) {
String serialNumber = getSerialNumber(); log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNumber, signature);
log.info("支付通知密文 {}", result); log.info("支付通知密文 {}", result);
try { try {
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号 // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String plainText = WxPayKit.verifyNotify( String plainText = WxPayKit.verifyNotify(
serialNumber, serialNo,
result, result,
signature, signature,
nonce, nonce,
...@@ -279,16 +279,8 @@ public class WxPayServiceImpl implements IWxPayService { ...@@ -279,16 +279,8 @@ public class WxPayServiceImpl implements IWxPayService {
config.getKeyPath(), config.getKeyPath(),
JSONUtil.toJsonStr(params)); JSONUtil.toJsonStr(params));
log.info("关闭订单:{} 查询响应 {}", outTradeNo, response); log.info("关闭订单:{} 查询响应 {}", outTradeNo, response);
if (response.getStatus() == IJPayConstants.CODE_200) { if (response.getStatus() == IJPayConstants.CODE_204) {
// 根据证书序列号查询对应的证书来验证签名结果 return true;
boolean verifySignature = WxPayKit.verifySignature(response, config.getPlatformCertPath());
log.info("verifySignature: {}", verifySignature);
//验签成功
if (verifySignature) {
return true;
} else {
return false;
}
} }
throw new RuntimeException("订单:" + outTradeNo + "关闭失败!"); throw new RuntimeException("订单:" + outTradeNo + "关闭失败!");
} catch (Exception e) { } catch (Exception e) {
......
package org.dromara.common.pay.util;
import com.ijpay.core.kit.HttpKit;
import jakarta.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
/**
* @author hzh
* @date 2024-12-19
**/
public class CustomHttpKit extends HttpKit {
public static String readData(HttpServletRequest request) {
BufferedReader br = null;
try {
StringBuilder result = new StringBuilder();
br = request.getReader();
for (String line; (line = br.readLine()) != null; ) {
if (result.length() > 0) {
result.append("\n");
}
result.append(line);
}
return result.toString();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
...@@ -101,7 +101,7 @@ public class LoginHelper { ...@@ -101,7 +101,7 @@ public class LoginHelper {
* 获取用户id * 获取用户id
*/ */
public static String getOpenId() { public static String getOpenId() {
return Convert.toStr(getExtra(YS_USER_ID)); return Convert.toStr(getExtra(OPEN_ID));
} }
/** /**
......
...@@ -81,6 +81,12 @@ ...@@ -81,6 +81,12 @@
<artifactId>ruoyi-api-server</artifactId> <artifactId>ruoyi-api-server</artifactId>
</dependency> </dependency>
<!-- RuoYi Api Order -->
<dependency>
<groupId>org.dromara</groupId>
<artifactId>ruoyi-api-order</artifactId>
</dependency>
</dependencies> </dependencies>
......
package org.dromara.job.snailjob;
import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
import com.aizuda.snailjob.client.model.ExecuteResult;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.order.api.RemoteOrderService;
import org.springframework.stereotype.Component;
/**
* @author hzh
* @date 2024-11-18
*/
@AllArgsConstructor
@Component
@JobExecutor(name = "payJobExecutor")
public class PayJobExecutor {
@DubboReference
private RemoteOrderService remoteOrderService;
public ExecuteResult jobExecute(JobArgs jobArgs) throws Exception {
remoteOrderService.autoUpdateOrGetCertificate(null);
return ExecuteResult.success("注册成功");
}
}
package org.dromara.order.controller; package org.dromara.order.controller;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.http.ContentType; import cn.hutool.http.ContentType;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.ijpay.core.kit.HttpKit;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.pay.domain.JsapiNotifyModel; import org.dromara.common.pay.domain.JsapiNotifyModel;
import org.dromara.common.pay.util.CustomHttpKit;
import org.dromara.common.web.core.BaseController; import org.dromara.common.web.core.BaseController;
import org.dromara.order.domain.bo.OrderBo;
import org.dromara.order.domain.vo.OrderVo;
import org.dromara.order.service.IOrderPayService; import org.dromara.order.service.IOrderPayService;
import org.dromara.order.service.IOrderService;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
/** /**
...@@ -49,97 +38,31 @@ import java.util.Map; ...@@ -49,97 +38,31 @@ import java.util.Map;
@RequestMapping("/order") @RequestMapping("/order")
public class OrderController extends BaseController { public class OrderController extends BaseController {
private final IOrderService orderService;
private final IOrderPayService orderPayService; private final IOrderPayService orderPayService;
/** /**
* 查询订单费用列表 * 回调函数
*/
@SaCheckPermission("order:order:list")
@GetMapping("/list")
public TableDataInfo<OrderVo> list(OrderBo bo, PageQuery pageQuery) {
return orderService.queryPageList(bo, pageQuery);
}
/**
* 导出订单费用列表
*/
@SaCheckPermission("order:order:export")
@Log(title = "订单费用", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(OrderBo bo, HttpServletResponse response) {
List<OrderVo> list = orderService.queryList(bo);
ExcelUtil.exportExcel(list, "订单费用", OrderVo.class, response);
}
/**
* 获取订单费用详细信息
* *
* @param id 主键
*/
@SaCheckPermission("order:order:query")
@GetMapping("/{id}")
public R<OrderVo> getInfo(@NotNull(message = "主键不能为空")
@PathVariable Long id) {
return R.ok(orderService.queryById(id));
}
/**
* 新增订单费用
*/
@SaCheckPermission("order:order:add")
@Log(title = "订单费用", businessType = BusinessType.INSERT)
@RepeatSubmit()
@PostMapping()
public R<Void> add(@Validated(AddGroup.class) @RequestBody OrderBo bo) {
return toAjax(orderService.insertByBo(bo));
}
/**
* 修改订单费用
*/
@SaCheckPermission("order:order:edit")
@Log(title = "订单费用", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping()
public R<Void> edit(@Validated(EditGroup.class) @RequestBody OrderBo bo) {
return toAjax(orderService.updateByBo(bo));
}
/**
* 删除订单费用
*
* @param ids 主键串
*/
@SaCheckPermission("order:order:remove")
@Log(title = "订单费用", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public R<Void> remove(@NotEmpty(message = "主键不能为空")
@PathVariable Long[] ids) {
return toAjax(orderService.deleteWithValidByIds(List.of(ids), true));
}
/**
* 回调原函数
*
* @param request request
* @param response response * @param response response
*/ */
@RequestMapping(value = "/v3/payNotify", method = {RequestMethod.POST, RequestMethod.GET}) @RequestMapping(value = "/v3/payNotify", method = {RequestMethod.POST, RequestMethod.GET})
public void payNotify(HttpServletRequest request, HttpServletResponse response) { public void payNotify(HttpServletResponse response) {
Map<String, String> map = new HashMap<>(12); Map<String, String> map = new HashMap<>(12);
try { try {
log.info("微信回调开始"); log.info("微信回调开始");
ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String>builder() jakarta.servlet.http.HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
ImmutableMap<String, String> builder = ImmutableMap.<String, String>builder()
.put("timestamp", request.getHeader("Wechatpay-Timestamp")) .put("timestamp", request.getHeader("Wechatpay-Timestamp"))
.put("nonce", request.getHeader("Wechatpay-Nonce")) .put("nonce", request.getHeader("Wechatpay-Nonce"))
.put("serialNo", request.getHeader("Wechatpay-Serial")) .put("serialNo", request.getHeader("Wechatpay-Serial"))
.put("signature", request.getHeader("Wechatpay-Signature")) .put("signature", request.getHeader("Wechatpay-Signature"))
.put("result", HttpKit.readData(request)); .put("result", CustomHttpKit.readData(request))
.build();
boolean result = orderPayService.notify(JSON.toJSONString(builder)); boolean result = orderPayService.notify(JSON.toJSONString(new HashMap<>(builder)));
if (result) { if (result) {
response.setStatus(200); response.setStatus(200);
......
...@@ -9,14 +9,18 @@ import io.seata.spring.annotation.GlobalTransactional; ...@@ -9,14 +9,18 @@ import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboService; import org.apache.dubbo.config.annotation.DubboService;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.core.utils.ValidatorUtils; import org.dromara.common.core.utils.ValidatorUtils;
import org.dromara.common.pay.service.IWxPayService; import org.dromara.common.pay.service.IWxPayService;
import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.order.api.RemoteOrderService; import org.dromara.order.api.RemoteOrderService;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder; import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder; import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.enums.OrderStatus; import org.dromara.order.api.enums.OrderStatus;
import org.dromara.order.api.enums.OrderType;
import org.dromara.order.api.enums.Source;
import org.dromara.order.constant.WechatTradeState; import org.dromara.order.constant.WechatTradeState;
import org.dromara.order.domain.bo.OrderBo; import org.dromara.order.domain.bo.OrderBo;
import org.dromara.order.domain.bo.OrderFeeBo; import org.dromara.order.domain.bo.OrderFeeBo;
...@@ -32,7 +36,6 @@ import java.math.BigDecimal; ...@@ -32,7 +36,6 @@ import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
...@@ -54,7 +57,7 @@ public class RemoteOrderServiceImpl implements RemoteOrderService { ...@@ -54,7 +57,7 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
@GlobalTransactional(rollbackFor = Exception.class) @GlobalTransactional(rollbackFor = Exception.class)
@Override @Override
public String createOrder(RemoteSaveOrder remoteOrder) throws Exception { public OrderPay createOrder(RemoteSaveOrder remoteOrder) throws Exception {
ValidatorUtils.validate(remoteOrder); ValidatorUtils.validate(remoteOrder);
//查询订单信息 //查询订单信息
Long userId = LoginHelper.getUserId(); Long userId = LoginHelper.getUserId();
...@@ -67,7 +70,7 @@ public class RemoteOrderServiceImpl implements RemoteOrderService { ...@@ -67,7 +70,7 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
).stream().findFirst().orElseGet(() -> { ).stream().findFirst().orElseGet(() -> {
//创建订单 //创建订单
OrderBo bo = new OrderBo() OrderBo bo = new OrderBo()
.setUserId(LoginHelper.getUserId()) .setUserId(userId)
.setOrderNo(System.currentTimeMillis() + "") .setOrderNo(System.currentTimeMillis() + "")
.setSource(remoteOrder.getSource().getSource()) .setSource(remoteOrder.getSource().getSource())
.setOrderType(remoteOrder.getOrderType().getType()) .setOrderType(remoteOrder.getOrderType().getType())
...@@ -81,30 +84,35 @@ public class RemoteOrderServiceImpl implements RemoteOrderService { ...@@ -81,30 +84,35 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
if (StringUtils.equals(order.getStatus(), OrderStatus.PAYED.getCode())) { if (StringUtils.equals(order.getStatus(), OrderStatus.PAYED.getCode())) {
throw new ServiceException("订单已支付"); throw new ServiceException("订单已支付");
} }
//获取订单支付信息
List<OrderFeeVo> feeList = Optional.ofNullable(orderFeeService.queryList(new OrderFeeBo() //删除历史订单费用信息
.setOrderNo(order.getOrderNo()))) List<OrderFeeVo> orderFeeVos = orderFeeService.queryList(new OrderFeeBo()
.orElseGet(() -> { .setOrderNo(order.getOrderNo()));
if (CollectionUtils.isNotEmpty(orderFeeVos)) {
//创建订单费用信息 orderFeeService.deleteWithValidByIds(StreamUtils.toList(orderFeeVos, OrderFeeVo::getId), false);
List<RemoteSaveOrder.Fee> list = remoteOrder.getFeeList(); }
//获取服务费信息 //创建订单费用信息
RemoteSaveOrder.Fee serviceFee = IOrderServiceFeeStrategy.calcServiceFee(remoteOrder.getSource(), remoteOrder.getOrderType(), list); List<RemoteSaveOrder.Fee> list = remoteOrder.getFeeList();
list.add(serviceFee);
//获取服务费信息
List<OrderFeeBo> ofList = list.stream().map(fee -> { RemoteSaveOrder.Fee serviceFee = IOrderServiceFeeStrategy.calcServiceFee(remoteOrder.getSource(), remoteOrder.getOrderType(), list);
return new OrderFeeBo() list.add(serviceFee);
.setOrderNo(order.getOrderNo())
.setFeeDesc(fee.getFeeDesc())
.setFeeAmount(fee.getFeeAmount()) List<OrderFeeBo> ofList = list.stream().map(fee -> {
.setFeeType(fee.getFeeType().getCode()) return new OrderFeeBo()
.setOtherInfo(fee.getOtherInfo()) .setUserId(order.getUserId())
.setRemark(fee.getRemark()); .setOrderNo(order.getOrderNo())
}).collect(Collectors.toList()); .setFeeDesc(fee.getFeeDesc())
orderFeeService.batchInsertByList(ofList); .setFeeAmount(fee.getFeeAmount())
return BeanUtil.copyToList(ofList, OrderFeeVo.class); .setFeeType(fee.getFeeType().getCode())
}); .setOtherInfo(fee.getOtherInfo())
.setRemark(fee.getRemark());
}).collect(Collectors.toList());
orderFeeService.batchInsertByList(ofList);
List<OrderFeeVo> feeList = BeanUtil.copyToList(ofList, OrderFeeVo.class);
//获取总金额 //获取总金额
assert feeList != null; assert feeList != null;
BigDecimal amount = feeList.stream().map(OrderFeeVo::getFeeAmount).reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal amount = feeList.stream().map(OrderFeeVo::getFeeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
...@@ -115,11 +123,15 @@ public class RemoteOrderServiceImpl implements RemoteOrderService { ...@@ -115,11 +123,15 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
for (OrderTradeVo ot : otList) { for (OrderTradeVo ot : otList) {
if (StringUtils.equals(ot.getTradeState(), WechatTradeState.USERPAYING.getState())) { if (StringUtils.equals(ot.getTradeState(), WechatTradeState.USERPAYING.getState())) {
wxPayService.close(ot.getOrderPayNo()); wxPayService.close(ot.getOrderPayNo());
ot.setTradeState(WechatTradeState.CLOSED.getState());
orderTradeService.updateByBo(BeanUtil.copyProperties(ot, OrderTradeBo.class));
} }
} }
} }
Date expireTime = DateUtil.offsetMinute(new Date(), expireMinute); Date expireTime = DateUtil.offsetMinute(new Date(), expireMinute);
String openId = LoginHelper.getOpenId();
//创建支付订单 //创建支付订单
OrderTradeBo ot = new OrderTradeBo() OrderTradeBo ot = new OrderTradeBo()
.setUserId(order.getUserId()) .setUserId(order.getUserId())
...@@ -133,18 +145,19 @@ public class RemoteOrderServiceImpl implements RemoteOrderService { ...@@ -133,18 +145,19 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
.setTradeType(remoteOrder.getTradeType().name()) .setTradeType(remoteOrder.getTradeType().name())
.setExpireTime(expireTime) .setExpireTime(expireTime)
.setTradeState(WechatTradeState.USERPAYING.getState()) .setTradeState(WechatTradeState.USERPAYING.getState())
.setPayOpenId(LoginHelper.getOpenId()); .setPayOpenId(openId);
orderTradeService.insertByBo(ot); orderTradeService.insertByBo(ot);
//跟新支付信息 //跟新支付信息
order.setAmount(ot.getAmount()); order.setAmount(ot.getAmount());
order.setPayAmount(ot.getPayAmount()); order.setPayAmount(ot.getPayAmount());
order.setActualPayAmount(ot.getActualPayAmount());
order.setDiscountAmount(ot.getDiscountAmount()); order.setDiscountAmount(ot.getDiscountAmount());
orderService.updateByBo(BeanUtil.copyProperties(order, OrderBo.class)); orderService.updateByBo(BeanUtil.copyProperties(order, OrderBo.class));
//获取支付订单 return new OrderPay()
return IPayStrategy.pay(JSON.toJSONString(ot), feeList, remoteOrder.getTradeType().name()); .setOrderNo(order.getOriginOrderNo())
.setOrderPayNo(ot.getOrderPayNo())
.setPayInfo(IPayStrategy.pay(JSON.toJSONString(ot), feeList, remoteOrder.getTradeType().name()));
} }
@Override @Override
...@@ -165,4 +178,9 @@ public class RemoteOrderServiceImpl implements RemoteOrderService { ...@@ -165,4 +178,9 @@ public class RemoteOrderServiceImpl implements RemoteOrderService {
public boolean autoUpdateOrGetCertificate(String serialNumber) throws Exception { public boolean autoUpdateOrGetCertificate(String serialNumber) throws Exception {
return wxPayService.autoUpdateOrGetCertificate(serialNumber); return wxPayService.autoUpdateOrGetCertificate(serialNumber);
} }
@Override
public RemoteSaveOrder.Fee calcServiceFee(Source source, OrderType orderType, List<RemoteSaveOrder.Fee> feeList) {
return IOrderServiceFeeStrategy.calcServiceFee(source, orderType, feeList);
}
} }
...@@ -39,12 +39,16 @@ public class JsapiPayStrategy implements IPayStrategy { ...@@ -39,12 +39,16 @@ public class JsapiPayStrategy implements IPayStrategy {
//获取支付金额 //获取支付金额
int amount = new BigDecimal("100").multiply(feeAmount).intValue(); int amount = new BigDecimal("100").multiply(feeAmount).intValue();
if (amount <= 0) {
throw new RuntimeException("支付金额不能小于等于0");
}
UnifiedOrderModel model = new UnifiedOrderModel() UnifiedOrderModel model = new UnifiedOrderModel()
.setDescription("测试") .setDescription("测试")
.setOut_trade_no(ot.getOrderPayNo()) .setOut_trade_no(ot.getOrderPayNo())
.setTime_expire(timeExpire) .setTime_expire(timeExpire)
.setAttach("") .setAttach("")
.setAmount(new Amount().setTotal(amount)) .setAmount(new Amount().setTotal(amount))
.setAmount(new Amount().setTotal(1))
.setPayer(new Payer().setOpenid(ot.getPayOpenId())); .setPayer(new Payer().setOpenid(ot.getPayOpenId()));
return wxPayService.jsapi(model); return wxPayService.jsapi(model);
} }
......
...@@ -12,6 +12,7 @@ import org.apache.dubbo.config.annotation.DubboReference; ...@@ -12,6 +12,7 @@ import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.common.pay.domain.JsapiNotifyModel; import org.dromara.common.pay.domain.JsapiNotifyModel;
import org.dromara.common.pay.service.IWxPayService; import org.dromara.common.pay.service.IWxPayService;
import org.dromara.order.api.enums.OrderStatus; import org.dromara.order.api.enums.OrderStatus;
import org.dromara.order.constant.WechatTradeState;
import org.dromara.order.domain.bo.OrderBo; import org.dromara.order.domain.bo.OrderBo;
import org.dromara.order.domain.bo.OrderTradeBo; import org.dromara.order.domain.bo.OrderTradeBo;
import org.dromara.order.domain.vo.OrderTradeVo; import org.dromara.order.domain.vo.OrderTradeVo;
...@@ -25,7 +26,9 @@ import org.springframework.stereotype.Service; ...@@ -25,7 +26,9 @@ import org.springframework.stereotype.Service;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
/** /**
* @author hzh * @author hzh
...@@ -52,6 +55,7 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService { ...@@ -52,6 +55,7 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
JsapiNotifyModel model = wxPayService.notify( JsapiNotifyModel model = wxPayService.notify(
bodyJson.getString("timestamp"), bodyJson.getString("timestamp"),
bodyJson.getString("nonce"), bodyJson.getString("nonce"),
bodyJson.getString("serialNo"),
bodyJson.getString("signature"), bodyJson.getString("signature"),
bodyJson.getString("result") bodyJson.getString("result")
); );
...@@ -80,10 +84,16 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService { ...@@ -80,10 +84,16 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
String orderPayNo = model.getOut_trade_no(); String orderPayNo = model.getOut_trade_no();
String tradeState = model.getTrade_state(); String tradeState = model.getTrade_state();
List<String> notUpdateStateList = List.of(WechatTradeState.NOTPAY.getState(), WechatTradeState.USERPAYING.getState());
if (notUpdateStateList.contains(tradeState)) {
return;
}
OrderTradeVo orderTrade = orderTradeService.getOne(new OrderTradeBo().setOrderPayNo(orderPayNo)); OrderTradeVo orderTrade = orderTradeService.getOne(new OrderTradeBo().setOrderPayNo(orderPayNo));
if (Objects.isNull(orderTrade)) { if (Objects.isNull(orderTrade)) {
throw new RuntimeException("交易订单不存在"); throw new RuntimeException("交易订单不存在");
} }
if (!StringUtils.equals(tradeState, orderTrade.getTradeState())) { if (!StringUtils.equals(tradeState, orderTrade.getTradeState())) {
//更新订单信息 //更新订单信息
String successTimeStr = model.getSuccess_time(); String successTimeStr = model.getSuccess_time();
...@@ -93,27 +103,32 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService { ...@@ -93,27 +103,32 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
String transactionId = model.getTransaction_id(); String transactionId = model.getTransaction_id();
JsapiNotifyModel.Amount amount = model.getAmount(); JsapiNotifyModel.Amount amount = model.getAmount();
//支付金额 //支付金额
int actualPayAmount = amount.getPayer_total(); Integer actualPayAmount = amount.getPayer_total();
//获取openId //获取openId
String payOpenId = model.getPayer().getOpenid(); String payOpenId = Optional.ofNullable(model.getPayer()).map(JsapiNotifyModel.Payer::getOpenid).orElse(null);
orderTrade.setPayOpenId(payOpenId); orderTrade.setPayOpenId(payOpenId);
orderTrade.setPayTime(payTime); orderTrade.setPayTime(payTime);
orderTrade.setTransactionId(transactionId); orderTrade.setTransactionId(transactionId);
orderTrade.setActualPayAmount(new BigDecimal(actualPayAmount).divide(new BigDecimal(100), 2, RoundingMode.CEILING)); if (Objects.nonNull(actualPayAmount)) {
orderTrade.setActualPayAmount(new BigDecimal(actualPayAmount).divide(new BigDecimal(100), 2, RoundingMode.CEILING));
}
orderTrade.setTradeState(tradeState); orderTrade.setTradeState(tradeState);
orderTrade.setTradeInfo(JSON.toJSONString(model)); orderTrade.setTradeInfo(JSON.toJSONString(model));
orderTradeService.updateByBo(BeanUtil.copyProperties(orderTrade, OrderTradeBo.class)); orderTradeService.updateByBo(BeanUtil.copyProperties(orderTrade, OrderTradeBo.class));
//跟新主表信息 if (StringUtils.equals(tradeState, WechatTradeState.SUCCESS.getState())) {
OrderVo order = orderService.getOne(new OrderBo().setOrderNo(orderTrade.getOrderNo())); //跟新主表信息
order.setOrderPayNo(orderPayNo); OrderVo order = orderService.getOne(new OrderBo().setOrderNo(orderTrade.getOrderNo()));
order.setActualPayAmount(orderTrade.getActualPayAmount()); order.setOrderPayNo(orderPayNo);
order.setPayTime(new Date()); order.setActualPayAmount(orderTrade.getActualPayAmount());
order.setStatus(OrderStatus.PAYED.getCode()); order.setPayTime(payTime);
orderService.updateByBo(BeanUtil.copyProperties(order, OrderBo.class)); order.setStatus(OrderStatus.PAYED.getCode());
orderService.updateByBo(BeanUtil.copyProperties(order, OrderBo.class));
//跟新云上相关信息
ysOrderService.payed(order.getOrderType(), order.getOriginOrderNo());
}
//跟新云上相关信息
ysOrderService.payed(order.getOrderType(), order.getOrderNo());
} }
} }
......
...@@ -2,7 +2,9 @@ package org.dromara.server.controller; ...@@ -2,7 +2,9 @@ package org.dromara.server.controller;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R; import org.dromara.common.core.domain.R;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder; import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.enums.OrderType; import org.dromara.order.api.enums.OrderType;
import org.dromara.server.domain.vo.OrderPayVo; import org.dromara.server.domain.vo.OrderPayVo;
import org.dromara.server.domain.vo.OrderQueryVo; import org.dromara.server.domain.vo.OrderQueryVo;
...@@ -32,7 +34,7 @@ public class OrderController { ...@@ -32,7 +34,7 @@ public class OrderController {
* 下单支付接口 * 下单支付接口
*/ */
@PostMapping("/pay") @PostMapping("/pay")
public R<Object> pay(@Validated @RequestBody OrderPayVo vo) throws Exception { public R<OrderPay> pay(@Validated @RequestBody OrderPayVo vo) throws Exception {
OrderType ot = OrderType.getEnum(vo.getOrderType()); OrderType ot = OrderType.getEnum(vo.getOrderType());
return R.ok(service.createOrder(vo.getOrderNo(), ot)); return R.ok(service.createOrder(vo.getOrderNo(), ot));
} }
...@@ -45,4 +47,16 @@ public class OrderController { ...@@ -45,4 +47,16 @@ public class OrderController {
return R.ok(service.queryList(vo.getOrderType(), vo.getOrderNoList())); return R.ok(service.queryList(vo.getOrderType(), vo.getOrderNoList()));
} }
/**
* 获取费用信息
* @param vo vo
* @return 费用列表
*/
@PostMapping("/calcFee")
public R<List<RemoteSaveOrder.Fee>> calcFee(@Validated @RequestBody OrderPayVo vo){
OrderType ot = OrderType.getEnum(vo.getOrderType());
return R.ok(service.calcFee(vo.getOrderNo(), ot));
}
} }
package org.dromara.server.service; package org.dromara.server.service;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder; import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.enums.OrderType; import org.dromara.order.api.enums.OrderType;
import java.util.List; import java.util.List;
...@@ -18,7 +20,7 @@ public interface IPayOrderService { ...@@ -18,7 +20,7 @@ public interface IPayOrderService {
* @param orderType 订单类型 * @param orderType 订单类型
* @return 订单号 * @return 订单号
*/ */
String createOrder(String orderNo, OrderType orderType) throws Exception; OrderPay createOrder(String orderNo, OrderType orderType) throws Exception;
/** /**
* 查询订单列表 * 查询订单列表
...@@ -29,4 +31,11 @@ public interface IPayOrderService { ...@@ -29,4 +31,11 @@ public interface IPayOrderService {
*/ */
List<RemoteOrder> queryList(String orderType, List<String> orderNoList); List<RemoteOrder> queryList(String orderType, List<String> orderNoList);
/**
* 计算费用
* @param orderNo 订单号
* @param ot 订单类型
* @return 费用列表
*/
List<RemoteSaveOrder.Fee> calcFee(String orderNo, OrderType ot);
} }
package org.dromara.server.service.impl; package org.dromara.server.service.impl;
import com.alibaba.nacos.common.utils.CollectionUtils;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference; import org.apache.dubbo.config.annotation.DubboReference;
import org.dromara.order.api.RemoteOrderService; import org.dromara.order.api.RemoteOrderService;
import org.dromara.order.api.domain.OrderPay;
import org.dromara.order.api.domain.RemoteOrder; import org.dromara.order.api.domain.RemoteOrder;
import org.dromara.order.api.domain.RemoteSaveOrder; import org.dromara.order.api.domain.RemoteSaveOrder;
import org.dromara.order.api.enums.OrderType; import org.dromara.order.api.enums.OrderType;
...@@ -12,6 +14,8 @@ import org.dromara.server.service.IOrderStrategy; ...@@ -12,6 +14,8 @@ import org.dromara.server.service.IOrderStrategy;
import org.dromara.server.service.IPayOrderService; import org.dromara.server.service.IPayOrderService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
...@@ -26,12 +30,16 @@ public class PayOrderServiceImpl implements IPayOrderService { ...@@ -26,12 +30,16 @@ public class PayOrderServiceImpl implements IPayOrderService {
private RemoteOrderService remoteOrderService; private RemoteOrderService remoteOrderService;
@Override @Override
public String createOrder(String orderNo, OrderType orderType) throws Exception { public OrderPay createOrder(String orderNo, OrderType orderType) throws Exception {
RemoteSaveOrder order = IOrderStrategy.createOrder(orderNo, orderType); RemoteSaveOrder order = IOrderStrategy.createOrder(orderNo, orderType);
order.setSource(Source.YSH); order.setSource(Source.YSH);
order.setOriginOrderNo(orderNo); order.setOriginOrderNo(orderNo);
order.setTradeType(TradeType.JSAPI); order.setTradeType(TradeType.JSAPI);
order.setOrderType(orderType); order.setOrderType(orderType);
BigDecimal amount = order.getFeeList().stream().map(RemoteSaveOrder.Fee::getFeeAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("订单金额不能小于等于0");
}
return remoteOrderService.createOrder(order); return remoteOrderService.createOrder(order);
} }
...@@ -39,4 +47,19 @@ public class PayOrderServiceImpl implements IPayOrderService { ...@@ -39,4 +47,19 @@ public class PayOrderServiceImpl implements IPayOrderService {
public List<RemoteOrder> queryList(String orderType, List<String> orderNoList) { public List<RemoteOrder> queryList(String orderType, List<String> orderNoList) {
return remoteOrderService.queryList(orderType, orderNoList); return remoteOrderService.queryList(orderType, orderNoList);
} }
@Override
public List<RemoteSaveOrder.Fee> calcFee(String orderNo, OrderType ot) {
RemoteSaveOrder order = IOrderStrategy.createOrder(orderNo, ot);
List<RemoteSaveOrder.Fee> feeList = order.getFeeList();
if (CollectionUtils.isEmpty(feeList)) {
return List.of();
}
RemoteSaveOrder.Fee fee = remoteOrderService.calcServiceFee(Source.YSH, ot, feeList);
if (fee != null) {
feeList = new ArrayList<>(feeList);
feeList.add(fee);
}
return feeList;
}
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论