fix payment and account controller recharge failed (#1617)

Signed-off-by: fanux <fanux@sealos.io>

Signed-off-by: fanux <fanux@sealos.io>
This commit is contained in:
中弈
2022-08-24 23:27:46 +08:00
committed by GitHub
parent 4f8ec792d8
commit 55cdca07a5
5 changed files with 47 additions and 43 deletions
@@ -106,7 +106,9 @@ func (in *AccountStatus) DeepCopyInto(out *AccountStatus) {
if in.ChargeList != nil {
in, out := &in.ChargeList, &out.ChargeList
*out = make([]Charge, len(*in))
copy(*out, *in)
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
@@ -123,7 +125,7 @@ func (in *AccountStatus) DeepCopy() *AccountStatus {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Charge) DeepCopyInto(out *Charge) {
*out = *in
out.Time = in.Time
in.Time.DeepCopyInto(&out.Time)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Charge.
@@ -34,16 +34,13 @@ spec:
type: object
spec:
description: AccountSpec defines the desired state of Account
properties:
balance:
description: Foo is an example field of Account. Edit account_types.go
to remove/update
format: int64
type: integer
type: object
status:
description: AccountStatus defines the observed state of Account
properties:
balance:
format: int64
type: integer
chargeList:
description: 'INSERT ADDITIONAL STATUS FIELD - define observed state
of cluster Important: Run "make" to regenerate code after modifying
@@ -56,29 +53,8 @@ spec:
status:
type: string
time:
description: Timestamp is a struct that is equivalent to Time,
but intended for protobuf marshalling/unmarshalling. It is
generated into a serialization that matches Time. Do not use
in Go structs.
properties:
nanos:
description: Non-negative fractions of a second at nanosecond
resolution. Negative second values with fractions must
still have non-negative nanos values that count forward
in time. Must be from 0 to 999,999,999 inclusive. This
field may be limited in precision depending on context.
format: int32
type: integer
seconds:
description: Represents seconds of UTC time since Unix epoch
1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z
to 9999-12-31T23:59:59Z inclusive.
format: int64
type: integer
required:
- nanos
- seconds
type: object
format: date-time
type: string
tradeNO:
type: string
type: object
@@ -21,12 +21,17 @@ import (
"fmt"
"time"
v1 "k8s.io/api/core/v1"
"github.com/labring/sealos/pkg/constants"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/api/errors"
"github.com/labring/sealos/pkg/pay"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/source"
userv1 "github.com/labring/sealos/controllers/user/api/v1"
@@ -55,35 +60,45 @@ type AccountReconciler struct {
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.12.2/pkg/reconcile
func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
payment := &userv1.Payment{}
if err := r.Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: req.Name}, payment); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
err := r.Get(ctx, client.ObjectKey{Namespace: req.Namespace, Name: req.Name}, payment)
if errors.IsNotFound(err) {
return ctrl.Result{}, nil
}
if payment.Spec.UserID == "" || payment.Spec.Amount == 0 || payment.Status.TradeNO == "" {
if err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get payment: %v", err)
}
if payment.Spec.UserID == "" || payment.Spec.Amount == 0 {
return ctrl.Result{}, fmt.Errorf("payment is invalid: %v", payment)
}
if payment.Status.TradeNO == "" {
return ctrl.Result{Requeue: true, RequeueAfter: time.Millisecond * 300}, nil
}
if payment.Status.Status == pay.StatusSuccess {
return ctrl.Result{}, nil
}
account := &userv1.Account{}
account.Name = payment.Spec.UserID
err := r.Get(ctx, req.NamespacedName, account)
account.Namespace = constants.SealosSystemNamespace
err = r.Get(ctx, client.ObjectKey{Namespace: constants.SealosSystemNamespace, Name: account.Name}, account)
if errors.IsNotFound(err) {
account.Name = payment.Spec.UserID
account.Status.Balance = 0
account.Status.ChargeList = []userv1.Charge{}
log.Info("create account", "account", account)
if err := r.Create(ctx, account); err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("create account failed: %v", err)
}
} else if err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("get account failed: %v", err)
}
status, err := pay.QueryOrder(payment.Status.TradeNO)
if err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("query order failed: %v", err)
}
log.Info(fmt.Sprintf("query order: %v", status))
switch status {
case pay.StatusSuccess:
account.Status.ChargeList = append(account.Status.ChargeList, userv1.Charge{
@@ -94,17 +109,17 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
})
account.Status.Balance += payment.Spec.Amount
if err := r.Status().Update(ctx, account); err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("update account failed: %v", err)
}
payment.Status.Status = status
if err := r.Status().Update(ctx, payment); err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("update payment failed: %v", err)
}
case pay.StatusProcessing:
case pay.StatusProcessing, pay.StatusNotPay:
return ctrl.Result{Requeue: true, RequeueAfter: time.Second}, nil
case pay.StatusFail:
if err := r.Delete(ctx, payment); err != nil {
return ctrl.Result{}, err
return ctrl.Result{}, fmt.Errorf("delete payment failed: %v", err)
}
return ctrl.Result{}, nil
default:
@@ -116,6 +131,14 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
// SetupWithManager sets up the controller with the Manager.
func (r *AccountReconciler) SetupWithManager(mgr ctrl.Manager) error {
err := r.Create(context.TODO(), &v1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: constants.SealosSystemNamespace,
},
})
if err != nil && !errors.IsAlreadyExists(err) {
return fmt.Errorf("failed to create system namespace: %v", err)
}
return ctrl.NewControllerManagedBy(mgr).
For(&userv1.Account{}).
Watches(&source.Kind{Type: &userv1.Payment{}}, &handler.EnqueueRequestForObject{}).
+2
View File
@@ -18,6 +18,8 @@ import (
"github.com/mitchellh/go-homedir"
)
const SealosSystemNamespace = "sealos-system"
const (
LvsCareStaticPodName = "kube-sealos-lvscare"
YamlFileSuffix = "yaml"
+1
View File
@@ -39,6 +39,7 @@ const (
StatusSuccess = "SUCCESS"
StatusProcessing = "PROCESSING"
StatusNotPay = "NOTPAY"
StatusFail = "FAILED"
DefaultCallbackURL = "https://sealos.io/payment/wechat/callback"