mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-23 22:53:31 +08:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
effd257040 | |||
a38747d90e | |||
da70682cd1 | |||
4a3bd84f84 | |||
7f2869cecb |
@ -16,6 +16,7 @@ package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/beego/beego/utils/pagination"
|
||||
"github.com/casdoor/casdoor/object"
|
||||
@ -163,11 +164,17 @@ func (c *ApiController) GetPolicies() {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
if adapter == nil {
|
||||
c.ResponseError(fmt.Sprintf(c.T("the adapter: %s is not found"), adapterId))
|
||||
return
|
||||
}
|
||||
|
||||
err = adapter.InitAdapter()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk()
|
||||
return
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ func (c *ApiController) GetSystemInfo() {
|
||||
// @Success 200 {object} util.VersionInfo The Response object
|
||||
// @router /get-version-info [get]
|
||||
func (c *ApiController) GetVersionInfo() {
|
||||
errInfo := ""
|
||||
versionInfo, err := util.GetVersionInfo()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
return
|
||||
errInfo = "Git error: " + err.Error()
|
||||
}
|
||||
|
||||
if versionInfo.Version != "" {
|
||||
@ -59,9 +59,11 @@ func (c *ApiController) GetVersionInfo() {
|
||||
|
||||
versionInfo, err = util.GetVersionInfoFromFile()
|
||||
if err != nil {
|
||||
c.ResponseError(err.Error())
|
||||
errInfo = errInfo + ", File error: " + err.Error()
|
||||
c.ResponseError(errInfo)
|
||||
return
|
||||
}
|
||||
|
||||
c.ResponseOk(versionInfo)
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,15 @@ func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
|
||||
}
|
||||
|
||||
bindPassword := string(r.AuthenticationSimple())
|
||||
bindUser, err := object.CheckUserPassword(bindOrg, bindUsername, bindPassword, "en")
|
||||
|
||||
enableCaptcha := false
|
||||
isSigninViaLdap := false
|
||||
isPasswordWithLdapEnabled := false
|
||||
if bindPassword != "" {
|
||||
isPasswordWithLdapEnabled = true
|
||||
}
|
||||
|
||||
bindUser, err := object.CheckUserPassword(bindOrg, bindUsername, bindPassword, "en", enableCaptcha, isSigninViaLdap, isPasswordWithLdapEnabled)
|
||||
if err != nil {
|
||||
log.Printf("Bind failed User=%s, Pass=%#v, ErrMsg=%s", string(r.Name()), r.Authentication(), err)
|
||||
res.SetResultCode(ldap.LDAPResultInvalidCredentials)
|
||||
|
@ -201,7 +201,7 @@ func notifyPayment(body []byte, owner string, paymentName string) (*Payment, *pp
|
||||
}
|
||||
|
||||
if payment.IsRecharge {
|
||||
err = updateUserBalance(payment.Owner, payment.User, payment.Price)
|
||||
err = UpdateUserBalance(payment.Owner, payment.User, payment.Price)
|
||||
return payment, notifyResult, err
|
||||
}
|
||||
|
||||
@ -222,6 +222,19 @@ func NotifyPayment(body []byte, owner string, paymentName string) (*Payment, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transaction, err := GetTransaction(payment.GetId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if transaction != nil {
|
||||
transaction.State = payment.State
|
||||
_, err = UpdateTransaction(transaction.GetId(), transaction)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return payment, nil
|
||||
|
@ -227,13 +227,17 @@ func BuyProduct(id string, user *User, providerName, pricingName, planName, host
|
||||
NotifyUrl: notifyUrl,
|
||||
PaymentEnv: paymentEnv,
|
||||
}
|
||||
|
||||
// custom process for WeChat & WeChat Pay
|
||||
if provider.Type == "WeChat Pay" {
|
||||
payReq.PayerId, err = getUserExtraProperty(user, "WeChat", idp.BuildWechatOpenIdKey(provider.ClientId2))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
} else if provider.Type == "Balance" {
|
||||
payReq.PayerId = user.GetId()
|
||||
}
|
||||
|
||||
payResp, err := pProvider.Pay(payReq)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -264,12 +268,46 @@ func BuyProduct(id string, user *User, providerName, pricingName, planName, host
|
||||
OutOrderId: payResp.OrderId,
|
||||
}
|
||||
|
||||
transaction := &Transaction{
|
||||
Owner: payment.Owner,
|
||||
Name: payment.Name,
|
||||
DisplayName: payment.DisplayName,
|
||||
Provider: provider.Name,
|
||||
Category: provider.Category,
|
||||
Type: provider.Type,
|
||||
|
||||
ProductName: product.Name,
|
||||
ProductDisplayName: product.DisplayName,
|
||||
Detail: product.Detail,
|
||||
Tag: product.Tag,
|
||||
Currency: product.Currency,
|
||||
Amount: payment.Price,
|
||||
ReturnUrl: payment.ReturnUrl,
|
||||
|
||||
User: payment.User,
|
||||
Application: owner,
|
||||
Payment: payment.GetId(),
|
||||
|
||||
State: pp.PaymentStateCreated,
|
||||
}
|
||||
|
||||
if provider.Type == "Dummy" {
|
||||
payment.State = pp.PaymentStatePaid
|
||||
err = updateUserBalance(user.Owner, user.Name, payment.Price)
|
||||
err = UpdateUserBalance(user.Owner, user.Name, payment.Price)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
} else if provider.Type == "Balance" {
|
||||
if product.Price > user.Balance {
|
||||
return nil, nil, fmt.Errorf("insufficient user balance")
|
||||
}
|
||||
transaction.Amount = -transaction.Amount
|
||||
err = UpdateUserBalance(user.Owner, user.Name, -product.Price)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
payment.State = pp.PaymentStatePaid
|
||||
transaction.State = pp.PaymentStatePaid
|
||||
}
|
||||
|
||||
affected, err := AddPayment(payment)
|
||||
@ -280,6 +318,17 @@ func BuyProduct(id string, user *User, providerName, pricingName, planName, host
|
||||
if !affected {
|
||||
return nil, nil, fmt.Errorf("failed to add payment: %s", util.StructToJson(payment))
|
||||
}
|
||||
|
||||
if product.IsRecharge || provider.Type == "Balance" {
|
||||
affected, err = AddTransaction(transaction)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !affected {
|
||||
return nil, nil, fmt.Errorf("failed to add transaction: %s", util.StructToJson(payment))
|
||||
}
|
||||
}
|
||||
|
||||
return payment, payResp.AttachInfo, nil
|
||||
}
|
||||
|
||||
|
@ -309,6 +309,12 @@ func GetPaymentProvider(p *Provider) (pp.PaymentProvider, error) {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else if typ == "Balance" {
|
||||
pp, err := pp.NewBalancePaymentProvider()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pp, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("the payment provider type: %s is not supported", p.Type)
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ package object
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/pp"
|
||||
"github.com/casdoor/casdoor/util"
|
||||
"github.com/xorm-io/core"
|
||||
)
|
||||
@ -43,7 +44,7 @@ type Transaction struct {
|
||||
Application string `xorm:"varchar(100)" json:"application"`
|
||||
Payment string `xorm:"varchar(100)" json:"payment"`
|
||||
|
||||
State string `xorm:"varchar(100)" json:"state"`
|
||||
State pp.PaymentState `xorm:"varchar(100)" json:"state"`
|
||||
}
|
||||
|
||||
func GetTransactionCount(owner, field, value string) (int64, error) {
|
||||
|
@ -1158,7 +1158,7 @@ func GenerateIdForNewUser(application *Application) (string, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func updateUserBalance(owner string, name string, balance float64) error {
|
||||
func UpdateUserBalance(owner string, name string, balance float64) error {
|
||||
user, err := getUser(owner, name)
|
||||
if err != nil {
|
||||
return err
|
||||
|
50
pp/balance.go
Normal file
50
pp/balance.go
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2024 The Casdoor 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 pp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/casdoor/casdoor/util"
|
||||
)
|
||||
|
||||
type BalancePaymentProvider struct{}
|
||||
|
||||
func NewBalancePaymentProvider() (*BalancePaymentProvider, error) {
|
||||
pp := &BalancePaymentProvider{}
|
||||
return pp, nil
|
||||
}
|
||||
|
||||
func (pp *BalancePaymentProvider) Pay(r *PayReq) (*PayResp, error) {
|
||||
owner, _ := util.GetOwnerAndNameFromId(r.PayerId)
|
||||
return &PayResp{
|
||||
PayUrl: r.ReturnUrl,
|
||||
OrderId: fmt.Sprintf("%s/%s", owner, r.PaymentName),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (pp *BalancePaymentProvider) Notify(body []byte, orderId string) (*NotifyResult, error) {
|
||||
return &NotifyResult{
|
||||
PaymentStatus: PaymentStatePaid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (pp *BalancePaymentProvider) GetInvoice(paymentName string, personName string, personIdCard string, personEmail string, personPhone string, invoiceType string, invoiceTitle string, invoiceTaxId string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (pp *BalancePaymentProvider) GetResponseError(err error) string {
|
||||
return ""
|
||||
}
|
@ -16,7 +16,7 @@ import React, {Component, Suspense, lazy} from "react";
|
||||
import "./App.less";
|
||||
import {Helmet} from "react-helmet";
|
||||
import * as Setting from "./Setting";
|
||||
import {setIsTourVisible, setTourLogo} from "./TourConfig";
|
||||
import {setOrgIsTourVisible, setTourLogo} from "./TourConfig";
|
||||
import {StyleProvider, legacyLogicalPropertiesTransformer} from "@ant-design/cssinjs";
|
||||
import {GithubOutlined, InfoCircleFilled, ShareAltOutlined} from "@ant-design/icons";
|
||||
import {Alert, Button, ConfigProvider, Drawer, FloatButton, Layout, Result, Tooltip} from "antd";
|
||||
@ -249,7 +249,7 @@ class App extends Component {
|
||||
this.setLanguage(account);
|
||||
this.setTheme(Setting.getThemeData(account.organization), Conf.InitThemeAlgorithm);
|
||||
setTourLogo(account.organization.logo);
|
||||
setIsTourVisible(account.organization.enableTour);
|
||||
setOrgIsTourVisible(account.organization.enableTour);
|
||||
} else {
|
||||
if (res.data !== "Please login first") {
|
||||
Setting.showMessage("error", `${i18next.t("application:Failed to sign in")}: ${res.msg}`);
|
||||
|
@ -122,7 +122,7 @@ class PaymentResultPage extends React.Component {
|
||||
payment: payment,
|
||||
});
|
||||
if (payment.state === "Created") {
|
||||
if (["PayPal", "Stripe", "Alipay", "WeChat Pay"].includes(payment.type)) {
|
||||
if (["PayPal", "Stripe", "Alipay", "WeChat Pay", "Balance"].includes(payment.type)) {
|
||||
this.setState({
|
||||
timeout: setTimeout(async() => {
|
||||
await PaymentBackend.notifyPayment(this.state.owner, this.state.paymentName);
|
||||
|
@ -725,7 +725,7 @@ class ProviderEditPage extends React.Component {
|
||||
(this.state.provider.category === "Web3") ||
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Local File System") ||
|
||||
(this.state.provider.category === "SMS" && this.state.provider.type === "Custom HTTP SMS") ||
|
||||
(this.state.provider.category === "Notification" && (this.state.provider.type === "Google Chat" || this.state.provider.type === "Custom HTTP")) ? null : (
|
||||
(this.state.provider.category === "Notification" && (this.state.provider.type === "Google Chat" || this.state.provider.type === "Custom HTTP") || this.state.provider.type === "Balance") ? null : (
|
||||
<React.Fragment>
|
||||
{
|
||||
(this.state.provider.category === "Storage" && this.state.provider.type === "Google Cloud Storage") ||
|
||||
|
@ -247,6 +247,10 @@ export const OtherProviderInfo = {
|
||||
logo: `${StaticBaseUrl}/img/payment_paypal.png`,
|
||||
url: "",
|
||||
},
|
||||
"Balance": {
|
||||
logo: `${StaticBaseUrl}/img/payment_balance.svg`,
|
||||
url: "",
|
||||
},
|
||||
"Alipay": {
|
||||
logo: `${StaticBaseUrl}/img/payment_alipay.png`,
|
||||
url: "https://www.alipay.com/",
|
||||
@ -1067,6 +1071,7 @@ export function getProviderTypeOptions(category) {
|
||||
} else if (category === "Payment") {
|
||||
return ([
|
||||
{id: "Dummy", name: "Dummy"},
|
||||
{id: "Balance", name: "Balance"},
|
||||
{id: "Alipay", name: "Alipay"},
|
||||
{id: "WeChat Pay", name: "WeChat Pay"},
|
||||
{id: "PayPal", name: "PayPal"},
|
||||
|
@ -203,9 +203,14 @@ export function getNextUrl(pathName = window.location.pathname) {
|
||||
return TourUrlList[TourUrlList.indexOf(pathName.replace("/", "")) + 1] || "";
|
||||
}
|
||||
|
||||
let orgIsTourVisible = true;
|
||||
|
||||
export function setOrgIsTourVisible(visible) {
|
||||
orgIsTourVisible = visible;
|
||||
}
|
||||
|
||||
export function setIsTourVisible(visible) {
|
||||
localStorage.setItem("isTourVisible", visible);
|
||||
window.dispatchEvent(new Event("storageTourChanged"));
|
||||
}
|
||||
|
||||
export function setTourLogo(tourLogoSrc) {
|
||||
@ -215,7 +220,7 @@ export function setTourLogo(tourLogoSrc) {
|
||||
}
|
||||
|
||||
export function getTourVisible() {
|
||||
return localStorage.getItem("isTourVisible") !== "false";
|
||||
return localStorage.getItem("isTourVisible") !== "false" && orgIsTourVisible;
|
||||
}
|
||||
|
||||
export function getNextButtonChild(nextPathName) {
|
||||
|
Reference in New Issue
Block a user