You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
6.3 KiB
170 lines
6.3 KiB
package pay
|
|
|
|
import (
|
|
"context"
|
|
"yunyan/comm"
|
|
"yunyan/lego/sys/log"
|
|
"yunyan/pb"
|
|
"yunyan/sys/pay/appleiap"
|
|
"yunyan/sys/pay/googleiap"
|
|
"yunyan/sys/pay/paypal"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// @Summary 验证订单
|
|
// @Description 验证支付订单是否有效
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Security BearerAuth
|
|
// @Param user body pb.PayAskOrCancelReq true "发送绑定请求"
|
|
// @Success 200 {object} comm.HttpResult{data=pb.PayPayOrderAskResp} "成功返回"
|
|
// @Router /api/home/pay_verifyorder [post]
|
|
func (this *apiComp) VerifyOrder(session comm.IUserSession, req *pb.PayAskOrCancelReq) (resp *pb.PayPayOrderAskResp, errdata *pb.ErrorData) {
|
|
var (
|
|
model *pb.DBPayOrder
|
|
user *pb.DBUser
|
|
err error
|
|
)
|
|
if req.Orderid == "" {
|
|
if orders, _, err0 := this.module.model.getUserPayOrders(session.GetUserId(), 1, 50); err0 == nil {
|
|
for _, o := range orders {
|
|
if o.Status == pb.PayOrderStatus_PAY_ORDER_PENDING {
|
|
req.Orderid = o.OrderId
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 查询订单
|
|
if model, err = this.module.model.getPayOrder(req.Orderid); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_PayOrderNotFound,
|
|
Message: "查询订单失败:" + fmt.Sprintf("%v", err),
|
|
}
|
|
return
|
|
}
|
|
// 查询用户
|
|
if user, err = this.module.model.getUser(session.GetUserId()); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: "查询用户失败:" + fmt.Sprintf("%v", err),
|
|
}
|
|
return
|
|
}
|
|
this.module.Debug("VerifyOrder", log.Field{Key: "order", Value: model})
|
|
// Google/Apple 主动查询与校验:仅在订单未支付时进行
|
|
if model.Status == pb.PayOrderStatus_PAY_ORDER_PENDING {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
|
|
defer cancel()
|
|
|
|
// PayPal 主动执行 capture 扣款
|
|
if model.PaymentMethod == pb.PaymentMethod_PayPal {
|
|
if model.TransactionId == "" {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayOrderNotFound, Message: "缺少 PayPal 订单号,无法执行 capture"}
|
|
return
|
|
}
|
|
captureJSON, err := paypal.CaptureOrder(ctx, model.TransactionId)
|
|
if err != nil {
|
|
if this.module.analyze != nil {
|
|
this.module.analyze.Report(&comm.StatEvent{Type: comm.StatEventOrderFailed, Uid: model.Uid})
|
|
}
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayCreateOrderFail, Message: "PayPal capture 失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
// 简单判定:返回中包含 status=COMPLETED 视为支付成功
|
|
if !strings.Contains(captureJSON, "\"status\":\"COMPLETED\"") {
|
|
if this.module.analyze != nil {
|
|
this.module.analyze.Report(&comm.StatEvent{Type: comm.StatEventOrderFailed, Uid: model.Uid})
|
|
}
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayCreateOrderFail, Message: "PayPal capture 未完成"}
|
|
return
|
|
}
|
|
// 扣款成功,更新订单并发放资源
|
|
model.Status = pb.PayOrderStatus_PAY_ORDER_PAID
|
|
model.PayTime = time.Now().Unix()
|
|
if err = this.deliverResourceByOrder(user, model); err != nil {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_ResourceDeliveryError, Message: "发放资源失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
if err = this.module.model.updatePayOrder(model); err != nil {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayOrderStatusError, Message: "更新订单状态失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
}
|
|
|
|
// Apple IAP 主动校验
|
|
if model.PaymentMethod == pb.PaymentMethod_AppleIAP {
|
|
if req.AppleReceiptData == "" {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_ReqParameterError, Message: "缺少苹果收据数据或交易ID"}
|
|
return
|
|
}
|
|
var ok bool
|
|
if req.AppleUseTransactionId {
|
|
ok, err = appleiap.VerifyTransaction(ctx, req.AppleReceiptData)
|
|
} else {
|
|
ok, err = appleiap.VerifyReceipt(ctx, req.AppleReceiptData)
|
|
}
|
|
if err != nil || !ok {
|
|
if this.module.analyze != nil {
|
|
this.module.analyze.Report(&comm.StatEvent{Type: comm.StatEventOrderFailed, Uid: model.Uid})
|
|
}
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayNotifyDecryptFail, Message: "Apple IAP 校验失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
// 校验通过,更新订单并发放资源
|
|
model.Status = pb.PayOrderStatus_PAY_ORDER_PAID
|
|
model.PayTime = time.Now().Unix()
|
|
if err = this.deliverResourceByOrder(user, model); err != nil {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_ResourceDeliveryError, Message: "发放资源失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
if err = this.module.model.updatePayOrder(model); err != nil {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayOrderStatusError, Message: "更新订单状态失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
}
|
|
|
|
// Google IAP 主动校验
|
|
if model.PaymentMethod == pb.PaymentMethod_GoogleIAP {
|
|
if req.GooglePackageName == "" || req.GoogleProductId == "" || req.GooglePurchaseToken == "" {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_ReqParameterError, Message: "缺少谷歌校验所需参数"}
|
|
return
|
|
}
|
|
var ok bool
|
|
if req.GoogleIsSubscription {
|
|
ok, err = googleiap.VerifySubscriptionPurchase(ctx, req.GooglePackageName, req.GoogleProductId, req.GooglePurchaseToken)
|
|
} else {
|
|
ok, err = googleiap.VerifyProductPurchase(ctx, req.GooglePackageName, req.GoogleProductId, req.GooglePurchaseToken)
|
|
}
|
|
if err != nil || !ok {
|
|
if this.module.analyze != nil {
|
|
this.module.analyze.Report(&comm.StatEvent{Type: comm.StatEventOrderFailed, Uid: model.Uid})
|
|
}
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayNotifyDecryptFail, Message: "Google IAP 校验失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
// 校验通过,更新订单并发放资源
|
|
model.Status = pb.PayOrderStatus_PAY_ORDER_PAID
|
|
model.PayTime = time.Now().Unix()
|
|
if err = this.deliverResourceByOrder(user, model); err != nil {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_ResourceDeliveryError, Message: "发放资源失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
if err = this.module.model.updatePayOrder(model); err != nil {
|
|
errdata = &pb.ErrorData{Code: pb.ErrorCode_PayOrderStatusError, Message: "更新订单状态失败:" + fmt.Sprintf("%v", err)}
|
|
return
|
|
}
|
|
}
|
|
} else if model.Status == pb.PayOrderStatus_PAY_ORDER_PAID {
|
|
this.module.Debug("VerifyOrder 已经完成", log.Field{Key: "order", Value: model})
|
|
}
|
|
resp = &pb.PayPayOrderAskResp{
|
|
Order: model,
|
|
User: user,
|
|
}
|
|
return
|
|
}
|
|
|