Payment Flow + Access Flow Change
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user