30262728@qq.com 2 週間 前
コミット
3e2eeb4f05
100 ファイル変更6880 行追加27 行削除
  1. 0 23
      pom.xml
  2. 7 0
      qnfhq-api/pom.xml
  3. 105 0
      qnfhq-api/src/main/java/com/qnfhq/common/ApiBaseController.java
  4. 32 0
      qnfhq-api/src/main/java/com/qnfhq/config/RedissonConfig.java
  5. 3 3
      qnfhq-api/src/main/java/com/qnfhq/config/SwaggerConfig.java
  6. 159 0
      qnfhq-api/src/main/java/com/qnfhq/constant/CacheConstants.java
  7. 293 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cAdController.java
  8. 92 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cMerchantController.java
  9. 873 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cOrderController.java
  10. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/AppAssetLogDao.java
  11. 32 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cAdDao.java
  12. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cAdLogDao.java
  13. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cLegalCoinDao.java
  14. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMerchantConfigDao.java
  15. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMerchantDao.java
  16. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderComplainDao.java
  17. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderComplainVoucherDao.java
  18. 26 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderDao.java
  19. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderLogDao.java
  20. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cPayWayDao.java
  21. 23 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cPaymentVoucherDao.java
  22. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cUserReceiptDao.java
  23. 60 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/AppAssetLogDTO.java
  24. 27 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdCancelDTO.java
  25. 62 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdCreateDTO.java
  26. 41 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdListDTO.java
  27. 50 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdLogDTO.java
  28. 43 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdTranDTO.java
  29. 52 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdViewDTO.java
  30. 60 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cLegalCoinDTO.java
  31. 35 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantApplyDTO.java
  32. 26 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantCheckDTO.java
  33. 31 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantConfigDTO.java
  34. 94 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantDTO.java
  35. 28 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMyReceiptDTO.java
  36. 32 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainDTO.java
  37. 32 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainDetailDTO.java
  38. 28 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainOidDTO.java
  39. 52 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainVoucherDTO.java
  40. 52 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderCreateDTO.java
  41. 86 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderDTO.java
  42. 28 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderIdDTO.java
  43. 49 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderListDTO.java
  44. 43 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderLogDTO.java
  45. 25 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPayWayDTO.java
  46. 55 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherDTO.java
  47. 28 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherIdDTO.java
  48. 26 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherQryDTO.java
  49. 36 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cUserReceiptDTO.java
  50. 21 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/setting/AdSetting.java
  51. 67 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/AppAssetLogEntity.java
  52. 106 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cAdEntity.java
  53. 58 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cAdLogEntity.java
  54. 70 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cLegalCoinEntity.java
  55. 33 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMerchantConfigEntity.java
  56. 113 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMerchantEntity.java
  57. 73 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderComplainEntity.java
  58. 69 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderComplainVoucherEntity.java
  59. 121 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderEntity.java
  60. 49 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderLogEntity.java
  61. 62 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cPayWayEntity.java
  62. 53 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cPaymentVoucherEntity.java
  63. 45 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cUserReceiptEntity.java
  64. 30 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/AdStatusEnum.java
  65. 31 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/C2cOrderComplainEnum.java
  66. 35 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/C2cOrderFlowEnum.java
  67. 39 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/C2cOrderStatusEnum.java
  68. 36 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/DirectionEnum.java
  69. 31 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MerchantStatusEnum.java
  70. 37 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/AppAssetLogService.java
  71. 20 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cAdLogService.java
  72. 81 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cAdService.java
  73. 19 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cLegalCoinService.java
  74. 22 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMerchantConfigService.java
  75. 29 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMerchantService.java
  76. 24 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderComplainService.java
  77. 18 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderComplainVoucherService.java
  78. 15 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderLogService.java
  79. 144 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderService.java
  80. 23 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cPayWayService.java
  81. 20 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cPaymentVoucherService.java
  82. 27 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cUserReceiptService.java
  83. 57 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/AppAssetLogServiceImpl.java
  84. 53 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cAdLogServiceImpl.java
  85. 597 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cAdServiceImpl.java
  86. 42 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cLegalCoinServiceImpl.java
  87. 46 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMerchantConfigServiceImpl.java
  88. 182 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMerchantServiceImpl.java
  89. 44 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderComplainServiceImpl.java
  90. 44 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderComplainVoucherServiceImpl.java
  91. 35 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderLogServiceImpl.java
  92. 767 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderServiceImpl.java
  93. 45 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cPayWayServiceImpl.java
  94. 52 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cPaymentVoucherServiceImpl.java
  95. 56 0
      qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cUserReceiptServiceImpl.java
  96. 30 1
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dao/AppAssetDao.java
  97. 16 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dao/AppWalletRecordDao.java
  98. 75 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppWalletRecordDTO.java
  99. 87 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/entity/AppWalletRecordEntity.java
  100. 45 0
      qnfhq-api/src/main/java/com/qnfhq/modules/user/enums/AuditStatusEnum.java

+ 0 - 23
pom.xml

@@ -81,29 +81,6 @@
             <groupId>com.mysql</groupId>
             <artifactId>mysql-connector-j</artifactId>
         </dependency>
-        <!-- oracle驱动 -->
-        <dependency>
-            <groupId>com.oracle</groupId>
-            <artifactId>ojdbc6</artifactId>
-            <version>${oracle.version}</version>
-        </dependency>
-        <!-- sqlserver驱动 -->
-        <dependency>
-            <groupId>com.microsoft.sqlserver</groupId>
-            <artifactId>sqljdbc4</artifactId>
-            <version>${sqlserver.version}</version>
-        </dependency>
-        <!-- postgresql驱动 -->
-        <dependency>
-            <groupId>org.postgresql</groupId>
-            <artifactId>postgresql</artifactId>
-        </dependency>
-        <!-- 达梦驱动 -->
-        <dependency>
-            <groupId>com.dameng</groupId>
-            <artifactId>DmJdbcDriver18</artifactId>
-            <version>${dameng.version}</version>
-        </dependency>
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>druid-spring-boot-3-starter</artifactId>

+ 7 - 0
qnfhq-api/pom.xml

@@ -14,6 +14,7 @@
         <mail.version>2.0.2</mail.version>
         <freemarker.version>2.3.34</freemarker.version>
         <aliyun.sms.version>4.1.1</aliyun.sms.version>
+        <redisson.version>3.52.0</redisson.version>
     </properties>
 	<dependencies>
 		<dependency>
@@ -63,6 +64,12 @@
             <artifactId>easy-captcha</artifactId>
             <version>${captcha.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson-spring-boot-starter</artifactId>
+            <version>${redisson.version}</version>
+        </dependency>
 	</dependencies>
 
 	<build>

+ 105 - 0
qnfhq-api/src/main/java/com/qnfhq/common/ApiBaseController.java

@@ -0,0 +1,105 @@
+package com.qnfhq.common;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.common.utils.SpringContextUtils;
+import com.qnfhq.modules.user.entity.AppUserEntity;
+import com.qnfhq.modules.user.service.AppUserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ApiBaseController {
+    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+
+    /**
+     * 获取用户ID
+     * @return
+     */
+    public Long getStpUserId(){
+        return StpUtil.getLoginIdAsLong();
+    }
+    /**
+     * 获取用户ID
+     * @return
+     */
+    public AppUserEntity getAppUser(){
+        long loginIdAsLong = StpUtil.getLoginIdAsLong();
+        AppUserService appUserService = SpringContextUtils.getBean(AppUserService.class);
+        return appUserService.selectById(loginIdAsLong);
+    }
+    /**
+     * 返回成功
+     */
+    public Result success()
+    {
+        return new Result();
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public Result error()
+    {
+        return new Result().error();
+    }
+
+    /**
+     * 返回成功消息
+     */
+    public Result success(String message)
+    {
+        Result result = new Result();
+        result.setMsg(message);
+        return result;
+    }
+
+    /**
+     * 返回成功消息
+     */
+    public Result success(Object data)
+    {
+        return new Result().ok(data);
+    }
+
+    /**
+     * 返回失败消息
+     */
+    public Result error(String message)
+    {
+        return new Result().error(message);
+    }
+
+    /**
+     * 响应返回结果
+     *
+     * @param rows 影响行数
+     * @return 操作结果
+     */
+    protected Result toAjax(int rows)
+    {
+        return rows > 0 ? success() : error();
+    }
+
+    /**
+     * 响应返回结果
+     *
+     * @param result 结果
+     * @return 操作结果
+     */
+    protected Result toAjax(boolean result)
+    {
+        return result ? success() : error();
+    }
+
+    /**
+     * 页面跳转
+     */
+    public String redirect(String url)
+    {
+        return String.format("redirect:{%s}", url);
+    }
+
+
+
+}

+ 32 - 0
qnfhq-api/src/main/java/com/qnfhq/config/RedissonConfig.java

@@ -0,0 +1,32 @@
+package com.qnfhq.config;
+
+import org.redisson.Redisson;
+import org.redisson.api.RedissonClient;
+import org.redisson.config.Config;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class RedissonConfig {
+
+    @Value("${spring.redis.host:127.0.0.1}")
+    private String host;
+
+    @Value("${spring.redis.port:6379}")
+    private int port;
+
+    // 如果有密码再加,没密码别加,redisson会报错
+    // @Value("${spring.redis.password}")
+    // private String password;
+
+    @Bean(destroyMethod = "shutdown")
+    public RedissonClient redissonClient() {
+        Config config = new Config();
+        config.useSingleServer()
+              .setAddress("redis://" + host + ":" + port)
+              // .setPassword(password)
+              .setDatabase(0);
+        return Redisson.create(config);
+    }
+}

+ 3 - 3
qnfhq-api/src/main/java/com/qnfhq/config/SwaggerConfig.java

@@ -22,9 +22,9 @@ public class SwaggerConfig {
 
     private Info apiInfo() {
         return new Info()
-                .title("区块链")
-                .description("qnfhq-api文档")
-                .version("5.x");
+                .title("区块链改造")
+                .description("接口文档")
+                .version("v1.0.0");
     }
 
     private List<SecurityRequirement> security() {

+ 159 - 0
qnfhq-api/src/main/java/com/qnfhq/constant/CacheConstants.java

@@ -0,0 +1,159 @@
+package com.qnfhq.constant;
+
+import java.math.BigDecimal;
+
+/**
+ * 缓存的key 常量
+ *
+ * @author table
+ */
+public class CacheConstants
+{
+    /**
+     * 登录用户 redis key
+     */
+//    public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+    /**
+     * 验证码 redis key
+     */
+//    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+    /**
+     * 参数管理 cache key
+     */
+//    public static final String SYS_CONFIG_KEY = "sys_config:";
+
+    /**
+     * 字典管理 cache key
+     */
+//    public static final String SYS_DICT_KEY = "sys_dict:";
+
+    /**
+     * 防重提交 redis key
+     */
+//    public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+    /**
+     * 限流 redis key
+     */
+//    public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+    /**
+     * 登录账户密码错误次数 redis key
+     */
+//    public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+
+    /**
+     * 验证码失效时间
+     */
+//    public static final int REGISTER_CODE_TIME = 5* 60;
+    /**
+     * 充值次数
+     */
+//    public static final String WITHDRAW = "withdraw:";
+    /**
+     * 充值消息KEY
+     */
+//    public static final String WITHDRAW_KEY = "withdraw_key";
+    /**
+     * 提现消息KEY
+//     */
+//    public static final String RECHARGE_KEY = "recharge_key";
+    /**
+     * 实名认证消息KEY
+     */
+//    public static final String VERIFIED_KEY = "verified_key";
+
+    /**
+     * 充值消息KEY
+     */
+//    public static final String WITHDRAW_KEY_BOT = "withdraw_key_bot";
+    /**
+     * 提现消息KEY
+     */
+//    public static final String RECHARGE_KEY_BOT = "recharge_key_bot";
+
+    /**
+     * C2C订单超时时间 30分钟
+      */
+    public static final Integer C2C_ORDER_EXPIRE_MIN = 30;
+
+    /**
+     * 法币列表
+     */
+    public static final String C2C_LEGAL_COIN_LIST ="currency_legal_coin_list";
+    /**
+     * 支付方式列表
+     */
+    public static final String C2C_LEGAL_PAYWAY_LIST ="currency_legal_payway_list";
+
+    /**
+     * 用户进行中的订单号
+     * @param uid
+     * @return
+     */
+    public static String getC2cOrderKeyByUid(String uid) {
+        return new StringBuilder("c2c_order_uid:").append(uid).toString();
+    }
+
+    /**
+     * C2C广告HASH Key
+     */
+    public static String getC2cAdHKey(String adId) {
+        return new StringBuilder("c2c_ad_h").append(adId).toString();
+    }
+
+//    /**
+//     * 用户待支付数
+//     */
+//    public static final String C2C_UNPAY_COUNTS ="c2c-unpay-counts:{}";
+//
+//    /**
+//     * 用户待放币订单数
+//     */
+//    public static final String C2C_RELEASE_COUNTS ="c2c-release-counts:{}";
+//
+//    /**
+//     * 商家待支付数统计
+//     */
+    public static String getC2cMertUnPayKey(String mertUid) {
+        return new StringBuilder("c2c-mtunpay-counts:").append(mertUid).toString();
+    }
+
+
+    /**
+     * 商家待放币订单数统计
+     */
+    public static String getC2cMertUnReleaseKey(String mertUid) {
+        return new StringBuilder("c2c-mtrelease-counts:").append(mertUid).toString();
+    }
+
+
+
+//    public static final BigDecimal AD_AVAIL_NUM_TOINT = new BigDecimal(100000000);
+//
+//    /**
+//     * 客服按会话数排序
+//     */
+//    public static final String KEFU_ZSET_KEY = "kefu_uids";
+//
+//    /**
+//     * 客服对应的会话
+//     */
+//    public static final String KEFU_SESSION_KEY = "session_";
+//
+//    /**
+//     * 客服信息
+//     */
+//    public static final String KEFU_INFO_KEY = "kefu_info_";
+//
+//    /**
+//     * 排队等待的用户
+//     */
+//    public static final String ONLINE_CUST_UID = "kefu_wait_uid";
+//    /**
+//     * 聊天的用户id
+//     */
+//    public static final String KEFU_UID_KEY = "im_uid_";
+}

+ 293 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cAdController.java

@@ -0,0 +1,293 @@
+package com.qnfhq.modules.c2c.controller;
+
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.json.JSONUtil;
+import com.qnfhq.common.ApiBaseController;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.common.validator.ValidatorUtils;
+import com.qnfhq.constant.CacheConstants;
+import com.qnfhq.modules.c2c.dto.*;
+import com.qnfhq.modules.c2c.dto.setting.AdSetting;
+import com.qnfhq.modules.c2c.entity.*;
+import com.qnfhq.modules.c2c.enums.DirectionEnum;
+import com.qnfhq.modules.c2c.service.*;
+import com.qnfhq.modules.user.entity.SettingEntity;
+import com.qnfhq.modules.user.enums.SettingEnum;
+import com.qnfhq.modules.user.service.SettingService;
+import jakarta.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.bind.annotation.*;
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@RestController
+@RequestMapping("/c2cad")
+@Tag(name="c2c商家广告")
+public class C2cAdController extends ApiBaseController {
+    @Resource
+    private C2cAdService c2cAdService;
+
+    @Resource
+    private C2cOrderService c2cOrderService;
+
+
+    @Resource
+    private RedisUtils redisUtils;
+
+    @Resource
+    private SettingService settingService;
+
+    @Resource
+    private C2cUserReceiptService c2cUserReceiptService;
+
+    @Autowired
+    private C2cLegalCoinService c2cLegalCoinService;
+
+    @Autowired
+    private C2cPayWayService c2cPayWayService;
+
+    @PostMapping("/create")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result create(@RequestBody C2cAdCreateDTO request) {
+        ValidatorUtils.validateEntity(request);
+
+        Result result = new Result();
+        Integer direction = request.getDirection();
+        if(!DirectionEnum.isValidCode(direction)) {
+            return result.error(MessageUtils.message("merchant.param.direction.invalid"));//参数direction值不正确
+        }
+        String symbol = request.getSymbol().toLowerCase();
+        String legalCoin = request.getLegalCoin().toUpperCase();
+        Integer priceType = request.getPriceType();
+        BigDecimal price = request.getPrice();//价格
+        BigDecimal num = request.getNum();//买入/卖出数量
+        BigDecimal minAmount = request.getMinAmount();
+        BigDecimal maxAmount = request.getMaxAmount();
+        String payway = request.getPayway().trim();
+
+        if(minAmount.compareTo(BigDecimal.ZERO)<=0) {
+            return result.error(MessageUtils.message("merchant.ad.minAmount.bigger.zero"));//最小限额必须大于0
+        }
+        if(maxAmount.compareTo(minAmount)<=0) {
+            return result.error(MessageUtils.message("merchant.minAmount.smaller.maxAmount"));//最小限额必须小于最大限额
+        }
+        if(num.compareTo(BigDecimal.ZERO) < 1) {
+            return result.error(MessageUtils.message("merchant.num.bigger.zero"));//数量必须大于0
+        }
+        if(price.compareTo(BigDecimal.ZERO) < 1) {
+            return result.error(MessageUtils.message("merchant.price.bigger.zero"));//价格必须大于0
+        }
+        if(maxAmount.compareTo(price.multiply(num)) == 1) {
+            return result.error(MessageUtils.message("merchant.maxAmount.smaller.price.num"));//最大限额必须小于价格和数量之积
+        }
+
+        //广告配置
+        SettingEntity setting = settingService.getSetting(SettingEnum.AD_SETTING.name());
+        List<AdSetting> adSettingsList = JSONUtil.toList(JSONUtil.parseArray(setting.getSettingValue()), AdSetting.class);
+        if (!CollectionUtils.isEmpty(adSettingsList)) {
+            Map<String, List<AdSetting>> symbolGroup = adSettingsList.stream().collect(Collectors.groupingBy(AdSetting::getSymbol));
+            List<AdSetting> symbolSettingList = symbolGroup.get(symbol);
+            AdSetting adSet = null;
+            for(AdSetting adSetting : symbolSettingList) {
+                if(adSetting.getLegalCoin().equals(legalCoin)) {
+                    adSet = adSetting;
+                    break;
+                }
+            }
+            if(adSet != null) {
+                if(price.compareTo(adSet.getMinPrice())==-1) {
+                    return result.error(MessageUtils.message("c2cAd.price.must.bigger.set",adSet.getMinPrice()));//价格必须大于{}
+                } else if (price.compareTo(adSet.getMaxPrice())==1) {
+                    return result.error(MessageUtils.message("c2cAd.price.must.small.set",adSet.getMaxPrice()));//价格必须小于{}
+                }
+                if(minAmount.compareTo(adSet.getMinAmount())==1) {
+                    return result.error(MessageUtils.message("c2cAd.minAmount.must.bigger.set",adSet.getMinAmount()));//最小限额必须大于{}
+                }
+                if(maxAmount.compareTo(adSet.getMaxAmount())==1) {
+                    return result.error(MessageUtils.message("c2cAd.maxAmount.must.small.set",adSet.getMaxAmount()));//最大限额必须小于{}
+                }
+            }
+        }
+
+        try {
+            long loginId = StpUtil.getLoginIdAsLong();
+            return c2cAdService.createAd(request,loginId);
+        } catch (Exception e) {
+            return result.error(e.getMessage());
+        }
+    }
+
+    /**
+     * 商家取消广告
+     * @param c2cAd
+     * @return
+     */
+    @PostMapping("/cancel")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result cancel(@RequestBody C2cAdCancelDTO c2cAd) {
+        ValidatorUtils.validateEntity(c2cAd);
+
+        if(c2cAd.getId()==null) {
+            return error(MessageUtils.message("c2c.ad.id.blank"));//广告编号不能空
+        }
+
+        Long adId = c2cAd.getId();
+        C2cAdEntity ad = c2cAdService.selectById(adId);
+        if(ad==null) {
+            return error(MessageUtils.message("c2c.ad.id.invalid"));//广告编号无效
+        }
+        if(ad.getUserId().longValue() != StpUtil.getLoginIdAsLong()) {
+            return error(MessageUtils.message("c2c.ad.cannot.cancel"));//您无权取消,您不是广告方
+        }
+
+        C2cOrderEntity c2cOrder = c2cOrderService.getTradingByAdId(adId);
+        if(c2cOrder!=null) {
+            return error(MessageUtils.message("c2c.ad.exist.order.cancel"));//当前广告存在进行中的订单,无法取消
+        }
+
+        try {
+            return c2cAdService.cancelAd(ad);
+        } catch (Exception e) {
+            return error(e.getMessage());
+        }
+    }
+
+
+    /**
+     * 商家主页广告列表
+     * @param c2cAdVo
+     * @return
+     */
+    @PostMapping("/list")
+    public Result list(@RequestBody C2cAdListDTO c2cAdVo) {
+        ValidatorUtils.validateEntity(c2cAdVo);
+
+        if(c2cAdVo.getMerchantId()==null) {
+            return error(MessageUtils.message("c2c.ad.merchant.id.blank"));//商家编号不能空
+        }
+        //分页
+        Integer pageNum = Convert.toInt(c2cAdVo.getPageNum(),1);
+        Integer pageSize = Convert.toInt(c2cAdVo.getPageSize(),10);
+        Map<String,Object> params = new HashMap<>();
+        params.put(Constant.PAGE,pageNum);
+        params.put(Constant.LIMIT,pageSize);
+        params.put("merchantId",c2cAdVo.getMerchantId());
+        params.put("direction",c2cAdVo.getDirection());
+        params.put("status",c2cAdVo.getStatus());
+        PageData<C2cAdEntity> page = c2cAdService.page(params);
+        return new Result<PageData<C2cAdEntity>>().ok(page);
+    }
+
+
+
+    /**
+     * 查询我的收款信息列表
+     */
+    @PostMapping("/myReceipt")
+    public Result myReceipt(@RequestBody C2cMyReceiptDTO dto)
+    {
+        dto.setUserId(StpUtil.getLoginIdAsLong());
+        List<C2cUserReceiptEntity> list = c2cUserReceiptService.selectListMyReceipt(dto);
+        return success(list);
+    }
+
+    /**
+     * 新增用户收款信息
+     */
+    @PostMapping("/addReceipt")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result addReceipt(@RequestBody C2cUserReceiptDTO dto)
+    {
+        ValidatorUtils.validateEntity(dto);
+
+        C2cUserReceiptEntity inReceipt = new C2cUserReceiptEntity();
+        inReceipt.setUserId(StpUtil.getLoginIdAsLong());
+        inReceipt.setType(dto.getType());
+        inReceipt.setInfo(dto.getInfo());
+
+        if(dto.getId()==null) {
+            C2cUserReceiptEntity myReceipt = c2cUserReceiptService.selectOneMyReceipt(StpUtil.getLoginIdAsLong(),dto.getType());
+            if(Objects.isNull(myReceipt)) {
+                inReceipt.setCreateTime(new Date());
+                inReceipt.setUpdateTime(new Date());
+                return toAjax(c2cUserReceiptService.insert(inReceipt));
+            } else {
+                return error(MessageUtils.message("c2c.userReceipt.add.repeat"));//添加成功,请勿重复提交
+            }
+        } else {
+            inReceipt.setId(dto.getId());
+            return toAjax(c2cUserReceiptService.updateById(inReceipt));
+        }
+
+    }
+
+
+    /**
+     * 快捷交易,查询广告
+     * @param tranDTO
+     * @return
+     */
+    @PostMapping("/queryTranAd")
+    public Result queryTranAd(@RequestBody C2cAdTranDTO tranDTO)
+    {
+        ValidatorUtils.validateEntity(tranDTO);
+        return c2cAdService.queryTranAd(tranDTO);
+    }
+
+
+    /**
+     * 用户浏览广告
+     * @param tranDTO
+     * @return
+     */
+    @PostMapping("/viewList")
+    public Result viewList(@RequestBody C2cAdViewDTO viewDTO) {
+        ValidatorUtils.validateEntity(viewDTO);
+        return c2cAdService.selectC2cAdViewList(viewDTO);
+    }
+
+    /**
+     * 获取法币列表
+     */
+    @PostMapping("/getLegalCoinList")
+    public Result getLegalCoinList() {
+        Object cacheObject = redisUtils.get(CacheConstants.C2C_LEGAL_COIN_LIST);
+        if(null != cacheObject) {
+            return new Result().ok(cacheObject);
+        }
+        List<C2cLegalCoinEntity> coinList = c2cLegalCoinService.selectAllList();
+        redisUtils.set(CacheConstants.C2C_LEGAL_COIN_LIST,coinList,2*3600);
+        return new Result().ok(coinList);
+    }
+
+    /**
+     * 查询支付方式列表
+     */
+    @PostMapping("/getPaywayList")
+    public Result getPaywayList(@RequestBody C2cPayWayDTO dto) {
+        ValidatorUtils.validateEntity(dto);
+        Object cacheObject = redisUtils.get(CacheConstants.C2C_LEGAL_PAYWAY_LIST);
+        if(null != cacheObject) {
+            return new Result().ok(cacheObject);
+        }
+        List<C2cPayWayEntity> paywayList = c2cPayWayService.selectListByLegalCoin("");
+        redisUtils.set(CacheConstants.C2C_LEGAL_PAYWAY_LIST,paywayList,2*3600);
+        return new Result().ok(paywayList);
+    }
+
+}

+ 92 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cMerchantController.java

@@ -0,0 +1,92 @@
+package com.qnfhq.modules.c2c.controller;
+
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.map.MapUtil;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.common.validator.ValidatorUtils;
+import com.qnfhq.modules.c2c.dto.C2cMerchantApplyDTO;
+import com.qnfhq.modules.c2c.dto.C2cMerchantCheckDTO;
+import com.qnfhq.modules.c2c.entity.C2cMerchantConfigEntity;
+import com.qnfhq.modules.c2c.entity.C2cMerchantEntity;
+import com.qnfhq.modules.c2c.service.C2cMerchantConfigService;
+import com.qnfhq.modules.c2c.service.C2cMerchantService;
+import com.qnfhq.modules.c2c.service.C2cOrderService;
+import jakarta.annotation.Resource;
+import org.springframework.web.bind.annotation.*;
+import java.math.BigDecimal;
+import java.util.Map;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+/**
+ * C2C认证商家
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@RestController
+@RequestMapping("/merchant")
+@Tag(name="C2C认证商家表")
+public class C2cMerchantController {
+
+    @Resource
+    private C2cMerchantService c2cMerchantService;
+
+    @Resource
+    private C2cOrderService c2cOrderService;
+
+    @Resource
+    private C2cMerchantConfigService c2cMerchantConfigService;
+
+    @Operation(summary = "检查c2c商家申请条件")
+    @PostMapping("/checkApply")
+    public Result checkApply(@RequestBody C2cMerchantCheckDTO appUserMerchant) {
+        ValidatorUtils.validateEntity(appUserMerchant);
+
+        Result result = new Result();
+        //查冻结保证金
+        C2cMerchantConfigEntity merchantConfig = c2cMerchantConfigService.getMerchantConfig(appUserMerchant.getLegalCoin().toUpperCase());
+        if(merchantConfig==null) {
+            return result.error(MessageUtils.message("c2c.merchant.apply.not.config"));//未配置认证商家保证金
+        }
+        Integer marginL = merchantConfig.getMargin();
+        BigDecimal margin = new BigDecimal(marginL);
+
+        Map<String, Object> data = c2cMerchantService.checkApply(margin, StpUtil.getLoginIdAsLong());
+        return result.ok(data);
+    }
+
+    @Operation(summary = "c2c商户申请")
+    @PostMapping("/apply")
+    public Result apply(@RequestBody C2cMerchantApplyDTO appUserMerchant) {
+        c2cMerchantService.apply(appUserMerchant,StpUtil.getLoginIdAsLong());
+        return new Result();
+    }
+
+    /**
+     * 查看商家主页与详情
+     */
+    @GetMapping(value = "/info/{id}")
+    public Result getInfo(@PathVariable("id") Long id)
+    {
+        C2cMerchantEntity merchant = c2cMerchantService.selectById(id);
+        return new Result().ok(merchant);
+    }
+
+    /**
+     * 查询自己是否商户
+     * @return
+     */
+    @GetMapping(value = "/myinfo")
+    public Result myinfo()
+    {
+        C2cMerchantEntity merchant = c2cMerchantService.getMerchantEntity(StpUtil.getLoginIdAsLong());
+        Map<String,Object> data = MapUtil.of("merchant",merchant);
+        data.put("isMt",merchant == null ? 0 : 1);
+        return new Result().ok(data);
+    }
+
+
+}

+ 873 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/controller/C2cOrderController.java

@@ -0,0 +1,873 @@
+package com.qnfhq.modules.c2c.controller;
+
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
+import com.qnfhq.common.ApiBaseController;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.exception.ErrorCode;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.common.validator.ValidatorUtils;
+import com.qnfhq.constant.CacheConstants;
+import com.qnfhq.modules.c2c.dto.*;
+import com.qnfhq.modules.c2c.entity.*;
+import com.qnfhq.modules.c2c.enums.AdStatusEnum;
+import com.qnfhq.modules.c2c.enums.C2cOrderFlowEnum;
+import com.qnfhq.modules.c2c.enums.C2cOrderStatusEnum;
+import com.qnfhq.modules.c2c.enums.DirectionEnum;
+import com.qnfhq.modules.c2c.service.*;
+import com.qnfhq.modules.user.entity.AppAssetEntity;
+import com.qnfhq.modules.user.entity.AppUserDetailEntity;
+import com.qnfhq.modules.user.enums.AssetEnum;
+import com.qnfhq.modules.user.enums.AuditStatusEnum;
+import com.qnfhq.modules.user.service.AppAssetService;
+import com.qnfhq.modules.user.service.AppUserDetailService;
+import com.qnfhq.utils.DistributedRedisLock;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Slf4j
+@RestController
+@RequestMapping("user/c2corder")
+@Tag(name="c2c订单")
+public class C2cOrderController extends ApiBaseController {
+    @Resource
+    private C2cOrderService c2cOrderService;
+
+    @Resource
+    private AppUserDetailService appUserDetailService;
+
+    @Resource
+    private AppAssetService appAssetService;
+
+    @Resource
+    private C2cAdService c2cAdService;
+
+    @Resource
+    private C2cPaymentVoucherService c2cPaymentVoucherService;
+
+    private final static String LOCK_C2C_ORDER = "lock_c2c_order";
+    private final static String LOCK_C2C_AD = "lock_c2c_ad:";
+    @Resource
+    private RedisUtils redisUtils;
+
+    @Resource
+    private DistributedRedisLock distributedRedisLock;
+    @Autowired
+    private C2cUserReceiptService c2cUserReceiptService;
+
+    @Resource
+    private C2cOrderComplainService orderComplainService;
+
+    @Resource
+    private C2cOrderComplainVoucherService orderComplainVoucherService;
+
+
+
+    private String getC2cAdLockKey(String adId) {
+        return new StringBuilder(LOCK_C2C_AD).append(adId).toString();
+    }
+
+    private String getC2cOrderLockKey(String oId) {
+        return new StringBuilder(LOCK_C2C_ORDER).append(oId).toString();
+    }
+
+    /**
+     * 下单,
+     * 1 判断用户是有进行中的订单, 缓存时间24小时, 完成订单才能继续下单
+     * 2 校验入参
+     * 3 校验广告可用
+     * 4 实名认证
+     * @param c2cOrder
+     * @return
+     */
+    @PostMapping("/create")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result create(@RequestBody C2cOrderCreateDTO c2cOrder) {
+        Result result = new Result();
+        ValidatorUtils.validateEntity(c2cOrder);
+
+        String odUserKey = c2cOrderService.getC2cOrderKeyByUid(StpUtil.getLoginIdAsString());//c2c_order_uid:1
+        String orderId = (String)redisUtils.get(odUserKey);
+        if(StrUtil.isNotBlank(orderId)) {
+            //判断订单状态
+            C2cOrderEntity order = c2cOrderService.selectOrder(Long.valueOf(orderId));
+            if(order == null) {//订单编号无效
+                c2cOrderService.deleteOrderCache(orderId, StpUtil.getLoginIdAsString());
+            } else {
+                if(order.getFlow().intValue() == C2cOrderFlowEnum.PROGRESS.getCode().intValue()) {
+                    return result.error(ErrorCode.C2C_ORDER_PROCESS, MessageUtils.message("c2c.order.create.tran.fail"));//您有一笔正在进行中的交易,请先处理。处理完成后,可继续交易。
+                } else {
+                    c2cOrderService.deleteOrderCache(orderId, StpUtil.getLoginIdAsString());
+                }
+            }
+        }
+
+        Integer direction = c2cOrder.getDirection();
+        if(!DirectionEnum.isValidCode(direction.intValue())) {
+            return result.error(MessageUtils.message("merchant.param.direction.invalid"));//参数direction值不正确
+        }
+
+
+        //实名认证
+        long loginUserId = StpUtil.getLoginIdAsLong();
+        AppUserDetailEntity appUserDetail = appUserDetailService.selectAppUserDetailByUserId(loginUserId);
+        if(appUserDetail==null || appUserDetail.getAuditStatus().intValue() == AuditStatusEnum.EXAMINATION_PASSED.getCode().intValue()) {
+            return result.error(ErrorCode.SHIMING_VERIFY,MessageUtils.message("user.authentication.not.certified"));//请先进行实名认证
+        }
+
+        //卖出检查资产
+        if(direction.intValue() == DirectionEnum.SELL.getCode().intValue()) {
+            AppAssetEntity tAppAsset = new AppAssetEntity();
+            tAppAsset.setUserId(loginUserId);
+            tAppAsset.setSymbol(c2cOrder.getSymbol());
+            tAppAsset.setType(AssetEnum.PLATFORM_ASSETS.getCode());
+            List<AppAssetEntity> assetList = appAssetService.selectList(tAppAsset);
+            AppAssetEntity sellerAsset = assetList.get(0);
+            if(sellerAsset.getAvailable().compareTo(c2cOrder.getTranAmount())==-1) {
+                return error(MessageUtils.message("c2c.order.availableAmount.insufficient"));//您的可用资产必须大于卖出数量
+            }
+        }
+
+        C2cAdEntity c2cAd = c2cAdService.selectById(c2cOrder.getC2cAdId());
+        if(c2cAd==null) {
+            //清除缓存
+            Integer adDirection = direction.intValue() == DirectionEnum.SELL.getCode().intValue() ? DirectionEnum.BUY.getCode() : DirectionEnum.SELL.getCode();
+            c2cAdService.deleteAdCache(c2cOrder.getC2cAdId(), c2cOrder.getPayType().toString(), c2cOrder.getLegalCoin(), c2cOrder.getSymbol(), adDirection);
+            return error(MessageUtils.message("c2c.order.param.adid"));//广告编号无效
+        }
+        if(c2cAd.getStatus().intValue()== AdStatusEnum.NOPASS.getCode()) {
+            //清除缓存
+            Integer adDirection = c2cAd.getDirection();
+            String adLegalCoin = c2cAd.getLegalCoin();
+            String adSymbol = c2cAd.getSymbol();
+            String adPayway = c2cAd.getPayway().replaceAll("^,|,$", "");
+            c2cAdService.deleteAdCache(c2cAd.getId(), adPayway, adLegalCoin, adSymbol, adDirection);
+            return error(MessageUtils.message("c2c.order.param.adid.invalid"));//广告已不可用
+        }
+
+        BigDecimal availableNum = c2cAd.getAvailableNum();
+        BigDecimal minAmount = c2cAd.getMinAmount();
+        BigDecimal maxAmount = c2cAd.getMaxAmount();
+        BigDecimal price = c2cAd.getPrice();
+
+        BigDecimal adMinBuyNum = minAmount.divide(price,2,BigDecimal.ROUND_DOWN);
+        if(availableNum.compareTo(adMinBuyNum)==-1) {
+            c2cAdService.updateC2cAdDisabled(c2cAd);
+            return error(MessageUtils.message("c2c.order.param.adid.invalid"));//广告已不可用
+        }
+
+        if(c2cAdService.selectAdFromRedis(c2cOrder.getC2cAdId())==null) {
+            c2cAdService.setAdCache(c2cAd);
+        }
+        //买入对应广告卖出
+        if(direction.intValue() == c2cAd.getDirection().intValue()) {
+            return error(MessageUtils.message("c2c.order.direction.invalid"));//参数direction值不正确
+        }
+        if(c2cAd.getUserId().longValue() == loginUserId) {
+            return error(MessageUtils.message("c2c.order.buyer.seller.must.different"));//买家和卖家不能是同一个用户
+        }
+
+        //交易币的数量 保留8位
+        String tranBy = c2cOrder.getTranBy();
+        BigDecimal tranAmount = c2cOrder.getTranAmount();
+        BigDecimal symbolNum = BigDecimal.ZERO;
+        if("amt".equals(tranBy)) {//按金额
+            symbolNum = tranAmount.divide(price,8, RoundingMode.DOWN);
+            tranAmount = tranAmount.setScale(2, RoundingMode.DOWN);
+        } else {//按数量
+            //用户卖出
+            symbolNum = tranAmount.setScale(8, RoundingMode.DOWN);
+            tranAmount = symbolNum.multiply(price).setScale(2, RoundingMode.DOWN);
+        }
+
+        if (tranAmount.compareTo(minAmount) == -1) {
+            return error(MessageUtils.message("c2c.order.param.tranAmt.min"));//金额必须大于最小限额
+        }
+        if (tranAmount.compareTo(maxAmount) == 1) {
+            return error(MessageUtils.message("c2c.order.param.tranAmt.max"));//金额必须小于最大限额
+        }
+        if(symbolNum.compareTo(availableNum)==1) {
+            return error(MessageUtils.message("c2c.order.param.tranAmt.max"));//交易金额超过最大限额
+        }
+
+        //获取锁对象
+        String lockKey = getC2cAdLockKey(c2cOrder.getC2cAdId().toString());
+        if (distributedRedisLock.lock(lockKey)) {
+            try {
+                return c2cOrderService.createC2cOrder(c2cOrder, c2cAd, symbolNum, loginUserId, appUserDetail.getRealName());
+            } catch (Exception e) {
+                log.error("createC2cOrder,{},{},{}",loginUserId,c2cOrder.getC2cAdId(),e.getMessage());
+                return error(e.getMessage());
+            } finally {
+                distributedRedisLock.unlock(lockKey);
+            }
+        }
+        return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+    }
+
+    /**
+     * 买家查询我的订单信息 (进行中的)
+     */
+    @PostMapping("/myOrder")
+    public Result myOrder()
+    {
+        String odUserKey = CacheConstants.getC2cOrderKeyByUid(StpUtil.getLoginIdAsString());
+        String orderId = (String)redisUtils.get(odUserKey);
+        if(StrUtil.isNotEmpty(orderId)) {
+            C2cOrderEntity order = c2cOrderService.selectOrder(Long.valueOf(orderId));
+            if(order==null) {
+                return error("未找到进行中的交易");
+            }
+            //查卖家的收款信息
+            Long sellUserId = null;
+            if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+                sellUserId = order.getTranUserId();
+            } else {
+                sellUserId = order.getUserId();
+            }
+            C2cUserReceiptEntity receipt = c2cUserReceiptService.selectOneMyReceipt(sellUserId,order.getPayType());
+            order.setReceiptInfo(receipt);
+            return success(order);
+        }
+        return error("未找到进行中的交易");
+
+    }
+
+    /**
+     * 用户取消订单:
+     * 已结束订单,申诉订单不能取消
+     * 用户买入: 用户未付款,已付款都可以取消
+     * 用户卖出: 商家已付款,用户不能取消
+     */
+    @PostMapping("/cancelOrder")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result cancelOrder(@RequestBody C2cOrderIdDTO dto)
+    {
+        ValidatorUtils.validateEntity(dto);
+
+        C2cOrderEntity order = c2cOrderService.selectOrder(dto.getId());
+        if(order == null) {
+            return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
+        }
+
+        if(order.getFlow().intValue() == C2cOrderFlowEnum.END.getCode().intValue()) {
+            return error(MessageUtils.message("c2c.order.status.end.not.cancel"));//订单已结束不能取消
+        }
+
+        if(order.getStatus().intValue() == C2cOrderStatusEnum.COMPLAIN.getCode().intValue()) {
+            return error(MessageUtils.message("c2c.order.complain.not.cancel"));//订单申诉中不能取消
+        }
+
+        //用户卖出对方已付款
+        if(order.getDirection().intValue() == DirectionEnum.SELL.getCode().intValue()) {
+            if(order.getStatus().intValue() == C2cOrderStatusEnum.PAY.getCode().intValue()) {
+                return error(MessageUtils.message("c2c.order.sell.payed.not.cancel"));//卖出订单已付款不能取消
+            }
+        }
+
+        String lockKey = getC2cOrderLockKey(order.getId().toString());
+        if (distributedRedisLock.lock(lockKey)) {
+            int oldStatus = order.getStatus().intValue();
+            try {
+                order.setRemark("用户主动取消订单");
+                c2cOrderService.cancelC2cOrder(order, StpUtil.getLoginIdAsLong());
+            } catch (Exception e) {
+                log.error("cancelOrder,{},{}",order.getId(),e.getMessage());
+                return error("取消订单失败");
+            } finally {
+                distributedRedisLock.unlock(lockKey);
+            }
+            c2cOrderService.cancelC2cOrderRedis(oldStatus, order);
+            return success();
+        }
+        return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+    }
+
+    /**
+     * 统计某个用户当天订单取消次数
+     */
+//    private void setUserCancelCount() {
+//        String keyCache = StringUtils.format("c2c-o-cancel-count:{}:{}", StpUtil.getLoginIdAsString(),DateUtils.getDate());
+//        if(StringUtils.isNotNull(redisCache.getCacheObject(keyCache))) {
+//            redisCache.increment(keyCache,1L);
+//        } else {
+//            redisCache.setCacheObject(keyCache, 1, 24, TimeUnit.HOURS);
+//        }
+//    }
+
+    /**
+     * 点击我已完成付款通知卖家 sendMessage
+     */
+    @PostMapping("/confirmPay")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result confirmPay(@RequestBody C2cOrderIdDTO dto)
+    {
+        ValidatorUtils.validateEntity(dto);
+
+        C2cOrderEntity order = c2cOrderService.selectOrder(dto.getId());
+        if(order == null) {
+            return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
+        }
+
+        long loginId = StpUtil.getLoginIdAsLong();
+        Long buyUserId  = null;
+        if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            buyUserId = order.getUserId();
+        } else {
+            buyUserId = order.getTranUserId();
+        }
+        if(buyUserId.longValue()!=loginId) {
+            return error(MessageUtils.message("c2c.order.pay.not.buyer"));//您不是买家
+        }
+
+        if(order.getStatus().intValue() == C2cOrderStatusEnum.PAY.getCode()) {
+            //前端重复调用,修改凭证,提交后提示成功
+            return success();
+        }
+
+        if(order.getFlow().intValue() == C2cOrderFlowEnum.END.getCode()) {
+            return error(MessageUtils.message("c2c.order.is.end"));//订单已结束
+        }
+
+        String lockKey = getC2cOrderLockKey(order.getId().toString());
+        if (distributedRedisLock.lock(lockKey)) {
+            try {
+                order.setRemark("买家已完成付款");
+                return c2cOrderService.confirmPay(order, loginId);
+            } catch (Exception e) {
+                log.error("confirmPay,{},{}",order.getId(),e.getMessage());
+                return error(e.getMessage());
+            } finally {
+                distributedRedisLock.unlock(lockKey);
+            }
+        }
+        return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+    }
+
+    /**
+     * 卖家确认收款并放币 sendMessage
+     */
+    @PostMapping("/verifyReceipt")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result verifyReceipt(@RequestBody C2cOrderIdDTO dto)
+    {
+        ValidatorUtils.validateEntity(dto);
+
+        C2cOrderEntity order = c2cOrderService.selectOrder(dto.getId());
+        if(order == null) {
+            return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
+        }
+        if(order.getFlow().intValue() == C2cOrderFlowEnum.END.getCode().intValue()) {
+            return error(MessageUtils.message("c2c.order.is.end"));//订单已结束
+        }
+        String lockKey = getC2cOrderLockKey(order.getId().toString());
+        if (distributedRedisLock.lock(lockKey)) {
+            try {
+                order.setRemark("卖家已确认收款并放行");
+                return toAjax(c2cOrderService.verifyReceipt(order,StpUtil.getLoginIdAsLong()));
+            } catch (Exception e) {
+                log.error("verifyReceipt,{},{}",order.getId(),e.getMessage());
+                return error(e.getMessage());
+            } finally {
+                distributedRedisLock.unlock(lockKey);
+            }
+        }
+        return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+    }
+
+    /**
+     * 查付款凭证
+     * @param c2cPaymentVoucher
+     * @return
+     */
+    @PostMapping("/queryPayment")
+    public Result queryPayment(@RequestBody C2cPaymentVoucherQryDTO c2cPaymentVoucher)
+    {
+        ValidatorUtils.validateEntity(c2cPaymentVoucher);
+
+        Long orderId = c2cPaymentVoucher.getOrderId();
+        C2cOrderEntity order = c2cOrderService.selectOrder(orderId);
+        if(order == null) {
+            return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
+        }
+        if(order.getUserId().longValue() == StpUtil.getLoginIdAsLong()
+                || order.getTranUserId().longValue() == StpUtil.getLoginIdAsLong()) {
+            List<C2cPaymentVoucherEntity> list = c2cPaymentVoucherService.selectList(orderId);
+            return success(list);
+        } else {
+            return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+        }
+    }
+
+    /**
+     * 上传付款凭证
+     * @param c2cPaymentVoucher
+     * @return
+     */
+    @PostMapping("/uploadPayment")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result uploadPayment(@RequestBody C2cPaymentVoucherDTO c2cPaymentVoucher) {
+        ValidatorUtils.validateEntity(c2cPaymentVoucher);
+
+        Long orderId = c2cPaymentVoucher.getOrderId();
+        String img = c2cPaymentVoucher.getImg();
+
+        C2cOrderEntity order = c2cOrderService.selectOrder(orderId);
+        if(order!=null && order.getFlow().intValue()==C2cOrderFlowEnum.END.getCode()) {
+            return error(MessageUtils.message("c2c.order.is.end"));//订单已结束
+        }
+
+        if(order.getUserId().longValue() != StpUtil.getLoginIdAsLong()
+                && order.getTranUserId().longValue() != StpUtil.getLoginIdAsLong()) {
+            return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+        }
+
+
+        if(c2cPaymentVoucher.getId() == null || c2cPaymentVoucher.getId().intValue() == 0) {
+            C2cPaymentVoucherEntity entity = new C2cPaymentVoucherEntity();
+            entity.setOrderId(orderId);
+            entity.setUserId(StpUtil.getLoginIdAsLong());
+            entity.setImg(img);
+            entity.setStatus(1);
+            entity.setCreateTime(new Date());
+            entity.setUpdateTime(new Date());
+            if(c2cPaymentVoucherService.insert(entity)) {
+                Map data = MapUtil.of("id", entity.getId());
+                return success(data);
+            } else {
+                return error(MessageUtils.message("c2c.order.uploadPayment.fail"));//上传付款凭证失败
+            }
+
+        } else {
+            C2cPaymentVoucherEntity voucher = c2cPaymentVoucherService.selectById(c2cPaymentVoucher.getId());
+            if(voucher==null) {
+                return error(MessageUtils.message("c2c.order.pay.cert.id.invalid"));//凭证编号无效
+            }
+            if(StpUtil.getLoginIdAsString().equals(voucher.getUserId().toString())) {
+
+                C2cPaymentVoucherEntity entity = new C2cPaymentVoucherEntity();
+                entity.setId(c2cPaymentVoucher.getId());
+                entity.setOrderId(orderId);
+                entity.setUserId(StpUtil.getLoginIdAsLong());
+                entity.setImg(img);
+                entity.setStatus(1);
+                entity.setUpdateTime(new Date());
+                if(c2cPaymentVoucherService.updateById(entity)) {
+                    Map data = MapUtil.of("id", entity.getId());
+                    return success(data);
+                } else {
+                    return error(MessageUtils.message("c2c.order.uploadPayment.fail"));//上传付款凭证失败
+                }
+
+            } else {
+                return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+            }
+        }
+    }
+
+    /**
+     * 删除付款凭证
+     * @param c2cPaymentVoucher
+     * @return
+     */
+    @PostMapping("/deletePayment")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result deletePayment(@RequestBody C2cPaymentVoucherIdDTO c2cPaymentVoucher) {
+        ValidatorUtils.validateEntity(c2cPaymentVoucher);
+
+        C2cPaymentVoucherEntity voucher = c2cPaymentVoucherService.selectById(c2cPaymentVoucher.getId());
+        if(voucher==null) {
+            return error(MessageUtils.message("c2c.order.pay.cert.id.invalid"));//凭证编号无效
+        }
+        //订单已完成不能删除
+        C2cOrderEntity order = c2cOrderService.selectOrder(voucher.getOrderId());
+        if(order!=null && order.getFlow().intValue()==C2cOrderFlowEnum.END.getCode()) {
+            return error(MessageUtils.message("c2c.order.is.end"));//订单已结束
+        }
+
+        if(StpUtil.getLoginIdAsString().equals(voucher.getUserId().toString())) {
+
+            C2cPaymentVoucherEntity entity = new C2cPaymentVoucherEntity();
+            entity.setId(c2cPaymentVoucher.getId());
+            entity.setStatus(-1);
+            entity.setUpdateTime(new Date());
+            return toAjax(c2cPaymentVoucherService.updateById(entity));
+        } else {
+            return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+        }
+    }
+
+
+
+
+    /**
+     * 用户或商家查询订单历史
+     * flow= 0 进行中 1 已结束
+     * status= 0 未付款 1 已付款(确认付款后)2 申诉 |  3 已完成 4 已取消
+     */
+    @PostMapping("/mylist")
+    public Result mylist(@RequestBody C2cOrderListDTO orderVo)
+    {
+        ValidatorUtils.validateEntity(orderVo);
+        //分页
+        Integer pageNum = Convert.toInt(orderVo.getPageNum(),1);
+        Integer pageSize = Convert.toInt(orderVo.getPageSize(),10);
+
+        Map<String,Object> params = new HashMap<>();
+        params.put(Constant.PAGE,pageNum);
+        params.put(Constant.LIMIT,pageSize);
+        params.put("direction",orderVo.getDirection());
+        params.put("flow",orderVo.getFlow());
+        params.put("status",orderVo.getStatus());
+        params.put("orderNo",orderVo.getOrderNo());
+        params.put("isMt",orderVo.getIsMt());
+        PageData<C2cOrderEntity> page = c2cOrderService.page(params);
+
+        List<C2cOrderEntity> orderList = page.getList();
+        // 查询付款凭证
+        orderList = c2cOrderService.selectPaymentVoucherByOrderList(orderList);
+        page.setList(orderList);
+
+
+        return new Result<PageData<C2cOrderEntity>>().ok(page);
+
+    }
+
+    /**
+     * 获取c2c订单详细信息
+     */
+    @GetMapping(value = "/{id}")
+    public Result getInfo(@PathVariable("id") Long id)
+    {
+        C2cOrderEntity c2cOrder = c2cOrderService.selectOrder(id);
+        if(c2cOrder == null) {
+            return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
+        }
+        if(c2cOrder.getUserId().longValue() != StpUtil.getLoginIdAsLong()
+                && c2cOrder.getTranUserId().longValue() != StpUtil.getLoginIdAsLong()) {
+            return error(MessageUtils.message("c2c.order.no.permission.view"));//您无权查看
+        }
+
+        //买家付款凭证
+        C2cPaymentVoucherEntity c2cPaymentVoucher = new C2cPaymentVoucherEntity();
+        c2cPaymentVoucher.setOrderId(c2cOrder.getId());
+        c2cPaymentVoucher.setStatus(1);
+        List<C2cPaymentVoucherEntity> payVoucherList = c2cPaymentVoucherService.selectList(c2cOrder.getId());
+        if(payVoucherList!=null && payVoucherList.size()>0) {
+            c2cOrder.setIsVoucher(1);
+            c2cOrder.setPayVoucherList(payVoucherList);
+        } else {
+            c2cOrder.setIsVoucher(0);
+        }
+        //卖家收款信息
+        Long sellUserId = null;
+        if(c2cOrder.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            sellUserId = c2cOrder.getTranUserId();
+        } else {
+            sellUserId = c2cOrder.getUserId();
+        }
+        C2cUserReceiptEntity receipt = c2cUserReceiptService.selectOneMyReceipt(sellUserId, c2cOrder.getPayType());
+        c2cOrder.setReceiptInfo(receipt);
+
+        return success(c2cOrder);
+
+    }
+
+    /**
+     * 商户统计:待处理的消息数=待支付 + 待放币
+     * @return
+     */
+    @PostMapping("/undoCounts")
+    public Result undoCounts() {
+        //待支付的订单数量
+        String unpayCountsKey = CacheConstants.getC2cMertUnPayKey(StpUtil.getLoginIdAsString());
+
+        //待放币的订单数量
+        String releaseCountsKey = CacheConstants.getC2cMertUnReleaseKey(StpUtil.getLoginIdAsString());
+
+        Integer unpayCounts = 0;
+        Integer releaseCounts = 0;
+        if(!redisUtils.hasKey(unpayCountsKey)) {
+            unpayCounts = setMtUnPayCount(unpayCountsKey);
+        } else {
+            unpayCounts = Convert.toInt(redisUtils.get(unpayCountsKey),0);
+        }
+        if(!redisUtils.hasKey(releaseCountsKey)) {
+            releaseCounts = setMtUnReleaseCount(releaseCountsKey);
+        } else {
+            releaseCounts = Convert.toInt(redisUtils.get(releaseCountsKey),0);
+        }
+        if(unpayCounts<0 || releaseCounts<0) {
+            unpayCounts = setMtUnPayCount(unpayCountsKey);
+            releaseCounts = setMtUnReleaseCount(releaseCountsKey);
+        }
+        Map<String,Integer> data = MapUtil.of("unpayCounts",unpayCounts);
+        data.put("releaseCounts",releaseCounts);
+        return success(data);
+    }
+
+    /**
+     * 设置商家待支付订单数
+     * @param unpayCountsKey
+     * @return
+     */
+    private Integer setMtUnPayCount(String unpayCountsKey) {
+        List<Map> mtUpPayList = c2cOrderService.selectMtUnPayCount(StpUtil.getLoginIdAsLong());
+        Map<String, Object> upPayMap = mtUpPayList.get(0);
+        Integer unpayCounts = Convert.toInt(upPayMap.get("NUM"), 0);
+        Random random = new Random();
+        int randomSecond = random.nextInt(12*3600)+  12*3600; // 生成12到24之间的随机数
+        redisUtils.set(unpayCountsKey, unpayCounts, randomSecond);
+        return unpayCounts;
+    }
+
+    /**
+     * 设置商家待放币数
+     * @param releaseCountsKey
+     * @return
+     */
+    private Integer setMtUnReleaseCount(String releaseCountsKey) {
+        List<Map> mtReleaseList = c2cOrderService.selectMtUnReleaseCount(StpUtil.getLoginIdAsLong());
+        Map<String,Object> releaseMap = mtReleaseList.get(0);
+        Integer releaseCounts = Convert.toInt(releaseMap.get("NUM"),0);
+        Random random = new Random();
+        int randomSecond = random.nextInt(12*3600)+12*3600; // 生成12到24之间的随机数
+        redisUtils.set(releaseCountsKey,releaseCounts,randomSecond);
+        return releaseCounts;
+    }
+
+    /**
+     * 用户统计:待处理的消息数=待支付 + 待放币
+     * @return
+     */
+//    @PostMapping("/userUndoCounts")
+//    public AjaxResult userUndoCounts() {
+//        //待支付的订单数量
+//        String unpayCountsKey = StringUtils.format(CacheConstants.C2C_UNPAY_COUNTS, StpUtil.getLoginIdAsString());
+//        Integer unpayCounts = Convert.toInt(redisCache.getCacheObject(unpayCountsKey),0);
+//        //待放币的订单数量
+//        String releaseCountsKey = StringUtils.format(CacheConstants.C2C_RELEASE_COUNTS, StpUtil.getLoginIdAsString());
+//        Integer releaseCounts = Convert.toInt(redisCache.getCacheObject(releaseCountsKey),0);
+//        Map<String,Integer> data = MapUtil.of("unpayCounts",unpayCounts);
+//        data.put("releaseCounts",releaseCounts);
+//        return success(data);
+//    }
+
+    /**
+     * 用户/商家发起申诉
+     * @param c2cOrderComplain
+     * @return
+     */
+    @PostMapping("/complain")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result complain(@RequestBody C2cOrderComplainDTO c2cOrderComplain)
+    {
+        ValidatorUtils.validateEntity(c2cOrderComplain);
+
+        C2cOrderEntity order = c2cOrderService.selectOrder(c2cOrderComplain.getOrderId());
+        if(order == null) {
+            return error(MessageUtils.message("c2c.order.not.exist"));//订单编号无效
+        }
+
+        //只有已付款才能发起申诉
+        if(order.getStatus().intValue() != C2cOrderStatusEnum.PAY.getCode().intValue()) {
+            //当前订单状态({0})不能发起申诉
+            return error(MessageUtils.message("c2c.order.status.complain.fail",C2cOrderStatusEnum.getByKey(order.getStatus().intValue()).getDesc()));
+        }
+
+        if(order.getUserId().longValue() != StpUtil.getLoginIdAsLong()
+                && order.getTranUserId().longValue() != StpUtil.getLoginIdAsLong()) {
+            return error(MessageUtils.message("c2c.complain.submit.fail"));//发起申诉失败,您不是买家或卖家
+        }
+
+        if(c2cOrderComplain.getReason().length()>250) {
+            return error(MessageUtils.message("c2c.order.complain.remark.maxval"));//申诉原因最多250个字
+        }
+
+        try {
+            C2cOrderComplainEntity c2cOrderComplainEntity = new C2cOrderComplainEntity();
+            c2cOrderComplainEntity.setOrderId(c2cOrderComplain.getOrderId());
+            c2cOrderComplainEntity.setReason(c2cOrderComplain.getReason());
+            return c2cOrderService.complain(order,c2cOrderComplainEntity,StpUtil.getLoginIdAsLong());
+        } catch (Exception e) {
+            return error(e.getMessage());
+        }
+
+    }
+
+    /**
+     * 用户或商家提交申诉凭证
+     * @param
+     * @return
+     */
+    @PostMapping("/complainVoucher")
+//    @RepeatSubmit(interval = 3000, message = "请求过于频繁")
+    public Result complainVoucher(@RequestBody C2cOrderComplainVoucherDTO dto)
+    {
+        ValidatorUtils.validateEntity(dto);
+
+        C2cOrderComplainEntity orderComplain = orderComplainService.selectById(dto.getComplainId());
+        if(orderComplain == null) {
+            return error(MessageUtils.message("c2c.order.complain.not.exist"));//申诉编号无效
+        }
+
+        if( StpUtil.getLoginIdAsLong() != orderComplain.getFromUserId().longValue()
+                && StpUtil.getLoginIdAsLong() != orderComplain.getToUserId().longValue()) {
+            return error(MessageUtils.message("c2c.complain.voucher.submit.fail"));//提交失败,您不是申诉人或被申诉人
+        }
+
+        if(StrUtil.isEmpty(dto.getRemark())) {
+            return error(MessageUtils.message("c2c.order.complain.remark.notEmpty"));//申诉原因不能空
+        }
+        if(dto.getRemark().length()>250) {
+            return error(MessageUtils.message("c2c.order.complain.remark.maxval"));//描述最多250个字
+        }
+
+        if(dto.getId()==null || dto.getId().intValue()==0) {
+            C2cOrderComplainVoucherEntity voucherEntity = new C2cOrderComplainVoucherEntity();
+            voucherEntity.setComplainId(dto.getComplainId());
+            voucherEntity.setRemark(dto.getRemark());
+            voucherEntity.setImg1(dto.getImg1());
+            voucherEntity.setImg2(dto.getImg2());
+            voucherEntity.setImg3(dto.getImg3());
+            voucherEntity.setImg4(dto.getImg4());
+            voucherEntity.setImg5(dto.getImg5());
+            voucherEntity.setUserId(StpUtil.getLoginIdAsLong());
+            voucherEntity.setStatus(1);
+            voucherEntity.setCreateTime(new Date());
+            voucherEntity.setUpdateTime(new Date());
+            if(orderComplainVoucherService.insert(voucherEntity)) {
+                Map data = MapUtil.of("id", voucherEntity.getId());
+                return success(data);
+            } else {
+                return error(MessageUtils.message("c2c.order.complain.voucher.save.fail"));//保存申诉凭证失败
+            }
+
+        } else {
+            C2cOrderComplainVoucherEntity voucherEntity = orderComplainVoucherService.selectById(dto.getId());
+            if(voucherEntity==null) {
+                return error(MessageUtils.message("c2c.order.complain.voucher.id.invalid"));//申诉凭证编号无效
+            }
+            if(orderComplain.getFlow().intValue() == C2cOrderFlowEnum.END.getCode()) {
+                return error(MessageUtils.message("c2c.order.complain.voucher.is.end"));//申诉已结束
+            }
+            if(StpUtil.getLoginIdAsLong() == voucherEntity.getUserId().longValue()) {
+                voucherEntity.setComplainId(dto.getComplainId());
+                voucherEntity.setRemark(dto.getRemark());
+                voucherEntity.setImg1(dto.getImg1());
+                voucherEntity.setImg2(dto.getImg2());
+                voucherEntity.setImg3(dto.getImg3());
+                voucherEntity.setImg4(dto.getImg4());
+                voucherEntity.setImg5(dto.getImg5());
+                voucherEntity.setUserId(StpUtil.getLoginIdAsLong());
+                voucherEntity.setStatus(1);
+                voucherEntity.setUpdateTime(new Date());
+                if(orderComplainVoucherService.updateById(voucherEntity)) {
+                    Map data = MapUtil.of("id", voucherEntity.getId());
+                    return success(data);
+                } else {
+                    return error(MessageUtils.message("c2c.order.complain.voucher.update.fail"));//修改申诉凭证失败
+                }
+            } else {
+                return error(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+            }
+
+        }
+
+
+    }
+
+    /**
+     * 用户或商家查询申诉历史
+     */
+    @PostMapping("/complainHis")
+    public Result complainHis(@RequestBody C2cOrderComplainOidDTO orderComplain)
+    {
+        ValidatorUtils.validateEntity(orderComplain);
+
+        List<C2cOrderComplainEntity> complainList = new ArrayList<>();
+        C2cOrderEntity order = c2cOrderService.selectOrder(orderComplain.getOrderId());
+
+        if( StpUtil.getLoginIdAsLong() != order.getUserId().longValue()
+                && StpUtil.getLoginIdAsLong() != order.getTranUserId().longValue()) {
+            return error(MessageUtils.message("c2c.order.no.permission.view"));//您无权查看
+        }
+
+        if(checkOrderTranUser(order)) {
+            complainList = orderComplainService.selectC2cOrderComplainList(orderComplain.getOrderId());
+        }
+        return success(complainList);
+    }
+
+    /**
+     * 检查登陆用户是否是买家或卖家
+     * @param order
+     * @return true 是
+     */
+    private boolean checkOrderTranUser(C2cOrderEntity order)
+    {
+        if(order.getUserId().longValue()==StpUtil.getLoginIdAsLong() ||
+                order.getTranUserId().longValue()==StpUtil.getLoginIdAsLong() ) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * 用户或商家查询申诉详情
+     */
+    @PostMapping("/complainDetail")
+    public Result complainDetail(@RequestBody C2cOrderComplainDetailDTO dto)
+    {
+        ValidatorUtils.validateEntity(dto);
+
+        C2cOrderComplainEntity orderComplain = null;
+        if (dto.getOrderId() != null) {
+            List<C2cOrderComplainEntity> orderComplainList = orderComplainService.selectC2cOrderComplainList(dto.getOrderId());
+            orderComplain = orderComplainList.get(0);
+        }
+        if (dto.getComplainId() != null) {
+            orderComplain = orderComplainService.selectById(dto.getComplainId());
+        }
+
+        if(orderComplain==null) {
+            return error(MessageUtils.message("c2c.order.complainId.orderId.invalid"));//申诉编号或订单编号无效
+        }
+
+        if(StpUtil.getLoginIdAsLong() != orderComplain.getFromUserId().longValue()
+                && StpUtil.getLoginIdAsLong() != orderComplain.getToUserId().longValue()) {
+            return error(MessageUtils.message("c2c.order.no.permission.view"));//您无权查看
+        }
+
+        List<C2cOrderComplainVoucherEntity> complainList = new ArrayList<>();
+        C2cOrderEntity order = c2cOrderService.selectOrder(orderComplain.getOrderId());
+
+        if(checkOrderTranUser(order)) {
+            complainList = orderComplainVoucherService.selectList(orderComplain.getId());
+        }
+        Map data = MapUtil.of("complainInfo", orderComplain);
+        data.put("voucherList", complainList);
+        return success(data);
+    }
+
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/AppAssetLogDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.AppAssetLogEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c用户资产变动日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-19
+ */
+@Mapper
+public interface AppAssetLogDao extends BaseDao<AppAssetLogEntity> {
+	
+}

+ 32 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cAdDao.java

@@ -0,0 +1,32 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cAdEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.Map;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cAdDao extends BaseDao<C2cAdEntity> {
+
+    /**
+     * 减少商家广告可用数量
+     * @param params
+     * @return
+     */
+    int updateC2cAdAvailableNumById(Map<String, Object> params);
+
+    /**
+     * 增加商家广告可用数量
+     * @param params
+     * @return
+     */
+    int addC2cAdAvailableNumById(Map<String, Object> params);
+
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cAdLogDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cAdLogEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c商家广告日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cAdLogDao extends BaseDao<C2cAdLogEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cLegalCoinDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cLegalCoinEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c法币
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Mapper
+public interface C2cLegalCoinDao extends BaseDao<C2cLegalCoinEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMerchantConfigDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cMerchantConfigEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * C2C认证商家配置表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cMerchantConfigDao extends BaseDao<C2cMerchantConfigEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cMerchantDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cMerchantEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * C2C认证商家表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cMerchantDao extends BaseDao<C2cMerchantEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderComplainDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cOrderComplainDao extends BaseDao<C2cOrderComplainEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderComplainVoucherDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainVoucherEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c申诉证明材料
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cOrderComplainVoucherDao extends BaseDao<C2cOrderComplainVoucherEntity> {
+	
+}

+ 26 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderDao.java

@@ -0,0 +1,26 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cOrderEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cOrderDao extends BaseDao<C2cOrderEntity> {
+
+    @Select("select count(1) NUM from c2c_order where tran_user_id=#{tranUserId} and status=0 and direction=2")
+    public List<Map> selectMtUnPayCount(@Param("tranUserId") Long tranUserId);
+
+    @Select("select count(1) NUM from c2c_order where tran_user_id=#{tranUserId} and status=1 and direction=1")
+    public List<Map> selectMtUnReleaseCount(@Param("tranUserId") Long tranUserId);
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cOrderLogDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cOrderLogEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c订单修改状态日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cOrderLogDao extends BaseDao<C2cOrderLogEntity> {
+	
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cPayWayDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cPayWayEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 法币支付方式
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Mapper
+public interface C2cPayWayDao extends BaseDao<C2cPayWayEntity> {
+	
+}

+ 23 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cPaymentVoucherDao.java

@@ -0,0 +1,23 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cPaymentVoucherEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cPaymentVoucherDao extends BaseDao<C2cPaymentVoucherEntity> {
+    /**
+     * 查询c2c付款证明列表
+     * @param ids
+     * @return
+     */
+    public List<C2cPaymentVoucherEntity> selectC2cPaymentVoucherByIds(Long[] ids);
+}

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dao/C2cUserReceiptDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.c2c.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.c2c.entity.C2cUserReceiptEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * c2c用户收款信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Mapper
+public interface C2cUserReceiptDao extends BaseDao<C2cUserReceiptEntity> {
+	
+}

+ 60 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/AppAssetLogDTO.java

@@ -0,0 +1,60 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import java.math.BigDecimal;
+
+/**
+ * c2c用户资产变动日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-19
+ */
+@Data
+@Schema(name = "c2c用户资产变动日志")
+public class AppAssetLogDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Long orderId;
+
+	@SchemaProperty(name = "")
+	private Long userId;
+
+	@SchemaProperty(name = "币种")
+	private String symbol;
+
+	@SchemaProperty(name = "资产类型 1=平台资产 2=理财资产 3=合约账户")
+	private Integer type;
+
+	@SchemaProperty(name = "资产总额")
+	private BigDecimal beforeTotal;
+
+	@SchemaProperty(name = "资产总额")
+	private BigDecimal afterTotal;
+
+	@SchemaProperty(name = "可用资产")
+	private BigDecimal beforeAvailable;
+
+	@SchemaProperty(name = "可用资产")
+	private BigDecimal afterAvailable;
+
+	@SchemaProperty(name = "占用资产")
+	private BigDecimal beforeFrozen;
+
+	@SchemaProperty(name = "占用资产")
+	private BigDecimal afterFrozen;
+
+	@SchemaProperty(name = "")
+	private String remark;
+
+	@SchemaProperty(name = "")
+	private Date createTime;
+
+
+}

+ 27 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdCancelDTO.java

@@ -0,0 +1,27 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c商家广告")
+public class C2cAdCancelDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "广告编号")
+    @NotNull(message="{NotNull.adId}")//广告编号不能为空
+	private Long id;
+
+}

+ 62 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdCreateDTO.java

@@ -0,0 +1,62 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c广告发布广告表单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c广告发布广告表单")
+public class C2cAdCreateDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "方向1买入2卖出")
+    @NotNull(message="{NotNull.direction}")//方向不能为空
+	private Integer direction;
+
+	@SchemaProperty(name = "法币")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能为空
+	private String legalCoin;
+
+	@SchemaProperty(name = "交易币种")
+    @NotBlank(message="{NotBlank.symbol}")//交易币种不能为空
+	private String symbol;
+
+	@SchemaProperty(name = "数量")
+    @NotNull(message="{NotNull.num}")//数量不能为空
+	private BigDecimal num;
+
+	@SchemaProperty(name = "价格类型:1固定")
+    @NotNull(message="{NotNull.priceType}")//价格类型不能为空
+	private Integer priceType;
+
+	@SchemaProperty(name = "单价")
+    @NotNull(message="{NotNull.price}")//价格不能为空
+	private BigDecimal price;
+
+	@SchemaProperty(name = "限量最小法币金额")
+    @NotNull(message="{NotNull.minAmount}")//最小金额不能为空
+	private BigDecimal minAmount;
+
+	@SchemaProperty(name = "限量最大法币金额")
+    @NotNull(message="{NotNull.maxAmount}")//最大金额不能为空
+	private BigDecimal maxAmount;
+
+	@SchemaProperty(name = "支付方式")
+    @NotBlank(message="{NotBlank.payway}")//支付方式不能为空
+	private String payway;
+
+    @SchemaProperty(name = "备注描述")
+    private String remark;
+}

+ 41 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdListDTO.java

@@ -0,0 +1,41 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c商家广告列表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c商家广告列表")
+public class C2cAdListDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+	@SchemaProperty(name = "商家编号")
+    @NotNull(message="{NotNull.merchantId}")//商家编号不能为空
+	private Integer merchantId;
+
+	@SchemaProperty(name = "1买入  2 卖出")
+    @NotNull(message="{NotNull.direction}")//方向不能为空
+	private Integer direction;
+
+	@SchemaProperty(name = "1可用 2不可用")
+    @NotNull(message="{NotNull.status}")//状态不能空
+	private Integer status;
+
+	@SchemaProperty(name = "页码")
+	private Integer pageNum;
+
+    @SchemaProperty(name = "每页大小")
+    private Integer pageSize;
+}

+ 50 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdLogDTO.java

@@ -0,0 +1,50 @@
+package com.qnfhq.modules.c2c.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import java.math.BigDecimal;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+/**
+ * c2c商家广告日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c商家广告日志")
+public class C2cAdLogDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Long adId;
+
+	@SchemaProperty(name = "")
+	private Long orderId;
+
+	@SchemaProperty(name = "数币的数量")
+	private BigDecimal symbolNum;
+
+	@SchemaProperty(name = "变更前剩余可用数币的数量")
+	private BigDecimal beforeAvailNum;
+
+	@SchemaProperty(name = "变更后剩余可用数币的数量")
+	private BigDecimal afterAvailNum;
+
+	@SchemaProperty(name = "变更前限量最大法币金额")
+	private BigDecimal beforeMaxAmount;
+
+	@SchemaProperty(name = "变更后限量最大法币金额")
+	private BigDecimal afterMaxAmount;
+
+	@SchemaProperty(name = "")
+	private String remark;
+
+	@SchemaProperty(name = "")
+	private Date createTime;
+
+
+}

+ 43 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdTranDTO.java

@@ -0,0 +1,43 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c商家广告")
+public class C2cAdTranDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "1买入  2 卖出")
+    @NotNull(message="{NotNull.direction}")//方向不能为空
+	private Integer direction;
+
+	@SchemaProperty(name = "法定货币比如CNY")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能为空
+	private String legalCoin;
+
+	@SchemaProperty(name = "交易币USDT")
+    @NotBlank(message="{NotBlank.symbol}")//交易币种不能为空
+	private String symbol;
+
+	@SchemaProperty(name = "买入法币的数量/卖出数币的数量")
+    @NotNull(message="{NotNull.num}")//数量不能为空
+	private BigDecimal amount;
+
+
+
+
+}

+ 52 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cAdViewDTO.java

@@ -0,0 +1,52 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 浏览广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "浏览广告")
+public class C2cAdViewDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "自增广告编号")
+	private Long id;
+
+    @SchemaProperty(name = "1买入  2 卖出")
+    @NotNull(message="{NotNull.direction}")//方向不能为空
+    private Integer direction;
+
+    @SchemaProperty(name = "法定货币比如CNY")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能为空
+    private String legalCoin;
+
+    @SchemaProperty(name = "交易币USDT")
+    @NotBlank(message="{NotBlank.symbol}")//交易币种不能为空
+    private String symbol;
+
+	@SchemaProperty(name = "数币的总数量")
+	private BigDecimal amount;
+
+	@SchemaProperty(name = "支付方式")
+	private String payway;
+
+	@SchemaProperty(name = "页码")
+	private Integer pageNum;
+
+	@SchemaProperty(name = "每页条数")
+	private Integer pageSize;
+
+
+}

+ 60 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cLegalCoinDTO.java

@@ -0,0 +1,60 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import java.math.BigDecimal;
+
+/**
+ * c2c法币
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Data
+@Schema(name = "c2c法币")
+public class C2cLegalCoinDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Long id;
+
+	@SchemaProperty(name = "国家")
+	private String country;
+
+	@SchemaProperty(name = "货币名称中文")
+	private String currencyZh;
+
+	@SchemaProperty(name = "货币名称英文")
+	private String currencyEn;
+
+	@SchemaProperty(name = "货币代码")
+	private String currencyCode;
+
+	@SchemaProperty(name = "数字代码")
+	private Integer currencyId;
+
+	@SchemaProperty(name = "状态 1有效 -1无效")
+	private Integer status;
+
+	@SchemaProperty(name = "货币代码首字母")
+	private String firstLetter;
+
+	@SchemaProperty(name = "排序")
+	private Integer sort;
+
+	@SchemaProperty(name = "兑换利率")
+	private BigDecimal exchangeRate;
+
+	@SchemaProperty(name = "")
+	private Date createTime;
+
+	@SchemaProperty(name = "")
+	private Date updateTime;
+
+
+}

+ 35 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantApplyDTO.java

@@ -0,0 +1,35 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * C2C认证商家申请
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "C2C认证商家申请")
+public class C2cMerchantApplyDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "法币")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能空
+	private String legalCoin;
+
+
+	@SchemaProperty(name = "社交账号")
+    @NotBlank(message="{NotBlank.socialAccount}")//社交账号不能空
+	private String socialAccount;
+
+    @SchemaProperty(name = "类型1 微信 2 Telegram")
+    @NotBlank(message="{NotBlank.socialType}")//社交账号类型不能空
+    private Integer socialType;
+
+}

+ 26 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantCheckDTO.java

@@ -0,0 +1,26 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * C2C认证商家检查
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "C2C认证商家检查")
+public class C2cMerchantCheckDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "法币")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能空
+	private String legalCoin;
+
+}

+ 31 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantConfigDTO.java

@@ -0,0 +1,31 @@
+package com.qnfhq.modules.c2c.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * C2C认证商家配置表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "C2C认证商家配置表")
+public class C2cMerchantConfigDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Integer id;
+
+	@SchemaProperty(name = "法币")
+	private String legalCoin;
+
+	@SchemaProperty(name = "冻结保证金")
+	private Integer margin;
+
+
+}

+ 94 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMerchantDTO.java

@@ -0,0 +1,94 @@
+package com.qnfhq.modules.c2c.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * C2C认证商家表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "C2C认证商家表")
+public class C2cMerchantDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Long id;
+
+	@SchemaProperty(name = "")
+	private Long userId;
+
+	@SchemaProperty(name = "")
+	private String userName;
+
+	@SchemaProperty(name = "法币")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能空
+	private String legalCoin;
+
+
+	@SchemaProperty(name = "类型1 微信 2 Telegram")
+	private Integer socialType;
+
+	@SchemaProperty(name = "社交账号")
+	private String socialAccount;
+
+	@SchemaProperty(name = "冻结保证金")
+	private Integer margin;
+
+	@SchemaProperty(name = "状态 0 审批中  1通过 -1不通过")
+	private Integer status;
+
+	@SchemaProperty(name = "")
+	private Date createTime;
+
+	@SchemaProperty(name = "")
+	private Date updateTime;
+
+	@SchemaProperty(name = "")
+	private String remark;
+
+	@SchemaProperty(name = "完成单数")
+	private Integer finishNum;
+
+	@SchemaProperty(name = "买入完成单数")
+	private Integer buyFinishNum;
+
+	@SchemaProperty(name = "卖出完成单数")
+	private Integer sellFinishNum;
+
+	@SchemaProperty(name = "完成率")
+	private String finishRate;
+
+	@SchemaProperty(name = "交易类型")
+	private String tranType;
+
+	@SchemaProperty(name = "30日成单数")
+	private Integer day30Num;
+
+	@SchemaProperty(name = "平均用时分钟")
+	private Integer averageTime;
+
+	@SchemaProperty(name = "平均用时分钟")
+	private Integer averageCancelTime;
+
+	@SchemaProperty(name = "创建时长天")
+	private Integer createNum;
+
+	@SchemaProperty(name = "首次交易")
+	private Integer firstTranNum;
+
+	@SchemaProperty(name = "首次交易时间")
+	private Date firstTranTime;
+
+	@SchemaProperty(name = "审核通过时间")
+	private Date operateTime;
+
+
+}

+ 28 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cMyReceiptDTO.java

@@ -0,0 +1,28 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c用户收款信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c用户收款信息")
+public class C2cMyReceiptDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "用户编号")
+	private Long userId;
+
+	@SchemaProperty(name = "支付方式t_pay_way.id")
+	private Integer type;
+
+
+}

+ 32 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainDTO.java

@@ -0,0 +1,32 @@
+package com.qnfhq.modules.c2c.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单申诉")
+public class C2cOrderComplainDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "订单编号")
+    @NotNull(message="{NotNull.orderId}")//订单编号不能为空
+	private Long orderId;
+
+	@SchemaProperty(name = "申诉原因")
+    @NotBlank(message="{NotBlank.reason}")//申诉原因不能为空
+	private String reason;
+
+
+}

+ 32 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainDetailDTO.java

@@ -0,0 +1,32 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单申诉")
+public class C2cOrderComplainDetailDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "订单编号")
+    @NotNull(message="{NotNull.orderId}")//订单编号不能为空
+	private Long orderId;
+
+	@SchemaProperty(name = "申诉编号")
+    @NotNull(message="{NotNull.complainId}")//申诉编号不能为空
+	private Long complainId;
+
+
+
+}

+ 28 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainOidDTO.java

@@ -0,0 +1,28 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单申诉")
+public class C2cOrderComplainOidDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "订单编号")
+    @NotNull(message="{NotNull.orderId}")//订单编号不能为空
+	private Long orderId;
+
+
+
+}

+ 52 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderComplainVoucherDTO.java

@@ -0,0 +1,52 @@
+package com.qnfhq.modules.c2c.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * c2c申诉证明材料
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c申诉证明材料")
+public class C2cOrderComplainVoucherDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "自增id")
+	private Long id;
+
+	@SchemaProperty(name = "申诉编号")
+    @NotNull(message="{NotNull.complainId}")//申诉编号不能为空
+	private Long complainId;
+
+	@SchemaProperty(name = "凭证描述")
+    @NotBlank(message="{NotBlank.remark}")//凭证描述不能为空
+	private String remark;
+
+	@SchemaProperty(name = "凭证截图1")
+    @NotBlank(message="{NotBlank.img1}")//凭证截图1不能为空
+	private String img1;
+
+	@SchemaProperty(name = "凭证截图2")
+	private String img2;
+
+	@SchemaProperty(name = "凭证截图3")
+	private String img3;
+
+	@SchemaProperty(name = "凭证截图4")
+	private String img4;
+
+	@SchemaProperty(name = "凭证截图5")
+	private String img5;
+
+
+
+}

+ 52 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderCreateDTO.java

@@ -0,0 +1,52 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单")
+public class C2cOrderCreateDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "方向1买入  2 卖出")
+    @NotNull(message="{NotNull.direction}")//方向不能为空
+	private Integer direction;
+
+	@SchemaProperty(name = "法币")
+    @NotBlank(message="{NotBlank.legalCoin}")//法币不能为空
+	private String legalCoin;
+
+	@SchemaProperty(name = "交易币种USDT,BTC")
+    @NotBlank(message="{NotBlank.symbol}")//交易币种不能为空
+	private String symbol;
+
+	@SchemaProperty(name = "广告编号")
+    @NotNull(message="{NotNull.c2cAdId}")//广告编号不能为空
+	private Long c2cAdId;
+
+	@SchemaProperty(name = "交易金额/数量")
+    @NotNull(message="{NotNull.tranAmount}")//交易金额/数量不能为空
+	private BigDecimal tranAmount;
+
+    @SchemaProperty(name = "交易方式amt/qty")
+    @NotBlank(message="{NotNull.tranBy}")//交易方式不能为空
+    private String tranBy;
+
+	@SchemaProperty(name = "支付方式比如1微信 2支付宝 3银行借记卡")
+    @NotNull(message="{NotNull.payType}")//支付方式不能为空
+	private Integer payType;
+
+}

+ 86 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderDTO.java

@@ -0,0 +1,86 @@
+package com.qnfhq.modules.c2c.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import java.math.BigDecimal;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单")
+public class C2cOrderDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Long id;
+
+	@SchemaProperty(name = "订单编号")
+	private String orderNo;
+
+	@SchemaProperty(name = "下单人的编号")
+	private Long userId;
+
+	@SchemaProperty(name = "下单名字")
+	private String userName;
+
+	@SchemaProperty(name = "1买入  2 卖出")
+	private Integer direction;
+
+	@SchemaProperty(name = "法定货币")
+	private String legalCoin;
+
+	@SchemaProperty(name = "交易币USDT,BTC")
+	private String symbol;
+
+	@SchemaProperty(name = "广告编号")
+	private Long c2cAdId;
+
+	@SchemaProperty(name = "交易对手编号")
+	private Long tranUserId;
+
+	@SchemaProperty(name = "交易对手名字")
+	private String tranUserName;
+
+	@SchemaProperty(name = "单价")
+	private BigDecimal tranPrice;
+
+	@SchemaProperty(name = "数量USDT")
+	private BigDecimal symbolNum;
+
+	@SchemaProperty(name = "法币的交易金额")
+	private BigDecimal tranAmount;
+
+	@SchemaProperty(name = "1微信  2支付宝 3银行借记卡")
+	private Integer payType;
+
+	@SchemaProperty(name = "0 进行中 1 已结束 ")
+	private Integer flow;
+
+	@SchemaProperty(name = "0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 ")
+	private Integer status;
+
+	@SchemaProperty(name = "广告要求")
+	private String remark;
+
+	@SchemaProperty(name = "")
+	private Date createTime;
+
+	@SchemaProperty(name = "")
+	private Date updateTime;
+
+	@SchemaProperty(name = "")
+	private Date endTime;
+
+	@SchemaProperty(name = "")
+	private Integer expireTime;
+
+
+}

+ 28 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderIdDTO.java

@@ -0,0 +1,28 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单")
+public class C2cOrderIdDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "订单编号")
+    @NotNull(message="{NotNull.oId}")//订单编号不能为空
+	private Long id;
+
+
+}

+ 49 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderListDTO.java

@@ -0,0 +1,49 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单历史查询")
+public class C2cOrderListDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "订单编号")
+    @NotBlank(message="{NotBlank.orderNo}")//订单编号不能空
+	private String orderNo;
+
+	@SchemaProperty(name = "方向1买入2卖出")
+    @NotNull(message="{NotNull.direction}")//方向不能空
+	private Integer direction;
+
+	@SchemaProperty(name = "状态0进行中1 已结束 ")
+    @NotNull(message="{NotNull.flow}")//状态不能空
+	private Integer flow;
+
+	@SchemaProperty(name = "0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 ")
+    @NotNull(message="{NotNull.status}")//状态不能空
+	private Integer status;
+
+	@SchemaProperty(name = "是否商家")
+	private Integer isMt;
+
+    @SchemaProperty(name = "页码")
+    private Integer pageNum;
+
+    @SchemaProperty(name = "每页条数")
+    private Integer pageSize;
+
+}

+ 43 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cOrderLogDTO.java

@@ -0,0 +1,43 @@
+package com.qnfhq.modules.c2c.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * c2c订单修改状态日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c订单修改状态日志")
+public class C2cOrderLogDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "")
+	private Long id;
+
+	@SchemaProperty(name = "0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 ")
+	private Integer oldStatus;
+
+	@SchemaProperty(name = "0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 ")
+	private Integer newStatus;
+
+	@SchemaProperty(name = "备注")
+	private String remark;
+
+	@SchemaProperty(name = "操作人")
+	private Long opUserId;
+
+	@SchemaProperty(name = "来源")
+	private String opType;
+
+	@SchemaProperty(name = "")
+	private Date createTime;
+
+
+}

+ 25 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPayWayDTO.java

@@ -0,0 +1,25 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+
+/**
+ * 法币支付方式
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Data
+@Schema(name = "法币支付方式")
+public class C2cPayWayDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "法币代码")
+	private String currencyCode;
+
+}

+ 55 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherDTO.java

@@ -0,0 +1,55 @@
+package com.qnfhq.modules.c2c.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c付款证明")
+public class C2cPaymentVoucherDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "自增编号")
+	private Long id;
+
+	@SchemaProperty(name = "自增订单编号")
+    @NotNull(message="{NotNull.orderId}")//自增订单编号不能为空
+	private Long orderId;
+
+	@SchemaProperty(name = "订单编号")
+	private String orderNo;
+
+	@SchemaProperty(name = "图片连接")
+    @NotBlank(message="{NotBlank.img}")//支付凭证不能为空
+	private String img;
+
+
+    /**
+     * 上传人的编号
+     */
+    private Long userId;
+    /**
+     * 状态 1有效 -1无效
+     */
+    private Integer status;
+    /**
+     *
+     */
+    private Date createTime;
+    /**
+     *
+     */
+    private Date updateTime;
+
+}

+ 28 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherIdDTO.java

@@ -0,0 +1,28 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c付款证明")
+public class C2cPaymentVoucherIdDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "编号")
+    @NotNull(message="{NotNull.id}")//编号不能为空
+	private Long id;
+
+
+}

+ 26 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cPaymentVoucherQryDTO.java

@@ -0,0 +1,26 @@
+package com.qnfhq.modules.c2c.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c付款证明")
+public class C2cPaymentVoucherQryDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "订单编号")
+    @NotNull(message="{NotNull.orderId}")//订单编号不能为空
+	private Long orderId;
+
+
+}

+ 36 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/C2cUserReceiptDTO.java

@@ -0,0 +1,36 @@
+package com.qnfhq.modules.c2c.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+
+/**
+ * c2c用户收款信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@Schema(name = "c2c用户收款信息")
+public class C2cUserReceiptDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @SchemaProperty(name = "主键")
+    private Long id;
+
+	@SchemaProperty(name = "支付方式")
+    @NotNull(message="{NotNull.payType}")//支付方式不能为空
+	private Integer type;
+
+	@SchemaProperty(name = "收款信息")
+    @NotBlank(message="{NotBlank.receiptInfo}")//收款信息不能空
+	private String info;
+
+
+
+}

+ 21 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/dto/setting/AdSetting.java

@@ -0,0 +1,21 @@
+package com.qnfhq.modules.c2c.dto.setting;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 广告配置
+ */
+@Data
+public class AdSetting {
+
+    private String legalCoin;//法币
+    private String symbol;//币种
+    private BigDecimal minPrice;//最小价格
+    private BigDecimal maxPrice;//最大价格
+    private BigDecimal minAmount;//最小金额
+    private BigDecimal maxAmount;//最大金额
+
+
+}

+ 67 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/AppAssetLogEntity.java

@@ -0,0 +1,67 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c用户资产变动日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-19
+ */
+@Data
+@TableName("t_app_asset_log")
+public class AppAssetLogEntity {
+
+    /**
+     * 
+     */
+	private Long orderId;
+    /**
+     * 
+     */
+	private Long userId;
+    /**
+     * 币种
+     */
+	private String symbol;
+    /**
+     * 资产类型 1=平台资产 2=理财资产 3=合约账户
+     */
+	private Integer type;
+    /**
+     * 资产总额
+     */
+	private BigDecimal beforeTotal;
+    /**
+     * 资产总额
+     */
+	private BigDecimal afterTotal;
+    /**
+     * 可用资产
+     */
+	private BigDecimal beforeAvailable;
+    /**
+     * 可用资产
+     */
+	private BigDecimal afterAvailable;
+    /**
+     * 占用资产
+     */
+	private BigDecimal beforeFrozen;
+    /**
+     * 占用资产
+     */
+	private BigDecimal afterFrozen;
+    /**
+     * 
+     */
+	private String remark;
+    /**
+     * 
+     */
+	private Date createTime;
+}

+ 106 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cAdEntity.java

@@ -0,0 +1,106 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_ad")
+public class C2cAdEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 广告编号
+     */
+	private String adNo;
+    /**
+     * 用户编号
+     */
+	private Long userId;
+    /**
+     * 
+     */
+	private String userName;
+    /**
+     * 商家编号
+     */
+	private Long merchantId;
+    /**
+     * 1买入  2 卖出
+     */
+	private Integer direction;
+    /**
+     * 法定货币比如CNY
+     */
+	private String legalCoin;
+    /**
+     * 交易币USDT
+     */
+	private String symbol;
+    /**
+     * 数币的总数量
+     */
+	private BigDecimal num;
+    /**
+     * 剩余可用数币的数量
+     */
+	private BigDecimal availableNum;
+    /**
+     * 价格类型:1固定
+     */
+	private Integer priceType;
+    /**
+     * 法币单价
+     */
+	private BigDecimal price;
+    /**
+     * 限量最小法币金额
+     */
+	private BigDecimal minAmount;
+    /**
+     * 限量最大法币金额
+     */
+	private BigDecimal maxAmount;
+    /**
+     * 支付方式
+     */
+	private String payway;
+    /**
+     * 广告要求
+     */
+	private String remark;
+    /**
+     * 状态 1可用 -1不可用
+     */
+	private Integer status;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+    /**
+     * 不可用的原因
+     */
+	private String reason;
+    /**
+     * 
+     */
+	private Long version;
+}

+ 58 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cAdLogEntity.java

@@ -0,0 +1,58 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c商家广告日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_ad_log")
+public class C2cAdLogEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long adId;
+    /**
+     * 
+     */
+	private Long orderId;
+    /**
+     * 数币的数量
+     */
+	private BigDecimal symbolNum;
+    /**
+     * 变更前剩余可用数币的数量
+     */
+	private BigDecimal beforeAvailNum;
+    /**
+     * 变更后剩余可用数币的数量
+     */
+	private BigDecimal afterAvailNum;
+    /**
+     * 变更前限量最大法币金额
+     */
+	private BigDecimal beforeMaxAmount;
+    /**
+     * 变更后限量最大法币金额
+     */
+	private BigDecimal afterMaxAmount;
+    /**
+     * 
+     */
+	private String remark;
+    /**
+     * 
+     */
+	private Date createTime;
+}

+ 70 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cLegalCoinEntity.java

@@ -0,0 +1,70 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * c2c法币
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Data
+@TableName("c2c_legal_coin")
+public class C2cLegalCoinEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 国家
+     */
+	private String country;
+    /**
+     * 货币名称中文
+     */
+	private String currencyZh;
+    /**
+     * 货币名称英文
+     */
+	private String currencyEn;
+    /**
+     * 货币代码
+     */
+	private String currencyCode;
+    /**
+     * 数字代码
+     */
+	private Integer currencyId;
+    /**
+     * 状态 1有效 -1无效
+     */
+	private Integer status;
+    /**
+     * 货币代码首字母
+     */
+	private String firstLetter;
+    /**
+     * 排序
+     */
+	private Integer sort;
+    /**
+     * 兑换利率
+     */
+	private BigDecimal exchangeRate;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+}

+ 33 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMerchantConfigEntity.java

@@ -0,0 +1,33 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * C2C认证商家配置表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_merchant_config")
+public class C2cMerchantConfigEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Integer id;
+    /**
+     * 法币
+     */
+	private String legalCoin;
+    /**
+     * 冻结保证金
+     */
+	private Integer margin;
+}

+ 113 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cMerchantEntity.java

@@ -0,0 +1,113 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * C2C认证商家表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_merchant")
+public class C2cMerchantEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 
+     */
+	private Long userId;
+    /**
+     * 
+     */
+	private String userName;
+    /**
+     * 法币
+     */
+	private String legalCoin;
+    /**
+     * 类型1 微信 2 Telegram
+     */
+	private Integer socialType;
+    /**
+     * 社交账号
+     */
+	private String socialAccount;
+    /**
+     * 冻结保证金
+     */
+	private Integer margin;
+    /**
+     * 状态 0 审批中  1通过 -1不通过
+     */
+	private Integer status;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+    /**
+     * 
+     */
+	private String remark;
+    /**
+     * 完成单数
+     */
+	private Integer finishNum;
+    /**
+     * 买入完成单数
+     */
+	private Integer buyFinishNum;
+    /**
+     * 卖出完成单数
+     */
+	private Integer sellFinishNum;
+    /**
+     * 完成率
+     */
+	private String finishRate;
+    /**
+     * 交易类型
+     */
+	private String tranType;
+    /**
+     * 30日成单数
+     */
+	private Integer day30Num;
+    /**
+     * 平均用时分钟
+     */
+	private Integer averageTime;
+    /**
+     * 平均用时分钟
+     */
+	private Integer averageCancelTime;
+    /**
+     * 创建时长天
+     */
+	private Integer createNum;
+    /**
+     * 首次交易
+     */
+	private Integer firstTranNum;
+    /**
+     * 首次交易时间
+     */
+	private Date firstTranTime;
+    /**
+     * 审核通过时间
+     */
+	private Date operateTime;
+}

+ 73 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderComplainEntity.java

@@ -0,0 +1,73 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_order_complain")
+public class C2cOrderComplainEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 
+     */
+	private Long orderId;
+    /**
+     * 申诉人的编号
+     */
+	private Long fromUserId;
+    /**
+     * 申诉人名字
+     */
+	private String fromUserName;
+    /**
+     * 申诉原因
+     */
+	private String reason;
+    /**
+     * 被申诉人的编号
+     */
+	private Long toUserId;
+    /**
+     * 被申诉人名字
+     */
+	private String toUserName;
+    /**
+     * 0 进行中 1 已结束 
+     */
+	private Integer flow;
+    /**
+     * 0 申诉已提交 1 被申诉人举证 2 审核中 3 已完成 4撤销申诉
+     */
+	private Integer status;
+    /**
+     * 申诉结果
+     */
+	private String result;
+    /**
+     * 操作人
+     */
+	private Long opUserId;
+    /**
+     * 
+     */
+	private Date opTime;
+    /**
+     * 
+     */
+	private Date createTime;
+}

+ 69 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderComplainVoucherEntity.java

@@ -0,0 +1,69 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c申诉证明材料
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_order_complain_voucher")
+public class C2cOrderComplainVoucherEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 
+     */
+	private Long complainId;
+    /**
+     * 凭证描述
+     */
+	private String remark;
+    /**
+     * 
+     */
+	private String img1;
+    /**
+     * 
+     */
+	private String img2;
+    /**
+     * 
+     */
+	private String img3;
+    /**
+     * 
+     */
+	private String img4;
+    /**
+     * 
+     */
+	private String img5;
+    /**
+     * 上传人的编号
+     */
+	private Long userId;
+    /**
+     * 状态 1有效 -1无效
+     */
+	private Integer status;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+}

+ 121 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderEntity.java

@@ -0,0 +1,121 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_order")
+public class C2cOrderEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 订单编号
+     */
+	private String orderNo;
+    /**
+     * 下单人的编号
+     */
+	private Long userId;
+    /**
+     * 下单名字
+     */
+	private String userName;
+    /**
+     * 1买入  2 卖出
+     */
+	private Integer direction;
+    /**
+     * 法定货币
+     */
+	private String legalCoin;
+    /**
+     * 交易币USDT,BTC
+     */
+	private String symbol;
+    /**
+     * 广告编号
+     */
+	private Long c2cAdId;
+    /**
+     * 交易对手编号
+     */
+	private Long tranUserId;
+    /**
+     * 交易对手名字
+     */
+	private String tranUserName;
+    /**
+     * 单价
+     */
+	private BigDecimal tranPrice;
+    /**
+     * 数量USDT
+     */
+	private BigDecimal symbolNum;
+    /**
+     * 法币的交易金额
+     */
+	private BigDecimal tranAmount;
+    /**
+     * 1微信  2支付宝 3银行借记卡
+     */
+	private Integer payType;
+    /**
+     * 0 进行中 1 已结束 
+     */
+	private Integer flow;
+    /**
+     * 0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 
+     */
+	private Integer status;
+    /**
+     * 广告要求
+     */
+	private String remark;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+    /**
+     * 
+     */
+	private Date endTime;
+    /**
+     * 
+     */
+	private Integer expireTime;
+
+    /**
+     * 卖家收款信息
+     */
+    @TableField(exist = false)
+    C2cUserReceiptEntity receiptInfo;
+
+    //是否有付款凭证
+    @TableField(exist = false)
+    Integer isVoucher=0;
+    //买家付款凭证
+    @TableField(exist = false)
+    List<C2cPaymentVoucherEntity> payVoucherList;
+}

+ 49 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cOrderLogEntity.java

@@ -0,0 +1,49 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c订单修改状态日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_order_log")
+public class C2cOrderLogEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 
+     */
+	private Integer oldStatus;
+    /**
+     * 0 未付款 1 已付款(确认付款后)2 申诉 3 已完成 4 已取消 
+     */
+	private Integer newStatus;
+    /**
+     * 备注
+     */
+	private String remark;
+    /**
+     * 操作人
+     */
+	private Long opUserId;
+    /**
+     * 来源
+     */
+	private String opType;
+    /**
+     * 
+     */
+	private Date createTime;
+}

+ 62 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cPayWayEntity.java

@@ -0,0 +1,62 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 法币支付方式
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Data
+@TableName("c2c_pay_way")
+public class C2cPayWayEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 支付方式名称
+     */
+	private String payName;
+    /**
+     * 支付方式图标
+     */
+	private String icon;
+    /**
+     * 货币代码
+     */
+	private String currencyCode;
+    /**
+     * 状态 1有效 -1无效
+     */
+	private Integer status;
+    /**
+     * 字段JSON格式
+     */
+	private String fieldList;
+    /**
+     * 排序
+     */
+	private Integer sort;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+
+    @TableField(exist = false)
+    private List<C2cAdEntity> adList;
+}

+ 53 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cPaymentVoucherEntity.java

@@ -0,0 +1,53 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_payment_voucher")
+public class C2cPaymentVoucherEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 
+     */
+	private Long orderId;
+    /**
+     * 订单编号
+     */
+	private String orderNo;
+    /**
+     * 
+     */
+	private String img;
+    /**
+     * 上传人的编号
+     */
+	private Long userId;
+    /**
+     * 状态 1有效 -1无效
+     */
+	private Integer status;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+}

+ 45 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/entity/C2cUserReceiptEntity.java

@@ -0,0 +1,45 @@
+package com.qnfhq.modules.c2c.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * c2c用户收款信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Data
+@TableName("c2c_user_receipt")
+public class C2cUserReceiptEntity implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+
+    @TableId(type = IdType.AUTO)
+	private Long id;
+    /**
+     * 
+     */
+	private Long userId;
+    /**
+     * 支付方式t_pay_way.id
+     */
+	private Integer type;
+    /**
+     * 字段JSON格式
+     */
+	private String info;
+    /**
+     * 
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private Date updateTime;
+}

+ 30 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/AdStatusEnum.java

@@ -0,0 +1,30 @@
+package com.qnfhq.modules.c2c.enums;
+
+/**
+ * C2C商户状态
+ */
+public enum AdStatusEnum {
+
+    PENDING(0,"审核中"),
+    PASS(1,"可用"),
+    NOPASS(-1,"不可用");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    AdStatusEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 31 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/C2cOrderComplainEnum.java

@@ -0,0 +1,31 @@
+package com.qnfhq.modules.c2c.enums;
+
+/**
+ * C2C 申诉流程状态
+ */
+public enum C2cOrderComplainEnum {
+    COMPLAINT(0,"申诉已提交"),
+    EVIDENCE(1,"被申诉人举证"),
+    REVIEW(2,"审核中"),
+    END(3,"已结束"),
+    CANCEL(4,"撤销申诉");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    C2cOrderComplainEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 35 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/C2cOrderFlowEnum.java

@@ -0,0 +1,35 @@
+package com.qnfhq.modules.c2c.enums;
+
+import java.util.Arrays;
+
+public enum C2cOrderFlowEnum {
+
+    PROGRESS(0,"进行中"),
+    END(1,"已结束"),
+    UNKNOWN(-1,"未知");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    C2cOrderFlowEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public static C2cOrderFlowEnum getByKey(int key) {
+        return Arrays.asList(C2cOrderFlowEnum.values()).stream()
+                .filter(a -> a.getCode().intValue() == key)
+                .findFirst().orElse(C2cOrderFlowEnum.UNKNOWN);
+    }
+}

+ 39 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/C2cOrderStatusEnum.java

@@ -0,0 +1,39 @@
+package com.qnfhq.modules.c2c.enums;
+
+import java.util.Arrays;
+
+
+public enum C2cOrderStatusEnum {
+
+    CREATE(0,"未付款"),
+    PAY(1,"已付款"),
+    COMPLAIN(2,"申诉"),
+    COMPLETE(3,"已完成"),
+    CANCEL(4,"已取消"),
+    UNKNOWN(-1,"未知");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    C2cOrderStatusEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public static C2cOrderStatusEnum getByKey(int key) {
+        return Arrays.asList(C2cOrderStatusEnum.values()).stream()
+                .filter(a -> a.getCode().intValue() == key)
+                .findFirst().orElse(C2cOrderStatusEnum.UNKNOWN);
+    }
+}

+ 36 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/DirectionEnum.java

@@ -0,0 +1,36 @@
+package com.qnfhq.modules.c2c.enums;
+
+
+public enum DirectionEnum {
+
+    SELL(2,"卖出"),
+    BUY(1,"买入");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    DirectionEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+
+    public static boolean isValidCode(Integer code) {
+        for (DirectionEnum directionEnum : DirectionEnum.values()) {
+            if (directionEnum.getCode().intValue() == code.intValue()) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

+ 31 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/enums/MerchantStatusEnum.java

@@ -0,0 +1,31 @@
+package com.qnfhq.modules.c2c.enums;
+
+/**
+ * C2C商户状态
+ */
+public enum MerchantStatusEnum {
+
+    PENDING(0,"审核中"),
+    PASS(1,"通过"),
+    NOPASS(-1,"不通过"),
+    LOCK(2,"锁定");
+
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getDesc()
+    {
+        return desc;
+    }
+
+    MerchantStatusEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+}

+ 37 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/AppAssetLogService.java

@@ -0,0 +1,37 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.AppAssetLogDTO;
+import com.qnfhq.modules.c2c.entity.AppAssetLogEntity;
+
+import java.math.BigDecimal;
+
+/**
+ * c2c用户资产变动日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-19
+ */
+public interface AppAssetLogService extends CrudService<AppAssetLogEntity, AppAssetLogDTO> {
+
+    /**
+     * 插入资产日志
+     * @param orderId
+     * @param userId
+     * @param symbol
+     * @param type
+     * @param beforeAmount
+     * @param afterAmount
+     * @param beforeAvail
+     * @param afterAvail
+     * @param beforeFrozen
+     * @param afterFrozen
+     * @param remark
+     * @return
+     */
+    boolean insertAssetLog(Long orderId, Long userId, String symbol, Integer type,
+                           BigDecimal beforeAmount, BigDecimal afterAmount,
+                           BigDecimal beforeAvail, BigDecimal afterAvail,
+                           BigDecimal beforeFrozen, BigDecimal afterFrozen,
+                           String remark);
+}

+ 20 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cAdLogService.java

@@ -0,0 +1,20 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.modules.c2c.entity.C2cAdLogEntity;
+
+import java.math.BigDecimal;
+
+/**
+ * c2c商家广告日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cAdLogService extends BaseService<C2cAdLogEntity> {
+
+    boolean insertC2cAdLog(Long adId, Long orderId, BigDecimal symbolNum,
+                       BigDecimal availableNum, BigDecimal afterAvailNum,
+                       BigDecimal beforeMaxAmount, BigDecimal afterMaxAmount, String remark);
+
+}

+ 81 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cAdService.java

@@ -0,0 +1,81 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.modules.c2c.dto.*;
+import com.qnfhq.modules.c2c.entity.C2cAdEntity;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cAdService extends BaseService<C2cAdEntity> {
+
+    public Result createAd(C2cAdCreateDTO c2cAdDTO, long loginId) throws Exception;
+
+    public Result cancelAd(C2cAdEntity ad) throws Exception;
+
+    PageData<C2cAdEntity> page(Map<String, Object> params);
+
+    /**
+     *  设置广告缓存
+     * @param c2cAd
+     */
+    void setAdCache(C2cAdEntity c2cAd);
+
+    public void deleteAdCache(Long c2cAdId,String payway,String legalCoin,String symbol,Integer direction);
+
+    public Result queryTranAd(C2cAdTranDTO tranDTO);
+
+    public Result selectC2cAdViewList(C2cAdViewDTO viewDTO);
+
+    /**
+     * 从redis中获取广告信息
+     * @param id
+     * @return
+     */
+    C2cAdEntity selectAdFromRedis(Long id);
+
+    /**
+     * 禁用广告
+     * @param c2cAd
+     * @return
+     */
+    boolean updateC2cAdDisabled(C2cAdEntity c2cAd);
+
+
+
+    /**
+     * 删除广告缓存
+     * @param c2cAd
+     */
+    void deleteC2cAdCache(C2cAdEntity c2cAd);
+
+    /**
+     *  修改广告可用数量
+     * @param id
+     * @param symbolNum
+     * @param maxAmount
+     * @param status
+     * @param version
+     * @return
+     */
+    int updateC2cAdAvailableNumById(Long id, BigDecimal symbolNum,BigDecimal maxAmount,Integer status,Long version);
+
+    /**
+     * 增加广告可用数量
+     * @param id
+     * @param symbolNum
+     * @param maxAmount
+     * @param version
+     * @return
+     */
+    int addC2cAdAvailableNumById(Long id, BigDecimal symbolNum,BigDecimal maxAmount,Long version);
+}

+ 19 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cLegalCoinService.java

@@ -0,0 +1,19 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cLegalCoinDTO;
+import com.qnfhq.modules.c2c.entity.C2cLegalCoinEntity;
+
+import java.util.List;
+
+/**
+ * c2c法币
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+public interface C2cLegalCoinService extends BaseService<C2cLegalCoinEntity> {
+    C2cLegalCoinEntity selectC2cLegalCoinByLegalCoin(String legalCoin);
+    List<C2cLegalCoinEntity> selectAllList();
+}

+ 22 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMerchantConfigService.java

@@ -0,0 +1,22 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cMerchantConfigDTO;
+import com.qnfhq.modules.c2c.entity.C2cMerchantConfigEntity;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * C2C认证商家配置表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cMerchantConfigService extends BaseService<C2cMerchantConfigEntity> {
+
+    C2cMerchantConfigEntity getMerchantConfig(String legalCoin);
+
+}

+ 29 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cMerchantService.java

@@ -0,0 +1,29 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cMerchantApplyDTO;
+import com.qnfhq.modules.c2c.dto.C2cMerchantDTO;
+import com.qnfhq.modules.c2c.entity.C2cMerchantEntity;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * C2C认证商家表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cMerchantService extends BaseService<C2cMerchantEntity> {
+
+    C2cMerchantEntity getMerchantEntity(long userId);
+
+    public Map<String, Object> checkApply(BigDecimal margin, long loginId);
+
+    public void apply(C2cMerchantApplyDTO appUserMerchant, long loginId);
+
+
+
+}

+ 24 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderComplainService.java

@@ -0,0 +1,24 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cOrderComplainDTO;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainEntity;
+
+import java.util.List;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cOrderComplainService extends BaseService<C2cOrderComplainEntity> {
+
+    /**
+     *  查询申诉列表
+     * @param orderId
+     * @return
+     */
+    public List<C2cOrderComplainEntity> selectC2cOrderComplainList(Long orderId);
+}

+ 18 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderComplainVoucherService.java

@@ -0,0 +1,18 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cOrderComplainVoucherDTO;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainVoucherEntity;
+
+import java.util.List;
+
+/**
+ * c2c申诉证明材料
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cOrderComplainVoucherService extends BaseService<C2cOrderComplainVoucherEntity> {
+    List<C2cOrderComplainVoucherEntity> selectList(Long complainId);
+}

+ 15 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderLogService.java

@@ -0,0 +1,15 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.modules.c2c.dto.C2cOrderLogDTO;
+import com.qnfhq.modules.c2c.entity.C2cOrderLogEntity;
+
+/**
+ * c2c订单修改状态日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cOrderLogService extends BaseService<C2cOrderLogEntity> {
+
+}

+ 144 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cOrderService.java

@@ -0,0 +1,144 @@
+package com.qnfhq.modules.c2c.service;
+
+
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.modules.c2c.dto.C2cOrderCreateDTO;
+import com.qnfhq.modules.c2c.dto.C2cOrderDTO;
+import com.qnfhq.modules.c2c.entity.C2cAdEntity;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainEntity;
+import com.qnfhq.modules.c2c.entity.C2cOrderEntity;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cOrderService extends BaseService<C2cOrderEntity> {
+
+    PageData<C2cOrderEntity> page(Map<String, Object> params);
+
+    /**
+     * c2c订单编号缓存Key
+     * @return
+     */
+    String getC2cOrderKeyByUid(String uid);
+
+    /**
+     * 查询进行中的订单
+     * @param adId
+     * @return
+     */
+    C2cOrderEntity getTradingByAdId(long adId);
+
+
+    /**
+     * 查询订单
+     * @param id
+     * @return
+     */
+    C2cOrderEntity selectOrder(Long id);
+
+    /**
+     * 删除订单缓存
+     * @param c2cOrder
+     * @return
+     */
+    void deleteOrderCache(C2cOrderEntity c2cOrder);
+    void deleteOrderCache(String orderId,String userId);
+
+
+    /**
+     * 创建订单
+     * @param c2cOrder
+     * @return
+     * @throws Exception
+     */
+    public Result createC2cOrder(C2cOrderCreateDTO c2cOrder, C2cAdEntity c2cAd, BigDecimal symbolNum,
+                                 Long loginUserId, String realName) throws Exception;
+
+
+    /**
+     * 取消订单删除缓存
+     * @param oldStatus
+     * @param order
+     * @return
+     */
+    int cancelC2cOrderRedis(int oldStatus,C2cOrderEntity order);
+
+    /**
+     * 用户取消订单
+     * @param order
+     * @param loginId
+     * @return
+     * @throws Exception
+     */
+    int cancelC2cOrder(C2cOrderEntity order,Long loginId) throws Exception;
+
+    /**
+     * 客服取消订单
+     * @param order
+     * @param loginId
+     * @return
+     * @throws Exception
+     */
+    int kfCancelC2cOrder(C2cOrderEntity order,Long loginId) throws Exception;
+
+    /**
+     * 确认已付款
+     * @param c2cOrder
+     * @return
+     */
+    public Result confirmPay(C2cOrderEntity c2cOrder,Long loginId) throws Exception;
+
+    /**
+     * 卖家确认收款然后放币
+     */
+    public int verifyReceipt(C2cOrderEntity c2cOrder,Long loginId) throws Exception;
+
+    /**
+     * 客服放币
+     * @param order
+     * @param loginId
+     * @return
+     * @throws Exception
+     */
+    int kfPassCoin(C2cOrderEntity order,Long loginId) throws Exception;
+    /**
+     * 查询订单付款凭证
+     * @param orderList
+     */
+    public List<C2cOrderEntity> selectPaymentVoucherByOrderList(List<C2cOrderEntity> orderList);
+
+    /**
+     * 获取商户待付款订单
+     * @param tranUserId
+     * @return
+     */
+    List<Map> selectMtUnPayCount(Long tranUserId);
+
+    /**
+     *  获取商户待放币订单
+     * @param tranUserId
+     * @return
+     */
+    List<Map> selectMtUnReleaseCount(Long tranUserId);
+
+
+    /**
+     * 申诉
+     * @param c2cOrder
+     * @param c2cOrderComplain
+     * @param loginId
+     * @return
+     * @throws Exception
+     */
+    public Result complain(C2cOrderEntity c2cOrder, C2cOrderComplainEntity c2cOrderComplain, Long loginId) throws Exception;
+
+}

+ 23 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cPayWayService.java

@@ -0,0 +1,23 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.entity.C2cPayWayEntity;
+
+import java.util.List;
+
+/**
+ * 法币支付方式
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+public interface C2cPayWayService extends BaseService<C2cPayWayEntity> {
+    /**
+     * 查询法币
+     * @param legalCoin
+     * @return
+     */
+    List<C2cPayWayEntity> selectListByLegalCoin(String legalCoin);
+
+}

+ 20 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cPaymentVoucherService.java

@@ -0,0 +1,20 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.common.service.CrudService;
+import com.qnfhq.modules.c2c.dto.C2cPaymentVoucherDTO;
+import com.qnfhq.modules.c2c.entity.C2cPaymentVoucherEntity;
+
+import java.util.List;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cPaymentVoucherService extends BaseService<C2cPaymentVoucherEntity> {
+    List<C2cPaymentVoucherEntity> selectList(Long orderId);
+
+    public List<C2cPaymentVoucherEntity> selectC2cPaymentVoucherByIds(Long[] ids);
+}

+ 27 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/C2cUserReceiptService.java

@@ -0,0 +1,27 @@
+package com.qnfhq.modules.c2c.service;
+
+import com.qnfhq.common.service.BaseService;
+import com.qnfhq.modules.c2c.dto.C2cMyReceiptDTO;
+import com.qnfhq.modules.c2c.dto.C2cUserReceiptDTO;
+import com.qnfhq.modules.c2c.entity.C2cUserReceiptEntity;
+
+import java.util.List;
+
+/**
+ * c2c用户收款信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+public interface C2cUserReceiptService extends BaseService<C2cUserReceiptEntity> {
+
+    List<C2cUserReceiptEntity> selectListMyReceipt(C2cMyReceiptDTO dto);
+
+    /**
+     * 获取用户收款信息
+     * @param userId
+     * @param type
+     * @return
+     */
+    C2cUserReceiptEntity selectOneMyReceipt(Long userId,Integer type);
+}

+ 57 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/AppAssetLogServiceImpl.java

@@ -0,0 +1,57 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.AppAssetLogDao;
+import com.qnfhq.modules.c2c.dto.AppAssetLogDTO;
+import com.qnfhq.modules.c2c.entity.AppAssetLogEntity;
+import com.qnfhq.modules.c2c.service.AppAssetLogService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * c2c用户资产变动日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-19
+ */
+@Service
+public class AppAssetLogServiceImpl extends CrudServiceImpl<AppAssetLogDao, AppAssetLogEntity, AppAssetLogDTO> implements AppAssetLogService {
+
+    @Override
+    public QueryWrapper<AppAssetLogEntity> getWrapper(Map<String, Object> params){
+        String id = (String)params.get("id");
+
+        QueryWrapper<AppAssetLogEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+
+        return wrapper;
+    }
+
+
+    @Override
+    public boolean insertAssetLog(Long orderId, Long userId, String symbol, Integer type,
+                              BigDecimal beforeAmount, BigDecimal afterAmount,
+                              BigDecimal beforeAvail, BigDecimal afterAvail,
+                              BigDecimal beforeFrozen, BigDecimal afterFrozen,
+                              String remark) {
+        AppAssetLogEntity appAssetLogEntity = new AppAssetLogEntity();
+        appAssetLogEntity.setOrderId(orderId);
+        appAssetLogEntity.setUserId(userId);
+        appAssetLogEntity.setSymbol(symbol);
+        appAssetLogEntity.setType(type);
+        appAssetLogEntity.setBeforeTotal(beforeAmount);
+        appAssetLogEntity.setAfterTotal(afterAmount);
+        appAssetLogEntity.setBeforeAvailable(beforeAvail);
+        appAssetLogEntity.setAfterAvailable(afterAvail);
+        appAssetLogEntity.setBeforeFrozen(beforeFrozen);
+        appAssetLogEntity.setAfterFrozen(afterFrozen);
+        appAssetLogEntity.setRemark(remark);
+        appAssetLogEntity.setCreateTime(new Date());
+        return insert(appAssetLogEntity);
+    }
+}

+ 53 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cAdLogServiceImpl.java

@@ -0,0 +1,53 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cAdLogDao;
+import com.qnfhq.modules.c2c.dto.C2cAdLogDTO;
+import com.qnfhq.modules.c2c.entity.C2cAdLogEntity;
+import com.qnfhq.modules.c2c.service.C2cAdLogService;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+
+/**
+ * c2c商家广告日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cAdLogServiceImpl extends BaseServiceImpl<C2cAdLogDao, C2cAdLogEntity> implements C2cAdLogService {
+
+//    @Override
+//    public QueryWrapper<C2cAdLogEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cAdLogEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+
+    @Override
+    public boolean insertC2cAdLog(Long adId,Long orderId,BigDecimal symbolNum,
+                              BigDecimal availableNum,BigDecimal afterAvailNum,
+                              BigDecimal beforeMaxAmount,BigDecimal afterMaxAmount,String remark) {
+        C2cAdLogEntity c2cAdLogEntity = new C2cAdLogEntity();
+        c2cAdLogEntity.setAdId(adId);
+        c2cAdLogEntity.setOrderId(orderId);
+        c2cAdLogEntity.setSymbolNum(symbolNum);
+        c2cAdLogEntity.setBeforeAvailNum(availableNum);
+        c2cAdLogEntity.setAfterAvailNum(afterAvailNum);
+        c2cAdLogEntity.setBeforeMaxAmount(beforeMaxAmount);
+        c2cAdLogEntity.setAfterMaxAmount(afterMaxAmount);
+        c2cAdLogEntity.setRemark(remark);
+        c2cAdLogEntity.setCreateTime(new Date());
+        return insert(c2cAdLogEntity);
+    }
+
+
+}

+ 597 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cAdServiceImpl.java

@@ -0,0 +1,597 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.json.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.Query;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.exception.ErrorCode;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.modules.c2c.dao.C2cAdDao;
+import com.qnfhq.modules.c2c.dto.*;
+import com.qnfhq.modules.c2c.entity.*;
+import com.qnfhq.modules.c2c.enums.AdStatusEnum;
+import com.qnfhq.modules.c2c.enums.DirectionEnum;
+import com.qnfhq.modules.c2c.enums.MerchantStatusEnum;
+import com.qnfhq.modules.c2c.service.*;
+import cn.hutool.core.util.StrUtil;
+import com.qnfhq.modules.user.entity.AppAssetEntity;
+import com.qnfhq.modules.user.enums.AssetEnum;
+import com.qnfhq.modules.user.service.AppAssetService;
+import com.qnfhq.utils.OrderUtils;
+import jakarta.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * c2c商家广告
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cAdServiceImpl extends BaseServiceImpl<C2cAdDao, C2cAdEntity> implements C2cAdService {
+
+    @Resource
+    private C2cMerchantService c2cMerchantService;
+
+    @Resource
+    private AppAssetService appAssetService;
+
+    @Resource
+    private RedisUtils redisUtils;
+
+    @Resource
+    private C2cPayWayService c2cPayWayService;
+
+    @Resource
+    private C2cLegalCoinService c2cLegalCoinService;
+
+    @Resource
+    private C2cAdDao c2cAdDao;
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Result createAd(C2cAdCreateDTO c2cAdDTO, long loginId) throws Exception {
+        Result result = new Result();
+        Integer direction = c2cAdDTO.getDirection();
+        String symbol = c2cAdDTO.getSymbol().toLowerCase();//usdt小写
+        String legalCoin = c2cAdDTO.getLegalCoin().toUpperCase();//法币大写
+        Integer priceType = c2cAdDTO.getPriceType();
+
+        BigDecimal price = c2cAdDTO.getPrice().setScale(2, RoundingMode.DOWN);
+        //币的数量
+        BigDecimal num = c2cAdDTO.getNum().setScale(8, RoundingMode.DOWN);
+        BigDecimal minAmount = c2cAdDTO.getMinAmount();
+        BigDecimal maxAmount = c2cAdDTO.getMaxAmount();
+        String payway = c2cAdDTO.getPayway().trim();
+        String remark = c2cAdDTO.getRemark();
+
+        C2cMerchantEntity merchant = c2cMerchantService.getMerchantEntity(loginId);
+        if(merchant==null) {
+            return result.error(ErrorCode.MERCHANT_SHIMING_VERIFY, MessageUtils.message("merchant.complete.merchant.apply"));//请完成认证商家申请
+        }
+        if (!Objects.equals(merchant.getStatus(), MerchantStatusEnum.PASS.getCode())) {
+            if (Objects.equals(merchant.getStatus(), MerchantStatusEnum.PENDING.getCode())){
+                return result.error(MessageUtils.message("merchant.under.review"));//认证商家审批中
+            } else if (Objects.equals(merchant.getStatus(), MerchantStatusEnum.LOCK.getCode())) {
+                return result.error(MessageUtils.message("merchant.under.lock"));//认证商家锁定中
+            } else {
+                return result.error(MessageUtils.message("merchant.approval.reject"));//认证商家审批不通过
+            }
+        }
+
+        //账户可用资金
+        BigDecimal avaAmount = BigDecimal.ZERO;
+        AppAssetEntity tAppAsset = new AppAssetEntity();
+        tAppAsset.setSymbol(symbol);
+        tAppAsset.setType(AssetEnum.PLATFORM_ASSETS.getCode());
+        tAppAsset.setUserId(merchant.getUserId());
+        List<AppAssetEntity> assetList = appAssetService.selectList(tAppAsset);
+        AppAssetEntity ptAsset = null;
+        if(assetList!=null && !assetList.isEmpty()) {
+            ptAsset = (AppAssetEntity)assetList.get(0);
+            avaAmount = ptAsset.getAvailable();
+        }
+        //卖出广告,用户平台资产要大于卖出数量
+        if(DirectionEnum.SELL.getCode()==direction) {
+            if(avaAmount.compareTo(num) == -1) {
+                return result.error(MessageUtils.message("merchant.buyCount.greater.sellCount"));//平台可用资产必须大于卖出数量
+            }
+        }
+
+        C2cAdEntity c2cAd = new C2cAdEntity();
+        c2cAd.setAdNo("AD"+ OrderUtils.generateAdNum());
+        c2cAd.setUserId(loginId);
+        c2cAd.setUserName(merchant.getUserName());
+        c2cAd.setMerchantId(merchant.getId());
+        c2cAd.setDirection(direction);
+        c2cAd.setLegalCoin(legalCoin);
+        c2cAd.setSymbol(symbol);
+        c2cAd.setNum(num);
+        c2cAd.setAvailableNum(num);
+        c2cAd.setPriceType(priceType);
+        c2cAd.setPrice(price);
+        c2cAd.setMinAmount(minAmount);
+        c2cAd.setMaxAmount(maxAmount);
+        c2cAd.setPayway(new StringBuilder(",").append(payway).append(",").toString());
+        c2cAd.setRemark(remark);
+        c2cAd.setStatus(AdStatusEnum.PASS.getCode());
+        //成交量
+//        c2cAd.setFinishNum(merchant.getFinishNum());
+        //成单率
+//        c2cAd.setFinishRate(merchant.getFinishRate());
+        if(!insert(c2cAd)) {
+            throw new Exception(MessageUtils.message("c2c.order.save.fail"));//保存广告失败
+        }
+        if (direction.intValue() == DirectionEnum.SELL.getCode().intValue()) {
+            //卖出广告 冻结卖出数量的币
+            if (appAssetService.frozeAssetByUserId(c2cAd.getUserId(), c2cAd.getSymbol(), c2cAd.getNum()) == 0) {
+                throw new Exception(MessageUtils.message("seller.asset.freeze.fail"));//冻结卖家资产失败
+            }
+        }
+        setAdCache(c2cAd);
+        return result.ok(c2cAd.getId());
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Result cancelAd(C2cAdEntity ad) throws Exception {
+        Result result = new Result();
+        ad.setStatus(AdStatusEnum.NOPASS.getCode());
+        ad.setReason("商户取消广告");
+        if(!updateById(ad)) {
+            throw new Exception(MessageUtils.message("c2c.ad.cancel.fail"));//取消广告失败
+        }
+
+        if (ad.getDirection().intValue() == DirectionEnum.SELL.getCode().intValue()) {
+            if (appAssetService.unblockAssetByUserId(ad.getUserId(), ad.getSymbol(), ad.getAvailableNum()) == 0) {
+                throw new Exception(MessageUtils.message("c2c.user.occupied.asset.fail"));//用户资产解冻失败
+            }
+        }
+
+        deleteAdCache(ad.getId(),ad.getPayway().replaceAll("^,|,$", ""),ad.getLegalCoin(),ad.getSymbol(),ad.getDirection());
+        return result;
+    }
+
+    private String getAdHKey(Long c2cAdId) {
+        return new StringBuilder("c2c_ad_h:").append(c2cAdId).toString();
+    }
+    private String getViewAdKey(Integer direction,String legalCoin,String symbol) {
+        if(DirectionEnum.BUY.getCode().intValue() == direction.intValue()) {
+            return new StringBuilder("c2c_ad_buy:").append(legalCoin).append(":").append(symbol).toString();
+        } else {
+            return new StringBuilder("c2c_ad_sell:").append(legalCoin).append(":").append(symbol).toString();
+        }
+    }
+    private String getQuickAdKey(String zsetKey,String paywayId) {
+        return new StringBuilder(zsetKey).append(":").append(paywayId).toString();
+    }
+
+    @Override
+    public void deleteAdCache(Long c2cAdId,String payway,String legalCoin,String symbol,Integer direction) {
+        //1 redis存储广告数据
+        String adHKey = getAdHKey(c2cAdId);
+        redisUtils.delete(adHKey);
+
+        //2 按价格排序,用于浏览广告
+        String zsetKey = getViewAdKey(direction, legalCoin, symbol);
+        redisUtils.removeZset(zsetKey, c2cAdId.toString());
+
+        //3 按支付方式、按最小数量排序,用于快捷交易 c2c_ad_payId_buy_cnyusdt
+        String[] paywayAr = payway.split(",");
+        for (String paywayId : paywayAr) {
+            redisUtils.removeZset(getQuickAdKey(zsetKey, paywayId), c2cAdId.toString());
+        }
+    }
+
+    @Override
+    public void setAdCache(C2cAdEntity c2cAd) {
+        //1 存储广告数据
+        String adHKey = getAdHKey(c2cAd.getId());
+        String payway = c2cAd.getPayway().replaceAll("^,|,$", "");
+        Map<String, Object> adMap = MapUtil.of("adNo", c2cAd.getAdNo());
+        adMap.put("userId", c2cAd.getUserId());
+        adMap.put("adNo",c2cAd.getAdNo());
+        adMap.put("userName", c2cAd.getUserName());
+        adMap.put("merchantId",c2cAd.getMerchantId());
+        adMap.put("direction", c2cAd.getDirection());
+        adMap.put("legalCoin", c2cAd.getLegalCoin());
+        adMap.put("symbol", c2cAd.getSymbol());
+        adMap.put("payway", payway);
+        adMap.put("total", c2cAd.getNum());
+        //可用数量
+        adMap.put("availableNum", c2cAd.getAvailableNum());
+        adMap.put("price", c2cAd.getPrice());
+        adMap.put("minAmount", c2cAd.getMinAmount());
+        adMap.put("maxAmount", c2cAd.getMaxAmount());
+        //成交量
+//        adMap.put("finishNum", Convert.toInt(c2cAd.getFinishNum(),0));
+        //成单率
+//        adMap.put("finishRate",Convert.toStr(c2cAd.getFinishRate(),"0%"));
+        adMap.put("status",c2cAd.getStatus());
+        Random random = new Random();
+        long randomHour = random.nextLong(24L)+24L; // 生成24到48之间的随机数
+        redisUtils.hMSet(adHKey, adMap, randomHour*3600L);
+
+        //2 按价格排序,用于浏览广告
+        String zsetKey = getViewAdKey(c2cAd.getDirection(), c2cAd.getLegalCoin(), c2cAd.getSymbol());
+        redisUtils.addZSet(zsetKey, c2cAd.getId().toString(), c2cAd.getPrice().doubleValue(), c2cAd.getDirection());
+
+        //3 按支付方式、按最小数量排序,用于快捷交易
+        String[] paywayAr = payway.split(",");
+        for (String paywayId : paywayAr) {
+            redisUtils.addZSet(getQuickAdKey(zsetKey, paywayId), c2cAd.getId().toString(), c2cAd.getMinAmount().doubleValue(), c2cAd.getDirection());
+        }
+    }
+
+
+    @Override
+    public PageData<C2cAdEntity> page(Map<String, Object> params) {
+        IPage<C2cAdEntity> page = baseDao.selectPage(
+                getPage(params, "id", false),
+                getWrapper(params)
+        );
+
+        return getPageData(page, C2cAdEntity.class);
+    }
+
+    private QueryWrapper<C2cAdEntity> getWrapper(Map<String, Object> params){
+
+        Integer merchantId = (Integer) params.get("merchantId");
+        Integer status = (Integer) params.get("status");
+        Integer direction = (Integer) params.get("direction");
+
+        QueryWrapper<C2cAdEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(Objects.nonNull(merchantId), "merchant_id", merchantId);
+        wrapper.eq(Objects.nonNull(direction), "direction", direction);
+        wrapper.eq(Objects.nonNull(status), "status", status);
+
+        return wrapper;
+    }
+
+
+    /**
+     * 快捷交易查询
+     * @param tranDTO
+     * @return
+     */
+    @Override
+    public Result queryTranAd(C2cAdTranDTO tranDTO) {
+        Result result = new Result();
+        long loginId = StpUtil.getLoginIdAsLong();
+        String tranSymbol = tranDTO.getSymbol().toLowerCase();
+        String tranLegalCoin = tranDTO.getLegalCoin().toUpperCase();
+        Integer tranDirection = tranDTO.getDirection();
+        //所有支付方式
+        List<C2cPayWayEntity> paywayList = c2cPayWayService.selectListByLegalCoin(tranLegalCoin);
+        if(CollectionUtils.isEmpty(paywayList)) {
+            return result.error(MessageUtils.message("c2c.ad.current.payway.empty"));//当前法币未设置支付方式
+        }
+        //法币和usdt兑换利率
+        C2cLegalCoinEntity tLegalCoin = c2cLegalCoinService.selectC2cLegalCoinByLegalCoin(tranLegalCoin);
+        BigDecimal maxAmount = BigDecimal.ZERO;
+        if (tranDTO.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            maxAmount = tranDTO.getAmount();//法币cny的金额
+        } else {
+            //卖出是usdt币的数量
+            maxAmount = tranDTO.getAmount().multiply(tLegalCoin.getExchangeRate());
+        }
+
+
+        boolean flag = true;
+        //1按支付方式从redis取数
+        for(C2cPayWayEntity payway : paywayList) {
+            long payId = payway.getId();
+            String zsetKey = getViewAdKey(tranDirection, tranLegalCoin, tranSymbol);
+            String zQuickKey = getQuickAdKey(zsetKey,payway.getId().toString());
+
+            ArrayList<Object> adidList = null;
+            //最小买入金额 ?test
+            adidList = redisUtils.getRangeByScore(zQuickKey, 10.0, maxAmount.doubleValue());
+            if (adidList != null) {
+                List<C2cAdEntity> adList = new ArrayList<>();
+                for (Object adId : adidList) {
+                    Long adIdLong = (Long) adId;//Long.valueOf((String)adId)
+                    C2cAdEntity ad = selectAdFromRedis(adIdLong);
+                    if(ad == null) {
+                        ad = selectById(adIdLong);
+                        delSetAdCache(ad);
+                    }
+                    if (ad!=null && ad.getMaxAmount().compareTo(maxAmount) != -1) {
+                        adList.add(ad);
+                        if (adList.size() > 2) {
+                            break;
+                        }
+                    }
+                }
+                if(adList.size()>0) {
+                    flag = false;
+                    sortAdList(adList,tranDTO.getDirection());
+                    payway.setAdList(adList);
+                }
+            }
+        }
+
+        if(flag) {
+            //2从数据库查询
+            Integer direction = 0;
+            if (tranDTO.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+                direction = DirectionEnum.SELL.getCode();
+            } else {
+                direction = DirectionEnum.BUY.getCode();
+            }
+            List<C2cAdEntity> queryAdList = selectC2cAdTranList(tranSymbol,direction,tranLegalCoin,maxAmount);
+            if (!CollectionUtils.isEmpty(queryAdList)) {
+                for(C2cPayWayEntity payway : paywayList) {
+                    List<C2cAdEntity> adList = new ArrayList<>();
+                    for(C2cAdEntity ad : queryAdList) {
+                        String[] payIds = ad.getPayway().split(",");
+                        if(Arrays.asList(payIds).contains(payway.getId().toString())
+                                && ad.getUserId().longValue()!=loginId) {
+                            adList.add(ad);
+                            if (adList.size() > 2) {
+                                break;
+                            }
+                        }
+                    }
+                    if(adList.size()>0) {
+                        sortAdList(adList,tranDTO.getDirection());
+                        payway.setAdList(adList);
+                    }
+                }
+            }
+        }
+        return result.ok(paywayList);
+    }
+
+    /**
+     * 查询快捷交易广告
+     * @param symbol
+     * @param direction
+     * @param legalCoin
+     * @param tranAmount
+     * @return
+     */
+    private List<C2cAdEntity> selectC2cAdTranList(String symbol,Integer direction,
+                                                  String legalCoin,BigDecimal tranAmount) {
+        return baseDao.selectList(new LambdaQueryWrapper<C2cAdEntity>()
+                    .eq(C2cAdEntity::getDirection,direction)
+                    .eq(C2cAdEntity::getLegalCoin,legalCoin)
+                    .eq(C2cAdEntity::getSymbol,symbol)
+                    .eq(C2cAdEntity::getStatus,AdStatusEnum.PASS.getCode())
+                    .ge(C2cAdEntity::getMaxAmount,tranAmount)
+                    .le(C2cAdEntity::getMinAmount,tranAmount)
+                    .last(" limit 50")
+                );
+    }
+
+    /**
+     * 浏览广告
+     * @param viewDTO
+     * @return
+     */
+    @Override
+    public Result selectC2cAdViewList(C2cAdViewDTO viewDTO)
+    {
+        Result result = new Result();
+        List<C2cAdEntity> resList = new ArrayList();
+        //查询单个广告
+        if(viewDTO.getId()!=null) {
+            C2cAdEntity ad = selectAdFromRedis(viewDTO.getId());
+            if(ad == null) {
+                ad = selectById(viewDTO.getId());
+            }
+            if(ad!=null) {
+                resList.add(ad);
+                PageData<C2cAdEntity> data = new PageData<C2cAdEntity>(resList,1L);
+                return result.ok(data);
+            }
+        }
+
+        //设置金额
+        BigDecimal amount = viewDTO.getAmount();
+        //设置支付方式
+        String payway = viewDTO.getPayway();
+
+        Map<String, Object> params = new HashMap<>();
+        //买入\卖出广告
+        Integer direction = null;
+        String type = "asc";
+        if (viewDTO.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            direction = DirectionEnum.SELL.getCode();
+            params.put("direction", DirectionEnum.SELL.getCode());
+        } else {
+            type = "desc";
+            direction = DirectionEnum.BUY.getCode();
+            params.put("direction", DirectionEnum.BUY.getCode());
+        }
+        long pageNum = Convert.toLong(viewDTO.getPageNum(), 1L);
+        long pageSize = Convert.toLong(viewDTO.getPageSize(), 10L);
+        params.put(Constant.PAGE,pageNum);
+        params.put(Constant.LIMIT,pageSize);
+        String inputSymbol = viewDTO.getSymbol().toLowerCase();
+        String inputLegalCoin = viewDTO.getLegalCoin().toUpperCase();
+
+        //1从redis取数
+        if(amount == null && StrUtil.isEmpty(payway)) {
+            long start = (pageNum - 1) * pageSize;
+            long end = pageNum * pageSize-1;
+            String zsetKey = getViewAdKey(direction, inputLegalCoin, inputSymbol);
+
+            ArrayList<Object> adList = redisUtils.getRange(zsetKey, type, start, end);
+            if (adList != null) {
+                for(Object adId : adList) {
+                    Long adIdLong = (Long) adId;
+                    C2cAdEntity ad = selectAdFromRedis(adIdLong);
+                    if(ad == null) {
+                        ad = selectById(adIdLong);
+                        delSetAdCache(ad);
+                    }
+                    if(ad!=null && ad.getUserId().longValue()!=StpUtil.getLoginIdAsLong()) {
+                        resList.add(ad);
+                    }
+                }
+                PageData<C2cAdEntity> data = new PageData<C2cAdEntity>(resList,redisUtils.countZset(zsetKey));
+                return result.ok(data);
+            }
+        }
+
+        //2 查数据库
+        List paywayList = new ArrayList();
+        if (StrUtil.isNotEmpty(payway)) {
+            paywayList = Arrays.stream(payway.split(",")).toList();
+        }
+        LambdaQueryWrapper<C2cAdEntity> wrapper = new LambdaQueryWrapper<C2cAdEntity>()
+                .ne(C2cAdEntity::getUserId, StpUtil.getLoginIdAsLong())
+                .eq(C2cAdEntity::getDirection, direction)
+                .eq(StrUtil.isNotBlank(inputLegalCoin),C2cAdEntity::getLegalCoin, inputLegalCoin)
+                .eq(StrUtil.isNotBlank(inputSymbol),C2cAdEntity::getSymbol, inputSymbol)
+                .eq(C2cAdEntity::getStatus,AdStatusEnum.PASS.getCode())
+                .le(Objects.nonNull(amount),C2cAdEntity::getMinAmount,amount)
+                .ge(Objects.nonNull(amount),C2cAdEntity::getMaxAmount,amount);
+        if(paywayList.size()>0) {
+            final List finalPaywayList = paywayList;
+            wrapper.and(qw -> createQw(qw, finalPaywayList));
+        }
+
+
+        IPage<C2cAdEntity> page = baseDao.selectPage(
+                getPage(params, "price", "asc".equals(type) ? true : false),
+                wrapper
+        );
+        PageData<C2cAdEntity> data = getPageData(page, C2cAdEntity.class);
+        return result.ok(data);
+    }
+
+    private void createQw(LambdaQueryWrapper<C2cAdEntity> qw, List<String> paywayList) {
+        for(int i = 0; i < paywayList.size(); i++) {
+            String payway = new StringBuilder(",").append(paywayList.get(i)).append(",").toString();
+            qw.or(qw1 -> qw1.like(C2cAdEntity::getPayway, payway));
+        }
+    }
+
+    @Override
+    public C2cAdEntity selectAdFromRedis(Long id) {
+        String adHKey = getAdHKey(id);
+        Map<String, Object> adMap = redisUtils.hGetAll(adHKey);
+        if(adMap == null || adMap.isEmpty()) {
+            return null;
+        }
+        C2cAdEntity c2cAd = new C2cAdEntity();
+        c2cAd.setId(id);
+        c2cAd.setAdNo(Convert.toStr(adMap.get("adNo")));
+        c2cAd.setUserId(Convert.toLong(adMap.get("userId")));
+        c2cAd.setUserName(Convert.toStr(adMap.get("userName")));
+        c2cAd.setMerchantId(Convert.toLong(adMap.get("merchantId")));
+        c2cAd.setDirection(Convert.toInt(adMap.get("direction")));
+        c2cAd.setSymbol(Convert.toStr(adMap.get("symbol")));
+        c2cAd.setLegalCoin(Convert.toStr(adMap.get("legalCoin")));
+        c2cAd.setNum(Convert.toBigDecimal(adMap.get("total")));
+        c2cAd.setAvailableNum(Convert.toBigDecimal(adMap.get("availableNum")));
+        c2cAd.setPrice(Convert.toBigDecimal(adMap.get("price")));
+        c2cAd.setMinAmount(Convert.toBigDecimal(adMap.get("minAmount")));
+        c2cAd.setMaxAmount(Convert.toBigDecimal(adMap.get("maxAmount")));
+        c2cAd.setPayway(Convert.toStr(adMap.get("payway")));
+//        c2cAd.setFinishNum(Convert.toInt(adMap.get("finishNum")));
+//        c2cAd.setFinishRate(Convert.toStr(adMap.get("finishRate")));
+        c2cAd.setStatus(Convert.toInt(adMap.get("status")));
+        return c2cAd;
+    }
+
+    //重设置广告缓存
+    private void delSetAdCache(C2cAdEntity ad) {
+        if(ad != null) {
+            if (ad.getStatus().intValue() == AdStatusEnum.NOPASS.getCode().intValue()) {
+                deleteAdCache(ad.getId(), ad.getPayway().replaceAll("^,|,$", ""), ad.getLegalCoin(), ad.getSymbol(), ad.getDirection());
+            } else {
+                deleteAdCache(ad.getId(), ad.getPayway().replaceAll("^,|,$", ""), ad.getLegalCoin(), ad.getSymbol(), ad.getDirection());
+                setAdCache(ad);
+            }
+        }
+    }
+
+    /**
+     * 买入 从低到高价格排序
+     * 卖出 从高到低排序
+     * @param adList
+     * @param direction
+     */
+    private void sortAdList(List<C2cAdEntity> adList,Integer direction) {
+        if (direction.intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            adList.sort((list1, list2) -> list1.getPrice().compareTo(list2.getPrice()));
+        } else {
+            adList.sort((list1, list2) -> list2.getPrice().compareTo(list1.getPrice()));
+        }
+    }
+
+
+    /**
+     * 更新广告不可用
+     * @param c2cAd c2c商家广告
+     * @return
+     */
+    @Override
+    public boolean updateC2cAdDisabled(C2cAdEntity c2cAd) {
+        Integer adDirection = c2cAd.getDirection();
+        String adLegalCoin = c2cAd.getLegalCoin();
+        String adSymbol = c2cAd.getSymbol();
+        String adPayway = c2cAd.getPayway().replaceAll("^,|,$", "");
+        deleteAdCache(c2cAd.getId(), adPayway, adLegalCoin, adSymbol, adDirection);
+        c2cAd.setStatus(AdStatusEnum.NOPASS.getCode());
+        return updateById(c2cAd);
+    }
+
+
+    /**
+     * 更新广告不可用
+     * @param c2cAd c2c商家广告
+     * @return
+     */
+    @Override
+    public void deleteC2cAdCache(C2cAdEntity c2cAd) {
+        Integer adDirection = c2cAd.getDirection();
+        String adLegalCoin = c2cAd.getLegalCoin();
+        String adSymbol = c2cAd.getSymbol();
+        String adPayway = c2cAd.getPayway().replaceAll("^,|,$", "");
+        deleteAdCache(c2cAd.getId(), adPayway, adLegalCoin, adSymbol, adDirection);
+    }
+
+
+    @Override
+    public int updateC2cAdAvailableNumById(Long id, BigDecimal symbolNum,BigDecimal maxAmount,Integer status,Long version) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id",id);
+        map.put("symbolNum",symbolNum);
+        map.put("maxAmount",maxAmount);
+        map.put("status",status);
+        map.put("version",version);
+        return c2cAdDao.updateC2cAdAvailableNumById(map);
+    }
+
+    @Override
+    public int addC2cAdAvailableNumById(Long id, BigDecimal symbolNum,BigDecimal maxAmount,Long version) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id",id);
+        map.put("symbolNum",symbolNum);
+        map.put("maxAmount",maxAmount);
+        map.put("version",version);
+        return c2cAdDao.addC2cAdAvailableNumById(map);
+    }
+}

+ 42 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cLegalCoinServiceImpl.java

@@ -0,0 +1,42 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cLegalCoinDao;
+import com.qnfhq.modules.c2c.dto.C2cLegalCoinDTO;
+import com.qnfhq.modules.c2c.entity.C2cLegalCoinEntity;
+import com.qnfhq.modules.c2c.service.C2cLegalCoinService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * c2c法币
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Service
+public class C2cLegalCoinServiceImpl extends BaseServiceImpl<C2cLegalCoinDao, C2cLegalCoinEntity> implements C2cLegalCoinService {
+
+
+    @Override
+    public C2cLegalCoinEntity selectC2cLegalCoinByLegalCoin(String legalCoin) {
+        return baseDao.selectOne(new LambdaQueryWrapper<C2cLegalCoinEntity>()
+                .eq(StrUtil.isNotBlank(legalCoin), C2cLegalCoinEntity::getCurrencyCode, legalCoin)
+                .eq(C2cLegalCoinEntity::getStatus,1)
+                .last(" limit 1")
+        );
+    }
+
+    @Override
+    public List<C2cLegalCoinEntity> selectAllList() {
+        return baseDao.selectList(new LambdaQueryWrapper<C2cLegalCoinEntity>()
+                .eq(C2cLegalCoinEntity::getStatus,1)
+        );
+    }
+}

+ 46 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMerchantConfigServiceImpl.java

@@ -0,0 +1,46 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cMerchantConfigDao;
+import com.qnfhq.modules.c2c.dto.C2cMerchantConfigDTO;
+import com.qnfhq.modules.c2c.entity.C2cMerchantConfigEntity;
+import com.qnfhq.modules.c2c.service.C2cMerchantConfigService;
+import cn.hutool.core.util.StrUtil;
+import com.qnfhq.modules.user.entity.AppUserEntity;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * C2C认证商家配置表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cMerchantConfigServiceImpl extends BaseServiceImpl<C2cMerchantConfigDao, C2cMerchantConfigEntity> implements C2cMerchantConfigService {
+
+//    @Override
+//    public QueryWrapper<C2cMerchantConfigEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cMerchantConfigEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+    @Override
+    public C2cMerchantConfigEntity getMerchantConfig(String legalCoin) {
+        return baseDao.selectOne(new LambdaQueryWrapper<C2cMerchantConfigEntity>()
+                .eq(C2cMerchantConfigEntity::getLegalCoin, legalCoin)
+                .last(" limit 1")
+        );
+    }
+
+}

+ 182 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cMerchantServiceImpl.java

@@ -0,0 +1,182 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import cn.hutool.core.map.MapUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.exception.RenException;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.modules.c2c.dao.C2cMerchantDao;
+import com.qnfhq.modules.c2c.dto.C2cMerchantApplyDTO;
+import com.qnfhq.modules.c2c.dto.C2cMerchantDTO;
+import com.qnfhq.modules.c2c.entity.C2cMerchantConfigEntity;
+import com.qnfhq.modules.c2c.entity.C2cMerchantEntity;
+import com.qnfhq.modules.c2c.enums.MerchantStatusEnum;
+import com.qnfhq.modules.c2c.service.C2cMerchantConfigService;
+import com.qnfhq.modules.c2c.service.C2cMerchantService;
+import cn.hutool.core.util.StrUtil;
+import com.qnfhq.modules.user.entity.AppAssetEntity;
+import com.qnfhq.modules.user.entity.AppUserDetailEntity;
+import com.qnfhq.modules.user.entity.AppUserEntity;
+import com.qnfhq.modules.user.enums.AuditStatusEnum;
+import com.qnfhq.modules.user.service.AppAssetService;
+import com.qnfhq.modules.user.service.AppUserDetailService;
+import com.qnfhq.modules.user.service.AppUserService;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * C2C认证商家表
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cMerchantServiceImpl extends BaseServiceImpl<C2cMerchantDao, C2cMerchantEntity> implements C2cMerchantService {
+
+//    @Override
+//    public QueryWrapper<C2cMerchantEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cMerchantEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+    @Resource
+    private C2cMerchantConfigService c2cMerchantConfigService;
+
+    @Resource
+    private AppAssetService appAssetService;
+
+    @Resource
+    private AppUserService appUserService;
+
+    @Resource
+    private AppUserDetailService appUserDetailService;
+
+    @Override
+    public C2cMerchantEntity getMerchantEntity(long userId) {
+        return baseDao.selectOne(new LambdaQueryWrapper<C2cMerchantEntity>()
+                .eq(C2cMerchantEntity::getUserId, userId)
+                .last(" limit 1")
+        );
+    }
+
+    /**
+     * 检查商户申请条件
+     * @param loginId
+     * @return
+     */
+    public Map<String, Object> checkApply(BigDecimal margin, long loginId) {
+        Boolean check = true;
+        Map<String, Object> ret = new HashMap<>();
+        //冻结保证金
+        ret.put("applyMargin",margin);
+        //可用资产
+        BigDecimal avaAmount = BigDecimal.ZERO;
+        List<AppAssetEntity> list = appAssetService.getUserAssets();
+        List<AppAssetEntity> ptAsset = list.stream().filter(a -> a.getType()==1).collect(Collectors.toList());
+        if(!ptAsset.isEmpty()) {
+            avaAmount = ((AppAssetEntity)ptAsset.get(0)).getAvailable();
+        }
+
+        if(avaAmount.compareTo(margin) == -1) {
+            //您的资金账户至少应有 {0}USDT的可用金额
+            ret.put("margin",new Result().error(0,MessageUtils.message("your.account.available.balance.insufficient",margin)));
+        } else {
+            ret.put("margin",new Result().set(1, MapUtil.of("availableAmount",avaAmount),"ok"));
+        }
+
+        AppUserEntity appUser = appUserService.selectById(loginId);
+        if(Objects.isNull(appUser) || appUser.getPhone().isEmpty()) {
+            ret.put("phone",new Result().error(0,MessageUtils.message("complete.mobile.bind")));
+        } else {
+            ret.put("phone",new Result().set(1,MapUtil.of("phone",appUser.getPhone()),"ok"));
+        }
+
+        if(Objects.isNull(appUser) || appUser.getEmail().isEmpty()) {
+            ret.put("email",new Result().error(0,MessageUtils.message("complete.email.bind")));
+        } else {
+            ret.put("email",new Result().set(1,MapUtil.of("email",appUser.getEmail()),"ok"));
+        }
+
+        AppUserDetailEntity appUserDetail = appUserDetailService.selectAppUserDetailByUserId(loginId);
+        if(Objects.nonNull(appUserDetail) && appUserDetail.getAuditStatus()==AuditStatusEnum.EXAMINATION_PASSED.getCode()) {
+            Map data = MapUtil.of("country",appUserDetail.getCountry());
+            data.put("realname",appUserDetail.getRealName());
+            ret.put("realname",new Result().set(1, data,"ok"));
+        } else {
+            ret.put("realname",new Result().error(0,MessageUtils.message("complete.identity.verification")));
+        }
+        return ret;
+    }
+
+    /**
+     * 商户申请
+     * 校验保证金是否足额
+     * 是否实名认证
+     * 邮箱、号码是否绑定
+     * @param loginId
+     * @return
+     */
+    public void apply(C2cMerchantApplyDTO appUserMerchant, long loginId) {
+        //冻结保证金
+        C2cMerchantConfigEntity merchantConfig = c2cMerchantConfigService.getMerchantConfig(appUserMerchant.getLegalCoin().toUpperCase());
+        if(merchantConfig==null) {
+            throw new RenException(MessageUtils.message("c2c.merchant.apply.not.config"));//未配置认证商家保证金
+        }
+        Integer marginL = merchantConfig.getMargin();
+        BigDecimal margin = new BigDecimal(marginL);
+
+        BigDecimal avaAmount = BigDecimal.ZERO;
+        List<AppAssetEntity> assetList = appAssetService.getUserAssets();
+        List<AppAssetEntity> ptAsset = assetList.stream().filter(a -> a.getType()==1).collect(Collectors.toList());
+        if(!ptAsset.isEmpty()) {
+            avaAmount = ((AppAssetEntity)ptAsset.get(0)).getAvailable();
+        }
+        if(avaAmount.compareTo(margin) == -1) {
+            //您的资金账户至少应有 {0}USDT的可用金额
+            throw new RenException(MessageUtils.message("your.account.available.balance.insufficient",margin));
+        }
+
+        AppUserEntity appUser = appUserService.selectById(loginId);
+        if(Objects.isNull(appUser) || appUser.getPhone().isEmpty()) {
+            throw new RenException(MessageUtils.message("complete.mobile.bind"));//完成手机号绑定
+        }
+        if(Objects.isNull(appUser) || appUser.getEmail().isEmpty()) {
+            throw new RenException(MessageUtils.message("complete.email.bind"));//完成邮箱绑定
+        }
+
+        AppUserDetailEntity appUserDetail = appUserDetailService.selectAppUserDetailByUserId(loginId);
+        if(Objects.nonNull(appUserDetail) && appUserDetail.getAuditStatus()!=AuditStatusEnum.EXAMINATION_PASSED.getCode()) {
+            throw new RenException(MessageUtils.message("complete.identity.verification"));//完成身份验证
+        }
+
+        C2cMerchantEntity merchant = getMerchantEntity(loginId);
+        if(Objects.isNull(merchant)) {
+            merchant = new C2cMerchantEntity();
+            merchant.setUserId(loginId);
+            merchant.setMargin(marginL);
+            merchant.setUserName(appUserDetail.getRealName());
+            merchant.setLegalCoin(appUserMerchant.getLegalCoin().toUpperCase());
+            merchant.setSocialType(appUserMerchant.getSocialType());
+            merchant.setSocialAccount(appUserMerchant.getSocialAccount());
+            merchant.setStatus(MerchantStatusEnum.PENDING.getCode());//0 审批中
+            merchant.setCreateTime(new Date());
+            merchant.setUpdateTime(new Date());
+            insert(merchant);
+        }
+    }
+
+
+
+}

+ 44 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderComplainServiceImpl.java

@@ -0,0 +1,44 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cOrderComplainDao;
+import com.qnfhq.modules.c2c.dto.C2cOrderComplainDTO;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainEntity;
+import com.qnfhq.modules.c2c.service.C2cOrderComplainService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * c2c订单申诉
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cOrderComplainServiceImpl extends BaseServiceImpl<C2cOrderComplainDao, C2cOrderComplainEntity> implements C2cOrderComplainService {
+
+//    @Override
+//    public QueryWrapper<C2cOrderComplainEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cOrderComplainEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+    @Override
+    public List<C2cOrderComplainEntity> selectC2cOrderComplainList(Long orderId) {
+        return baseDao.selectList(new LambdaQueryWrapper<C2cOrderComplainEntity>()
+                .eq(Objects.nonNull(orderId),C2cOrderComplainEntity::getOrderId, orderId)
+                .orderByDesc(C2cOrderComplainEntity::getId)
+            );
+    }
+
+}

+ 44 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderComplainVoucherServiceImpl.java

@@ -0,0 +1,44 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cOrderComplainVoucherDao;
+import com.qnfhq.modules.c2c.dto.C2cOrderComplainVoucherDTO;
+import com.qnfhq.modules.c2c.entity.C2cOrderComplainVoucherEntity;
+import com.qnfhq.modules.c2c.service.C2cOrderComplainVoucherService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * c2c申诉证明材料
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cOrderComplainVoucherServiceImpl extends BaseServiceImpl<C2cOrderComplainVoucherDao, C2cOrderComplainVoucherEntity> implements C2cOrderComplainVoucherService {
+
+//    @Override
+//    public QueryWrapper<C2cOrderComplainVoucherEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cOrderComplainVoucherEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+    @Override
+    public List<C2cOrderComplainVoucherEntity> selectList(Long complainId) {
+        return baseDao.selectList(new QueryWrapper<C2cOrderComplainVoucherEntity>()
+                .eq(Objects.nonNull(complainId),"complain_id", complainId)
+                .eq("status", 1)
+                .orderByDesc("id")
+        );
+    }
+}

+ 35 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderLogServiceImpl.java

@@ -0,0 +1,35 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cOrderLogDao;
+import com.qnfhq.modules.c2c.dto.C2cOrderLogDTO;
+import com.qnfhq.modules.c2c.entity.C2cOrderLogEntity;
+import com.qnfhq.modules.c2c.service.C2cOrderLogService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * c2c订单修改状态日志
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cOrderLogServiceImpl extends BaseServiceImpl<C2cOrderLogDao, C2cOrderLogEntity> implements C2cOrderLogService {
+
+//    @Override
+//    public QueryWrapper<C2cOrderLogEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cOrderLogEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+
+}

+ 767 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cOrderServiceImpl.java

@@ -0,0 +1,767 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.map.MapUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.qnfhq.common.constant.Constant;
+import com.qnfhq.common.page.PageData;
+import com.qnfhq.common.redis.RedisUtils;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.common.utils.DateUtils;
+import com.qnfhq.common.utils.MessageUtils;
+import com.qnfhq.common.utils.Result;
+import com.qnfhq.constant.CacheConstants;
+import com.qnfhq.modules.c2c.dao.C2cOrderDao;
+import com.qnfhq.modules.c2c.dto.C2cOrderCreateDTO;
+import com.qnfhq.modules.c2c.dto.C2cOrderDTO;
+import com.qnfhq.modules.c2c.dto.C2cOrderLogDTO;
+import com.qnfhq.modules.c2c.entity.*;
+import com.qnfhq.modules.c2c.enums.*;
+import com.qnfhq.modules.c2c.service.*;
+import cn.hutool.core.util.StrUtil;
+import com.qnfhq.modules.user.entity.AppAssetEntity;
+import com.qnfhq.modules.user.entity.AppUserEntity;
+import com.qnfhq.modules.user.enums.AssetEnum;
+import com.qnfhq.modules.user.enums.RecordEnum;
+import com.qnfhq.modules.user.service.AppAssetService;
+import com.qnfhq.modules.user.service.AppUserService;
+import com.qnfhq.modules.user.service.AppWalletRecordService;
+import com.qnfhq.utils.OrderUtils;
+import jakarta.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * c2c订单
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cOrderServiceImpl extends BaseServiceImpl<C2cOrderDao, C2cOrderEntity> implements C2cOrderService {
+    @Resource
+    private RedisUtils redisUtils;
+
+    @Resource
+    private AppUserService appUserService;
+
+    @Resource
+    private C2cOrderLogService c2cOrderLogService;
+
+    @Resource
+    private AppAssetService appAssetService;
+
+    @Resource
+    private AppAssetLogService appAssetLogService;
+
+    @Resource
+    private C2cAdService c2cAdService;
+
+    @Resource
+    private C2cAdLogService c2cAdLogService;
+
+    @Resource
+    private  C2cPaymentVoucherService c2cPaymentVoucherService;
+
+    @Resource
+    private  C2cOrderComplainService complainService;
+
+    @Resource
+    private AppWalletRecordService appWalletRecordService;
+
+
+    @Override
+    public PageData<C2cOrderEntity> page(Map<String, Object> params) {
+        IPage<C2cOrderEntity> page = baseDao.selectPage(
+                getPage(params, "id", false),
+                getWrapper(params)
+        );
+
+        return getPageData(page, C2cOrderEntity.class);
+    }
+
+
+    public QueryWrapper<C2cOrderEntity> getWrapper(Map<String, Object> params){
+
+        Integer direction = (Integer) params.get("direction");
+        Integer flow = (Integer) params.get("flow");
+        Integer status = (Integer) params.get("status");
+        Integer isMt = (Integer) params.get("isMt");
+        String orderNo = (String) params.get("orderNo");
+
+
+        QueryWrapper<C2cOrderEntity> qw = new QueryWrapper<>();
+        if(direction!=null && direction != -1) {
+            qw.eq("direction", direction);
+        }
+        if(flow!=null && flow != -1) {
+            qw.eq("flow",flow);
+        }
+        if(status!=null && status != -1) {
+            qw.eq("status",status);
+        }
+        if(StrUtil.isNotEmpty(orderNo)) {
+            qw.eq("order_no",orderNo);
+        }
+        if(isMt==null || isMt==1) {//用户
+            qw.eq("user_id", StpUtil.getLoginIdAsLong());
+        } else {
+            //表示商家查询订单列表
+            qw.eq("tran_user_id", StpUtil.getLoginIdAsLong());
+        }
+
+        return qw;
+    }
+
+
+//    @Override
+//    public QueryWrapper<C2cOrderEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cOrderEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+    @Override
+    public String getC2cOrderKeyByUid(String uid) {
+        return new StringBuilder("c2c_order_uid:").append(uid).toString();
+    }
+
+    @Override
+    public C2cOrderEntity getTradingByAdId(long adId) {
+        return baseDao.selectOne(new LambdaQueryWrapper<C2cOrderEntity>()
+                .eq(C2cOrderEntity::getC2cAdId, adId)
+                .eq(C2cOrderEntity::getFlow, 0)
+                .last(" limit 1")
+        );
+    }
+
+
+
+    @Override
+    public C2cOrderEntity selectOrder(Long id) {
+        C2cOrderEntity order = selectOrderFromRedis(id);
+        if(order == null) {
+            order = selectById(id);
+            if(order == null) {
+                return null;
+            }
+            setOrderCache(order);
+        }
+        return order;
+    }
+
+    private String getC2cOrderKeyByOid(String oid) {
+        return new StringBuilder("c2c_order_h:").append(oid).toString();
+    }
+
+    private C2cOrderEntity selectOrderFromRedis(Long id) {
+        String odHKey = getC2cOrderKeyByOid(id.toString());
+        Map<String, Object> odMap = redisUtils.hGetAll(odHKey);
+        if(odMap == null || odMap.isEmpty()) {
+            return null;
+        }
+
+        C2cOrderEntity order = new C2cOrderEntity();
+        order.setId(id);
+        order.setOrderNo(Convert.toStr(odMap.get("orderNo")));
+        order.setUserId(Convert.toLong(odMap.get("userId")));
+        order.setUserName(Convert.toStr(odMap.get("userName")));
+        order.setDirection(Convert.toInt(odMap.get("direction")));
+        order.setLegalCoin(Convert.toStr(odMap.get("legalCoin")));
+        order.setSymbol(Convert.toStr(odMap.get("symbol")));
+        order.setC2cAdId(Convert.toLong(odMap.get("c2cAdId")));
+        order.setTranUserId(Convert.toLong(odMap.get("tranUserId")));
+        order.setTranUserName(Convert.toStr(odMap.get("tranUserName")));
+        order.setTranPrice(Convert.toBigDecimal(odMap.get("tranPrice")));
+        order.setSymbolNum(Convert.toBigDecimal(odMap.get("symbolNum")));
+        order.setTranAmount(Convert.toBigDecimal(odMap.get("tranAmount")));
+        order.setPayType(Convert.toInt(odMap.get("payType")));
+        order.setFlow(Convert.toInt(odMap.get("flow")));
+        order.setStatus(Convert.toInt(odMap.get("status")));
+        order.setCreateTime(DateUtils.strForDate(Convert.toStr(odMap.get("createTime"))));
+        order.setUpdateTime(DateUtils.strForDate(Convert.toStr(odMap.get("updateTime"))));
+        order.setEndTime(DateUtils.strForDate(Convert.toStr(odMap.get("endTime"))));
+        return order;
+    }
+
+
+    private void setOrderCache(C2cOrderEntity c2cOrder) {
+        //设置订单 c2c_order_h:1
+        String odHKey = getC2cOrderKeyByOid(c2cOrder.getId().toString());
+        Map<String, Object> odMap = MapUtil.of("id", c2cOrder.getId());
+        odMap.put("orderNo", c2cOrder.getOrderNo());
+        odMap.put("userId", c2cOrder.getUserId());
+        odMap.put("userName", c2cOrder.getUserName());
+        odMap.put("direction", c2cOrder.getDirection());
+        odMap.put("legalCoin", c2cOrder.getLegalCoin());
+        odMap.put("symbol", c2cOrder.getSymbol());
+        odMap.put("c2cAdId", c2cOrder.getC2cAdId());
+        odMap.put("tranUserId", c2cOrder.getTranUserId());
+        odMap.put("tranUserName", c2cOrder.getTranUserName());
+        odMap.put("tranPrice", c2cOrder.getTranPrice());
+        odMap.put("symbolNum", c2cOrder.getSymbolNum());
+        odMap.put("tranAmount", c2cOrder.getTranAmount());
+        odMap.put("payType", c2cOrder.getPayType());
+        odMap.put("flow", c2cOrder.getFlow());
+        odMap.put("status", c2cOrder.getStatus());
+        odMap.put("createTime", DateUtils.format(c2cOrder.getCreateTime(),DateUtils.DATE_TIME_PATTERN));
+        odMap.put("updateTime", DateUtils.format(c2cOrder.getUpdateTime(),DateUtils.DATE_TIME_PATTERN));
+        odMap.put("endTime", DateUtils.format(c2cOrder.getEndTime(),DateUtils.DATE_TIME_PATTERN));
+        Random random = new Random();
+        long randomSecond = random.nextLong(3600L)+3600L; // 生成1到2小时的随机数
+        redisUtils.hMSet(odHKey, odMap, randomSecond);
+    }
+    private void setOrderUserIdCache(C2cOrderEntity c2cOrder) {
+        //c2c_order_uid:1
+        String odUserKey = getC2cOrderKeyByUid(c2cOrder.getUserId().toString());
+        redisUtils.set(odUserKey, c2cOrder.getId().toString());
+    }
+
+    @Override
+    public void deleteOrderCache(C2cOrderEntity c2cOrder) {
+        String odHKey = getC2cOrderKeyByOid(c2cOrder.getId().toString());
+        List list = new ArrayList<>();
+        list.add(odHKey);
+        String odUserKey = getC2cOrderKeyByUid(c2cOrder.getUserId().toString());
+        list.add(odUserKey);
+        redisUtils.delete(list);
+    }
+
+    @Override
+    public void deleteOrderCache(String orderId,String userId) {
+        String odHKey = getC2cOrderKeyByOid(orderId);
+        List list = new ArrayList<>();
+        list.add(odHKey);
+        String odUserKey = getC2cOrderKeyByUid(userId);
+        list.add(odUserKey);
+        redisUtils.delete(list);
+    }
+
+    /**
+     * 下订单,
+     * 买入:创建订单,更新广告的可用数量
+     * 卖出:创建订单,冻结卖家资产,更新广告的可用数量
+     * @param c2cOrderDTO
+     * @return
+     * @throws Exception
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result createC2cOrder(C2cOrderCreateDTO c2cOrderDTO, C2cAdEntity c2cAd, BigDecimal symbolNum,
+                                 Long loginUserId, String realName) throws Exception {
+        /** 1买入  2 卖出 */
+        Integer direction = c2cOrderDTO.getDirection();
+        /** 交易币 */
+        String symbol = c2cOrderDTO.getSymbol().toLowerCase();
+        /** 法定货币 */
+        String legalCoin = c2cOrderDTO.getLegalCoin().toLowerCase();
+        /** 交易金额 */
+        BigDecimal tranAmount = c2cOrderDTO.getTranAmount();
+        /** 广告编号 */
+        Long c2cAdId = c2cOrderDTO.getC2cAdId();
+        /** 支付方式 */
+        Integer payType = c2cOrderDTO.getPayType();
+
+
+        String adUserName = c2cAd.getUserName();
+        BigDecimal price = c2cAd.getPrice();
+        Long tranUserId = c2cAd.getUserId();
+
+        C2cOrderEntity c2cOrder = new C2cOrderEntity();
+        c2cOrder.setOrderNo("C"+ OrderUtils.generateAdNum());
+        c2cOrder.setUserId(loginUserId);
+        c2cOrder.setUserName(realName);
+        c2cOrder.setDirection(direction);
+        c2cOrder.setLegalCoin(legalCoin);
+        c2cOrder.setSymbol(symbol);
+        c2cOrder.setC2cAdId(c2cAdId);
+        c2cOrder.setTranUserId(tranUserId);
+        c2cOrder.setTranUserName(adUserName);
+        c2cOrder.setTranPrice(price);
+        c2cOrder.setSymbolNum(symbolNum);
+        c2cOrder.setTranAmount(tranAmount);
+        c2cOrder.setPayType(payType);
+        c2cOrder.setFlow(C2cOrderFlowEnum.PROGRESS.getCode());
+        c2cOrder.setStatus(C2cOrderStatusEnum.CREATE.getCode());
+        c2cOrder.setCreateTime(new Date());
+        c2cOrder.setUpdateTime(new Date());
+        c2cOrder.setEndTime(DateUtils.getNowDateAddMins(CacheConstants.C2C_ORDER_EXPIRE_MIN));
+
+        String adHKey = CacheConstants.getC2cAdHKey(c2cAd.getId().toString());
+        if(!insert(c2cOrder)) {
+            throw new Exception(MessageUtils.message("c2c.order.save.fail"));//保存广告失败
+        }
+        insertC2cOrderLog(c2cOrder.getId(), null, C2cOrderStatusEnum.CREATE.getCode(), "创建订单",loginUserId,"app");
+        //用户卖出冻结资金
+        if(c2cOrder.getDirection().intValue() == DirectionEnum.SELL.getCode().intValue()) {
+            AppAssetEntity userPlatformAsset = appAssetService.getAppAssetEntity(c2cOrder.getUserId(),
+                    c2cOrder.getSymbol(),AssetEnum.PLATFORM_ASSETS.getCode());
+            if(userPlatformAsset.getAvailable().compareTo(c2cOrder.getSymbolNum())==-1) {
+                throw new Exception(MessageUtils.message("c2c.order.availableAmount.insufficient"));//您的可用资产必须大于卖出数量
+            }
+            if (appAssetService.frozeAssetByUserId(loginUserId, c2cOrder.getSymbol(), c2cOrder.getSymbolNum()) == 0) {
+                throw new Exception(MessageUtils.message("c2c.order.update.asset.fail"));//更新卖家资产失败
+            }
+            appAssetLogService.insertAssetLog(c2cOrder.getId(),c2cOrder.getUserId(),c2cOrder.getSymbol(),AssetEnum.PLATFORM_ASSETS.getCode(),
+                    userPlatformAsset.getTotal(),userPlatformAsset.getTotal(),
+                    userPlatformAsset.getAvailable(),userPlatformAsset.getAvailable().subtract(c2cOrder.getSymbolNum()),
+                    userPlatformAsset.getFrozen(),userPlatformAsset.getFrozen().add(c2cOrder.getSymbolNum()),"c2c卖出冻结资产");
+        }
+
+        // 更新广告的可用数量
+        BigDecimal newMaxAmount = null;
+        Integer newStatus = null;
+        BigDecimal avaiAmount = c2cAd.getAvailableNum().subtract(symbolNum).multiply(price);
+        if(c2cAd.getMaxAmount().compareTo(avaiAmount)==1) {
+            newMaxAmount = avaiAmount;
+            redisUtils.hSet(adHKey, "maxAmount", newMaxAmount);
+        }
+        if(avaiAmount.compareTo(c2cAd.getMinAmount())==-1) {
+            newStatus = AdStatusEnum.NOPASS.getCode();
+            c2cAdService.deleteC2cAdCache(c2cAd);
+        }
+        if (c2cAdService.updateC2cAdAvailableNumById(c2cAdId, c2cOrder.getSymbolNum(), newMaxAmount, newStatus,c2cAd.getVersion()) == 0) {
+            throw new Exception(MessageUtils.message("operation.fail.please.refresh"));//操作失败,请刷新后重试
+        }
+        c2cAdLogService.insertC2cAdLog(c2cAdId,c2cOrder.getId(),c2cOrder.getSymbolNum(),
+                c2cAd.getAvailableNum(),c2cAd.getAvailableNum().subtract(c2cOrder.getSymbolNum()),
+                c2cAd.getMaxAmount(),
+                newMaxAmount!=null?newMaxAmount:c2cAd.getMaxAmount(),"创建C2C订单");
+
+
+        //设置缓存
+        setOrderCache(c2cOrder);
+        setOrderUserIdCache(c2cOrder);
+
+        if(c2cOrder.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            //用户待支付数+1
+//                unpayCountsKey = StringUtils.format(CacheConstants.C2C_UNPAY_COUNTS, c2cOrder.getUserId());
+        } else {
+            //如果是卖出,商家待支付数统计
+            String unpayCountsKey = CacheConstants.getC2cMertUnPayKey(c2cOrder.getTranUserId().toString());
+            redisUtils.increment(unpayCountsKey, 1L, RedisUtils.NOT_EXPIRE);
+        }
+
+
+        //发消息通知交易对手
+//        HashMap<String, Object> object = new HashMap<>();
+//        object.put("c2c_create",c2cOrder.getTranUserId().toString());
+//        redisUtils.addStream(redisStreamNamesApi,object);
+
+        return new Result().ok(c2cOrder.getId());
+
+    }
+
+
+
+    public void insertC2cOrderLog(Long id,Integer oldStatus,Integer newStatus,
+                                  String remark,Long loginId,String opType) throws Exception {
+        C2cOrderLogEntity c2cOrderLog = new C2cOrderLogEntity();
+        c2cOrderLog.setId(id);
+        c2cOrderLog.setOldStatus(oldStatus);
+        c2cOrderLog.setNewStatus(newStatus);
+        c2cOrderLog.setRemark(remark);
+        c2cOrderLog.setOpUserId(loginId);
+        c2cOrderLog.setOpType(opType);
+        c2cOrderLog.setCreateTime(new Date());
+        if(!c2cOrderLogService.insert(c2cOrderLog)) {
+            throw new Exception(MessageUtils.message("c2c.order.log.fail"));//插入订单日志失败
+        }
+    }
+
+
+    @Override
+    public int cancelC2cOrderRedis(int oldStatus,C2cOrderEntity order) {
+        //redis广告可用数量恢复
+        C2cAdEntity c2cAd = c2cAdService.selectById(order.getC2cAdId());
+        c2cAdService.deleteAdCache(c2cAd.getId(),c2cAd.getPayway().replaceAll("^,|,$", ""),c2cAd.getLegalCoin(),c2cAd.getSymbol(),c2cAd.getDirection());
+        c2cAdService.setAdCache(c2cAd);
+        deleteOrderCache(order);
+
+
+        //待处理数量
+        Long sellUserId = null;
+        Long buyUserId = null;
+        if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            sellUserId = order.getTranUserId();
+            if (oldStatus == C2cOrderStatusEnum.PAY.getCode().intValue()) {
+                //商家待放币数-1
+                String releaseCountsKey = CacheConstants.getC2cMertUnReleaseKey(sellUserId.toString());
+                long count = redisUtils.decrement(releaseCountsKey, 1L, RedisUtils.NOT_EXPIRE);
+                if(count < 0) {
+                    redisUtils.delete(releaseCountsKey);
+                }
+            }
+
+        } else {
+            buyUserId = order.getTranUserId();
+            if(oldStatus == C2cOrderStatusEnum.CREATE.getCode().intValue()) {
+                //商家待支付数-1
+                String unpayCountsKey = CacheConstants.getC2cMertUnPayKey(buyUserId.toString());
+                long count = redisUtils.decrement(unpayCountsKey, 1L, RedisUtils.NOT_EXPIRE);
+                if (count<0) {
+                    redisUtils.delete(unpayCountsKey);
+                }
+            }
+        }
+
+
+        //发消息
+//        HashMap<String, Object> object = new HashMap<>();
+//        object.put("c2c_cancel",order.getTranUserId().toString());
+//        redisUtil.addStream(redisStreamNamesApi,object);
+        return 1;
+    }
+
+
+    /**
+     * 买家主动取消
+     * @param order
+     * @return
+     * @throws Exception
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public int cancelC2cOrder(C2cOrderEntity order,Long loginId) throws Exception {
+        return cancelOrder(order,loginId,"app");
+    }
+
+    private int cancelOrder(C2cOrderEntity order,Long loginId,String source) throws Exception {
+        //卖家
+        Long sellUserId = getSellUserId(order);
+        if(sellUserId==null) {
+            throw new Exception(MessageUtils.message("c2c.seller.uid.not.empty"));//卖家编号不能空
+        }
+
+        insertC2cOrderLog(order.getId(), order.getStatus(), C2cOrderStatusEnum.CANCEL.getCode(),
+                order.getRemark(),loginId,source);
+
+        order.setFlow(C2cOrderFlowEnum.END.getCode());
+        order.setStatus(C2cOrderStatusEnum.CANCEL.getCode());
+        order.setUpdateTime(new Date());
+        order.setEndTime(new Date());
+        if(!updateById(order)) {
+            throw new Exception(MessageUtils.message("c2c.order.update.fail"));//更新订单失败
+        }
+
+        if(order.getDirection().intValue() == DirectionEnum.SELL.getCode().intValue()) {
+            AppAssetEntity info = appAssetService.getAppAssetEntity(order.getUserId(),order.getSymbol(),AssetEnum.PLATFORM_ASSETS.getCode());
+            if (appAssetService.unblockAssetByUserId(sellUserId, order.getSymbol(), order.getSymbolNum()) <= 0) {
+                throw new Exception(MessageUtils.message("c2c.user.occupied.asset.fail"));//用户资产解冻失败
+            }
+            appAssetLogService.insertAssetLog(order.getId(),order.getUserId(),order.getSymbol(),AssetEnum.PLATFORM_ASSETS.getCode(),
+                    info.getTotal(),info.getTotal(),
+                    info.getAvailable(),info.getAvailable().add(order.getSymbolNum()),
+                    info.getFrozen(),info.getFrozen().subtract(order.getSymbolNum()),"用户卖出订单取消解冻资产");
+        }
+        //广告可用数量恢复
+        C2cAdEntity c2cAd = c2cAdService.selectById(order.getC2cAdId());
+        BigDecimal maxAmount = null;
+        if(order.getTranAmount().compareTo(c2cAd.getMaxAmount())==1) {
+            maxAmount = order.getTranAmount();
+        }
+        if(c2cAdService.addC2cAdAvailableNumById(order.getC2cAdId(),order.getSymbolNum(),maxAmount,c2cAd.getVersion())<=0) {
+            throw new Exception(MessageUtils.message("c2c.ad.availAmount.update.fail"));//更新广告可用数量失败
+        }
+        c2cAdLogService.insertC2cAdLog(order.getC2cAdId(),order.getId(),order.getSymbolNum(),
+                c2cAd.getAvailableNum(),c2cAd.getAvailableNum().add(order.getSymbolNum()),
+                c2cAd.getMaxAmount(),c2cAd.getMaxAmount(),"用户取消订单恢复广告可用数量");
+        return 1;
+    }
+
+    /**
+     * 客服取消订单
+     * @param order
+     * @param loginId
+     * @return
+     * @throws Exception
+     */
+    @Override
+    public int kfCancelC2cOrder(C2cOrderEntity order,Long loginId) throws Exception {
+        return cancelOrder(order,loginId,"web");
+    }
+
+    private Long getBuyUserId(C2cOrderEntity order) {
+        if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            return order.getUserId();
+        } else {
+            return order.getTranUserId();
+        }
+    }
+
+    private Long getSellUserId(C2cOrderEntity order) {
+        if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            return order.getTranUserId();
+        } else {
+            return order.getUserId();
+        }
+    }
+
+    /**
+     * 买家确认付款
+     * @param order
+     * @return
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Result confirmPay(C2cOrderEntity order,Long loginId) throws Exception {
+        Long buyUserId = getBuyUserId(order);
+        Long sellUserId = getSellUserId(order);
+
+        insertC2cOrderLog(order.getId(), order.getStatus(), C2cOrderStatusEnum.PAY.getCode(),
+                order.getRemark(),loginId,"app");
+
+        order.setStatus(C2cOrderStatusEnum.PAY.getCode());
+        if(!updateById(order)) {
+            throw new Exception(MessageUtils.message("c2c.order.update.fail"));//更新订单失败
+        }
+        //设置订单状态
+        setOrderStatusCache(order);
+
+        //用户买入,用户未支付数减1 商家放币订单数+1
+        if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            String releaseCountsKey = CacheConstants.getC2cMertUnReleaseKey(sellUserId.toString());
+            redisUtils.increment(releaseCountsKey, 1L, RedisUtils.NOT_EXPIRE);
+        } else {
+            String unpayCountsKey = CacheConstants.getC2cMertUnPayKey(buyUserId.toString());
+            long count = redisUtils.decrement(unpayCountsKey, 1L,RedisUtils.NOT_EXPIRE);
+            if(count<0) {
+                redisUtils.delete(unpayCountsKey);
+            }
+        }
+
+        //发消息通知卖家
+//        HashMap<String, Object> object = new HashMap<>();
+//        object.put("c2c_pay",sellUserId.toString());
+//        redisUtil.addStream(redisStreamNamesApi,object);
+        return new Result();
+    }
+
+
+    /**
+     * 更新缓存订单状态
+     * @param order
+     */
+    private void setOrderStatusCache(C2cOrderEntity order) {
+        String odHKey = getC2cOrderKeyByOid(order.getId().toString());
+        if(redisUtils.hasKey(odHKey)) {
+            redisUtils.hSet(odHKey, "status", order.getStatus());
+        }
+    }
+
+
+    /**
+     * 卖家发放
+     * @param order
+     * @return
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public int verifyReceipt(C2cOrderEntity order,Long loginId) throws Exception {
+        Long buyUserId = getBuyUserId(order);
+        Long sellUserId = getSellUserId(order);
+        if(buyUserId==null || sellUserId==null || sellUserId.longValue() != loginId.longValue() ) {
+            throw new Exception(MessageUtils.message("c2c.order.not.seller"));//您不是卖家
+        }
+        passCoin(order, sellUserId, buyUserId, loginId, "app");
+        releaseCounts(order, sellUserId);
+        return 1;
+    }
+
+    //商家未放币订单数-1
+    private void releaseCounts(C2cOrderEntity order,Long sellUserId) {
+        if(order.getDirection().intValue() == DirectionEnum.BUY.getCode().intValue()) {
+            String releaseCountsKey = CacheConstants.getC2cMertUnReleaseKey(sellUserId.toString());
+            long count = redisUtils.decrement(releaseCountsKey, 1L, RedisUtils.NOT_EXPIRE);
+            if(count<0) {
+                redisUtils.delete(releaseCountsKey);
+            }
+        }
+    }
+
+    /**
+     * 客服放币
+     * @param order
+     * @return
+     * @throws Exception
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public int kfPassCoin(C2cOrderEntity order,Long loginId) throws Exception {
+        Long buyUserId = getBuyUserId(order);
+        Long sellUserId = getSellUserId(order);
+        return passCoin(order, sellUserId, buyUserId, loginId,"web");
+    }
+
+    private int passCoin(C2cOrderEntity order,Long sellUserId,Long buyUserId,Long loginId,String source) throws Exception{
+        insertC2cOrderLog(order.getId(), order.getStatus(), C2cOrderStatusEnum.COMPLETE.getCode(),
+                order.getRemark(),loginId,source);
+
+        order.setFlow(C2cOrderFlowEnum.END.getCode());
+        order.setStatus(C2cOrderStatusEnum.COMPLETE.getCode());
+        order.setUpdateTime(new Date());
+        order.setEndTime(new Date());
+        //1 更新订单状态已完成
+        if(!updateById(order)) {
+            throw new Exception(MessageUtils.message("c2c.order.update.fail"));//更新订单失败
+        }
+        //2 更新买家账户
+        AppAssetEntity buyerAsset = appAssetService.getAppAssetEntity(buyUserId, order.getSymbol(), AssetEnum.PLATFORM_ASSETS.getCode());
+
+        //判断是否需要创建买家资产账户
+        if (Objects.isNull(buyerAsset)) {
+            AppUserEntity buyUser = appUserService.selectById(buyUserId);
+            appAssetService.createAsset(buyUser, order.getSymbol(), AssetEnum.PLATFORM_ASSETS.getCode());
+
+            buyerAsset = new AppAssetEntity();
+            buyerAsset.setTotal(BigDecimal.ZERO);
+            buyerAsset.setFrozen(BigDecimal.ZERO);
+            buyerAsset.setAvailable(BigDecimal.ZERO);
+        }
+        //卖家资产
+        AppAssetEntity sellerAsset = appAssetService.getAppAssetEntity(sellUserId, order.getSymbol(), AssetEnum.PLATFORM_ASSETS.getCode());
+
+        if (appAssetService.addAssetByUserId(buyUserId, order.getSymbol(), order.getSymbolNum()) <= 0) {
+            throw new Exception(MessageUtils.message("c2c.buyer.asset.update.fail"));//更新买家资产失败
+        }
+
+        if(appAssetService.releaseAssetByUserId(sellUserId, order.getSymbol(), order.getSymbolNum()) <= 0) {
+            throw new Exception(MessageUtils.message("c2c.seller.asset.update.fail"));//更新卖家资产失败
+        }
+
+        //买家资产变更记录
+        appWalletRecordService.generateRecord(buyUserId, order.getSymbolNum(),
+                RecordEnum.C2C_TRAN_BUY.getCode(), "system", order.getOrderNo(),
+                RecordEnum.C2C_TRAN_BUY.getInfo(), buyerAsset.getTotal(), buyerAsset.getTotal().add(order.getSymbolNum()),
+                order.getSymbol(), "");
+
+        //卖家资产变更记录
+        appWalletRecordService.generateRecord(sellUserId, order.getSymbolNum(),
+                RecordEnum.C2C_TRAN_SELL.getCode(), "system", order.getOrderNo(),
+                RecordEnum.C2C_TRAN_SELL.getInfo(), buyerAsset.getTotal(), buyerAsset.getTotal().subtract(order.getSymbolNum()),
+                order.getSymbol(), "");
+
+        deleteOrderCache(order);
+
+        //通知买方已放币
+//        HashMap<String, Object> object = new HashMap<>();
+//        object.put("c2c_receipt", buyUserId.toString());
+//        redisUtil.addStream(redisStreamNamesApi, object);
+        return 1;
+    }
+
+
+    @Override
+    public List<C2cOrderEntity> selectPaymentVoucherByOrderList(List<C2cOrderEntity> orderList) {
+        if(!orderList.isEmpty()) {
+            List<Long> orderIdList = new ArrayList<>();
+            orderList.forEach(orderItem -> {
+                if (orderItem.getStatus().intValue() != C2cOrderStatusEnum.CREATE.getCode()) {
+                    orderIdList.add(orderItem.getId());
+                }});
+            if(!orderIdList.isEmpty()) {
+                Long[] orderIds = new  Long[orderIdList.size()];
+                orderIdList.toArray(orderIds);
+                List<C2cPaymentVoucherEntity> paymentVoucherList = c2cPaymentVoucherService.selectC2cPaymentVoucherByIds(orderIds);
+                Map<Long, List<C2cPaymentVoucherEntity>> payVouchGroup = paymentVoucherList.stream().collect(Collectors.groupingBy(C2cPaymentVoucherEntity::getOrderId));
+                orderList.forEach(order -> {
+                    if (payVouchGroup.containsKey(order.getId())) {
+                        order.setIsVoucher(1);
+                        order.setPayVoucherList(payVouchGroup.get(order.getId()));
+                    } else {
+                        order.setIsVoucher(0);
+                    }
+                });
+            }
+        }
+        return orderList;
+    }
+
+    @Override
+    public List<Map> selectMtUnPayCount(Long tranUserId) {
+        return selectMtUnPayCount(tranUserId);
+    }
+
+    @Override
+    public List<Map> selectMtUnReleaseCount(Long tranUserId) {
+        return selectMtUnReleaseCount(tranUserId);
+    }
+
+
+    /**
+     * 买家/卖家申诉
+     * @param order
+     * @return
+     * @throws Exception
+     */
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public Result complain(C2cOrderEntity order,C2cOrderComplainEntity c2cOrderComplain,Long loginId) throws Exception {
+        Long buyUserId = getBuyUserId(order);
+        Long sellUserId = getSellUserId(order);
+        Result result = new Result();
+        if(buyUserId.longValue()!=loginId.longValue() && sellUserId.longValue()!=loginId.longValue()) {
+            return result.error(MessageUtils.message("c2c.order.not.buyer.seller"));//您不是交易用户,不能发起申诉
+        }
+
+        if(order.getStatus().intValue() == C2cOrderStatusEnum.COMPLAIN.getCode()) {
+            return result;
+        }
+
+        insertC2cOrderLog(order.getId(), order.getStatus(), C2cOrderStatusEnum.COMPLAIN.getCode(), c2cOrderComplain.getReason(),StpUtil.getLoginIdAsLong(),"app");
+
+        order.setStatus(C2cOrderStatusEnum.COMPLAIN.getCode());
+        if(!updateById(order)) {
+            throw new Exception(MessageUtils.message("c2c.order.pay.update.fail"));//订单更新失败
+        }
+
+        if(loginId.longValue() == order.getUserId().longValue()) {
+            c2cOrderComplain.setFromUserId(order.getUserId());
+            c2cOrderComplain.setFromUserName(order.getUserName());
+            c2cOrderComplain.setToUserId(order.getTranUserId());
+            c2cOrderComplain.setToUserName(order.getTranUserName());
+        } else {
+            c2cOrderComplain.setFromUserId(order.getTranUserId());
+            c2cOrderComplain.setFromUserName(order.getTranUserName());
+            c2cOrderComplain.setToUserId(order.getUserId());
+            c2cOrderComplain.setToUserName(order.getUserName());
+        }
+        c2cOrderComplain.setStatus(C2cOrderComplainEnum.COMPLAINT.getCode());
+        c2cOrderComplain.setCreateTime(new Date());
+        if(!complainService.insert(c2cOrderComplain)) {
+            throw new Exception(MessageUtils.message("c2c.order.complain.submit.fail"));//提交申诉失败
+        }
+
+        //设置订单状态
+        setOrderStatusCache(order);
+
+        //邮件通知被申诉人
+//        TAppUser appUser = appUserService.getById(c2cOrderComplain.getToUserId());
+//        if(StringUtils.isNotEmpty(appUser.getEmail())) {
+//            String orderNo = new StringBuffer("******").append(StringUtils.substring(order.getOrderNo(),14)).toString();
+//            String emailText = new StringBuffer("您的订单号").append(orderNo).append(",金额为").append(order.getSymbolNum()).append(order.getSymbol()).append("的C2C订单被提交申诉。请登录您的C2C订单详情页以处理申诉。").toString();
+//            EmailUtils.sendComplainMail(appUser.getEmail(), emailText);
+//        }
+
+        releaseCounts(order, sellUserId);
+
+        return result.ok(c2cOrderComplain.getId());
+    }
+
+
+
+}

+ 45 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cPayWayServiceImpl.java

@@ -0,0 +1,45 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cPayWayDao;
+import com.qnfhq.modules.c2c.dto.C2cPayWayDTO;
+import com.qnfhq.modules.c2c.entity.C2cLegalCoinEntity;
+import com.qnfhq.modules.c2c.entity.C2cPayWayEntity;
+import com.qnfhq.modules.c2c.service.C2cPayWayService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 法币支付方式
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-18
+ */
+@Service
+public class C2cPayWayServiceImpl extends BaseServiceImpl<C2cPayWayDao, C2cPayWayEntity> implements C2cPayWayService {
+
+//    @Override
+//    public QueryWrapper<C2cPayWayEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cPayWayEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+    @Override
+    public List<C2cPayWayEntity> selectListByLegalCoin(String legalCoin) {
+        return baseDao.selectList(new LambdaQueryWrapper<C2cPayWayEntity>()
+                .eq(StrUtil.isNotBlank(legalCoin), C2cPayWayEntity::getCurrencyCode, legalCoin)
+                .eq(C2cPayWayEntity::getStatus,1)
+        );
+    }
+
+}

+ 52 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cPaymentVoucherServiceImpl.java

@@ -0,0 +1,52 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cPaymentVoucherDao;
+import com.qnfhq.modules.c2c.dto.C2cPaymentVoucherDTO;
+import com.qnfhq.modules.c2c.entity.C2cPaymentVoucherEntity;
+import com.qnfhq.modules.c2c.service.C2cPaymentVoucherService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * c2c付款证明
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cPaymentVoucherServiceImpl extends BaseServiceImpl<C2cPaymentVoucherDao, C2cPaymentVoucherEntity> implements C2cPaymentVoucherService {
+    private final C2cPaymentVoucherDao c2cPaymentVoucherDao;
+
+    public C2cPaymentVoucherServiceImpl(C2cPaymentVoucherDao c2cPaymentVoucherDao) {
+        super();
+        this.c2cPaymentVoucherDao = c2cPaymentVoucherDao;
+    }
+
+//    @Override
+//    public QueryWrapper<C2cPaymentVoucherEntity> getWrapper(Map<String, Object> params){
+//        String id = (String)params.get("id");
+//
+//        QueryWrapper<C2cPaymentVoucherEntity> wrapper = new QueryWrapper<>();
+//        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+//
+//        return wrapper;
+//    }
+
+    @Override
+    public List<C2cPaymentVoucherEntity> selectList(Long orderId) {
+        return baseDao.selectList(new QueryWrapper<C2cPaymentVoucherEntity>().eq("order_id", orderId)
+                .eq("status", 1).orderByDesc("id"));
+
+    }
+
+    @Override
+    public List<C2cPaymentVoucherEntity> selectC2cPaymentVoucherByIds(Long[] ids) {
+        return c2cPaymentVoucherDao.selectC2cPaymentVoucherByIds(ids);
+    }
+}

+ 56 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/c2c/service/impl/C2cUserReceiptServiceImpl.java

@@ -0,0 +1,56 @@
+package com.qnfhq.modules.c2c.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qnfhq.common.service.impl.BaseServiceImpl;
+import com.qnfhq.common.service.impl.CrudServiceImpl;
+import com.qnfhq.modules.c2c.dao.C2cUserReceiptDao;
+import com.qnfhq.modules.c2c.dto.C2cMyReceiptDTO;
+import com.qnfhq.modules.c2c.dto.C2cUserReceiptDTO;
+import com.qnfhq.modules.c2c.entity.C2cUserReceiptEntity;
+import com.qnfhq.modules.c2c.service.C2cUserReceiptService;
+import cn.hutool.core.util.StrUtil;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * c2c用户收款信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-17
+ */
+@Service
+public class C2cUserReceiptServiceImpl extends BaseServiceImpl<C2cUserReceiptDao, C2cUserReceiptEntity> implements C2cUserReceiptService {
+
+
+    private QueryWrapper<C2cUserReceiptEntity> getWrapper(Map<String, Object> params){
+        String id = (String)params.get("id");
+
+        QueryWrapper<C2cUserReceiptEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(StrUtil.isNotBlank(id), "id", id);
+
+        return wrapper;
+    }
+
+    @Override
+    public List<C2cUserReceiptEntity> selectListMyReceipt(C2cMyReceiptDTO dto) {
+        QueryWrapper<C2cUserReceiptEntity> wrapper = new QueryWrapper<>();
+        wrapper.eq(Objects.nonNull(dto.getUserId()), "user_id", dto.getUserId());
+        wrapper.eq(Objects.nonNull(dto.getType()), "type", dto.getType());
+        return baseDao.selectList(wrapper);
+    }
+
+    @Override
+    public C2cUserReceiptEntity selectOneMyReceipt(Long userId,Integer type) {
+        return baseDao.selectOne(new LambdaQueryWrapper<C2cUserReceiptEntity>()
+                .eq(Objects.nonNull(userId), C2cUserReceiptEntity::getUserId, userId)
+                .eq(Objects.nonNull(type), C2cUserReceiptEntity::getType, type)
+                .last(" limit 1"));
+    }
+
+
+}

+ 30 - 1
qnfhq-api/src/main/java/com/qnfhq/modules/user/dao/AppAssetDao.java

@@ -4,6 +4,8 @@ import com.qnfhq.common.dao.BaseDao;
 import com.qnfhq.modules.user.entity.AppAssetEntity;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.Map;
+
 /**
  * 玩家资产表
  *
@@ -12,5 +14,32 @@ import org.apache.ibatis.annotations.Mapper;
  */
 @Mapper
 public interface AppAssetDao extends BaseDao<AppAssetEntity> {
-	
+
+    /**
+     * 冻结资产
+     * @param params
+     * @return
+     */
+    int frozeAssetByUserId(Map<String,Object> params);
+
+    /**
+     * 解冻资产
+     * @param params
+     * @return
+     */
+    int unblockAssetByUserId(Map<String, Object> params);
+
+    /**
+     * c2c买币 增加资产
+     * @param params
+     * @return
+     */
+    int addAssetByUserId(Map<String, Object> params);
+
+    /**
+     * C2C卖家放币 减少资产
+     * @param params
+     * @return
+     */
+    int releaseAssetByUserId(Map<String, Object> params);
 }

+ 16 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dao/AppWalletRecordDao.java

@@ -0,0 +1,16 @@
+package com.qnfhq.modules.user.dao;
+
+import com.qnfhq.common.dao.BaseDao;
+import com.qnfhq.modules.user.entity.AppWalletRecordEntity;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 用户账变信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-20
+ */
+@Mapper
+public interface AppWalletRecordDao extends BaseDao<AppWalletRecordEntity> {
+	
+}

+ 75 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/dto/AppWalletRecordDTO.java

@@ -0,0 +1,75 @@
+package com.qnfhq.modules.user.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.media.SchemaProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import java.math.BigDecimal;
+
+/**
+ * 用户账变信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-20
+ */
+@Data
+@Schema(name = "用户账变信息")
+public class AppWalletRecordDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+	@SchemaProperty(name = "卡ID")
+	private Long id;
+
+	@SchemaProperty(name = "余额")
+	private BigDecimal amount;
+
+	@SchemaProperty(name = "")
+	private String createBy;
+
+	@SchemaProperty(name = "创建时间")
+	private Date createTime;
+
+	@SchemaProperty(name = "")
+	private String updateBy;
+
+	@SchemaProperty(name = "更新时间")
+	private Date updateTime;
+
+	@SchemaProperty(name = "")
+	private String remark;
+
+	@SchemaProperty(name = "用户id")
+	private Long userId;
+
+	@SchemaProperty(name = "")
+	private String searchValue;
+
+	@SchemaProperty(name = "前值")
+	private BigDecimal beforeAmount;
+
+	@SchemaProperty(name = "后值")
+	private BigDecimal afterAmount;
+
+	@SchemaProperty(name = "")
+	private String serialId;
+
+	@SchemaProperty(name = "账变类型")
+	private Integer type;
+
+	@SchemaProperty(name = "币种")
+	private String symbol;
+
+	@SchemaProperty(name = "代理ID")
+	private String adminParentIds;
+
+	@SchemaProperty(name = "换算U金额")
+	private BigDecimal uAmount;
+
+	@SchemaProperty(name = "操作时间")
+	private Date operateTime;
+
+
+}

+ 87 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/entity/AppWalletRecordEntity.java

@@ -0,0 +1,87 @@
+package com.qnfhq.modules.user.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 用户账变信息
+ *
+ * @author yelz 30262728@qq.com
+ * @since 1.0.0 2025-11-20
+ */
+@Data
+@TableName("t_app_wallet_record")
+public class AppWalletRecordEntity {
+
+    /**
+     * 卡ID
+     */
+	private Long id;
+    /**
+     * 余额
+     */
+	private BigDecimal amount;
+    /**
+     * 
+     */
+	private String createBy;
+    /**
+     * 创建时间
+     */
+	private Date createTime;
+    /**
+     * 
+     */
+	private String updateBy;
+    /**
+     * 更新时间
+     */
+	private Date updateTime;
+    /**
+     * 
+     */
+	private String remark;
+    /**
+     * 用户id
+     */
+	private Long userId;
+    /**
+     * 
+     */
+	private String searchValue;
+    /**
+     * 前值
+     */
+	private BigDecimal beforeAmount;
+    /**
+     * 后值
+     */
+	private BigDecimal afterAmount;
+    /**
+     * 
+     */
+	private String serialId;
+    /**
+     * 账变类型
+     */
+	private Integer type;
+    /**
+     * 币种
+     */
+	private String symbol;
+    /**
+     * 代理ID
+     */
+	private String adminParentIds;
+    /**
+     * 换算U金额
+     */
+	private BigDecimal uAmount;
+    /**
+     * 操作时间
+     */
+	private Date operateTime;
+}

+ 45 - 0
qnfhq-api/src/main/java/com/qnfhq/modules/user/enums/AuditStatusEnum.java

@@ -0,0 +1,45 @@
+package com.qnfhq.modules.user.enums;
+
+/**
+ * 实名认证状态
+ */
+public enum AuditStatusEnum {
+
+
+    /**
+     * 审核通过
+     */
+    EXAMINATION_PASSED(1,"审核通过"),
+
+    /**
+     * 不通过
+     */
+    AUDIT_NOT_PASSED(2,"不通过"),
+    /**
+     * 未审核
+     */
+    NOT_REVIEWED(3,"未审核"),
+
+
+
+
+    ;
+    private Integer code;
+
+    private String desc;
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getInfo()
+    {
+        return desc;
+    }
+
+    AuditStatusEnum(Integer code, String desc){
+        this.code = code;
+        this.desc = desc;
+    }
+}

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません