From 55cdca07a5beea6c289f62d9b3be3eb5eef1d062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=AD=E5=BC=88?= Date: Wed, 24 Aug 2022 23:27:46 +0800 Subject: [PATCH] fix payment and account controller recharge failed (#1617) Signed-off-by: fanux Signed-off-by: fanux --- .../user/api/v1/zz_generated.deepcopy.go | 6 ++- .../crd/bases/user.sealos.io_accounts.yaml | 34 ++------------ .../user/controllers/account_controller.go | 47 ++++++++++++++----- pkg/constants/contants.go | 2 + pkg/pay/wechat_payment.go | 1 + 5 files changed, 47 insertions(+), 43 deletions(-) diff --git a/controllers/user/api/v1/zz_generated.deepcopy.go b/controllers/user/api/v1/zz_generated.deepcopy.go index c3e8151692a..361358e7571 100644 --- a/controllers/user/api/v1/zz_generated.deepcopy.go +++ b/controllers/user/api/v1/zz_generated.deepcopy.go @@ -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. diff --git a/controllers/user/config/crd/bases/user.sealos.io_accounts.yaml b/controllers/user/config/crd/bases/user.sealos.io_accounts.yaml index 50cf38407f2..411025a86f1 100644 --- a/controllers/user/config/crd/bases/user.sealos.io_accounts.yaml +++ b/controllers/user/config/crd/bases/user.sealos.io_accounts.yaml @@ -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 diff --git a/controllers/user/controllers/account_controller.go b/controllers/user/controllers/account_controller.go index f8a7f30ad64..bed5be30a19 100644 --- a/controllers/user/controllers/account_controller.go +++ b/controllers/user/controllers/account_controller.go @@ -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{}). diff --git a/pkg/constants/contants.go b/pkg/constants/contants.go index 33c0c477e18..44a475f9bc5 100644 --- a/pkg/constants/contants.go +++ b/pkg/constants/contants.go @@ -18,6 +18,8 @@ import ( "github.com/mitchellh/go-homedir" ) +const SealosSystemNamespace = "sealos-system" + const ( LvsCareStaticPodName = "kube-sealos-lvscare" YamlFileSuffix = "yaml" diff --git a/pkg/pay/wechat_payment.go b/pkg/pay/wechat_payment.go index db14ab13866..5dbe5fa5ffb 100644 --- a/pkg/pay/wechat_payment.go +++ b/pkg/pay/wechat_payment.go @@ -39,6 +39,7 @@ const ( StatusSuccess = "SUCCESS" StatusProcessing = "PROCESSING" + StatusNotPay = "NOTPAY" StatusFail = "FAILED" DefaultCallbackURL = "https://sealos.io/payment/wechat/callback"