chore: add crypto payment
This commit is contained in:
@@ -76,6 +76,7 @@ func IPNWebhook(c *gin.Context) {
|
||||
|
||||
// GetCommandPaymentStatus - GET /api/v1/commands/:id/payment-status
|
||||
// Retourne le statut du paiement crypto d'une commande (polling côté client)
|
||||
// Effectue un refresh temps réel depuis NowPayments si le paiement est encore en attente
|
||||
func GetCommandPaymentStatus(c *gin.Context) {
|
||||
database := c.MustGet("database").(*db.Database)
|
||||
|
||||
@@ -95,6 +96,30 @@ func GetCommandPaymentStatus(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Refresh temps réel depuis NowPayments pour les statuts intermédiaires (comme la référence)
|
||||
switch payment.Status {
|
||||
case "waiting", "confirming", "confirmed", "sending":
|
||||
np, npOk := c.Get("nowpayments")
|
||||
if npOk && np != nil {
|
||||
npClient := np.(*services.NowPaymentsClient)
|
||||
npStatus, err := npClient.GetPaymentStatus(payment.NowPaymentID)
|
||||
if err == nil && npStatus.PaymentStatus != payment.Status {
|
||||
payAmount, _ := npStatus.PayAmount.Float64()
|
||||
if updateErr := database.UpdateCryptoPaymentStatus(payment.ID, npStatus.PaymentStatus, payAmount); updateErr == nil {
|
||||
payment.Status = npStatus.PaymentStatus
|
||||
payment.PayAmount = payAmount
|
||||
log.Printf("[PAYMENT-STATUS] cmd %d: %s → %s (refresh temps réel)", commandID, payment.Status, npStatus.PaymentStatus)
|
||||
}
|
||||
switch npStatus.PaymentStatus {
|
||||
case "finished", "confirmed":
|
||||
_ = database.ActivateCryptoCommand(commandID)
|
||||
case "failed", "expired":
|
||||
_ = database.CancelCryptoCommand(commandID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"command_id": payment.CommandID,
|
||||
"payment_status": payment.Status,
|
||||
|
||||
@@ -27,15 +27,17 @@ func GetPublicSettings(c *gin.Context) {
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"penalties_enabled": settings.PenaltiesEnabled,
|
||||
"show_amende_score": settings.ShowAmendeScore,
|
||||
"points_enabled": settings.PointsEnabled,
|
||||
"points_separated": len(settings.PointsPools) > 1,
|
||||
"pool_names": poolNames,
|
||||
"pool_keys": poolKeys,
|
||||
"referral_enabled": settings.ReferralEnabled,
|
||||
"delivery_schedule": settings.DeliverySchedule,
|
||||
"success": true,
|
||||
"penalties_enabled": settings.PenaltiesEnabled,
|
||||
"show_amende_score": settings.ShowAmendeScore,
|
||||
"points_enabled": settings.PointsEnabled,
|
||||
"points_separated": len(settings.PointsPools) > 1,
|
||||
"pool_names": poolNames,
|
||||
"pool_keys": poolKeys,
|
||||
"referral_enabled": settings.ReferralEnabled,
|
||||
"delivery_schedule": settings.DeliverySchedule,
|
||||
"crypto_payment_enabled": settings.CryptoPaymentEnabled,
|
||||
"nowpayments_currencies": settings.NowPaymentsCurrencies,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,16 @@ func main() {
|
||||
// Démarrage des workers Redis en arrière-plan
|
||||
go workers.StartRedisWorkers(database)
|
||||
log.Println("✅ Workers Redis démarrés")
|
||||
|
||||
// Worker de vérification des paiements crypto (recharge les clés dynamiquement)
|
||||
workers.StartDynamicPaymentChecker(database, func() *services.NowPaymentsClient {
|
||||
s, err := database.GetSettings()
|
||||
if err != nil || !s.CryptoPaymentEnabled || s.NowPaymentsAPIKey == "" {
|
||||
return nil
|
||||
}
|
||||
return services.NewNowPaymentsClient(s.NowPaymentsAPIKey, s.NowPaymentsIPNSecret)
|
||||
}, 2*time.Minute)
|
||||
log.Println("✅ Worker paiements crypto démarré (2 min)")
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
r := gin.Default()
|
||||
|
||||
@@ -118,6 +128,16 @@ func main() {
|
||||
c.Next()
|
||||
})
|
||||
|
||||
// Middleware NowPayments : injecte le client si crypto activé dans les settings
|
||||
r.Use(func(c *gin.Context) {
|
||||
settings, err := database.GetSettings()
|
||||
if err == nil && settings.CryptoPaymentEnabled && settings.NowPaymentsAPIKey != "" {
|
||||
np := services.NewNowPaymentsClient(settings.NowPaymentsAPIKey, settings.NowPaymentsIPNSecret)
|
||||
c.Set("nowpayments", np)
|
||||
}
|
||||
c.Next()
|
||||
})
|
||||
|
||||
// Fichiers statiques
|
||||
r.Static("/uploads", "./uploads")
|
||||
|
||||
|
||||
@@ -17,6 +17,23 @@ func StartPaymentChecker(database *db.Database, np *services.NowPaymentsClient,
|
||||
log.Printf("[CRON] payment checker démarré (toutes les %s)", interval)
|
||||
}
|
||||
|
||||
// StartDynamicPaymentChecker démarre un checker qui recharge le client NowPayments à chaque tick
|
||||
// (permet de prendre en compte les changements de clé API sans redémarrer)
|
||||
func StartDynamicPaymentChecker(database *db.Database, clientFn func() *services.NowPaymentsClient, interval time.Duration) {
|
||||
go func() {
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
np := clientFn()
|
||||
if np == nil {
|
||||
continue
|
||||
}
|
||||
checkPendingCryptoPayments(database, np)
|
||||
}
|
||||
}()
|
||||
log.Printf("[CRON] payment checker dynamique démarré (toutes les %s)", interval)
|
||||
}
|
||||
|
||||
func checkPendingCryptoPayments(database *db.Database, np *services.NowPaymentsClient) {
|
||||
payments, err := database.GetPendingCryptoPayments()
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user