mirror of
https://github.com/casdoor/casdoor.git
synced 2025-05-23 18:54:03 +08:00
feat: support payment cancel state (#2165)
This commit is contained in:
parent
67ac3d6d21
commit
d7b2bcf288
@ -186,20 +186,23 @@ func notifyPayment(request *http.Request, body []byte, owner string, paymentName
|
|||||||
|
|
||||||
notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
|
notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return payment, notifyResult, err
|
return payment, nil, err
|
||||||
}
|
}
|
||||||
|
if notifyResult.PaymentStatus != pp.PaymentStatePaid {
|
||||||
|
return payment, notifyResult, nil
|
||||||
|
}
|
||||||
|
// Only check paid payment
|
||||||
if notifyResult.ProductDisplayName != "" && notifyResult.ProductDisplayName != product.DisplayName {
|
if notifyResult.ProductDisplayName != "" && notifyResult.ProductDisplayName != product.DisplayName {
|
||||||
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", notifyResult.ProductDisplayName, product.DisplayName)
|
err = fmt.Errorf("the payment's product name: %s doesn't equal to the expected product name: %s", notifyResult.ProductDisplayName, product.DisplayName)
|
||||||
return payment, notifyResult, err
|
return payment, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if notifyResult.Price != product.Price {
|
if notifyResult.Price != product.Price {
|
||||||
err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", notifyResult.Price, product.Price)
|
err = fmt.Errorf("the payment's price: %f doesn't equal to the expected price: %f", notifyResult.Price, product.Price)
|
||||||
return payment, notifyResult, err
|
return payment, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return payment, notifyResult, err
|
return payment, notifyResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, error) {
|
func NotifyPayment(request *http.Request, body []byte, owner string, paymentName string, orderId string) (*Payment, error) {
|
||||||
@ -210,6 +213,7 @@ func NotifyPayment(request *http.Request, body []byte, owner string, paymentName
|
|||||||
payment.Message = err.Error()
|
payment.Message = err.Error()
|
||||||
} else {
|
} else {
|
||||||
payment.State = notifyResult.PaymentStatus
|
payment.State = notifyResult.PaymentStatus
|
||||||
|
payment.Message = notifyResult.NotifyMessage
|
||||||
}
|
}
|
||||||
_, err = UpdatePayment(payment.GetId(), payment)
|
_, err = UpdatePayment(payment.GetId(), payment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
28
pp/paypal.go
28
pp/paypal.go
@ -17,6 +17,7 @@ package pp
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -89,14 +90,24 @@ func (pp *PaypalPaymentProvider) Pay(providerName string, productName string, pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, authorityPublicKey string, orderId string) (*NotifyResult, error) {
|
||||||
|
notifyResult := &NotifyResult{}
|
||||||
captureRsp, err := pp.Client.OrderCapture(context.Background(), orderId, nil)
|
captureRsp, err := pp.Client.OrderCapture(context.Background(), orderId, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if captureRsp.Code != paypal.Success {
|
if captureRsp.Code != paypal.Success {
|
||||||
|
errDetail := captureRsp.ErrorResponse.Details[0]
|
||||||
|
switch errDetail.Issue {
|
||||||
// If order is already captured, just skip this type of error and check the order detail
|
// If order is already captured, just skip this type of error and check the order detail
|
||||||
if !(len(captureRsp.ErrorResponse.Details) == 1 && captureRsp.ErrorResponse.Details[0].Issue == "ORDER_ALREADY_CAPTURED") {
|
case "ORDER_ALREADY_CAPTURED":
|
||||||
return nil, errors.New(captureRsp.ErrorResponse.Message)
|
// skip
|
||||||
|
case "ORDER_NOT_APPROVED":
|
||||||
|
notifyResult.PaymentStatus = PaymentStateCanceled
|
||||||
|
notifyResult.NotifyMessage = errDetail.Description
|
||||||
|
return notifyResult, nil
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf(errDetail.Description)
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check the order detail
|
// Check the order detail
|
||||||
@ -105,7 +116,16 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if captureRsp.Code != paypal.Success {
|
if captureRsp.Code != paypal.Success {
|
||||||
return nil, errors.New(captureRsp.ErrorResponse.Message)
|
errDetail := captureRsp.ErrorResponse.Details[0]
|
||||||
|
switch errDetail.Issue {
|
||||||
|
case "ORDER_NOT_APPROVED":
|
||||||
|
notifyResult.PaymentStatus = PaymentStateCanceled
|
||||||
|
notifyResult.NotifyMessage = errDetail.Description
|
||||||
|
return notifyResult, nil
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf(errDetail.Description)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paymentName := detailRsp.Response.Id
|
paymentName := detailRsp.Response.Id
|
||||||
@ -126,7 +146,7 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth
|
|||||||
default:
|
default:
|
||||||
paymentStatus = PaymentStateError
|
paymentStatus = PaymentStateError
|
||||||
}
|
}
|
||||||
notifyResult := &NotifyResult{
|
notifyResult = &NotifyResult{
|
||||||
PaymentStatus: paymentStatus,
|
PaymentStatus: paymentStatus,
|
||||||
PaymentName: paymentName,
|
PaymentName: paymentName,
|
||||||
|
|
||||||
|
@ -21,16 +21,18 @@ import (
|
|||||||
type PaymentState string
|
type PaymentState string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PaymentStatePaid PaymentState = "Paid"
|
PaymentStatePaid PaymentState = "Paid"
|
||||||
PaymentStateCreated PaymentState = "Created"
|
PaymentStateCreated PaymentState = "Created"
|
||||||
PaymentStateError PaymentState = "Error"
|
PaymentStateCanceled PaymentState = "Canceled"
|
||||||
|
PaymentStateError PaymentState = "Error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NotifyResult struct {
|
type NotifyResult struct {
|
||||||
PaymentName string
|
PaymentName string
|
||||||
PaymentStatus PaymentState
|
PaymentStatus PaymentState
|
||||||
ProviderName string
|
NotifyMessage string
|
||||||
|
|
||||||
|
ProviderName string
|
||||||
ProductName string
|
ProductName string
|
||||||
ProductDisplayName string
|
ProductDisplayName string
|
||||||
Price float64
|
Price float64
|
||||||
|
@ -115,6 +115,26 @@ class PaymentResultPage extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (payment.state === "Canceled") {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
Setting.renderHelmet(payment)
|
||||||
|
}
|
||||||
|
<Result
|
||||||
|
status="warning"
|
||||||
|
title={`${i18next.t("payment:The payment has been canceled")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
|
||||||
|
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
|
||||||
|
extra={[
|
||||||
|
<Button type="primary" key="returnUrl" onClick={() => {
|
||||||
|
this.goToPaymentUrl(payment);
|
||||||
|
}}>
|
||||||
|
{i18next.t("payment:Return to Website")}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@ -124,7 +144,7 @@ class PaymentResultPage extends React.Component {
|
|||||||
<Result
|
<Result
|
||||||
status="error"
|
status="error"
|
||||||
title={`${i18next.t("payment:The payment has failed")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
|
title={`${i18next.t("payment:The payment has failed")}: ${payment.productDisplayName}, ${i18next.t("payment:the current state is")}: ${payment.state}`}
|
||||||
subTitle={i18next.t("payment:Please click the below button to return to the original website")}
|
subTitle={`${i18next.t("payment:Failed reason")}: ${payment.message}`}
|
||||||
extra={[
|
extra={[
|
||||||
<Button type="primary" key="returnUrl" onClick={() => {
|
<Button type="primary" key="returnUrl" onClick={() => {
|
||||||
this.goToPaymentUrl(payment);
|
this.goToPaymentUrl(payment);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user