fonchain-fiee/pkg/service/bundle/pay.go

369 lines
11 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package bundle
import (
"context"
"encoding/json"
"errors"
"fmt"
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/order"
"fonchain-fiee/api/payment"
"fonchain-fiee/pkg/config"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/common"
bundleModel "fonchain-fiee/pkg/service/bundle/model"
"io"
"math"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
func CreateStripeCheckoutSession(c *gin.Context) {
var req order.CreateStripeCheckoutSessionRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
// 获取 用户信息
userInfo := login.GetUserInfoFromC(c)
// 检查 订单信息
detail, detailErr := service.BundleProvider.OrderRecordsDetail(context.Background(), &bundle.OrderRecordsDetailRequest{
OrderNo: req.OutTradeNo,
})
if detailErr != nil {
service.Error(c, detailErr)
return
}
fmt.Println("detail.OrderRecord.CustomerID :", detail.OrderRecord.CustomerID)
// 判断 是否是 本人操作
if strconv.FormatUint(userInfo.ID, 10) != detail.OrderRecord.CustomerID {
service.Error(c, errors.New(common.NotMatchOrderInfo))
return
}
fmt.Println("detail.OrderRecord.TotalAmount :", detail.OrderRecord.TotalAmount)
fmt.Println("req.ProductAllPrice :", req.ProductAllPrice)
fmt.Println("detail.OrderRecord.TotalAmount*100 :", detail.OrderRecord.TotalAmount*100)
//金额校验
orderAmountInCents := int64(math.Round(float64(detail.OrderRecord.TotalAmount * 100)))
reqAmountInCents := int64(math.Round(float64(req.ProductAllPrice)))
if orderAmountInCents != reqAmountInCents {
fmt.Println("111111111111111111111111111111111111")
service.Error(c, errors.New(common.InvalidOrderAmount))
return
}
fmt.Println("detail.OrderRecord.Status :", detail.OrderRecord.Status)
fmt.Println("detail.OrderRecord.CheckoutSessionId :", detail.OrderRecord.CheckoutSessionId)
fmt.Println("detail.OrderRecord.PayTime :", detail.OrderRecord.PayTime)
// 如果 当前订单 是 已签未支付 且 存在 checkoutSessionId 需要 查询 支付结果
if detail.OrderRecord.Status == bundleModel.OrderSigned && detail.OrderRecord.CheckoutSessionId != "" && detail.OrderRecord.PayTime == "" {
// 查询支付结果
stripeInfosRes, stripeInfosErr := service.OrderProvider.QueryStripeInfoByCheckSessionIds(context.Background(), &order.QueryStripeInfoRequest{
CheckoutSessionIds: []string{detail.OrderRecord.CheckoutSessionId},
})
if stripeInfosErr != nil {
service.Error(c, errors.New(common.ErrorQueryStripeInfo))
return
}
if stripeInfosRes != nil && len(stripeInfosRes.StripeInfos) > 0 {
for _, stripeInfo := range stripeInfosRes.StripeInfos {
if stripeInfo.OutTradeNo == detail.OrderRecord.OrderNo && stripeInfo.PaymentIntentStatus == "paid" {
_, updateOrderRecordErr := service.BundleProvider.UpdateOrderRecord(context.Background(), &bundle.OrderRecord{
Uuid: detail.OrderRecord.Uuid,
Status: bundleModel.OrderPaid,
PayTime: common.GetBeijingTime(),
})
fmt.Println("detail.OrderRecord.Uuid :", detail.OrderRecord.Uuid)
if updateOrderRecordErr != nil {
service.Error(c, detailErr)
return
}
service.Success(c, &service.Response{
Msg: common.HadPay,
Code: 0,
})
return
}
}
}
}
//调用微服务获取支付地址
result, err := service.OrderProvider.CreateStripeCheckoutSession(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
fmt.Println("result.CheckoutSessionId :", result.CheckoutSessionId)
fmt.Println("result.CheckoutSessionUrl :", result.CheckoutSessionUrl)
//更新订单状态
_, updateOrderRecordErr := service.BundleProvider.UpdateOrderRecord(context.Background(), &bundle.OrderRecord{
Uuid: detail.OrderRecord.Uuid,
CheckoutSessionId: result.CheckoutSessionId,
CheckoutSessionUrl: result.CheckoutSessionUrl,
})
if updateOrderRecordErr != nil {
service.Error(c, updateOrderRecordErr)
return
}
service.Success(c, result)
}
func CreateAntomPay(c *gin.Context) {
var req order.CreateStripeCheckoutSessionRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
// 获取 用户信息
userInfo := login.GetUserInfoFromC(c)
// 检查 订单信息
detail, detailErr := service.BundleProvider.OrderRecordsDetail(context.Background(), &bundle.OrderRecordsDetailRequest{
OrderNo: req.OutTradeNo,
})
if detailErr != nil {
service.Error(c, detailErr)
return
}
fmt.Println("detail.OrderRecord.CustomerID :", detail.OrderRecord.CustomerID)
// 判断 是否是 本人操作
if strconv.FormatUint(userInfo.ID, 10) != detail.OrderRecord.CustomerID {
service.Error(c, errors.New(common.NotMatchOrderInfo))
return
}
fmt.Println("detail.OrderRecord.TotalAmount :", detail.OrderRecord.TotalAmount)
fmt.Println("req.ProductAllPrice :", req.ProductAllPrice)
fmt.Println("detail.OrderRecord.TotalAmount*100 :", detail.OrderRecord.TotalAmount*100)
//金额校验
orderAmountInCents := int64(math.Round(float64(detail.OrderRecord.TotalAmount * 100)))
reqAmountInCents := int64(math.Round(float64(req.ProductAllPrice)))
if orderAmountInCents != reqAmountInCents {
fmt.Println("111111111111111111111111111111111111")
service.Error(c, errors.New(common.InvalidOrderAmount))
return
}
fmt.Println("detail.OrderRecord.Status :", detail.OrderRecord.Status)
fmt.Println("detail.OrderRecord.CheckoutSessionId :", detail.OrderRecord.CheckoutSessionId)
fmt.Println("detail.OrderRecord.PayTime :", detail.OrderRecord.PayTime)
// 如果 当前订单 是 已签未支付 且 存在 checkoutSessionId 需要 查询 支付结果
if detail.OrderRecord.Status == bundleModel.OrderSigned && detail.OrderRecord.CheckoutSessionId != "" && detail.OrderRecord.PayTime == "" {
// 查询支付结果
stripeInfosRes, stripeInfosErr := service.PaymentProvider.QueryAntomPayByCheckoutSessionId(context.Background(), &payment.AntomPayQueryRequest{
CheckoutSessionIds: []string{detail.OrderRecord.CheckoutSessionId},
})
if stripeInfosErr != nil {
service.Error(c, errors.New(common.ErrorQueryStripeInfo))
return
}
if stripeInfosRes != nil && len(stripeInfosRes.Infos) > 0 {
for _, info := range stripeInfosRes.Infos {
if info.OutTradeNo == detail.OrderRecord.OrderNo && info.Status == "paid" {
_, updateOrderRecordErr := service.BundleProvider.UpdateOrderRecord(context.Background(), &bundle.OrderRecord{
Uuid: detail.OrderRecord.Uuid,
Status: bundleModel.OrderPaid,
PayTime: common.GetBeijingTime(),
})
fmt.Println("detail.OrderRecord.Uuid :", detail.OrderRecord.Uuid)
if updateOrderRecordErr != nil {
service.Error(c, detailErr)
return
}
service.Success(c, &service.Response{
Msg: common.HadPay,
Code: 0,
})
return
}
}
}
}
var antomReq payment.CreatePayRequest
antomReq.Payee = "Antom"
antomReq.Platform = "antom"
antomReq.ChannelType = "antom"
antomReq.ProductDescription = req.ProductDescription
antomReq.BusinessType = "useless"
antomReq.Domain = "fiee"
antomReq.Amount = req.ProductAllPrice
antomReq.Currency = req.ProductPriceCurrency
antomReq.OutTradeNo = req.OutTradeNo
antomReq.ReturnUrl = req.SuccessUrl
//调用微服务获取支付地址
result, err := service.PaymentProvider.CreatePay(context.Background(), &antomReq)
if err != nil {
service.Error(c, err)
return
}
fmt.Println("result.CheckoutSessionId :", result.CheckoutSessionId)
fmt.Println("result.Url :", result.Url)
//更新订单状态
_, updateOrderRecordErr := service.BundleProvider.UpdateOrderRecord(context.Background(), &bundle.OrderRecord{
Uuid: detail.OrderRecord.Uuid,
CheckoutSessionId: result.CheckoutSessionId,
CheckoutSessionUrl: result.Url,
})
fmt.Println("=====================================")
resp := &order.CreateStripeCheckoutSessionResponse{}
resp.CheckoutSessionUrl = result.Url
resp.CheckoutSessionId = result.CheckoutSessionId
fmt.Println("resp:", resp)
if updateOrderRecordErr != nil {
fmt.Println("有更新报错:", updateOrderRecordErr)
service.Error(c, updateOrderRecordErr)
return
}
service.Success(c, resp)
}
func StripeCheckoutSessionWebhook(c *gin.Context) {
var req order.GetCheckoutWebhookRequest
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, int64(65536))
payloadBytes, err := io.ReadAll(c.Request.Body)
if err != nil {
service.Error(c, err)
return
}
req.Payload = string(payloadBytes)
req.Signature = c.GetHeader("Stripe-Signature")
req.WebhookKey = config.Webhookkey
fmt.Printf("webhookKey:%s\n", req.WebhookKey)
resp, err := service.OrderProvider.CommonCheckoutWebhook(c, &req)
if err != nil {
service.Error(c, err)
return
}
fmt.Println("resp.PaymentIntentStatus:", resp.PaymentIntentStatus)
if resp.PaymentIntentStatus == "paid" {
//支付成功
_, updateStatusErr := service.BundleProvider.UpdateOrderRecordByOrderNo(context.Background(), &bundle.OrderRecord{
OrderNo: resp.OutTradeNo,
PayTime: common.GetBeijingTime(),
Status: bundleModel.OrderPaid,
})
if updateStatusErr != nil {
service.Error(c, err)
return
}
}
service.Success(c)
}
func AntomWebhook(c *gin.Context) {
var err error
data, err := io.ReadAll(c.Request.Body)
if err != nil {
service.Error(c, err)
return
}
// 将数据转换为字符串形式并记录日志(如果数据过大则不记录)
dataStr := string(data)
fmt.Println("================ Antom回调参数", dataStr)
// 将读取到的数据解析为 map[string]interface{}
var reqMap map[string]interface{}
if err := json.Unmarshal(data, &reqMap); err != nil {
service.Error(c, err)
return
}
// 提取需要的字段
notifyType, _ := reqMap["notifyType"].(string)
resultMap, resultExists := reqMap["result"].(map[string]interface{})
if !resultExists {
service.Error(c, errors.New("result 字段不存在或类型错误"))
return
}
requestId, _ := reqMap["paymentRequestId"].(string)
paymentId, _ := reqMap["paymentId"].(string)
paymentTime, _ := reqMap["paymentTime"].(string)
// 提取 result 字段中的子字段
resultStatus, _ := resultMap["resultStatus"].(string)
resultMessage, _ := resultMap["resultMessage"].(string)
// 打印提取的字段(可以根据需要处理)
fmt.Println("通知类型:", notifyType)
fmt.Println("订单号:", requestId)
fmt.Println("支付ID:", paymentId)
fmt.Println("支付时间:", paymentTime)
fmt.Println("支付结果状态:", resultStatus)
fmt.Println("支付结果消息:", resultMessage)
/*
* S: 当 notifyType 为PAYMENT_RESULT时表示支付成功当 notifyType 为PAYMENT_PENDING时表示支付处理中。
* F: 表示支付失败。
* */
params := &payment.AntomNotifyPayRequest{
NotifyType: notifyType,
RequestId: requestId,
PaymentId: paymentId,
PaymentTime: paymentTime,
ResultStatus: resultStatus,
ResultMessage: resultMessage,
ChannelCode: "Antom", // fiee对应payment的渠道码
}
resp, err := service.PaymentProvider.AntomWebhook(c, params)
if err != nil {
service.Error(c, err)
return
}
fmt.Println("resp.Status:", resp.Status)
if resp.Status == "paid" {
//支付成功
_, updateStatusErr := service.BundleProvider.UpdateOrderRecordByOrderNo(context.Background(), &bundle.OrderRecord{
OrderNo: resp.OutTradeNo,
PayTime: common.GetBeijingTime(),
Status: bundleModel.OrderPaid,
})
if updateStatusErr != nil {
service.Error(c, err)
return
}
}
service.Success(c)
}