# coding=utf-8 import time import os from django.conf import settings from django.db import models from django.utils import timezone from apps.WechatTp.models import WechatTp from utils.wx.wechat import WeChat from utils.exceptions import CustomError from utils.file_operation import CertPath from apps.tenant.models import Tenant class WechatApplet(models.Model): AUDIT_SUCCESS = 0 AUDIT_REJECT = 1 AUDITING = 2 RECALL = 3 AUDIT_DELAY = 4 AUDIT_STATUS_CHOICE = ( (AUDIT_SUCCESS, u'审核通过'), (AUDIT_REJECT, u'审核拒绝'), (AUDITING, u'审核中'), (RECALL, u'已撤回'), (AUDIT_DELAY, u'审核延后'), ) tenant = models.ForeignKey(Tenant, verbose_name=u'租户', on_delete=models.PROTECT, editable=False) wechat_tp = models.ForeignKey(WechatTp, verbose_name=u'第三方平台', on_delete=models.PROTECT, editable=False) authorizer_appid = models.CharField(max_length=512, verbose_name=u'授权方appid') secret = models.CharField(max_length=512, verbose_name=u'小程序秘钥', null=True) authorizer_refresh_token = models.CharField(max_length=512, verbose_name=u'刷新令牌') authorizer_access_token = models.CharField(max_length=512, verbose_name=u'令牌') access_token_gtime = models.DateTimeField(verbose_name=u"获取令牌时间") expires_in = models.IntegerField(verbose_name=u'令牌有效期') is_authorize = models.BooleanField(verbose_name=u'是否授权', default=False) message_template_id = models.CharField(max_length=255, verbose_name=u'消息模版ID', null=True) nick_name = models.CharField(max_length=255, verbose_name=u'昵称', default="") head_img = models.CharField(max_length=255, verbose_name=u'头像', default="") principal_name = models.CharField(max_length=255, verbose_name=u'主体名称', default="") qrcode_url = models.CharField(max_length=512, verbose_name=u'二维码', default="") user_version = models.CharField(max_length=512, verbose_name=u'当前程序版本', default="") template_id = models.CharField(max_length=512, verbose_name=u'当前模板', default="") tenant_num = models.CharField(max_length=512, verbose_name=u'商户号', default="") tenant_key = models.CharField(max_length=512, verbose_name=u'商户密钥', default="") apiclient_cert = models.CharField(max_length=255, verbose_name=u'API证书cert', default="") apiclient_key = models.CharField(max_length=255, verbose_name=u'API证书key', default="") auditid = models.CharField(max_length=512, verbose_name=u'待审核ID', default="") wait_audit_version = models.CharField(max_length=512, verbose_name=u'待审核版本', null=True) wait_audit_template = models.CharField(max_length=512, verbose_name=u'待审核模板', null=True) audit_status = models.IntegerField(choices=AUDIT_STATUS_CHOICE, verbose_name=u'审核状态', null=True) reject_reason = models.CharField(max_length=512, verbose_name=u'拒绝原因', default="") class Meta: db_table = "wechat_applet" ordering = ['-id'] index_together = () verbose_name = u"小程序" default_permissions = () @staticmethod def getById(id): try: id = int(id) except: raise CustomError(u'无效的小程序ID!') instance = WechatApplet.objects.filter(pk=id).first() if not instance: raise CustomError(u'未找到相应的小程序!') return instance @staticmethod def getByAppid(appid): instance = WechatApplet.objects.filter(authorizer_appid=appid).first() if not instance: raise CustomError(u'未找到相应的小程序!') return instance @staticmethod def addAuthorizer(wechat_component, authorization_code, tenant): gtime = timezone.now() component_appid = wechat_component.getAppid() component_access_token = wechat_component.getAccessToken() res = WeChat.getAuthorizationInfo(component_appid, authorization_code, component_access_token) ares = WeChat.getAuthorizerInfo(component_appid, res['authorization_info']['authorizer_appid'], component_access_token) authorizer = WechatApplet.getByAppidAndComponentAppid(res['authorization_info']['authorizer_appid'], component_appid) if authorizer: if authorizer.is_authorize: raise CustomError(u'该小程序已授权!') authorizer.refresh(res['authorization_info'], ares['authorizer_info'], gtime, tenant) else: authorizer = WechatApplet.objects.create( tenant=tenant, wechat_tp=wechat_component, authorizer_appid=res['authorization_info']['authorizer_appid'], authorizer_refresh_token=res['authorization_info']['authorizer_refresh_token'], authorizer_access_token=res['authorization_info']['authorizer_access_token'], access_token_gtime=gtime, expires_in=res['authorization_info']['expires_in'], principal_name=ares['authorizer_info']['principal_name'], nick_name=ares['authorizer_info']['nick_name'], head_img=ares['authorizer_info']['head_img'], qrcode_url=ares['authorizer_info']['qrcode_url'], is_authorize=True ) # 设置服务器域名 authorizer.setDomain() return authorizer @staticmethod def getByAppidAndComponentAppid(appid, component_appid): authorizer = WechatApplet.objects.filter(authorizer_appid=appid, wechat_tp_id__component_appid=component_appid).first() return authorizer def getComponent(self): return self.wechat_tp def getAccessToken(self): if self.authorizer_access_token: last_time = time.mktime(self.access_token_gtime.timetuple()) + self.expires_in now = time.mktime(timezone.now().timetuple()) if last_time > now: return self.authorizer_access_token if not self.authorizer_refresh_token: return '' gtime = timezone.now() component = self.getComponent() res = WeChat.getAuthorizerAccessToken(component.getAppid(), self.authorizer_appid, self.authorizer_refresh_token, component.getAccessToken()) self.refreshAccessToken(gtime, res['authorizer_access_token'], res['expires_in'], res['authorizer_refresh_token']) return self.authorizer_access_token def revoke(self): tenant = self.tenant tenant.is_bind_app = False tenant.save() self.is_authorize = False self.save() def refreshAccessToken(self, gtime, access_token, expires_in, refresh_token): self.authorizer_access_token = access_token self.access_token_gtime = gtime self.expires_in = expires_in self.authorizer_refresh_token = refresh_token self.save() def refresh(self, authorization_info, authorizer_info, access_token_gtime, tenant): self.authorizer_refresh_token = authorization_info['authorizer_refresh_token'] self.authorizer_access_token = authorization_info['authorizer_access_token'] self.access_token_gtime = access_token_gtime self.expires_in = authorization_info['expires_in'] self.principal_name = authorizer_info['principal_name'] self.nick_name = authorizer_info['nick_name'] self.head_img = authorizer_info['head_img'] self.qrcode_url = authorizer_info['qrcode_url'] self.is_authorize = True self.tenant = tenant self.save() def uploadCode(self, template_id, user_version, user_desc): WeChat.commitCode(self.getAccessToken(), template_id, user_version, user_desc) result = WeChat.submitAuditCode(self.getAccessToken()) self.auditid = result['auditid'] self.wait_audit_version = user_version self.wait_audit_template = template_id self.audit_status = WechatApplet.AUDITING self.reject_reason = '' self.save() def refreshAuditStatus(self): result = WeChat.getLastSubmitAuditCodeStatus(self.getAccessToken()) if self.auditid == str(result['auditid']): if result['status'] == WechatApplet.AUDIT_SUCCESS: self.weapp_audit_success() elif result['status'] == WechatApplet.AUDIT_REJECT: self.weapp_audit_fail(result['reason']) elif result['status'] == WechatApplet.RECALL: self.weapp_audit_recall() elif result['status'] == WechatApplet.AUDIT_DELAY: self.weapp_audit_delay(result['reason']) def weapp_audit_recall(self): self.auditid = '' self.wait_audit_template = None self.wait_audit_version = None self.audit_status = None self.reject_reason = '' self.save() def weapp_audit_success(self): self.user_version = self.wait_audit_version self.template_id = self.wait_audit_template self.auditid = '' self.wait_audit_template = None self.wait_audit_version = None self.audit_status = None self.reject_reason = '' self.save() def weapp_audit_fail(self, reason): self.audit_status = WechatApplet.AUDIT_REJECT self.reject_reason = reason self.save() def weapp_audit_delay(self, reason): self.audit_status = WechatApplet.AUDIT_DELAY self.reject_reason = reason self.save() def setDomain(self): requestdomain = uploaddomain = downloaddomain = ['https://baoxiu360.top', ] wsrequestdomain = [] WeChat.modify_domain(self.getAccessToken(), 'set', requestdomain, wsrequestdomain, uploaddomain, downloaddomain) def addPlugin(self): result = WeChat.addPlugin(self.getAccessToken()) return result def releaseApplet(self): result = WeChat.releaseCode(self.getAccessToken()) return result def getMsgTemplateId(self): if self.message_template_id: return self.message_template_id templates = WeChat.getTemplateList(self.getAccessToken()) for template in templates: if template['title'] == u'维修完成通知': self.message_template_id = template['priTmplId'] self.save() return template['priTmplId'] return '' def sendMsg(self, openid, name, address, fault_des, no): template_id = self.getMsgTemplateId() if not template_id: return time = timezone.now().strftime('%Y-%m-%d %H:%M:%S') data = { 'time5': {'value': time}, 'name4':{'value':name}, 'thing3':{'value':address}, 'thing2':{'value': fault_des}, 'character_string7':{'value': no}, } page = 'pages/repairList/repairList?sort=baoxiu&name=我的报修' WeChat.sendSubscribeMessage(self.getAccessToken(), openid, template_id, page, data) def upload_cert_file(self, file): path = 'zzly_xcx_cert/%d/' % self.id upload_path = CertPath(path) filename = '%s%s' % (upload_path.path, file.name) full_filename = "%s/%s" % (settings.MEDIA_ROOT, filename) with open(full_filename, 'wb+') as destination: for chunk in file.chunks(): destination.write(chunk) if file.name == 'apiclient_cert.pem': self.apiclient_cert = full_filename elif file.name == 'apiclient_key.pem': self.apiclient_key = full_filename self.save()