Payment Flow + Access Flow Change

This commit is contained in:
mr
2026-05-27 15:50:23 +02:00
parent e6a9558cbf
commit cef23b5f30
40 changed files with 2227 additions and 410 deletions
+151
View File
@@ -0,0 +1,151 @@
package payment
import (
"time"
"cloud.o-forge.io/core/oc-lib/models/common/pricing"
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
)
type PaymentStatus int
const (
PAYMENT_PENDING PaymentStatus = iota
PAYMENT_PROCESSING // en cours de traitement blockchain/réseau
PAYMENT_COMPLETED // confirmé
PAYMENT_FAILED // échoué
PAYMENT_CANCELLED // annulé avant exécution
PAYMENT_REFUNDED // remboursé
)
func (s PaymentStatus) String() string {
return [...]string{"pending", "processing", "completed", "failed", "cancelled", "refunded"}[s]
}
func PaymentStatusList() []PaymentStatus {
return []PaymentStatus{PAYMENT_PENDING, PAYMENT_PROCESSING, PAYMENT_COMPLETED, PAYMENT_FAILED, PAYMENT_CANCELLED, PAYMENT_REFUNDED}
}
type PaymentMethod int
const (
METHOD_BLOCKCHAIN PaymentMethod = iota
METHOD_CREDIT_CARD
METHOD_BANK_TRANSFER
METHOD_CRYPTO
METHOD_INTERNAL_CREDIT // crédit interne à la plateforme
)
func (m PaymentMethod) String() string {
return [...]string{"blockchain", "credit_card", "bank_transfer", "crypto", "internal_credit"}[m]
}
func PaymentMethodList() []PaymentMethod {
return []PaymentMethod{METHOD_BLOCKCHAIN, METHOD_CREDIT_CARD, METHOD_BANK_TRANSFER, METHOD_CRYPTO, METHOD_INTERNAL_CREDIT}
}
// Payment représente une transaction de paiement — instantanée, mensuelle ou annuelle.
type Payment struct {
utils.AbstractObject
BillID string `json:"bill_id,omitempty" bson:"bill_id,omitempty"`
InvoiceID string `json:"invoice_id,omitempty" bson:"invoice_id,omitempty"`
SubscriptionID string `json:"subscription_id,omitempty" bson:"subscription_id,omitempty"`
PayerPeerID string `json:"payer_peer_id,omitempty" bson:"payer_peer_id,omitempty"`
RecipientPeerID string `json:"recipient_peer_id,omitempty" bson:"recipient_peer_id,omitempty"`
Amount float64 `json:"amount" bson:"amount"`
Currency string `json:"currency" bson:"currency" default:"EUR"`
Status PaymentStatus `json:"status" bson:"status"`
Method PaymentMethod `json:"method" bson:"method"`
PaymentType pricing.PaymentType `json:"payment_type" bson:"payment_type"` // PAY_ONCE, PAY_EVERY_MONTH, PAY_EVERY_YEAR
TransactionID string `json:"transaction_id,omitempty" bson:"transaction_id,omitempty"`
WalletFrom string `json:"wallet_from,omitempty" bson:"wallet_from,omitempty"`
WalletTo string `json:"wallet_to,omitempty" bson:"wallet_to,omitempty"`
ScheduledAt *time.Time `json:"scheduled_at,omitempty" bson:"scheduled_at,omitempty"`
ProcessedAt *time.Time `json:"processed_at,omitempty" bson:"processed_at,omitempty"`
FailureReason string `json:"failure_reason,omitempty" bson:"failure_reason,omitempty"`
Metadata map[string]string `json:"metadata,omitempty" bson:"metadata,omitempty"`
}
// NewInstantPayment crée un paiement immédiat (PAY_ONCE).
func NewInstantPayment(billID, payerPeerID, recipientPeerID string, amount float64, currency string, method PaymentMethod) *Payment {
return &Payment{
BillID: billID,
PayerPeerID: payerPeerID,
RecipientPeerID: recipientPeerID,
Amount: amount,
Currency: currency,
Status: PAYMENT_PENDING,
Method: method,
PaymentType: pricing.PAY_ONCE,
}
}
// NewScheduledPayment crée un paiement programmé (mensuel ou annuel).
func NewScheduledPayment(subscriptionID, payerPeerID, recipientPeerID string, amount float64, currency string, method PaymentMethod, paymentType pricing.PaymentType, scheduledAt time.Time) *Payment {
return &Payment{
SubscriptionID: subscriptionID,
PayerPeerID: payerPeerID,
RecipientPeerID: recipientPeerID,
Amount: amount,
Currency: currency,
Status: PAYMENT_PENDING,
Method: method,
PaymentType: paymentType,
ScheduledAt: &scheduledAt,
}
}
// Complete marque le paiement comme confirmé.
func (p *Payment) Complete(transactionID string) {
now := time.Now().UTC()
p.Status = PAYMENT_COMPLETED
p.TransactionID = transactionID
p.ProcessedAt = &now
}
// Fail marque le paiement comme échoué.
func (p *Payment) Fail(reason string) {
now := time.Now().UTC()
p.Status = PAYMENT_FAILED
p.FailureReason = reason
p.ProcessedAt = &now
}
// Cancel annule le paiement s'il est encore en attente.
func (p *Payment) Cancel() bool {
if p.Status != PAYMENT_PENDING {
return false
}
p.Status = PAYMENT_CANCELLED
return true
}
// IsRefundable indique si le paiement peut faire l'objet d'un remboursement.
func (p *Payment) IsRefundable() bool {
return p.Status == PAYMENT_COMPLETED
}
func (p *Payment) GetAccessor(request *tools.APIRequest) utils.Accessor {
return NewAccessor(request)
}
func (p *Payment) StoreDraftDefault() {
p.IsDraft = true
}
func (p *Payment) CanUpdate(set utils.DBObject) (bool, utils.DBObject) {
incoming := set.(*Payment)
if !p.IsDraft && p.Status != incoming.Status {
return true, &Payment{
Status: incoming.Status,
TransactionID: incoming.TransactionID,
FailureReason: incoming.FailureReason,
}
}
return p.IsDraft, set
}
func (p *Payment) CanDelete() bool {
return p.IsDraft || p.Status == PAYMENT_PENDING
}