예제 #1
0
    def get(self, siteid, out_trade_no):
        appid = self.get_argument('appid')
        appinfo = self.storage.get_app_info(appid=appid)
        if not appinfo:
            self.send_response(err_code=3201)
            raise tornado.gen.Return()

        req_data = {
            'appid': appid,
            'mch_id': appinfo.get('mch_id'),
            'transaction_id': '',
            'out_trade_no': out_trade_no
        }
        req_key = appinfo['apikey']
        security.add_sign(req_data, req_key)

        try:
            resp = yield httputils.post_dict(url=url.mch_order_query,
                                             data=req_data,
                                             data_type='xml')
        except tornado.httpclient.HTTPError:
            self.send_response(err_code=1001)
            raise tornado.gen.Return()

        resp_data = self.parse_payment_resp(resp, req_key)
        if resp_data:
            post_resp_data = dtools.transfer(resp_data,
                                             copys=[
                                                 'appid', 'openid',
                                                 'trade_state', 'out_trade_no',
                                                 'total_fee', 'transaction_id',
                                                 'time_end'
                                             ])
            self.send_response(post_resp_data)
예제 #2
0
def _wechat_api_call(method, appid, fn_url, fn_data=None, retry=0):
    token_result = yield _get_access_token(appid, refresh=(retry != 0))
    if token_result['err_code'] != 0:
        raise tornado.gen.Return(token_result)
    token = token_result['data']['access_token']
    logging.info('access_token: %s', token)
    try:
        if method == 'GET':
            resp = yield httputils.get_dict(url=fn_url,
                                            data=dict(fn_data or {},
                                                      access_token=token))
        elif method == 'POST':
            resp = yield httputils.post_dict(url=build_url(
                fn_url, {'access_token': token}),
                                             data=fn_data,
                                             data_type='json')
        else:
            return
    except tornado.httpclient.HTTPError:
        raise tornado.gen.Return({'err_code': 1001})
    result = _parse_wechat_resp(resp)
    if result['err_code'] == 1004 and retry < 3:
        result = yield _wechat_api_call(appid, fn_url, fn_data, retry + 1)
        raise tornado.gen.Return(result)
    else:
        raise tornado.gen.Return(result)
예제 #3
0
def _wechat_api_call(method, appid, fn_url, fn_data=None, retry=0):
    token_result = yield _get_access_token(appid, refresh=(retry != 0))
    if token_result['err_code'] != 0:
        raise tornado.gen.Return(token_result)
    token = token_result['data']['access_token']
    logging.info('access_token: %s', token)
    try:
        if method == 'GET':
            resp = yield httputils.get_dict(
                url=fn_url,
                data=dict(fn_data or {}, access_token=token)
            )
        elif method == 'POST':
            resp = yield httputils.post_dict(
                url=build_url(fn_url, {
                    'access_token': token
                }),
                data=fn_data,
                data_type='json'
            )
        else:
            return
    except tornado.httpclient.HTTPError:
        raise tornado.gen.Return({'err_code': 1001})
    result = _parse_wechat_resp(resp)
    if result['err_code'] == 1004 and retry < 3:
        result = yield _wechat_api_call(appid, fn_url, fn_data, retry + 1)
        raise tornado.gen.Return(result)
    else:
        raise tornado.gen.Return(result)
예제 #4
0
    def post(self):
        req_data = dtools.transfer(self.post_args,
                                   copys=[
                                       'appid', 'result_code', 'err_code_des',
                                       'out_trade_no', 'total_fee', 'openid',
                                       'transaction_id', 'time_end'
                                   ])
        req_data['unionid'] = self.storage.get_user_info(
            appid=req_data['appid'],
            openid=req_data['openid'],
            select_key='unionid')
        attach = dict(
            [t.split('=') for t in self.post_args['attach'].split(',')])
        site_info = self.storage.get_site_info(siteid=attach['siteid'])
        req_key = site_info['sitekey']
        security.add_sign(req_data, req_key)

        try:
            resp = yield httputils.post_dict(url=site_info['pay_notify_url'],
                                             data=req_data)
        except tornado.httpclient.HTTPError:
            self.send_response(err_code=9002)
            return

        if resp.code == 200:
            try:
                resp_data = json.loads(resp.body.decode('utf8'))
                self.send_response(err_code=0 if resp_data.
                                   get('return_code') == 'SUCCESS' else 1)
            except ValueError:
                self.send_response(err_code=9101)
        else:
            self.send_response(err_code=9002)
예제 #5
0
 def _post_data(self, appid, post_url, data, content_type, **kwargs):
     headers = dict(_default_headers, **{
         'Referer': kwargs.get('referer', url.mp_base),
         'Cookie': self._build_cookies(appid),
         'Content-Type': content_type,
     })
     resp = yield httputils.post_dict(url=post_url, data=data, data_type='raw', headers=headers)
     if resp.code == 200:
         self._set_cookies(appid, resp.headers)
     raise tornado.gen.Return(resp)
예제 #6
0
 def _post_form(self, appid, post_url, data, **kwargs):
     headers = dict(_default_headers, **{
         'Referer': kwargs.get('referer', url.mp_base),
         'Cookie': self._build_cookies(appid),
         'Accept': kwargs.get('accept', 'application/json, text/javascript, */*; q=0.01'),
     })
     resp = yield httputils.post_dict(url=post_url, data=data, headers=headers)
     if resp.code == 200:
         self._set_cookies(appid, resp.headers)
     raise tornado.gen.Return(resp)
예제 #7
0
 def _post_data(self, appid, post_url, data, content_type, **kwargs):
     headers = dict(
         _default_headers, **{
             'Referer': kwargs.get('referer', url.mp_base),
             'Cookie': self._build_cookies(appid),
             'Content-Type': content_type,
         })
     resp = yield httputils.post_dict(url=post_url,
                                      data=data,
                                      data_type='raw',
                                      headers=headers)
     if resp.code == 200:
         self._set_cookies(appid, resp.headers)
     raise tornado.gen.Return(resp)
예제 #8
0
 def notify(self, status, message, openid):
     req_data = {'appid': consts.appid,
                 'openid': openid,
                 'msg_type': 'text'}
     if status == 0:
         req_data['content'] = message
     elif status == 1:
         req_data['content'] = consts.image_data_err_msg
     elif status == 2:
         req_data['content'] = consts.image_resolution_err_msg
     else:
         req_data['content'] = consts.image_fail_err_msg
     security.add_sign(req_data, consts.sitekey)
     response = yield httputils.post_dict(url=consts.wechat_msgs_url, data=req_data)
     logging.info('notify result: %s', response.body)
     raise tornado.gen.Return(response)
예제 #9
0
 def _post_form(self, appid, post_url, data, **kwargs):
     headers = dict(
         _default_headers, **{
             'Referer':
             kwargs.get('referer', url.mp_base),
             'Cookie':
             self._build_cookies(appid),
             'Accept':
             kwargs.get('accept',
                        'application/json, text/javascript, */*; q=0.01'),
         })
     resp = yield httputils.post_dict(url=post_url,
                                      data=data,
                                      headers=headers)
     if resp.code == 200:
         self._set_cookies(appid, resp.headers)
     raise tornado.gen.Return(resp)
예제 #10
0
def process_astrometry(request):
    if request['msg_id'] in astrometry_tasks:
        raise tornado.gen.Return(None)
    response = yield httputils.post_dict(
        url=consts.astrometry_url,
        data={'pic_url': request.get('pic_url', ''),
              'openid': request.get('openid')})
    if response.code == 200:
        astrometry_tasks.append(request['msg_id'])
        if len(astrometry_tasks) > 100:
            astrometry_tasks.pop(0)
        raise tornado.gen.Return({
            'msg_type': 'text',
            'content': consts.image_response,
            'tag': 'astrometry'
        })
    else:
        raise tornado.gen.Return(None)
예제 #11
0
    def send_request(self, service, args=None, retry=0, retry_limit=1):
        if retry > retry_limit:
            raise tornado.gen.Return(None)

        if self.session and args:
            args.update({'session': self.session})
        json_data = json.dumps(args or {})
        url = consts.astrometry_net_api_url + service
        logging.info('Sending to URL: %s', url)
        logging.info('Sending json: %s', json_data)
        try:
            response = yield httputils.post_dict(url=url, data={'request-json': json_data})
        except tornado.web.HTTPError:
            response = yield self.send_request(service, args, retry + 1, retry_limit)
            raise tornado.gen.Return(response)
        if response.code == 200:
            raise tornado.gen.Return(json.loads(response.body.decode('utf8')))
        else:
            response = yield self.send_request(service, args, retry + 1, retry_limit)
            raise tornado.gen.Return(response)
예제 #12
0
def process_astrometry(request):
    if request['msg_id'] in astrometry_tasks:
        raise tornado.gen.Return(None)
    response = yield httputils.post_dict(url=consts.astrometry_url,
                                         data={
                                             'pic_url':
                                             request.get('pic_url', ''),
                                             'openid': request.get('openid')
                                         })
    if response.code == 200:
        astrometry_tasks.append(request['msg_id'])
        if len(astrometry_tasks) > 100:
            astrometry_tasks.pop(0)
        raise tornado.gen.Return({
            'msg_type': 'text',
            'content': consts.image_response,
            'tag': 'astrometry'
        })
    else:
        raise tornado.gen.Return(None)
예제 #13
0
    def get(self, siteid, out_trade_no):
        appid = self.get_argument('appid')
        appinfo = self.storage.get_app_info(appid=appid)
        if not appinfo:
            self.send_response(err_code=3201)
            raise tornado.gen.Return()

        req_data = {
            'appid': appid,
            'mch_id': appinfo.get('mch_id'),
            'transaction_id': '',
            'out_trade_no': out_trade_no
        }
        req_key = appinfo['apikey']
        security.add_sign(req_data, req_key)

        try:
            resp = yield httputils.post_dict(url=url.mch_order_query, data=req_data, data_type='xml')
        except tornado.httpclient.HTTPError:
            self.send_response(err_code=1001)
            raise tornado.gen.Return()

        resp_data = self.parse_payment_resp(resp, req_key)
        if resp_data:
            post_resp_data = dtools.transfer(
                resp_data,
                copys=[
                    'appid',
                    'openid',
                    'trade_state',
                    'out_trade_no',
                    'total_fee',
                    'transaction_id',
                    'time_end'
                ]
            )
            self.send_response(post_resp_data)
예제 #14
0
    def post(self):
        post_args = dtools.xml2dict(self.request.body.decode('utf8'))
        logging.info(post_args)
        appinfo = self.storage.get_app_info(openid=post_args['ToUserName'])
        appid = appinfo['appid']
        crypter = None
        if appinfo['is_encrypted']:
            crypter = Prpcrypt(appinfo['encoding_key'])
            plain_xml = crypter.decrypt(post_args['Encrypt'], appid)
            if plain_xml:
                post_args = dtools.xml2dict(plain_xml)
            else:
                # TODO: error
                pass
        req_data = dtools.transfer(
            post_args,
            renames=[
                ('FromUserName', 'openid'),
                ('MsgType', 'msg_type'),
                ('MsgId', 'msg_id'),
                ('CreateTime', 'msg_time'),
                ('Content', 'content'),
                ('Event', 'event_type'),
                ('PicUrl', 'pic_url'),
                ('Location_X', 'latitude'),
                ('Location_Y', 'longitude'),
                ('Label', 'label'),
                ('MediaId', 'media_id')],
            allow_empty=False
        )
        logging.info('message from tencent: %s', req_data)
        req_data['appid'] = appid
        site_info = self.storage.get_site_info(appinfo['siteid'])
        security.add_sign(req_data, site_info['sitekey'])
        try:
            resp = yield httputils.post_dict(
                url=site_info['msg_notify_url'],
                data=req_data)
        except tornado.httpclient.HTTPError:
            self.send_response(err_code=9002)
            raise tornado.gen.Return()
        if resp.code != 200:
            self.send_response(err_code=9002)
            raise tornado.gen.Return()

        try:
            resp_data = json.loads(resp.body.decode('utf8'))
            if resp_data.get('err_code') == 0:
                wx_resp = build_response(from_id=post_args['ToUserName'],
                                         to_id=post_args['FromUserName'],
                                         data=resp_data.get('data'))
                if appinfo['is_encrypted']:
                    wx_resp = encrypt_data(wx_resp, crypter, appid)
                self.send_response(wx_resp)
            else:
                self.send_response(err_code=9003)
        except ValueError:
            self.send_response(err_code=9101)

        # Add basic user info
        openid = req_data['openid']
        user_info = self.storage.get_user_info(appid=appid, openid=openid)
        if not user_info:
            if appinfo['is_verified']:
                yield wxclient.update_user_info(appid, openid)
            else:
                self.storage.add_user_info({
                    'appid': appid,
                    'openid': openid,
                    'fakeid': openid
                })

        # Use mock_browser to get user info
        if not appinfo['is_protected'] and (not user_info or not user_info.get('nickname')) and not req_data.get(
                'event_type'):
            user_resp = yield wxclient.mock_browser.find_user(
                appid=appid,
                timestamp=int(req_data['msg_time']),
                mtype=req_data['msg_type'],
                content=req_data.get('content', '')
            )
            if user_resp['err_code'] == 0:
                more_info = {
                    'appid': appid,
                    'openid': openid,
                    'fakeid': user_resp['data']['fakeid'],
                    'nickname': user_resp['data']['nick_name']
                }
                if not appinfo['is_verified']:
                    contact_resp = yield wxclient.mock_browser.get_contact_info(
                        appid=appid,
                        fakeid=user_resp['data']['fakeid'],
                        msg_id=user_resp['data']['id']
                    )
                    contact_info = contact_resp['data']['contact_info']
                    more_info.update({
                        'sex': contact_info['gender'],
                        'city': contact_info['city'],
                        'province': contact_info['province'],
                        'country': contact_info['country']
                    })
                logging.info('userinfo updated: %s', more_info)
                self.storage.add_user_info(more_info)
예제 #15
0
    def post(self, siteid):
        parse_args = self.assign_arguments(
            essential=['appid',
                       'title',
                       'out_trade_no',
                       'total_fee',
                       'spbill_create_ip',
                       'trade_type'],
            extra=[('detail', ''),
                   ('unionid', ''),
                   ('openid', '')]
        )
        if not parse_args.get('unionid') and not parse_args.get('openid'):
            raise tornado.web.HTTPError(400)

        req_data = dtools.transfer(
            parse_args,
            copys=['appid',
                   'out_trade_no',
                   'detail',
                   'total_fee',
                   'spbill_create_ip',
                   'trade_type',
                   'openid'],
            renames=[('title', 'body')]
        )
        if not req_data.get('openid'):
            req_data['openid'] = self.storage.get_user_info(appid=parse_args['appid'],
                                                            unionid=parse_args['unionid'],
                                                            select_key='openid')
        appinfo = self.storage.get_app_info(appid=req_data['appid'])
        if not appinfo:
            self.send_response(err_code=3201)
            raise tornado.gen.Return()

        req_data.update(
            {
                'attach': 'siteid=' + siteid,
                'mch_id': appinfo.get('mch_id'),
                'notify_url': self.storage.get_site_info(siteid, select_key='pay_notify_url')
            }
        )
        req_key = appinfo['apikey']
        security.add_sign(req_data, req_key)

        try:
            resp = yield httputils.post_dict(url=url.mch_order_add, data=req_data, data_type='xml')
        except tornado.httpclient.HTTPError:
            self.send_response(err_code=1001)
            raise tornado.gen.Return()

        resp_data = self.parse_payment_resp(resp, req_key)
        if resp_data:
            real_sign_data = {
                'appId': resp_data['appid'],
                'timeStamp': str(int(time.time())),
                'nonceStr': security.nonce_str(),
                'package': 'prepay_id=' + resp_data['prepay_id'],
                'signType': 'MD5'
            }
            post_resp_data = {
                'appid': real_sign_data['appId'],
                'timestamp': real_sign_data['timeStamp'],
                'noncestr': real_sign_data['nonceStr'],
                'prepay_id': resp_data['prepay_id'],
                'sign_type': real_sign_data['signType'],
                'pay_sign': security.build_sign(real_sign_data, req_key)
            }
            self.send_response(post_resp_data)
예제 #16
0
    def post(self, siteid):
        parse_args = self.assign_arguments(essential=[
            'appid', 'title', 'out_trade_no', 'total_fee', 'spbill_create_ip',
            'trade_type'
        ],
                                           extra=[('detail', ''),
                                                  ('unionid', ''),
                                                  ('openid', '')])
        if not parse_args.get('unionid') and not parse_args.get('openid'):
            raise tornado.web.HTTPError(400)

        req_data = dtools.transfer(parse_args,
                                   copys=[
                                       'appid', 'out_trade_no', 'detail',
                                       'total_fee', 'spbill_create_ip',
                                       'trade_type', 'openid'
                                   ],
                                   renames=[('title', 'body')])
        if not req_data.get('openid'):
            req_data['openid'] = self.storage.get_user_info(
                appid=parse_args['appid'],
                unionid=parse_args['unionid'],
                select_key='openid')
        appinfo = self.storage.get_app_info(appid=req_data['appid'])
        if not appinfo:
            self.send_response(err_code=3201)
            raise tornado.gen.Return()

        req_data.update({
            'attach':
            'siteid=' + siteid,
            'mch_id':
            appinfo.get('mch_id'),
            'notify_url':
            self.storage.get_site_info(siteid, select_key='pay_notify_url')
        })
        req_key = appinfo['apikey']
        security.add_sign(req_data, req_key)

        try:
            resp = yield httputils.post_dict(url=url.mch_order_add,
                                             data=req_data,
                                             data_type='xml')
        except tornado.httpclient.HTTPError:
            self.send_response(err_code=1001)
            raise tornado.gen.Return()

        resp_data = self.parse_payment_resp(resp, req_key)
        if resp_data:
            real_sign_data = {
                'appId': resp_data['appid'],
                'timeStamp': str(int(time.time())),
                'nonceStr': security.nonce_str(),
                'package': 'prepay_id=' + resp_data['prepay_id'],
                'signType': 'MD5'
            }
            post_resp_data = {
                'appid': real_sign_data['appId'],
                'timestamp': real_sign_data['timeStamp'],
                'noncestr': real_sign_data['nonceStr'],
                'prepay_id': resp_data['prepay_id'],
                'sign_type': real_sign_data['signType'],
                'pay_sign': security.build_sign(real_sign_data, req_key)
            }
            self.send_response(post_resp_data)