data_api_check.go 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520
  1. // Copyright 2019 utimes.cc. All rights reserved.
  2. // Use of this source code is governed by utimes.cc.
  3. // data_api_check 包提供平台api参数校验功能,和与业务相关的后台数据查询功能
  4. package data_api_check
  5. import (
  6. "context"
  7. "encoding/hex"
  8. "encoding/json"
  9. "fmt"
  10. "gd_auth_check/apis"
  11. "gd_auth_check/errors"
  12. "gd_auth_check/limit"
  13. "github.com/tidwall/gjson"
  14. "sort"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "time"
  19. "gd_auth_check/common.in/cache"
  20. "gd_auth_check/common.in/config"
  21. "gd_auth_check/common.in/jsonrpc2"
  22. "gd_auth_check/common.in/utils"
  23. "github.com/astaxie/beego/orm"
  24. "go.uber.org/zap"
  25. )
  26. // timeInfo 包含api用量、时间等信息
  27. type timeInfo struct {
  28. // mdaId 商户数据api id
  29. mdaId int64
  30. // startTime 套餐的开始时间
  31. startTime int64
  32. // endTime 套餐的结束时间
  33. endTime int64
  34. // dayCount 单天调用量上限
  35. dayCount int
  36. // totalCount 总调用量上限
  37. totalCount int
  38. // 套餐类型
  39. comboType int
  40. // 是否是免费套餐
  41. isFree int
  42. // 单天即查量上限
  43. dayTotalCount int
  44. }
  45. // checkTimeResult 包含用量检查后的信息
  46. type checkTimeResult struct {
  47. info timeInfo
  48. // accessCountId 对应的计数日志id
  49. accessCountId int64
  50. // 套餐类型
  51. comboType int
  52. // 剩余使用天数
  53. remainDays int
  54. // 剩余总次数
  55. remainCount int
  56. // 剩余单天次数
  57. remainDayCount int
  58. // 总的天数上限
  59. totalDays int
  60. }
  61. // setMysqlError 记录mysql错误信息
  62. func setMysqlError(sql string, args string, err error) {
  63. if err != nil {
  64. l.Error("mysql",
  65. zap.String("sql", sql),
  66. zap.String("args", args),
  67. zap.String("error", err.Error()))
  68. }
  69. }
  70. // redis 消息channel
  71. const (
  72. ApiNotifyChannel = "api_notify"
  73. MerchantNotifyChannel = "merchant_notify"
  74. MerchantApiNotifyChannel = "merchant_api_notify"
  75. )
  76. type ApiInfo struct {
  77. apiId int64
  78. apiName string
  79. enable bool
  80. }
  81. // 本地缓存map
  82. var apiMap = map[string]*ApiInfo{}
  83. var merchantMap = map[string]*MerchantInfo{}
  84. var merchantApiMap = map[string][]orm.Params{}
  85. //var priceMap = map[int64]float64{}
  86. // 操作本地缓存的锁
  87. var apiMutex sync.RWMutex
  88. var merchantMutex sync.RWMutex
  89. var merchantApiMutex sync.RWMutex
  90. var priceMutex sync.Mutex
  91. // setApiMap 设置基础api本地缓存
  92. func setApiMap(router, method string, apiId int64, apiName string, enable bool) {
  93. apiMutex.Lock()
  94. defer apiMutex.Unlock()
  95. key := router + "-" + method
  96. apiMap[key] = &ApiInfo{
  97. apiId: apiId,
  98. apiName: apiName,
  99. enable: enable,
  100. }
  101. }
  102. // getApiFromMap从本地缓存获取基础api信息
  103. func getApiFromMap(router, method string) *ApiInfo {
  104. apiMutex.RLock()
  105. defer apiMutex.RUnlock()
  106. key := router + "-" + method
  107. ret, ok := apiMap[key]
  108. if ok == false {
  109. return nil
  110. }
  111. return ret
  112. }
  113. // setMerchantMap 商户基本信息保存到本地缓存
  114. func setMerchantMap(appKey string, merchantInfo *MerchantInfo) {
  115. merchantMutex.Lock()
  116. defer merchantMutex.Unlock()
  117. merchantMap[appKey] = merchantInfo
  118. }
  119. // getMerchantFromMap 从本地缓存获取商户基本信息
  120. func getMerchantFromMap(appKey string) *MerchantInfo {
  121. merchantMutex.RLock()
  122. defer merchantMutex.RUnlock()
  123. ret, ok := merchantMap[appKey]
  124. if ok == false {
  125. return nil
  126. }
  127. return ret
  128. }
  129. // setMerchantApiMap 将商户的api信息保存到本地缓存
  130. func setMerchantApiMap(apiId int64, merchantId int64, infos []orm.Params) {
  131. merchantApiMutex.Lock()
  132. defer merchantApiMutex.Unlock()
  133. key := fmt.Sprintf("%d-%d", apiId, merchantId)
  134. merchantApiMap[key] = infos
  135. }
  136. // getMerchantApiFromMap 从本地缓存获取商户的api信息
  137. func getMerchantApiFromMap(apiId int64, merchantId int64) []orm.Params {
  138. merchantApiMutex.RLock()
  139. defer merchantApiMutex.RUnlock()
  140. key := fmt.Sprintf("%d-%d", apiId, merchantId)
  141. ret, ok := merchantApiMap[key]
  142. if ok == false {
  143. return nil
  144. }
  145. return ret
  146. }
  147. // cleanMerchantMap 清理本地缓存的商户信息
  148. func cleanMerchantMap() {
  149. merchantMutex.Lock()
  150. defer merchantMutex.Unlock()
  151. i := 0
  152. array := make([]string, len(merchantMap))
  153. for k, _ := range merchantMap {
  154. array[i] = k
  155. i++
  156. }
  157. for _, v := range array {
  158. delete(merchantMap, v)
  159. }
  160. }
  161. /*func cleanPriceMap(){
  162. priceMutex.Lock()
  163. defer priceMutex.Unlock()
  164. array := make([]int64, len(priceMap))
  165. i := 0
  166. for k, _ := range priceMap {
  167. array[i] = k
  168. i++
  169. }
  170. for _, v := range array {
  171. delete(priceMap, v)
  172. }
  173. }*/
  174. // cleanMerchantApiMap 清理本地缓存的商户api信息
  175. func cleanMerchantApiMap() {
  176. merchantApiMutex.Lock()
  177. defer merchantApiMutex.Unlock()
  178. i := 0
  179. array := make([]string, len(merchantApiMap))
  180. for k, _ := range merchantApiMap {
  181. array[i] = k
  182. i++
  183. }
  184. for _, v := range array {
  185. delete(merchantApiMap, v)
  186. }
  187. }
  188. // cleanApiMap清理本地缓存的基础api信息
  189. func cleanApiMap() {
  190. apiMutex.Lock()
  191. defer apiMutex.Unlock()
  192. i := 0
  193. array := make([]string, len(apiMap))
  194. for k, _ := range apiMap {
  195. array[i] = k
  196. i++
  197. }
  198. for _, v := range array {
  199. delete(apiMap, v)
  200. }
  201. }
  202. // CleanLocalCache 定时清理本地缓存
  203. func CleanLocalCache() {
  204. t := time.NewTicker(5 * time.Minute)
  205. for {
  206. select {
  207. case <-t.C:
  208. LoadRedis()
  209. cleanApiMap()
  210. cleanMerchantMap()
  211. cleanMerchantApiMap()
  212. //cleanPriceMap()
  213. }
  214. }
  215. }
  216. // clearApiMap 删除本地缓存的某个基础api
  217. func clearApiMap(router, method string) {
  218. apiMutex.Lock()
  219. defer apiMutex.Unlock()
  220. key := router + "-" + method
  221. delete(apiMap, key)
  222. }
  223. // clearMerchantMap 删除本地缓存的某个商户
  224. func clearMerchantMap(appKey string) {
  225. merchantMutex.Lock()
  226. defer merchantMutex.Unlock()
  227. delete(merchantMap, appKey)
  228. }
  229. /*func clearPriceMap(appKey string) {
  230. merchantId := int64(0)
  231. o := orm.NewOrm()
  232. err := o.Raw("select id from t_gd_merchants where app_key=?", appKey).QueryRow(&merchantId)
  233. if err != nil {
  234. return
  235. }
  236. priceMutex.Lock()
  237. defer priceMutex.Unlock()
  238. delete(priceMap, merchantId)
  239. }*/
  240. // clearMerchantApiMap 删除本地缓存的某个商户的api
  241. func clearMerchantApiMap(apiId int64, merchantId int64) {
  242. merchantApiMutex.Lock()
  243. defer merchantApiMutex.Unlock()
  244. key := fmt.Sprintf("%d-%d", apiId, merchantId)
  245. delete(merchantApiMap, key)
  246. }
  247. // handleApiNotify 处理基础api的消息通知
  248. func handleApiNotify(data string) {
  249. m := map[string]string{}
  250. json.Unmarshal([]byte(data), &m)
  251. if m["router"] != "" && m["method"] != "" {
  252. clearApiMap(m["router"], m["method"])
  253. }
  254. }
  255. // handleMerchantNotify 处理商户的消息通知
  256. func handleMerchantNotify(data string) {
  257. if data != "" {
  258. clearMerchantMap(data)
  259. //clearPriceMap(data)
  260. }
  261. }
  262. // handleMerchantApiNotify 处理商户api的消息通知
  263. func handleMerchantApiNotify(data string) {
  264. m := map[string]interface{}{}
  265. json.Unmarshal([]byte(data), &m)
  266. if _, ok := m["api_id"]; ok == false {
  267. return
  268. }
  269. if _, ok := m["merchant_id"]; ok == false {
  270. return
  271. }
  272. f, _ := m["api_id"].(float64)
  273. apiId := int64(f)
  274. f, _ = m["merchant_id"].(float64)
  275. merchantId := int64(f)
  276. clearMerchantApiMap(apiId, merchantId)
  277. }
  278. // Watch 订阅基础api,商户,商户api的消息
  279. func Watch() {
  280. go func() {
  281. cache.Redis.RegisterFunc(ApiNotifyChannel, handleApiNotify)
  282. cache.Redis.RegisterFunc(MerchantNotifyChannel, handleMerchantNotify)
  283. cache.Redis.RegisterFunc(MerchantApiNotifyChannel, handleMerchantApiNotify)
  284. cache.Redis.SubscribeAndHandle(ApiNotifyChannel, MerchantNotifyChannel, MerchantApiNotifyChannel)
  285. }()
  286. }
  287. // getAccessCountInfo 获取商户数据api的用量信息
  288. func getAccessCountInfo(o orm.Ormer, mdaId int64) (totalUsed int, dayUsed int, specialDayUsed int, totalId int64, dayId int64, dayTotalUsed int64, dayTotalUsedDayCombo int64, err error) {
  289. sql := "select id, count, day_count as special_day_count, day_total_count from t_gd_api_access_count where merchant_data_api_id=? and create_time=?"
  290. totalTime := "0000-00-00"
  291. dayTime := time.Now().Format("2006-01-02")
  292. err = o.Raw(sql, mdaId, totalTime).QueryRow(&totalId, &totalUsed, &specialDayUsed, &dayTotalUsed)
  293. if err != nil {
  294. if err != orm.ErrNoRows {
  295. err = errors.DataBaseError
  296. return
  297. }
  298. }
  299. sql = "select id, count, day_total_count from t_gd_api_access_count where merchant_data_api_id=? and create_time=?"
  300. err = o.Raw(sql, mdaId, dayTime).QueryRow(&dayId, &dayUsed, &dayTotalUsedDayCombo)
  301. if err != nil {
  302. if err != orm.ErrNoRows {
  303. err = errors.DataBaseError
  304. return
  305. }
  306. }
  307. err = nil
  308. return
  309. }
  310. // setExpire 设置数据api状态为过期
  311. func setExpire(o orm.Ormer, mdaId int64) {
  312. o.Raw("update t_gd_merchant_data_api set state=1 where id=?", mdaId).Exec()
  313. }
  314. // setState 设置数据api状态为正常
  315. func setState(o orm.Ormer, mdaId int64) {
  316. o.Raw("update t_gd_merchant_data_api set state=0 where id=?", mdaId).Exec()
  317. }
  318. // checkTime 用量检查, info 包含套餐信息, state为数据api的原始状态
  319. func checkTime(o orm.Ormer, info timeInfo, state int) (ret checkTimeResult, err error) {
  320. now := time.Now().Unix()
  321. nowday := time.Now().Format("2006-01-02")
  322. updated := false
  323. defer func() {
  324. if updated == false {
  325. return
  326. }
  327. if err == nil {
  328. return
  329. }
  330. // 商户类型为预结算或者后付款次数不回退
  331. /*if (merchantType == 2 || merchantType == 3) && err == errors.CheckApiDayCountLimitNew{
  332. return
  333. }*/
  334. // 如果超出次数限制,次数减一
  335. sql := ""
  336. if info.comboType == 2 {
  337. sql = fmt.Sprintf("update t_gd_api_access_count set count= case when count > 0 then count - 1 when count=0 then 0 end, day_total_count= case when day_total_count > 0 then day_total_count - 1 else 0 end where merchant_data_api_id=%d and create_time<>'0000-00-00'", info.mdaId)
  338. } else {
  339. sql = fmt.Sprintf("update t_gd_api_access_count set count= case when count > 0 then count - 1 when count=0 then 0 end, day_count= case when day_count > 0 then day_count - 1 else 0 end, day_total_count= case when day_total_count > 0 then day_total_count - 1 else 0 end where merchant_data_api_id=%d and create_time='0000-00-00'", info.mdaId)
  340. }
  341. o.Raw(sql).Exec()
  342. }()
  343. // 初始化套餐类型
  344. if info.comboType == 0 {
  345. if info.endTime == 0 {
  346. info.comboType = 1
  347. } else {
  348. info.comboType = 2
  349. }
  350. }
  351. // 免费套餐直接通过
  352. if info.isFree > 0 {
  353. ret.info = info
  354. return ret, nil
  355. }
  356. ret.comboType = info.comboType
  357. // 按天套餐天数过期,直接返错
  358. if now > info.endTime && info.comboType == 2 {
  359. if state != 0 {
  360. return ret, errors.CheckApiDaysLimit
  361. }
  362. setExpire(o, info.mdaId)
  363. return ret, errors.CheckApiDaysLimit
  364. }
  365. sql := ""
  366. // 次数记录不存在则创建
  367. if info.comboType == 2 {
  368. sql = fmt.Sprintf("insert into t_gd_api_access_count(fail_count,"+
  369. " count, day_total_count, merchant_data_api_id, create_time) select 0, 0, 0, %d, '%s' "+
  370. "from dual where not exists (select * from t_gd_api_access_count where create_time <> '0000-00-00' and merchant_data_api_id = %d)",
  371. info.mdaId, nowday, info.mdaId)
  372. } else {
  373. sql = fmt.Sprintf("insert into t_gd_api_access_count(fail_count, "+
  374. "count, day_total_count, merchant_data_api_id, create_time, day_count, now_date) select 0, 0, 0, %d, '0000-00-00', 0, '%s' "+
  375. "from dual where not exists (select * from t_gd_api_access_count where create_time = '0000-00-00' and merchant_data_api_id = %d)",
  376. info.mdaId, nowday, info.mdaId)
  377. }
  378. _, err = o.Raw(sql).Exec()
  379. if err != nil && strings.Contains(err.Error(), "Duplicate") == false {
  380. return ret, errors.DataBaseError
  381. }
  382. // 首先将次数加1,限制并发下商户次数
  383. if info.comboType == 2 {
  384. sql = fmt.Sprintf("update t_gd_api_access_count set last_day_count= case when create_time ='%s' then last_day_count else count end, last_day_date=case when create_time='%s' then last_day_date else create_time end, count=case when"+
  385. " create_time <>'%s' then 1 when create_time='%s' then count+1 end, "+
  386. "day_total_count = case when create_time <>'%s' then 1 when create_time='%s' then day_total_count+1 end, "+
  387. "create_time='%s',fail_count= case when create_time <>'%s' then 0 when"+
  388. " create_time='%s' then fail_count end, create_time='%s' where merchant_data_api_id=%d and create_time<>'0000-00-00'", nowday, nowday, nowday, nowday, nowday, nowday, nowday, nowday, nowday, nowday, info.mdaId)
  389. } else {
  390. sql = fmt.Sprintf("update t_gd_api_access_count set last_day_count= case when now_date ='%s' then last_day_count else day_count end, last_day_date=case when now_date='%s' then last_day_date else now_date end, count=count+1, day_count= case when now_date='%s' then day_count+1 else 1 end,day_total_count= case when now_date='%s' then day_total_count+1 else 1 end, now_date= '%s' where merchant_data_api_id=%d and create_time='0000-00-00'", nowday, nowday, nowday, nowday, nowday, info.mdaId)
  391. }
  392. _, err = o.Raw(sql).Exec()
  393. if err != nil {
  394. return ret, errors.DataBaseError
  395. }
  396. updated = true
  397. // 获取已用次数信息
  398. totalUsed, dayUsed, specialDayUsed, totalId, dayId, dayTotalUsed, dayTotalUsedDayCombo, err := getAccessCountInfo(o, info.mdaId)
  399. if err != nil {
  400. return ret, err
  401. }
  402. ret.remainCount = info.totalCount - totalUsed + 1
  403. ret.remainDayCount = info.dayCount - dayUsed + 1
  404. ret.remainDays = int((info.endTime - now) / int64(3600*24))
  405. ret.totalDays = int((info.endTime - info.startTime) / int64(3600*24))
  406. ret.info = info
  407. if ret.comboType == 1 {
  408. // 按次套餐单日即查量超次
  409. // TODO
  410. if info.dayTotalCount > 0 && info.dayTotalCount-int(dayTotalUsed)+1 <= 0 {
  411. return ret, errors.CheckApiDayCountLimit
  412. }
  413. // 单日计费次数超次
  414. // TODO
  415. if info.dayCount > 0 && info.dayCount-specialDayUsed+1 <= 0 {
  416. return ret, errors.CheckApiDayCountLimit
  417. }
  418. // 状态已过期
  419. if state != 0 {
  420. return ret, errors.CheckApiTotalCountLimit
  421. }
  422. // 总计费次数超次
  423. if ret.remainCount <= 0 {
  424. setExpire(o, info.mdaId)
  425. return ret, errors.CheckApiTotalCountLimit
  426. }
  427. ret.accessCountId = totalId
  428. return ret, nil
  429. }
  430. // 按天套餐按日即查次数超次
  431. // TODO
  432. if info.dayTotalCount > 0 && info.dayTotalCount-int(dayTotalUsedDayCombo)+1 <= 0 {
  433. return ret, errors.CheckApiDayCountLimit
  434. }
  435. // 未超次,则恢复状态
  436. if state != 0 {
  437. if ret.remainDayCount > 0 {
  438. setState(o, info.mdaId)
  439. }
  440. }
  441. // 按天套餐单日计费次数超次
  442. if ret.remainDayCount <= 0 {
  443. return ret, errors.CheckApiDayCountLimit
  444. }
  445. ret.accessCountId = dayId
  446. return ret, nil
  447. }
  448. func getMerchantInfoFromMysql(o orm.Ormer, appKey string) (*MerchantInfo, error) {
  449. minfo := MerchantInfo{}
  450. if appKey == "" {
  451. return nil, nil
  452. }
  453. sql := "select id, app_secret, merchant_name, ip_whitelist,is_http_code,merchant_type,arrearage,auth_status from t_gd_merchants where app_key=?"
  454. err := o.Raw(sql, appKey).QueryRow(&minfo)
  455. if err != nil {
  456. if err == orm.ErrNoRows {
  457. return nil, errors.CheckMerchantNotExist
  458. }
  459. setMysqlError(sql, fmt.Sprintf("%s", appKey), err)
  460. return nil, errors.DataBaseError
  461. }
  462. if minfo.Id > 0 {
  463. setMerchantMap(appKey, &minfo)
  464. }
  465. return &minfo, nil
  466. }
  467. // getMerchantInfo 根据appKey获取商户信息
  468. func getMerchantInfo(o orm.Ormer, appKey string) (*MerchantInfo, error) {
  469. minfo := MerchantInfo{}
  470. if appKey == "" {
  471. return nil, nil
  472. }
  473. if minfo := getMerchantFromMap(appKey); minfo != nil {
  474. return minfo, nil
  475. }
  476. key := fmt.Sprintf("t_gd_merchants-%s", appKey)
  477. tab := apis.TGdMerchants{}
  478. utils.RedisGet(key, &tab)
  479. if tab.Id == 0 {
  480. return getMerchantInfoFromMysql(o, appKey)
  481. }
  482. minfo.Id = tab.Id
  483. minfo.AppSecret = tab.AppSecret
  484. minfo.MerchantName = tab.MerchantName
  485. minfo.IpWhitelist = tab.IpWhitelist
  486. minfo.IsHttpCode = tab.IsHttpCode
  487. minfo.MerchantType = tab.MerchantType
  488. minfo.Arrearage = tab.Arrearage
  489. minfo.AuthStatus = tab.AuthStatus
  490. if minfo.Id > 0 {
  491. setMerchantMap(appKey, &minfo)
  492. }
  493. return &minfo, nil
  494. }
  495. // getBaseApiIdFromMysql 从mysql获取基础api id等信息
  496. func getBaseApiIdFromMysql(o orm.Ormer, req *apis.ManagementCheckApiReq) (int64, bool, string, error) {
  497. var baseApiId int64
  498. var enable bool
  499. name := ""
  500. sql := "select id, enable, name from t_gd_api where router=? and method=?"
  501. err := o.Raw(sql, req.Router, req.Method).QueryRow(&baseApiId, &enable, &name)
  502. if err != nil {
  503. if err == orm.ErrNoRows {
  504. return 0, false, "", errors.CheckApiNotExist
  505. }
  506. setMysqlError(sql, fmt.Sprintf("%s %s", req.Router, req.Method), err)
  507. return 0, false, "", errors.DataBaseError
  508. }
  509. if baseApiId > 0 {
  510. setApiMap(req.Router, req.Method, baseApiId, name, enable)
  511. }
  512. return baseApiId, enable, name, nil
  513. }
  514. // getBaseApiId 获取基础api id等信息
  515. func getBaseApiId(o orm.Ormer, req *apis.ManagementCheckApiReq) (int64, bool, string, error) {
  516. if api := getApiFromMap(req.Router, req.Method); api != nil {
  517. return api.apiId, api.enable, api.apiName, nil
  518. }
  519. key := fmt.Sprintf("t_gd_api-%s-%s", req.Method, req.Router)
  520. tab := apis.TGdApi{}
  521. utils.RedisGet(key, &tab)
  522. if tab.Id == 0 {
  523. return getBaseApiIdFromMysql(o, req)
  524. }
  525. if tab.Id > 0 {
  526. setApiMap(req.Router, req.Method, tab.Id, tab.Name, tab.Enable)
  527. }
  528. return tab.Id, tab.Enable, tab.Name, nil
  529. }
  530. // getResultMaps 获取商户api相关信息,minfo包含了商户信息,isCache表示是否使用本地缓存
  531. func getResultMaps(o orm.Ormer, req *apis.ManagementCheckApiReq, minfo *MerchantInfo, isCache bool) ([]orm.Params, int64, error) {
  532. var baseApiId int64
  533. var enable bool
  534. // TODO 获取商户api 单价
  535. if minfo == nil {
  536. return nil, 0, nil
  537. }
  538. merchantId := minfo.Id
  539. // 获取基础api信息
  540. baseApiId, enable, apiname, err := getBaseApiId(o, req)
  541. if err != nil {
  542. return nil, baseApiId, err
  543. }
  544. minfo.ApiName = apiname
  545. // 基础api未启用
  546. if enable == false {
  547. return nil, baseApiId, errors.CheckApiNotEnable
  548. }
  549. // 从本地缓存获取商户api信息
  550. if isCache {
  551. if maps := getMerchantApiFromMap(baseApiId, merchantId); len(maps) > 0 {
  552. return maps, baseApiId, nil
  553. }
  554. }
  555. maps := []orm.Params{}
  556. /*
  557. sql = "select a.id, a.merchant_data_api_id, a.count_type, a.count_code, a.is_crypto, a.is_enable, a.force_update, a.request_param, a.response_param, b.count as total_count, b.count_per_day as day_count, b.start_time, b.end_time from t_gd_merchant_child_data_api as a inner join t_gd_merchant_data_api as b on a.merchant_data_api_id=b.id where a.api_id=? and b.merchant_id=?"
  558. */
  559. sql := "select a.id, a.filter, a.merchant_data_api_id, b.ip_whitelist, b.ip_whitelist_enable, a.count_type, a.count_code, a.is_crypto, " +
  560. "a.is_enable, a.force_update, a.reuse_time, a.request_param, a.response_param,a.timeout,a.minimal_time_consuming,a.random_percentage,a.is_raw_error_code, (select is_free" +
  561. " from t_gd_data_api_query_type where id=b.query_type_id) as is_free, b.count as total_count, " +
  562. "b.count_per_day as day_count, b.state as api_state, b.combo_type, b.start_time, b.end_time, b.day_total_count,b.unit_price from " +
  563. "t_gd_merchant_child_data_api as a inner join t_gd_merchant_data_api as b on a.merchant_data_api_id=b.id where a.api_id=? and b.merchant_id=?"
  564. _, err = o.Raw(sql, baseApiId, merchantId).Values(&maps)
  565. if err != nil {
  566. if err == orm.ErrNoRows {
  567. return nil, baseApiId, errors.CheckApiInfoNotExist
  568. }
  569. setMysqlError(sql, fmt.Sprintf("%d %d", baseApiId, merchantId), err)
  570. return nil, baseApiId, errors.DataBaseError
  571. }
  572. if len(maps) == 0 {
  573. return nil, baseApiId, errors.CheckApiInfoNotExist
  574. }
  575. if len(maps) > 0 {
  576. setMerchantApiMap(baseApiId, merchantId, maps)
  577. }
  578. return maps, baseApiId, nil
  579. }
  580. // getOriginMerchantApi 获取原始商户的一条数据api信息
  581. // 数据查询中支持使用原始商户的api配置,计费算到内部商户(又称替换商户)头上
  582. func getOriginMerchantApi(o orm.Ormer, req *apis.ManagementCheckApiReq, maps []orm.Params, minfo *MerchantInfo) (orm.Params, error) {
  583. var checkTimeError error
  584. var matchedRecord orm.Params
  585. for _, v := range maps {
  586. minfo.MerchantChildApiId = int64(ormStringToInt(v, "id"))
  587. matchedRecord = v
  588. break
  589. }
  590. return matchedRecord, checkTimeError
  591. }
  592. // getAvailableApi 商户如果购买了多个包含相同基础api的数据api,任意选一个可用的
  593. func getAvailableApi(o orm.Ormer, req *apis.ManagementCheckApiReq, maps []orm.Params, minfo *MerchantInfo) (orm.Params, checkTimeResult, error) {
  594. var checkTimeError error
  595. var ctr checkTimeResult
  596. var matchedRecord orm.Params
  597. for _, v := range maps {
  598. // 初始化套餐信息
  599. info := timeInfo{
  600. startTime: ormStringToInt(v, "start_time"),
  601. endTime: ormStringToInt(v, "end_time"),
  602. comboType: int(ormStringToInt(v, "combo_type")),
  603. mdaId: int64(ormStringToInt(v, "merchant_data_api_id")),
  604. dayCount: int(ormStringToInt(v, "day_count")),
  605. totalCount: int(ormStringToInt(v, "total_count")),
  606. isFree: int(ormStringToInt(v, "is_free")),
  607. dayTotalCount: int(ormStringToInt(v, "day_total_count")),
  608. }
  609. matchedRecord = v
  610. minfo.MerchantChildApiId = int64(ormStringToInt(v, "id"))
  611. isIpWhitelistEnable := int(ormStringToInt(v, "ip_whitelist_enable"))
  612. // ip报名单检查
  613. if value, ok := v["ip_whitelist"]; ok && isIpWhitelistEnable == 1 {
  614. ipWhitelist, _ := value.(string)
  615. if ipWhitelist != "" && checkIpWhite(ipWhitelist, req.Ip) == false {
  616. checkTimeError = errors.IpAddrErr
  617. continue
  618. }
  619. }
  620. // api是否启用
  621. if int(ormStringToInt(v, "is_enable")) == 0 {
  622. checkTimeError = errors.CheckApiNotEnable
  623. continue
  624. }
  625. // api是否过期
  626. ctr, checkTimeError = checkTime(o, info, int(ormStringToInt(v, "api_state")))
  627. ctr.info = info
  628. if checkTimeError != nil {
  629. continue
  630. }
  631. //matchedRecord = v
  632. break
  633. }
  634. return matchedRecord, ctr, checkTimeError
  635. }
  636. // setCheckResult 设置公共校验完成后的返回参数
  637. func setCheckResult(ctr checkTimeResult, matchedRecord orm.Params) (apis.CheckMerchantApiResult, error) {
  638. var err error
  639. result := apis.CheckMerchantApiResult{}
  640. reqParamConf, _ := matchedRecord["request_param"].(string)
  641. resParamConf, _ := matchedRecord["response_param"].(string)
  642. result.MerchantChildApiId = ormStringToInt(matchedRecord, "id")
  643. result.ComboType = ctr.comboType
  644. result.CountType = int(ormStringToInt(matchedRecord, "count_type"))
  645. result.CountCode, _ = matchedRecord["count_code"].(string)
  646. result.ReuseTime = int(ormStringToInt(matchedRecord, "reuse_time"))
  647. result.Timeout = uint64(ormStringToInt(matchedRecord, "timeout"))
  648. result.MinimalTimeConsuming = int(ormStringToInt(matchedRecord, "minimal_time_consuming"))
  649. result.RandomPercentage = int(ormStringToInt(matchedRecord, "random_percentage"))
  650. if int(ormStringToInt(matchedRecord, "is_raw_error_code")) == 1 {
  651. result.IsRawErrorCode = true
  652. }
  653. if int(ormStringToInt(matchedRecord, "force_update")) == 1 {
  654. result.IsForceUpdate = true
  655. }
  656. if result.RequstParamConf, err = parseParamConf(reqParamConf); err != nil {
  657. return result, err
  658. }
  659. if result.ResponseParamConf, err = parseParamConf(resParamConf); err != nil {
  660. return result, err
  661. }
  662. //result.ProviderInfo = providers
  663. return result, nil
  664. }
  665. // parseParamConf 将配置参数字符串转为json数组
  666. func parseParamConf(data string) ([]apis.ManagementBaseApiParam, error) {
  667. params := []apis.ManagementBaseApiParam{}
  668. err := json.Unmarshal([]byte(data), &params)
  669. if err != nil {
  670. return nil, errors.CheckApiParamConfParseFailed
  671. }
  672. return params, nil
  673. }
  674. // 判断实际数据是否加密,加密返回解密后数据和true, 未加密返回原数据
  675. func isActualEncrypt(data []byte, secret []byte) ([]byte, bool) {
  676. bytes, err := hex.DecodeString(string(data))
  677. if err != nil {
  678. return data, false
  679. }
  680. paramBytes, err := config.AesDecrypt(bytes, secret)
  681. if err != nil {
  682. return data, false
  683. }
  684. return paramBytes, true
  685. }
  686. // decryptParam 解密参数
  687. func decryptParam(req *apis.ManagementCheckApiReq, secret []byte, isCrypto int) (paramBytes []byte, err error) {
  688. // 加密
  689. var origin = map[string]string{}
  690. // 原始参数解析
  691. json.Unmarshal(req.RequestParam, &origin)
  692. enType := req.Header["encrypt_type"]
  693. // 非加密模式
  694. if enType == ""{
  695. return req.RequestParam, nil
  696. }
  697. for k,v := range origin{
  698. if v != "" {
  699. if enType == "MD5"{
  700. }else if enType == "AES"{
  701. bytes, err := hex.DecodeString(v)
  702. if err != nil {
  703. return nil,errors.CheckParamDecryptFail
  704. }
  705. desBytes, err := config.AesDecrypt(bytes, secret)
  706. if err != nil {
  707. return nil,errors.CheckParamDecryptFail
  708. }
  709. origin[k] = string(desBytes)
  710. }else{
  711. return nil,errors.CryptoTypeFailed
  712. }
  713. }
  714. }
  715. return json.Marshal(origin)
  716. return req.RequestParam, nil
  717. }
  718. // decreaseCount api调用量减一
  719. // 因为公共校验时会先将api用量加一(防止并发引起的多调),当校验不通过时会减一
  720. func decreaseCount(o orm.Ormer, id int64) {
  721. if id <= 0 {
  722. return
  723. }
  724. o.Raw("update t_gd_api_access_count set count= case when count>0 then count - 1 when count=0 then 0 end, day_total_count = case when day_total_count > 0 then day_total_count -1 else 0 end, day_count = case when day_count > 0 then day_count - 1 else 0 end where id=?", id).Exec()
  725. }
  726. func increaseBalance(o orm.Ormer, merchantDataApiId, merchantId int64, unitPrice float64, error error) {
  727. sql := fmt.Sprintf("update t_gd_merchants set balance=balance+%f where id=?", unitPrice)
  728. o.Raw(sql, merchantId).Exec()
  729. var e jsonrpc2.Error
  730. err := json.Unmarshal([]byte(error.Error()), &e)
  731. if err == nil {
  732. if e.Code == 1102 || e.Code == 1103 || e.Code == 1023 {
  733. if merchantDataApiId == 0 || merchantId == 0 {
  734. return
  735. }
  736. timeNow := time.Now()
  737. day := timeNow.Format("2006-01-02")
  738. month := timeNow.Format("2006-01")
  739. sql = "insert into t_gd_consume(day,month,merchant_data_api_id,merchant_id,total_count,remark) " +
  740. "value ('%s','%s',%d,%d,1,'') ON DUPLICATE key UPDATE total_count=total_count+1"
  741. sql = fmt.Sprintf(sql, day, month, merchantDataApiId, merchantId)
  742. _, err = o.Raw(sql).Exec()
  743. }
  744. }
  745. }
  746. func checkBalance(o orm.Ormer, merchantType int, merchantId int64, unitPrice, arrearage float64, info timeInfo, comboType int) error {
  747. timeNow := time.Now()
  748. day := timeNow.Format("2006-01-02")
  749. totalCount := 0
  750. chargeCount := 0
  751. sql := "select total_count, charge_count from t_gd_consume where day=? and merchant_data_api_id=?"
  752. err := o.Raw(sql, day, info.mdaId).QueryRow(&totalCount, &chargeCount)
  753. if err == nil {
  754. // 单日计费次数超次
  755. if info.dayTotalCount > 0 && info.dayTotalCount <= totalCount {
  756. return errors.CheckApiDayCountLimit
  757. }
  758. if comboType == 1 {
  759. if info.dayCount > 0 && info.dayCount <= chargeCount {
  760. return errors.CheckApiDayCountLimit
  761. }
  762. }
  763. }
  764. // 预付款
  765. if unitPrice == 0 {
  766. return nil
  767. }
  768. if merchantType == 2 {
  769. sql := fmt.Sprintf("update t_gd_merchants set balance=balance-%f where id=? and balance-%f>=0", unitPrice, unitPrice)
  770. if arrearage != 0 {
  771. sql = fmt.Sprintf("update t_gd_merchants set balance=balance-%f where id=? and balance-%f>=%f", unitPrice, unitPrice, -arrearage)
  772. }
  773. result, err := o.Raw(sql, merchantId).Exec()
  774. if err != nil {
  775. return errors.DataBaseError
  776. }
  777. row, _ := result.RowsAffected()
  778. if row == 0 {
  779. return errors.BalanceError
  780. }
  781. } else {
  782. // 后结算
  783. sql := fmt.Sprintf("update t_gd_merchants set balance=balance-%f where id=?", unitPrice)
  784. if arrearage != 0 {
  785. sql = fmt.Sprintf("update t_gd_merchants set balance=balance-%f where id=? and balance-%f>=%f", unitPrice, unitPrice, -arrearage)
  786. }
  787. result, err := o.Raw(sql, merchantId).Exec()
  788. if err != nil {
  789. return errors.DataBaseError
  790. }
  791. row, _ := result.RowsAffected()
  792. if row == 0 {
  793. return errors.ArrearageError
  794. }
  795. }
  796. return nil
  797. }
  798. func RobotMsg(content string) (err error) {
  799. body := map[string]interface{}{
  800. "msgtype": "text",
  801. "text": map[string]interface{}{"content": content},
  802. }
  803. bytes, _ := json.Marshal(body)
  804. h := utils.HttpRequestWithHeadCommon{
  805. Method: "POST",
  806. Url: config.Conf.ThirdPart.RobotUrl,
  807. Body: bytes,
  808. TimeOut: 10 * time.Second,
  809. }
  810. bytes, err = h.Request()
  811. if err != nil {
  812. l.Error("func",
  813. zap.String("call", "RobotMsg"),
  814. zap.String("params", content),
  815. zap.String("error", err.Error()))
  816. return errors.VendorError
  817. }
  818. errcode := gjson.GetBytes(bytes, "errcode").Int()
  819. errmsg := gjson.GetBytes(bytes, "errmsg").String()
  820. if errcode != 0 {
  821. l.Error("func",
  822. zap.String("call", "RobotMsg"),
  823. zap.String("params", content),
  824. zap.String("error", errmsg))
  825. return errors.VendorError
  826. }
  827. return nil
  828. }
  829. func balanceCheckSendDingTalk(o orm.Ormer, merchantId int64, unitPrice, arrearage float64, merchantType int) {
  830. if merchantType == 3 {
  831. if arrearage == 0 {
  832. return
  833. }
  834. }
  835. // 抓异常代码
  836. defer func() {
  837. if r := recover(); r != nil {
  838. fmt.Println("err :", r)
  839. }
  840. }()
  841. //priceMutex.Lock()
  842. //defer priceMutex.Unlock()
  843. //ret, ok := priceMap[merchantId]
  844. //if ok == false {
  845. balance := float64(0)
  846. err := o.Raw("select balance from t_gd_merchants where id=?", merchantId).QueryRow(&balance)
  847. if err != nil {
  848. fmt.Println("err:", err)
  849. return
  850. }
  851. // ret = balance
  852. //}else {
  853. // ret = ret - unitPrice
  854. //}
  855. //priceMap[merchantId] = ret
  856. if (balance + arrearage) <= 10 {
  857. // 发送钉钉消息
  858. key := fmt.Sprintf("dingding-%d", merchantId)
  859. isSucess, err := utils.RedisSetNxEx(key, 864000, "1")
  860. if err != nil {
  861. fmt.Println("err:", err)
  862. return
  863. }
  864. if isSucess {
  865. merchantName := ""
  866. err = o.Raw("select merchant_name from t_gd_merchants where id=?", merchantId).QueryRow(&merchantName)
  867. if err != nil {
  868. fmt.Println("err:", err)
  869. return
  870. }
  871. content := fmt.Sprintf("商户(%s)余额不足", merchantName)
  872. _ = RobotMsg(content)
  873. //d := ding.Webhook{AccessToken: config.Conf.ThirdPart.DingDing.AccessToken, Secret: config.Conf.ThirdPart.DingDing.Secret}
  874. //_ = d.SendMessage(content)
  875. //SendToDingTalk(content)
  876. }
  877. }
  878. }
  879. // getResultInfos 获取公共校验结果
  880. func getResultInfos(o orm.Ormer, req *apis.ManagementCheckApiReq, reply *apis.ManagementCheckApiReply, minfo *MerchantInfo, isCache bool, appKey string) error {
  881. // 获取商户api原始信息
  882. maps, baseApiId, err := getResultMaps(o, req, minfo, isCache)
  883. defer func() {
  884. maps = nil
  885. }()
  886. reply.MerchantApiInfo.BaseApiId = baseApiId
  887. if err != nil {
  888. return err
  889. }
  890. feeType := 1
  891. // 从原始信息中获取一条可用的记录
  892. matchedRecord, ctr, err := getAvailableApi(o, req, maps, minfo)
  893. if err == errors.IpAddrErr || err == errors.CheckApiNotEnable {
  894. return err
  895. }
  896. //unitPrice := float64(100)
  897. unitPrice := float64(ormStringToFloat(matchedRecord, "unit_price"))
  898. if int(ormStringToInt(matchedRecord, "is_raw_error_code")) == 1 {
  899. reply.MerchantApiInfo.IsRawErrorCode = true
  900. }
  901. // 可欠费金额
  902. arrearage := minfo.Arrearage
  903. if err != nil {
  904. // TODO 检查是否是按收费
  905. if minfo.MerchantType == 2 || minfo.MerchantType == 3 {
  906. err = checkBalance(o, minfo.MerchantType, minfo.Id, unitPrice, arrearage, ctr.info, ctr.comboType)
  907. if err == nil || err == errors.ArrearageError || err == errors.BalanceError {
  908. go balanceCheckSendDingTalk(o, minfo.Id, unitPrice, arrearage, minfo.MerchantType)
  909. }
  910. if err != nil {
  911. return err
  912. }
  913. feeType = 2
  914. } else {
  915. return err
  916. }
  917. }
  918. // 参数解密
  919. isCrypto := int(ormStringToInt(matchedRecord, "is_crypto"))
  920. paramBytes, err := decryptParam(req, []byte(minfo.AppSecret), isCrypto)
  921. if err != nil {
  922. // 商户为普通商户
  923. if feeType == 1 {
  924. decreaseCount(o, ctr.accessCountId)
  925. } else {
  926. // TODO 返钱
  927. increaseBalance(o, 0, minfo.Id, unitPrice, err)
  928. }
  929. return err
  930. }
  931. // 设置部分校验结果
  932. result, err := setCheckResult(ctr, matchedRecord)
  933. if isCrypto == 1 {
  934. result.IsCrypto = true
  935. }
  936. result.AppSecret = minfo.AppSecret
  937. result.MerchantId = minfo.Id
  938. result.BaseApiId = baseApiId
  939. result.DecryptParam = paramBytes
  940. result.UnitPrice = unitPrice
  941. reply.MerchantApiInfo = result
  942. reply.MerchantApiInfo.AccessCountId = ctr.accessCountId
  943. reply.MerchantApiInfo.MerchantDataApiId = ctr.info.mdaId
  944. if err != nil {
  945. // 扣次
  946. if feeType == 1 {
  947. decreaseCount(o, ctr.accessCountId)
  948. } else {
  949. // TODO 返钱
  950. increaseBalance(o, reply.MerchantApiInfo.MerchantDataApiId, minfo.Id, unitPrice, err)
  951. }
  952. return err
  953. }
  954. // 参数公共检查
  955. filters := []apis.BaseApiParamFilter{}
  956. filterString, _ := matchedRecord["filter"].(string)
  957. if filterString != "" {
  958. json.Unmarshal([]byte(filterString), &filters)
  959. }
  960. requestBytes, err := utils.GetRequestParamNew(reply.MerchantApiInfo, filters, paramBytes, filterRuleMap)
  961. if err != nil {
  962. // 扣次
  963. if feeType == 1 {
  964. decreaseCount(o, ctr.accessCountId)
  965. } else {
  966. // TODO 返钱
  967. increaseBalance(o, reply.MerchantApiInfo.MerchantDataApiId, minfo.Id, unitPrice, err)
  968. }
  969. return err
  970. }
  971. err, token := limit.Allow(req.Router, appKey)
  972. if err != nil {
  973. // 扣次
  974. if feeType == 1 {
  975. decreaseCount(o, ctr.accessCountId)
  976. } else {
  977. increaseBalance(o, reply.MerchantApiInfo.MerchantDataApiId, minfo.Id, unitPrice, err)
  978. }
  979. return err
  980. }
  981. reply.MerchantApiInfo.Token = *token
  982. reply.MerchantApiInfo.DecryptParam = requestBytes
  983. reply.MerchantApiInfo.FeeType = feeType
  984. return nil
  985. }
  986. // getReplaceResultInfos 使用内部商户扣费时,获取公共校验结果
  987. func getReplaceResultInfos(o orm.Ormer, req *apis.ManagementCheckApiReq, reply *apis.ManagementCheckApiReply, minfo *MerchantInfo, rminfo *MerchantInfo, isCache bool) error {
  988. // 获取原始商户的api信息(一条或多条记录)
  989. maps, baseApiId, err := getResultMaps(o, req, minfo, isCache)
  990. defer func() {
  991. maps = nil
  992. }()
  993. reply.MerchantApiInfo.BaseApiId = baseApiId
  994. if err != nil {
  995. return err
  996. }
  997. // 获取内部商户的api信息(一条或多条记录)
  998. rmaps, rbaseApiId, err := getResultMaps(o, req, rminfo, isCache)
  999. defer func() {
  1000. rmaps = nil
  1001. }()
  1002. if err != nil {
  1003. return err
  1004. }
  1005. // 获取一条原始商户api信息
  1006. originRecord, err := getOriginMerchantApi(o, req, maps, minfo)
  1007. if err != nil {
  1008. return err
  1009. }
  1010. // 获取一条可用的记录
  1011. replaceRecord, ctr, err := getAvailableApi(o, req, rmaps, rminfo)
  1012. if int(ormStringToInt(replaceRecord, "is_raw_error_code")) == 1 {
  1013. reply.MerchantApiInfo.IsRawErrorCode = true
  1014. }
  1015. if err != nil {
  1016. return err
  1017. }
  1018. // 参数解密
  1019. isCrypto := int(ormStringToInt(originRecord, "is_crypto"))
  1020. paramBytes, err := decryptParam(req, []byte(minfo.AppSecret), isCrypto)
  1021. if err != nil {
  1022. decreaseCount(o, ctr.accessCountId)
  1023. return err
  1024. }
  1025. // 设置部分校验结果
  1026. result, err := setCheckResult(ctr, originRecord)
  1027. if isCrypto == 1 {
  1028. result.IsCrypto = true
  1029. }
  1030. result.AppSecret = minfo.AppSecret
  1031. result.MerchantId = minfo.Id
  1032. result.BaseApiId = baseApiId
  1033. result.DecryptParam = paramBytes
  1034. reply.MerchantApiInfo = result
  1035. reply.MerchantApiInfo.AccessCountId = ctr.accessCountId
  1036. reply.MerchantApiInfo.ReplaceInfo.ReplaceBaseApiId = rbaseApiId
  1037. reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantId = rminfo.Id
  1038. reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantDataApiId = ctr.info.mdaId
  1039. reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantChildApiId = ormStringToInt(replaceRecord, "id")
  1040. reply.MerchantApiInfo.MerchantDataApiId = int64(ormStringToInt(originRecord, "merchant_data_api_id"))
  1041. if err != nil {
  1042. decreaseCount(o, ctr.accessCountId)
  1043. return err
  1044. }
  1045. // 公共参数检查
  1046. filters := []apis.BaseApiParamFilter{}
  1047. filterString, _ := originRecord["filter"].(string)
  1048. if filterString != "" {
  1049. json.Unmarshal([]byte(filterString), &filters)
  1050. }
  1051. requestBytes, err := utils.GetRequestParamNew(reply.MerchantApiInfo, filters, paramBytes, filterRuleMap)
  1052. if err != nil {
  1053. decreaseCount(o, ctr.accessCountId)
  1054. return err
  1055. }
  1056. reply.MerchantApiInfo.DecryptParam = requestBytes
  1057. return nil
  1058. }
  1059. func signCheck(req *apis.ManagementCheckApiReq, secret string, appKey string) error {
  1060. ts := ""
  1061. ok := false
  1062. sign := ""
  1063. if sign, ok = req.Header["sign"]; ok {
  1064. if sign == ""{
  1065. return nil
  1066. }
  1067. }else{
  1068. return nil
  1069. }
  1070. /*if isSign, ok := req.Header["is_sign"]; ok {
  1071. if isSign == "0" {
  1072. if sign == secret {
  1073. return nil
  1074. } else {
  1075. return errors.CheckSignFailed
  1076. }
  1077. }
  1078. }*/
  1079. if ts, ok = req.Header["ts"]; ok == false {
  1080. return errors.ArgsError
  1081. }
  1082. m := map[string]string{}
  1083. json.Unmarshal(req.RequestParam,&m)
  1084. var keyList []string
  1085. for k,_ := range m{
  1086. keyList = append(keyList,k)
  1087. }
  1088. sort.Strings(keyList)
  1089. //fmt.Println("keylist :",keyList)
  1090. signParam := ""
  1091. for _,v := range keyList{
  1092. signParam = signParam + v+m[v]
  1093. }
  1094. //fmt.Println("sign param :",signParam)
  1095. signtext := fmt.Sprintf("%s%s%s%s", appKey,secret, ts,signParam)
  1096. signcomput := utils.MD5(signtext)
  1097. if signcomput != strings.ToLower(sign) {
  1098. return errors.CheckSignFailed
  1099. }
  1100. return nil
  1101. }
  1102. type MerchantInfo struct {
  1103. Id int64 `json:"id"`
  1104. AppSecret string `json:"app_secret"`
  1105. MerchantName string `json:"merchant_name"`
  1106. IpWhitelist string `json:"ip_whitelist"`
  1107. Email string `json:"email"`
  1108. ApiName string `json:"api_name"`
  1109. MerchantChildApiId int64 `json:"merchant_child_api_id"`
  1110. IsHttpCode int `json:"is_http_code"`
  1111. // TODO 获取商户类型
  1112. MerchantType int `json:"merchant_type"`
  1113. Arrearage float64 `json:"arrearage"` // 可欠费金额
  1114. AuthStatus int `json:"auth_status" description:"认证状态0 待认证,1认证通过, 2认证不通过"`
  1115. }
  1116. // replaceMerchantId 将商户id替换为内部商户id
  1117. func replaceMerchantId(req *apis.ManagementCheckApiReq, reply *apis.ManagementCheckApiReply) {
  1118. r, _ := req.Header["replace_app_key"]
  1119. if r == "" {
  1120. return
  1121. }
  1122. if reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantId > 0 {
  1123. reply.MerchantApiInfo.MerchantId = reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantId
  1124. }
  1125. }
  1126. // ipv4ToArray ip字符串转为数组
  1127. func ipv4ToArray(ip string) []int {
  1128. array := strings.Split(ip, ".")
  1129. if len(array) != 4 {
  1130. return nil
  1131. }
  1132. ret := [4]int{}
  1133. var err error
  1134. for i, v := range array {
  1135. ret[i], err = strconv.Atoi(v)
  1136. if err != nil {
  1137. return nil
  1138. }
  1139. }
  1140. return ret[:]
  1141. }
  1142. // checkIpSegment ip段检查, 参数中start, end为白名单中的起止ip, ip为客户实际ip
  1143. func checkIpSegment(start, end, ip string) bool {
  1144. // 开始ip转为ip数组
  1145. startArray := ipv4ToArray(start)
  1146. if len(startArray) != 4 {
  1147. return false
  1148. }
  1149. // 结束ip转为ip数组
  1150. endArray := ipv4ToArray(end)
  1151. if len(endArray) != 4 {
  1152. return false
  1153. }
  1154. // 实际ip转为ip数组
  1155. ipArray := ipv4ToArray(ip)
  1156. if len(ipArray) != 4 {
  1157. return false
  1158. }
  1159. // 判断ip是否在起止ip段中
  1160. for i, v := range startArray {
  1161. if startArray[i] == endArray[i] {
  1162. if ipArray[i] != v {
  1163. return false
  1164. }
  1165. continue
  1166. }
  1167. if ipArray[i] < v || ipArray[i] > endArray[i] {
  1168. return false
  1169. }
  1170. }
  1171. return true
  1172. }
  1173. // checkIpWhite ip白名单检查
  1174. func checkIpWhite(iplist string, ip string) bool {
  1175. array := strings.Split(iplist, ",")
  1176. for _, ipseg := range array {
  1177. ipsegArray := strings.Split(ipseg, "-")
  1178. if len(ipsegArray) == 1 {
  1179. if ipsegArray[0] == ip {
  1180. return true
  1181. }
  1182. continue
  1183. }
  1184. if len(ipsegArray) == 0 {
  1185. continue
  1186. }
  1187. if checkIpSegment(ipsegArray[0], ipsegArray[1], ip) {
  1188. return true
  1189. }
  1190. }
  1191. return false
  1192. }
  1193. // ManagementCheckApi 公共校验
  1194. // 商户调api时会先经过该模块,判断签名,是否过期,是否在白名单内等条件,并返回其他模块所需的api信息
  1195. func ManagementCheckApi(ctx context.Context, req *apis.ManagementCheckApiReq, reply *apis.ManagementCheckApiReply) (err error) {
  1196. o := orm.NewOrm()
  1197. // 处理异常
  1198. defer func() {
  1199. if r := recover(); r != nil {
  1200. err = errors.ServiceError
  1201. l.Error("fatal",
  1202. zap.String("func", "ManagementCheckApi"),
  1203. zap.String("error", fmt.Sprintf("%v", r)))
  1204. replaceMerchantId(req, reply)
  1205. return
  1206. }
  1207. if err != nil {
  1208. replaceMerchantId(req, reply)
  1209. return
  1210. }
  1211. if reply.MerchantApiInfo.BaseApiId == 0 {
  1212. reply.MerchantApiInfo.BaseApiId, _, _, _ = getBaseApiId(o, req)
  1213. if reply.MerchantApiInfo.BaseApiId == 0 {
  1214. err = jsonrpc2.NewJsonError(20005, "api信息获取异常")
  1215. }
  1216. if reply.MerchantApiInfo.MerchantId == 0 {
  1217. err = jsonrpc2.NewJsonError(20005, "商户信息获取异常")
  1218. }
  1219. }
  1220. if replaceKey, _ := req.Header["replace_app_key"]; replaceKey != "" &&
  1221. (reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantChildApiId == 0 ||
  1222. reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantDataApiId == 0 ||
  1223. reply.MerchantApiInfo.ReplaceInfo.ReplaceMerchantId == 0 ||
  1224. reply.MerchantApiInfo.ReplaceInfo.ReplaceBaseApiId == 0) {
  1225. err = jsonrpc2.NewJsonError(20005, "内部商户信息获取异常")
  1226. }
  1227. }()
  1228. reply.MerchantApiInfo.DecryptParam = req.RequestParam
  1229. appKey, ok := req.Header["app_key"]
  1230. if ok == false || appKey == "" {
  1231. return errors.ArgsError
  1232. }
  1233. // 跑批内部商户appkey
  1234. replaceAppKey, _ := req.Header["replace_app_key"]
  1235. // 获取商户信息
  1236. minfo, err := getMerchantInfo(o, appKey)
  1237. if err != nil {
  1238. return err
  1239. }
  1240. if replaceAppKey != "" && replaceAppKey != config.Conf.GdInnerAccount {
  1241. return jsonrpc2.NewJsonError(20005, "内部账户不匹配")
  1242. }
  1243. // 获取内部商户信息
  1244. rminfo, err := getMerchantInfo(o, replaceAppKey)
  1245. if err != nil {
  1246. return err
  1247. }
  1248. reply.MerchantApiInfo.MerchantId = minfo.Id
  1249. reply.MerchantApiInfo.IsHttpCode = minfo.IsHttpCode
  1250. //IP白名单验证
  1251. if minfo.IpWhitelist != "" && replaceAppKey == "" && checkIpWhite(minfo.IpWhitelist, req.Ip) == false {
  1252. return errors.IpAddrErr
  1253. }
  1254. // 签名验证
  1255. reply.MerchantApiInfo.AppSecret = minfo.AppSecret
  1256. err = signCheck(req, minfo.AppSecret, appKey)
  1257. if err != nil {
  1258. return err
  1259. }
  1260. // TODO 限流影响扣次
  1261. // 获取并发请求token
  1262. /*err, token := limit.Allow(req.Router, appKey)
  1263. if err != nil {
  1264. return err
  1265. }
  1266. reply.MerchantApiInfo.Token = *token*/
  1267. // 根据原商户获取检查结果或根据内部商户获取检查结果
  1268. if rminfo == nil {
  1269. if minfo.AuthStatus == 0 {
  1270. // 未认证
  1271. return errors.NotAuthError
  1272. } else if minfo.AuthStatus == 2 {
  1273. // 认证不通过
  1274. return errors.AuthFailError
  1275. }
  1276. err = getResultInfos(o, req, reply, minfo, true, appKey)
  1277. } else {
  1278. err = getReplaceResultInfos(o, req, reply, minfo, rminfo, true)
  1279. }
  1280. reply.MerchantApiInfo.IsHttpCode = minfo.IsHttpCode
  1281. // 商户不存在,尝试非缓存读取信息进行检查
  1282. if err != nil {
  1283. if err == errors.CheckApiInfoNotExist {
  1284. minfo, err = getMerchantInfoFromMysql(o, appKey)
  1285. if err != nil {
  1286. return err
  1287. }
  1288. rminfo, err = getMerchantInfoFromMysql(o, replaceAppKey)
  1289. if err != nil {
  1290. return err
  1291. }
  1292. if rminfo == nil {
  1293. if minfo.AuthStatus == 0 {
  1294. // 未认证
  1295. return errors.NotAuthError
  1296. } else if minfo.AuthStatus == 2 {
  1297. // 认证不通过
  1298. return errors.AuthFailError
  1299. }
  1300. err = getResultInfos(o, req, reply, minfo, false, appKey)
  1301. } else {
  1302. err = getReplaceResultInfos(o, req, reply, minfo, rminfo, false)
  1303. }
  1304. if err != nil {
  1305. return err
  1306. }
  1307. } else {
  1308. return err
  1309. }
  1310. }
  1311. // TODO 限流影响扣次
  1312. // 获取并发请求token
  1313. /*err, token := limit.Allow(req.Router, appKey)
  1314. if err != nil {
  1315. return err
  1316. }*/
  1317. //reply.MerchantApiInfo.Token = *token
  1318. l.Debug(utils.MarshalJsonString(req, reply))
  1319. return nil
  1320. }
  1321. // LoadRedis 从redis中加载api、商户信息
  1322. func LoadRedis() {
  1323. o := orm.NewOrm()
  1324. apiTabs := []apis.TGdApi{}
  1325. merchantTabs := []apis.TGdMerchants{}
  1326. o.QueryTable("t_gd_api").All(&apiTabs)
  1327. o.QueryTable("t_gd_merchants").All(&merchantTabs)
  1328. for _, v := range apiTabs {
  1329. tmp := v
  1330. utils.RedisSet("t_gd_api", v.Method+"-"+v.Router, tmp)
  1331. }
  1332. for _, v := range merchantTabs {
  1333. tmp := v
  1334. utils.RedisSet("t_gd_merchants", v.AppKey, tmp)
  1335. }
  1336. }
  1337. var filterRuleMap = map[int64]apis.FilterRule{}
  1338. // GetFilterRule 获取参数过滤规则
  1339. func GetFilterRule() {
  1340. o := orm.NewOrm()
  1341. tabs := []apis.FilterRule{}
  1342. o.Raw("select * from t_gd_filter_rule").QueryRows(&tabs)
  1343. for _, v := range tabs {
  1344. filterRuleMap[v.RuleId] = v
  1345. }
  1346. }