diff --git a/controllers/payment.go b/controllers/payment.go
new file mode 100644
index 00000000..b2bbcc36
--- /dev/null
+++ b/controllers/payment.go
@@ -0,0 +1,116 @@
+// Copyright 2022 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package controllers
+
+import (
+ "encoding/json"
+
+ "github.com/astaxie/beego/utils/pagination"
+ "github.com/casdoor/casdoor/object"
+ "github.com/casdoor/casdoor/util"
+)
+
+// GetPayments
+// @Title GetPayments
+// @Tag Payment API
+// @Description get payments
+// @Param owner query string true "The owner of payments"
+// @Success 200 {array} object.Payment The Response object
+// @router /get-payments [get]
+func (c *ApiController) GetPayments() {
+ owner := c.Input().Get("owner")
+ limit := c.Input().Get("pageSize")
+ page := c.Input().Get("p")
+ field := c.Input().Get("field")
+ value := c.Input().Get("value")
+ sortField := c.Input().Get("sortField")
+ sortOrder := c.Input().Get("sortOrder")
+ if limit == "" || page == "" {
+ c.Data["json"] = object.GetPayments(owner)
+ c.ServeJSON()
+ } else {
+ limit := util.ParseInt(limit)
+ paginator := pagination.SetPaginator(c.Ctx, limit, int64(object.GetPaymentCount(owner, field, value)))
+ payments := object.GetPaginationPayments(owner, paginator.Offset(), limit, field, value, sortField, sortOrder)
+ c.ResponseOk(payments, paginator.Nums())
+ }
+}
+
+// @Title GetPayment
+// @Tag Payment API
+// @Description get payment
+// @Param id query string true "The id of the payment"
+// @Success 200 {object} object.Payment The Response object
+// @router /get-payment [get]
+func (c *ApiController) GetPayment() {
+ id := c.Input().Get("id")
+
+ c.Data["json"] = object.GetPayment(id)
+ c.ServeJSON()
+}
+
+// @Title UpdatePayment
+// @Tag Payment API
+// @Description update payment
+// @Param id query string true "The id of the payment"
+// @Param body body object.Payment true "The details of the payment"
+// @Success 200 {object} controllers.Response The Response object
+// @router /update-payment [post]
+func (c *ApiController) UpdatePayment() {
+ id := c.Input().Get("id")
+
+ var payment object.Payment
+ err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
+ if err != nil {
+ panic(err)
+ }
+
+ c.Data["json"] = wrapActionResponse(object.UpdatePayment(id, &payment))
+ c.ServeJSON()
+}
+
+// @Title AddPayment
+// @Tag Payment API
+// @Description add payment
+// @Param body body object.Payment true "The details of the payment"
+// @Success 200 {object} controllers.Response The Response object
+// @router /add-payment [post]
+func (c *ApiController) AddPayment() {
+ var payment object.Payment
+ err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
+ if err != nil {
+ panic(err)
+ }
+
+ c.Data["json"] = wrapActionResponse(object.AddPayment(&payment))
+ c.ServeJSON()
+}
+
+// @Title DeletePayment
+// @Tag Payment API
+// @Description delete payment
+// @Param body body object.Payment true "The details of the payment"
+// @Success 200 {object} controllers.Response The Response object
+// @router /delete-payment [post]
+func (c *ApiController) DeletePayment() {
+ var payment object.Payment
+ err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
+ if err != nil {
+ panic(err)
+ }
+
+ c.Data["json"] = wrapActionResponse(object.DeletePayment(&payment))
+ c.ServeJSON()
+}
diff --git a/object/adapter.go b/object/adapter.go
index 2fcf93a6..3efae0d2 100644
--- a/object/adapter.go
+++ b/object/adapter.go
@@ -183,6 +183,11 @@ func (a *Adapter) createTable() {
panic(err)
}
+ err = a.Engine.Sync2(new(Payment))
+ if err != nil {
+ panic(err)
+ }
+
err = a.Engine.Sync2(new(Ldap))
if err != nil {
panic(err)
@@ -211,4 +216,4 @@ func GetSession(owner string, offset, limit int, field, value, sortField, sortOr
session = session.Desc(util.SnakeString(sortField))
}
return session
-}
\ No newline at end of file
+}
diff --git a/object/payment.go b/object/payment.go
new file mode 100644
index 00000000..1b3912b0
--- /dev/null
+++ b/object/payment.go
@@ -0,0 +1,129 @@
+// Copyright 2022 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package object
+
+import (
+ "fmt"
+
+ "github.com/casdoor/casdoor/util"
+ "xorm.io/core"
+)
+
+type Payment struct {
+ Owner string `xorm:"varchar(100) notnull pk" json:"owner"`
+ Name string `xorm:"varchar(100) notnull pk" json:"name"`
+ CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
+ DisplayName string `xorm:"varchar(100)" json:"displayName"`
+
+ Provider string `xorm:"varchar(100)" json:"provider"`
+ Type string `xorm:"varchar(100)" json:"type"`
+ Organization string `xorm:"varchar(100)" json:"organization"`
+ User string `xorm:"varchar(100)" json:"user"`
+ Good string `xorm:"varchar(100)" json:"good"`
+ Amount string `xorm:"varchar(100)" json:"amount"`
+ Currency string `xorm:"varchar(100)" json:"currency"`
+
+ State string `xorm:"varchar(100)" json:"state"`
+}
+
+func GetPaymentCount(owner, field, value string) int {
+ session := GetSession(owner, -1, -1, field, value, "", "")
+ count, err := session.Count(&Payment{})
+ if err != nil {
+ panic(err)
+ }
+
+ return int(count)
+}
+
+func GetPayments(owner string) []*Payment {
+ payments := []*Payment{}
+ err := adapter.Engine.Desc("created_time").Find(&payments, &Payment{Owner: owner})
+ if err != nil {
+ panic(err)
+ }
+
+ return payments
+}
+
+func GetPaginationPayments(owner string, offset, limit int, field, value, sortField, sortOrder string) []*Payment {
+ payments := []*Payment{}
+ session := GetSession(owner, offset, limit, field, value, sortField, sortOrder)
+ err := session.Find(&payments)
+ if err != nil {
+ panic(err)
+ }
+
+ return payments
+}
+
+func getPayment(owner string, name string) *Payment {
+ if owner == "" || name == "" {
+ return nil
+ }
+
+ payment := Payment{Owner: owner, Name: name}
+ existed, err := adapter.Engine.Get(&payment)
+ if err != nil {
+ panic(err)
+ }
+
+ if existed {
+ return &payment
+ } else {
+ return nil
+ }
+}
+
+func GetPayment(id string) *Payment {
+ owner, name := util.GetOwnerAndNameFromId(id)
+ return getPayment(owner, name)
+}
+
+func UpdatePayment(id string, payment *Payment) bool {
+ owner, name := util.GetOwnerAndNameFromId(id)
+ if getPayment(owner, name) == nil {
+ return false
+ }
+
+ affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(payment)
+ if err != nil {
+ panic(err)
+ }
+
+ return affected != 0
+}
+
+func AddPayment(payment *Payment) bool {
+ affected, err := adapter.Engine.Insert(payment)
+ if err != nil {
+ panic(err)
+ }
+
+ return affected != 0
+}
+
+func DeletePayment(payment *Payment) bool {
+ affected, err := adapter.Engine.ID(core.PK{payment.Owner, payment.Name}).Delete(&Payment{})
+ if err != nil {
+ panic(err)
+ }
+
+ return affected != 0
+}
+
+func (payment *Payment) GetId() string {
+ return fmt.Sprintf("%s/%s", payment.Owner, payment.Name)
+}
diff --git a/routers/router.go b/routers/router.go
index 348818bc..aa67e269 100644
--- a/routers/router.go
+++ b/routers/router.go
@@ -149,6 +149,12 @@ func initAPI() {
beego.Router("/api/add-cert", &controllers.ApiController{}, "POST:AddCert")
beego.Router("/api/delete-cert", &controllers.ApiController{}, "POST:DeleteCert")
+ beego.Router("/api/get-payments", &controllers.ApiController{}, "GET:GetPayments")
+ beego.Router("/api/get-payment", &controllers.ApiController{}, "GET:GetPayment")
+ beego.Router("/api/update-payment", &controllers.ApiController{}, "POST:UpdatePayment")
+ beego.Router("/api/add-payment", &controllers.ApiController{}, "POST:AddPayment")
+ beego.Router("/api/delete-payment", &controllers.ApiController{}, "POST:DeletePayment")
+
beego.Router("/api/send-email", &controllers.ApiController{}, "POST:SendEmail")
beego.Router("/api/send-sms", &controllers.ApiController{}, "POST:SendSms")
diff --git a/web/src/App.js b/web/src/App.js
index 7f9553a1..dbb12e7f 100644
--- a/web/src/App.js
+++ b/web/src/App.js
@@ -43,6 +43,8 @@ import SyncerListPage from "./SyncerListPage";
import SyncerEditPage from "./SyncerEditPage";
import CertListPage from "./CertListPage";
import CertEditPage from "./CertEditPage";
+import PaymentListPage from "./PaymentListPage";
+import PaymentEditPage from "./PaymentEditPage";
import AccountPage from "./account/AccountPage";
import HomePage from "./basic/HomePage";
import CustomGithubCorner from "./CustomGithubCorner";
@@ -126,6 +128,8 @@ class App extends Component {
this.setState({ selectedMenuKey: '/syncers' });
} else if (uri.includes('/certs')) {
this.setState({ selectedMenuKey: '/certs' });
+ } else if (uri.includes('/payments')) {
+ this.setState({ selectedMenuKey: '/payments' });
} else if (uri.includes('/signup')) {
this.setState({ selectedMenuKey: '/signup' });
} else if (uri.includes('/login')) {
@@ -408,6 +412,13 @@ class App extends Component {
);
+ res.push(
+
+
+ {i18next.t("general:Payments")}
+
+
+ );
res.push(
@@ -478,6 +489,8 @@ class App extends Component {
this.renderLoginIfNotLoggedIn()}/>
this.renderLoginIfNotLoggedIn()}/>
this.renderLoginIfNotLoggedIn()}/>
+ this.renderLoginIfNotLoggedIn()}/>
+ this.renderLoginIfNotLoggedIn()}/>
this.renderLoginIfNotLoggedIn()}/>
}/>
{
+ this.setState({
+ payment: payment,
+ });
+ });
+ }
+
+ parsePaymentField(key, value) {
+ if ([""].includes(key)) {
+ value = Setting.myParseInt(value);
+ }
+ return value;
+ }
+
+ updatePaymentField(key, value) {
+ value = this.parsePaymentField(key, value);
+
+ let payment = this.state.payment;
+ payment[key] = value;
+ this.setState({
+ payment: payment,
+ });
+ }
+
+ renderPayment() {
+ return (
+
+ {i18next.t("payment:Edit Payment")}
+
+
+
+ } style={(Setting.isMobile())? {margin: '5px'}:{}} type="inner">
+
+
+ {Setting.getLabel(i18next.t("general:Organization"), i18next.t("general:Organization - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('organization', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('name', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("general:Display name"), i18next.t("general:Display name - Tooltip"))} :
+
+
+ {
+ this.updatePaymentField('displayName', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("general:Name"), i18next.t("general:Name - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('name', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("general:Provider"), i18next.t("general:Provider - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('provider', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("provider:Type"), i18next.t("provider:Type - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('type', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("payment:Good"), i18next.t("payment:Good - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('good', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("payment:Amount"), i18next.t("payment:Amount - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('amount', e.target.value);
+ }} />
+
+
+
+
+ {Setting.getLabel(i18next.t("payment:Currency"), i18next.t("payment:Currency - Tooltip"))} :
+
+
+ {
+ // this.updatePaymentField('currency', e.target.value);
+ }} />
+
+
+
+ )
+ }
+
+ submitPaymentEdit(willExist) {
+ let payment = Setting.deepCopy(this.state.payment);
+ PaymentBackend.updatePayment(this.state.organizationName, this.state.paymentName, payment)
+ .then((res) => {
+ if (res.msg === "") {
+ Setting.showMessage("success", `Successfully saved`);
+ this.setState({
+ paymentName: this.state.payment.name,
+ });
+
+ if (willExist) {
+ this.props.history.push(`/payments`);
+ } else {
+ this.props.history.push(`/payments/${this.state.payment.name}`);
+ }
+ } else {
+ Setting.showMessage("error", res.msg);
+ this.updatePaymentField('name', this.state.paymentName);
+ }
+ })
+ .catch(error => {
+ Setting.showMessage("error", `Failed to connect to server: ${error}`);
+ });
+ }
+
+ render() {
+ return (
+
+ {
+ this.state.payment !== null ? this.renderPayment() : null
+ }
+
+
+
+
+
+ );
+ }
+}
+
+export default PaymentEditPage;
diff --git a/web/src/PaymentListPage.js b/web/src/PaymentListPage.js
new file mode 100644
index 00000000..80314ce4
--- /dev/null
+++ b/web/src/PaymentListPage.js
@@ -0,0 +1,264 @@
+// Copyright 2022 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import React from "react";
+import {Link} from "react-router-dom";
+import {Button, Popconfirm, Switch, Table} from 'antd';
+import moment from "moment";
+import * as Setting from "./Setting";
+import * as PaymentBackend from "./backend/PaymentBackend";
+import i18next from "i18next";
+import BaseListPage from "./BaseListPage";
+import * as Provider from "./auth/Provider";
+
+class PaymentListPage extends BaseListPage {
+ newPayment() {
+ const randomName = Setting.getRandomName();
+ return {
+ owner: "admin",
+ name: `payment_${randomName}`,
+ createdTime: moment().format(),
+ displayName: `New Payment - ${randomName}`,
+ provider: "provider_pay_paypal",
+ type: "PayPal",
+ organization: "built-in",
+ user: "admin",
+ good: "A notebook computer",
+ amount: "300",
+ currency: "USD",
+ state: "Paid",
+ }
+ }
+
+ addPayment() {
+ const newPayment = this.newPayment();
+ PaymentBackend.addPayment(newPayment)
+ .then((res) => {
+ Setting.showMessage("success", `Payment added successfully`);
+ this.props.history.push(`/payments/${newPayment.name}`);
+ }
+ )
+ .catch(error => {
+ Setting.showMessage("error", `Payment failed to add: ${error}`);
+ });
+ }
+
+ deletePayment(i) {
+ PaymentBackend.deletePayment(this.state.data[i])
+ .then((res) => {
+ Setting.showMessage("success", `Payment deleted successfully`);
+ this.setState({
+ data: Setting.deleteRow(this.state.data, i),
+ pagination: {total: this.state.pagination.total - 1},
+ });
+ }
+ )
+ .catch(error => {
+ Setting.showMessage("error", `Payment failed to delete: ${error}`);
+ });
+ }
+
+ renderTable(payments) {
+ const columns = [
+ {
+ title: i18next.t("general:Organization"),
+ dataIndex: 'owner',
+ key: 'owner',
+ width: '120px',
+ sorter: true,
+ ...this.getColumnSearchProps('owner'),
+ render: (text, record, index) => {
+ return (
+
+ {text}
+
+ )
+ }
+ },
+ {
+ title: i18next.t("general:User"),
+ dataIndex: 'user',
+ key: 'user',
+ width: '120px',
+ sorter: true,
+ ...this.getColumnSearchProps('user'),
+ render: (text, record, index) => {
+ return (
+
+ {text}
+
+ )
+ }
+ },
+ {
+ title: i18next.t("general:Name"),
+ dataIndex: 'name',
+ key: 'name',
+ width: '150px',
+ fixed: 'left',
+ sorter: true,
+ ...this.getColumnSearchProps('name'),
+ render: (text, record, index) => {
+ return (
+
+ {text}
+
+ )
+ }
+ },
+ {
+ title: i18next.t("general:Created time"),
+ dataIndex: 'createdTime',
+ key: 'createdTime',
+ width: '160px',
+ sorter: true,
+ render: (text, record, index) => {
+ return Setting.getFormattedDate(text);
+ }
+ },
+ // {
+ // title: i18next.t("general:Display name"),
+ // dataIndex: 'displayName',
+ // key: 'displayName',
+ // width: '160px',
+ // sorter: true,
+ // ...this.getColumnSearchProps('displayName'),
+ // },
+ {
+ title: i18next.t("general:Provider"),
+ dataIndex: 'provider',
+ key: 'provider',
+ width: '150px',
+ fixed: 'left',
+ sorter: true,
+ ...this.getColumnSearchProps('provider'),
+ render: (text, record, index) => {
+ return (
+
+ {text}
+
+ )
+ }
+ },
+ {
+ title: i18next.t("provider:Type"),
+ dataIndex: 'type',
+ key: 'type',
+ width: '110px',
+ align: 'center',
+ filterMultiple: false,
+ filters: [
+ {text: 'Payment', value: 'Payment', children: Setting.getProviderTypeOptions('Payment').map((o) => {return {text:o.id, value:o.name}})},
+ ],
+ sorter: true,
+ render: (text, record, index) => {
+ return Provider.getProviderLogoWidget(record);
+ }
+ },
+ {
+ title: i18next.t("payment:Good"),
+ dataIndex: 'good',
+ key: 'good',
+ width: '160px',
+ sorter: true,
+ ...this.getColumnSearchProps('good'),
+ },
+ {
+ title: i18next.t("payment:Amount"),
+ dataIndex: 'amount',
+ key: 'amount',
+ width: '120px',
+ sorter: true,
+ ...this.getColumnSearchProps('amount'),
+ },
+ {
+ title: i18next.t("payment:Currency"),
+ dataIndex: 'currency',
+ key: 'currency',
+ width: '120px',
+ sorter: true,
+ ...this.getColumnSearchProps('currency'),
+ },
+ {
+ title: i18next.t("general:Action"),
+ dataIndex: '',
+ key: 'op',
+ width: '170px',
+ fixed: (Setting.isMobile()) ? "false" : "right",
+ render: (text, record, index) => {
+ return (
+
+
+
this.deletePayment(index)}
+ >
+
+
+
+ )
+ }
+ },
+ ];
+
+ const paginationProps = {
+ total: this.state.pagination.total,
+ showQuickJumper: true,
+ showSizeChanger: true,
+ showTotal: () => i18next.t("general:{total} in total").replace("{total}", this.state.pagination.total),
+ };
+
+ return (
+
+
(
+
+ {i18next.t("general:Payments")}
+
+
+ )}
+ loading={this.state.loading}
+ onChange={this.handleTableChange}
+ />
+
+ );
+ }
+
+ fetch = (params = {}) => {
+ let field = params.searchedColumn, value = params.searchText;
+ let sortField = params.sortField, sortOrder = params.sortOrder;
+ if (params.type !== undefined && params.type !== null) {
+ field = "type";
+ value = params.type;
+ }
+ this.setState({ loading: true });
+ PaymentBackend.getPayments("", params.pagination.current, params.pagination.pageSize, field, value, sortField, sortOrder)
+ .then((res) => {
+ if (res.status === "ok") {
+ this.setState({
+ loading: false,
+ data: res.data,
+ pagination: {
+ ...params.pagination,
+ total: res.data2,
+ },
+ searchText: params.searchText,
+ searchedColumn: params.searchedColumn,
+ });
+ }
+ });
+ };
+}
+
+export default PaymentListPage;
diff --git a/web/src/ProviderEditPage.js b/web/src/ProviderEditPage.js
index 61d3ceed..6c07e697 100644
--- a/web/src/ProviderEditPage.js
+++ b/web/src/ProviderEditPage.js
@@ -184,6 +184,7 @@ class ProviderEditPage extends React.Component {
{id: 'SMS', name: 'SMS'},
{id: 'Storage', name: 'Storage'},
{id: 'SAML', name: 'SAML'},
+ {id: 'Payment', name: 'Payment'},
].map((providerCategory, index) => )
}
diff --git a/web/src/Setting.js b/web/src/Setting.js
index aa287667..980b4b30 100644
--- a/web/src/Setting.js
+++ b/web/src/Setting.js
@@ -432,6 +432,12 @@ export function getProviderTypeOptions(category) {
{id: 'Aliyun IDaaS', name: 'Aliyun IDaaS'},
{id: 'Keycloak', name: 'Keycloak'},
]);
+ } else if (category === "Payment") {
+ return ([
+ {id: 'Alipay', name: 'Alipay'},
+ {id: 'WeChat Pay', name: 'WeChat Pay'},
+ {id: 'PayPal', name: 'PayPal'},
+ ]);
} else {
return [];
}
diff --git a/web/src/auth/Provider.js b/web/src/auth/Provider.js
index 2c7f16d2..48ebc7ca 100644
--- a/web/src/auth/Provider.js
+++ b/web/src/auth/Provider.js
@@ -137,6 +137,20 @@ const otherProviderInfo = {
url: "https://www.keycloak.org/"
},
},
+ Payment: {
+ "Alipay": {
+ logo: `${StaticBaseUrl}/img/payment_alipay.png`,
+ url: "https://www.alipay.com/"
+ },
+ "WeChat Pay": {
+ logo: `${StaticBaseUrl}/img/payment_wechat_pay.png`,
+ url: "https://pay.weixin.qq.com/"
+ },
+ "PayPal": {
+ logo: `${StaticBaseUrl}/img/payment_paypal.png`,
+ url: "https://www.paypal.com/"
+ },
+ },
};
export function getProviderLogo(provider) {
diff --git a/web/src/backend/PaymentBackend.js b/web/src/backend/PaymentBackend.js
new file mode 100644
index 00000000..85bb76f6
--- /dev/null
+++ b/web/src/backend/PaymentBackend.js
@@ -0,0 +1,56 @@
+// Copyright 2022 The casbin Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import * as Setting from "../Setting";
+
+export function getPayments(owner, page = "", pageSize = "", field = "", value = "", sortField = "", sortOrder = "") {
+ return fetch(`${Setting.ServerUrl}/api/get-payments?owner=${owner}&p=${page}&pageSize=${pageSize}&field=${field}&value=${value}&sortField=${sortField}&sortOrder=${sortOrder}`, {
+ method: "GET",
+ credentials: "include"
+ }).then(res => res.json());
+}
+
+export function getPayment(owner, name) {
+ return fetch(`${Setting.ServerUrl}/api/get-payment?id=${owner}/${encodeURIComponent(name)}`, {
+ method: "GET",
+ credentials: "include"
+ }).then(res => res.json());
+}
+
+export function updatePayment(owner, name, payment) {
+ let newPayment = Setting.deepCopy(payment);
+ return fetch(`${Setting.ServerUrl}/api/update-payment?id=${owner}/${encodeURIComponent(name)}`, {
+ method: 'POST',
+ credentials: 'include',
+ body: JSON.stringify(newPayment),
+ }).then(res => res.json());
+}
+
+export function addPayment(payment) {
+ let newPayment = Setting.deepCopy(payment);
+ return fetch(`${Setting.ServerUrl}/api/add-payment`, {
+ method: 'POST',
+ credentials: 'include',
+ body: JSON.stringify(newPayment),
+ }).then(res => res.json());
+}
+
+export function deletePayment(payment) {
+ let newPayment = Setting.deepCopy(payment);
+ return fetch(`${Setting.ServerUrl}/api/delete-payment`, {
+ method: 'POST',
+ credentials: 'include',
+ body: JSON.stringify(newPayment),
+ }).then(res => res.json());
+}
diff --git a/web/src/locales/de/data.json b/web/src/locales/de/data.json
index 07d2ae25..20fb2cea 100644
--- a/web/src/locales/de/data.json
+++ b/web/src/locales/de/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "Random parameters used for password encryption",
"Password type": "Passworttyp",
"Password type - Tooltip": "The form in which the password is stored in the database",
+ "Payments": "Payments",
"Permissions": "Berechtigungen",
"Personal name": "Persönlicher Name",
"Phone": "Telefon",
@@ -142,6 +143,7 @@
"Preview": "Vorschau",
"Preview - Tooltip": "The form in which the password is stored in the database",
"Provider": "Anbieter",
+ "Provider - Tooltip": "Provider - Tooltip",
"Providers": "Anbieter",
"Providers - Tooltip": "List of third-party applications that can be used to log in",
"Records": "Datensätze",
@@ -234,6 +236,15 @@
"Website URL": "Website-URL",
"Website URL - Tooltip": "Unique string-style identifier"
},
+ "payment": {
+ "Amount": "Amount",
+ "Amount - Tooltip": "Amount - Tooltip",
+ "Currency": "Currency",
+ "Currency - Tooltip": "Currency - Tooltip",
+ "Edit Payment": "Edit Payment",
+ "Good": "Good",
+ "Good - Tooltip": "Good - Tooltip"
+ },
"permission": {
"Actions": "Aktionen",
"Actions - Tooltip": "Aktionen - Tooltip",
diff --git a/web/src/locales/en/data.json b/web/src/locales/en/data.json
index 0bb974a2..0954ba08 100644
--- a/web/src/locales/en/data.json
+++ b/web/src/locales/en/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "Password salt - Tooltip",
"Password type": "Password type",
"Password type - Tooltip": "Password type - Tooltip",
+ "Payments": "Payments",
"Permissions": "Permissions",
"Personal name": "Personal name",
"Phone": "Phone",
@@ -142,6 +143,7 @@
"Preview": "Preview",
"Preview - Tooltip": "Preview - Tooltip",
"Provider": "Provider",
+ "Provider - Tooltip": "Provider - Tooltip",
"Providers": "Providers",
"Providers - Tooltip": "Providers - Tooltip",
"Records": "Records",
@@ -234,6 +236,15 @@
"Website URL": "Website URL",
"Website URL - Tooltip": "Website URL - Tooltip"
},
+ "payment": {
+ "Amount": "Amount",
+ "Amount - Tooltip": "Amount - Tooltip",
+ "Currency": "Currency",
+ "Currency - Tooltip": "Currency - Tooltip",
+ "Edit Payment": "Edit Payment",
+ "Good": "Good",
+ "Good - Tooltip": "Good - Tooltip"
+ },
"permission": {
"Actions": "Actions",
"Actions - Tooltip": "Actions - Tooltip",
diff --git a/web/src/locales/fr/data.json b/web/src/locales/fr/data.json
index 646e54cd..4493ef75 100644
--- a/web/src/locales/fr/data.json
+++ b/web/src/locales/fr/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "Random parameters used for password encryption",
"Password type": "Type de mot de passe",
"Password type - Tooltip": "The form in which the password is stored in the database",
+ "Payments": "Payments",
"Permissions": "Permissions",
"Personal name": "Nom personnel",
"Phone": "Téléphone",
@@ -142,6 +143,7 @@
"Preview": "Aperçu",
"Preview - Tooltip": "The form in which the password is stored in the database",
"Provider": "Fournisseur",
+ "Provider - Tooltip": "Provider - Tooltip",
"Providers": "Fournisseurs",
"Providers - Tooltip": "List of third-party applications that can be used to log in",
"Records": "Enregistrements",
@@ -234,6 +236,15 @@
"Website URL": "URL du site web",
"Website URL - Tooltip": "Unique string-style identifier"
},
+ "payment": {
+ "Amount": "Amount",
+ "Amount - Tooltip": "Amount - Tooltip",
+ "Currency": "Currency",
+ "Currency - Tooltip": "Currency - Tooltip",
+ "Edit Payment": "Edit Payment",
+ "Good": "Good",
+ "Good - Tooltip": "Good - Tooltip"
+ },
"permission": {
"Actions": "Actions",
"Actions - Tooltip": "Actions - Info-bulle",
diff --git a/web/src/locales/ja/data.json b/web/src/locales/ja/data.json
index be36da5b..d3c44d67 100644
--- a/web/src/locales/ja/data.json
+++ b/web/src/locales/ja/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "Random parameters used for password encryption",
"Password type": "パスワードの種類",
"Password type - Tooltip": "The form in which the password is stored in the database",
+ "Payments": "Payments",
"Permissions": "アクセス許可",
"Personal name": "個人名",
"Phone": "電話番号",
@@ -142,6 +143,7 @@
"Preview": "プレビュー",
"Preview - Tooltip": "The form in which the password is stored in the database",
"Provider": "プロバイダー",
+ "Provider - Tooltip": "Provider - Tooltip",
"Providers": "プロバイダー",
"Providers - Tooltip": "List of third-party applications that can be used to log in",
"Records": "レコード",
@@ -234,6 +236,15 @@
"Website URL": "Website URL",
"Website URL - Tooltip": "Unique string-style identifier"
},
+ "payment": {
+ "Amount": "Amount",
+ "Amount - Tooltip": "Amount - Tooltip",
+ "Currency": "Currency",
+ "Currency - Tooltip": "Currency - Tooltip",
+ "Edit Payment": "Edit Payment",
+ "Good": "Good",
+ "Good - Tooltip": "Good - Tooltip"
+ },
"permission": {
"Actions": "アクション",
"Actions - Tooltip": "アクション → ツールチップ",
diff --git a/web/src/locales/ko/data.json b/web/src/locales/ko/data.json
index a106821e..2dc7b696 100644
--- a/web/src/locales/ko/data.json
+++ b/web/src/locales/ko/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "Random parameters used for password encryption",
"Password type": "Password type",
"Password type - Tooltip": "The form in which the password is stored in the database",
+ "Payments": "Payments",
"Permissions": "Permissions",
"Personal name": "Personal name",
"Phone": "Phone",
@@ -142,6 +143,7 @@
"Preview": "Preview",
"Preview - Tooltip": "The form in which the password is stored in the database",
"Provider": "Provider",
+ "Provider - Tooltip": "Provider - Tooltip",
"Providers": "Providers",
"Providers - Tooltip": "List of third-party applications that can be used to log in",
"Records": "Records",
@@ -234,6 +236,15 @@
"Website URL": "Website URL",
"Website URL - Tooltip": "Unique string-style identifier"
},
+ "payment": {
+ "Amount": "Amount",
+ "Amount - Tooltip": "Amount - Tooltip",
+ "Currency": "Currency",
+ "Currency - Tooltip": "Currency - Tooltip",
+ "Edit Payment": "Edit Payment",
+ "Good": "Good",
+ "Good - Tooltip": "Good - Tooltip"
+ },
"permission": {
"Actions": "Actions",
"Actions - Tooltip": "Actions - Tooltip",
diff --git a/web/src/locales/ru/data.json b/web/src/locales/ru/data.json
index 7b74ca2d..aa1517bb 100644
--- a/web/src/locales/ru/data.json
+++ b/web/src/locales/ru/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "Random parameters used for password encryption",
"Password type": "Тип пароля",
"Password type - Tooltip": "The form in which the password is stored in the database",
+ "Payments": "Payments",
"Permissions": "Права доступа",
"Personal name": "Личное имя",
"Phone": "Телефон",
@@ -142,6 +143,7 @@
"Preview": "Предпросмотр",
"Preview - Tooltip": "The form in which the password is stored in the database",
"Provider": "Поставщик",
+ "Provider - Tooltip": "Provider - Tooltip",
"Providers": "Поставщики",
"Providers - Tooltip": "List of third-party applications that can be used to log in",
"Records": "Отчеты",
@@ -234,6 +236,15 @@
"Website URL": "URL сайта",
"Website URL - Tooltip": "Unique string-style identifier"
},
+ "payment": {
+ "Amount": "Amount",
+ "Amount - Tooltip": "Amount - Tooltip",
+ "Currency": "Currency",
+ "Currency - Tooltip": "Currency - Tooltip",
+ "Edit Payment": "Edit Payment",
+ "Good": "Good",
+ "Good - Tooltip": "Good - Tooltip"
+ },
"permission": {
"Actions": "Действия",
"Actions - Tooltip": "Действия - Подсказка",
diff --git a/web/src/locales/zh/data.json b/web/src/locales/zh/data.json
index dce0f11b..9af83849 100644
--- a/web/src/locales/zh/data.json
+++ b/web/src/locales/zh/data.json
@@ -133,6 +133,7 @@
"Password salt - Tooltip": "用于密码加密的随机参数",
"Password type": "密码类型",
"Password type - Tooltip": "密码在数据库中存储的形式",
+ "Payments": "付款",
"Permissions": "权限",
"Personal name": "姓名",
"Phone": "手机号",
@@ -142,6 +143,7 @@
"Preview": "预览",
"Preview - Tooltip": "预览",
"Provider": "提供商",
+ "Provider - Tooltip": "第三方登录需要配置的提供方",
"Providers": "提供商",
"Providers - Tooltip": "第三方登录需要配置的提供方",
"Records": "日志",
@@ -234,6 +236,15 @@
"Website URL": "网页地址",
"Website URL - Tooltip": "网页地址"
},
+ "payment": {
+ "Amount": "金额",
+ "Amount - Tooltip": "付款的金额",
+ "Currency": "币种",
+ "Currency - Tooltip": "如USD(美元),CNY(人民币)等",
+ "Edit Payment": "编辑付款",
+ "Good": "商品",
+ "Good - Tooltip": "购买的商品名称"
+ },
"permission": {
"Actions": "动作",
"Actions - Tooltip": "授权的动作",