|
@@ -1,6 +1,7 @@
|
|
|
package com.haha.service.payment.payscore.impl;
|
|
package com.haha.service.payment.payscore.impl;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson2.JSON;
|
|
import com.alibaba.fastjson2.JSON;
|
|
|
|
|
+import com.alibaba.fastjson2.JSONObject;
|
|
|
import com.haha.common.constant.OrderConstants;
|
|
import com.haha.common.constant.OrderConstants;
|
|
|
import com.haha.common.enums.OrderStatus;
|
|
import com.haha.common.enums.OrderStatus;
|
|
|
import com.haha.common.enums.PayScoreState;
|
|
import com.haha.common.enums.PayScoreState;
|
|
@@ -16,6 +17,7 @@ import com.haha.service.payment.payscore.PayScoreCreateRequest.PostPayment;
|
|
|
import com.haha.service.payment.payscore.PayScoreCompleteRequest.PostDiscount;
|
|
import com.haha.service.payment.payscore.PayScoreCompleteRequest.PostDiscount;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
@@ -26,6 +28,7 @@ import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* 支付分业务服务实现
|
|
* 支付分业务服务实现
|
|
@@ -47,9 +50,14 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
@Autowired(required = false)
|
|
@Autowired(required = false)
|
|
|
private WxPayConfig wxPayConfig;
|
|
private WxPayConfig wxPayConfig;
|
|
|
|
|
|
|
|
|
|
+ @Autowired(required = false)
|
|
|
|
|
+ private StringRedisTemplate stringRedisTemplate;
|
|
|
|
|
+
|
|
|
|
|
+ private static final String REDIS_KEY_PREFIX = "payscore:preauth:";
|
|
|
|
|
+ private static final long REDIS_TTL_MINUTES = 10;
|
|
|
|
|
+
|
|
|
private static final BigDecimal DEFAULT_RISK_FUND_AMOUNT = new BigDecimal("99.00");
|
|
private static final BigDecimal DEFAULT_RISK_FUND_AMOUNT = new BigDecimal("99.00");
|
|
|
private static final String DEFAULT_RISK_FUND_NAME = "DEPOSIT";
|
|
private static final String DEFAULT_RISK_FUND_NAME = "DEPOSIT";
|
|
|
- private static final int PAYSCORE_ENABLED = 1;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@@ -555,50 +563,6 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
|
|
|
|
|
// ==================== 用户端支付分业务方法 ====================
|
|
// ==================== 用户端支付分业务方法 ====================
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
|
- public Map<String, Object> checkPayscoreEnabled(Long userId) {
|
|
|
|
|
- User user = userService.getById(userId);
|
|
|
|
|
- boolean isEnabled = isPayscoreEnabled(user);
|
|
|
|
|
- Map<String, Object> data = new HashMap<>();
|
|
|
|
|
- data.put("enabled", isEnabled);
|
|
|
|
|
- data.put("userId", userId);
|
|
|
|
|
- return data;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Map<String, Object> enablePayscore(Long userId) {
|
|
|
|
|
- User user = userService.getById(userId);
|
|
|
|
|
- if (isPayscoreEnabled(user)) {
|
|
|
|
|
- Map<String, Object> data = new HashMap<>();
|
|
|
|
|
- data.put("enabled", true);
|
|
|
|
|
- data.put("userId", userId);
|
|
|
|
|
- return data;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- String outOrderNo = generatePayscoreOrderNo(userId);
|
|
|
|
|
- Map<String, Object> data = new HashMap<>();
|
|
|
|
|
- data.put("enabled", false);
|
|
|
|
|
- data.put("userId", userId);
|
|
|
|
|
- data.put("outOrderNo", outOrderNo);
|
|
|
|
|
- return data;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
|
|
- public Map<String, Object> confirmEnablePayscore(Long userId, String outOrderNo) {
|
|
|
|
|
- User user = userService.getById(userId);
|
|
|
|
|
- PayScoreResult result = queryPayScoreOrder(outOrderNo);
|
|
|
|
|
-
|
|
|
|
|
- if (result.isSuccess() && "ACCEPTED".equals(result.getState())) {
|
|
|
|
|
- updateUserPayscoreStatus(user);
|
|
|
|
|
- Map<String, Object> data = new HashMap<>();
|
|
|
|
|
- data.put("enabled", true);
|
|
|
|
|
- data.put("userId", userId);
|
|
|
|
|
- return data;
|
|
|
|
|
- }
|
|
|
|
|
- return null; // 开通失败
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public Map<String, Object> createUserPayScoreOrder(Long userId, Long orderId, String openId,
|
|
public Map<String, Object> createUserPayScoreOrder(Long userId, Long orderId, String openId,
|
|
@@ -746,17 +710,6 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
return completeUserPayScoreOrder(userId, orderId, totalAmount, payments, discounts);
|
|
return completeUserPayScoreOrder(userId, orderId, totalAmount, payments, discounts);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
|
|
- public Map<String, Object> confirmUserPayScoreOrder(Long userId, Map<String, Object> params) {
|
|
|
|
|
- if (!params.containsKey("outOrderNo")) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- String outOrderNo = params.get("outOrderNo").toString();
|
|
|
|
|
- return confirmEnablePayscore(userId, outOrderNo);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public Map<String, Object> cancelUserPayScoreOrder(Long userId, Map<String, Object> params) {
|
|
public Map<String, Object> cancelUserPayScoreOrder(Long userId, Map<String, Object> params) {
|
|
@@ -770,20 +723,130 @@ public class PayScoreServiceImpl implements PayScoreService {
|
|
|
return cancelUserPayScoreOrder(userId, orderId, reason);
|
|
return cancelUserPayScoreOrder(userId, orderId, reason);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private boolean isPayscoreEnabled(User user) {
|
|
|
|
|
- return user != null && user.getPayscoreEnabled() != null && user.getPayscoreEnabled() == PAYSCORE_ENABLED;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ @Override
|
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
|
+ public Map<String, Object> preCreatePayScoreOrder(Long userId, String deviceId, String openId) {
|
|
|
|
|
+ log.info("[支付分服务] 预创建服务订单(需确认模式)- userId: {}, deviceId: {}", userId, deviceId);
|
|
|
|
|
+
|
|
|
|
|
+ PayScoreResult checkResult = checkServiceAvailable();
|
|
|
|
|
+ if (checkResult != null) {
|
|
|
|
|
+ Map<String, Object> errorData = new HashMap<>();
|
|
|
|
|
+ errorData.put("success", false);
|
|
|
|
|
+ errorData.put("errorMsg", checkResult.getErrorMsg());
|
|
|
|
|
+ return errorData;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果没有传 openId,从用户表中获取
|
|
|
|
|
+ if (openId == null || openId.isEmpty()) {
|
|
|
|
|
+ User user = userService.getById(userId);
|
|
|
|
|
+ if (user == null || user.getOpenid() == null) {
|
|
|
|
|
+ Map<String, Object> errorData = new HashMap<>();
|
|
|
|
|
+ errorData.put("success", false);
|
|
|
|
|
+ errorData.put("errorMsg", "用户openId未获取,请重新登录");
|
|
|
|
|
+ return errorData;
|
|
|
|
|
+ }
|
|
|
|
|
+ openId = user.getOpenid();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 创建本地预订单(金额为0,识别后回调更新)
|
|
|
|
|
+ Order order = new Order();
|
|
|
|
|
+ order.setUserId(userId);
|
|
|
|
|
+ order.setDeviceId(deviceId);
|
|
|
|
|
+ order.setTotalAmount(BigDecimal.ZERO);
|
|
|
|
|
+ order.setPayChannel(PaymentChannel.WECHAT_PAYSCORE.getCode());
|
|
|
|
|
+ order.setPayType("微信支付分");
|
|
|
|
|
+ order.setStatus(OrderStatus.PENDING_PAYMENT.getCode());
|
|
|
|
|
+ order.setPayStatus(PayStatus.UNPAID.getCode());
|
|
|
|
|
+ orderService.save(order);
|
|
|
|
|
+ log.info("[支付分服务] 预订单已创建 - orderId: {}", order.getId());
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 创建微信支付分服务订单
|
|
|
|
|
+ PayScoreCreateRequest request = new PayScoreCreateRequest();
|
|
|
|
|
+ request.setOutOrderNo(generateOutOrderNo(order.getId()));
|
|
|
|
|
+ request.setServiceIntroduction("智能零售服务");
|
|
|
|
|
+ request.setOpenId(openId);
|
|
|
|
|
+ request.setRiskFundName("DEPOSIT");
|
|
|
|
|
+ request.setRiskFundAmount(DEFAULT_RISK_FUND_AMOUNT);
|
|
|
|
|
+ request.setStartTime("OnAccept");
|
|
|
|
|
+ request.setStartDeviceId(deviceId);
|
|
|
|
|
|
|
|
- private void updateUserPayscoreStatus(User user) {
|
|
|
|
|
- user.setPayscoreEnabled(PAYSCORE_ENABLED);
|
|
|
|
|
- user.setUpdateTime(LocalDateTime.now());
|
|
|
|
|
- boolean updated = userService.updateById(user);
|
|
|
|
|
- if (!updated) {
|
|
|
|
|
- throw new RuntimeException("更新用户状态失败");
|
|
|
|
|
|
|
+ PayScoreResult result = payScoreStrategy.createServiceOrder(request);
|
|
|
|
|
+
|
|
|
|
|
+ if (result.isSuccess()) {
|
|
|
|
|
+ // 更新订单的支付分字段
|
|
|
|
|
+ order.setPayScoreOrderId(result.getOutOrderNo());
|
|
|
|
|
+ order.setPayScoreState(result.getState());
|
|
|
|
|
+ if (wxPayConfig != null) {
|
|
|
|
|
+ order.setServiceId(wxPayConfig.getServiceId());
|
|
|
|
|
+ }
|
|
|
|
|
+ order.setServiceStartTime(LocalDateTime.now());
|
|
|
|
|
+ orderService.updateById(order);
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 将支付分信息存入 Redis,供回调创建订单时关联
|
|
|
|
|
+ if (stringRedisTemplate != null) {
|
|
|
|
|
+ String redisKey = REDIS_KEY_PREFIX + deviceId + ":" + userId;
|
|
|
|
|
+ JSONObject json = new JSONObject();
|
|
|
|
|
+ json.put("payScoreOrderId", result.getOutOrderNo());
|
|
|
|
|
+ json.put("payScoreState", result.getState());
|
|
|
|
|
+ if (wxPayConfig != null) {
|
|
|
|
|
+ json.put("serviceId", wxPayConfig.getServiceId());
|
|
|
|
|
+ }
|
|
|
|
|
+ json.put("orderId", order.getId());
|
|
|
|
|
+ stringRedisTemplate.opsForValue().set(redisKey, json.toJSONString(), REDIS_TTL_MINUTES, TimeUnit.MINUTES);
|
|
|
|
|
+ log.info("[支付分服务] 支付分信息已存入Redis - key: {}, ttl: {}min", redisKey, REDIS_TTL_MINUTES);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> data = new HashMap<>();
|
|
|
|
|
+ data.put("success", true);
|
|
|
|
|
+ data.put("orderId", order.getId());
|
|
|
|
|
+ data.put("outOrderNo", result.getOutOrderNo());
|
|
|
|
|
+ data.put("package", result.getPackageStr());
|
|
|
|
|
+ log.info("[支付分服务] 预创建服务订单成功 - orderId: {}, outOrderNo: {}", order.getId(), result.getOutOrderNo());
|
|
|
|
|
+ return data;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ log.error("[支付分服务] 预创建服务订单失败 - orderId: {}, error: {}", order.getId(), result.getErrorMsg());
|
|
|
|
|
+ Map<String, Object> errorData = new HashMap<>();
|
|
|
|
|
+ errorData.put("success", false);
|
|
|
|
|
+ errorData.put("errorMsg", result.getErrorMsg());
|
|
|
|
|
+ return errorData;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private String generatePayscoreOrderNo(Long userId) {
|
|
|
|
|
- return "PS" + System.currentTimeMillis() + String.format("%04d", userId % 10000);
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 从 Redis 获取预创建的支付分信息并关联到订单
|
|
|
|
|
+ * 由 HahaCallbackServiceImpl 在创建订单后调用
|
|
|
|
|
+ */
|
|
|
|
|
+ public void applyPreAuthPayScore(Order order) {
|
|
|
|
|
+ if (stringRedisTemplate == null || order == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String redisKey = REDIS_KEY_PREFIX + order.getDeviceId() + ":" + order.getUserId();
|
|
|
|
|
+ String jsonStr = stringRedisTemplate.opsForValue().get(redisKey);
|
|
|
|
|
+ if (jsonStr == null) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ JSONObject json = JSON.parseObject(jsonStr);
|
|
|
|
|
+ String payScoreOrderId = json.getString("payScoreOrderId");
|
|
|
|
|
+ String payScoreState = json.getString("payScoreState");
|
|
|
|
|
+ String serviceId = json.getString("serviceId");
|
|
|
|
|
+
|
|
|
|
|
+ if (payScoreOrderId != null) {
|
|
|
|
|
+ order.setPayScoreOrderId(payScoreOrderId);
|
|
|
|
|
+ order.setPayScoreState(payScoreState != null ? payScoreState : PayScoreState.CREATED.getCode());
|
|
|
|
|
+ order.setServiceId(serviceId);
|
|
|
|
|
+ order.setPayChannel(PaymentChannel.WECHAT_PAYSCORE.getCode());
|
|
|
|
|
+ order.setPayType("微信支付分");
|
|
|
|
|
+ orderService.updateById(order);
|
|
|
|
|
+
|
|
|
|
|
+ // 删除 Redis 记录,防止重复使用
|
|
|
|
|
+ stringRedisTemplate.delete(redisKey);
|
|
|
|
|
+ log.info("[支付分服务] 预授权信息已关联到订单 - orderId: {}, payScoreOrderId: {}", order.getId(), payScoreOrderId);
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.error("[支付分服务] 关联预授权信息失败 - orderId: {}", order.getId(), e);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|