Skip to content

Commit

Permalink
Rebase #3867 (#4092)
Browse files Browse the repository at this point in the history
* feat: develop unified-pay api

Signed-off-by: xy <[email protected]>

* feat: optimize unified-pay api

Signed-off-by: xy <[email protected]>

* feat: Translated some Chinese TODO

Signed-off-by: xy <[email protected]>

* fix some errors

Signed-off-by: xy <[email protected]>

* change encryption algorithm

Signed-off-by: xy <[email protected]>

* optimized code

Signed-off-by: xy <[email protected]>

* build gcr images

Signed-off-by: xy <[email protected]>

* fix bug and optimized code

Signed-off-by: xy <[email protected]>

* remove service/payment

* fix cluster-image-build arm64

* build pay service cluter image

* fix build service

* fix package imports

---------

Signed-off-by: xy <[email protected]>
Co-authored-by: xy <[email protected]>
  • Loading branch information
bxy4543 and geniuxy authored Oct 16, 2023
1 parent deb72ca commit 4ad2acb
Show file tree
Hide file tree
Showing 35 changed files with 1,828 additions and 7 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
strategy:
matrix:
## TODO: add more modules
module: [ database ]
module: [ database, pay ]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down Expand Up @@ -169,7 +169,7 @@ jobs:
strategy:
matrix:
## TODO: add more modules
module: [ database ]
module: [ database, pay ]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down Expand Up @@ -229,7 +229,7 @@ jobs:
CLUSTER_IMAGE_NAME=${{ steps.prepare.outputs.cluster_repo }}:${{ steps.prepare.outputs.tag_name }}
CLUSTER_IMAGE_NAME_LATEST=${{ steps.prepare.outputs.cluster_repo }}:latest
sudo sealos tag ${CLUSTER_IMAGE_NAME}-amd64 ${CLUSTER_IMAGE_NAME_LATEST}-amd64
sudo sealos tag ${CLUSTER_IMAGE_NAME}-amd64 ${CLUSTER_IMAGE_NAME_LATEST}-amd64
sudo sealos tag ${CLUSTER_IMAGE_NAME}-arm64 ${CLUSTER_IMAGE_NAME_LATEST}-arm64
sudo sealos images
bash docker/patch/manifest-cluster-images.sh $CLUSTER_IMAGE_NAME_LATEST
- name: Renew issue and Sync Images
Expand Down
1 change: 1 addition & 0 deletions controllers/account/controllers/account_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ func (r *AccountReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, err
}
// get payment details(status, amount)
// TODO The GetPaymentDetails may cause issues when using Stripe
status, orderAmount, err := payHandler.GetPaymentDetails(payment.Status.TradeNO)
if err != nil {
return ctrl.Result{}, fmt.Errorf("query order failed: %v", err)
Expand Down
6 changes: 3 additions & 3 deletions controllers/pkg/pay/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
package pay

const (
PaymentSuccess = "success"
PaymentNotPaid = "not_paid"
PaymentNotPaid = "notpaid"
PaymentProcessing = "processing"
PaymentExpired = "expired"
PaymentFailed = "failed"
PaymentExpired = "expired"
PaymentSuccess = "success"
PaymentUnknown = "unknown"
)

Expand Down
1 change: 1 addition & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use (
./controllers/pkg
./service/database
./service/hub
./service/pay
./staging/src/github.com/labring/image-cri-shim
./staging/src/github.com/labring/lvscare
./staging/src/github.com/labring/controllers/imagehub
Expand Down
6 changes: 5 additions & 1 deletion go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1049,7 +1049,6 @@ github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA
github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g=
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 h1:uH66TXeswKn5PW5zdZ39xEwfS9an067BirqA+P4QaLI=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/checkpoint-restore/go-criu/v4 v4.1.0 h1:WW2B2uxx9KWF6bGlHqhm8Okiafwwx7Y2kcpn8lCpjgo=
Expand All @@ -1075,6 +1074,7 @@ github.com/cncf/xds/go v0.0.0-20220314180256-7f1daf1720fc/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20230105202645-06c439db220b/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195 h1:58f1tJ1ra+zFINPlwLWvQsR9CzAKt2e+EWV2yX9oXQ4=
github.com/cncf/xds/go v0.0.0-20230310173818-32f1caf87195/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/cockroachdb/cockroach-go/v2 v2.3.3/go.mod h1:1wNJ45eSXW9AnOc3skntW9ZUZz6gxrQK3cOj3rK+BC8=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
Expand Down Expand Up @@ -1247,13 +1247,15 @@ github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPO
github.com/envoyproxy/go-control-plane v0.10.3/go.mod h1:fJJn/j26vwOu972OllsvAgJJM//w9BV6Fxbg2LuVd34=
github.com/envoyproxy/go-control-plane v0.11.0 h1:jtLewhRR2vMRNnq2ZZUoCjUlgut+Y0+sDDWPOfwOi1o=
github.com/envoyproxy/go-control-plane v0.11.0/go.mod h1:VnHyVMpzcLvCFt9yUz1UnCwHLhwx1WguiVDV7pTG/tI=
github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q=
github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws=
github.com/envoyproxy/protoc-gen-validate v0.6.7/go.mod h1:dyJXwwfPK2VSqiB9Klm1J6romD608Ba7Hij42vrOBCo=
github.com/envoyproxy/protoc-gen-validate v0.9.1/go.mod h1:OKNgG7TCp5pF4d6XftA0++PMirau2/yoOwVac3AbF2w=
github.com/envoyproxy/protoc-gen-validate v0.10.0 h1:oIfnZFdC0YhpNNEX+SuIqko4cqqVZeN9IGTrhZje83Y=
github.com/envoyproxy/protoc-gen-validate v0.10.0/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss=
github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE=
github.com/euank/go-kmsg-parser v2.0.0+incompatible h1:cHD53+PLQuuQyLZeriD1V/esuG4MuU0Pjs5y6iknohY=
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
Expand Down Expand Up @@ -2620,6 +2622,8 @@ google.golang.org/genproto v0.0.0-20230222225845-10f96fb3dbec/go.mod h1:3Dl5ZL0q
google.golang.org/genproto v0.0.0-20230223222841-637eb2293923/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak=
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk=
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
Expand Down
1 change: 1 addition & 0 deletions service/pay/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

8 changes: 8 additions & 0 deletions service/pay/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM gcr.io/distroless/static:nonroot

ARG TARGETARCH
COPY bin/service-pay-$TARGETARCH /manager
EXPOSE 2303
USER 65532:65532

ENTRYPOINT ["/manager"]
58 changes: 58 additions & 0 deletions service/pay/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Image URL to use all building/pushing image targets
IMG ?= ghcr.io/labring/sealos-pay-service:latest

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

# only support linux, non cgo
PLATFORMS ?= linux_arm64 linux_amd64
GOOS=linux
CGO_ENABLED=0
TARGETARCH=arm64
GOARCH=$(shell go env GOARCH)

GO_BUILD_FLAGS=-trimpath -ldflags "-s -w"

.PHONY: all
all: build

##@ General

# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk commands is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php

.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)


##@ Build

.PHONY: clean
clean:
rm -f $(SERVICE_NAME)

.PHONY: build
build: clean ## Build service-hub binary.
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) go build $(GO_BUILD_FLAGS) -o bin/manager main.go

.PHONY: docker-build
docker-build: build
mv bin/manager bin/service-pay-$(TARGETARCH)
docker build -t $(IMG) .

.PHONY: docker-push
docker-push:
docker push $(IMG)
30 changes: 30 additions & 0 deletions service/pay/api/appdetail.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package api

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/labring/sealos/service/pay/handler"
"github.com/labring/sealos/service/pay/helper"
"go.mongodb.org/mongo-driver/mongo"
)

func GetAppDetails(c *gin.Context, client *mongo.Client) {
request, err := helper.Init(c, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("init failed before get app details: %v, %v", request, err)})
return
}

payDetails, err := handler.GetAppDetails(request, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("get app details failed : %v", err)})
return
}

c.JSON(http.StatusOK, gin.H{
"message": "get app details success",
"payDetails": payDetails,
})
}
30 changes: 30 additions & 0 deletions service/pay/api/bill.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package api

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/labring/sealos/service/pay/handler"
"github.com/labring/sealos/service/pay/helper"
"go.mongodb.org/mongo-driver/mongo"
)

func GetBill(c *gin.Context, client *mongo.Client) {
request, err := helper.Init(c, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("init failed before get bills: %v, %v", request, err)})
return
}

billDetails, err := handler.GetBillDetails(request, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("get bill details failed : %v", err)})
return
}

c.JSON(http.StatusOK, gin.H{
"message": "get the bill details of user(" + request.User + ") success",
"billDetails": billDetails,
})
}
59 changes: 59 additions & 0 deletions service/pay/api/payapp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package api

import (
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"time"

"github.com/gin-gonic/gin"
"github.com/labring/sealos/service/pay/handler"
"github.com/labring/sealos/service/pay/helper"
"go.mongodb.org/mongo-driver/mongo"
)

func CreatePayApp(c *gin.Context, client *mongo.Client) {
request, err := helper.Init(c, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("init failed before create payapp: %v, %v", request, err)})
return
}

appName := request.PayAppName
// check if the app Name already exists in appcoll
if err := handler.CheckAppNameExistOrNot(client, appName); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("app name already exists: %v", err)})
return
}

// generate sign
data := []byte(appName + time.Now().Format("20060102150405"))
hash := sha256.Sum256(data)
sign := hex.EncodeToString(hash[:7])
// generate appID
data = []byte(sign + time.Now().Format("20060102150405"))
hash = sha256.Sum256(data)
var appID int64
_, err = fmt.Sscanf(hex.EncodeToString(hash[:7]), "%16x", &appID)
if err != nil {
fmt.Println("appID could not be generated:", err)
return
}
// TODO At present, only wechat and stripe are supported, and then you can consider extending them
methods := []string{"wechat", "stripe"}

result, err := handler.InsertApp(client, appID, sign, appName, methods)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("create pay app failed when insert into db: %v", err)})
return
}

c.JSON(http.StatusOK, gin.H{
"message": "create pay app success",
"payAppName": appName,
"appID": appID,
"sign": sign,
"result": result,
})
}
37 changes: 37 additions & 0 deletions service/pay/api/paymethod.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package api

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/labring/sealos/service/pay/handler"
"github.com/labring/sealos/service/pay/helper"
"go.mongodb.org/mongo-driver/mongo"
)

func CreatePayMethod(c *gin.Context, client *mongo.Client) {
request, err := helper.Init(c, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("init failed before create paymethod: %v, %v", request, err)})
return
}

if ok, err := handler.CheckPayMethodExistOrNot(client, request.Currency, request.PayMethod); ok && err == nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "paymethod is exist"})
return
}

result, err := handler.InsertPayMethod(request, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("create pay method failed when insert into db: %v", err)})
return
}

c.JSON(http.StatusOK, gin.H{
"message": "create pay method success",
"result": result,
})
}

// TODO Change the amount or exchange rate or tax rate for a payment method
31 changes: 31 additions & 0 deletions service/pay/api/paysession.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package api

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/labring/sealos/service/pay/helper"
"github.com/labring/sealos/service/pay/method"
"go.mongodb.org/mongo-driver/mongo"
)

// GetSession Get url from payment service providers (such as WeChat and Stripe)
func GetSession(c *gin.Context, client *mongo.Client) {
request, err := helper.Init(c, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("init failed before get paysession: %v, %v", request, err)})
return
}

switch request.PayMethod {
case "wechat":
method.GetWechatURL(c, request, client)
case "stripe":
method.GetStripeSession(c, request, client)
default:
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("paymethod is illegal: %v", request.PayMethod)})
}
// TODO At present, the Currency of wechat and stripe seems to be CNY, and then if there are other currencies, here needs to be changed
// TODO To prevent multiple orders from the same IP address, you need to add IP restrictions
}
29 changes: 29 additions & 0 deletions service/pay/api/paystatus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package api

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"github.com/labring/sealos/service/pay/helper"
"github.com/labring/sealos/service/pay/method"
"go.mongodb.org/mongo-driver/mongo"
)

func GetPayStatus(c *gin.Context, client *mongo.Client) {
request, err := helper.Init(c, client)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("init failed before get payment status: %v, %v", request, err)})
return
}

switch request.PayMethod {
case "wechat":
method.GetWechatPaymentStatus(c, request, client)
case "stripe":
method.GetStripePaymentStatus(c, request, client)
default:
c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("paymethod is illegal: %v", request.PayMethod)})
}
// TODO The other status of this area except notpaid has not been tested, and it will be tested later
}
Loading

0 comments on commit 4ad2acb

Please sign in to comment.