WechatService.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. import random
  2. from DCbackend.settings import IPINFO
  3. from backend.Service.AdminService import AdminService
  4. from backend.Service.SMSService import SMSService
  5. from base import logger
  6. import re
  7. import requests
  8. from django.core.paginator import Paginator
  9. from django.db import transaction
  10. from DCbackend import settings
  11. from DCbackend.utils.common import success, fail, pageData
  12. from backend.Form.WechatUserForm import WechatUserForm
  13. from backend.models import WechatUser, Admin
  14. from django.core.cache import cache
  15. #微信公众号
  16. class WechatService:
  17. @staticmethod
  18. @transaction.atomic
  19. def insertInfo(request):
  20. form = WechatUserForm(request.POST)
  21. if form.is_valid():
  22. form.save()
  23. return success("保存成功")
  24. else:
  25. return fail(form.errors)
  26. @staticmethod
  27. def getInfoList(request):
  28. page = request.POST.get("page")
  29. pageSize = request.POST.get("pageSize")
  30. if page is None:
  31. page = 1
  32. if pageSize is None:
  33. pageSize = 10
  34. where = {}
  35. name = request.POST.get("name", '')
  36. if name:
  37. where["name__icontains"] = name
  38. status = request.POST.get("status")
  39. if status:
  40. where['status'] = status
  41. paginator = Paginator(WechatUser.objects.filter(**where).exclude(status=4).order_by("-id"),
  42. pageSize) # 每页显示10条数据
  43. page_obj = paginator.get_page(page)
  44. dataList = []
  45. for item in page_obj:
  46. info = WechatService.getDetail(item)
  47. dataList.append(info)
  48. return success(pageData(page, pageSize, paginator.num_pages, paginator.count, dataList))
  49. @staticmethod
  50. def getDetail(item: WechatUser):
  51. return {
  52. "id": item.id,
  53. 'name': item.name,
  54. 'nikeName': item.nikeName,
  55. 'phone': item.phone,
  56. 'openid': item.openid,
  57. 'age': item.age,
  58. 'level': item.level,
  59. 'user_id': item.user_id,
  60. 'mini_url': item.mini_url,
  61. 'examine': item.examine,
  62. 'status': item.status,
  63. 'source': item.source
  64. }
  65. @staticmethod
  66. @transaction.atomic
  67. def updateUserInfo(request):
  68. openid = request.POST.get("openid")
  69. wechatUser = WechatUser.objects.filter(openid=openid).exclude(status=4).first()
  70. if not wechatUser:
  71. return fail("未登录小程序")
  72. id_card = request.POST.get("id_card")
  73. if WechatService.is_valid_id(id_card):
  74. wechatUser.id_card = id_card
  75. else:
  76. return fail("身份证格式错误")
  77. wechatUser.name = request.POST.get("name")
  78. wechatUser.nikeName = request.POST.get("nikeName")
  79. wechatUser.age = request.POST.get("age")
  80. wechatUser.mini_url = request.POST.get("mini_url")
  81. wechatUser.phone = request.POST.get("purePhoneNumber")
  82. wechatUser.examine = request.POST.get("examine")
  83. wechatUser.save()
  84. return success("提交审核成功")
  85. @staticmethod
  86. @transaction.atomic
  87. def updateNikeName(request):
  88. openid = request.POST.get("openid")
  89. wechatUser = WechatUser.objects.filter(openid=openid).exclude(status=4).first()
  90. if not wechatUser:
  91. return fail("未登录小程序")
  92. wechatUser.nikeName = request.POST.get("nikeName")
  93. wechatUser.save()
  94. return success("提交审核成功")
  95. @staticmethod
  96. @transaction.atomic
  97. def to_examine(request):
  98. id = request.POST.get("id")
  99. if not id:
  100. return fail("id为空")
  101. wechatUser = WechatUser.objects.filter(id=id).exclude(status=4).first()
  102. if not wechatUser:
  103. return fail("无此小程序用户信息")
  104. level = request.POST.get("level")
  105. wechatUser.level = level
  106. wechatUser.examine = 1
  107. wechatUser.save()
  108. return success("审核完成")
  109. @staticmethod
  110. def is_valid_id(id_card):
  111. pattern = r'^[1-9]\d{5}(18|19|20|21|22)?\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}(\d|[Xx])$'
  112. return bool(re.match(pattern, id_card))
  113. @staticmethod
  114. def deleteUserInfo(request):
  115. id = request.POST.get("id")
  116. wechatUser = WechatUser.objects.filter(id=id).first()
  117. if wechatUser:
  118. wechatUser.status = 4
  119. wechatUser.save()
  120. return success("删除成功")
  121. else:
  122. return fail("删除失败")
  123. @staticmethod
  124. def get_access_token(request):
  125. try:
  126. # 首先尝试从缓存中获取 access_token
  127. access_token = cache.get('wechat_access_token')
  128. if access_token:
  129. return access_token
  130. # return success("m没有获取到")
  131. # 如果缓存中没有,则从微信服务器获取新的 access_token
  132. appid = settings.WECHAT_APPID
  133. secret = settings.WECHAT_SECRET
  134. url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}"
  135. response = requests.get(url)
  136. result = response.json()
  137. if 'access_token' in result:
  138. access_token = result['access_token']
  139. expires_in = result.get('expires_in', 7200) # 默认7200秒
  140. # 将 access_token 存入缓存,有效期设置比微信给的稍短一些
  141. cache.set('wechat_access_token', access_token, expires_in - 200)
  142. return access_token
  143. else:
  144. error_msg = result.get('errmsg', '未知错误')
  145. return fail(f"获取access_token失败: {error_msg}")
  146. except Exception as e:
  147. return fail(f"获取access_token时发生错误: {str(e)}")
  148. @staticmethod
  149. @transaction.atomic
  150. def wechatLogin(request):
  151. try:
  152. js_code = request.POST.get("code")
  153. if not js_code:
  154. return fail(f"缺少code参数,{js_code}")
  155. appid = settings.WECHAT_APPID
  156. secret = settings.WECHAT_SECRET
  157. url = "https://api.weixin.qq.com/sns/jscode2session"
  158. params = {
  159. "appid": appid,
  160. "secret": secret,
  161. "js_code": js_code,
  162. "grant_type": "authorization_code"
  163. }
  164. response = requests.get(url, params=params)
  165. result = response.json()
  166. if 'openid' in result:
  167. # 创建新的WechatUser对象
  168. wechat_user, created = WechatUser.objects.get_or_create(
  169. openid=result['openid'],
  170. source="mini",
  171. defaults={
  172. 'level': 1,
  173. 'status': 5 # 假设1表示活跃状态
  174. }
  175. )
  176. return success({
  177. "openid": result['openid'],
  178. "session_key": result.get('session_key'),
  179. "unionid": result.get('unionid'),
  180. "user_id": wechat_user.id,
  181. "is_new_user": created
  182. }, "微信登录成功")
  183. else:
  184. error_msg = result.get('errmsg', '未知错误')
  185. return fail(f"微信登录失败: {error_msg}")
  186. except Exception as e:
  187. return fail(f"微信登录过程中发生错误: {str(e)}")
  188. @staticmethod
  189. @transaction.atomic
  190. def getUserPhoneNumber(request):
  191. try:
  192. access_token = WechatService.get_access_token(request)
  193. if not access_token:
  194. return fail("access_token为空")
  195. code = request.POST.get("code")
  196. if not code:
  197. return fail("缺少code参数")
  198. openid = request.POST.get("openid")
  199. if not openid:
  200. return fail("缺少openid")
  201. url = f"https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={access_token}"
  202. data = {
  203. "code": code
  204. }
  205. response = requests.post(url, json=data)
  206. result = response.json()
  207. if result.get('errcode') == 0:
  208. phone_info = result.get('phone_info', {})
  209. purePhoneNumber = phone_info.get('purePhoneNumber')
  210. WechatUser.objects.filter(openid=openid, source="mini").update(phone=purePhoneNumber)
  211. return success({
  212. "phoneNumber": phone_info.get('phoneNumber'),
  213. "purePhoneNumber": purePhoneNumber,
  214. "countryCode": phone_info.get('countryCode'),
  215. }, "获取用户手机号成功")
  216. else:
  217. error_msg = result.get('errmsg', '未知错误')
  218. return fail(f"获取用户手机号失败: {error_msg}")
  219. except Exception as e:
  220. return fail(f"获取用户手机号过程中发生错误: {str(e)}")
  221. @staticmethod
  222. def getOpenPid(request):
  223. try:
  224. access_token_result = WechatService.get_access_token(request)
  225. if not access_token_result:
  226. return fail("获取access_token失败")
  227. access_token = access_token_result
  228. code = request.POST.get("code")
  229. if not code:
  230. return fail("缺少code参数")
  231. url = f"https://api.weixin.qq.com/wxa/getpluginopenpid?access_token={access_token}"
  232. data = {
  233. "code": code
  234. }
  235. response = requests.post(url, json=data)
  236. result = response.json()
  237. if result.get('errcode') == 0:
  238. openpid = result.get('openpid')
  239. return success(openpid, "获取插件用户openPid成功")
  240. else:
  241. error_msg = result.get('errmsg', '未知错误')
  242. return fail(f"获取插件用户openPid失败: {error_msg}")
  243. except Exception as e:
  244. return fail(f"获取插件用户openPid过程中发生错误: {str(e)}")
  245. @staticmethod
  246. def getUserInfo(request):
  247. openid = request.POST.get("openid")
  248. if not openid:
  249. return fail("缺少 openid 参数")
  250. try:
  251. user = WechatUser.objects.filter(openid=openid).exclude(status=4).first()
  252. if not user:
  253. return fail("未找到用户信息")
  254. user_info = {
  255. "id": user.id,
  256. "name": user.name,
  257. "nikeName": user.nikeName,
  258. "phone": user.phone,
  259. "openid": user.openid,
  260. "age": user.age,
  261. "level": user.level,
  262. "user_id": user.user_id,
  263. "id_card": user.id_card,
  264. "mini_url": user.mini_url,
  265. "examine": user.examine,
  266. "status": user.status,
  267. "source": user.source,
  268. }
  269. return success(user_info)
  270. except WechatUser.DoesNotExist:
  271. return fail("用户不存在")
  272. @staticmethod
  273. def getKbmUrl(request):
  274. openid = request.POST.get("openid")
  275. # waibu = "https://ai.raycos.net/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false"
  276. # neibu = "https://ai.raycos.net/api/v1/run/9263c538-2cd2-4c1b-8c9a-3bb986920d6d?stream=false"
  277. #
  278. info = WechatUser.objects.filter(openid=openid).exclude(status=4).first()
  279. waibu = {}
  280. waibuurl = "http://ai.raycos.net/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false"
  281. waibutweaks = {
  282. "ChatInput-dDbhW": {
  283. "sender": info.openid,
  284. "sender_name": info.openid
  285. },
  286. "Prompt-1stgH": {},
  287. "ChatOutput-b1zWw": {},
  288. "OllamaModel-5n7vc": {},
  289. "Milvus-1X7fT": {},
  290. "OllamaEmbeddings-V29wK": {},
  291. "Memory-GrHZr": {
  292. "session_id": info.openid
  293. },
  294. "ParseData-0dk9n": {}
  295. }
  296. waibu["url"] = waibuurl
  297. waibu["tweaks"] = waibutweaks
  298. neibu = {}
  299. neibuurl = "https://ai.raycos.net/api/v1/run/9263c538-2cd2-4c1b-8c9a-3bb986920d6d?stream=false"
  300. neibutweaks = {
  301. "ChatInput-NYqTq": {
  302. "sender": info.openid,
  303. "sender_name": info.openid
  304. },
  305. "Prompt-oVfSC": {},
  306. "ChatOutput-sA5Uc": {},
  307. # "SplitText-GvztW": {},
  308. # "File-rHitZ": {},
  309. "OllamaModel-UxNZ1": {},
  310. "Milvus-fRZVH": {},
  311. "OllamaEmbeddings-lHoKv": {},
  312. "Memory-ZBrXL": {
  313. "session_id": info.openid
  314. },
  315. "ParseData-ZmaJQ": {}
  316. }
  317. neibu["url"] = neibuurl
  318. neibu["tweaks"] = neibutweaks
  319. if not openid:
  320. return success(waibu, "普通用户返回外部知识库链接")
  321. if not info:
  322. return success(waibu, "普通用户返回外部知识库链接")
  323. if info.level == 1:
  324. return success(waibu, "普通用户返回外部知识库链接")
  325. return success(neibu, "内部人员返回内部知识库链接")
  326. @staticmethod
  327. @transaction.atomic
  328. def updateBackground(request):
  329. id = request.POST.get("id")
  330. wechatUser = WechatUser.objects.filter(id=id).first()
  331. if wechatUser:
  332. wechatUser.name = request.POST.get("name")
  333. wechatUser.nikeName = request.POST.get("nikeName")
  334. wechatUser.phone = request.POST.get("phone")
  335. wechatUser.openid = request.POST.get("openid")
  336. wechatUser.age = request.POST.get("age")
  337. wechatUser.level = request.POST.get("level")
  338. wechatUser.user_id = request.POST.get("user_id")
  339. wechatUser.id_card = request.POST.get("id_card")
  340. wechatUser.mini_url = request.POST.get("mini_url")
  341. wechatUser.status = request.POST.get("status")
  342. wechatUser.save()
  343. return success("修改成功")
  344. else:
  345. return fail("修改失败")
  346. @staticmethod
  347. def pcSMS(request):
  348. phone = request.POST.get("phone")
  349. if not phone:
  350. return fail("手机号为空")
  351. verification_code = ''.join(random.choices('0123456789', k=6))
  352. result = SMSService.send_sms(phone, verification_code)
  353. if result and result.get('Code') == 'OK':
  354. cache.set(f"sms_code:{phone}", verification_code, timeout=3*60)
  355. return success("验证码发送成功")
  356. else:
  357. return fail("验证码发送失败")
  358. #校验验证码
  359. @staticmethod
  360. def codeCheckout(request):
  361. phone = request.POST.get("phone")
  362. if not phone:
  363. return fail("手机号为空")
  364. verification_code = request.POST.get("verification_code")
  365. if not verification_code:
  366. return fail("验证码为空")
  367. stored_code = cache.get(f"sms_code:{phone}")
  368. if verification_code == stored_code:
  369. return success(phone,"验证成功")
  370. else:
  371. return fail("验证失败,请检查验证码和手机号")
  372. @staticmethod
  373. @transaction.atomic
  374. def pcLoging(request):
  375. try:
  376. phone = request.POST.get("phone")
  377. if not phone:
  378. return fail("手机号为空")
  379. info, created = WechatUser.objects.get_or_create(
  380. phone=phone,
  381. source="pc",
  382. defaults={
  383. 'level': 1,
  384. 'status': 5
  385. }
  386. )
  387. waibu = {
  388. "url": f"http://{IPINFO}:7860/api/v1/run/951e3ba4-c66a-496c-9497-7dbddc2647f8?stream=false",
  389. "tweaks": {
  390. "ChatInput-dDbhW": {
  391. "sender": info.phone,
  392. "sender_name": info.phone
  393. },
  394. "Prompt-1stgH": {},
  395. "ChatOutput-b1zWw": {},
  396. "OllamaModel-5n7vc": {},
  397. "Milvus-1X7fT": {},
  398. "OllamaEmbeddings-V29wK": {},
  399. "Memory-GrHZr": {
  400. "session_id": info.phone
  401. },
  402. "ParseData-0dk9n": {}
  403. }
  404. }
  405. return success(waibu,"登录成功")
  406. except Exception as e:
  407. logger.info(f"登录异常:{e}")
  408. return fail(str(e))
  409. @staticmethod
  410. def pcInnerAi(request):
  411. token = request.POST.get("token")
  412. if not token:
  413. return fail("token为空")
  414. adminInfo = AdminService.verify_token(token)
  415. if not adminInfo:
  416. return fail("查无此人")
  417. uid = adminInfo.id
  418. neibu = {
  419. "url": f"http://{IPINFO}:7860/api/v1/run/ed188be9-5bf5-4194-b35d-6a583a44452d?stream=false",
  420. "tweaks":{
  421. "ChatInput-aJZLS": {
  422. "sender": str(uid),
  423. "sender_name": str(uid)
  424. },
  425. "Prompt-hc9OF": {},
  426. "ChatOutput-5HfMA": {},
  427. # "SplitText-GvztW": {},
  428. # "File-rHitZ": {},
  429. "OllamaModel-kxuW7": {},
  430. "Milvus-q5ixS": {},
  431. "OllamaEmbeddings-ANKWT": {},
  432. "Memory-FHaLh": {
  433. "session_id": str(uid)
  434. },
  435. "ParseData-tNR5t": {}
  436. }
  437. }
  438. return success(neibu,"内部链接")