trade_order.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package order
  2. import (
  3. "encoding/json"
  4. logger "eta/eta_mini_ht_api/common/component/log"
  5. "eta/eta_mini_ht_api/models"
  6. merchantDao "eta/eta_mini_ht_api/models/merchant"
  7. "eta/eta_mini_ht_api/models/message"
  8. "eta/eta_mini_ht_api/models/order"
  9. "fmt"
  10. "math/rand"
  11. "strconv"
  12. "time"
  13. )
  14. const (
  15. RMB = "CNY"
  16. AliPayWay PaymentWay = "alipay"
  17. WechatPay PaymentWay = "wechat"
  18. RefundSuccess = "success"
  19. RefundFail = "fail"
  20. PaySuccess = "success"
  21. PayFail = "fail"
  22. )
  23. type PaymentWay string
  24. type TradeOrderDTO struct {
  25. ID int `gorm:"column:id;primaryKey"`
  26. TransactionID string `gorm:"column:transaction_id;type:varchar(255);comment:第三方平台ID"`
  27. ProductOrderID string `gorm:"column:product_order_id;type:varchar(255);comment:商品订单号"`
  28. PaymentAccount string `gorm:"column:payment_account;type:varchar(255);comment:支付账号"`
  29. PaymentWay string `gorm:"column:payment_way;type:enum('wechat');comment:支付渠道"`
  30. Amount string `gorm:"column:amount;type:varchar(20);comment:支付金额"`
  31. Currency string `gorm:"column:currency;type:varchar(255);comment:货币"`
  32. MerchantID string `gorm:"column:merchant_id;type:int(11);comment:商户id"`
  33. UserID int `gorm:"column:user_id;type:int(11);comment:用户id"`
  34. TemplateUserID int `gorm:"column:template_user_id;type:int(11);comment:临时用户id"`
  35. PaymentType string `gorm:"column:payment_type;type:enum('pay','refund');comment:订单类型"`
  36. PaymentStatus string `gorm:"column:payment_status;type:enum('pending','processing','done','failed');comment:支付状态"`
  37. DealTime time.Time `gorm:"column:deal_time;type:datetime;comment:完成时间"`
  38. }
  39. func GenerateTradeOrderNo() string {
  40. timestamp := time.Now().UnixNano() / 1000000 // 毫秒级时间戳
  41. // 生成随机数
  42. rand.New(rand.NewSource(time.Now().UnixNano()))
  43. randomPart := rand.Intn(999999)
  44. // 格式化订单号
  45. orderNumber := fmt.Sprintf("T%d%06d", timestamp, randomPart)
  46. return orderNumber
  47. }
  48. func CreateTradeOrder(userId, templateUserId int, productOrderNo, tradeOrderNo, merchantNo string) (err error) {
  49. db := models.Main()
  50. productOrder, err := order.GetOrderByUser(templateUserId, productOrderNo)
  51. if err != nil {
  52. logger.Error("获取商品订单信息失败%v", err)
  53. return
  54. }
  55. tx := db.Begin()
  56. defer func() {
  57. if err != nil {
  58. tx.Rollback()
  59. return
  60. }
  61. tx.Commit()
  62. }()
  63. tradeOrder := order.TradeOrder{
  64. ProductOrderID: productOrderNo,
  65. ProductName: productOrder.ProductName,
  66. TransactionID: tradeOrderNo,
  67. Amount: productOrder.TotalAmount,
  68. Mobile: productOrder.Mobile,
  69. AreaCode: productOrder.AreaCode,
  70. RealName: productOrder.RealName,
  71. PaymentWay: order.WechatPayWay,
  72. Currency: RMB,
  73. MerchantID: merchantNo,
  74. UserID: userId,
  75. TemplateUserID: templateUserId,
  76. PaymentType: order.PaymentTypePay,
  77. }
  78. err = tx.Create(&tradeOrder).Error
  79. if err != nil {
  80. logger.Error("创建支付订单失败%v", err)
  81. return
  82. }
  83. err = tx.Model(&order.ProductOrder{}).Where("id = ?", productOrder.ID).Updates(map[string]interface{}{
  84. "trade_id": tradeOrder.ID,
  85. "trade_no": tradeOrder.TransactionID,
  86. "payment_time": time.Now(),
  87. "payment_amount": tradeOrder.Amount,
  88. "payment_way": tradeOrder.PaymentWay,
  89. }).Error
  90. return
  91. }
  92. func convertToDTO(tradeOrder order.TradeOrder) TradeOrderDTO {
  93. return TradeOrderDTO{
  94. ID: tradeOrder.ID,
  95. TransactionID: tradeOrder.TransactionID,
  96. ProductOrderID: tradeOrder.ProductOrderID,
  97. PaymentAccount: tradeOrder.PaymentAccount,
  98. PaymentWay: string(tradeOrder.PaymentWay),
  99. Amount: tradeOrder.Amount,
  100. Currency: tradeOrder.Currency,
  101. MerchantID: tradeOrder.MerchantID,
  102. UserID: tradeOrder.UserID,
  103. TemplateUserID: tradeOrder.UserID,
  104. PaymentType: string(tradeOrder.PaymentType),
  105. PaymentStatus: string(tradeOrder.PaymentStatus),
  106. DealTime: tradeOrder.DealTime,
  107. }
  108. }
  109. func GetUnFailedTradeFlowByProductOrder(productOrderNo string) (dtoList []TradeOrderDTO, err error) {
  110. var tradeOrderList []order.TradeOrder
  111. tradeOrderList, err = order.GetUnFailedTradeFlowByProductOrder(productOrderNo)
  112. for _, tradeOrder := range tradeOrderList {
  113. dtoList = append(dtoList, convertToDTO(tradeOrder))
  114. }
  115. return
  116. }
  117. func GetTradeOrderByNo(tradeOrderNo string) (dto TradeOrderDTO, err error) {
  118. var tradeOrder order.TradeOrder
  119. tradeOrder, err = order.GetTradeOrderByNo(tradeOrderNo, order.PaymentTypePay)
  120. dto = convertToDTO(tradeOrder)
  121. return
  122. }
  123. type RefundDealFlowDTO struct {
  124. OperatorUserID int `gorm:"column:operator_user_id"`
  125. ProductOrderNo string `gorm:"column:product_order_no"`
  126. RefundOrderNo string `gorm:"column:refund_order_no"`
  127. }
  128. func convertRefundDTO(flow order.RefundDealFlow) RefundDealFlowDTO {
  129. return RefundDealFlowDTO{
  130. OperatorUserID: flow.OperatorUserID,
  131. ProductOrderNo: flow.ProductOrderNo,
  132. RefundOrderNo: flow.RefundOrderNo,
  133. }
  134. }
  135. func createRefundMetaInfo(sysUserId int, productOrderNo string, flag string) (err error) {
  136. productOrder, err := order.GetOrderByOrderNo(productOrderNo)
  137. if err != nil {
  138. logger.Error("生成退款消息通知失败,获取订单信息失败:v,订单编号:%s", err, productOrderNo)
  139. return
  140. }
  141. var result string
  142. switch flag {
  143. case RefundSuccess:
  144. result = "成功"
  145. case RefundFail:
  146. result = "失败"
  147. default:
  148. logger.Error("生成退款消息通知失败,未知的退款状态%s,订单编号:%s", flag, productOrderNo)
  149. return
  150. }
  151. refundInfo := message.RefundMetaData{
  152. RealName: productOrder.RealName,
  153. ProductOrderNo: productOrderNo,
  154. Result: result,
  155. }
  156. bytes, err := json.Marshal(refundInfo)
  157. if err != nil {
  158. logger.Error("生成退款消息通知失败,序列化退款信息失败:%v,订单编号:%s", err, productOrderNo)
  159. return
  160. }
  161. metaInfo := message.MetaInfo{
  162. Meta: string(bytes),
  163. MetaType: message.SysUserNoticeType,
  164. SourceType: message.RefundSourceType,
  165. Status: message.InitStatusType,
  166. From: "HTTradePlate",
  167. To: strconv.Itoa(sysUserId),
  168. }
  169. return message.CreateMetaInfo(metaInfo)
  170. }
  171. func DealRefund(refundOrderNo string, flag string) (productOrderDTO ProductOrderDTO, err error) {
  172. flow, err := order.GetRefundFlow(refundOrderNo)
  173. if err != nil {
  174. logger.Error("获取退款流水失败%v,退款订单:%s", err, refundOrderNo)
  175. return
  176. }
  177. //处理退款订单
  178. tradeOrder, err := order.GetTradeOrderByNo(flow.RefundOrderNo, order.PaymentTypeRefund)
  179. if err != nil {
  180. logger.Error("获取退款订单失败%v,退款订单:%s", err, refundOrderNo)
  181. return
  182. }
  183. isSuccess := false
  184. if flag == RefundSuccess {
  185. isSuccess = true
  186. }
  187. err = order.DealRefundOrder(tradeOrder, isSuccess)
  188. if err != nil {
  189. logger.Error("处理退款结果失败%v,退款订单:%s", err, refundOrderNo)
  190. return
  191. }
  192. var productOrder order.ProductOrder
  193. productOrder, err = order.GetOrderByOrderNo(tradeOrder.ProductOrderID)
  194. if err != nil {
  195. logger.Error("获取产品订单失败%v,退款订单:%s", err, refundOrderNo)
  196. return
  197. }
  198. productOrderDTO = ConvertProductOrderDTO(productOrder)
  199. _ = createRefundMetaInfo(flow.OperatorUserID, flow.ProductOrderNo, flag)
  200. return
  201. }
  202. func DealPayment(tradeOrderNo string, flag string) (productOrderDTO ProductOrderDTO, err error) {
  203. //处理退款订单
  204. tradeOrder, err := order.GetTradeOrderByNo(tradeOrderNo, order.PaymentTypePay)
  205. if err != nil {
  206. logger.Error("获取支付订单失败%v,支付订单:%s", err, tradeOrderNo)
  207. return
  208. }
  209. isSuccess := false
  210. if flag == PaySuccess {
  211. isSuccess = true
  212. }
  213. var productOrder order.ProductOrder
  214. productOrder, err = order.GetOrderByOrderNo(tradeOrder.ProductOrderID)
  215. if err != nil {
  216. logger.Error("获取产品订单失败%v,支付订单:%s", err, tradeOrderNo)
  217. return
  218. }
  219. product, err := merchantDao.GetMerchantProductById(productOrder.ProductID)
  220. if err != nil {
  221. logger.Error("获取产品信息失败:%v,productId:%d", err, productOrder.ProductID)
  222. }
  223. var validDuration string
  224. if product.Type == merchantDao.Package {
  225. beginDate := time.Now().Format(time.DateOnly)
  226. endDate := time.Now().Add(time.Duration(product.ValidDays * 24)).Format(time.DateOnly)
  227. validDuration = fmt.Sprintf("%s~%s", beginDate, endDate)
  228. } else {
  229. validDuration = "永久有效"
  230. }
  231. err = order.DealPaymentOrder(tradeOrder, isSuccess, validDuration)
  232. if err != nil {
  233. logger.Error("处理支付结果失败%v,支付订单:%s", err, tradeOrderNo)
  234. return
  235. }
  236. productOrderDTO = ConvertProductOrderDTO(productOrder)
  237. return
  238. }