新增微信支付对接,后台客服取消订单

This commit is contained in:
2023-08-03 14:42:33 +08:00
parent faabe27f32
commit 96308ff608
18 changed files with 684 additions and 1 deletions
+6
View File
@@ -6,6 +6,7 @@ type Api struct {
userDoctorManage // 医生管理
Admin // 公共方法
basic // 基础数据
order // 订单管理
}
// SysSetting 系统设置
@@ -31,3 +32,8 @@ type basic struct {
Bank // 银行管理
Area // 省市区管理
}
// 订单管理
type order struct {
OrderInquiry // 问诊订单
}
+51
View File
@@ -0,0 +1,51 @@
package controller
import (
"github.com/gin-gonic/gin"
"hospital-admin-api/api/responses"
"hospital-admin-api/api/service"
"strconv"
)
type OrderInquiry struct{}
// GetOrderInquiryPage 获取问诊订单列表-分页
func (r *OrderInquiry) GetOrderInquiryPage(c *gin.Context) {
responses.Ok(c)
}
// GetOrderInquiry 问诊订单详情
func (r *OrderInquiry) GetOrderInquiry(c *gin.Context) {
responses.Ok(c)
}
// DeleteOrderInquiry 删除问诊订单
func (r *OrderInquiry) DeleteOrderInquiry(c *gin.Context) {
responses.Ok(c)
}
// CancelOrderInquiry 取消问诊订单
func (r *OrderInquiry) CancelOrderInquiry(c *gin.Context) {
id := c.Param("order_inquiry_id")
if id == "" {
responses.FailWithMessage("缺少参数", c)
return
}
// 将 id 转换为 int64 类型
orderInquiryId, err := strconv.ParseInt(id, 10, 64)
if err != nil {
responses.Fail(c)
return
}
// 业务处理
orderInquiryService := service.OrderInquiryService{}
_, err = orderInquiryService.CancelOrderInquiry(orderInquiryId)
if err != nil {
responses.FailWithMessage(err.Error(), c)
return
}
responses.Ok(c)
}
+73
View File
@@ -0,0 +1,73 @@
package dao
import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hospital-admin-api/api/model"
"hospital-admin-api/global"
)
type OrderInquiryDao struct {
}
// GetOrderInquiryById 获取问诊订单数据-问诊订单id
func (r *OrderInquiryDao) GetOrderInquiryById(doctorId int64) (m *model.OrderInquiry, err error) {
err = global.Db.First(&m, doctorId).Error
if err != nil {
return nil, err
}
return m, nil
}
// GetOrderInquiryPreloadById 获取问诊订单数据-加载全部关联-问诊订单id
func (r *OrderInquiryDao) GetOrderInquiryPreloadById(orderInquiryId int64) (m *model.OrderInquiry, err error) {
err = global.Db.Preload(clause.Associations).First(&m, orderInquiryId).Error
if err != nil {
return nil, err
}
return m, nil
}
// DeleteOrderInquiry 删除问诊订单
func (r *OrderInquiryDao) DeleteOrderInquiry(tx *gorm.DB, maps interface{}) error {
err := tx.Where(maps).Delete(&model.OrderInquiry{}).Error
if err != nil {
return err
}
return nil
}
// EditOrderInquiry 修改问诊订单
func (r *OrderInquiryDao) EditOrderInquiry(tx *gorm.DB, maps interface{}, data interface{}) error {
err := tx.Model(&model.OrderInquiry{}).Where(maps).Updates(data).Error
if err != nil {
return err
}
return nil
}
// EditOrderInquiryById 修改问诊订单-问诊订单id
func (r *OrderInquiryDao) EditOrderInquiryById(tx *gorm.DB, orderInquiryId int64, data interface{}) error {
err := tx.Model(&model.OrderInquiry{}).Where("order_inquiry_id = ?", orderInquiryId).Updates(data).Error
if err != nil {
return err
}
return nil
}
// GetOrderInquiryList 获取问诊订单列表
func (r *OrderInquiryDao) GetOrderInquiryList(maps interface{}) (m []*model.OrderInquiry, err error) {
err = global.Db.Where(maps).Find(&m).Error
if err != nil {
return nil, err
}
return m, nil
}
// AddOrderInquiry 新增问诊订单
func (r *OrderInquiryDao) AddOrderInquiry(tx *gorm.DB, model *model.OrderInquiry) (*model.OrderInquiry, error) {
if err := tx.Create(model).Error; err != nil {
return nil, err
}
return model, nil
}
+73
View File
@@ -0,0 +1,73 @@
package dao
import (
"gorm.io/gorm"
"gorm.io/gorm/clause"
"hospital-admin-api/api/model"
"hospital-admin-api/global"
)
type OrderInquiryRefundDao struct {
}
// GetOrderInquiryRefundById 获取问诊退款订单数据-问诊退款订单id
func (r *OrderInquiryRefundDao) GetOrderInquiryRefundById(doctorId int64) (m *model.OrderInquiryRefund, err error) {
err = global.Db.First(&m, doctorId).Error
if err != nil {
return nil, err
}
return m, nil
}
// GetOrderInquiryRefundPreloadById 获取问诊退款订单数据-加载全部关联-问诊退款订单id
func (r *OrderInquiryRefundDao) GetOrderInquiryRefundPreloadById(inquiryRefundId int64) (m *model.OrderInquiryRefund, err error) {
err = global.Db.Preload(clause.Associations).First(&m, inquiryRefundId).Error
if err != nil {
return nil, err
}
return m, nil
}
// DeleteOrderInquiryRefund 删除问诊退款订单
func (r *OrderInquiryRefundDao) DeleteOrderInquiryRefund(tx *gorm.DB, maps interface{}) error {
err := tx.Where(maps).Delete(&model.OrderInquiryRefund{}).Error
if err != nil {
return err
}
return nil
}
// EditOrderInquiryRefund 修改问诊退款订单
func (r *OrderInquiryRefundDao) EditOrderInquiryRefund(tx *gorm.DB, maps interface{}, data interface{}) error {
err := tx.Model(&model.OrderInquiryRefund{}).Where(maps).Updates(data).Error
if err != nil {
return err
}
return nil
}
// EditOrderInquiryRefundById 修改问诊退款订单-问诊退款订单id
func (r *OrderInquiryRefundDao) EditOrderInquiryRefundById(tx *gorm.DB, inquiryRefundId int64, data interface{}) error {
err := tx.Model(&model.OrderInquiryRefund{}).Where("inquiry_refund_id = ?", inquiryRefundId).Updates(data).Error
if err != nil {
return err
}
return nil
}
// GetOrderInquiryRefundList 获取问诊退款订单列表
func (r *OrderInquiryRefundDao) GetOrderInquiryRefundList(maps interface{}) (m []*model.OrderInquiryRefund, err error) {
err = global.Db.Where(maps).Find(&m).Error
if err != nil {
return nil, err
}
return m, nil
}
// AddOrderInquiryRefund 新增问诊退款订单
func (r *OrderInquiryRefundDao) AddOrderInquiryRefund(tx *gorm.DB, model *model.OrderInquiryRefund) (*model.OrderInquiryRefund, error) {
if err := tx.Create(model).Error; err != nil {
return nil, err
}
return model, nil
}
+62
View File
@@ -0,0 +1,62 @@
package model
import (
"gorm.io/gorm"
"hospital-admin-api/global"
"time"
)
// OrderInquiry 订单-问诊表
type OrderInquiry struct {
OrderInquiryId int64 `gorm:"column:order_inquiry_id;type:bigint(19);primary_key;comment:主键id" json:"order_inquiry_id"`
UserId int64 `gorm:"column:user_id;type:bigint(19);comment:用户id-患者;NOT NULL" json:"user_id"`
PatientId int64 `gorm:"column:patient_id;type:bigint(19);comment:患者id;NOT NULL" json:"patient_id"`
DoctorId int64 `gorm:"column:doctor_id;type:bigint(19);comment:医生id(未分配时为null" json:"doctor_id"`
FamilyId int64 `gorm:"column:family_id;type:bigint(19);comment:家庭成员id(就诊用户);NOT NULL" json:"family_id"`
InquiryType int `gorm:"column:inquiry_type;type:tinyint(1);comment:订单类型(1:专家问诊 2:快速问诊 3:公益问诊 4:问诊购药 5:检测);NOT NULL" json:"inquiry_type"`
InquiryMode int `gorm:"column:inquiry_mode;type:tinyint(1);comment:订单问诊方式(1:图文 2:视频 3:语音 4:电话 5:会员);NOT NULL" json:"inquiry_mode"`
InquiryStatus int `gorm:"column:inquiry_status;type:tinyint(1);default:1;comment:问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消);NOT NULL" json:"inquiry_status"`
IsDelete int `gorm:"column:is_delete;type:tinyint(1);default:0;comment:删除状态(0:否 1:是)" json:"is_delete"`
InquiryRefundStatus int `gorm:"column:inquiry_refund_status;type:tinyint(1);default:0;comment:问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常)" json:"inquiry_refund_status"`
InquiryPayChannel int `gorm:"column:inquiry_pay_channel;type:tinyint(1);comment:支付渠道(1:小程序支付 2:微信扫码支付 3:模拟支付)" json:"inquiry_pay_channel"`
InquiryPayStatus int `gorm:"column:inquiry_pay_status;type:tinyint(1);default:1;comment:支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款);NOT NULL" json:"inquiry_pay_status"`
InquiryNo string `gorm:"column:inquiry_no;type:varchar(30);comment:系统订单编号;NOT NULL" json:"inquiry_no"`
EscrowTradeNo string `gorm:"column:escrow_trade_no;type:varchar(100);comment:第三方支付流水号" json:"escrow_trade_no"`
AmountTotal float64 `gorm:"column:amount_total;type:decimal(10,2);default:0.00;comment:订单金额" json:"amount_total"`
CouponAmountTotal float64 `gorm:"column:coupon_amount_total;type:decimal(10,2);comment:优惠卷总金额" json:"coupon_amount_total"`
PaymentAmountTotal float64 `gorm:"column:payment_amount_total;type:decimal(10,2);default:0.00;comment:实际付款金额" json:"payment_amount_total"`
PayTime time.Time `gorm:"column:pay_time;type:datetime;comment:支付时间" json:"pay_time"`
ReceptionTime time.Time `gorm:"column:reception_time;type:datetime;comment:接诊时间(已接诊)" json:"reception_time"`
CompleteTime time.Time `gorm:"column:complete_time;type:datetime;comment:订单完成时间(问诊完成时间)" json:"complete_time"`
FinishTime time.Time `gorm:"column:finish_time;type:datetime;comment:订单结束时间" json:"finish_time"`
StatisticsStatus int `gorm:"column:statistics_status;type:tinyint(1);default:0;comment:订单统计状态(0:未统计 1:已统计 2:统计失败)" json:"statistics_status"`
StatisticsTime time.Time `gorm:"column:statistics_time;type:datetime;comment:订单统计时间" json:"statistics_time"`
IsWithdrawal int `gorm:"column:is_withdrawal;type:tinyint(1);default:0;comment:是否提现(0:否 1:是 2:提现中)" json:"is_withdrawal"`
WithdrawalTime time.Time `gorm:"column:withdrawal_time;type:datetime;comment:提现时间" json:"withdrawal_time"`
CancelTime time.Time `gorm:"column:cancel_time;type:datetime;comment:订单取消时间" json:"cancel_time"`
CancelReason int `gorm:"column:cancel_reason;type:tinyint(1);comment:取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时)" json:"cancel_reason"`
CancelRemarks string `gorm:"column:cancel_remarks;type:varchar(255);comment:取消订单备注(自动添加)" json:"cancel_remarks"`
PatientName string `gorm:"column:patient_name;type:varchar(255);comment:患者姓名-就诊人" json:"patient_name"`
PatientNameMask string `gorm:"column:patient_name_mask;type:varchar(255);comment:患者姓名-就诊人(掩码)" json:"patient_name_mask"`
PatientSex int `gorm:"column:patient_sex;type:tinyint(1);default:0;comment:患者性别-就诊人(0:未知 1:男 2:女)" json:"patient_sex"`
PatientAge int `gorm:"column:patient_age;type:int(1);comment:患者年龄-就诊人" json:"patient_age"`
Model
}
func (m *OrderInquiry) TableName() string {
return "gdxz_order_inquiry"
}
func (m *OrderInquiry) BeforeCreate(tx *gorm.DB) error {
if m.OrderInquiryId == 0 {
m.OrderInquiryId = global.Snowflake.Generate().Int64()
}
m.CreatedAt = LocalTime(time.Now())
tx.Statement.SetColumn("CreatedAt", m.CreatedAt)
m.UpdatedAt = LocalTime(time.Now())
tx.Statement.SetColumn("UpdatedAt", m.UpdatedAt)
return nil
}
+39
View File
@@ -0,0 +1,39 @@
package model
import (
"gorm.io/gorm"
"hospital-admin-api/global"
"time"
)
// OrderInquiryRefund 订单-问诊-退款表
type OrderInquiryRefund struct {
InquiryRefundId int64 `gorm:"column:inquiry_refund_id;type:bigint(19);primary_key;comment:主键id" json:"inquiry_refund_id"`
PatientId int64 `gorm:"column:patient_id;type:bigint(19);comment:患者id" json:"patient_id"`
OrderInquiryId int64 `gorm:"column:order_inquiry_id;type:bigint(19);comment:订单-问诊id" json:"order_inquiry_id"`
InquiryNo string `gorm:"column:inquiry_no;type:varchar(40);comment:系统订单编号" json:"inquiry_no"`
InquiryRefundNo string `gorm:"column:inquiry_refund_no;type:varchar(50);comment:系统退款编号" json:"inquiry_refund_no"`
RefundId string `gorm:"column:refund_id;type:varchar(50);comment:第三方退款单号" json:"refund_id"`
InquiryRefundStatus int `gorm:"column:inquiry_refund_status;type:tinyint(4);comment:问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常)" json:"inquiry_refund_status"`
RefundTotal float64 `gorm:"column:refund_total;type:decimal(10,2);comment:退款金额" json:"refund_total"`
RefundReason string `gorm:"column:refund_reason;type:varchar(255);comment:退款原因" json:"refund_reason"`
SuccessTime time.Time `gorm:"column:success_time;type:datetime;comment:退款成功时间" json:"success_time"`
Model
}
func (m *OrderInquiryRefund) TableName() string {
return "gdxz_order_inquiry_refund"
}
func (m *OrderInquiryRefund) BeforeCreate(tx *gorm.DB) error {
if m.InquiryRefundId == 0 {
m.InquiryRefundId = global.Snowflake.Generate().Int64()
}
m.CreatedAt = LocalTime(time.Now())
tx.Statement.SetColumn("CreatedAt", m.CreatedAt)
m.UpdatedAt = LocalTime(time.Now())
tx.Statement.SetColumn("UpdatedAt", m.UpdatedAt)
return nil
}
+19
View File
@@ -355,4 +355,23 @@ func privateRouter(r *gin.Engine, api controller.Api) {
}
}
// 订单管理
orderGroup := adminGroup.Group("/order")
{
// 问诊订单
inquiryGroup := orderGroup.Group("/inquiry")
{
// 获取问诊订单列表-分页
inquiryGroup.GET("", api.OrderInquiry.GetOrderInquiryPage)
// 问诊订单详情
inquiryGroup.GET("/:order_inquiry_id", api.OrderInquiry.GetOrderInquiry)
// 删除问诊订单
inquiryGroup.DELETE("/:order_inquiry_id", api.OrderInquiry.DeleteOrderInquiry)
// 取消问诊订单
inquiryGroup.PUT("/:order_inquiry_id", api.OrderInquiry.CancelOrderInquiry)
}
}
}
+182
View File
@@ -0,0 +1,182 @@
package service
import (
"errors"
"hospital-admin-api/api/dao"
"hospital-admin-api/api/model"
"hospital-admin-api/config"
"hospital-admin-api/extend/weChat"
"hospital-admin-api/global"
"strconv"
"time"
)
type OrderInquiryService struct {
}
// CancelOrderInquiry 取消问诊订单
func (r *OrderInquiryService) CancelOrderInquiry(orderInquiryId int64) (bool, error) {
// 获取订单数据
orderInquiryDao := dao.OrderInquiryDao{}
orderInquiry, err := orderInquiryDao.GetOrderInquiryById(orderInquiryId)
if err != nil || orderInquiry == nil {
return false, errors.New("订单数据错误")
}
// 检测订单状态 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
if orderInquiry.InquiryStatus == 6 {
return false, errors.New("订单已结束,无法取消")
}
if orderInquiry.InquiryStatus == 7 {
return false, errors.New("订单已取消,无法再次取消")
}
if orderInquiry.InquiryStatus == 1 {
return false, errors.New("订单处于待支付状态,无法取消")
}
if orderInquiry.InquiryStatus == 2 {
return false, errors.New("订单处于分配状态,无法取消")
}
if orderInquiry.InquiryStatus == 3 {
return false, errors.New("订单处于等待接诊状态,无法取消")
}
// 检测订单退款状态 问诊订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常)
if orderInquiry.InquiryRefundStatus == 1 {
return false, errors.New("订单申请退款中,无法取消")
}
if orderInquiry.InquiryRefundStatus == 2 {
return false, errors.New("订单正在退款中,无法取消")
}
if orderInquiry.InquiryRefundStatus == 3 {
return false, errors.New("订单已退款成功,无法取消")
}
if orderInquiry.InquiryRefundStatus == 6 {
return false, errors.New("订单退款异常,请联系技术人员")
}
// 检测支付状态 支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款)
if orderInquiry.InquiryPayStatus != 2 {
return false, errors.New("订单未支付,无需取消")
}
// 订单完成时间预留5分钟进行操作
if !orderInquiry.CompleteTime.IsZero() {
// 计算三天后的时间
threeDaysLater := orderInquiry.CompleteTime.Add(3 * 24 * time.Hour)
if time.Since(threeDaysLater) > 5*time.Minute {
return false, errors.New("距离订单完成时间不足5分钟,无法取消")
}
}
// 开始事务
tx := global.Db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
// 问诊订单修改数据
orderInquiryData := make(map[string]interface{})
// 发起退款
if orderInquiry.PaymentAmountTotal > 0 {
// 退款编号
inquiryRefundNo := strconv.FormatInt(global.Snowflake.Generate().Int64(), 10)
refundRequest := weChat.RefundRequest{
TransactionId: orderInquiry.EscrowTradeNo,
OutTradeNo: orderInquiry.InquiryNo,
OutRefundNo: inquiryRefundNo,
Reason: "客服取消",
PaymentAmountTotal: int64(orderInquiry.PaymentAmountTotal * 100),
NotifyUrl: "https://dev.hospital.applets.igandanyiyuan.com/" + config.C.Wechat.PatientInquiryRefundNotifyUrl,
}
refund, err := refundRequest.Refund()
if err != nil {
tx.Rollback()
return false, errors.New(err.Error())
}
if refund.Status == nil {
tx.Rollback()
return false, errors.New("退款状态错误")
}
// 退款状态转换
var inquiryRefundStatus int
var successTime time.Time
if *refund.Status == "SUCCESS" {
// 退款成功
inquiryRefundStatus = 3
if refund.SuccessTime != nil {
// 使用 time.Parse 解析时间字符串为 time.Time 类型
successTime = *refund.SuccessTime
}
} else if *refund.Status == "CLOSED" {
// 退款关闭
inquiryRefundStatus = 5
} else if *refund.Status == "PROCESSING" {
// 退款处理中
inquiryRefundStatus = 2
} else if *refund.Status == "ABNORMAL" {
// 退款异常
tx.Rollback()
return false, errors.New("退款状态错误")
} else {
tx.Rollback()
return false, errors.New("退款状态错误")
}
if refund.RefundId == nil {
tx.Rollback()
return false, errors.New("缺少退款订单编号")
}
// 新增退款表
orderInquiryRefundDao := dao.OrderInquiryRefundDao{}
orderInquiryRefund := &model.OrderInquiryRefund{
PatientId: orderInquiry.PatientId,
OrderInquiryId: orderInquiryId,
InquiryNo: orderInquiry.InquiryNo,
InquiryRefundNo: inquiryRefundNo,
RefundId: *refund.RefundId,
InquiryRefundStatus: inquiryRefundStatus,
RefundTotal: orderInquiry.PaymentAmountTotal,
RefundReason: "客服取消",
SuccessTime: successTime,
}
orderInquiryRefund, err = orderInquiryRefundDao.AddOrderInquiryRefund(tx, orderInquiryRefund)
if err != nil || orderInquiryRefund == nil {
tx.Rollback()
return false, errors.New(err.Error())
}
}
orderInquiryData["inquiry_status"] = 7 // 问诊订单状态(1:待支付 2:待分配 3:待接诊 4:已接诊 5:已完成 6:已结束 7:已取消)
orderInquiryData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05") // 订单取消时间
orderInquiryData["cancel_reason"] = 4 // 取消订单原因(1:医生未接诊 2:主动取消 3:无可分配医生 4:客服取消 5:支付超时)
orderInquiryData["cancel_remarks"] = "客服取消" // 取消订单备注(自动添加)
// 修改问诊订单退款状态
err = orderInquiryDao.EditOrderInquiryById(tx, orderInquiryId, orderInquiryData)
if err != nil {
tx.Rollback()
return false, errors.New("取消订单失败")
}
tx.Commit()
return true, nil
}