智慧食堂
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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