mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 10:45:47 +08:00
Add NotifyPayment API.
This commit is contained in:
parent
bf5d4eea48
commit
a4fc04474e
@ -16,10 +16,12 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/astaxie/beego/utils/pagination"
|
"github.com/astaxie/beego/utils/pagination"
|
||||||
"github.com/casdoor/casdoor/object"
|
"github.com/casdoor/casdoor/object"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/go-pay/gopay/alipay"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetPayments
|
// GetPayments
|
||||||
@ -122,12 +124,18 @@ func (c *ApiController) DeletePayment() {
|
|||||||
// @Success 200 {object} controllers.Response The Response object
|
// @Success 200 {object} controllers.Response The Response object
|
||||||
// @router /notify-payment [post]
|
// @router /notify-payment [post]
|
||||||
func (c *ApiController) NotifyPayment() {
|
func (c *ApiController) NotifyPayment() {
|
||||||
var payment object.Payment
|
bm, err := alipay.ParseNotifyToBodyMap(c.Ctx.Request)
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &payment)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = wrapActionResponse(object.NotifyPayment("111", "222"))
|
ok := object.NotifyPayment(bm)
|
||||||
c.ServeJSON()
|
if ok {
|
||||||
|
_, err = c.Ctx.ResponseWriter.Write([]byte("success"))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(fmt.Errorf("NotifyPayment() failed: %v", ok))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
|
"github.com/go-pay/gopay"
|
||||||
|
"github.com/go-pay/gopay/alipay"
|
||||||
"xorm.io/core"
|
"xorm.io/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,13 +29,14 @@ type Payment struct {
|
|||||||
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
CreatedTime string `xorm:"varchar(100)" json:"createdTime"`
|
||||||
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
DisplayName string `xorm:"varchar(100)" json:"displayName"`
|
||||||
|
|
||||||
Provider string `xorm:"varchar(100)" json:"provider"`
|
Provider string `xorm:"varchar(100)" json:"provider"`
|
||||||
Type string `xorm:"varchar(100)" json:"type"`
|
Type string `xorm:"varchar(100)" json:"type"`
|
||||||
Organization string `xorm:"varchar(100)" json:"organization"`
|
Organization string `xorm:"varchar(100)" json:"organization"`
|
||||||
User string `xorm:"varchar(100)" json:"user"`
|
User string `xorm:"varchar(100)" json:"user"`
|
||||||
Good string `xorm:"varchar(100)" json:"good"`
|
ProductId string `xorm:"varchar(100)" json:"productId"`
|
||||||
Amount string `xorm:"varchar(100)" json:"amount"`
|
ProductName string `xorm:"varchar(100)" json:"productName"`
|
||||||
Currency string `xorm:"varchar(100)" json:"currency"`
|
Price float64 `json:"price"`
|
||||||
|
Currency string `xorm:"varchar(100)" json:"currency"`
|
||||||
|
|
||||||
State string `xorm:"varchar(100)" json:"state"`
|
State string `xorm:"varchar(100)" json:"state"`
|
||||||
}
|
}
|
||||||
@ -124,16 +127,58 @@ func DeletePayment(payment *Payment) bool {
|
|||||||
return affected != 0
|
return affected != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyPayment(id string, state string) bool {
|
func NotifyPayment(bm gopay.BodyMap) bool {
|
||||||
owner, name := util.GetOwnerAndNameFromId(id)
|
owner := "admin"
|
||||||
payment := getPayment(owner, name)
|
productName := bm.Get("subject")
|
||||||
if payment == nil {
|
paymentId := bm.Get("out_trade_no")
|
||||||
return false
|
priceString := bm.Get("total_amount")
|
||||||
|
price := util.ParseFloat(priceString)
|
||||||
|
productId := bm.Get("productId")
|
||||||
|
providerId := bm.Get("providerId")
|
||||||
|
|
||||||
|
product := getProduct(owner, productId)
|
||||||
|
if product == nil {
|
||||||
|
panic(fmt.Errorf("the product: %s does not exist", productId))
|
||||||
}
|
}
|
||||||
|
|
||||||
payment.State = state
|
if productName != product.DisplayName {
|
||||||
|
panic(fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", productName, product.DisplayName))
|
||||||
|
}
|
||||||
|
|
||||||
affected, err := adapter.Engine.ID(core.PK{owner, name}).AllCols().Update(payment)
|
if price != product.Price {
|
||||||
|
panic(fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", price, product.Price))
|
||||||
|
}
|
||||||
|
|
||||||
|
payment := getPayment(owner, paymentId)
|
||||||
|
if payment == nil {
|
||||||
|
panic(fmt.Errorf("the payment: %s does not exist", paymentId))
|
||||||
|
}
|
||||||
|
|
||||||
|
provider, err := product.getProvider(providerId)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cert := getCert(owner, provider.Cert)
|
||||||
|
if cert == nil {
|
||||||
|
panic(fmt.Errorf("the cert: %s does not exist", provider.Cert))
|
||||||
|
}
|
||||||
|
|
||||||
|
ok, err := alipay.VerifySignWithCert(cert.AuthorityPublicKey, bm)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
payment.State = "Paid"
|
||||||
|
} else {
|
||||||
|
if cert == nil {
|
||||||
|
panic(fmt.Errorf("VerifySignWithCert() failed: %v", ok))
|
||||||
|
}
|
||||||
|
//payment.State = "Failed"
|
||||||
|
}
|
||||||
|
|
||||||
|
affected, err := adapter.Engine.ID(core.PK{owner, paymentId}).AllCols().Update(payment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -139,19 +139,28 @@ func (product *Product) isValidProvider(provider *Provider) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (product *Product) getProvider(providerId string) (*Provider, error) {
|
||||||
|
provider := getProvider(product.Owner, providerId)
|
||||||
|
if provider == nil {
|
||||||
|
return nil, fmt.Errorf("the payment provider: %s does not exist", providerId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !product.isValidProvider(provider) {
|
||||||
|
return nil, fmt.Errorf("the payment provider: %s is not valid for the product: %s", providerId, product.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider, nil
|
||||||
|
}
|
||||||
|
|
||||||
func BuyProduct(id string, providerId string, host string) (string, error) {
|
func BuyProduct(id string, providerId string, host string) (string, error) {
|
||||||
product := GetProduct(id)
|
product := GetProduct(id)
|
||||||
if product == nil {
|
if product == nil {
|
||||||
return "", fmt.Errorf("the product: %s does not exist", id)
|
return "", fmt.Errorf("the product: %s does not exist", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := getProvider(product.Owner, providerId)
|
provider, err := product.getProvider(providerId)
|
||||||
if provider == nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("the payment provider: %s does not exist", providerId)
|
return "", err
|
||||||
}
|
|
||||||
|
|
||||||
if !product.isValidProvider(provider) {
|
|
||||||
return "", fmt.Errorf("the payment provider: %s is not valid for the product: %s", providerId, id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cert := getCert(product.Owner, provider.Cert)
|
cert := getCert(product.Owner, provider.Cert)
|
||||||
@ -170,6 +179,6 @@ func BuyProduct(id string, providerId string, host string) (string, error) {
|
|||||||
returnUrl := fmt.Sprintf("%s/payments/%s", originFrontend, paymentId)
|
returnUrl := fmt.Sprintf("%s/payments/%s", originFrontend, paymentId)
|
||||||
notifyUrl := fmt.Sprintf("%s/api/notify-payment", originBackend)
|
notifyUrl := fmt.Sprintf("%s/api/notify-payment", originBackend)
|
||||||
|
|
||||||
payUrl, err := pProvider.Pay(product.DisplayName, paymentId, product.Price, returnUrl, notifyUrl)
|
payUrl, err := pProvider.Pay(product.DisplayName, product.Name, provider.Name, paymentId, product.Price, returnUrl, notifyUrl)
|
||||||
return payUrl, err
|
return payUrl, err
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func TestProvider(t *testing.T) {
|
|||||||
paymentId := util.GenerateTimeId()
|
paymentId := util.GenerateTimeId()
|
||||||
returnUrl := ""
|
returnUrl := ""
|
||||||
notifyUrl := ""
|
notifyUrl := ""
|
||||||
payUrl, err := pProvider.Pay(product.DisplayName, paymentId, product.Price, returnUrl, notifyUrl)
|
payUrl, err := pProvider.Pay(product.DisplayName, product.Name, provider.Name, paymentId, product.Price, returnUrl, notifyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func NewAlipayPaymentProvider(appId string, appPublicKey string, appPrivateKey s
|
|||||||
return pp
|
return pp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pp *AlipayPaymentProvider) Pay(productName string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error) {
|
func (pp *AlipayPaymentProvider) Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error) {
|
||||||
pp.Client.DebugSwitch = gopay.DebugOn
|
pp.Client.DebugSwitch = gopay.DebugOn
|
||||||
|
|
||||||
priceString := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", price), "0"), ".")
|
priceString := strings.TrimRight(strings.TrimRight(fmt.Sprintf("%.2f", price), "0"), ".")
|
||||||
@ -53,10 +53,12 @@ func (pp *AlipayPaymentProvider) Pay(productName string, paymentId string, price
|
|||||||
bm.Set("subject", productName)
|
bm.Set("subject", productName)
|
||||||
bm.Set("out_trade_no", paymentId)
|
bm.Set("out_trade_no", paymentId)
|
||||||
bm.Set("total_amount", priceString)
|
bm.Set("total_amount", priceString)
|
||||||
|
|
||||||
bm.Set("return_url", returnUrl)
|
bm.Set("return_url", returnUrl)
|
||||||
bm.Set("notify_url", notifyUrl)
|
bm.Set("notify_url", notifyUrl)
|
||||||
|
|
||||||
|
bm.Set("productId", productId)
|
||||||
|
bm.Set("providerId", productId)
|
||||||
|
|
||||||
payUrl, err := pp.Client.TradePagePay(context.Background(), bm)
|
payUrl, err := pp.Client.TradePagePay(context.Background(), bm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
package pp
|
package pp
|
||||||
|
|
||||||
type PaymentProvider interface {
|
type PaymentProvider interface {
|
||||||
Pay(productName string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error)
|
Pay(productName string, productId string, providerId string, paymentId string, price float64, returnUrl string, notifyUrl string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPaymentProvider(typ string, appId string, appPublicKey string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) PaymentProvider {
|
func GetPaymentProvider(typ string, appId string, appPublicKey string, appPrivateKey string, authorityPublicKey string, authorityRootPublicKey string) PaymentProvider {
|
||||||
|
@ -42,6 +42,15 @@ func ParseInt(s string) int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseFloat(s string) float64 {
|
||||||
|
f, err := strconv.ParseFloat(s, 64)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
func ParseBool(s string) bool {
|
func ParseBool(s string) bool {
|
||||||
i := ParseInt(s)
|
i := ParseInt(s)
|
||||||
return i != 0
|
return i != 0
|
||||||
|
@ -112,7 +112,7 @@ class PaymentEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("provider:Type"), i18next.t("provider:Type - Tooltip"))} :
|
{Setting.getLabel(i18next.t("payment:Type"), i18next.t("payment:Type - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.payment.type} onChange={e => {
|
<Input value={this.state.payment.type} onChange={e => {
|
||||||
@ -122,20 +122,20 @@ class PaymentEditPage extends React.Component {
|
|||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("payment:Good"), i18next.t("payment:Good - Tooltip"))} :
|
{Setting.getLabel(i18next.t("payment:Product"), i18next.t("payment:Product - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.payment.good} onChange={e => {
|
<Input value={this.state.payment.productName} onChange={e => {
|
||||||
// this.updatePaymentField('good', e.target.value);
|
// this.updatePaymentField('productName', e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row style={{marginTop: '20px'}} >
|
<Row style={{marginTop: '20px'}} >
|
||||||
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
<Col style={{marginTop: '5px'}} span={(Setting.isMobile()) ? 22 : 2}>
|
||||||
{Setting.getLabel(i18next.t("payment:Amount"), i18next.t("payment:Amount - Tooltip"))} :
|
{Setting.getLabel(i18next.t("payment:Price"), i18next.t("payment:Price - Tooltip"))} :
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={22} >
|
<Col span={22} >
|
||||||
<Input value={this.state.payment.amount} onChange={e => {
|
<Input value={this.state.payment.price} onChange={e => {
|
||||||
// this.updatePaymentField('amount', e.target.value);
|
// this.updatePaymentField('amount', e.target.value);
|
||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -34,8 +34,9 @@ class PaymentListPage extends BaseListPage {
|
|||||||
type: "PayPal",
|
type: "PayPal",
|
||||||
organization: "built-in",
|
organization: "built-in",
|
||||||
user: "admin",
|
user: "admin",
|
||||||
good: "A notebook computer",
|
productId: "computer-1",
|
||||||
amount: "300",
|
productName: "A notebook computer",
|
||||||
|
price: 300.00,
|
||||||
currency: "USD",
|
currency: "USD",
|
||||||
state: "Paid",
|
state: "Paid",
|
||||||
}
|
}
|
||||||
@ -151,7 +152,7 @@ class PaymentListPage extends BaseListPage {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("provider:Type"),
|
title: i18next.t("payment:Type"),
|
||||||
dataIndex: 'type',
|
dataIndex: 'type',
|
||||||
key: 'type',
|
key: 'type',
|
||||||
width: '110px',
|
width: '110px',
|
||||||
@ -165,20 +166,20 @@ class PaymentListPage extends BaseListPage {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("payment:Good"),
|
title: i18next.t("payment:Product"),
|
||||||
dataIndex: 'good',
|
dataIndex: 'productName',
|
||||||
key: 'good',
|
key: 'productName',
|
||||||
width: '160px',
|
width: '160px',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
...this.getColumnSearchProps('good'),
|
...this.getColumnSearchProps('productName'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("payment:Amount"),
|
title: i18next.t("payment:Price"),
|
||||||
dataIndex: 'amount',
|
dataIndex: 'price',
|
||||||
key: 'amount',
|
key: 'price',
|
||||||
width: '120px',
|
width: '120px',
|
||||||
sorter: true,
|
sorter: true,
|
||||||
...this.getColumnSearchProps('amount'),
|
...this.getColumnSearchProps('price'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18next.t("payment:Currency"),
|
title: i18next.t("payment:Currency"),
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {Button, Descriptions} from "antd";
|
import {Button, Descriptions, Spin} from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import * as ProductBackend from "./backend/ProductBackend";
|
import * as ProductBackend from "./backend/ProductBackend";
|
||||||
import * as ProviderBackend from "./backend/ProviderBackend";
|
import * as ProviderBackend from "./backend/ProviderBackend";
|
||||||
@ -28,6 +28,7 @@ class ProductBuyPage extends React.Component {
|
|||||||
productName: props.match?.params.productName,
|
productName: props.match?.params.productName,
|
||||||
product: null,
|
product: null,
|
||||||
providers: [],
|
providers: [],
|
||||||
|
isPlacingOrder: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,16 +110,21 @@ class ProductBuyPage extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
buyProduct(product, provider) {
|
buyProduct(product, provider) {
|
||||||
|
this.setState({
|
||||||
|
isPlacingOrder: true,
|
||||||
|
});
|
||||||
|
|
||||||
ProductBackend.buyProduct(this.state.product.owner, this.state.productName, provider.name)
|
ProductBackend.buyProduct(this.state.product.owner, this.state.productName, provider.name)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.msg === "") {
|
if (res.msg === "") {
|
||||||
const payUrl = res.data;
|
const payUrl = res.data;
|
||||||
Setting.goToLink(payUrl);
|
Setting.goToLink(payUrl);
|
||||||
this.setState({
|
|
||||||
productName: this.state.product.name,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
Setting.showMessage("error", res.msg);
|
Setting.showMessage("error", res.msg);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
isPlacingOrder: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
@ -182,31 +188,33 @@ class ProductBuyPage extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Descriptions title={i18next.t("product:Buy Product")} bordered>
|
<Spin spinning={this.state.isPlacingOrder} size="large" tip={i18next.t("product:Placing order...")} style={{paddingTop: "10%"}} >
|
||||||
<Descriptions.Item label={i18next.t("general:Name")} span={3}>
|
<Descriptions title={i18next.t("product:Buy Product")} bordered>
|
||||||
|
<Descriptions.Item label={i18next.t("general:Name")} span={3}>
|
||||||
<span style={{fontSize: 28}}>
|
<span style={{fontSize: 28}}>
|
||||||
{product?.displayName}
|
{product?.displayName}
|
||||||
</span>
|
</span>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Detail")}><span style={{fontSize: 16}}>{product?.detail}</span></Descriptions.Item>
|
<Descriptions.Item label={i18next.t("product:Detail")}><span style={{fontSize: 16}}>{product?.detail}</span></Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Tag")}><span style={{fontSize: 16}}>{product?.tag}</span></Descriptions.Item>
|
<Descriptions.Item label={i18next.t("product:Tag")}><span style={{fontSize: 16}}>{product?.tag}</span></Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:SKU")}><span style={{fontSize: 16}}>{product?.name}</span></Descriptions.Item>
|
<Descriptions.Item label={i18next.t("product:SKU")}><span style={{fontSize: 16}}>{product?.name}</span></Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Image")} span={3}>
|
<Descriptions.Item label={i18next.t("product:Image")} span={3}>
|
||||||
<img src={product?.image} alt={product?.image} height={90} style={{marginBottom: '20px'}}/>
|
<img src={product?.image} alt={product?.image} height={90} style={{marginBottom: '20px'}}/>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Price")}>
|
<Descriptions.Item label={i18next.t("product:Price")}>
|
||||||
<span style={{fontSize: 28, color: "red", fontWeight: "bold"}}>
|
<span style={{fontSize: 28, color: "red", fontWeight: "bold"}}>
|
||||||
{`${this.getCurrencySymbol(product)}${product?.price} (${this.getCurrencyText(product)})`}
|
{`${this.getCurrencySymbol(product)}${product?.price} (${this.getCurrencyText(product)})`}
|
||||||
</span>
|
</span>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Quantity")}><span style={{fontSize: 16}}>{product?.quantity}</span></Descriptions.Item>
|
<Descriptions.Item label={i18next.t("product:Quantity")}><span style={{fontSize: 16}}>{product?.quantity}</span></Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Sold")}><span style={{fontSize: 16}}>{product?.sold}</span></Descriptions.Item>
|
<Descriptions.Item label={i18next.t("product:Sold")}><span style={{fontSize: 16}}>{product?.sold}</span></Descriptions.Item>
|
||||||
<Descriptions.Item label={i18next.t("product:Pay")} span={3}>
|
<Descriptions.Item label={i18next.t("product:Pay")} span={3}>
|
||||||
{
|
{
|
||||||
this.renderPay(product)
|
this.renderPay(product)
|
||||||
}
|
}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
</Descriptions>
|
</Descriptions>
|
||||||
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "Unique string-style identifier"
|
"Website URL - Tooltip": "Unique string-style identifier"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "Amount",
|
|
||||||
"Amount - Tooltip": "Amount - Tooltip",
|
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
"Currency - Tooltip": "Currency - Tooltip",
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
"Edit Payment": "Edit Payment",
|
"Edit Payment": "Edit Payment",
|
||||||
"Good": "Good",
|
"New Payment": "New Payment",
|
||||||
"Good - Tooltip": "Good - Tooltip",
|
"Price": "Price",
|
||||||
"New Payment": "New Payment"
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "Aktionen",
|
"Actions": "Aktionen",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
"Buy Product": "Buy Product",
|
"Buy Product": "Buy Product",
|
||||||
"CNY": "CNY",
|
"CNY": "CNY",
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "Payment providers",
|
"Payment providers": "Payment providers",
|
||||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
"Price": "Price",
|
"Price": "Price",
|
||||||
"Price - Tooltip": "Price - Tooltip",
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
"Quantity": "Quantity",
|
"Quantity": "Quantity",
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "Website URL - Tooltip"
|
"Website URL - Tooltip": "Website URL - Tooltip"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "Amount",
|
|
||||||
"Amount - Tooltip": "Amount - Tooltip",
|
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
"Currency - Tooltip": "Currency - Tooltip",
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
"Edit Payment": "Edit Payment",
|
"Edit Payment": "Edit Payment",
|
||||||
"Good": "Good",
|
"New Payment": "New Payment",
|
||||||
"Good - Tooltip": "Good - Tooltip",
|
"Price": "Price",
|
||||||
"New Payment": "New Payment"
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
"Buy Product": "Buy Product",
|
"Buy Product": "Buy Product",
|
||||||
"CNY": "CNY",
|
"CNY": "CNY",
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "Payment providers",
|
"Payment providers": "Payment providers",
|
||||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
"Price": "Price",
|
"Price": "Price",
|
||||||
"Price - Tooltip": "Price - Tooltip",
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
"Quantity": "Quantity",
|
"Quantity": "Quantity",
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "Unique string-style identifier"
|
"Website URL - Tooltip": "Unique string-style identifier"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "Amount",
|
|
||||||
"Amount - Tooltip": "Amount - Tooltip",
|
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
"Currency - Tooltip": "Currency - Tooltip",
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
"Edit Payment": "Edit Payment",
|
"Edit Payment": "Edit Payment",
|
||||||
"Good": "Good",
|
"New Payment": "New Payment",
|
||||||
"Good - Tooltip": "Good - Tooltip",
|
"Price": "Price",
|
||||||
"New Payment": "New Payment"
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
"Buy Product": "Buy Product",
|
"Buy Product": "Buy Product",
|
||||||
"CNY": "CNY",
|
"CNY": "CNY",
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "Payment providers",
|
"Payment providers": "Payment providers",
|
||||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
"Price": "Price",
|
"Price": "Price",
|
||||||
"Price - Tooltip": "Price - Tooltip",
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
"Quantity": "Quantity",
|
"Quantity": "Quantity",
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "Unique string-style identifier"
|
"Website URL - Tooltip": "Unique string-style identifier"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "Amount",
|
|
||||||
"Amount - Tooltip": "Amount - Tooltip",
|
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
"Currency - Tooltip": "Currency - Tooltip",
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
"Edit Payment": "Edit Payment",
|
"Edit Payment": "Edit Payment",
|
||||||
"Good": "Good",
|
"New Payment": "New Payment",
|
||||||
"Good - Tooltip": "Good - Tooltip",
|
"Price": "Price",
|
||||||
"New Payment": "New Payment"
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "アクション",
|
"Actions": "アクション",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
"Buy Product": "Buy Product",
|
"Buy Product": "Buy Product",
|
||||||
"CNY": "CNY",
|
"CNY": "CNY",
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "Payment providers",
|
"Payment providers": "Payment providers",
|
||||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
"Price": "Price",
|
"Price": "Price",
|
||||||
"Price - Tooltip": "Price - Tooltip",
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
"Quantity": "Quantity",
|
"Quantity": "Quantity",
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "Unique string-style identifier"
|
"Website URL - Tooltip": "Unique string-style identifier"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "Amount",
|
|
||||||
"Amount - Tooltip": "Amount - Tooltip",
|
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
"Currency - Tooltip": "Currency - Tooltip",
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
"Edit Payment": "Edit Payment",
|
"Edit Payment": "Edit Payment",
|
||||||
"Good": "Good",
|
"New Payment": "New Payment",
|
||||||
"Good - Tooltip": "Good - Tooltip",
|
"Price": "Price",
|
||||||
"New Payment": "New Payment"
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "Actions",
|
"Actions": "Actions",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
"Buy Product": "Buy Product",
|
"Buy Product": "Buy Product",
|
||||||
"CNY": "CNY",
|
"CNY": "CNY",
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "Payment providers",
|
"Payment providers": "Payment providers",
|
||||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
"Price": "Price",
|
"Price": "Price",
|
||||||
"Price - Tooltip": "Price - Tooltip",
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
"Quantity": "Quantity",
|
"Quantity": "Quantity",
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "Unique string-style identifier"
|
"Website URL - Tooltip": "Unique string-style identifier"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "Amount",
|
|
||||||
"Amount - Tooltip": "Amount - Tooltip",
|
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
"Currency - Tooltip": "Currency - Tooltip",
|
"Currency - Tooltip": "Currency - Tooltip",
|
||||||
"Edit Payment": "Edit Payment",
|
"Edit Payment": "Edit Payment",
|
||||||
"Good": "Good",
|
"New Payment": "New Payment",
|
||||||
"Good - Tooltip": "Good - Tooltip",
|
"Price": "Price",
|
||||||
"New Payment": "New Payment"
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
|
"Product": "Product",
|
||||||
|
"Product - Tooltip": "Product - Tooltip",
|
||||||
|
"Type": "Type",
|
||||||
|
"Type - Tooltip": "Type - Tooltip"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "Действия",
|
"Actions": "Действия",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "Alipay",
|
"Alipay": "Alipay",
|
||||||
|
"Buy": "Buy",
|
||||||
"Buy Product": "Buy Product",
|
"Buy Product": "Buy Product",
|
||||||
"CNY": "CNY",
|
"CNY": "CNY",
|
||||||
"Currency": "Currency",
|
"Currency": "Currency",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "Payment providers",
|
"Payment providers": "Payment providers",
|
||||||
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
"Payment providers - Tooltip": "Payment providers - Tooltip",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "Placing order...",
|
||||||
"Price": "Price",
|
"Price": "Price",
|
||||||
"Price - Tooltip": "Price - Tooltip",
|
"Price - Tooltip": "Price - Tooltip",
|
||||||
"Quantity": "Quantity",
|
"Quantity": "Quantity",
|
||||||
|
@ -252,14 +252,16 @@
|
|||||||
"Website URL - Tooltip": "网页地址"
|
"Website URL - Tooltip": "网页地址"
|
||||||
},
|
},
|
||||||
"payment": {
|
"payment": {
|
||||||
"Amount": "金额",
|
|
||||||
"Amount - Tooltip": "付款的金额",
|
|
||||||
"Currency": "币种",
|
"Currency": "币种",
|
||||||
"Currency - Tooltip": "如USD(美元),CNY(人民币)等",
|
"Currency - Tooltip": "如USD(美元),CNY(人民币)等",
|
||||||
"Edit Payment": "编辑付款",
|
"Edit Payment": "编辑付款",
|
||||||
"Good": "商品",
|
"New Payment": "添加付款",
|
||||||
"Good - Tooltip": "购买的商品名称",
|
"Price": "价格",
|
||||||
"New Payment": "添加付款"
|
"Price - Tooltip": "商品价格",
|
||||||
|
"Product": "商品",
|
||||||
|
"Product - Tooltip": "商品名称",
|
||||||
|
"Type": "支付方式",
|
||||||
|
"Type - Tooltip": "商品购买时的支付方式"
|
||||||
},
|
},
|
||||||
"permission": {
|
"permission": {
|
||||||
"Actions": "动作",
|
"Actions": "动作",
|
||||||
@ -274,6 +276,7 @@
|
|||||||
},
|
},
|
||||||
"product": {
|
"product": {
|
||||||
"Alipay": "支付宝",
|
"Alipay": "支付宝",
|
||||||
|
"Buy": "购买",
|
||||||
"Buy Product": "购买商品",
|
"Buy Product": "购买商品",
|
||||||
"CNY": "人民币",
|
"CNY": "人民币",
|
||||||
"Currency": "币种",
|
"Currency": "币种",
|
||||||
@ -288,6 +291,7 @@
|
|||||||
"Payment providers": "支付提供商",
|
"Payment providers": "支付提供商",
|
||||||
"Payment providers - Tooltip": "支付提供商 - 工具提示",
|
"Payment providers - Tooltip": "支付提供商 - 工具提示",
|
||||||
"Paypal": "Paypal",
|
"Paypal": "Paypal",
|
||||||
|
"Placing order...": "正在下单...",
|
||||||
"Price": "价格",
|
"Price": "价格",
|
||||||
"Price - Tooltip": "价格 - 工具提示",
|
"Price - Tooltip": "价格 - 工具提示",
|
||||||
"Quantity": "库存",
|
"Quantity": "库存",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user