skyfffire 3 days ago
parent
commit
188c7ae0aa

+ 4 - 1
.gitignore

@@ -34,4 +34,7 @@ build/
 .vscode/
 
 ### Mac OS ###
-.DS_Store
+.DS_Store
+
+### Claude ###
+.claude/

+ 42 - 42
src/main/java/common/model/base/BaseDeposit.java

@@ -35,95 +35,95 @@ public abstract class BaseDeposit<M extends BaseDeposit<M>> extends Model<M> imp
 		return getLong("user_id");
 	}
 	/**
-	 * 微信解析完成的json原文
+	 * 充值数量
 	 */
-	public void setWxDecrypted(java.lang.String wxDecrypted) {
-		set("wx_decrypted", wxDecrypted);
+	public void setAmount(java.lang.Integer amount) {
+		set("amount", amount);
 	}
 	
 	/**
-	 * 微信解析完成的json原文
+	 * 充值数量
 	 */
-	public java.lang.String getWxDecrypted() {
-		return getStr("wx_decrypted");
+	public java.lang.Integer getAmount() {
+		return getInt("amount");
 	}
 	/**
-	 * 微信回调原文
+	 * 充值记录描述
 	 */
-	public void setWxOriginal(java.lang.String wxOriginal) {
-		set("wx_original", wxOriginal);
+	public void setDescription(java.lang.String description) {
+		set("description", description);
 	}
 	
 	/**
-	 * 微信回调原文
+	 * 充值记录描述
 	 */
-	public java.lang.String getWxOriginal() {
-		return getStr("wx_original");
+	public java.lang.String getDescription() {
+		return getStr("description");
 	}
 	/**
-	 * 微信的充值单号
+	 * 充值记录创建时间
 	 */
-	public void setWxOrderNo(java.lang.String wxOrderNo) {
-		set("wx_order_no", wxOrderNo);
+	public void setCreateTime(java.lang.Long createTime) {
+		set("create_time", createTime);
 	}
 	
 	/**
-	 * 微信的充值单号
+	 * 充值记录创建时间
 	 */
-	public java.lang.String getWxOrderNo() {
-		return getStr("wx_order_no");
+	public java.lang.Long getCreateTime() {
+		return getLong("create_time");
 	}
 	/**
-	 * 微信的回调状态
+	 * 通联订单号
 	 */
-	public void setWxOrderStatus(java.lang.String wxOrderStatus) {
-		set("wx_order_status", wxOrderStatus);
+	public void setTlOrderNo(java.lang.String tlOrderNo) {
+		set("tl_order_no", tlOrderNo);
 	}
 	
 	/**
-	 * 微信的回调状态
+	 * 通联订单号
 	 */
-	public java.lang.String getWxOrderStatus() {
-		return getStr("wx_order_status");
+	public java.lang.String getTlOrderNo() {
+		return getStr("tl_order_no");
 	}
 	/**
-	 * 充值数量
+	 * 通联支付链接
 	 */
-	public void setAmount(java.lang.Integer amount) {
-		set("amount", amount);
+	public void setTlPayUrl(java.lang.String tlPayUrl) {
+		set("tl_pay_url", tlPayUrl);
 	}
 	
 	/**
-	 * 充值数量
+	 * 通联支付链接
 	 */
-	public java.lang.Integer getAmount() {
-		return getInt("amount");
+	public java.lang.String getTlPayUrl() {
+		return getStr("tl_pay_url");
 	}
 	/**
-	 * 充值记录描述
+	 * 通联支付状态
 	 */
-	public void setDescription(java.lang.String description) {
-		set("description", description);
+	public void setTlStatus(java.lang.String tlStatus) {
+		set("tl_status", tlStatus);
 	}
 	
 	/**
-	 * 充值记录描述
+	 * 通联支付状态
 	 */
-	public java.lang.String getDescription() {
-		return getStr("description");
+	public java.lang.String getTlStatus() {
+		return getStr("tl_status");
 	}
 	/**
-	 * 充值记录创建时间
+	 * 通联最后一次查单结果
 	 */
-	public void setCreateTime(java.lang.Long createTime) {
-		set("create_time", createTime);
+	public void setTlLastQueryResult(java.lang.String tlLastQueryResult) {
+		set("tl_last_query_result", tlLastQueryResult);
 	}
 	
 	/**
-	 * 充值记录创建时间
+	 * 通联最后一次查单结果
 	 */
-	public java.lang.Long getCreateTime() {
-		return getLong("create_time");
+	public java.lang.String getTlLastQueryResult() {
+		return getStr("tl_last_query_result");
 	}
 	public void setIsDeleted(java.lang.Integer isDeleted) {
 		set("is_deleted", isDeleted);

+ 1 - 0
src/main/java/common/utils/http/MyRet.java

@@ -9,6 +9,7 @@ public class MyRet extends Ret {
     public static final int CODE_FAILED = 3;            // 一般错误
     public static final int CODE_NO_AUTH = 4;           // 未实名认证
     public static final int CODE_NO_ADDR = 5;           // 未设置默认地址
+    public static final int CODE_NO_MONEY = 6;          // 没有钱请充值
 
     public static MyRet fail(String msg) {
         return new MyRet().setState(false).setCode(CODE_FAILED).setMsg(msg);

+ 227 - 39
src/main/java/modules/deposit/DepositService.java

@@ -1,8 +1,13 @@
 package modules.deposit;
 
+import com.alibaba.fastjson.JSON;
 import com.jfinal.plugin.activerecord.Db;
+import com.jfinal.plugin.activerecord.Record;
 import common.model.Deposit;
+import common.model.User;
+import common.model.BalanceLog;
 import common.utils.http.MyRet;
+import common.utils.tl.AllinpaySDK;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -13,45 +18,228 @@ public class DepositService {
     public String hello() {
         return "Hello deposit";
     }
-    
-    // public MyRet createDepositOrder(Integer amount, String ip, long userId) {
-    //     String notifyUrl = System.getenv("URL_BASE") + "/deposit/deposited";
-    //     String outTradeNo = "DLTBH_WX_" + System.currentTimeMillis() + "_" + userId;
-    //
-    //     // 场景信息
-    //     H5Info h5Info = new H5Info();
-    //     h5Info.setType("Wrp"); // 使用H5支付的场景:Wap、iOS、Android
-    //
-    //     SceneInfo sceneInfo = new SceneInfo();
-    //     sceneInfo.setPayerClientIp(ip);
-    //     sceneInfo.setH5Info(h5Info);
-    //
-    //     // 方便获取报错信息
-    //     try {
-    //         // 获取微信支付订单结果
-    //         PrepayResponse response = prepay(amount, outTradeNo, notifyUrl, sceneInfo);
-    //        
-    //         // 微信支付订单创建成功,创建内部订单
-    //         Deposit deposit = new Deposit();
-    //        
-    //         // put各类参数
-    //         deposit.setUserId(userId);
-    //         deposit.setWxOrderNo(outTradeNo);
-    //         deposit.setAmount(amount);
-    //         deposit.setCreateTime(System.currentTimeMillis());
-    //        
-    //         if (deposit.save()) {
-    //             return MyRet.ok("微信支付订单创建成功").setData(response.getH5Url());
-    //         } else {
-    //             return MyRet.fail("微信支付订单创建失败:Deposit入库失败").setData(deposit);
-    //         }
-    //     } catch (Exception e) {
-    //         return MyRet.fail("微信支付订单创建失败").setData(e.getMessage());
-    //     }
-    // }
-    
-    public Deposit findDepositByWxOrderNo(String wxOrderNo) {
-        return Deposit.dao.findFirst("SELECT * FROM t_deposit WHERE wx_order_no=?", wxOrderNo);
+
+    /**
+     * 创建通联充值订单
+     *
+     * @param amount 充值金额(分)
+     * @param userId 用户ID
+     * @return 充值结果,包含支付链接和订单号
+     */
+    public MyRet createTLDepositOrder(Integer amount, Long userId) {
+        try {
+            // 生成通联订单号
+            String tlOrderNo = "DLTBH_TL_" + System.currentTimeMillis() + "_" + userId;
+
+            // 设置异步通知地址
+            String notifyUrl = System.getenv("URL_BASE") + "/deposit/tl-notify";
+            // 设置同步跳转地址
+            String returnUrl = System.getenv("URL_BASE") + "/deposit/return";
+
+            // 调用通联支付SDK生成H5支付链接
+            AllinpaySDK.PaymentResult payResult = AllinpaySDK.h5Pay(
+                amount.longValue(),           // 交易金额(分)
+                tlOrderNo,                    // 商户订单号
+                "购买大连特别火商品",           // 订单标题
+                (amount / 100.0) + "元", // 订单备注
+                notifyUrl,                    // 异步通知地址
+                returnUrl,                    // 同步跳转地址
+                "UTF-8",                      // 字符编码
+                30,                           // 有效期30分钟
+                null,                         // 支付限制
+                null,                         // 真实姓名
+                null                          // 证件号
+            );
+
+            if (!payResult.isSuccess()) {
+                return MyRet.fail("通联支付订单创建失败").setData(payResult.getMessage());
+            }
+
+            // 创建充值记录
+            Deposit deposit = new Deposit();
+            deposit.setUserId(userId);
+            deposit.setTlOrderNo(tlOrderNo);
+            deposit.setTlPayUrl(payResult.getPayUrl());
+            deposit.setAmount(amount);
+            deposit.setTlStatus("PENDING"); // 初始状态为处理中
+            deposit.setDescription("通联充值订单创建");
+
+            if (deposit.save()) {
+                Map<String, Object> resultData = new HashMap<>();
+                resultData.put("tl_pay_url", payResult.getPayUrl());
+                resultData.put("tl_order_no", tlOrderNo);
+                resultData.put("amount", amount);
+
+                return MyRet.ok("通联支付订单创建成功").setData(resultData);
+            } else {
+                return MyRet.fail("通联支付订单创建失败:充值记录入库失败");
+            }
+
+        } catch (Exception e) {
+            return MyRet.fail("通联支付订单创建失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询通联支付状态并处理充值
+     *
+     * @param tlOrderNo 通联订单号
+     * @return 查询结果
+     */
+    public MyRet queryOrderStatus(String tlOrderNo) {
+        try {
+            // 根据订单号查找充值记录
+            Deposit deposit = findDepositByTLOrderNo(tlOrderNo);
+            if (deposit == null) {
+                return MyRet.fail("充值记录不存在");
+            }
+
+            // 如果已经充值成功,直接返回
+            if ("SUCCESS".equals(deposit.getTlStatus())) {
+                User user = User.dao.findById(deposit.getUserId());
+                Map<String, Object> resultData = new HashMap<>();
+                resultData.put("tl_status", "SUCCESS");
+                resultData.put("balance", user != null ? user.getBalance() : 0);
+                resultData.put("message", "订单已处理完成");
+
+                return MyRet.ok("订单已处理完成").setData(resultData);
+            }
+
+            // 调用通联查单接口
+            AllinpaySDK.QueryResult queryResult = AllinpaySDK.queryPayment(tlOrderNo);
+
+            // 保存查单结果
+            deposit.setTlLastQueryResult(JSON.toJSONString(queryResult));
+
+            if (!queryResult.isSuccess()) {
+                deposit.setTlStatus("QUERY_FAILED");
+                deposit.update();
+                return MyRet.fail("查询通联支付状态失败:" + queryResult.getMessage());
+            }
+
+            // 验证金额一致性
+            Integer queryAmount = Integer.parseInt(queryResult.getTrxamt());
+            if (!queryAmount.equals(deposit.getAmount())) {
+                deposit.setTlStatus("AMOUNT_MISMATCH");
+                deposit.update();
+                return MyRet.fail("金额校验失败:订单金额与实际支付金额不符");
+            }
+
+            // 根据通联返回状态处理
+            String tlStatus = mapTlStatus(queryResult.getTrxstatus());
+
+            if ("SUCCESS".equals(tlStatus)) {
+                // 支付成功,执行充值
+                boolean rechargeResult = addUserBalance(deposit.getUserId(), deposit.getAmount(), tlOrderNo);
+
+                if (rechargeResult) {
+                    deposit.setTlStatus("SUCCESS");
+                    // deposit.setTlTrxId(queryResult.getTrxid());
+                    deposit.setDescription("通联充值成功,交易ID:" + queryResult.getTrxid());
+
+                    // 获取更新后的用户余额
+                    User user = User.dao.findById(deposit.getUserId());
+
+                    Map<String, Object> resultData = new HashMap<>();
+                    resultData.put("tl_status", "SUCCESS");
+                    resultData.put("balance", user != null ? user.getBalance() : 0);
+                    resultData.put("message", "充值成功");
+                    resultData.put("trx_id", queryResult.getTrxid());
+
+                    deposit.update();
+                    return MyRet.ok("充值成功").setData(resultData);
+                } else {
+                    deposit.setTlStatus("RECHARGE_FAILED");
+                    deposit.update();
+                    return MyRet.fail("充值失败:余额更新异常");
+                }
+            } else {
+                // 其他状态,更新状态并返回
+                deposit.setTlStatus(tlStatus);
+                deposit.setDescription("通联支付状态:" + tlStatus + "," + queryResult.getMessage());
+                deposit.update();
+
+                Map<String, Object> resultData = new HashMap<>();
+                resultData.put("tl_status", tlStatus);
+                resultData.put("message", queryResult.getMessage());
+
+                return MyRet.ok("状态更新成功").setData(resultData);
+            }
+
+        } catch (Exception e) {
+            return MyRet.fail("查询支付状态失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据通联订单号查找充值记录
+     */
+    public Deposit findDepositByTLOrderNo(String tlOrderNo) {
+        return Deposit.dao.findFirst("SELECT * FROM t_deposit WHERE tl_order_no=?", tlOrderNo);
+    }
+
+    /**
+     * 用户余额充值
+     *
+     * @param userId 用户ID
+     * @param amount 充值金额(分)
+     * @param tlOrderNo 通联订单号
+     * @return 是否充值成功
+     */
+    public boolean addUserBalance(Long userId, Integer amount, String tlOrderNo) {
+        try {
+            return Db.tx(() -> {
+                // 1. 查询用户信息
+                User user = User.dao.findById(userId);
+                if (user == null) {
+                    return false;
+                }
+
+                // 2. 更新用户余额
+                float oldBalance = user.getBalance();
+                user.setBalance(oldBalance + amount);
+                if (!user.update()) {
+                    return false;
+                }
+
+                // 3. 记录余额变动日志
+                BalanceLog balanceLog = new BalanceLog();
+                balanceLog.setUserId(userId);
+                balanceLog.setAmount(amount); // 正数表示增加
+                balanceLog.setDescription("通联充值成功,订单号:" + tlOrderNo);
+                balanceLog.setCreateTime(System.currentTimeMillis());
+                balanceLog.setIsDeleted(0);
+
+                if (!balanceLog.save()) {
+                    return false;
+                }
+
+                return true;
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * 映射通联支付状态码
+     *
+     * @param trxstatus 通联返回的状态码
+     * @return 标准化状态
+     */
+    private String mapTlStatus(String trxstatus) {
+        if ("0000".equals(trxstatus)) {
+            return "SUCCESS";    // 支付成功
+        } else if ("1001".equals(trxstatus)) {
+            return "FAILED";     // 支付失败
+        } else if ("2001".equals(trxstatus)) {
+            return "PENDING";    // 支付处理中
+        } else if ("2002".equals(trxstatus)) {
+            return "TIMEOUT";    // 支付超时
+        } else {
+            return "PENDING";    // 默认处理中
+        }
     }
     
     public MyRet list(int pageNumber, int pageSize, Long userId) {