智慧食堂
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.

505 line
16 KiB

  1. package svc
  2. import (
  3. "applet/app/customer/enum"
  4. "applet/app/customer/md"
  5. "applet/app/db"
  6. "applet/app/db/model"
  7. enum2 "applet/app/enum"
  8. svc3 "applet/app/svc"
  9. "applet/app/utils"
  10. "applet/app/utils/logx"
  11. "encoding/json"
  12. "errors"
  13. "fmt"
  14. "github.com/gin-gonic/gin"
  15. "github.com/wechatpay-apiv3/wechatpay-go/core"
  16. "github.com/wechatpay-apiv3/wechatpay-go/services/partnerpayments/jsapi"
  17. "io/ioutil"
  18. "net/url"
  19. "time"
  20. )
  21. func BuyPackageForAli(c *gin.Context, req md.BuyPackageReq) (outTradeNo, tradeNo, total string, err error) {
  22. user := GetUser(c)
  23. session := db.Db.NewSession()
  24. defer session.Close()
  25. session.Begin()
  26. if err != nil {
  27. _ = session.Rollback()
  28. return
  29. }
  30. //1、判断是否为教师
  31. isTeacher := false
  32. userIdentityDb := db.UserIdentityDb{}
  33. userIdentityDb.Set(0)
  34. userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId)
  35. if err != nil {
  36. return
  37. }
  38. if userIdentity == nil {
  39. err = errors.New("未查询到对应身份记录")
  40. return
  41. }
  42. if userIdentity.Identity == enum2.UserIdentityForCentralKitchenForTeacher {
  43. isTeacher = true
  44. }
  45. //2、计算数据(1:按学期购买 2:按月购买 3:按天购买 4:补餐)
  46. var totalPrice float64
  47. var data []*model.CentralKitchenForSchoolUserWithDay
  48. if req.Kind == 1 {
  49. totalPrice, data, err = CalcBySchoolTerm(user.Id, isTeacher, req)
  50. if err != nil {
  51. return
  52. }
  53. }
  54. if req.Kind == 2 {
  55. totalPrice, data, err = CalcByMonth(user.Id, isTeacher, req)
  56. if err != nil {
  57. return
  58. }
  59. }
  60. if req.Kind == 3 {
  61. totalPrice, data, err = CalcByDay(user.Id, isTeacher, req)
  62. if err != nil {
  63. return
  64. }
  65. }
  66. if req.Kind == 4 {
  67. totalPrice, data, err = CalcSupplementaryByDay(user.Id, isTeacher, req)
  68. if err != nil {
  69. return
  70. }
  71. }
  72. total = utils.Float64ToStr(totalPrice)
  73. //3、生成订单号
  74. outTradeNo = utils.OrderUUID(user.Id)
  75. //4、请求 alipay.trade.create(统一收单交易创建接口)
  76. sysCfgDb := db.SysCfgDb{}
  77. sysCfgDb.Set()
  78. sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.OpenAppletAppid, enum2.OpenAlipayAppid, enum2.OpenAlipayAppPrivateKey, enum2.OpenAlipayPublicKey, enum2.JsapiPayAppAutToken, enum2.JsapiPayNotifyUrl)
  79. err, resp := CurlAlipayTradeCreate(md.CurlAlipayTradeCreateReq{
  80. Config: struct {
  81. PayAliAppId string `json:"pay_ali_app_id" label:"支付宝开放平台-第三方应用-appid"`
  82. PayAliPrivateKey string `json:"pay_ali_private_key" label:"支付宝开放平台-第三方应用-接口加签-应用私钥"`
  83. PayAliPublicKey string `json:"pay_ali_public_key" label:"支付宝开放平台-第三方应用-接口加签-支付宝公钥"`
  84. }{
  85. PayAliAppId: sysCfg[enum2.OpenAlipayAppid],
  86. PayAliPrivateKey: sysCfg[enum2.OpenAlipayAppPrivateKey],
  87. PayAliPublicKey: sysCfg[enum2.OpenAlipayPublicKey],
  88. },
  89. OpAppId: sysCfg[enum2.OpenAppletAppid],
  90. BuyerId: user.UserId,
  91. TotalAmount: total,
  92. OutTradeNo: outTradeNo,
  93. Subject: "购买食堂套餐",
  94. AppAuthToken: sysCfg[enum2.JsapiPayAppAutToken],
  95. NotifyUrl: sysCfg[enum2.JsapiPayNotifyUrl],
  96. })
  97. if err != nil {
  98. return
  99. }
  100. //5、插入订单记录
  101. now := time.Now()
  102. centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{}
  103. centralKitchenForSchoolPackageOrd.Set(outTradeNo)
  104. _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdInsertBySession(session, &model.CentralKitchenForSchoolPackageOrd{
  105. EnterpriseId: req.EnterpriseId,
  106. Uid: user.Id,
  107. UserIdentityId: req.UserIdentityId,
  108. UserIdentityName: userIdentity.Name,
  109. TotalPrice: total,
  110. Kind: req.Kind,
  111. OutTradeNo: outTradeNo,
  112. TradeNo: resp.TradeNo,
  113. State: enum2.CentralKitchenForSchoolPackageOrdStateForWait,
  114. OrdState: enum2.CentralKitchenForSchoolPackageOrdOrdStateForWait,
  115. ReqContent: string(utils.Serialize(req)),
  116. WithDayData: string(utils.Serialize(data)),
  117. PayWay: enum.PayWayForAli,
  118. CreateAt: now.Format("2006-01-02 15:04:05"),
  119. UpdateAt: now.Format("2006-01-02 15:04:05"),
  120. })
  121. if err != nil {
  122. _ = session.Rollback()
  123. return
  124. }
  125. session.Commit()
  126. tradeNo = resp.TradeNo
  127. return
  128. }
  129. func BuyPackageForWx(c *gin.Context, req md.BuyPackageReq) (outTradeNo, prepayId, total string, err error) {
  130. user := GetUser(c)
  131. session := db.Db.NewSession()
  132. defer session.Close()
  133. session.Begin()
  134. if err != nil {
  135. _ = session.Rollback()
  136. return
  137. }
  138. //1、判断是否为教师
  139. isTeacher := false
  140. userIdentityDb := db.UserIdentityDb{}
  141. userIdentityDb.Set(0)
  142. userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId)
  143. if err != nil {
  144. return
  145. }
  146. if userIdentity == nil {
  147. err = errors.New("未查询到对应身份记录")
  148. return
  149. }
  150. if userIdentity.Identity == enum2.UserIdentityForCentralKitchenForTeacher {
  151. isTeacher = true
  152. }
  153. //2、计算数据(1:按学期购买 2:按月购买 3:按天购买 4:补餐)
  154. var totalPrice float64
  155. var data []*model.CentralKitchenForSchoolUserWithDay
  156. if req.Kind == 1 {
  157. totalPrice, data, err = CalcBySchoolTerm(user.Id, isTeacher, req)
  158. if err != nil {
  159. return
  160. }
  161. }
  162. if req.Kind == 2 {
  163. totalPrice, data, err = CalcByMonth(user.Id, isTeacher, req)
  164. if err != nil {
  165. return
  166. }
  167. }
  168. if req.Kind == 3 {
  169. totalPrice, data, err = CalcByDay(user.Id, isTeacher, req)
  170. if err != nil {
  171. return
  172. }
  173. }
  174. if req.Kind == 4 {
  175. totalPrice, data, err = CalcSupplementaryByDay(user.Id, isTeacher, req)
  176. if err != nil {
  177. return
  178. }
  179. }
  180. total = utils.Float64ToStr(totalPrice)
  181. //3、生成订单号
  182. outTradeNo = utils.OrderUUID(user.Id)
  183. //4、请求 /v3/pay/partner/transactions/jsapi (生成预支付交易单)
  184. sysCfgDb := db.SysCfgDb{}
  185. sysCfgDb.Set()
  186. client, err := svc3.NewWxPayClient(c)
  187. if err != nil {
  188. return
  189. }
  190. wxSvc := jsapi.JsapiApiService{Client: client}
  191. sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.WxSpAppId, enum2.WxSpMchId, enum2.WxAppletAppId, enum2.WxMchId, enum2.WxJsapiPayNotifyUrl)
  192. resp, _, err := wxSvc.Prepay(c,
  193. jsapi.PrepayRequest{
  194. SpAppid: core.String(sysCfg[enum2.WxSpAppId]),
  195. SpMchid: core.String(sysCfg[enum2.WxSpMchId]),
  196. SubAppid: core.String(sysCfg[enum2.WxAppletAppId]),
  197. SubMchid: core.String(sysCfg[enum2.WxMchId]),
  198. Description: core.String("购买食堂套餐"),
  199. OutTradeNo: core.String(outTradeNo),
  200. TimeExpire: core.Time(time.Now().Add(30 * time.Minute)),
  201. //Attach: core.String("自定义数据说明"),
  202. NotifyUrl: core.String(sysCfg[enum2.WxJsapiPayNotifyUrl]),
  203. Amount: &jsapi.Amount{
  204. Currency: core.String("CNY"),
  205. Total: core.Int64(int64(totalPrice * 100)),
  206. },
  207. Payer: &jsapi.Payer{
  208. //SpOpenid: core.String("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"),
  209. SubOpenid: core.String(user.OpenId),
  210. },
  211. },
  212. )
  213. fmt.Println(">>>>>>>>>>>", core.Int64(utils.StrToInt64(total)*100))
  214. if err != nil {
  215. _ = session.Rollback()
  216. return
  217. }
  218. //5、插入订单记录
  219. now := time.Now()
  220. centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{}
  221. centralKitchenForSchoolPackageOrd.Set(outTradeNo)
  222. _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdInsertBySession(session, &model.CentralKitchenForSchoolPackageOrd{
  223. EnterpriseId: req.EnterpriseId,
  224. Uid: user.Id,
  225. UserIdentityId: req.UserIdentityId,
  226. UserIdentityName: userIdentity.Name,
  227. TotalPrice: total,
  228. Kind: req.Kind,
  229. OutTradeNo: outTradeNo,
  230. TradeNo: "",
  231. State: enum2.CentralKitchenForSchoolPackageOrdStateForWait,
  232. OrdState: enum2.CentralKitchenForSchoolPackageOrdOrdStateForWait,
  233. ReqContent: string(utils.Serialize(req)),
  234. WithDayData: string(utils.Serialize(data)),
  235. PayWay: enum.PayWayForWx,
  236. CreateAt: now.Format("2006-01-02 15:04:05"),
  237. UpdateAt: now.Format("2006-01-02 15:04:05"),
  238. })
  239. if err != nil {
  240. _ = session.Rollback()
  241. return
  242. }
  243. session.Commit()
  244. prepayId = *resp.PrepayId
  245. return
  246. }
  247. func NursingHomeBuyPackageReq(c *gin.Context, req md.NursingHomeBuyPackageReq) (outTradeNo, tradeNo, total string, err error) {
  248. user := GetUser(c)
  249. session := db.Db.NewSession()
  250. defer session.Close()
  251. session.Begin()
  252. if err != nil {
  253. _ = session.Rollback()
  254. return
  255. }
  256. userIdentityDb := db.UserIdentityDb{}
  257. userIdentityDb.Set(0)
  258. userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId)
  259. if err != nil {
  260. return
  261. }
  262. if userIdentity == nil {
  263. err = errors.New("未查询到对应身份记录")
  264. return
  265. }
  266. //1、计算数据(1:按年购买 2:按月购买 3:按天购买 4:补餐)
  267. var totalPrice float64
  268. var data []*model.NursingHomeUserWithDay
  269. if req.Kind == 1 {
  270. totalPrice, data, err = CalcByYearForNursingHome(user.Id, req)
  271. if err != nil {
  272. return
  273. }
  274. }
  275. if req.Kind == 2 {
  276. totalPrice, data, err = CalcByMonthForNursingHome(user.Id, req)
  277. if err != nil {
  278. return
  279. }
  280. }
  281. if req.Kind == 3 {
  282. totalPrice, data, err = CalcByDayForNursingHome(user.Id, req)
  283. if err != nil {
  284. return
  285. }
  286. }
  287. if req.Kind == 4 {
  288. totalPrice, data, err = CalcByDayForNursingHome(user.Id, req)
  289. if err != nil {
  290. return
  291. }
  292. }
  293. total = utils.Float64ToStr(totalPrice)
  294. //3、生成订单号
  295. outTradeNo = utils.OrderUUID(user.Id)
  296. //4、请求 alipay.trade.create(统一收单交易创建接口)
  297. sysCfgDb := db.SysCfgDb{}
  298. sysCfgDb.Set()
  299. sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.OpenAppletAppid, enum2.OpenAlipayAppid, enum2.OpenAlipayAppPrivateKey, enum2.OpenAlipayPublicKey, enum2.JsapiPayAppAutToken)
  300. err, resp := CurlAlipayTradeCreate(md.CurlAlipayTradeCreateReq{
  301. Config: struct {
  302. PayAliAppId string `json:"pay_ali_app_id" label:"支付宝开放平台-第三方应用-appid"`
  303. PayAliPrivateKey string `json:"pay_ali_private_key" label:"支付宝开放平台-第三方应用-接口加签-应用私钥"`
  304. PayAliPublicKey string `json:"pay_ali_public_key" label:"支付宝开放平台-第三方应用-接口加签-支付宝公钥"`
  305. }{
  306. PayAliAppId: sysCfg[enum2.OpenAlipayAppid],
  307. PayAliPrivateKey: sysCfg[enum2.OpenAlipayAppPrivateKey],
  308. PayAliPublicKey: sysCfg[enum2.OpenAlipayPublicKey],
  309. },
  310. OpAppId: sysCfg[enum2.OpenAppletAppid],
  311. BuyerId: user.UserId,
  312. TotalAmount: total,
  313. OutTradeNo: outTradeNo,
  314. Subject: "购买食堂套餐",
  315. AppAuthToken: sysCfg[enum2.JsapiPayAppAutToken],
  316. })
  317. if err != nil {
  318. return
  319. }
  320. //5、插入订单记录
  321. now := time.Now()
  322. NursingHomePackageOrd := db.NursingHomePackageOrd{}
  323. NursingHomePackageOrd.Set(outTradeNo)
  324. _, err = NursingHomePackageOrd.NursingHomePackageOrdInsertBySession(session, &model.NursingHomePackageOrd{
  325. EnterpriseId: req.EnterpriseId,
  326. Uid: user.Id,
  327. UserIdentityId: req.UserIdentityId,
  328. UserIdentityName: userIdentity.Name,
  329. TotalPrice: total,
  330. Kind: req.Kind,
  331. OutTradeNo: outTradeNo,
  332. TradeNo: resp.TradeNo,
  333. State: enum2.NursingHomePackageOrdStateForWait,
  334. OrdState: enum2.NursingHomePackageOrdOrdStateForWait,
  335. ReqContent: string(utils.Serialize(req)),
  336. WithDayData: string(utils.Serialize(data)),
  337. CreateAt: now.Format("2006-01-02 15:04:05"),
  338. UpdateAt: now.Format("2006-01-02 15:04:05"),
  339. })
  340. if err != nil {
  341. _ = session.Rollback()
  342. return
  343. }
  344. session.Commit()
  345. tradeNo = resp.TradeNo
  346. return
  347. }
  348. func DealCentralKitchenForSchoolOrderCallBack(outTradeNo, tradeStatus string) (state int, err error) {
  349. centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{}
  350. centralKitchenForSchoolPackageOrd.Set(outTradeNo)
  351. ord, err := centralKitchenForSchoolPackageOrd.GetCentralKitchenForSchoolPackageOrd()
  352. if err != nil {
  353. return
  354. }
  355. if ord == nil {
  356. err = errors.New("未查询到对应订单记录")
  357. return
  358. }
  359. if ord.State == enum2.CentralKitchenForSchoolPackageOrdStateForWait {
  360. if tradeStatus == "TRADE_CLOSED" {
  361. ord.State = enum2.CentralKitchenForSchoolPackageOrdStateForFail
  362. }
  363. if tradeStatus == "TRADE_SUCCESS" {
  364. ord.State = enum2.CentralKitchenForSchoolPackageOrdStateForSuccess
  365. ord.OrdState = enum2.CentralKitchenForSchoolPackageOrdOrdStateForSuccess
  366. //TODO::将预留数据插入到 `central_kitchen_for_school_user_with_day`
  367. var data []*model.CentralKitchenForSchoolUserWithDay
  368. err = json.Unmarshal([]byte(ord.WithDayData), &data)
  369. if err != nil {
  370. return
  371. }
  372. var hasMonths = map[string]map[string]interface{}{}
  373. var hasKinds = map[string]map[string]string{}
  374. var hasTotalPrice = map[string]map[string]float64{}
  375. for _, v := range data {
  376. date, _ := time.ParseInLocation("2006-01-02", v.Date, time.Local)
  377. if hasMonths[utils.TimeParseStd(v.Date).Month().String()] == nil {
  378. hasMonths[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]interface{})
  379. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"] = date.Format("2006-01-02")
  380. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"] = date.Format("2006-01-02")
  381. } else {
  382. startTime, _ := time.ParseInLocation("2006-01-02", utils.AnyToString(hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"]), time.Local)
  383. if startTime.After(date) {
  384. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"] = date.Format("2006-01-02")
  385. }
  386. endTime, _ := time.ParseInLocation("2006-01-02", utils.AnyToString(hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"]), time.Local)
  387. if endTime.Before(date) {
  388. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"] = date.Format("2006-01-02")
  389. }
  390. }
  391. if hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()] == nil {
  392. hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]float64)
  393. }
  394. if hasKinds[utils.TimeParseStd(v.Date).Month().String()] == nil {
  395. hasKinds[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]string)
  396. }
  397. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["month"] = int(utils.TimeParseStd(v.Date).Month())
  398. hasKinds[utils.TimeParseStd(v.Date).Month().String()][utils.IntToStr(v.Kind)] = utils.IntToStr(v.Kind)
  399. hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()][utils.IntToStr(v.Kind)] += utils.StrToFloat64(v.Amount)
  400. v.OrdNo = outTradeNo
  401. }
  402. centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{}
  403. centralKitchenForSchoolUserWithDayDb.Set(0)
  404. _, err = centralKitchenForSchoolUserWithDayDb.BatchAddCentralKitchenForSchoolUserWithDays(data)
  405. if err != nil {
  406. return
  407. }
  408. //TODO::插入数据至 `central_kitchen_for_school_package_ord_for_reserve`
  409. centralKitchenForSchoolPackageOrdForReserve := db.CentralKitchenForSchoolPackageOrdForReserve{}
  410. centralKitchenForSchoolPackageOrdForReserve.Set(outTradeNo)
  411. for k, v := range hasMonths {
  412. for _, v1 := range hasKinds[k] {
  413. _, err = centralKitchenForSchoolPackageOrdForReserve.CentralKitchenForSchoolPackageOrdForReserveInsert(&model.CentralKitchenForSchoolPackageOrdForReserve{
  414. EnterpriseId: ord.EnterpriseId,
  415. Uid: ord.Uid,
  416. UserIdentityName: ord.UserIdentityName,
  417. UserIdentityId: ord.UserIdentityId,
  418. Kind: utils.StrToInt(v1),
  419. OutTradeNo: ord.OutTradeNo,
  420. ReserveMonth: utils.AnyToString(v["month"]),
  421. MealTimeStart: utils.AnyToString(v["meal_time_start"]),
  422. MealTimeEnd: utils.AnyToString(v["meal_time_end"]),
  423. TotalPrice: utils.Float64ToStr(hasTotalPrice[k][v1]),
  424. CreateAt: time.Now().Format("2006-01-02 15:04:05"),
  425. UpdateAt: time.Now().Format("2006-01-02 15:04:05"),
  426. })
  427. if err != nil {
  428. return
  429. }
  430. }
  431. }
  432. }
  433. _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdUpdate(ord, "state", "ord_state")
  434. if err != nil {
  435. return
  436. }
  437. }
  438. state = ord.State
  439. return
  440. }
  441. func CheckAllCallbackParams(c *gin.Context) interface{} {
  442. body, _ := ioutil.ReadAll(c.Request.Body)
  443. utils.FilePutContents("CheckAllCallbackParams", utils.SerializeStr(string(body)))
  444. dataAlipay, _ := GetAlipayCallbackParams(body)
  445. if dataAlipay != nil {
  446. return dataAlipay
  447. }
  448. return nil
  449. }
  450. // GetAlipayCallbackParams 支付宝参数解析
  451. func GetAlipayCallbackParams(body []byte) (*md.AliPayCallback, error) {
  452. decodeArgs, err := url.QueryUnescape(string(body))
  453. if err != nil {
  454. _ = logx.Warn(err)
  455. return nil, logx.Warn("回调参数解码错误")
  456. }
  457. data, err := url.ParseQuery(decodeArgs)
  458. if err != nil {
  459. return nil, err
  460. }
  461. dataMap := make(map[string]interface{})
  462. for k := range data {
  463. dataMap[k] = data.Get(k)
  464. }
  465. callbackStr := utils.Serialize(dataMap)
  466. fmt.Println("支付宝回调数据", string(callbackStr))
  467. var args md.AliPayCallback
  468. if err := json.Unmarshal(callbackStr, &args); err != nil {
  469. return nil, logx.Warn(err)
  470. }
  471. return &args, nil
  472. }