Exemple #1
0
def api_retrieve_shop_info():
    """
    @api {post} /shop/complex_query/:page [商户]基本信息复杂查询
    @apiDescription 查询多条商户详细信息记录(mongodb __raw__).
    @apiName api_retrieve_shop_info
    @apiGroup shop

    @apiParamExample {json} 请求body示例:
        {
            "_id": "56c2d708a785c90ab0014d00"
        }
    """
    kw = ctx.request.input()
    query = {}

    if 'query' in kw:
        query = pickle.loads(kw.query)
    if '_id' in kw:
        query['_id'] = ObjectId(kw['_id'])
    for k in ('tel', 'name'):
        if k in kw:
            query[k] = kw[k]
    page, count = parse_page_count(kw)

    excludes = (str('password'), )
    only = kw.get('only')
    if only:
        shops = Shop.objects(__raw__=query).only(*only).skip(
            (page * count)).limit(count)
    else:
        shops = Shop.objects(__raw__=query).exclude(*excludes).skip(
            (page * count)).limit(count)
    _count = Shop.objects(__raw__=query).count()
    ret = []
    for s in shops:
        s_packed = ShopLogic.pack_shop(s, excludes=excludes, only=only)
        ret.append(s_packed)
    ctx.response.set_header("X-Resource-Count".encode('utf-8'), _count)
    return ret[0] if len(ret) == 1 else ret if len(ret) > 1 else {}
Exemple #2
0
def api_get_shop_info_from_token():
    # 输入: token <token>
    params = ctx.request.input()
    if 'token' not in params:
        logging.warning(
            "You are calling /shop/token without [token] key in params%s." %
            params)
    token = params.token.split()[1]
    key = key_shop_token.format(content=token)
    # 可能值: id
    who = redis_client.get(key)
    if not who:
        ctx.response.status = '401 Unauthorized'
        return None

    elif len(who) == 24:
        s = Shop.objects(id=who).first()
        # 如果该商户没有定价, 取默认定价
        if s.fee and s.fee.get('fh'):
            pass
        else:
            _s = Shop.objects(tel='00000000000').only('fee').first()
            s.fee = _s.fee
        return ShopLogic.pack_shop(s)
Exemple #3
0
def api_shop_wap_top_up_as_pay():
    # shop_id, cash
    kw = ctx.request.input()
    # 记录这次尝试
    transact_num = gen_transact_num()
    s = Shop.objects(id=kw.shop_id).first()

    # todo 暂时用充值尝试的记录
    TopUpLogic.create(transact_num=transact_num,
                      shop_id=kw.shop_id,
                      shop_name=s.name,
                      shop_tel=s.tel,
                      cash=kw.cash)
    # 创建手机wap转账接口链接
    url = gen_wap_transfer_link(transact_num, kw.cash, '商户现金支付')
    logging.info(url)
    return {'transact_num': transact_num, 'url': url}
Exemple #4
0
def api_shop_wap_top_up():
    # 输入: shop_id, cash
    kw = ctx.request.input()
    # 记录这次尝试
    transact_num = gen_transact_num()
    kw.transact_num = transact_num
    s = Shop.objects(id=kw.shop_id).first()
    kw.shop_name = s.name
    kw.shop_tel = s.tel
    TopUpLogic.create(**kw)
    # 创建手机wap充值接口链接
    url = create_wap_trade(transact_num, kw.cash, '商户充值')
    logging.info(url)
    # 返回示例 {'transact_num': transact_num,
    #         'url': 'http://wappaygw.alipay.com/service/rest.htm?service=alipay.wap.auth.authAndExecute
    # &format=xml&v=2.0&_input_charset=utf-8
    # &req_data=<auth_and_execute_req><request_token>20160226c760e7d843186665408fa6729ee21979</request_token>
    # </auth_and_execute_req>&sec_id=MD5&partner=2088901729140845&sign=f7d02ce9ece212677a512108687594fb}
    return {'transact_num': transact_num, 'url': url}
Exemple #5
0
def api_shop_h5_wx_top_up():
    kw = Schema({
        'shop_id': schema_unicode,
        'cash': schema_float_2,
        'code': schema_unicode,  # 用于获取用户标识openid
    }).validate(ctx.request.input())
    code = kw.pop('code')
    # 记录这次尝试
    transact_num = gen_transact_num()
    kw.transact_num = transact_num
    s = Shop.objects(id=kw.shop_id).first()
    kw.shop_name = s.name
    kw.shop_tel = s.tel
    TopUpLogic.create(**kw)
    # 创建预支付交易会话, 获取预支付交易会话标识
    result = wx_generate_prepay_jsapi(transact_num, kw['cash'],
                                      ctx.request.remote_addr, code)
    if result['result'] == 'success':
        return {
            'prepay_id': result['prepay_id'],
        }
    else:
        raise ValueError('wxPay[JSAPI] Error: %s' % result['msg'])
Exemple #6
0
def api_shop_web_top_up():
    # shop_id, cash
    params = ctx.request.input()
    # 记录这次尝试
    transact_num = gen_transact_num()
    params.transact_num = transact_num
    s = Shop.objects(id=params.shop_id).first()
    params.shop_name = s.name
    params.shop_tel = s.tel
    TopUpLogic.create(**params)
    # 创建PC网页端充值接口链接
    url = create_web_trade(transact_num, params.cash)
    logging.info(url)
    # 返回示例 {
    #     "transact_num": "20160226117671",
    #     "url": "https://mapi.alipay.com/gateway.do?seller_email=abcx%40123feng.com&seller_id=2088901729140845"
    #            "&total_fee=0.01&service=create_direct_pay_by_user"
    #            "&_input_charset=utf-8&sign=d4ee6f2151e2a0aafce26865b4fb4ad9"
    #            "&out_trade_no=20160226117671&payment_type=1"
    #            "&notify_url=http%3A%2F%2F123.57.45.209%3A5000%2Fpay%2Falipay%2Fweb%2Fnotify"
    #            "&sign_type=MD5&partner=2088901729140845&subject=charge",
    # }
    return {'transact_num': transact_num, 'url': url}
Exemple #7
0
def api_shop_login():
    """
    @api {get} /shop/login?shop_id=&password= [商户]登录
    @apiDescription 风先生商户登录成功则返回token,失败则报错.
    @apiName api_shop_login
    @apiGroup shop

    @apiParam {string(11)} [shop_id] 商户工号, 如 7748657.
    @apiParam {string(11)} [tel] 商户手机号, 如 150687929321.
    @apiParam {string(32)} password 商户密码hash(如果是id+密码登录), 验证码(如果是手机号+验证码登录).

    @apiParamExample {json} 请求url示例:
          /shop/login?shop_id=17066&password=0192023a7bbd73250516f069df18b500
    OR    /shop/login?tel=150687929321&password=123456
    @apiSuccessExample {json} 手机号验证码登录成功示例:
        HTTP/1.1 200 OK
        {
          "tel": "150687929321",
          "token": "36dc92e290f334aaa96466d3ee9b9efa"
        }
    @apiSuccessExample {json} 工号密码登录成功示例:
        HTTP/1.1 200 OK
        {
          "shop_id": "17066",
          "token": "36dc92e290f334aaa96466d3ee9b9efa"
        }
    @apiErrorExample {json} 失败示例:
        HTTP/1.1 400 ValueError
        {
          "message": "No such shop=[150687929321]."
        }
    @apiErrorExample {json} 失败示例:
        HTTP/1.1 400 ValueError
        {
          "message": "Password validation for [17066]=[012023a7bbd73250516f069df18b500] failed."
        }
    """
    def set_token(inner_who):
        token = hashlib.md5('%s%s' % (inner_who, utc_8_now())).hexdigest()
        key = key_shop_token.format(content=token)
        # 插入token到redis中, 30天有效期: get token:fe11ad907e2fa779ed2f363ef589d3f9 => 7740959
        redis_client.setex(key, inner_who, 30 * 24 * 3600)
        return token

    params = ctx.request.input()
    shop_id = str(params.get("id", "")).strip()
    tel = str(params.get("tel", "")).strip()
    password_or_sms_code = str(params.get('password', '')).strip()

    # ==> 首先检查是不是免密码[优先级为: 免密码>手机]
    who = shop_id if shop_id else tel if tel else None
    if not who:
        raise ValueError("Expect either [shop_id] or [tel] in params%s." %
                         params)
    elif not password_or_sms_code:
        raise ValueError("Expect [password] in params%s." % params)
    # 存放: 免密码名单和token(30天)
    # 登录成功: smembers no_password => set(13245678901,...); sismember(key_login, tel)
    elif redis_client.sismember(key_no_password, who):
        if tel:
            shop = Shop.objects(tel=tel).first()
            content = set_token(str(shop.pk))
            s_packed = ShopLogic.pack_shop(shop)
            s_packed.update(dict(token=content))
            return s_packed

    # ==> 商户登录: 商户owner手机号+密码
    shop = None
    if shop_id:
        shop = Shop.objects(id=shop_id).first()
    elif tel:
        shop = Shop.objects(tel=tel).first()
    password_in_db = str(shop.password).strip() if shop else None
    # 如果此人不存在,直接报错
    if not password_in_db:
        logging.info("No such shop=[%s]." % who)
        raise ValueError("商户不存在,请注册后登录.")
    # 登录成功: 密码与数据库中值匹配
    if password_or_sms_code == password_in_db:
        content = set_token(str(shop.pk))
        s_packed = ShopLogic.pack_shop(shop)
        s_packed.update(dict(token=content))
        return s_packed
    # 登录失败
    else:
        logging.info(
            "Password validation for [%s]=[%s] failed, expected [%s]." %
            (who, password_or_sms_code, password_in_db))
        raise ValueError("用户名或密码错误.")
Exemple #8
0
def api_shop_operation(operation):
    def set_token(inner_who):
        token = hashlib.md5('%s%s' % (inner_who, utc_8_now())).hexdigest()
        key = key_shop_token.format(content=token)
        # 插入token到redis中, 7天有效期: get shop:token:fe11ad907e2fa779ed2f363ef589d3f9 => 7740959
        redis_client.setex(key, inner_who, 7 * 24 * 3600)
        return token

    operation = str(operation).upper().strip()
    kw = ctx.request.input()
    # ==> 商户注册
    if operation == OPERATIONS.REGISTER:
        kw = Schema({
            'tel': schema_unicode,
            'sms_code': schema_unicode,
            'password': schema_unicode,
            Optional('name'): schema_unicode,
            'contact': {
                Optional('name', default=''): schema_unicode_empty,
                Optional('tel', default=''): schema_unicode_empty
            },
            Optional("loc"): {
                "address": schema_unicode,
                "longitude": schema_float,
                "latitude": schema_float,
                Optional(object): object
            },
            Optional('recommended_by'): {
                'tel': schema_unicode_empty
            },
        }).validate(ctx.request.input())
        tel = kw['tel']
        sms_code = kw['sms_code']
        password = kw['password']
        # song.123feng.com/APP注册: 手机号+验证码
        if tel:
            sms_key = key_sms_code.format(tel=tel)
            # 验证成功: 验证码匹配 get sms:code:15901739717 => 123456
            sms_code_in_redis = redis_client.get(sms_key)
            if sms_code_in_redis == sms_code:
                shop = Shop.objects(tel=tel).first()
                if not shop:
                    # 记录商户到mongodb(如无记录): status=STATUS_VALID
                    # 记录商户到mongodb(如无记录): status=STATUS_INFO_YES
                    if 'recommended_by' in kw:
                        kw['recommended_by']['time'] = TimeZone.utc_now()
                    kw_filtered = ShopLogic.filter_shop(kw)
                    shop = Shop(**kw_filtered).save()
                    # ===== 注册风信账户 =====
                    http_client = HTTPClient()
                    http_client.fetch(account.req_create(
                        account_type=conf.ACCOUNT_TYPE_SHOP,
                        account_id=str(shop.pk)),
                                      raise_error=False)
                else:
                    # 允许重复注册, 改一下密码
                    shop.password = password
                    shop.save()
                shop.reload()
                shop_id = str(shop.pk)
                content = set_token(shop_id)
                s_packed = ShopLogic.pack_shop(shop)
                s_packed.update(dict(token=content))
                return s_packed
            # 登录失败
            else:
                logging.info(
                    "SMS code validation for [%s]=[%s] failed, expected[%s]." %
                    (tel, sms_code, sms_code_in_redis))
                raise ValueError("验证码验证失败.")
    # ==> 商户事件
    elif operation in ShopFSM.FE_INSIDE_EVENTS or operation in ShopFSM.OUTSIDE_EVENTS:
        # 对完善资料特殊添加时间信息
        if operation == ShopFSM.EVENT_COMPLETE_INFO and 'recommended_by' in kw:
            kw['recommended_by']['time'] = TimeZone.utc_now()
        # 对修改定价特殊处理: 能用tel找商户id
        if operation == ShopFSM.EVENT_ALTER_INFO:
            shop = Shop.objects(tel=kw.tel).first()
        # 其他事件一概用shop_id
        else:
            shop = Shop.objects(id=kw.shop_id).first()
        if shop:
            operator_type = kw.operator_type
            kw.pop('operator_type')
            modified_shop = ShopFSM.update_status(operator_type, shop,
                                                  operation, **kw)
            if not modified_shop:
                raise ValueError(
                    "State transfer for shop[%s][%s][%s] using [%s] failed." %
                    (kw.shop_id, shop.name, shop.status, operation))
            return ShopLogic.pack_shop(modified_shop)

    else:
        pass