goldenChat base source add
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
package com.goldenchart.service;
|
||||
|
||||
import com.goldenchart.entity.GcFcmToken;
|
||||
import com.goldenchart.repository.GcFcmTokenRepository;
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.messaging.*;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class FcmPushService {
|
||||
|
||||
private final GcFcmTokenRepository tokenRepo;
|
||||
private final AppSettingsService appSettingsService;
|
||||
|
||||
@Value("${firebase.enabled:false}")
|
||||
private boolean firebaseEnabled;
|
||||
|
||||
@Transactional
|
||||
public void registerToken(Long userId, String deviceId, String token) {
|
||||
if (token == null || token.isBlank()) return;
|
||||
String dev = deviceId != null ? deviceId : "anonymous";
|
||||
Optional<GcFcmToken> existing = tokenRepo.findByToken(token);
|
||||
if (existing.isPresent()) {
|
||||
GcFcmToken t = existing.get();
|
||||
t.setUserId(userId);
|
||||
t.setDeviceId(dev);
|
||||
t.setActive(true);
|
||||
t.setLastUsedAt(LocalDateTime.now());
|
||||
tokenRepo.save(t);
|
||||
} else {
|
||||
tokenRepo.save(GcFcmToken.builder()
|
||||
.token(token)
|
||||
.userId(userId)
|
||||
.deviceId(dev)
|
||||
.active(true)
|
||||
.lastUsedAt(LocalDateTime.now())
|
||||
.build());
|
||||
}
|
||||
log.info("[FCM] token registered device={}", dev);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteByDevice(String deviceId) {
|
||||
if (deviceId != null) tokenRepo.deleteByDeviceId(deviceId);
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return firebaseEnabled && !FirebaseApp.getApps().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 매매 시그널 FCM — deviceId 일치 토큰 + fcm_push_enabled 설정 시.
|
||||
*/
|
||||
public void sendTradeSignalIfEnabled(String deviceId, Long userId, String market,
|
||||
String signalType, double price,
|
||||
String strategyName, Long signalId) {
|
||||
if (!isAvailable() || deviceId == null) return;
|
||||
var app = appSettingsService.getEntity(userId, deviceId);
|
||||
if (!Boolean.TRUE.equals(app.getFcmPushEnabled())) return;
|
||||
|
||||
List<GcFcmToken> tokens = tokenRepo.findByDeviceIdAndActiveTrue(deviceId);
|
||||
if (tokens.isEmpty()) {
|
||||
tokens = tokenRepo.findByActiveTrue();
|
||||
}
|
||||
if (tokens.isEmpty()) return;
|
||||
|
||||
String title = "BUY".equals(signalType) ? "🟢 매수 시그널" : "🔴 매도 시그널";
|
||||
String body = String.format("%s · ₩%,.0f%s",
|
||||
market, price,
|
||||
strategyName != null ? " · " + strategyName : "");
|
||||
|
||||
for (GcFcmToken t : tokens) {
|
||||
try {
|
||||
Message msg = Message.builder()
|
||||
.setToken(t.getToken())
|
||||
.setNotification(Notification.builder().setTitle(title).setBody(body).build())
|
||||
.putData("type", "trade_signal")
|
||||
.putData("signalId", signalId != null ? String.valueOf(signalId) : "")
|
||||
.putData("market", market)
|
||||
.putData("signalType", signalType)
|
||||
.putData("price", String.valueOf(price))
|
||||
.build();
|
||||
FirebaseMessaging.getInstance().send(msg);
|
||||
t.setLastUsedAt(LocalDateTime.now());
|
||||
tokenRepo.save(t);
|
||||
} catch (FirebaseMessagingException e) {
|
||||
log.warn("[FCM] send failed: {}", e.getMessagingErrorCode());
|
||||
if (e.getMessagingErrorCode() == MessagingErrorCode.UNREGISTERED
|
||||
|| e.getMessagingErrorCode() == MessagingErrorCode.INVALID_ARGUMENT) {
|
||||
t.setActive(false);
|
||||
tokenRepo.save(t);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("[FCM] send error: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendTest(Long userId, String deviceId) {
|
||||
if (!isAvailable()) {
|
||||
log.warn("[FCM] test skipped — Firebase not initialized");
|
||||
return;
|
||||
}
|
||||
List<GcFcmToken> tokens = deviceId != null
|
||||
? tokenRepo.findByDeviceIdAndActiveTrue(deviceId)
|
||||
: tokenRepo.findByActiveTrue();
|
||||
for (GcFcmToken t : tokens) {
|
||||
try {
|
||||
Message msg = Message.builder()
|
||||
.setToken(t.getToken())
|
||||
.setNotification(Notification.builder()
|
||||
.setTitle("GoldenChart 테스트")
|
||||
.setBody("FCM 푸시가 정상 동작합니다.")
|
||||
.build())
|
||||
.putData("type", "test")
|
||||
.build();
|
||||
FirebaseMessaging.getInstance().send(msg);
|
||||
} catch (Exception e) {
|
||||
log.warn("[FCM] test send failed: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user