From 5a60a92f4b983fdecb578e50af81c6416af26ac1 Mon Sep 17 00:00:00 2001
From: wolter <wolter@yourdomain.com>
Date: Fri, 2 Aug 2024 09:18:49 +0800
Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E5=AD=97=E6=AE=B5=E7=99=BD?=
 =?UTF-8?q?=E5=90=8D=E5=8D=95=E5=92=8C=E4=B8=8B=E6=B8=B8=E9=80=9A=E7=9F=A5?=
 =?UTF-8?q?=E5=9C=B0=E5=9D=80=E7=94=B1app=E7=AE=A1=E7=90=86=EF=BC=8C?=
 =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=BA=94=E7=94=A8=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/constants/errorcode/error_code.go       |   5 +
 app/data/merchat.go                         |   4 +
 app/data/pay_channel.go                     |   2 +-
 app/http/controllers/backend/app.go         |  75 +++++++++++++++
 app/http/controllers/backend/pay_channel.go |  63 ++++++++++++
 app/http/domains/filter.go                  |  12 ---
 app/http/domains/product.go                 |  23 -----
 app/http/entities/backend/app.go            | 101 ++++++++++++++++++++
 app/http/entities/backend/pay_channel.go    |  78 ++++++++++-----
 app/http/requestmapping/backend.go          |  11 +++
 app/http/routes/admin.go                    |  15 +++
 app/models/appmodel/app.go                  |   4 +-
 app/models/ordersmodel/orders.go            |   2 +-
 app/models/paychannelmodel/pay_channel.go   |  20 ++--
 app/services/app.go                         |  86 +++++++++++++++++
 app/services/pay_channel.go                 |  85 ++++++++++++++++
 16 files changed, 516 insertions(+), 70 deletions(-)
 create mode 100644 app/http/controllers/backend/app.go
 create mode 100644 app/http/controllers/backend/pay_channel.go
 delete mode 100644 app/http/domains/filter.go
 delete mode 100644 app/http/domains/product.go
 create mode 100644 app/http/entities/backend/app.go
 create mode 100644 app/services/app.go
 create mode 100644 app/services/pay_channel.go

diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go
index 9d16981..f240f37 100644
--- a/app/constants/errorcode/error_code.go
+++ b/app/constants/errorcode/error_code.go
@@ -21,6 +21,9 @@ const (
 
 	//未登录
 	NotLogin = 1000
+
+	// 商户
+	MerchantNotFound = 1100
 )
 
 var MsgEN = map[int]string{
@@ -38,6 +41,8 @@ var MsgZH = map[int]string{
 	NotFound:   "数据不存在",
 	NotAuth:    "未经授权",
 	NotLogin:   "未登录",
+
+	MerchantNotFound: "商户不存在",
 }
 var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
 
diff --git a/app/data/merchat.go b/app/data/merchat.go
index 17ae5f7..763758c 100644
--- a/app/data/merchat.go
+++ b/app/data/merchat.go
@@ -37,3 +37,7 @@ func (m *MerchantRepo) MerchantDelete(merchant *merchantmodel.Merchant, conn bui
 func (m *MerchantRepo) MerchantUpdate(merchant *merchantmodel.Merchant, conn builder.Cond, columns ...string) (int64, error) {
 	return m.repo.Where(conn).MustCols(columns...).Update(merchant)
 }
+
+func (m *MerchantRepo) MerchantDetail(merchant *merchantmodel.Merchant, conn builder.Cond) (bool, error) {
+	return m.repo.Where(conn).Get(merchant)
+}
diff --git a/app/data/pay_channel.go b/app/data/pay_channel.go
index 883d3c1..5a26f22 100644
--- a/app/data/pay_channel.go
+++ b/app/data/pay_channel.go
@@ -33,7 +33,7 @@ func (m *PayChannelRepo) PayChannelDelete(merchant *paychannelmodel.PayChannel,
 	return m.repo.Where(conn).Delete(merchant)
 }
 
-// columns 参数为要更新的字段
+// columns 参数为要更新的字段,即使为空
 func (m *PayChannelRepo) PayChannelUpdate(merchant *paychannelmodel.PayChannel, conn builder.Cond, columns ...string) (int64, error) {
 	return m.repo.Where(conn).MustCols(columns...).Update(merchant)
 }
diff --git a/app/http/controllers/backend/app.go b/app/http/controllers/backend/app.go
new file mode 100644
index 0000000..a729f37
--- /dev/null
+++ b/app/http/controllers/backend/app.go
@@ -0,0 +1,75 @@
+package backend
+
+import (
+	"PaymentCenter/app/constants/errorcode"
+	"PaymentCenter/app/http/controllers"
+	"PaymentCenter/app/http/entities"
+	"PaymentCenter/app/http/entities/backend"
+	"PaymentCenter/app/models/appmodel"
+	"PaymentCenter/app/services"
+	"PaymentCenter/app/utils/sm2"
+	"github.com/ahmetb/go-linq/v3"
+	"github.com/gin-gonic/gin"
+)
+
+func AppList(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.AppListRequest)
+	req.SetDefault()
+	payChannelList, total, code := services.AppList(*req)
+
+	result := make([]backend.AppResponse, 0, len(payChannelList))
+	linq.From(payChannelList).SelectT(func(in appmodel.App) (out backend.AppResponse) {
+		out.ResponseFromDb(in)
+		return
+	}).ToSlice(&result)
+	data := entities.PageRsp{
+		Total: total,
+		Data:  result,
+	}
+	controllers.HandCodeRes(c, data, code)
+}
+
+func AppCreate(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.AppCreateRequest)
+	payChannel := req.RequestToDb()
+	code := services.AppCreate(&payChannel)
+
+	data := backend.AppResponse{}
+	data.ResponseFromDb(payChannel)
+	controllers.HandCodeRes(c, data, code)
+}
+
+func AppUpdate(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.AppUpdateRequest)
+	payChannel := req.RequestToDb()
+	code := services.AppUpdate(&payChannel)
+
+	data := backend.AppResponse{}
+	data.ResponseFromDb(payChannel)
+	controllers.HandCodeRes(c, data, code)
+}
+
+func AppDelete(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*entities.IdRequest)
+	code := services.AppDelete(*req)
+	controllers.HandCodeRes(c, nil, code)
+}
+
+func GenerateDecrypt(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.GenerateDecryptKeyRequest)
+	var publicKey, privateKey string
+	var err error
+	switch req.KeyType {
+	default:
+		publicKey, privateKey, err = sm2.GenerateSM2Key()
+		if err != nil {
+			controllers.Error(c, errorcode.SystemError, err.Error())
+			return
+		}
+	}
+
+	controllers.HandCodeRes(c, map[string]string{
+		"publicKey":  publicKey,
+		"privateKey": privateKey,
+	}, errorcode.Success)
+}
diff --git a/app/http/controllers/backend/pay_channel.go b/app/http/controllers/backend/pay_channel.go
new file mode 100644
index 0000000..775067a
--- /dev/null
+++ b/app/http/controllers/backend/pay_channel.go
@@ -0,0 +1,63 @@
+package backend
+
+import (
+	"PaymentCenter/app/constants/errorcode"
+	"PaymentCenter/app/http/controllers"
+	"PaymentCenter/app/http/entities"
+	"PaymentCenter/app/http/entities/backend"
+	"PaymentCenter/app/models/paychannelmodel"
+	"PaymentCenter/app/services"
+	"github.com/ahmetb/go-linq/v3"
+	"github.com/gin-gonic/gin"
+)
+
+func PayChannelList(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.PayChannelListRequest)
+	req.SetDefault()
+	payChannelList, total, code := services.PayChannelList(*req)
+
+	result := make([]backend.PayChannelResponse, 0, len(payChannelList))
+	linq.From(payChannelList).SelectT(func(in paychannelmodel.PayChannel) (out backend.PayChannelResponse) {
+		out.ResponseFromDb(in)
+		return
+	}).ToSlice(&result)
+	data := entities.PageRsp{
+		Total: total,
+		Data:  result,
+	}
+	controllers.HandCodeRes(c, data, code)
+}
+
+func PayChannelCreate(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.PayChannelCreateRequest)
+	payChannel, err := req.RequestToDb()
+	if err != nil {
+		controllers.Error(c, errorcode.ParamError, err.Error())
+		return
+	}
+	code := services.PayChannelCreate(&payChannel)
+
+	data := backend.PayChannelResponse{}
+	data.ResponseFromDb(payChannel)
+	controllers.HandCodeRes(c, data, code)
+}
+
+func PayChannelUpdate(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*backend.PayChannelUpdateRequest)
+	payChannel, err := req.RequestToDb()
+	if err != nil {
+		controllers.Error(c, errorcode.ParamError, err.Error())
+		return
+	}
+	code := services.PayChannelUpdate(&payChannel)
+
+	data := backend.PayChannelResponse{}
+	data.ResponseFromDb(payChannel)
+	controllers.HandCodeRes(c, data, code)
+}
+
+func PayChannelDelete(c *gin.Context) {
+	req, _ := controllers.GetRequest(c).(*entities.IdRequest)
+	code := services.PayChannelDelete(*req)
+	controllers.HandCodeRes(c, nil, code)
+}
diff --git a/app/http/domains/filter.go b/app/http/domains/filter.go
deleted file mode 100644
index 3a561e1..0000000
--- a/app/http/domains/filter.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package domains
-
-type Filter struct {
-	Page     int `json:"page"`
-	PageSize int `json:"page_size"`
-}
-
-type ProductFilter struct {
-	Page        int    `json:"page" form:"page"`
-	PageSize    int    `json:"page_size" form:"page_size"`
-	ProductName string `json:"product_name" form:"product_name"`
-}
diff --git a/app/http/domains/product.go b/app/http/domains/product.go
deleted file mode 100644
index 8e7a7a9..0000000
--- a/app/http/domains/product.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package domains
-
-import "time"
-
-type Product struct {
-	Id                  int
-	ProductName         string
-	ProductType         int
-	PacketRule          int
-	ProductKind         int
-	Amount              string
-	CouponType          int
-	IsSuperposition     int
-	TemplateId          int
-	Status              int
-	IsNeedBill          int
-	CreateTime          time.Time
-	SupplierProductId   int64
-	SupplierProductName string
-
-	Creator    string
-	UpdateTime time.Time
-}
diff --git a/app/http/entities/backend/app.go b/app/http/entities/backend/app.go
new file mode 100644
index 0000000..c35bb55
--- /dev/null
+++ b/app/http/entities/backend/app.go
@@ -0,0 +1,101 @@
+package backend
+
+import (
+	"PaymentCenter/app/http/entities"
+	"PaymentCenter/app/models/appmodel"
+)
+
+type AppListRequest struct {
+	MerchantId int64 `json:"merchant_id"`
+	entities.PageRequest
+}
+
+type AppResponse struct {
+	Id                int64  `json:"id"`
+	MerchantId        int64  `json:"merchant_id"`
+	AppName           string `json:"app_name"`
+	AppRemark         string `json:"app_remark"`
+	Status            int    `json:"status"`
+	KeyType           int    `json:"key_type"`
+	PublicKey         string `json:"public_key"`
+	PrivateKey        string `json:"private_key"`
+	MerchantPublicKey string `json:"merchant_public_key"`
+	CreateTime        string `json:"create_time"`
+	WhiteIp           string `json:"white_ip"`
+	NotifyUrl         string `json:"notify_url"`
+}
+
+func (a *AppResponse) ResponseFromDb(db appmodel.App) {
+	a.Id = db.Id
+	a.MerchantId = db.MerchantId
+	a.AppName = db.AppName
+	a.AppRemark = db.AppRemark
+	a.Status = db.Status
+	a.KeyType = db.KeyType
+	a.PublicKey = db.PublicKey
+	a.PrivateKey = db.PrivateKey
+	a.MerchantPublicKey = db.MerchantPublicKey
+	a.CreateTime = db.CreateTime.Format("2006-01-02 15:04:05")
+	a.WhiteIp = db.WhiteIp
+	a.NotifyUrl = db.NotifyUrl
+}
+
+type AppCreateRequest struct {
+	MerchantId        int64  `json:"merchant_id" validate:"required" label:"商户ID"`
+	AppName           string `json:"app_name" validate:"required" label:"应用名称"`
+	AppRemark         string `json:"app_remark" label:"应用备注"`
+	Status            int    `json:"status" validate:"oneof=0 1 2" label:"应用状态"`
+	KeyType           int    `json:"key_type" validate:"required" label:"应用密钥类型"`
+	PublicKey         string `json:"public_key" validate:"required" label:"应用公钥"`
+	PrivateKey        string `json:"private_key" validate:"required" label:"应用私钥"`
+	MerchantPublicKey string `json:"merchant_public_key"  label:"商户公钥"`
+	WhiteIp           string `json:"white_ip"`
+	NotifyUrl         string `json:"notify_url"`
+}
+
+func (a *AppCreateRequest) RequestToDb() (db appmodel.App) {
+	db.MerchantId = a.MerchantId
+	db.AppName = a.AppName
+	db.AppRemark = a.AppRemark
+	db.Status = a.Status
+	db.KeyType = a.KeyType
+	db.PublicKey = a.PublicKey
+	db.PrivateKey = a.PrivateKey
+	db.MerchantPublicKey = a.MerchantPublicKey
+	db.WhiteIp = a.WhiteIp
+	db.NotifyUrl = a.NotifyUrl
+	return
+}
+
+type AppUpdateRequest struct {
+	Id                int64  `json:"id" validate:"required" label:"应用ID"`
+	MerchantId        int64  `json:"merchant_id" validate:"required" label:"商户ID"`
+	AppName           string `json:"app_name" validate:"required" label:"应用名称"`
+	AppRemark         string `json:"app_remark" label:"应用备注"`
+	Status            int    `json:"status" validate:"oneof=0 1 2" label:"应用状态"`
+	KeyType           int    `json:"key_type" validate:"required" label:"应用密钥类型"`
+	PublicKey         string `json:"public_key" validate:"required" label:"应用公钥"`
+	PrivateKey        string `json:"private_key" validate:"required" label:"应用私钥"`
+	MerchantPublicKey string `json:"merchant_public_key" label:"商户公钥"`
+	WhiteIp           string `json:"white_ip"`
+	NotifyUrl         string `json:"notify_url"`
+}
+
+func (a *AppUpdateRequest) RequestToDb() (db appmodel.App) {
+	db.Id = a.Id
+	db.MerchantId = a.MerchantId
+	db.AppName = a.AppName
+	db.AppRemark = a.AppRemark
+	db.Status = a.Status
+	db.KeyType = a.KeyType
+	db.PublicKey = a.PublicKey
+	db.PrivateKey = a.PrivateKey
+	db.MerchantPublicKey = a.MerchantPublicKey
+	db.WhiteIp = a.WhiteIp
+	db.NotifyUrl = a.NotifyUrl
+	return
+}
+
+type GenerateDecryptKeyRequest struct {
+	KeyType int `json:"key_type" label:"密钥类型"`
+}
diff --git a/app/http/entities/backend/pay_channel.go b/app/http/entities/backend/pay_channel.go
index 558090b..7bbb096 100644
--- a/app/http/entities/backend/pay_channel.go
+++ b/app/http/entities/backend/pay_channel.go
@@ -2,6 +2,7 @@ package backend
 
 import (
 	"PaymentCenter/app/constants/common"
+	"PaymentCenter/app/http/entities"
 	"PaymentCenter/app/models/paychannelmodel"
 	"PaymentCenter/app/utils"
 	"encoding/json"
@@ -9,16 +10,15 @@ import (
 )
 
 type PayChannelResponse struct {
-	Id               int64            `json:"id"`
-	PayName          string           `json:"pay_name"`
-	MerchantId       int64            `json:"merchant_id"`
-	ChannelType      int              `json:"channel_type"`
-	WhiteIp          string           `json:"white_ip"`
-	AppId            string           `json:"app_id"`
-	ExpireTime       string           `json:"expire_time"`
-	CreateTime       string           `json:"create_time"`
-	AliPayPayChannel AliPayPayChannel `json:"ali_pay_pay_channel,omitempty"`
-	WechatPayChannel WechatPayChannel `json:"wechat_pay_channel,omitempty"`
+	Id               int64             `json:"id"`
+	PayName          string            `json:"pay_name"`
+	MerchantId       int64             `json:"merchant_id"`
+	ChannelType      int               `json:"channel_type"`
+	AppId            string            `json:"app_id"`
+	ExpireTime       string            `json:"expire_time"`
+	CreateTime       string            `json:"create_time"`
+	AliPayPayChannel *AliPayPayChannel `json:"ali_pay_pay_channel,omitempty"`
+	WechatPayChannel *WechatPayChannel `json:"wechat_pay_channel,omitempty"`
 }
 
 func (p *PayChannelResponse) ResponseFromDb(db paychannelmodel.PayChannel) {
@@ -26,32 +26,30 @@ func (p *PayChannelResponse) ResponseFromDb(db paychannelmodel.PayChannel) {
 	p.PayName = db.PayName
 	p.MerchantId = db.MerchantId
 	p.ChannelType = db.ChannelType
-	p.WhiteIp = db.WhiteIp
 	p.AppId = db.AppId
 	p.ExpireTime = db.ExpireTime.Format("2006-01-02 15:04:05")
 	p.CreateTime = db.CreateTime.Format("2006-01-02 15:04:05")
 
 	switch p.ChannelType {
-	case common.PAY_CHANNEL_WECHAT_H5 | common.PAY_CHANNEL_WECHAT_JSAPI | common.PAY_CHANNEL_WECHAT_NATIVE | common.PAY_CHANNEL_WECHAT_APP | common.PAY_CHANNEL_WECHAT_MINI:
+	case common.PAY_CHANNEL_WECHAT_H5, common.PAY_CHANNEL_WECHAT_JSAPI, common.PAY_CHANNEL_WECHAT_NATIVE, common.PAY_CHANNEL_WECHAT_APP, common.PAY_CHANNEL_WECHAT_MINI:
 		_ = json.Unmarshal([]byte(db.ExtJson), &p.WechatPayChannel)
-	case common.PAY_CHANNEL_ALIPAY_JSAPI | common.PAY_CHANNEL_ALIPAY_WEB | common.PAY_CHANNEL_ALIPAY_MINI:
+	case common.PAY_CHANNEL_ALIPAY_JSAPI, common.PAY_CHANNEL_ALIPAY_WEB, common.PAY_CHANNEL_ALIPAY_MINI:
 		_ = json.Unmarshal([]byte(db.ExtJson), &p.AliPayPayChannel)
 	}
 }
 
 type PayChannelCreateRequest struct {
-	PayName          string           `json:"pay_name"`
-	MerchantId       int64            `json:"merchant_id"`
-	ChannelType      int              `json:"channel_type"` //支付渠道枚举,1微信JSAPI,2微信H5,3微信app,4微信Native,5微信小程序,6支付宝网页&移动应用,7支付宝小程序,8支付宝JSAPI
-	WhiteIp          string           `json:"white_ip"`
-	AppId            string           `json:"app_id"`
+	PayName          string           `json:"pay_name" validate:"required" label:"支付渠道名称"`
+	MerchantId       int64            `json:"merchant_id" validate:"required" label:"商户ID"`
+	ChannelType      int              `json:"channel_type" validate:"required" label:"支付渠道"` //支付渠道枚举,1微信JSAPI,2微信H5,3微信app,4微信Native,5微信小程序,6支付宝网页&移动应用,7支付宝小程序,8支付宝JSAPI
+	AppId            string           `json:"app_id" validate:"required" label:"应用appId"`
 	ExpireTime       string           `json:"expire_time"`
 	AliPayPayChannel AliPayPayChannel `json:"ali_pay_pay_channel,omitempty"`
 	WechatPayChannel WechatPayChannel `json:"wechat_pay_channel,omitempty"`
 }
 
 type WechatPayChannel struct {
-	MchId                      int    `json:"mch_id"`                        //直连商户号
+	MchId                      string `json:"mch_id"`                        //直连商户号
 	MchCertificateSerialNumber string `json:"mch_certificate_serial_number"` //商户证书序列号
 	MchAPIv3Key                string `json:"mch_APIv3_key"`                 //商户APIv3密钥
 	PrivateKeyPath             string `json:"private_key_path"`              //商户私钥文件路径
@@ -67,7 +65,6 @@ func (p *PayChannelCreateRequest) RequestToDb() (db paychannelmodel.PayChannel,
 	db.PayName = p.PayName
 	db.MerchantId = p.MerchantId
 	db.ChannelType = p.ChannelType
-	db.WhiteIp = p.WhiteIp
 	db.AppId = p.AppId
 	if p.ExpireTime != "" {
 		db.ExpireTime, err = utils.StrToTimeShanghai(p.ExpireTime)
@@ -76,12 +73,49 @@ func (p *PayChannelCreateRequest) RequestToDb() (db paychannelmodel.PayChannel,
 		}
 	}
 	switch p.ChannelType {
-	case common.PAY_CHANNEL_WECHAT_H5 | common.PAY_CHANNEL_WECHAT_JSAPI | common.PAY_CHANNEL_WECHAT_NATIVE | common.PAY_CHANNEL_WECHAT_APP | common.PAY_CHANNEL_WECHAT_MINI:
+	case common.PAY_CHANNEL_WECHAT_H5, common.PAY_CHANNEL_WECHAT_JSAPI, common.PAY_CHANNEL_WECHAT_NATIVE, common.PAY_CHANNEL_WECHAT_APP, common.PAY_CHANNEL_WECHAT_MINI:
 		b, _ := json.Marshal(p.WechatPayChannel)
 		db.ExtJson = string(b)
-	case common.PAY_CHANNEL_ALIPAY_JSAPI | common.PAY_CHANNEL_ALIPAY_WEB | common.PAY_CHANNEL_ALIPAY_MINI:
+	case common.PAY_CHANNEL_ALIPAY_JSAPI, common.PAY_CHANNEL_ALIPAY_WEB, common.PAY_CHANNEL_ALIPAY_MINI:
 		b, _ := json.Marshal(p.AliPayPayChannel)
 		db.ExtJson = string(b)
+	default:
+		err = errors.New("支付渠道类型错误")
+	}
+	return
+}
+
+type PayChannelListRequest struct {
+	MerchantId int64 `json:"merchant_id"`
+	entities.PageRequest
+}
+
+type PayChannelUpdateRequest struct {
+	Id int64 `json:"id" validate:"required"`
+	PayChannelCreateRequest
+}
+
+func (p PayChannelUpdateRequest) RequestToDb() (db paychannelmodel.PayChannel, err error) {
+	db.Id = p.Id
+	db.PayName = p.PayName
+	db.MerchantId = p.MerchantId
+	db.ChannelType = p.ChannelType
+	db.AppId = p.AppId
+	if p.ExpireTime != "" {
+		db.ExpireTime, err = utils.StrToTimeShanghai(p.ExpireTime)
+		if err != nil {
+			err = errors.Wrap(err, "时间格式错误")
+		}
+	}
+	switch p.ChannelType {
+	case common.PAY_CHANNEL_WECHAT_H5, common.PAY_CHANNEL_WECHAT_JSAPI, common.PAY_CHANNEL_WECHAT_NATIVE, common.PAY_CHANNEL_WECHAT_APP, common.PAY_CHANNEL_WECHAT_MINI:
+		b, _ := json.Marshal(p.WechatPayChannel)
+		db.ExtJson = string(b)
+	case common.PAY_CHANNEL_ALIPAY_JSAPI, common.PAY_CHANNEL_ALIPAY_WEB, common.PAY_CHANNEL_ALIPAY_MINI:
+		b, _ := json.Marshal(p.AliPayPayChannel)
+		db.ExtJson = string(b)
+	default:
+		err = errors.New("支付渠道类型错误")
 	}
 	return
 }
diff --git a/app/http/requestmapping/backend.go b/app/http/requestmapping/backend.go
index 61af681..d5edcf7 100644
--- a/app/http/requestmapping/backend.go
+++ b/app/http/requestmapping/backend.go
@@ -13,4 +13,15 @@ var BackendRequestMap = map[string]func() interface{}{
 	common.ADMIN_V1 + "/merchant/update": func() interface{} { return new(backend.MerchantUpdateRequest) },
 	common.ADMIN_V1 + "/merchant/list":   func() interface{} { return new(backend.MerchantListRequest) },
 	common.ADMIN_V1 + "/merchant/delete": func() interface{} { return new(entities.IdRequest) },
+	// 支付方式
+	common.ADMIN_V1 + "/paychannel/create": func() interface{} { return new(backend.PayChannelCreateRequest) },
+	common.ADMIN_V1 + "/paychannel/update": func() interface{} { return new(backend.PayChannelUpdateRequest) },
+	common.ADMIN_V1 + "/paychannel/list":   func() interface{} { return new(backend.PayChannelListRequest) },
+	common.ADMIN_V1 + "/paychannel/delete": func() interface{} { return new(entities.IdRequest) },
+	// 应用
+	common.ADMIN_V1 + "/app/create":  func() interface{} { return new(backend.AppCreateRequest) },
+	common.ADMIN_V1 + "/app/update":  func() interface{} { return new(backend.AppUpdateRequest) },
+	common.ADMIN_V1 + "/app/list":    func() interface{} { return new(backend.AppListRequest) },
+	common.ADMIN_V1 + "/app/delete":  func() interface{} { return new(entities.IdRequest) },
+	common.ADMIN_V1 + "/app/decrypt": func() interface{} { return new(backend.GenerateDecryptKeyRequest) },
 }
diff --git a/app/http/routes/admin.go b/app/http/routes/admin.go
index 168744a..f9461d9 100644
--- a/app/http/routes/admin.go
+++ b/app/http/routes/admin.go
@@ -31,6 +31,21 @@ func RegisterAdminRoute(router *gin.Engine) {
 		merchant.POST("/create", backend.MerchantCreate)   // 商户创建
 		merchant.PUT("/update", backend.MerchantUpdate)    // 商户更新
 		merchant.DELETE("/delete", backend.MerchantDelete) // 商户删除
+		// 支付方式
+		pay := v1.Group("/paychannel")
+		pay.GET("/list", backend.PayChannelList)        // 支付方式列表
+		pay.POST("/create", backend.PayChannelCreate)   // 支付方式创建
+		pay.PUT("/update", backend.PayChannelUpdate)    // 支付方式更新
+		pay.DELETE("/delete", backend.PayChannelDelete) // 支付方式删除
+
+		// 应用管理
+		app := v1.Group("/app")
+		app.GET("/list", backend.AppList)            // 应用列表
+		app.POST("/create", backend.AppCreate)       // 应用创建
+		app.PUT("/update", backend.AppUpdate)        // 应用更新
+		app.DELETE("/delete", backend.AppDelete)     // 应用删除
+		app.GET("/decrypt", backend.GenerateDecrypt) // 生成密钥对
+
 	}
 
 }
diff --git a/app/models/appmodel/app.go b/app/models/appmodel/app.go
index cabff21..b840778 100644
--- a/app/models/appmodel/app.go
+++ b/app/models/appmodel/app.go
@@ -13,7 +13,7 @@ var (
 
 // 实体
 type App struct {
-	Id                int64     `xorm:"pk autoincr AUTO_RANDOM"`
+	Id                int64
 	MerchantId        int64     `xorm:"'merchant_id' bigint(20)"`
 	AppName           string    `xorm:"'app_name' varchar(128)"`
 	AppRemark         string    `xorm:"'app_remark' varchar(255)"`
@@ -22,6 +22,8 @@ type App struct {
 	PublicKey         string    `xorm:"'public_key' varchar(1024)"`
 	PrivateKey        string    `xorm:"'private_key' varchar(1024)"`
 	MerchantPublicKey string    `xorm:"'merchant_public_key' varchar(1024)"`
+	NotifyUrl         string    `xorm:"'notify_url' varchar(128)"`
+	WhiteIp           string    `xorm:"'white_ip' varchar(128)"`
 	CreateTime        time.Time `xorm:"'create_time' datetime created"`
 	UpdateTime        time.Time `xorm:"'update_time' timestamp updated"`
 	DeleteTime        time.Time `xorm:"'delete_time' timestamp deleted"`
diff --git a/app/models/ordersmodel/orders.go b/app/models/ordersmodel/orders.go
index 182d7dc..48e9aa3 100644
--- a/app/models/ordersmodel/orders.go
+++ b/app/models/ordersmodel/orders.go
@@ -16,11 +16,11 @@ type Orders struct {
 	Id               int64
 	MerchantId       int64     `xorm:"'merchant_id' bigint(20)"`
 	PayId            int64     `xorm:"'pay_id' bigint(20)"`
+	AppId            int64     `xorm:"'app_id' bigint(20)"`
 	MerchantOrderId  string    `xorm:"'merchant_order_id' varchar(128)"`
 	Status           int       `xorm:"'status' int(11)"`
 	OrderType        int       `xorm:"'order_type' int(11)"`
 	Amount           int       `xorm:"'amount' int(11)"`
-	NotifyUrl        string    `xorm:"'notify_url' varchar(255)"`
 	IpAddress        string    `xorm:"'ip_address' varchar(128)"`
 	MerchantRequest  string    `xorm:"'merchant_request' varchar(2048)"`
 	MerchantResponse string    `xorm:"'merchant_response' varchar(255)"`
diff --git a/app/models/paychannelmodel/pay_channel.go b/app/models/paychannelmodel/pay_channel.go
index 48f9873..cede2df 100644
--- a/app/models/paychannelmodel/pay_channel.go
+++ b/app/models/paychannelmodel/pay_channel.go
@@ -14,16 +14,16 @@ var (
 // 实体
 type PayChannel struct {
 	Id          int64
-	PayName     string    `xorm:"'pay_name' varchar(128)"`
-	MerchantId  int64     `xorm:"'merchant_id' bigint(20)"`
-	ChannelType int       `xorm:"'channel_type' int(11)"`
-	WhiteIp     string    `xorm:"'white_ip' varchar(1024)"`
-	AppId       string    `xorm:"'app_id' varchar(255)"`
-	ExtJson     string    `xorm:"'ext_json' JSON"`
-	ExpireTime  time.Time `xorm:"'expire_time' datetime"`
-	CreateTime  time.Time `xorm:"'create_time' datetime created"`
-	UpdateTime  time.Time `xorm:"'update_time' timestamp updated"`
-	DeleteTime  time.Time `xorm:"'delete_time' timestamp deleted"`
+	PayName     string `xorm:"'pay_name' varchar(128)"`
+	MerchantId  int64  `xorm:"'merchant_id' bigint(20)"`
+	ChannelType int    `xorm:"'channel_type' int(11)"`
+
+	AppId      string    `xorm:"'app_id' varchar(255)"`
+	ExtJson    string    `xorm:"'ext_json' JSON"`
+	ExpireTime time.Time `xorm:"'expire_time' datetime"`
+	CreateTime time.Time `xorm:"'create_time' datetime created"`
+	UpdateTime time.Time `xorm:"'update_time' timestamp updated"`
+	DeleteTime time.Time `xorm:"'delete_time' timestamp deleted"`
 }
 
 // 表名
diff --git a/app/services/app.go b/app/services/app.go
new file mode 100644
index 0000000..90dd740
--- /dev/null
+++ b/app/services/app.go
@@ -0,0 +1,86 @@
+package services
+
+import (
+	"PaymentCenter/app/constants/errorcode"
+	"PaymentCenter/app/data"
+	"PaymentCenter/app/http/entities"
+	"PaymentCenter/app/http/entities/backend"
+	"PaymentCenter/app/models/appmodel"
+	"PaymentCenter/app/models/merchantmodel"
+	"PaymentCenter/app/models/paychannelmodel"
+	"xorm.io/builder"
+)
+
+func AppList(req backend.AppListRequest) (result []appmodel.App, total int64, code int) {
+	repo := data.NewAppRepo(paychannelmodel.GetInstance().GetDb())
+	// 拼接查询条件
+	conn := builder.NewCond()
+	if req.MerchantId > 0 {
+		conn = conn.And(builder.Eq{"merchant_id": req.MerchantId})
+	}
+
+	// 调用repo
+	appList := make([]appmodel.App, 0)
+	count, err := repo.AppList(conn, req.PageRequest, &appList)
+	code = handErr(err)
+	return appList, count, code
+}
+
+func AppCreate(App *appmodel.App) (code int) {
+	db := paychannelmodel.GetInstance().GetDb()
+	repo := data.NewAppRepo(db)
+	merchantRepo := data.NewMerchantRepo(db)
+	// 拼接查询条件
+	conn := builder.NewCond()
+	conn = conn.And(builder.Eq{"id": App.MerchantId})
+	merchant := merchantmodel.Merchant{}
+	has, err := merchantRepo.MerchantDetail(&merchant, conn)
+	if err != nil {
+		return handErr(err)
+	}
+	if !has {
+		return errorcode.MerchantNotFound
+	}
+
+	_, err = repo.AppInsertOne(App)
+	code = handErr(err)
+	return
+}
+
+func AppUpdate(App *appmodel.App) (code int) {
+	db := paychannelmodel.GetInstance().GetDb()
+	repo := data.NewAppRepo(db)
+	merchantRepo := data.NewMerchantRepo(db)
+	// 拼接查询条件
+	conn := builder.NewCond()
+	conn = conn.And(builder.Eq{"id": App.MerchantId})
+	merchant := merchantmodel.Merchant{}
+	has, err := merchantRepo.MerchantDetail(&merchant, conn)
+	if err != nil {
+		return handErr(err)
+	}
+	if !has {
+		return errorcode.MerchantNotFound
+	}
+
+	// 拼接查询条件
+	uconn := builder.NewCond()
+	uconn = uconn.And(builder.Eq{"Id": App.Id})
+	_, err = repo.AppUpdate(App, uconn, "app_remark")
+
+	code = handErr(err)
+	return
+}
+
+func AppDelete(req entities.IdRequest) (code int) {
+	repo := data.NewAppRepo(paychannelmodel.GetInstance().GetDb())
+
+	// 拼接查询条件
+	conn := builder.NewCond()
+	conn = conn.And(builder.Eq{"Id": req.Id})
+	m := appmodel.App{Id: req.Id}
+	_, err := repo.AppDelete(&m, conn)
+
+	code = handErr(err)
+	return
+}
diff --git a/app/services/pay_channel.go b/app/services/pay_channel.go
new file mode 100644
index 0000000..0e19da3
--- /dev/null
+++ b/app/services/pay_channel.go
@@ -0,0 +1,85 @@
+package services
+
+import (
+	"PaymentCenter/app/constants/errorcode"
+	"PaymentCenter/app/data"
+	"PaymentCenter/app/http/entities"
+	"PaymentCenter/app/http/entities/backend"
+	"PaymentCenter/app/models/merchantmodel"
+	"PaymentCenter/app/models/paychannelmodel"
+	"xorm.io/builder"
+)
+
+func PayChannelList(req backend.PayChannelListRequest) (result []paychannelmodel.PayChannel, total int64, code int) {
+	repo := data.NewPayChannelRepo(paychannelmodel.GetInstance().GetDb())
+	// 拼接查询条件
+	conn := builder.NewCond()
+	if req.MerchantId > 0 {
+		conn = conn.And(builder.Eq{"merchant_id": req.MerchantId})
+	}
+
+	// 调用repo
+	paychannelList := make([]paychannelmodel.PayChannel, 0)
+	count, err := repo.PayChannelList(conn, req.PageRequest, &paychannelList)
+	code = handErr(err)
+	return paychannelList, count, code
+}
+
+func PayChannelCreate(payChannel *paychannelmodel.PayChannel) (code int) {
+	db := paychannelmodel.GetInstance().GetDb()
+	repo := data.NewPayChannelRepo(db)
+	merchantRepo := data.NewMerchantRepo(db)
+	// 拼接查询条件
+	conn := builder.NewCond()
+	conn = conn.And(builder.Eq{"id": payChannel.MerchantId})
+	merchant := merchantmodel.Merchant{}
+	has, err := merchantRepo.MerchantDetail(&merchant, conn)
+	if err != nil {
+		return handErr(err)
+	}
+	if !has {
+		return errorcode.MerchantNotFound
+	}
+
+	_, err = repo.PayChannelInsertOne(payChannel)
+	code = handErr(err)
+	return
+}
+
+func PayChannelUpdate(payChannel *paychannelmodel.PayChannel) (code int) {
+	db := paychannelmodel.GetInstance().GetDb()
+	repo := data.NewPayChannelRepo(db)
+	merchantRepo := data.NewMerchantRepo(db)
+	// 拼接查询条件
+	conn := builder.NewCond()
+	conn = conn.And(builder.Eq{"id": payChannel.MerchantId})
+	merchant := merchantmodel.Merchant{}
+	has, err := merchantRepo.MerchantDetail(&merchant, conn)
+	if err != nil {
+		return handErr(err)
+	}
+	if !has {
+		return errorcode.MerchantNotFound
+	}
+
+	// 拼接查询条件
+	uconn := builder.NewCond()
+	uconn = uconn.And(builder.Eq{"Id": payChannel.Id})
+	_, err = repo.PayChannelUpdate(payChannel, uconn, "white_ip")
+
+	code = handErr(err)
+	return
+}
+
+func PayChannelDelete(req entities.IdRequest) (code int) {
+	repo := data.NewPayChannelRepo(paychannelmodel.GetInstance().GetDb())
+
+	// 拼接查询条件
+	conn := builder.NewCond()
+	conn = conn.And(builder.Eq{"Id": req.Id})
+	m := paychannelmodel.PayChannel{Id: req.Id}
+	_, err := repo.PayChannelDelete(&m, conn)
+
+	code = handErr(err)
+	return
+}