智慧食堂
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

499 righe
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(utils.StrToInt64(total) * 100),
  206. },
  207. Payer: &jsapi.Payer{
  208. //SpOpenid: core.String("oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"),
  209. SubOpenid: core.String(user.OpenId),
  210. },
  211. },
  212. )
  213. //5、插入订单记录
  214. now := time.Now()
  215. centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{}
  216. centralKitchenForSchoolPackageOrd.Set(outTradeNo)
  217. _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdInsertBySession(session, &model.CentralKitchenForSchoolPackageOrd{
  218. EnterpriseId: req.EnterpriseId,
  219. Uid: user.Id,
  220. UserIdentityId: req.UserIdentityId,
  221. UserIdentityName: userIdentity.Name,
  222. TotalPrice: total,
  223. Kind: req.Kind,
  224. OutTradeNo: outTradeNo,
  225. TradeNo: "",
  226. State: enum2.CentralKitchenForSchoolPackageOrdStateForWait,
  227. OrdState: enum2.CentralKitchenForSchoolPackageOrdOrdStateForWait,
  228. ReqContent: string(utils.Serialize(req)),
  229. WithDayData: string(utils.Serialize(data)),
  230. PayWay: enum.PayWayForWx,
  231. CreateAt: now.Format("2006-01-02 15:04:05"),
  232. UpdateAt: now.Format("2006-01-02 15:04:05"),
  233. })
  234. if err != nil {
  235. _ = session.Rollback()
  236. return
  237. }
  238. session.Commit()
  239. prepayId = *resp.PrepayId
  240. return
  241. }
  242. func NursingHomeBuyPackageReq(c *gin.Context, req md.NursingHomeBuyPackageReq) (outTradeNo, tradeNo, total string, err error) {
  243. user := GetUser(c)
  244. session := db.Db.NewSession()
  245. defer session.Close()
  246. session.Begin()
  247. if err != nil {
  248. _ = session.Rollback()
  249. return
  250. }
  251. userIdentityDb := db.UserIdentityDb{}
  252. userIdentityDb.Set(0)
  253. userIdentity, err := userIdentityDb.GetUserIdentity(req.UserIdentityId)
  254. if err != nil {
  255. return
  256. }
  257. if userIdentity == nil {
  258. err = errors.New("未查询到对应身份记录")
  259. return
  260. }
  261. //1、计算数据(1:按年购买 2:按月购买 3:按天购买 4:补餐)
  262. var totalPrice float64
  263. var data []*model.NursingHomeUserWithDay
  264. if req.Kind == 1 {
  265. totalPrice, data, err = CalcByYearForNursingHome(user.Id, req)
  266. if err != nil {
  267. return
  268. }
  269. }
  270. if req.Kind == 2 {
  271. totalPrice, data, err = CalcByMonthForNursingHome(user.Id, req)
  272. if err != nil {
  273. return
  274. }
  275. }
  276. if req.Kind == 3 {
  277. totalPrice, data, err = CalcByDayForNursingHome(user.Id, req)
  278. if err != nil {
  279. return
  280. }
  281. }
  282. if req.Kind == 4 {
  283. totalPrice, data, err = CalcByDayForNursingHome(user.Id, req)
  284. if err != nil {
  285. return
  286. }
  287. }
  288. total = utils.Float64ToStr(totalPrice)
  289. //3、生成订单号
  290. outTradeNo = utils.OrderUUID(user.Id)
  291. //4、请求 alipay.trade.create(统一收单交易创建接口)
  292. sysCfgDb := db.SysCfgDb{}
  293. sysCfgDb.Set()
  294. sysCfg := sysCfgDb.SysCfgFindWithDb(enum2.OpenAppletAppid, enum2.OpenAlipayAppid, enum2.OpenAlipayAppPrivateKey, enum2.OpenAlipayPublicKey, enum2.JsapiPayAppAutToken)
  295. err, resp := CurlAlipayTradeCreate(md.CurlAlipayTradeCreateReq{
  296. Config: struct {
  297. PayAliAppId string `json:"pay_ali_app_id" label:"支付宝开放平台-第三方应用-appid"`
  298. PayAliPrivateKey string `json:"pay_ali_private_key" label:"支付宝开放平台-第三方应用-接口加签-应用私钥"`
  299. PayAliPublicKey string `json:"pay_ali_public_key" label:"支付宝开放平台-第三方应用-接口加签-支付宝公钥"`
  300. }{
  301. PayAliAppId: sysCfg[enum2.OpenAlipayAppid],
  302. PayAliPrivateKey: sysCfg[enum2.OpenAlipayAppPrivateKey],
  303. PayAliPublicKey: sysCfg[enum2.OpenAlipayPublicKey],
  304. },
  305. OpAppId: sysCfg[enum2.OpenAppletAppid],
  306. BuyerId: user.UserId,
  307. TotalAmount: total,
  308. OutTradeNo: outTradeNo,
  309. Subject: "购买食堂套餐",
  310. AppAuthToken: sysCfg[enum2.JsapiPayAppAutToken],
  311. })
  312. if err != nil {
  313. return
  314. }
  315. //5、插入订单记录
  316. now := time.Now()
  317. NursingHomePackageOrd := db.NursingHomePackageOrd{}
  318. NursingHomePackageOrd.Set(outTradeNo)
  319. _, err = NursingHomePackageOrd.NursingHomePackageOrdInsertBySession(session, &model.NursingHomePackageOrd{
  320. EnterpriseId: req.EnterpriseId,
  321. Uid: user.Id,
  322. UserIdentityId: req.UserIdentityId,
  323. UserIdentityName: userIdentity.Name,
  324. TotalPrice: total,
  325. Kind: req.Kind,
  326. OutTradeNo: outTradeNo,
  327. TradeNo: resp.TradeNo,
  328. State: enum2.NursingHomePackageOrdStateForWait,
  329. OrdState: enum2.NursingHomePackageOrdOrdStateForWait,
  330. ReqContent: string(utils.Serialize(req)),
  331. WithDayData: string(utils.Serialize(data)),
  332. CreateAt: now.Format("2006-01-02 15:04:05"),
  333. UpdateAt: now.Format("2006-01-02 15:04:05"),
  334. })
  335. if err != nil {
  336. _ = session.Rollback()
  337. return
  338. }
  339. session.Commit()
  340. tradeNo = resp.TradeNo
  341. return
  342. }
  343. func DealCentralKitchenForSchoolOrderCallBack(outTradeNo, tradeStatus string) (state int, err error) {
  344. centralKitchenForSchoolPackageOrd := db.CentralKitchenForSchoolPackageOrd{}
  345. centralKitchenForSchoolPackageOrd.Set(outTradeNo)
  346. ord, err := centralKitchenForSchoolPackageOrd.GetCentralKitchenForSchoolPackageOrd()
  347. if err != nil {
  348. return
  349. }
  350. if ord == nil {
  351. err = errors.New("未查询到对应订单记录")
  352. return
  353. }
  354. if ord.State == enum2.CentralKitchenForSchoolPackageOrdStateForWait {
  355. if tradeStatus == "TRADE_CLOSED" {
  356. ord.State = enum2.CentralKitchenForSchoolPackageOrdStateForFail
  357. }
  358. if tradeStatus == "TRADE_SUCCESS" {
  359. ord.State = enum2.CentralKitchenForSchoolPackageOrdStateForSuccess
  360. ord.OrdState = enum2.CentralKitchenForSchoolPackageOrdOrdStateForSuccess
  361. //TODO::将预留数据插入到 `central_kitchen_for_school_user_with_day`
  362. var data []*model.CentralKitchenForSchoolUserWithDay
  363. err = json.Unmarshal([]byte(ord.WithDayData), &data)
  364. if err != nil {
  365. return
  366. }
  367. var hasMonths = map[string]map[string]interface{}{}
  368. var hasKinds = map[string]map[string]string{}
  369. var hasTotalPrice = map[string]map[string]float64{}
  370. for _, v := range data {
  371. date, _ := time.ParseInLocation("2006-01-02", v.Date, time.Local)
  372. if hasMonths[utils.TimeParseStd(v.Date).Month().String()] == nil {
  373. hasMonths[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]interface{})
  374. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"] = date.Format("2006-01-02")
  375. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"] = date.Format("2006-01-02")
  376. } else {
  377. startTime, _ := time.ParseInLocation("2006-01-02", utils.AnyToString(hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"]), time.Local)
  378. if startTime.After(date) {
  379. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_start"] = date.Format("2006-01-02")
  380. }
  381. endTime, _ := time.ParseInLocation("2006-01-02", utils.AnyToString(hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"]), time.Local)
  382. if endTime.Before(date) {
  383. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["meal_time_end"] = date.Format("2006-01-02")
  384. }
  385. }
  386. if hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()] == nil {
  387. hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]float64)
  388. }
  389. if hasKinds[utils.TimeParseStd(v.Date).Month().String()] == nil {
  390. hasKinds[utils.TimeParseStd(v.Date).Month().String()] = make(map[string]string)
  391. }
  392. hasMonths[utils.TimeParseStd(v.Date).Month().String()]["month"] = int(utils.TimeParseStd(v.Date).Month())
  393. hasKinds[utils.TimeParseStd(v.Date).Month().String()][utils.IntToStr(v.Kind)] = utils.IntToStr(v.Kind)
  394. hasTotalPrice[utils.TimeParseStd(v.Date).Month().String()][utils.IntToStr(v.Kind)] += utils.StrToFloat64(v.Amount)
  395. v.OrdNo = outTradeNo
  396. }
  397. centralKitchenForSchoolUserWithDayDb := db.CentralKitchenForSchoolUserWithDayDb{}
  398. centralKitchenForSchoolUserWithDayDb.Set(0)
  399. _, err = centralKitchenForSchoolUserWithDayDb.BatchAddCentralKitchenForSchoolUserWithDays(data)
  400. if err != nil {
  401. return
  402. }
  403. //TODO::插入数据至 `central_kitchen_for_school_package_ord_for_reserve`
  404. centralKitchenForSchoolPackageOrdForReserve := db.CentralKitchenForSchoolPackageOrdForReserve{}
  405. centralKitchenForSchoolPackageOrdForReserve.Set(outTradeNo)
  406. for k, v := range hasMonths {
  407. for _, v1 := range hasKinds[k] {
  408. _, err = centralKitchenForSchoolPackageOrdForReserve.CentralKitchenForSchoolPackageOrdForReserveInsert(&model.CentralKitchenForSchoolPackageOrdForReserve{
  409. EnterpriseId: ord.EnterpriseId,
  410. Uid: ord.Uid,
  411. UserIdentityName: ord.UserIdentityName,
  412. UserIdentityId: ord.UserIdentityId,
  413. Kind: utils.StrToInt(v1),
  414. OutTradeNo: ord.OutTradeNo,
  415. ReserveMonth: utils.AnyToString(v["month"]),
  416. MealTimeStart: utils.AnyToString(v["meal_time_start"]),
  417. MealTimeEnd: utils.AnyToString(v["meal_time_end"]),
  418. TotalPrice: utils.Float64ToStr(hasTotalPrice[k][v1]),
  419. CreateAt: time.Now().Format("2006-01-02 15:04:05"),
  420. UpdateAt: time.Now().Format("2006-01-02 15:04:05"),
  421. })
  422. if err != nil {
  423. return
  424. }
  425. }
  426. }
  427. }
  428. _, err = centralKitchenForSchoolPackageOrd.CentralKitchenForSchoolPackageOrdUpdate(ord, "state", "ord_state")
  429. if err != nil {
  430. return
  431. }
  432. }
  433. state = ord.State
  434. return
  435. }
  436. func CheckAllCallbackParams(c *gin.Context) interface{} {
  437. body, _ := ioutil.ReadAll(c.Request.Body)
  438. utils.FilePutContents("CheckAllCallbackParams", utils.SerializeStr(string(body)))
  439. dataAlipay, _ := GetAlipayCallbackParams(body)
  440. if dataAlipay != nil {
  441. return dataAlipay
  442. }
  443. return nil
  444. }
  445. // GetAlipayCallbackParams 支付宝参数解析
  446. func GetAlipayCallbackParams(body []byte) (*md.AliPayCallback, error) {
  447. decodeArgs, err := url.QueryUnescape(string(body))
  448. if err != nil {
  449. _ = logx.Warn(err)
  450. return nil, logx.Warn("回调参数解码错误")
  451. }
  452. data, err := url.ParseQuery(decodeArgs)
  453. if err != nil {
  454. return nil, err
  455. }
  456. dataMap := make(map[string]interface{})
  457. for k := range data {
  458. dataMap[k] = data.Get(k)
  459. }
  460. callbackStr := utils.Serialize(dataMap)
  461. fmt.Println("支付宝回调数据", string(callbackStr))
  462. var args md.AliPayCallback
  463. if err := json.Unmarshal(callbackStr, &args); err != nil {
  464. return nil, logx.Warn(err)
  465. }
  466. return &args, nil
  467. }