Add a full payment and subscription system supporting EasyPay (Alipay/WeChat), Stripe, and direct Alipay/WeChat Pay providers with multi-instance load balancing.
54 lines
1.8 KiB
Go
54 lines
1.8 KiB
Go
package payment
|
|
|
|
import (
|
|
"encoding/hex"
|
|
"fmt"
|
|
"log/slog"
|
|
|
|
dbent "github.com/Wei-Shaw/sub2api/ent"
|
|
"github.com/Wei-Shaw/sub2api/internal/config"
|
|
"github.com/google/wire"
|
|
)
|
|
|
|
// EncryptionKey is a named type for the payment encryption key (AES-256, 32 bytes).
|
|
// Using a named type avoids Wire ambiguity with other []byte parameters.
|
|
type EncryptionKey []byte
|
|
|
|
// ProvideEncryptionKey derives the payment encryption key from the TOTP encryption key in config.
|
|
// When the key is empty, nil is returned (payment features that need encryption will be disabled).
|
|
// When the key is non-empty but invalid (bad hex or wrong length), an error is returned
|
|
// to prevent startup with a misconfigured encryption key.
|
|
func ProvideEncryptionKey(cfg *config.Config) (EncryptionKey, error) {
|
|
if cfg.Totp.EncryptionKey == "" {
|
|
slog.Warn("payment encryption key not configured — encrypted payment config will be unavailable")
|
|
return nil, nil
|
|
}
|
|
key, err := hex.DecodeString(cfg.Totp.EncryptionKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("invalid payment encryption key (hex decode): %w", err)
|
|
}
|
|
if len(key) != 32 {
|
|
return nil, fmt.Errorf("payment encryption key must be 32 bytes, got %d", len(key))
|
|
}
|
|
return EncryptionKey(key), nil
|
|
}
|
|
|
|
// ProvideRegistry creates an empty payment provider registry.
|
|
// Providers are registered at runtime after application startup.
|
|
func ProvideRegistry() *Registry {
|
|
return NewRegistry()
|
|
}
|
|
|
|
// ProvideDefaultLoadBalancer creates a DefaultLoadBalancer backed by the ent client.
|
|
func ProvideDefaultLoadBalancer(client *dbent.Client, key EncryptionKey) *DefaultLoadBalancer {
|
|
return NewDefaultLoadBalancer(client, []byte(key))
|
|
}
|
|
|
|
// ProviderSet is the Wire provider set for the payment package.
|
|
var ProviderSet = wire.NewSet(
|
|
ProvideEncryptionKey,
|
|
ProvideRegistry,
|
|
ProvideDefaultLoadBalancer,
|
|
wire.Bind(new(LoadBalancer), new(*DefaultLoadBalancer)),
|
|
)
|