From d7b2bcf2889b35ee5ab7b08befc8a19a5c271e2c Mon Sep 17 00:00:00 2001 From: haiwu <54203997+Chinoholo0807@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:24:13 +0800 Subject: [PATCH] feat: support payment cancel state (#2165) --- object/payment.go | 14 +++++++++----- pp/paypal.go | 28 ++++++++++++++++++++++++---- pp/provider.go | 10 ++++++---- web/src/PaymentResultPage.js | 22 +++++++++++++++++++++- 4 files changed, 60 insertions(+), 14 deletions(-) diff --git a/object/payment.go b/object/payment.go index caef8232..a37ecbfe 100644 --- a/object/payment.go +++ b/object/payment.go @@ -186,20 +186,23 @@ func notifyPayment(request *http.Request, body []byte, owner string, paymentName notifyResult, err := pProvider.Notify(request, body, cert.AuthorityPublicKey, orderId) 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 { 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 { 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) { @@ -210,6 +213,7 @@ func NotifyPayment(request *http.Request, body []byte, owner string, paymentName payment.Message = err.Error() } else { payment.State = notifyResult.PaymentStatus + payment.Message = notifyResult.NotifyMessage } _, err = UpdatePayment(payment.GetId(), payment) if err != nil { diff --git a/pp/paypal.go b/pp/paypal.go index 74d09268..67a46240 100644 --- a/pp/paypal.go +++ b/pp/paypal.go @@ -17,6 +17,7 @@ package pp import ( "context" "errors" + "fmt" "net/http" "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) { + notifyResult := &NotifyResult{} captureRsp, err := pp.Client.OrderCapture(context.Background(), orderId, nil) if err != nil { return nil, err } 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 !(len(captureRsp.ErrorResponse.Details) == 1 && captureRsp.ErrorResponse.Details[0].Issue == "ORDER_ALREADY_CAPTURED") { - return nil, errors.New(captureRsp.ErrorResponse.Message) + case "ORDER_ALREADY_CAPTURED": + // 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 @@ -105,7 +116,16 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth return nil, err } 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 @@ -126,7 +146,7 @@ func (pp *PaypalPaymentProvider) Notify(request *http.Request, body []byte, auth default: paymentStatus = PaymentStateError } - notifyResult := &NotifyResult{ + notifyResult = &NotifyResult{ PaymentStatus: paymentStatus, PaymentName: paymentName, diff --git a/pp/provider.go b/pp/provider.go index 0053f7e3..18d2e8ef 100644 --- a/pp/provider.go +++ b/pp/provider.go @@ -21,16 +21,18 @@ import ( type PaymentState string const ( - PaymentStatePaid PaymentState = "Paid" - PaymentStateCreated PaymentState = "Created" - PaymentStateError PaymentState = "Error" + PaymentStatePaid PaymentState = "Paid" + PaymentStateCreated PaymentState = "Created" + PaymentStateCanceled PaymentState = "Canceled" + PaymentStateError PaymentState = "Error" ) type NotifyResult struct { PaymentName string PaymentStatus PaymentState - ProviderName string + NotifyMessage string + ProviderName string ProductName string ProductDisplayName string Price float64 diff --git a/web/src/PaymentResultPage.js b/web/src/PaymentResultPage.js index 315c923d..2304f538 100644 --- a/web/src/PaymentResultPage.js +++ b/web/src/PaymentResultPage.js @@ -115,6 +115,26 @@ class PaymentResultPage extends React.Component { /> ); + } else if (payment.state === "Canceled") { + return ( +
+ { + Setting.renderHelmet(payment) + } + { + this.goToPaymentUrl(payment); + }}> + {i18next.t("payment:Return to Website")} + , + ]} + /> +
+ ); } else { return (
@@ -124,7 +144,7 @@ class PaymentResultPage extends React.Component { { this.goToPaymentUrl(payment);