فهرست منبع

消息、通知、交易

qrs 2 هفته پیش
والد
کامیت
a0852d438c

+ 15 - 0
alien-config/src/main/java/shop/alien/config/redis/BaseRedisService.java

@@ -2,8 +2,10 @@ package shop.alien.config.redis;
 
 import lombok.RequiredArgsConstructor;
 import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.data.redis.core.script.RedisScript;
 import org.springframework.stereotype.Component;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -30,6 +32,19 @@ public class BaseRedisService {
     }
 
     /**
+     * 取出并删除列表中的所有元素(原子操作)
+     */
+    public List<String> popBatchFromList(String key) {
+        String luaScript =
+                "local elements = redis.call('LRANGE', KEYS[1], 0, -1) " +
+                        "redis.call('DEL', KEYS[1]) " +
+                        "return elements ";
+
+        RedisScript<List> script = RedisScript.of(luaScript, List.class);
+        return stringRedisTemplate.execute(script, Collections.singletonList(key));
+    }
+
+    /**
      * 添加List, 所有
      *
      * @param key   键

+ 24 - 0
alien-entity/src/main/java/shop/alien/entity/second/SecondTradeRecord.java

@@ -68,10 +68,34 @@ public class SecondTradeRecord extends Model<SecondTradeRecord> {
     @TableField("buyer_sign_in")
     private Integer buyerSignIn;
 
+    @ApiModelProperty(value = "买家签到时间")
+    @TableField("buyer_sign_in_time")
+    private Date buyerSignInTime;
+
+    @ApiModelProperty(value = "买家签到地点(经纬度)")
+    @TableField("buyer_sign_in_latitude_longitude")
+    private String buyerSignInLatitudeLongitude;
+
+    @ApiModelProperty(value = "买家签到地点(经纬度)")
+    @TableField("buyer_sign_in_latitude_longitude_address")
+    private String buyerSignInLatitudeLongitudeAddress;
+
     @ApiModelProperty(value = "卖家是否签到  0-未签到  1-已签到")
     @TableField("seller_sign_in")
     private Integer sellerSignIn;
 
+    @ApiModelProperty(value = "卖家签到时间")
+    @TableField("seller_sign_in_time")
+    private Date sellerSignInTime;
+
+    @ApiModelProperty(value = "卖家签到地点(经纬度)")
+    @TableField("seller_sign_in_latitude_longitude")
+    private String sellerSignInLatitudeLongitude;
+
+    @ApiModelProperty(value = "卖家签到地点(经纬度地址)")
+    @TableField("seller_sign_in_latitude_longitude_address")
+    private String sellerSignInLatitudeLongitudeAddress;
+
     @ApiModelProperty(value = "买家交易状态  1-交易成功  2-交易失败")
     @TableField("buyer_transaction_status")
     private Integer buyerTransactionStatus;

+ 1 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/WebsocketVo.java

@@ -14,7 +14,7 @@ public class WebsocketVo {
     @ApiModelProperty(value = "接收者id")
     private String receiverId;
 
-    @ApiModelProperty(value = "类别(消息-message 公告-notice 心跳-heartbeat)")
+    @ApiModelProperty(value = "类别  message:消息  notice:公告  heartbeat:心跳  receipt:消息发送成功回调(用来记录消息id)")
     private String category;
 
     @ApiModelProperty(value = "消息类型  1-文本  2-图片 3-链接分享  4-二手交易(确认/拒绝/取消)  5-二手交易签到提醒  6-二手交易已签到")

+ 2 - 1
alien-entity/src/main/java/shop/alien/mapper/second/SecondTradeRecordMapper.java

@@ -27,6 +27,7 @@ public interface SecondTradeRecordMapper extends BaseMapper<SecondTradeRecord> {
     @Select("select trade.id, goods.title, goods.home_image, goods.price, trade.transaction_amount, trade.trade_status, " +
             "       trade.transaction_latitude_longitude, trade.transaction_latitude_longitude_address, trade.transaction_location " +
             "from second_trade_record trade " +
-            "left join second_goods goods on goods.id = trade.goods_id ")
+            "left join second_goods goods on goods.id = trade.goods_id " +
+            "${ew.customSqlSegment} ")
     List<SecondTradeRecordVo> getTradeRecord(@Param(Constants.WRAPPER) QueryWrapper<SecondTradeRecord> wrapper);
 }

+ 3 - 2
alien-job/src/main/java/shop/alien/job/AlienJobApplication.java

@@ -3,13 +3,14 @@ package shop.alien.job;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.ComponentScan;
 
 
 @SpringBootApplication
-@ComponentScan({"shop.alien.job.*",
-})
+@ComponentScan({"shop.alien.job.*", "shop.alien.config.redis"})
 @MapperScan({"shop.alien.mapper"})
+@EnableFeignClients(basePackages = {"shop.alien.job.feign"})
 public class AlienJobApplication {
 
     public static void main(String[] args) {

+ 20 - 0
alien-job/src/main/java/shop/alien/job/feign/AlienStoreFeign.java

@@ -0,0 +1,20 @@
+package shop.alien.job.feign;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@FeignClient(url = "http://localhost:8888", name = "alien-store")
+public interface AlienStoreFeign {
+
+    @GetMapping("/websocket/sendMsgToClientByPhoneId")
+    JSONObject sendMsgToClientByPhoneId(@RequestParam(value = "messageReceiverId") String messageReceiverId,
+                                        @RequestParam(value = "senderId") String senderId,
+                                        @RequestParam(value = "receiverId") String receiverId,
+                                        @RequestParam(value = "category") String category,
+                                        @RequestParam(value = "type") String type,
+                                        @RequestParam(value = "text") String text,
+                                        @RequestParam(value = "messageId") Integer messageId);
+
+}

+ 185 - 0
alien-job/src/main/java/shop/alien/job/second/SecondGoodsTradeXxlJob.java

@@ -0,0 +1,185 @@
+package shop.alien.job.second;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.xxl.job.core.context.XxlJobHelper;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import shop.alien.config.redis.BaseRedisService;
+import shop.alien.entity.second.SecondTradeRecord;
+import shop.alien.entity.store.LifeMessage;
+import shop.alien.entity.store.LifeNotice;
+import shop.alien.entity.store.LifeUser;
+import shop.alien.entity.store.vo.WebsocketVo;
+import shop.alien.job.feign.AlienStoreFeign;
+import shop.alien.mapper.LifeMessageMapper;
+import shop.alien.mapper.LifeNoticeMapper;
+import shop.alien.mapper.LifeUserMapper;
+import shop.alien.mapper.second.SecondTradeRecordMapper;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class SecondGoodsTradeXxlJob {
+
+    private final SecondTradeRecordMapper secondTradeRecordMapper;
+
+    private final LifeNoticeMapper lifeNoticeMapper;
+
+    private final LifeUserMapper lifeUserMapper;
+
+    private final LifeMessageMapper lifeMessageMapper;
+
+    private final AlienStoreFeign alienStoreFeign;
+
+    private final BaseRedisService baseRedisService;
+
+    /**
+     * 商品交易时间十分钟之前发送签到提醒
+     */
+    @XxlJob("secondTradeRemind")
+    public void secondTradeRemind() {
+        try {
+            LocalDateTime now = LocalDateTime.now().withSecond(0).withNano(0);
+
+            // 查询所有待交易
+            LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
+            wrapper.eq(SecondTradeRecord::getTradeStatus, 3);
+            List<SecondTradeRecord> tradeRecordList = secondTradeRecordMapper.selectList(wrapper);
+
+            for (SecondTradeRecord tradeRecord : tradeRecordList) {
+                // 十分钟前
+                LocalDateTime tenMinutesAgo = tradeRecord.getTransactionTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().minusMinutes(10).withSecond(0).withNano(0);
+                // 交易时间的十分钟前
+                if (now.isEqual(tenMinutesAgo)) {
+                    // 封装交易信息
+                    JSONObject message = new JSONObject();
+                    message.put("tradeId", tradeRecord.getId());
+                    message.put("transactionAmount", tradeRecord.getTransactionAmount());
+                    message.put("transactionLatitudeLongitude", tradeRecord.getTransactionLatitudeLongitude());
+                    message.put("transactionLatitudeLongitudeAddress", tradeRecord.getTransactionLatitudeLongitudeAddress());
+                    message.put("transactionLocation", tradeRecord.getTransactionLocation());
+                    message.put("transactionTime", tradeRecord.getTransactionTime());
+                    message.put("tradeStatus", tradeRecord.getTradeStatus());
+
+                    LifeUser buyer = lifeUserMapper.selectById(tradeRecord.getBuyerId());
+                    LifeUser seller = lifeUserMapper.selectById(tradeRecord.getSellerId());
+
+                    String buyerPhoneId = null == buyer ? "" : "user_" + buyer.getUserPhone();
+                    String sellerPhoneId = null == seller ? "" : "user_" + seller.getUserPhone();
+
+                    // 给买家发送消息
+                    LifeMessage lifeMessage = new LifeMessage();
+                    lifeMessage.setSenderId(sellerPhoneId);
+                    lifeMessage.setReceiverId(buyerPhoneId);
+                    lifeMessage.setContent(message.toJSONString());
+                    lifeMessage.setType("5");
+                    lifeMessage.setIsRead(1);
+                    lifeMessageMapper.insert(lifeMessage);
+
+                    // 给买家推送消息
+                    WebsocketVo websocketVo = new WebsocketVo();
+                    websocketVo.setSenderId(sellerPhoneId);
+                    websocketVo.setReceiverId(buyerPhoneId);
+                    websocketVo.setCategory("message");
+                    websocketVo.setType("5");
+                    websocketVo.setText(message.toJSONString());
+                    websocketVo.setMessageId(lifeMessage.getId());
+                    alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, sellerPhoneId, buyerPhoneId, "message", "5", message.toJSONString(), lifeMessage.getId());
+
+                    // 给买家发送通知
+                    LifeNotice lifeNotice = new LifeNotice();
+                    lifeNotice.setSenderId("system");
+                    lifeNotice.setReceiverId(buyerPhoneId);
+                    lifeNotice.setBusinessId(tradeRecord.getId());
+                    lifeNotice.setTitle("交易签到提醒");
+                    lifeNotice.setContext("您有一笔交易即将开始, 请及时前往查看");
+                    lifeNotice.setNoticeType(1);
+                    lifeNoticeMapper.insert(lifeNotice);
+
+                    // 给买家推送通知
+                    websocketVo = new WebsocketVo();
+                    websocketVo.setSenderId("system");
+                    websocketVo.setReceiverId(buyerPhoneId);
+                    websocketVo.setCategory("notice");
+                    websocketVo.setType("5");
+                    websocketVo.setText(message.toJSONString());
+                    websocketVo.setMessageId(lifeMessage.getId());
+                    alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, "system", buyerPhoneId, "notice", "5", message.toJSONString(), lifeMessage.getId());
+
+                    // 给卖家发送消息
+                    lifeMessage = new LifeMessage();
+                    lifeMessage.setSenderId(buyerPhoneId);
+                    lifeMessage.setReceiverId(sellerPhoneId);
+                    lifeMessage.setContent(message.toJSONString());
+                    lifeMessage.setType("5");
+                    lifeMessage.setIsRead(1);
+                    lifeMessageMapper.insert(lifeMessage);
+
+                    // 给卖家推送消息
+                    websocketVo = new WebsocketVo();
+                    websocketVo.setSenderId(buyerPhoneId);
+                    websocketVo.setReceiverId(sellerPhoneId);
+                    websocketVo.setCategory("message");
+                    websocketVo.setType("5");
+                    websocketVo.setText(message.toJSONString());
+                    websocketVo.setMessageId(lifeMessage.getId());
+                    alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, buyerPhoneId, sellerPhoneId, "message", "5", message.toJSONString(), lifeMessage.getId());
+
+                    // 给卖家发送通知
+                    lifeNotice = new LifeNotice();
+                    lifeNotice.setSenderId("system");
+                    lifeNotice.setReceiverId(sellerPhoneId);
+                    lifeNotice.setBusinessId(tradeRecord.getId());
+                    lifeNotice.setTitle("交易签到提醒");
+                    lifeNotice.setContext("您有一笔交易即将开始, 请及时前往查看");
+                    lifeNotice.setNoticeType(1);
+                    lifeNoticeMapper.insert(lifeNotice);
+
+                    // 给卖家推送通知
+                    websocketVo = new WebsocketVo();
+                    websocketVo.setSenderId("system");
+                    websocketVo.setReceiverId(sellerPhoneId);
+                    websocketVo.setCategory("notice");
+                    websocketVo.setType("5");
+                    websocketVo.setText(message.toJSONString());
+                    websocketVo.setMessageId(lifeMessage.getId());
+                    alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, "system", sellerPhoneId, "notice", "5", message.toJSONString(), lifeMessage.getId());
+                }
+            }
+        } catch (Exception e) {
+            log.error("SecondGoodsTradeXxlJob.secondTradeRemind Error Mgs={}", e.getMessage());
+        }
+    }
+
+    /**
+     * 每分钟从redis中读取已读的消息id 并将数据库设为已读
+     */
+    @XxlJob("readMessage")
+    public void readMessage() {
+        try {
+            if (CollectionUtil.isEmpty(baseRedisService.getList("readMessageIdKey"))) {
+                return;
+            }
+
+            List<String> dataList = baseRedisService.popBatchFromList("readMessageIdKey");
+            if (CollectionUtil.isNotEmpty(dataList)) {
+                LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
+                wrapper.in(LifeMessage::getId, dataList)
+                        .set(LifeMessage::getIsRead, 1);
+                lifeMessageMapper.update(null, wrapper);
+            }
+        } catch (Exception e) {
+            log.error("ScheduledTask.readMessage Error Mgs={}", e.getMessage());
+        }
+    }
+}

+ 203 - 21
alien-job/src/main/resources/application-prod.yml

@@ -1,42 +1,224 @@
 spring:
-  # redis 配置
+
+  servlet:
+    multipart:
+      max-file-size: 100MB
+      max-request-size: 100MB
+
+  http:
+    multipart:
+      max-file-size: 100MB
+      max-request-size: 100MB
+
+  jackson:
+    default-property-inclusion: non_null
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+
   redis:
-    # 地址
-    host: 127.0.0.1
-    # 端口,默认为6379
+    host: 8.152.195.41
     port: 6379
-    # 数据库索引
     database: 10
     # 密码
-    password: ssk172380199
-    # 连接超时时间
+    password: wady@1213
     timeout: 10s
     lettuce:
       pool:
-        # 连接池中的最小空闲连接
         min-idle: 0
-        # 连接池中的最大空闲连接
         max-idle: 8
-        # 连接池的最大数据库连接数
         max-active: 8
-        # #连接池最大阻塞等待时间(使用负值表示没有限制)
         max-wait: -1ms
 
   datasource:
-    url: jdbc:mysql://xiaokuihua.fun:3006/sunflower_assistant?useUnicode=true&characterEncoding=utf8&jdbcCompliantTruncation=false&verifyServerCertificate=false&useSSL=false&rewriteBatchedStatements=true&serverTimezone=GMT%2b8
-    username: root
-    password: .,ZyL021405
-    driver-class-name: com.mysql.cj.jdbc.Driver
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      url: jdbc:mysql://8.152.195.41:3306/alien?serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
+      username: root
+      password: wady@1213
+      #url: jdbc:mysql://39.103.60.142:3306/locallife?serverTimezone=Asia/Shanghai&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false
+      #password: n*XMiDIcQ&8$HOPf
+
+      #连接初始化数量
+      initial-size: 1
+      #连接池中的最小空闲连接数
+      min-idle: 1
+      #配置连接池同时能维持的最大连接数
+      max-active: 20
+      #获取连接等待超时时间,单位是毫秒
+      #      max-wait: 60000
+      #间隔多久进行一次检测,检测需要关闭的空闲连接
+      time-between-eviction-runs-millis: 60000
+      #一个连接在池中最小生存的时间,单位是毫秒
+      min-evictable-idle-time-millis: 300000
+      #一个连接在池中最大生存的时间,单位是毫秒
+      max-evictable-idle-time-millis: 900000
+      #Druid用来测试连接是否可用的SQL语句
+      validation-query: SELECT 'x' FROM DUAL
+      #申请连接的时候检测
+      test-while-idle: true
+      #申请连接时执行validationQuery检测连接是否有效
+      test-on-borrow: true
+      #归还连接时执行validationQuery检测连接是否有效
+      test-on-return: false
+      #是否缓存preparedStatement
+      pool-prepared-statements: false
+      #最大缓存
+      max-pool-prepared-statement-per-connection-size: 20
+      #监控统计用的filter:stat
+      filters: stat
+      #通过connectProperties属性来打开mergeSql功能;慢SQL记录
+      connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=10000
+      stat-view-servlet:
+        #是否开启druid管理界面
+        enabled: true
+      #是否启用StatFilter默认值false,用于采集 web-jdbc 关联监控的数据。
+      web-stat-filter:
+        enabled: true
+        #排除一些静态资源,以提高效率
+        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
+        #需要监控的 url
+        url-pattern: "/*"
+
+  web:
+    resources:
+      # 上传静态资源目录
+      #static-locations: /usr/local/alien/file
+      # 上传app目录
+      app-locations: /usr/local/alien/file/app
+      static-locations: E:/usr/local/alien/file
+      url: http://devfile.ailien.shop/
+      # excel表格
+      excel-path: /usr/local/alien/file/excel/
+      # 回执单模板名称
+      excel-clearing-receipt: clearing_receipt.xlsx
+      #生成的文件地址
+      excel-generate-path: /generate/
+
+  elasticsearch:
+    rest:
+      uris: http://localhost:9200
+
+mybatis-plus:
+  #实体扫描,多个package用逗号或者分号分隔
+  typeAliasesPackage: shop.alien.store.entity
+  global-config:
+    #数据库相关配置
+    db-config:
+      #主键类型  AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
+      id-type: auto #主键自增
+      auto-fill: true #自动填充
+      logic-delete-value: 1 #逻辑删除值
+      logic-not-delete-value: 0 #逻辑未删除值
+  #    banner: false
+  #原生配置
+  configuration:
+    #数据库字段驼峰下划线转换
+    map-underscore-to-camel-case: true
+    cache-enabled: false
+    call-setters-on-nulls: true
+    jdbc-type-for-null: 'null'
+    # 打印sql
+    # sql只打印到控制台
+    #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
+    # sql 打印到日志和控制台
+    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
+
+# 分页
+pagehelper:
+  helperDialect: mysql
+  reasonable: true
+  supportMethodsArguments: true
+  params: count=countSql
 
 logging:
   config: classpath:logback-spring.xml
   level:
-    cc:
-      xiaokuihua:
-        xiaokuihuaentity:
-          analysis:
-            mapper: error
+    shop:
+      alien:
+        mapper: debug
 
     com:
       baomidou:
-        mybatisplus: error
+        mybatisplus: debug
+
+#阿里云短信
+ali:
+  aes:
+    #对称加密算法密钥
+    encryptKey: '4lSSA6Fi+4BG1qhakxdncw=='
+
+  #短信
+  sms:
+    endPoint: 'dysmsapi.aliyuncs.com'
+    accessKeyId: 'LTAI5tNeG9kUFWTYukrtVQxU'
+    accessKeySecret: 'vIWYJQWzCRcfH3rgnH5cuq05KEOwgw'
+    signName: '爱丽恩严大连商务科技'
+    templateCode: 'SMS_483575093'
+
+  yundun:
+    accessKeyID:
+      LTAI5tReZWshffH78oQJPzZG
+    secret:
+      Gi30OLYAWunaDbwsv5qqdZ3PzbDyGP
+    regionId:
+      cn-beijing
+    textEndpoint:
+      green-cip.cn-beijing.aliyuncs.com
+    imgEndpoint:
+      green-cip.cn-beijing.aliyuncs.com
+
+  oss:
+    endPoint: oss-cn-beijing.aliyuncs.com
+    bucketName: alien-volume
+    accessKeyId: LTAI5tG6wSYrSgN3Cwek17Du
+    accessKeySecret: PQDPdTtDy0v848p0Bl9vT5yHmpt79H
+
+#支付宝app
+app:
+  #商家端
+  business:
+    appId: 2021004191696239
+    #app公钥
+    appPublicKey: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqIxlCU8fx+mDYF6XEqtl7u/8ylH8TLLUcPx0wn00m/V/LT1vbd70QU4oyaPRslCmfj6mscadR2DeDK5Flpp67DDvPERU3UxMCxMNbKuv6MPsxedh5PnZkLGQ5NGlImv/xtJ6A9kFbSu62y51TL96/R7gwzwdxr5nph+qNfUr40THvHhvcqVV695YSktgcHOrg6pfpeOIAuTpdUs5gPEt7RuGhSz2x3+bOC2c1hdwc4azqcJ5Tz45DxTXG5PWxcSybqDg3Rh5rISzhLgipQYdoGoAHTWgJUmoqBlRMVhiRHxUKYs8Gng/4Ksvyq+EXREcswe34tmUHvBTmbGM6aDtvQIDAQAB'
+    #app私钥
+    appPrivateKey: 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCojGUJTx/H6YNgXpcSq2Xu7/zKUfxMstRw/HTCfTSb9X8tPW9t3vRBTijJo9GyUKZ+Pqaxxp1HYN4MrkWWmnrsMO88RFTdTEwLEw1sq6/ow+zF52Hk+dmQsZDk0aUia//G0noD2QVtK7rbLnVMv3r9HuDDPB3GvmemH6o19SvjRMe8eG9ypVXr3lhKS2Bwc6uDql+l44gC5Ol1SzmA8S3tG4aFLPbHf5s4LZzWF3BzhrOpwnlPPjkPFNcbk9bFxLJuoODdGHmshLOEuCKlBh2gagAdNaAlSaioGVExWGJEfFQpizwaeD/gqy/Kr4RdERyzB7fi2ZQe8FOZsYzpoO29AgMBAAECggEAarRHGree9R7eb1oy5jzgUX5ZWXTB94SXfdg1yxMdBUdMdkWYj8RAej+TDuTJUsxAO1hKi+2jkJbAvOJvZ8Lw4yqvqkXQPDGbSr+LFiszOHchJMExdpa+qB3iDxqyIrKgwSxq1pjEGLNAnpYw6J+oqyqrPK6IY1QTplYRmgtW949+Wa+0nkH8rKczbX4VZhT1u3OAXSj+0IoJLm+6AM73Q3U+Zu95WSKiX9rKN7IBFjHZJm+1NLDQMroilcLvgbJ1Q7Tez+0r0yOdeFEnq3ZIuEs95bRLCyew36QOVK8qSMPAPtkoRRWH+iCgWJ6nTZK+HphL+6WN0Llm8eVWFcNnuQKBgQD44L0o9da2lBp98UcmZRp7+dAIiLySwzThKcMfcIlLahFddFpwVzZHIWl4nN3YT12aPmT/aN31tQ9IO2t+L2iZglPgbzZIcZOJhp9Xott7onp3yMrB0Jxs/rEAlRuR3CHY0ONnrkPMIMAFCdRRpffuHcqqhJavBBs9ThLFw3e33wKBgQCtXysAtAa9j3IC6x3aImKzhAVJJyOzR8DBWP1FPVS4R9o0752Fjwa7FAgi4B04FTw+QOWUbdw9pzupjlgetRM1oCkAcvF1dT2+i7kOjjq/hM2lE63PY9nLNWDGbl8mt15J62w4GA61efH9AAUrA3KaEj5Or5Y+q04sITeWmG994wKBgH++o3ltzlsC5CI3AUVE6fYuwMhQnzJZvj/AtuXhVqd99xHYEj/NlA+op8GACyLnge0VD7RFuIBRAloaHc+0N+VrjvAJRXyjx430qr9J2Yy5VlE7oE8ha9lKVcItxuv0aO8oMUFbonMZcFZluDR8kykG46royYtl+TFbbKlT7pRTAoGABCfq3Ppzyul8XyuJrKf0W79HbSh+B5cpvLjIYXeF52D5jxlLWl9CVwu04jkjGiwQJKHjnvo/NE8k8/yQijPnAPsU4Ijg1uL3lvC8f+fS6rJhR5rAKN+I4gEmj7snlsMAhJ8bGgEhoSIKNflhJlXP0nerfLFi1Z+/oPku3vJKgecCgYEAy5UkL8X1OGMIanrm53Bx4N0kSv1D2RlR52LGwCfkglaSH1sVrlXiDIyr55bieiyUQ4J5uknta/hGXnJM9w8w8+HM1gmbO5vXyTUQLEt4k9gBJECY82ZrxxtTKXDprryxKciM9Zs46cDsuEQWbpr8Ps4NIeI9F6LfClbDJiQBdCY='
+
+    win:
+      #应用公钥证书文件路径
+      appCertPath: 'E:/Cache/business/appCertPublicKey_2021004191696239.crt'
+      #支付宝公钥证书文件路径
+      alipayPublicCertPath: 'E:/Cache/business/alipayCertPublicKey_RSA2.crt'
+      #支付宝根证书文件路径
+      alipayRootCertPath: 'E:/Cache/business/alipayRootCert.crt'
+
+    linux:
+      #应用公钥证书文件路径
+      appCertPath: '/usr/local/alien/aliPayCert/appCertPublicKey_2021004191696239.crt'
+      #支付宝公钥证书文件路径
+      alipayPublicCertPath: '/usr/local/alien/aliPayCert/alipayCertPublicKey_RSA2.crt'
+      #支付宝根证书文件路径
+      alipayRootCertPath: '/usr/local/alien/aliPayCert/alipayRootCert.crt'
+
+  #用户端
+  user:
+    appId: 2021004192631044
+    #app公钥
+    appPublicKey: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgSlnroP58xYTdsFxY9BuMJVJHEkp2K+DzV9EOk5hCq91E33rHLxizYRTkIGQ+Fw4+Qkrjcj330+eVI7ZABkdqF2YQah0hPbWSnyJtdJuECTgb8ZSoYTInA1aoKOkifBNy6/yeOARW+Sus3uLDt+svtQJuJ04sFO8YLQOQRomLfztdRsUsdnBUoEufb7hTeAnpJD/4lj2zsRGhKzi/bqSq4iRDg2sr6FJurFaROqXND9R8/DLQNuJQfj0bCaf2u2bNAVtodFzS/HWeXWeGH03JU9NQByBUB5KHZd3qUQaYmkpSNAEOJyt8e6weNFk2mEYhVlLC8nx7gj0NvAoEh7s7QIDAQAB'
+    #app私钥
+    appPrivateKey: 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCBKWeug/nzFhN2wXFj0G4wlUkcSSnYr4PNX0Q6TmEKr3UTfescvGLNhFOQgZD4XDj5CSuNyPffT55UjtkAGR2oXZhBqHSE9tZKfIm10m4QJOBvxlKhhMicDVqgo6SJ8E3Lr/J44BFb5K6ze4sO36y+1Am4nTiwU7xgtA5BGiYt/O11GxSx2cFSgS59vuFN4CekkP/iWPbOxEaErOL9upKriJEODayvoUm6sVpE6pc0P1Hz8MtA24lB+PRsJp/a7Zs0BW2h0XNL8dZ5dZ4YfTclT01AHIFQHkodl3epRBpiaSlI0AQ4nK3x7rB40WTaYRiFWUsLyfHuCPQ28CgSHuztAgMBAAECggEABHzQymJxe72nnXepHeOvAGcfbCkqmAm5FZiawT/Z5UolUjEMyynMcQGI+btWsxpZLGXiKoHyAsM8aAmyhmtY+XGPCbD1o20EEwBytGuEQXFWjuugEVaQtcNNA8nLvLMpsMsDLKn0UHIIk9nWAgVJdjPdxplHz/CI2f9Hg4GKFAzpXwV1c574+rSDIkpa2NDFI2lqwtbew7/1ETaCiBXSbqw4X/tk+2wgUdT8u4uA/Ts5bVZvvHm54U9ZdTLs2rHzIk2O9VbKB3waHT1WkQzrPF8+JrPvcYjsK7ROxi07N1e5kv4TuxLfK3rXvmoUI8TvidSLhmq57VXhU9iNZBEHwQKBgQD4GR58WhOotPHcNI5oKRkJSektNSz/pXFLjh3oF/y98kOuFfeH903Z+JQ/5fgjzQjKra3HqjsVDlTjhCSZtNc/QpYafMf6TGzX+41QNnjlxxeZgYa2CCPOAlOw8d1a6YV0v8mjjnWoh2+vaYaqBKZmm2uid9zyklbg8I0DZiYaUQKBgQCFRogto52N6i5QSMwPGrPJOabKqkpA2EtbEgnkrpybN5DFQ+OqwWujQVkwWNlufHAhWdb2OCJ+bb2dCwrmX8kHB/SF+VSlYGsRdDAONF9aVGHqnaJB1yvfwp4ArNUb0vORJun22jRCpmtN0dA7lS/PnwqgCZw8LNWkAFuVewSl3QKBgF+PdVGadHYH9BzIVY3DPrR4NotGLyXs+J2MiPJrwtr65Jy6M1S4qdDqUVfnYVOQ1vESQpxkckti8MmNjXdy03G3WQ+svm4nX8k1SDH8OUbwD6P94wBcVEY2WTwPfR5WUiQs9yK7bZBTUm5zK/5yuhFNjgDPQFhii3oqzXXgs45xAoGADjZ4XU2ehrzblYo94Lp7Q9FXHTPN2V53os2oqm+ImfDyCmd0Bwi7ftyAM2y2O1cf6h6XkwhnfU4cs3uy/OBoIszRYdw2D7DZmjHm0gz5wjtPeeK3pAfbUPCDQxUrYN09RlR9DOs2OYlf1huy9jexspWGX4zG0ZACdIvpOGa3Fy0CgYEA8waJ9ciOG50VjX/f/vYRKQUQTFQKhvZ0xcFnA8iT30FNfBs7XOhiBaXF25mul34hHhAxVuUIlEmOqyEkLO/ZWioOtWy//gRZIFL8qHoCaM8lS8xwT/xOz8nfDiu2hpISEXAquU2PNdP4yGiLg4qyafrvdctRw4TtpHEOrtYYyt8='
+    #支付宝公钥
+    aliPayPublicKey: 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqEK+9FHCA4GX/veehln6mFaYdpfAA8knkF8rRMX1RGunTZcIGs65yPvmGuyEhNZH3hajbGIMt4AKrdi9NO+1kSCSNc14IKYhpQFq6NIHxQHYP2+0aRCPy3JPpCBSowjWuzounh2uaEOImatykCSRiuicFymlwb8cv75vlOp6Pq6Gu+Ep/NIeHbhqbE9YtScmaRBvwpn0tz9M1yN9AVDuZD6VxSfjObtgMDQqHSUJJmmRuo4/DYGX0rkvtzhQcJbU9LTA1QkBWKgriww/4ZyAMg7q02FQ0dh81h9DxC0ugPhSo55FouMx7wrgN/GPYrdcEyOojpzgSYZC3uRnWuqZpQIDAQAB'
+
+gaode:
+  key: e1042879da68199b4b3545ebc146c8fc
+  distanceUrl: 'https://restapi.amap.com/v3/distance?key=%s&origins=%s,%s&destination=%s,%s'
+  geoUrl: 'https://restapi.amap.com/v3/geocode/geo?address=%s&key=%s'
+  geoListUrl: 'https://restapi.amap.com/v3/assistant/inputtips?keywords=%s&key=%s&city=%s'
+  getDistrict: 'https://restapi.amap.com/v3/config/district?key=%s&keywords=%s'
+  nearUrl: 'https://restapi.amap.com/v3/place/around?location=%s,%s&key=%s&radius=%s&offset=%s&page=%s'
+  subwayUrl: 'https://restapi.amap.com/v3/place/around?key=%s&location=%s,%s&keywords=%s&radius=%s&types=%s&sortrule=distance'
+  addressUrl: 'https://restapi.amap.com/v3/geocode/regeo?location=%s,%s&key=%s&radius=%s&extensions=%s'
+
+jwt:
+  #token过期时间, 单位:d:天、h:小时、m:分钟、s:秒
+  expiration-time: 30d

+ 5 - 3
alien-second/src/main/java/shop/alien/second/controller/SecondTradeRecordController.java

@@ -80,11 +80,13 @@ public class SecondTradeRecordController {
     @ApiOperationSupport(order = 4)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "tradeId", value = "交易id", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "messageId", value = "消息id", dataType = "Integer", paramType = "query", required = true)})
+            @ApiImplicitParam(name = "messageId", value = "消息id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "signInLatitudeLongitude", value = "签到地点(经纬度)", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "signInLatitudeLongitudeAddress", value = "签到地点(经纬度地址)", dataType = "String", paramType = "query", required = true)})
     @GetMapping("/tradeSignIn")
-    public R<Boolean> tradeSignIn(@RequestParam int tradeId, int messageId) throws Exception {
+    public R<Boolean> tradeSignIn(@RequestParam int tradeId, int messageId, String signInLatitudeLongitude, String signInLatitudeLongitudeAddress) throws Exception {
         log.info("SecondTradeRecordController.tradeSignIn?tradeId={}, messageId={}", tradeId, messageId);
-        if (secondTradeRecordService.tradeSignIn(tradeId, messageId)) return R.success("签到成功");
+        if (secondTradeRecordService.tradeSignIn(tradeId, messageId, signInLatitudeLongitude, signInLatitudeLongitudeAddress)) return R.success("签到成功");
         return R.fail("签到失败");
     }
 

+ 1 - 1
alien-second/src/main/java/shop/alien/second/service/SecondTradeRecordService.java

@@ -25,7 +25,7 @@ public interface SecondTradeRecordService extends IService<SecondTradeRecord> {
 
     boolean cancelTrade(int tradeId, String cancelReason, String cancelReasonSupplement) throws Exception;
 
-    boolean tradeSignIn(int tradeId, int messageId) throws Exception;
+    boolean tradeSignIn(int tradeId, int messageId, String signInLatitudeLongitude, String signInLatitudeLongitudeAddress) throws Exception;
 
     boolean tradeCompleteConfirm(int tradeId, int type, String evaluate) throws Exception;
 

+ 73 - 122
alien-second/src/main/java/shop/alien/second/service/impl/SecondTradeRecordServiceImpl.java

@@ -7,13 +7,13 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import shop.alien.entity.second.SecondGoods;
 import shop.alien.entity.second.SecondTradeRecord;
 import shop.alien.entity.second.vo.SecondTradeRecordVo;
 import shop.alien.entity.store.LifeMessage;
 import shop.alien.entity.store.LifeUser;
 import shop.alien.entity.store.StoreDictionary;
-import shop.alien.entity.store.vo.WebsocketVo;
 import shop.alien.mapper.LifeMessageMapper;
 import shop.alien.mapper.LifeUserMapper;
 import shop.alien.mapper.StoreDictionaryMapper;
@@ -23,6 +23,9 @@ import shop.alien.second.feign.AlienStoreFeign;
 import shop.alien.second.service.SecondTradeRecordService;
 import shop.alien.util.common.JwtUtil;
 
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
 import java.util.List;
 import java.util.Objects;
 
@@ -46,12 +49,8 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
     private final AlienStoreFeign alienStoreFeign;
     private final StoreDictionaryMapper storeDictionaryMapper;
 
-    /**
-     * 创建交易
-     * @param trade 交易记录对象
-     * @return 操作结果
-     */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public boolean createTrade(SecondTradeRecord trade) throws Exception {
         try {
             // 保存交易记录
@@ -81,8 +80,10 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
      * @param goods        商品信息
      * @param trade        交易信息
      * @param tradeStatus  1-待确认  2-已拒绝  3-待交易  6-交易取消
+     * @param messageType  4-二手交易创建/确认/拒绝/取消  5-二手交易签到提醒  6-二手交易已签到
      */
-    private void sendMsg(SecondGoods goods, SecondTradeRecord trade, Integer tradeStatus, String messageType) {
+    @Transactional(rollbackFor = Exception.class)
+    public void sendMsg(SecondGoods goods, SecondTradeRecord trade, Integer tradeStatus, String messageType) {
         // 封装交易信息
         JSONObject message = new JSONObject();
         message.put("title", goods.getTitle());
@@ -142,6 +143,7 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public boolean tradeConfirm(int tradeId, int messageId, int type) throws Exception {
         try {
             // 修改交易状态
@@ -160,40 +162,31 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
             // 商品信息
             SecondGoods goods = secondGoodsMapper.selectById(trade.getGoodsId());
 
+            // 修改待确认的消息
+            LifeMessage lastMessage = lifeMessageMapper.selectById(messageId);
+
+            JSONObject lastMessageContent = JSONObject.parseObject(lastMessage.getContent());
+            lastMessageContent.put("messageId", lastMessage.getId());
+            lastMessageContent.put("tradeStatus", type == 1 ? 3 : 2);
+            LifeMessage message = new LifeMessage();
+            message.setId(lastMessage.getId());
+            message.setContent(lastMessageContent.toJSONString());
+            lifeMessageMapper.updateById(message);
+
             // 发送消息
             sendMsg(goods, trade, trade.getTradeStatus(), "4");
 
-//            // 发起交易人信息
-//            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
-//            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
-//
-//            // 获取交易对方信息
-//            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
-//            String receiverId = "user_" + lifeUser.getUserPhone();
-//
-//            // 封装交易信息
-//            JSONObject message = new JSONObject();
-//            message.put("title", goods.getTitle());
-//            message.put("homeImage", goods.getHomeImage());
-//            message.put("tradeId", trade.getId());
-//            message.put("transactionAmount", trade.getTransactionAmount());
-//            message.put("transactionLatitudeLongitude", trade.getTransactionLatitudeLongitude());
-//            message.put("transactionLatitudeLongitudeAddress", trade.getTransactionLatitudeLongitudeAddress());
-//            message.put("transactionLocation", trade.getTransactionLocation());
-//            message.put("transactionTime", trade.getTransactionTime());
-//            message.put("tradeStatus", 3);
-//
-//            // 保存消息记录
-//            LifeMessage lifeMessage = new LifeMessage();
-//            lifeMessage.setSenderId(phoneId);
-//            lifeMessage.setReceiverId(receiverId);
-//            lifeMessage.setType("4");
-//            lifeMessage.setContent(message.toJSONString());
-//            lifeMessageMapper.insert(lifeMessage);
-//
-//            // 给买家与卖家发送交易消息
-//            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, phoneId, receiverId, "message", "4", message.toJSONString(), lifeMessage.getId());
-//            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, phoneId, receiverId, "message", "4", message.toJSONString(), lifeMessage.getId());
+            // 发起交易人信息
+            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
+            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
+
+            // 获取交易对方信息
+            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
+            String receiverId = "user_" + lifeUser.getUserPhone();
+
+            // 给买家与卖家发送交易消息
+            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, phoneId, receiverId, "message", "4", lastMessageContent.toJSONString(), lastMessage.getId());
+            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, phoneId, receiverId, "message", "4", lastMessageContent.toJSONString(), lastMessage.getId());
 
             return true;
         } catch (Exception e) {
@@ -203,11 +196,11 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public boolean cancelTrade(int tradeId, String cancelReason, String cancelReasonSupplement) throws Exception {
         try {
             // 发起交易人信息
             Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
-            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
 
             // 修改交易状态
             SecondTradeRecord tradeRecord = new SecondTradeRecord();
@@ -221,50 +214,8 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
             // 交易信息
             SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);
 
-            // 商品信息
-            SecondGoods goods = secondGoodsMapper.selectById(trade.getGoodsId());
-
             // 发送消息
-            sendMsg(goods, trade, 6, "4");
-
-//            // 获取交易对方信息
-//            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
-//            String receiverId = "user_" + lifeUser.getUserPhone();
-//
-//            // 封装交易信息
-//
-//            JSONObject message = new JSONObject();
-//            message.put("title", goods.getTitle());
-//            message.put("homeImage", goods.getHomeImage());
-//            message.put("tradeId", trade.getId());
-//            message.put("transactionAmount", trade.getTransactionAmount());
-//            message.put("transactionLatitudeLongitude", trade.getTransactionLatitudeLongitude());
-//            message.put("transactionLatitudeLongitudeAddress", trade.getTransactionLatitudeLongitudeAddress());
-//            message.put("transactionLocation", trade.getTransactionLocation());
-//            message.put("transactionTime", trade.getTransactionTime());
-//            message.put("tradeStatus", 6);
-//            message.put("cancelUserId", trade.getCancelUserId());
-//            message.put("cancelReason", trade.getCancelReason());
-//            message.put("cancelReasonSupplement", trade.getCancelReasonSupplement());
-//
-//            // 查询字典表
-//            LambdaQueryWrapper<StoreDictionary> wrapper = new LambdaQueryWrapper<>();
-//            wrapper.eq(StoreDictionary::getTypeName, "cancelTradeReason");
-//            wrapper.eq(StoreDictionary::getDictId, trade.getCancelReason());
-//            StoreDictionary storeDictionary = storeDictionaryMapper.selectOne(wrapper);
-//            message.put("cancelReasonName", null == storeDictionary ? "" : storeDictionary.getDictDetail());
-//
-//            // 保存消息记录
-//            LifeMessage lifeMessage = new LifeMessage();
-//            lifeMessage.setSenderId(phoneId);
-//            lifeMessage.setReceiverId(receiverId);
-//            lifeMessage.setType("4");
-//            lifeMessage.setContent(message.toJSONString());
-//            lifeMessageMapper.insert(lifeMessage);
-//
-//            // 给买家与卖家发送交易消息
-//            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, phoneId, receiverId, "message", "4", message.toJSONString(), lifeMessage.getId());
-//            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, phoneId, receiverId, "message", "4", message.toJSONString(), lifeMessage.getId());
+            sendMsg(secondGoodsMapper.selectById(trade.getGoodsId()), trade, 6, "4");
 
             return true;
         } catch (Exception e) {
@@ -274,59 +225,59 @@ public class SecondTradeRecordServiceImpl extends ServiceImpl<SecondTradeRecordM
     }
 
     @Override
-    public boolean tradeSignIn(int tradeId, int messageId) throws Exception {
+    @Transactional(rollbackFor = Exception.class)
+    public boolean tradeSignIn(int tradeId, int messageId, String signInLatitudeLongitude, String signInLatitudeLongitudeAddress) throws Exception {
         try {
-            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
             SecondTradeRecord trade = secondTradeRecordMapper.selectById(tradeId);
+            if (null == trade) return false;
+
+            // 发起交易人信息
+            int userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
+            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
+
+            // 获取交易对方信息
+            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
+            String receiverId = "user_" + lifeUser.getUserPhone();
+
+            // 保存交易签到信息
             SecondTradeRecord record = new SecondTradeRecord();
             record.setId(tradeId);
+            Date now = Date.from(LocalDateTime.now().withSecond(0).withNano(0).atZone(ZoneId.systemDefault()).toInstant());
             if (userId == trade.getBuyerId()) {
                 record.setBuyerSignIn(1);
+                record.setBuyerSignInTime(now);
+                record.setBuyerSignInLatitudeLongitude(signInLatitudeLongitude);
+                record.setBuyerSignInLatitudeLongitudeAddress(signInLatitudeLongitudeAddress);
             } else if (userId == trade.getSellerId()) {
                 record.setSellerSignIn(1);
+                record.setSellerSignInTime(now);
+                record.setSellerSignInLatitudeLongitude(signInLatitudeLongitude);
+                record.setSellerSignInLatitudeLongitudeAddress(signInLatitudeLongitudeAddress);
             } else {
                 return false;
             }
             secondTradeRecordMapper.updateById(record);
 
-            // 商品信息
-            SecondGoods goods = secondGoodsMapper.selectById(trade.getGoodsId());
-
-            // 发送消息
-            sendMsg(goods, trade, 3, "6");
-
-            // 封装交易信息
-//            JSONObject message = new JSONObject();
-//            message.put("title", goods.getTitle());
-//            message.put("homeImage", goods.getHomeImage());
-//            message.put("tradeId", trade.getId());
-//            message.put("transactionAmount", trade.getTransactionAmount());
-//            message.put("transactionLatitudeLongitude", trade.getTransactionLatitudeLongitude());
-//            message.put("transactionLatitudeLongitudeAddress", trade.getTransactionLatitudeLongitudeAddress());
-//            message.put("transactionLocation", trade.getTransactionLocation());
-//            message.put("transactionTime", trade.getTransactionTime());
-//            message.put("tradeStatus", 3);
-//
-//            // 发起交易人信息
-////            Integer userId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getInteger("userId");
-//            String phoneId = JwtUtil.getCurrentUserInfo().getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
-//
-//            // 获取交易对方信息
-//            LifeUser lifeUser = lifeUserMapper.selectById(Objects.equals(userId, trade.getBuyerId()) ? trade.getSellerId() : trade.getBuyerId());
-//            String receiverId = "user_" + lifeUser.getUserPhone();
-//
-//            // 消息
-//            LifeMessage lifeMessage = new LifeMessage();
-//            lifeMessage.setSenderId(phoneId);
-//            lifeMessage.setReceiverId(receiverId);
-//            lifeMessage.setType("6");
-//            lifeMessage.setContent(message.toJSONString());
-//            lifeMessageMapper.insert(lifeMessage);
-//
-//            // 给买家与卖家发送交易消息
-//            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, phoneId, receiverId, "message", "6", message.toJSONString(), lifeMessage.getId());
-//            alienStoreFeign.sendMsgToClientByPhoneId(r
-//           eceiverId, phoneId, receiverId, "message", "6", message.toJSONString(), lifeMessage.getId());
+            // 删除签到提醒
+            LifeMessage signInMessage = lifeMessageMapper.selectById(messageId);
+            lifeMessageMapper.deleteById(messageId);
+
+            // 发送已签到消息
+            JSONObject messageContent = JSONObject.parseObject(signInMessage.getContent());
+            messageContent.put("tradeId", tradeId);
+            messageContent.put("signInTime", now.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
+            messageContent.put("signInLatitudeLongitude", signInLatitudeLongitude);
+            messageContent.put("signInLatitudeLongitudeAddress", signInLatitudeLongitudeAddress);
+            LifeMessage message = new LifeMessage();
+            message.setSenderId(phoneId);
+            message.setReceiverId(receiverId);
+            message.setContent(messageContent.toJSONString());
+            message.setType("6");
+            lifeMessageMapper.insert(message);
+
+            // 推送已签到消息
+            alienStoreFeign.sendMsgToClientByPhoneId(phoneId, phoneId, receiverId, "message", "6", messageContent.toJSONString(), message.getId());
+            alienStoreFeign.sendMsgToClientByPhoneId(receiverId, phoneId, receiverId, "message", "6", messageContent.toJSONString(), message.getId());
 
             return true;
         } catch (Exception e) {

+ 2 - 0
alien-store/src/main/java/shop/alien/store/config/BaseRedisService.java

@@ -1,5 +1,6 @@
 package shop.alien.store.config;
 
+import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.geo.*;
 import org.springframework.data.redis.connection.RedisGeoCommands;
@@ -19,6 +20,7 @@ import java.util.concurrent.TimeUnit;
  * @date 2022/3/14 15:14
  */
 @Component
+@RequiredArgsConstructor
 public class BaseRedisService {
 
     @Autowired