def make_trade_order(userid, amount, trade_type, comment, pay_type='cash'): trade_order = { 'order_trade_id': app_helper.get_new_order_id(), 'userid': userid, 'total_sum': amount, 'trade_type': trade_type, # receipt 收款 refund 退款 consume 消费 'pay_type': pay_type, 'pay_time': app_helper.time_str(), 'cash_sum': amount, 'comment': comment, } db.order_trade.update_one( {'order_trade_id': trade_order['order_trade_id']}, {'$set': trade_order}, upsert=True) return trade_order['order_trade_id']
def POST(self): web.header('Content-Type', 'application/json') param = web.input(app_id='', session='', shop_id='', order_id='', addr_id='', coupon_id='', cart='', sign='') print param if '' in (param.app_id, param.session, param.shop_id, param.addr_id, param.cart, param.sign): return json.dumps({'ret': -2, 'msg': '参数错误'}) uname = app_helper.logged(param.session) # 检查session登录 if uname: #验证签名 md5_str = app_helper.generate_sign([ param.app_id, param.session, param.order_id, param.shop_id, param.addr_id, param.coupon_id, param.cart ]) if md5_str != param.sign: return json.dumps({'ret': -1, 'msg': '签名验证错误'}) # 记录版本信息 db.app_user.update_one({'uname': uname}, {'$set': { 'version': 'v1' }}) # mice 为黄牛手机号标志,mice==1不可以下单 2015-08-22 db_user = db.app_user.find_one( {'uname': uname}, #, 'mice':{'$ne':1}}, { 'coupon': 1, 'address': 1, 'credit': 1, 'app_id': 1, 'mice': 1 }) if db_user == None: # 不应该发生 return json.dumps({'ret': -9, 'msg': '未找到用户信息'}) # 检查mice, 排除白名单 if db_user.get('mice') == 1 and uname not in app_helper.WHITE_LIST: print 'mice !!!' return json.dumps({'ret': -9, 'msg': '未找到用户信息'}) app_id = db_user['app_id'] # 修改未付款的过期订单 db.order_app.update_many( { #'uname' : uname, 'status': 'DUE', 'deadline': { '$lt': int(time.time()) } }, {'$set': { 'status': 'TIMEOUT' }}) # 检查是否有新红包 #app_helper.check_hb(uname) # 先要核对送货地址是否在门店送货范围内!!!!!!! -- 需补充 # 查找shop db_shop = db.base_shop.find_one({'_id': ObjectId(param.shop_id)}) if db_shop == None: return json.dumps({'ret': -6, 'msg': 'shop_id错误'}) # 查询收货地址 address = None for i in db_user['address']: if i[0] == param.addr_id: address = list(i) break if address == None: return json.dumps({'ret': -7, 'msg': 'addr_id错误'}) ########################################################################### # 用收货电话检查黄牛 2015-08-22 db_recv = db.recv_tel.find_one({'tel': address[2]}) if db_recv: one_more = 0 if uname not in db_recv['unames']: # 补充疑似账号 db.recv_tel.update_one({'tel': address[2]}, {'$push': { 'unames': uname }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现 mice mice = 1 for b in db_recv['unames']: if b in app_helper.WHITE_LIST: # 过滤白名单相关号码 mice = 0 break db.app_user.update_many( {'uname': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) db.app_user.update_many( {'openid': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) if one_more == 1: db.app_user.update_one({'uname': uname}, {'$set': { 'mice': mice }}) if mice == 1: print '!!! mice:', address[ 2] #, uname, db_recv['unames'] return json.dumps({'ret': -9, 'msg': '黄牛下单1'}) else: db.recv_tel.insert_one({'tel': address[2], 'unames': [uname]}) print 'insert', address[2] # 用收货地址检查黄牛, 不准确,不能标注 2015-08-23 db_recv = db.recv_addr.find_one({'addr': address[3]}) if db_recv: one_more = 0 if uname not in db_recv['unames']: db.recv_addr.update_one({'addr': address[3]}, {'$push': { 'unames': uname }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现疑似mice,不标注,因为不确定 print '!!! maybe a mice:', address[3].encode( 'utf-8') #, uname, db_recv['unames'] else: db.recv_addr.insert_one({ 'addr': address[3], 'unames': [uname] }) #print 'insert', address[2] # 用app_id检查黄牛 appid_count = db.app_user.find({ 'app_id': app_id }, { '_id': 1 }).count() if appid_count > 10 and app_id.strip( ) != '': # app_id 可能为空,新绑定的用户 # 改为10,2015-10-12 # 发现 mice db_mice = db.app_user.find({'app_id': app_id}, {'uname': 1}) mice = [] for m in db_mice: if m['uname'] in app_helper.WHITE_LIST: # 过滤白名单 mice = [] break else: mice.append(m['uname']) db.app_user.update_many({'uname': { '$in': mice }}, {'$set': { 'mice': 1 }}) if mice != []: print '!!! mice by app_id: ', mice return json.dumps({'ret': -9, 'msg': '黄牛下单1'}) # 查黄牛-结束 ########################################################################### # 查找优惠券 # 未查到,则不使用优惠券 coupon = None for i in db_user['coupon']: if i[0] == param.coupon_id: coupon = list(i) break # 转换cart数据为json,应该有异常捕获 !!! cart = json.loads(param.cart) #print cart if len(cart) == 0: return json.dumps({'ret': -5, 'msg': '购物车无数据'}) if param.order_id == '': #cc = 1 #while cc!=None: # # 取得sku计数, 不与线下order共用 # db_sa = db.user.find_one_and_update( # {'uname' : 'settings'}, # {'$inc' : {'app_count' : 1}}, # {'app_count' : 1} # ) # order_id = 'n%06d' % db_sa['app_count'] # # 防止订单号重复 # cc = db.order_app.find_one({'order_id' : order_id},{'_id':1}) order_id = app_helper.get_new_order_id('v1') print 'new order_id', order_id else: order_id = param.order_id cc = db.order_app.find_one( { #'uname' : uname, # 防止app的bug,重复order_id 'order_id': order_id, }, { 'status': 1, }) if cc != None and cc[ 'status'] != 'DUE': # 检查订单状态,只有due才可以checkout print "BUG! order_id status" return json.dumps({'ret': -99, 'msg': '参数错误'}) # 订单状态:DUE, PAID, ONROAD, COMPLETED, CANCELED, FINISH # 默认运费 5元,免邮门槛 29元 order = { 'status': 'DUE', 'uname': uname, 'shop': db_shop['_id'], 'user': uname, 'order_id': order_id, 'order_source': app_helper.get_devive_type(param.app_id), 'address': address, # 收货地址 'coupon': coupon, # 使用的优惠券 'cart': [], 'cost': '0.00', # 成本合计,参考 'total': '0.00', # 价格小计,加项 'coupon_disc': '0.00', # 优惠券抵扣,减项 'first_disc': '0.00', # 首单立减, 减项 'delivery_fee': '0.00', # 运费,加项 'due': '0.00', # 应付价格 'uname_id': db_user['_id'], # for processor 'next_status': '', 'lock': 0, 'man': 0, 'retry': 0, 'comment': '', 'b_time': int(time.time()), 'e_time': int(time.time()), 'deadline': int(time.time() + 60 * 15), } # 统计旧订单数,为0则是首单 2015-09-29 old_order_num = db.order_app.find( { 'user': uname, 'status': { '$nin': ['DUE', 'TIMEOUT', 'CANCEL'] } }, { '_id': 1 }).count() # item = { # “product_id” : “k000011”, # “num” : “5”, # } # 应该只有 k-prod cart_to_return = [] cate_001 = 0 b3_sku = 0 for item in cart: # sku db_sku = db.sku_store.find_one( {'product_id': item['product_id']}, { 'app_title': 1, 'is_onsale': 1, 'special_price': 1, 'ref_price': 1, 'maximun': 1, 'list_in_app': 1, }) if db_sku == None: # 应该不会发生 print 'Error: db_sku==None' continue if db_sku['list_in_app'] == -3: # B3 整箱预售 # -3 不启动B3销售 r = db.inventory.find_one( # 线上销售要检查库存 { 'product_id' : item['product_id'], 'list_in_app' : {'$ne' : 0}, 'shop' : ObjectId(setting.B3_shop), }, { 'cost_price' : 1, 'ref_prod_id' : 1, 'price' : 1, 'sku' : 1, 'num' : 1, 'category' : 1, 'first_order' : 1 } ) b3_sku += 1 else: r = db.inventory.find_one( # 线上销售要检查库存 { 'product_id' : item['product_id'], 'list_in_app' : {'$ne' : 0}, 'shop' : db_shop['_id'], }, { 'cost_price' : 1, 'ref_prod_id' : 1, 'price' : 1, 'sku' : 1, 'num' : 1, 'category' : 1, 'first_order' : 1 } ) if r: # 如果库存数据中没此sku,会忽略掉,此情况应该不会发生 new_num = int(item['num']) new_num = new_num if new_num <= r['num'] else r['num'] new_num = max(0, new_num) # 发现过小于零的情况,微信 # 检查是不是 001 (水果) 分类 if r['category'] == '001': cate_001 += 1 # 检查是否限购 if db_sku['maximun'] > 0: ''' # 每日限购,生成当天的时间tick tday = app_helper.time_str(format=1) begin_d = '%s 00:00:00' % tday end_d = '%s 23:59:59' % tday begin_t = int(time.mktime(time.strptime(begin_d,"%Y-%m-%d %H:%M:%S"))) end_t = int(time.mktime(time.strptime(end_d,"%Y-%m-%d %H:%M:%S"))) print begin_d, end_d, begin_t, end_t # 检查时间段内购买记录 c = db.order_app.find({ 'uname' : uname, 'order_id' : {'$ne':order_id}, 'status' : {'$ne':'TIMEOUT'}, 'cart.product_id' : item['product_id'], '$and' : [{'b_time' : {'$gt' : begin_t}}, {'b_time' : {'$lt' : end_t}}], }, {'_id':1}).count() print 'findings: ',c if c>0: # 限购商品只允许购买1次 new_num=0 else: new_num=min(new_num, db_sku['maximun']) print 'limit : ',new_num ''' # 每单限购 if new_num > db_sku['maximun']: new_num = db_sku['maximun'] item['num'] = '%d' % new_num # 防止iOS闪退!!! print 'limit : ', new_num ''' # 买一送一 每单限购1件 if item['product_id'] in app_helper.buy_1_give_1: #new_num=min(new_num, 1) #print 'buy 1 give 1 limit : ',new_num new_item = { 'product_id' : item['product_id'], 'num' : '%d' % new_num, 'num2' : new_num, 'price' : r['price'], 'title' : db_sku['app_title'], } else: ''' # 首单可见商品,非首单用户 2015-09-29 if r.has_key('first_order') and r[ 'first_order'] == 1 and old_order_num > 0: # 非首单用户,不让购买,比较生硬 new_num = 0 item['num'] = '%d' % new_num # 防止iOS闪退!!! new_item = { 'product_id': item['product_id'], 'num': item['num'], 'num2': new_num, 'price': r['price'], 'title': db_sku['app_title'], } # 是否有优惠价格 if db_sku['is_onsale']==1 and \ float(db_sku['special_price'])<float(r['price']): # 优惠价格比门店价格低 new_item['price'] = db_sku['special_price'] # 计算总价 item_price = round(new_num * float(new_item['price']), 2) new_item['price'] = '%.2f' % item_price cart_to_return.append(new_item) # 返回到app的cart不包含cost cost_price = r['cost_price'] #if item[0][0]=='w': # w-prod 信息都用 u-prod的替换 # new_item['product_id'] = r['ref_prod_id'] # new_item['w_id'] = item[0] # # 查询成本, 从对应u-prod当前成本 # r2 = db.inventory.find_one({ # u-prod # 'shop' : db_shop['shop'], # 'product_id' : r['ref_prod_id'], # }, {'cost_price':1}) # cost_price = r2['cost_price'] # 计算成本 item_cost = round(new_num * float(cost_price), 2) new_item['cost'] = '%.2f' % item_cost # 加入cart order['cart'].append(new_item) # 累计售价和成本 order['total'] = '%.2f' % (float(order['total']) + item_price) order['cost'] = '%.2f' % (float(order['cost']) + item_cost) else: # 店内未找到库存, !!!应该不会发生 new_item = { 'product_id': item['product_id'], 'num': item['num'], 'num2': 0, 'price': '0.00', 'cost': '0.00', 'title': db_sku['app_title'], } cart_to_return.append(new_item) # 返回到app的cart不包含cost order['cart'].append(new_item) tt = float(order['total']) if tt > 0: # 免邮门槛 #if tt<29: # 免邮门槛 29 if tt < app_helper.free_delivery: # 免邮门槛 order[ 'delivery_fee'] = '%.2f' % app_helper.delivery_fee # 运费5元 ''' # 首单立减 first_promote元, 商品总额大于 first_promote_threshold元 cut_now = app_helper.first_promote # if cate_001>0 and (tt+float(order['delivery_fee']))>=app_helper.first_promote_threshold and \ db.order_app.find({'user':uname, 'status':{'$nin':['DUE','TIMEOUT','CANCEL']}},{'_id':1}).count()==0: order['first_disc'] = '%.2f' % cut_now ''' # 首单立减 first_promote元, 商品总额大于 first_promote_threshold元 if cate_001 > 0 and old_order_num == 0: # 符合首单条件,且有一个水果商品 print '首单' if str(db_shop['_id']) in app_helper.first_promote2_shop and \ (tt+float(order['delivery_fee']))>=app_helper.first_promote2_threshold: # 站点落在 指定站点范围内,使用首单立减2 print '首单立减 - 指定站点' order[ 'first_disc'] = '%.2f' % app_helper.first_promote2 elif (tt + float(order['delivery_fee']) ) >= app_helper.first_promote_threshold: # 其他站点使用首单立减1 print '首单立减' order['first_disc'] = '%.2f' % app_helper.first_promote # 优惠券, 检查有效期, 优惠券门槛为10元 if float(order['first_disc'])==0.0 and coupon!=None and \ coupon[3]==1 and app_helper.time_str(format=1)<=coupon[1]: if len(coupon ) > 5 and coupon[5] == 'apple' and cate_001 < 1: # 水果券,但没有水果 2015-09-29 print '水果券没水果' order['coupon'] = None elif len(coupon) > 5 and coupon[5] == 'b3' and b3_sku < 1: # 整箱券,但没有整箱 2015-10-18 print '整箱券没整箱' order['coupon'] = None else: if len(coupon) > 4: # (id, 有效期, 金额, 是否已用, 门槛) 2015-09-27 # 有门槛信息,使用优惠券门槛信息 if (tt + float(order['delivery_fee'])) < coupon[4]: order['coupon'] = None else: order['coupon_disc'] = coupon[2] else: # 使用默认条件 if float(coupon[2]) == 6.0 and ( tt + float(order['delivery_fee'])) < 29.9: order['coupon'] = None elif float(coupon[2]) == 9.0 and ( tt + float(order['delivery_fee'])) < 39.9: order['coupon'] = None elif (tt + float(order['delivery_fee'])) < 14.9: order['coupon'] = None else: order['coupon_disc'] = coupon[2] else: order['coupon'] = None # 计算应付:价格合计 - 优惠券 - 首单立减 + 运费 print(tt + float(order['delivery_fee']) - float(order['coupon_disc']) - float(order['first_disc'])) print tt, float(order['delivery_fee']), float( order['coupon_disc']), float(order['first_disc']) order['due'] = '%.2f' % (tt + float(order['delivery_fee']) - float(order['coupon_disc']) - float(order['first_disc'])) if float(order['due']) <= 0: order['due'] = '0.10' # 如果没有,则insert #db.order_app.replace_one({'order_id':order_id}, order, upsert=True) db.order_app.update_one({'order_id': order_id}, { '$set': order, '$push': { 'history': (app_helper.time_str(), uname, '提交结算') } }, upsert=True) ret_json = { # 返回结果,实际有库存的结果, 'ret': 0, 'data': { 'order_id': order['order_id'], 'shop_id': str(order['shop']), 'shop': db_shop['name'], # 可能会变,如果地址与门店不匹配的时候 'addr_id': address[0], 'cart_num': len(order['cart']), 'cart': cart_to_return, 'total': order['total'], 'coupon': coupon[0] if order['coupon'] else '', 'coupon_disc': order['coupon_disc'], 'first_disc': order['first_disc'], 'delivery_fee': order['delivery_fee'], 'due': order['due'], 'credit': '%.2f' % db_user.get('credit', 0.0) } } print ret_json return json.dumps(ret_json) else: return json.dumps({'ret': -4, 'msg': '无效的session'})
def POST(self, version='v2'): web.header('Content-Type', 'application/json') if version not in ('v2', 'v3'): return json.dumps({'ret': -999, 'msg': '版本错误!'}) print 'version=', version param = web.input(app_id='', session='', order_id='', total='', note='', sign='') if version == 'v2': if '' in (param.app_id, param.order_id, param.session, param.total, param.sign): return json.dumps({'ret': -2, 'msg': '参数错误'}) elif version == 'v3': if '' in (param.app_id, param.session, param.total, param.sign): return json.dumps({'ret': -2, 'msg': '参数错误'}) if web.ctx.has_key('environ'): client_ip = web.ctx.environ['REMOTE_ADDR'] else: return json.dumps({'ret': -5, 'msg': '无法取得客户端ip地址'}) uname = app_helper.app_logged(param.session) # 检查session登录 if uname: #验证签名 md5_str = app_helper.generate_sign([ param.app_id, param.session, param.order_id, param.total, param.note ]) if md5_str != param.sign: return json.dumps({'ret': -1, 'msg': '签名验证错误'}) #db_shop = db.base_shop.find_one({'_id':ObjectId(setting.default_shop)},{'name':1}) # 统一下单接口获取 prepay_id nonce_str = app_helper.my_rand(30) body = 'U掌柜app' trade_type = 'APP' if version == 'v2': order_id = '%s_%d' % (param.order_id.encode('utf-8'), int(time.time())) elif version == 'v3': if len(param.order_id) > 0: order_id = '%s_%d' % (param.order_id.encode('utf-8'), int(time.time())) print order_id else: # 生成order_id order_id = app_helper.get_new_order_id(version).encode( 'utf-8') print 'new order_id', order_id total_fee = param.total.encode('utf-8') para = [('appid', wx_appid), ('body', body), ('mch_id', mch_id), ('nonce_str', nonce_str), ('notify_url', notify_url), ('out_trade_no', order_id), ('spbill_create_ip', client_ip), ('total_fee', total_fee), ('trade_type', trade_type)] print para stringA = '&'.join('%s=%s' % i for i in para) stringSignTemp = '%s&key=%s' % (stringA, api_key) sign = hashlib.md5(stringSignTemp).hexdigest().upper() para_xml = '<xml>' \ '<appid>'+wx_appid+'</appid>' \ '<mch_id>'+mch_id+'</mch_id>' \ '<nonce_str>'+nonce_str+'</nonce_str>' \ '<sign>'+sign+'</sign>' \ '<body>'+body+'</body>' \ '<out_trade_no>'+order_id+'</out_trade_no>' \ '<total_fee>'+total_fee+'</total_fee>' \ '<spbill_create_ip>'+client_ip+'</spbill_create_ip>' \ '<notify_url>'+notify_url+'</notify_url>' \ '<trade_type>'+trade_type+'</trade_type>' \ '</xml>' print para_xml #return json.dumps({'ret' : 0, 'data' : 'here'}) urllib3.disable_warnings() pool = urllib3.PoolManager(num_pools=2, timeout=180, retries=False) url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' r = pool.urlopen('POST', url, body=para_xml) if r.status == 200: data = r.data print data if version == 'v2': # 记录微信商户订单号 db.order_app.update_one( {'order_id': param.order_id}, {'$set': { 'wx_out_trade_no': order_id }}) return json.dumps({'ret': 0, 'data': data}) elif version == 'v3': if len(param.order_id) > 0: db_order = db.order_app.find_one( {'order_id': param.order_id}) if db_order['status'] != 'DUE': print '============================== -100' return json.dumps({ 'ret': -100, 'msg': '订单状态变化,请确认' }) ret_json = checkout( version, uname, { 'session': param.session, 'order_id': param.order_id, 'shop_id': str(db_order['shop']), 'addr_id': db_order['address'][0], 'coupon_id': db_order['coupon'][0] if float(db_order['coupon_disc']) > 0 else '', 'cart': json.dumps(db_order['cart']), 'app_id': param.app_id, 'use_credit': '1' if float(db_order.get('use_credit', '0')) > 0 else '', #2015-11-19 }) if ret_json['ret'] < 0: # checkout 出错 return json.dumps({ 'ret': ret_json['ret'], 'msg': ret_json['msg'] }) if float(ret_json['data']['due']) != float( db_order.get('due3', db_order['due'])): # checkout后金额有变化,说明库存或优惠券有变化 db.order_app.update_one( {'order_id': param.order_id}, { '$set': { 'status': 'CANCEL' }, '$push': { 'history': (app_helper.time_str(), uname['uname'], '订单取消(微信支付)') } }) print '============================== -100' return json.dumps({ 'ret': -100, 'msg': '很抱歉,数据异常,订单已取消,请重新下单' }) # 可支付 db.order_app.update_one({'order_id': param.order_id}, { '$set': { 'wx_out_trade_no': order_id }, '$push': { 'history': (app_helper.time_str(), uname['uname'], '提交微信支付2') } }) return json.dumps({ 'ret': 0, 'order_id': param.order_id, 'data': data }) else: # 生成新订单 db_cart = db.app_user.find_one( {'uname': uname['uname']}, {'cart_order.%s' % param.session: 1}) new_order = dict(db_cart['cart_order'][param.session]) new_order['order_id'] = order_id new_order['status'] = 'DUE' new_order['user_note'] = param.note.strip() new_order['wx_out_trade_no'] = order_id new_order['history'] = [(app_helper.time_str(), uname['uname'], '提交微信支付')] ret_json = checkout( version, uname, { 'session': param.session, 'order_id': order_id, 'shop_id': str(new_order['shop']), 'addr_id': new_order['address'][0], 'coupon_id': new_order['coupon'][0] if float(new_order['coupon_disc']) > 0 else '', 'cart': json.dumps(new_order['cart']), 'app_id': param.app_id, 'use_credit': '1' if float(new_order.get('use_credit', '0')) > 0 else '', #2015-11-23 }) if ret_json['ret'] < 0: # checkout 出错 return json.dumps({ 'ret': ret_json['ret'], 'msg': ret_json['msg'] }) if float(ret_json['data']['due']) != float( new_order.get('due3', new_order['due'])): # checkout后金额有变化,说明库存或优惠券有变化 print '============================== -100' return json.dumps({ 'ret': -100, 'msg': '很抱歉,数据异常,请重新下单' }) db.order_app.insert_one(new_order) return json.dumps({ 'ret': 0, 'order_id': order_id, 'data': data }) else: return json.dumps({'ret': -1, 'data': r.status}) else: return json.dumps({'ret': -4, 'msg': '无效的session'})
def checkout(version, uname, param): print param # mice 为黄牛手机号标志,mice==1不可以下单 2015-08-22 db_user = db.app_user.find_one( {'uname': uname['uname']}, #, 'mice':{'$ne':1}}, { 'coupon': 1, 'address': 1, 'credit': 1, 'app_id': 1, 'mice': 1 }) if db_user == None: # 不应该发生 return {'ret': -9, 'msg': '未找到用户信息'} # 检查mice, 排除白名单 if db_user.get( 'mice') == 1 and uname['uname'] not in app_helper.WHITE_LIST: print 'mice !!!' return {'ret': -9, 'msg': '未找到用户信息'} app_id = db_user['app_id'] # 修改为付款的过期订单 r = db.order_app.update_many( { #'uname' : {'$in':uname.values()}, 'status': 'DUE', 'deadline': { '$lt': int(time.time()) } }, {'$set': { 'status': 'TIMEOUT' }}) # 查找shop db_shop = db.base_shop.find_one({'_id': ObjectId(param['shop_id'])}) if db_shop == None: return {'ret': -6, 'msg': 'shop_id错误'} # 查询收货地址 address = None for i in db_user['address']: if i[0] == param['addr_id']: address = list(i) break if address == None: return {'ret': -7, 'msg': 'addr_id错误'} # 获得 收货地址 坐标 if len(address) > 5: # 使用已有的gps地址 loc = address[5] else: ret, loc = lbs.addr_to_loc(address[3].encode('utf-8')) if ret < 0: # 重试一次 ret, loc = lbs.addr_to_loc(address[3].encode('utf-8')) if ret < 0: loc = {'lat': 0, 'lng': 0} print loc # 多边形检查 poly_shop = lbs.check_in_poly((loc['lat'], loc['lng']), db_shop.get('poly_xy', [])) if poly_shop == None: return {'ret': -6, 'msg': 'shop_id错误'} ########################################################################### # 用收货电话检查黄牛 2015-08-22 db_recv = db.recv_tel.find_one({'tel': address[2]}) if db_recv: one_more = 0 if uname['uname'] not in db_recv['unames']: # 补充疑似账号 db.recv_tel.update_one({'tel': address[2]}, {'$push': { 'unames': uname['uname'] }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现 mice mice = 1 for b in db_recv['unames']: if b in app_helper.WHITE_LIST: # 过滤白名单相关号码 mice = 0 break db.app_user.update_many({'uname': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) db.app_user.update_many({'openid': { '$in': db_recv['unames'] }}, {'$set': { 'mice': mice }}) if one_more == 1: db.app_user.update_one({'uname': uname['uname']}, {'$set': { 'mice': mice }}) if mice == 1: print '!!! mice:', address[ 2] #, uname['uname'], db_recv['unames'] return {'ret': -9, 'msg': '黄牛下单1'} else: db.recv_tel.insert_one({'tel': address[2], 'unames': [uname['uname']]}) #print 'insert', address[2] # 用收货地址检查黄牛, 不准确,不能标注 2015-08-23 db_recv = db.recv_addr.find_one({'addr': address[3]}) if db_recv: one_more = 0 if uname['uname'] not in db_recv['unames']: db.recv_addr.update_one({'addr': address[3]}, {'$push': { 'unames': uname['uname'] }}) one_more = 1 if len(db_recv['unames']) + one_more > 10: # 改为10,2015-10-12 # 发现疑似mice,不标注,因为不确定 print '!!! maybe a mice:', address[3].encode( 'utf-8') #, uname['uname'], db_recv['unames'] else: db.recv_addr.insert_one({ 'addr': address[3], 'unames': [uname['uname']] }) #print 'insert', address[2] # 用app_id检查黄牛 appid_count = db.app_user.find({'app_id': app_id}, {'_id': 1}).count() if appid_count > 10 and app_id.strip( ) != '': # app_id 可能为空,新绑定的用户 # 改为10,2015-10-12 # 发现 mice db_mice = db.app_user.find({'app_id': app_id}, {'uname': 1}) mice = [] for m in db_mice: if m['uname'] in app_helper.WHITE_LIST: # 过滤白名单 mice = [] break else: mice.append(m['uname']) db.app_user.update_many({'uname': { '$in': mice }}, {'$set': { 'mice': 1 }}) if mice != []: print '!!! mice by app_id: ', mice return {'ret': -9, 'msg': '黄牛下单1'} # 查黄牛-结束 ########################################################################### # 查找优惠券 # 未查到,则不使用优惠券 coupon = None for i in db_user['coupon']: if i[0] == param['coupon_id']: coupon = list(i) break # 转换cart数据为json,应该有异常捕获 !!! #print param['cart'] cart = json.loads(param['cart']) #print cart if len(cart) == 0: return {'ret': -5, 'msg': '购物车无数据'} if version == 'v2': # v3 不在这生成订单号 if param['order_id'] == '': #cc = 1 #while cc!=None: # # 取得sku计数, 不与线下order共用 # db_sa = db.user.find_one_and_update( # {'uname' : 'settings'}, # {'$inc' : {'app_count' : 1}}, # {'app_count' : 1} # ) # order_id = 'n%06d%s' % (db_sa['app_count'], setting.order_fuffix) # # 防止订单号重复 # cc = db.order_app.find_one({'order_id' : order_id},{'_id':1}) order_id = app_helper.get_new_order_id(version) print 'new order_id', order_id else: order_id = param['order_id'] cc = db.order_app.find_one( { #'uname' : {'$in':uname.values()}, # 防止app的bug,重复order_id 'order_id': order_id, }, { 'status': 1, }) if cc != None and cc['status'] != 'DUE': # 检查订单状态,只有due才可以checkout print "BUG! order_id status" return {'ret': -99, 'msg': '订单状态错误'} # 订单状态:DUE, PAID, ONROAD, COMPLETED, CANCELED, FINISH # 默认运费 5元,免邮门槛 29元 order = { 'status': 'DUE', 'uname': uname['uname'], 'shop': db_shop['_id'], 'user': uname['uname'], 'order_id': order_id if version == 'v2' else '', 'order_source': app_helper.get_devive_type(param['app_id']), 'address': address, # 收货地址 'coupon': coupon, # 使用的优惠券 'cart': [], 'cost': '0.00', # 成本合计,参考 'total': '0.00', # 价格小计,加项 'coupon_disc': '0.00', # 优惠券抵扣,减项 'first_disc': '0.00', # 首单立减, 减项 'delivery_fee': '0.00', # 运费,加项 'due': '0.00', # 应付总金额 2015-11-24 'openid': uname['openid'], 'app_uname': uname['uname'], 'uname_id': db_user['_id'], 'type': 'HOUR', # 订单类型, 2015-11-19 # for processor 'next_status': '', 'lock': 0, 'man': 0, 'retry': 0, 'comment': '', 'b_time': int(time.time()), 'e_time': int(time.time()), 'deadline': int(time.time() + 60 * 15), 'poly_shop': 1 if poly_shop else 0, # 是否匹配到门店 2015-10-18 'credit_total': '0.00', # 余额支付金额 2015-11-24 'wxpay_total': '0.00', # 微信支付金额 'alipay_total': '0.00', # 支付宝支付金额 'use_credit': '0.00', # 部分支付时,余额支付金额 'due3': '0.00', # 第3方应付金额 use_credit + due3 = due } # 统计旧订单数,为0则是首单 2015-09-29 old_order_num = db.order_app.find( { 'user': { '$in': uname.values() }, 'status': { '$nin': ['DUE', 'TIMEOUT', 'CANCEL'] } }, { '_id': 1 }).count() # item = { # “product_id” : “k000011”, # “num” : “5”, # } # 应该只有 k-prod cart_to_return = [] cart_to_return_b3 = [] cate_001 = 0 b3_sku = 0 all_sku = 0 num_change = 0 buy_limit = 0 only_one = 0 for item in cart: is_b3 = False # sku db_sku = db.sku_store.find_one({'product_id': item['product_id']}, { 'app_title': 1, 'is_onsale': 1, 'special_price': 1, 'ref_price': 1, 'maximun': 1, 'list_in_app': 1, }) if db_sku == None: # 应该不会发生 print 'Error: db_sku==None' continue all_sku += 1 if db_sku['list_in_app'] == -3: # B3 整箱预售 # 不启动B3 2015-10-27 r = db.inventory.find_one( # 线上销售要检查库存 { 'product_id' : item['product_id'], 'list_in_app' : {'$ne' : 0}, 'shop' : ObjectId(setting.B3_shop), }, { 'cost_price' : 1, 'ref_prod_id' : 1, 'price' : 1, 'sku' : 1, 'num' : 1, 'category' : 1, 'first_order' : 1 } ) b3_sku += 1 is_b3 = True # 标记是B3商品, v3 elif poly_shop: # 门店库存 r = db.inventory.find_one( # 线上销售要检查库存 { 'product_id' : item['product_id'], 'list_in_app' : {'$ne' : 0}, 'shop' : db_shop['_id'], }, { 'cost_price':1, 'ref_prod_id':1, 'price':1, 'sku':1, 'num':1, 'category':1, 'first_order':1 } ) else: # 不在送货范围 r = None if r: # 如果库存数据中没此sku,会忽略掉,此情况应该不会发生 new_num = int(item['num']) new_num = new_num if new_num <= r['num'] else r['num'] new_num = max(0, new_num) # 发现过小于零的情况,微信 # 检查是不是 001 (水果) 分类 if r['category'] == '001': cate_001 += 1 # 检查是否限购 if db_sku['maximun'] > 0: ''' # 每日限购,生成当天的时间tick tday = app_helper.time_str(format=1) begin_d = '%s 00:00:00' % tday end_d = '%s 23:59:59' % tday begin_t = int(time.mktime(time.strptime(begin_d,"%Y-%m-%d %H:%M:%S"))) end_t = int(time.mktime(time.strptime(end_d,"%Y-%m-%d %H:%M:%S"))) print begin_d, end_d, begin_t, end_t # 检查时间段内购买记录 c = db.order_app.find({ 'uname' : {'$in':uname.values()}, 'order_id' : {'$ne':order_id}, 'status' : {'$ne':'TIMEOUT'}, 'cart.product_id' : item['product_id'], '$and' : [{'b_time' : {'$gt' : begin_t}}, {'b_time' : {'$lt' : end_t}}], }, {'_id':1}).count() print 'findings: ',c if c>0: # 限购商品只允许购买1次 new_num=0 buy_limit += 1 else: new_num=min(new_num, db_sku['maximun']) print 'limit : ',new_num ''' # 每单限购 if new_num > db_sku['maximun']: new_num = db_sku['maximun'] print 'limit : ', new_num # 首单可见商品,非首单用户 2015-09-30 if r.has_key('first_order' ) and r['first_order'] == 1 and old_order_num > 0: # 非首单用户,不让购买,还是有人能买到,靠! new_num = 0 # v3 检查是否是互斥商品 if version == 'v3' and item['product_id'] in app_helper.only_one: if only_one > 0: # 已有互斥商品,此商品清零 new_num = 0 else: only_one += 1 # v3 检查是否买X送Y if version == 'v3' and item[ 'product_id'] in app_helper.buy_X_give_Y.keys(): numX = app_helper.buy_X_give_Y[item['product_id']][0] numY = app_helper.buy_X_give_Y[item['product_id']][1] #new_num = int(item['num']) new_num_give = int(new_num / numX) * numY new_num = new_num if new_num + new_num_give <= r[ 'num'] else int(r['num'] / (numX + numY)) * numX new_num = max(0, new_num) # 预防小于零的情况 new_num_give = int(new_num / numX) * numY # 更新赠品数量 new_item = { 'product_id': item['product_id'], 'num': item['num'], 'num2': new_num, 'price': r['price'], 'title': db_sku['app_title'], } # v3 买X送Y数量 if version == 'v3': if item['product_id'] in app_helper.buy_X_give_Y.keys(): new_item['numyy'] = new_num_give else: new_item['numyy'] = 0 if int(new_num) != int(item['num']): num_change += 1 # 是否有优惠价格 if db_sku['is_onsale']==1 and \ float(db_sku['special_price'])<float(r['price']): # 优惠价格比门店价格低 new_item['price'] = db_sku['special_price'] # 计算总价 item_price = round(new_num * float(new_item['price']), 2) new_item['price'] = '%.2f' % item_price if version == 'v3' and is_b3: cart_to_return_b3.append(new_item) else: cart_to_return.append(new_item) # 返回到app的cart不包含cost cost_price = r['cost_price'] #if item[0][0]=='w': # w-prod 信息都用 u-prod的替换 # new_item['product_id'] = r['ref_prod_id'] # new_item['w_id'] = item[0] # # 查询成本, 从对应u-prod当前成本 # r2 = db.inventory.find_one({ # u-prod # 'shop' : db_shop['shop'], # 'product_id' : r['ref_prod_id'], # }, {'cost_price':1}) # cost_price = r2['cost_price'] # 计算成本 item_cost = round(new_num * float(cost_price), 2) new_item['cost'] = '%.2f' % item_cost # 加入cart order['cart'].append(new_item) # 累计售价和成本 order['total'] = '%.2f' % (float(order['total']) + item_price) order['cost'] = '%.2f' % (float(order['cost']) + item_cost) else: # 店内未找到库存, !!!应该不会发生 new_item = { 'product_id': item['product_id'], 'num': item['num'], 'num2': 0, 'price': '0.00', 'cost': '0.00', 'title': db_sku['app_title'], } cart_to_return.append(new_item) # 返回到app的cart不包含cost order['cart'].append(new_item) # 记录判断数量变化 if int(new_item['num2']) != int(item['num']): num_change += 1 tt = float(order['total']) if tt > 0: # 免邮门槛 if str(order['shop']) in app_helper.delivery_by_shop.keys(): delivery_fee = app_helper.delivery_by_shop[str( order['shop'])]['delivery_fee'] free_delivery = app_helper.delivery_by_shop[str( order['shop'])]['free_delivery'] else: delivery_fee = app_helper.delivery_fee free_delivery = app_helper.free_delivery #if tt<29: # 免邮门槛 29 if tt < free_delivery: # 免邮门槛 order['delivery_fee'] = '%.2f' % delivery_fee # 运费5元 # 首单立减 first_promote元, 商品总额大于 first_promote_threshold元 if cate_001 > 0 and old_order_num == 0: # 符合首单条件,且有一个水果商品 print '首单' if str(db_shop['_id']) in app_helper.first_promote2_shop and \ (tt+float(order['delivery_fee']))>=app_helper.first_promote2_threshold: # 站点落在 指定站点范围内,使用首单立减2 print '首单立减 - 指定站点' order['first_disc'] = '%.2f' % app_helper.first_promote2 elif (tt + float(order['delivery_fee']) ) >= app_helper.first_promote_threshold: # 其他站点使用首单立减1 print '首单立减' order['first_disc'] = '%.2f' % app_helper.first_promote # 优惠券, 检查有效期, 优惠券门槛为10元 if float(order['first_disc'])==0.0 and coupon!=None and \ coupon[3]==1 and app_helper.time_str(format=1)<=coupon[1]: print '检查抵用券' if len(coupon) > 5 and coupon[5] == 'apple' and cate_001 < 1: # 水果券,但没有水果 2015-09-29 print '水果券没水果' order['coupon'] = None elif len(coupon) > 5 and coupon[5] == 'b3' and b3_sku < 1: # 整箱券,但没有整箱 2015-10-18 print '整箱券没整箱' order['coupon'] = None else: if len(coupon) > 4: # (id, 有效期, 金额, 是否已用, 门槛) 2015-09-27 # 有门槛信息,使用优惠券门槛信息 if (tt + float(order['delivery_fee'])) < coupon[4]: order['coupon'] = None else: order['coupon_disc'] = coupon[2] else: # 使用默认条件 if float(coupon[2]) == 6.0 and ( tt + float(order['delivery_fee'])) < 29.9: order['coupon'] = None elif float(coupon[2]) == 9.0 and ( tt + float(order['delivery_fee'])) < 39.9: order['coupon'] = None elif (tt + float(order['delivery_fee'])) < 14.9: order['coupon'] = None else: order['coupon_disc'] = coupon[2] else: order['coupon'] = None # 计算应付:价格合计 - 优惠券 - 首单立减 + 运费 print(tt + float(order['delivery_fee']) - float(order['coupon_disc']) - float(order['first_disc'])) print tt, float(order['delivery_fee']), float( order['coupon_disc']), float(order['first_disc']) order['due'] = '%.2f' % (tt + float(order['delivery_fee']) - float( order['coupon_disc']) - float(order['first_disc'])) # 不能是负的, 要付一点 if float(order['due']) <= 0: order['due'] = '0.10' # 是否使用余额(部分)支付, 2015-11-19 if param.has_key('use_credit') and param['use_credit'] == '1': # 使用余额 my_due = float(order['due']) my_credit = db_user.get('credit', 0.0) if my_credit > my_due: order['due3'] = '0.00' order['use_credit'] = '%.2f' % my_due else: order['due3'] = '%.2f' % (my_due - my_credit) order['use_credit'] = '%.2f' % my_credit else: order['use_credit'] = '0.00' order['due3'] = order['due'] # 准备可用的优惠券 2015-09-11 coupon_list = [] for i in db_user['coupon']: if app_helper.time_str(format=1) > i[1]: # 过期抵用券 continue elif i[3] != 1: continue # 检查优惠券条件 b3_sku if tt > 0 and float(order['first_disc']) == 0.0: if len(i) > 5 and i[5] == 'apple' and cate_001 < 1: # 水果券没水果 continue if len(i) > 5 and i[5] == 'b3' and b3_sku < 1: # 整箱券没整箱 2015-10-18 continue if len(i) > 4: # 带门槛优惠券 if (tt + float(order['delivery_fee'])) < i[4]: continue else: # 过滤不符合条件的优惠券 if float(i[2]) == 6.0 and ( tt + float(order['delivery_fee'])) < 29.9: continue elif float(i[2]) == 9.0 and ( tt + float(order['delivery_fee'])) < 39.9: continue elif (tt + float(order['delivery_fee'])) < 14.9: continue coupon_list.append({ 'id': i[0], 'valid': i[1], 'cash': i[2], 'status': 'unused', 'msg1': '条件1', 'msg2': '条件2', }) coupon_list = quick(coupon_list) # 如果没有,则insert #db.order_app.replace_one({'order_id':order_id}, order, upsert=True) if version == 'v2': db.order_app.update_one({'order_id': order_id}, { '$set': order, '$push': { 'history': (app_helper.time_str(), uname['uname'], '提交结算') } }, upsert=True) elif version == 'v3': db.app_user.update_one( {'uname': uname['uname']}, {'$set': { 'cart_order.%s' % param['session']: order }}) # 提示信息 #print all_sku, b3_sku if poly_shop == False: msg_alert = True if b3_sku > 0: if all_sku > b3_sku: #message = '很抱歉,普通商品无法配送到当前地址,商品已更新' #,整箱预售商品可正常购买' msg_alert = False message = '' else: # 只有 b3 商品时不提醒 msg_alert = False message = '' else: message = '很抱歉,收货地址不在配送范围内,购物车商品已清空' else: if num_change > 0: msg_alert = True message = '库存不足,已更新商品数量,请查看' elif buy_limit > 0: msg_alert = True message = '部分商品限购,已更新商品数量,请查看' else: msg_alert = False message = '' if version == 'v2': ret_json = { # 返回结果,实际有库存的结果, 'ret': 0, 'data': { 'order_id': order['order_id'], 'shop_id': str(order['shop']), 'shop': db_shop['name'], # 可能会变,如果地址与门店不匹配的时候 'addr_id': address[0], 'cart_num': len(order['cart']), 'cart': cart_to_return, 'total': order['total'], 'coupon_list': coupon_list, # 可用的优惠券 'coupon': coupon[0] if order['coupon'] else '', 'coupon_disc': order['coupon_disc'], 'first_disc': order['first_disc'], 'delivery_fee': order['delivery_fee'], 'due': order['due'], 'credit': '%.2f' % db_user.get('credit', 0.0), 'alert': msg_alert, 'message': message, } } elif version == 'v3': hh = time.localtime().tm_hour if hh >= 9 and hh < 20: alert_title = False cart_title = '' else: alert_title = True if hh >= 20 and hh <= 23: cart_title = '目前是掌柜打烊时间,预计明日9点送出' else: cart_title = '目前是掌柜打烊时间,预计今日9点送出' if b3_sku > 0: if hh < 16: # 明天 tomorrow_tick = int(time.time()) + 3600 * 24 tomorrow = time.strftime("%m月%d日", time.localtime(tomorrow_tick)) cart_title_b3 = '以下预售商品,预计明天%s送达' % tomorrow else: # 后天 the_day_after_tick = int(time.time()) + 3600 * 24 * 2 the_day_after = time.strftime( "%m月%d日", time.localtime(the_day_after_tick)) cart_title_b3 = '以下预售商品,预计后天%s送达' % the_day_after else: cart_title_b3 = '' ret_json = { # 返回结果,实际有库存的结果, 'ret': 0, 'data': { 'shop_id': str(order['shop']), 'shop': db_shop['name'], # 可能会变,如果地址与门店不匹配的时候 'addr_id': address[0], 'cart_num': len(order['cart']), 'cart': cart_to_return, 'cart_b3': cart_to_return_b3, 'total': order['total'], 'coupon_list': coupon_list, # 可用的优惠券 'coupon': coupon[0] if order['coupon'] else '', 'coupon_disc': order['coupon_disc'], 'first_disc': order['first_disc'], 'delivery_fee': order['delivery_fee'], 'due': order['due3'], # 返回的事第3方需支付的金额 2015-11-24 'use_credit': order['use_credit'], # 使用余额的金额 2015-11-19 'credit': '%.2f' % db_user.get('credit', 0.0), 'alert': msg_alert, 'message': message, 'alert_title': alert_title, 'cart_title': cart_title, 'alert_title_b3': True, 'cart_title_b3': cart_title_b3, } } print ret_json return ret_json
def POST(self): web.header('Content-Type', 'application/json') param = web.input(session_id='', pay_sum='', pay_type='') if param.session_id=='': return json.dumps({'ret' : -1, 'msg' : 'session_id参数错误'}) uname = app_helper.wx_logged(param.session_id) if uname is None: return json.dumps({'ret' : -4, 'msg' : '无效的session_id'}) if '' in (param.pay_sum, param.pay_type): return json.dumps({'ret' : -2, 'msg' : '参数错误'}) if not param['pay_sum'].isdigit(): return json.dumps({'ret' : -2, 'msg' : '参数错误'}) if int(param.pay_type)==3: pay_type='wxpay' else: return json.dumps({'ret' : -5, 'msg' : '错误的pay_type'}) #-------------------------------------------------- #生产充值流水号 deposit_order_id = app_helper.get_new_order_id('vx','d').encode('utf-8') print 'new deposit_order_id', deposit_order_id wx_total_fee = '%d'%int(param['pay_sum']) ali_total_fee = '%.2f'%float(int(wx_total_fee)/100.0) # 微信支付,获得prepay信息 if pay_type=='wxpay': if web.ctx.has_key('environ'): client_ip = web.ctx.environ['REMOTE_ADDR'] else: return json.dumps({'ret' : -7, 'msg' : '无法取得客户端ip地址'}) r = wxpay_helper.get_prepay_id(wx_appid, mch_id, 'JSAPI', client_ip, deposit_order_id, wx_total_fee, uname['openid'].encode('utf-8')) if r.status==200: wx_prepay_data = r.data else: return json.dumps({'ret' : -6, 'data' : r.status}) # 获取prepay信息错误 else: wx_prepay_data = '' print wx_prepay_data # 生成充值订单 new_deposit_order = { 'userid' : uname['userid'], 'recharge_id' : deposit_order_id, 'order_trade_flow_id' : '', # 交易记录的id,收到钱时候才填 'create_time' : app_helper.time_str(), 'recharge_sum' : wx_total_fee, # 实际充值金额, 如果有满送,在这里处理 'due' : wx_total_fee, # 实际应付的金额,支付成功时会核对这个金额 'pay_type' : pay_type, 'status' : 'DUE', 'wx_prepay_data' : wx_prepay_data, 'deadline' : int(time.time())+60*15, } db.order_recharge.update_one( {'recharge_id' : deposit_order_id}, {'$set' : new_deposit_order}, upsert=True ) ret_data = { 'order_trade_id' : deposit_order_id, # 实际返回的是充值订单号 'pay_type' : int(param.pay_type), 'notify_url' : '', # 支付宝和微信的异步通知回调url } # 回调地址 ret_data['notify_url'] = notify_url_wx print notify_url_wx if wx_prepay_data!='': try: import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET xml=ET.fromstring(wx_prepay_data) ret_data['appid'] = xml.find('appid').text if xml.find('appid') is not None else '' ret_data['mch_id'] = xml.find('mch_id').text if xml.find('mch_id') is not None else '' ret_data['prepay_id'] = xml.find('prepay_id').text if xml.find('prepay_id') is not None else '' # 返回 return json.dumps({ 'ret' : 0, 'data' : ret_data, })
def POST(self, version='v3'): web.header('Content-Type', 'application/json') if version not in ('v2', 'v3'): return json.dumps({'ret': -999, 'msg': '版本错误!'}) print 'version=', version param = web.input(app_id='', session='', order_id='', total='', note='', sign='') if '' in (param.app_id, param.session, param.total, param.sign): return json.dumps({'ret': -2, 'msg': '参数错误'}) uname = app_helper.app_logged(param.session) # 检查session登录 if uname: #验证签名 md5_str = app_helper.generate_sign([ param.app_id, param.session, param.order_id, param.total, param.note ]) if md5_str != param.sign: return json.dumps({'ret': -1, 'msg': '签名验证错误'}) #db_shop = db.base_shop.find_one({'_id':ObjectId(setting.default_shop)},{'name':1}) if len(param.order_id) > 0: print param.order_id db_order = db.order_app.find_one({'order_id': param.order_id}) if db_order['status'] != 'DUE': print '============================== -100' return json.dumps({'ret': -100, 'msg': '订单状态变化,请确认'}) ret_json = checkout( version, uname, { 'session': param.session, 'order_id': param.order_id, 'shop_id': str(db_order['shop']), 'addr_id': db_order['address'][0], 'coupon_id': db_order['coupon'][0] if float(db_order['coupon_disc']) > 0 else '', 'cart': json.dumps(db_order['cart']), 'app_id': param.app_id, 'use_credit': '1' if float(db_order.get('use_credit', '0')) > 0 else '', #2015-11-19 }) if ret_json['ret'] < 0: # checkout 出错 return json.dumps({ 'ret': ret_json['ret'], 'msg': ret_json['msg'] }) if float(ret_json['data']['due']) != float( db_order.get( 'due3', db_order['due'])): # 返回的是需第三方支付的金额,所有比对due3,而不是due # checkout后金额有变化,说明库存或优惠券有变化 db.order_app.update_one({'order_id': param.order_id}, { '$set': { 'status': 'CANCEL' }, '$push': { 'history': (app_helper.time_str(), uname['uname'], '订单取消(支付宝)') } }) print '============================== -100' return json.dumps({ 'ret': -100, 'msg': '很抱歉,数据异常,订单已取消,请重新下单' }) # 可支付 db.order_app.update_one({'order_id': param.order_id}, { '$push': { 'history': (app_helper.time_str(), uname['uname'], '提交支付宝支付2') } }) return json.dumps({'ret': 0, 'order_id': param.order_id}) else: # 生成order_id order_id = app_helper.get_new_order_id(version) print 'new order_id', order_id # 生成新订单 db_cart = db.app_user.find_one( {'uname': uname['uname']}, {'cart_order.%s' % param.session: 1}) new_order = dict(db_cart['cart_order'][param.session]) new_order['order_id'] = order_id new_order['status'] = 'DUE' new_order['user_note'] = param.note.strip() new_order['history'] = [(app_helper.time_str(), uname['uname'], '提交支付宝支付')] ret_json = checkout( version, uname, { 'session': param.session, 'order_id': order_id, 'shop_id': str(new_order['shop']), 'addr_id': new_order['address'][0], 'coupon_id': new_order['coupon'][0] if float(new_order['coupon_disc']) > 0 else '', 'cart': json.dumps(new_order['cart']), 'app_id': param.app_id, 'use_credit': '1' if float(new_order.get('use_credit', '0')) > 0 else '', #2015-11-23 }) if ret_json['ret'] < 0: # checkout 出错 return json.dumps({ 'ret': ret_json['ret'], 'msg': ret_json['msg'] }) if float(ret_json['data']['due']) != float( new_order.get('due3', new_order['due'])): # checkout后金额有变化,说明库存或优惠券有变化 print '============================== -100' return json.dumps({'ret': -100, 'msg': '很抱歉,数据异常,请重新下单'}) db.order_app.insert_one(new_order) return json.dumps({'ret': 0, 'order_id': order_id}) else: return json.dumps({'ret': -4, 'msg': '无效的session'})
def POST(self): web.header('Content-Type', 'application/json') param = web.input(openid='', session_id='', pt_order_id='', order_id='', type='', total='') print param if '' in (param.total, param.type): return json.dumps({'ret' : -2, 'msg' : '参数错误'}) if web.ctx.has_key('environ'): client_ip = web.ctx.environ['REMOTE_ADDR'] else: return json.dumps({'ret' : -5, 'msg' : '无法取得客户端ip地址'}) if param.openid=='' and param.session_id=='': return json.dumps({'ret' : -2, 'msg' : '参数错误1'}) # 同时支持openid和session_id if param.openid!='': uname = app_helper.check_openid(param.openid) else: uname = app_helper.wx_logged(param.session_id) if uname: db_shop = db.base_shop.find_one({'_id':ObjectId(setting.default_shop)},{'name':1}) db_session = db.app_sessions.find_one({'session_id':param.session_id},{'ticket':1}) ticket = db_session.get('ticket','') # 修改为付款的过期订单 r = db.order_app.update_many({ 'uname' : {'$in' : uname.values()}, 'status' : 'DUE', 'deadline' : {'$lt':int(time.time())} }, {'$set': {'status':'TIMEOUT'}}) # 统一下单接口获取 prepay_id nonce_str = app_helper.my_rand(30) body = 'U掌柜app' trade_type = 'JSAPI' if len(param.order_id)>0: #order_id = '%s_%d' % (param.order_id.encode('utf-8'), int(time.time())) order_id = param.order_id.encode('utf-8') else: # 生成order_id, 2015-10-29 order_id = app_helper.get_new_order_id('x').encode('utf-8') # 拼团订单 t 开头 if param.type=='TUAN': order_id = 't'+order_id[1:] total_fee = param.total.encode('utf-8') openid = uname['openid'].encode('utf-8') para = [ ('appid' , wx_appid), ('body' , body), ('mch_id' , mch_id), ('nonce_str' , nonce_str), ('notify_url' , notify_url), ('openid' , openid), ('out_trade_no' , order_id), ('spbill_create_ip' , client_ip), ('total_fee' , total_fee), ('trade_type' , trade_type) ] #print para stringA = '&'.join('%s=%s' % i for i in para) stringSignTemp = '%s&key=%s' % (stringA, api_key) sign = hashlib.md5(stringSignTemp).hexdigest().upper() para_xml = '<xml>' \ '<appid>'+wx_appid+'</appid>' \ '<mch_id>'+mch_id+'</mch_id>' \ '<nonce_str>'+nonce_str+'</nonce_str>' \ '<sign>'+sign+'</sign>' \ '<body>'+body+'</body>' \ '<out_trade_no>'+order_id+'</out_trade_no>' \ '<total_fee>'+total_fee+'</total_fee>' \ '<spbill_create_ip>'+client_ip+'</spbill_create_ip>' \ '<notify_url>'+notify_url+'</notify_url>' \ '<trade_type>'+trade_type+'</trade_type>' \ '<openid>'+openid+'</openid>' \ '</xml>' print para_xml #return json.dumps({'ret' : 0, 'data' : 'here'}) urllib3.disable_warnings() pool = urllib3.PoolManager(num_pools=2, timeout=180, retries=False) url = 'https://api.mch.weixin.qq.com/pay/unifiedorder' r = pool.urlopen('POST', url, body=para_xml) if r.status==200: data = r.data print data # 检查和生成订单 if len(param.order_id)>0: db_order = db.order_app.find_one({'order_id':param.order_id}) if db_order['status']!='DUE': print '============================== -100' return json.dumps({'ret' : -100, 'msg' : '订单状态变化,请确认'}) # 再次 checkout if param.type=='TUAN': ret_json = pt_checkout( uname, { 'region_id' : db_order['region_id'], 'addr_id' : db_order['address'][0], 'coupon_id' : db_order['coupon'][0] if float(db_order['coupon_disc'])>0 else '', 'cart' : json.dumps(db_order['cart']), 'pt_order_id' : db_order['pt_order_id'], }) if ret_json['ret']<0: # checkout 出错 return json.dumps({'ret' : ret_json['ret'], 'msg' : ret_json['msg']}) else: ret_json = checkout( uname, { 'shop_id' : str(db_order['shop']), 'addr_id' : db_order['address'][0], 'coupon_id' : db_order['coupon'][0] if float(db_order['coupon_disc'])>0 else '', 'cart' : json.dumps(db_order['cart']), 'order_id' : db_order['order_id'], }) if ret_json['ret']<0: # checkout 出错 return json.dumps({'ret' : ret_json['ret'], 'msg' : ret_json['msg']}) if float(ret_json['data']['due'])!=float(db_order['due']): # checkout后金额有变化,说明库存或优惠券有变化 db.order_app.update_one({'order_id':param.order_id},{ '$set' : {'status': 'CANCEL'}, '$push' : {'history':(app_helper.time_str(), uname['uname'], '订单取消(微信支付)')} }) print '============================== -100' return json.dumps({'ret' : -100, 'msg' : '很抱歉,数据异常,订单已取消,请重新下单'}) # 可支付 db.order_app.update_one({'order_id':param.order_id},{ '$set' : {'wx_out_trade_no':order_id}, '$push' : {'history':(app_helper.time_str(), uname['openid'], '提交微信支付2')} }) if param.type=='TUAN': # 拼团订单 return json.dumps({ 'ret' : 0, 'order_id' : param.order_id, 'pt_order_id' : db_order['pt_order_id'], 'position' : db_order['position'], 'data' : data, 'ticket' : ticket }) else: # 1小时订单 return json.dumps({ 'ret' : 0, 'order_id' : param.order_id, 'data' : data, 'ticket' : ticket }) else: # 生成新订单 db_cart = db.app_user.find_one({'openid':uname['openid']},{'cart_order_wx':1}) if param.type=='TUAN': # 拼团订单 if not db_cart.has_key('cart_order_wx'): print 'fail: 不该发生, 缺少购物车数据' return json.dumps({'ret' : -9, 'msg' : '系统错误,请重试!'}) new_order = dict(db_cart['cart_order_wx'][0]) new_order['order_id']=order_id new_order['status']='DUE' new_order['user_note']=param.note.strip() new_order['wx_out_trade_no']=order_id new_order['history']=[(app_helper.time_str(), uname['openid'], '提交微信支付')] # 如果是新开团,添加pt_order if len(db_cart['cart_order_wx'])>1: new_pt_order = dict(db_cart['cart_order_wx'][1]) new_pt_order['pt_order_id']='pt'+order_id[1:] new_pt_order['status']='WAIT' new_pt_order['history']=[(app_helper.time_str(), uname['openid'], '等待开团')] db.pt_order.insert_one(new_pt_order) # 订单数据里添加 pt_order_id new_order['pt_order_id']=new_pt_order['pt_order_id'] # 再次 checkout ret_json = pt_checkout( uname, { 'region_id' : new_order['region_id'], 'addr_id' : new_order['address'][0], 'coupon_id' : new_order['coupon'][0] if float(new_order['coupon_disc'])>0 else '', 'cart' : json.dumps(new_order['cart']), 'pt_order_id' : new_order['pt_order_id'], }) if ret_json['ret']<0: print 'checkout 检查未通过,不能支付' return json.dumps({'ret' : -9, 'msg' : ret_json['msg']}) db.order_app.insert_one(new_order) return json.dumps({ 'ret' : 0, 'order_id' : new_order['order_id'], 'pt_order_id' : new_order['pt_order_id'], 'position' : new_order['position'], # 测试 'data' : data, 'ticket' : ticket }) else: # 1小时订单 new_order = dict(db_cart['cart_order_wx']) new_order['order_id']=order_id new_order['status']='DUE' new_order['user_note']=param.note.strip() new_order['wx_out_trade_no']=order_id new_order['history']=[(app_helper.time_str(), uname['openid'], '提交微信支付')] # 再次 checkout ret_json = checkout( uname, { 'shop_id' : str(new_order['shop']), 'addr_id' : new_order['address'][0], 'coupon_id' : new_order['coupon'][0] if float(new_order['coupon_disc'])>0 else '', 'cart' : json.dumps(new_order['cart']), 'order_id' : new_order['order_id'], }) if ret_json['ret']<0: print 'checkout 检查未通过,不能支付' return json.dumps({'ret' : -9, 'msg' : ret_json['msg']}) if float(ret_json['data']['due'])!=float(new_order['due']): # checkout后金额有变化,说明库存或优惠券有变化 print '============================== -100' return json.dumps({'ret' : -100, 'msg' : '很抱歉,数据异常,请重新下单'}) db.order_app.insert_one(new_order) return json.dumps({ 'ret' : 0, 'order_id' : order_id, 'data' : data, 'ticket' : ticket }) else: return json.dumps({'ret' : -1, 'data' : r.status}) else: return json.dumps({'ret' : -4, 'msg' : '无效的openid'})
def u_new_order(order_id): order_app_db = db.order_app.find_one({'elm_order_id': order_id}, {'order_id': 1}) if order_app_db: print 'elm ********* 订单已存在' return 'ok' else: restaurant_info_path_url = "/order/{0}/".format(order_id) method = 'GET' params = {} response = elm_helper.elm_port(restaurant_info_path_url, params, method) dict = json.loads(response) if dict['code'] == 200: print dict['data'] detail = dict['data']['detail'] #print dict['data']['restaurant_id'] address = [ 'elm', dict['data']['consignee'], dict['data']['phone_list'][0], #dict['data']['address'], #dict['data']['address'].encode('utf-8')+'('+dict['data']['delivery_poi_address'].encode('utf-8')+')', dict['data']['delivery_poi_address'] if dict['data']['delivery_poi_address'] != None else dict['data']['address'], ] status = 'PAID' '''根据restaurant_id查询shop_id''' shop_id = db_rep.shop_restaurant.find_one( {'elm_restaurant_id': dict['data']['restaurant_id']}, {'shop_id': 1}) print 'elm *********** shop_id: ', shop_id if shop_id == None: print 'elm ???????????? 未找到 restaurant_id' return 'error' order_id = 'e' + app_helper.get_new_order_id( 've') # 新订单号逻辑 2015-10-24 delivery_fee = dict['data']['deliver_fee'] first_disc = 0.0 cost = 0.0 first_disc = 0.0 user = '******' due = dict['data']['original_price'] history = [[ dict['data']['created_at'], dict['data']['phone_list'][0], '饿了吗接单' ]] retry = 0 #print dict['data']['created_at'],type(dict['data']['created_at']) e_time = int( time.mktime( time.strptime(dict['data']['created_at'], '%Y-%m-%d %H:%M:%S'))) b_time = int( time.mktime( time.strptime(dict['data']['created_at'], '%Y-%m-%d %H:%M:%S'))) coupon = [] uname = 'elm' coupon_disc = 0.0 comment = '' man = 0 pay = dict['data']['original_price'] paid_tick = int( time.mktime( time.strptime(dict['data']['created_at'], '%Y-%m-%d %H:%M:%S'))) change = 0.0 paid_time = dict['data']['created_at'] deadline = int( time.mktime( time.strptime(dict['data']['created_at'], '%Y-%m-%d %H:%M:%S'))) lock = 0 next_status = '' paid2_tick = int( time.mktime( time.strptime(dict['data']['created_at'], '%Y-%m-%d %H:%M:%S'))) paid2_time = dict['data']['created_at'] pay_type = 'elm' user_note = dict['data']['description'] cart = [] elm_order_id = dict['data']['order_id'] total = 0 b2 = [] # C端商品 2015-10-09 b3 = [] # B3整箱预售商品 2015-10-09 b3_total = 0.0 # 2015-10-09 for g2 in detail['group']: for g in g2: # 可能多个篮子 '''根据shop_id和elm_food_id查询produc_id''' product_id_db = db_rep.product_category.find_one( { 'shop': shop_id['shop_id'], 'elm_food_id': g['id'] }, {'product_id': 1}) if product_id_db == None: print 'elm ???????????? 未找到elm_food_id', g['id'] return 'error' print 'elm *********** food_id: ', g['id'] num = g['quantity'] num2 = g['quantity'] title = g['name'] price = g['quantity'] * g['price'] total += price item = { "cost": cost, "product_id": product_id_db['product_id'], "num2": num2, "title": title, "price": price, "num": num, 'elm_food_id': g['id'] } #cart.append(item) # 记录销售量 db.sku_store.update_one( {'product_id': item['product_id']}, {'$inc': { 'volume': float(item['num2']) }}) r3 = db.sku_store.find_one( {'product_id': item['product_id']}, {'list_in_app': 1}) if r3['list_in_app'] == -3: # B3商品不需要改库存 # -3 不启动B3销售 2015-10-27 b3_total += float(item['price']) b3.append(item) item['title'] = item['title'] + u'(整箱预售,次日送达)' b2.append(item) continue # 买X送Y if item['product_id'] in app_helper.buy_X_give_Y.keys(): print 'elm 买X送Y' numX = app_helper.buy_X_give_Y[item['product_id']][0] numY = app_helper.buy_X_give_Y[item['product_id']][1] item['numyy'] = int(item['num2'] / numX) * numY # 赠 else: item['numyy'] = 0 #if item['product_id'] in app_helper.buy_1_give_1: # print '买一送一' # lc_num2 = float(item['num2']) # item['num2'] = int(lc_num2 + lc_num2) # item['title'] = item['title'].replace(u'买一送一',u'特惠活动') # 过滤数量价格为零的 if item['num2'] == 0 and float(item['price']) == 0.0: continue # num2 实际购买数量, numyy 赠送数量, v3之后才有munyy 2015-10-20 num_to_change = float(item['num2']) + float( item.get('numyy', 0.0)) r2 = db.inventory.find_one_and_update( # 不检查库存,有可能负库存 { 'product_id' : item['product_id'], 'shop' : shop_id['shop_id'], }, { '$inc' : { 'num' : 0-num_to_change, # num2 实际购买数量 'pre_pay_num' : num_to_change, # 记录预付数量 } #'$push' : { 'history' : (helper.time_str(), # helper.get_session_uname(), '售出 %s' % str(item['num']))}, }, {'_id':1} ) #print r if r2 == None: # 不应该发生 print 'elm *********** 修改库存失败,请联系管理员!' return 'ok' #return json.dumps({'ret' : -9, 'msg' : '修改库存失败,请联系管理员!'}) else: b2.append(item) #print shop_id['shop_id'],'===' #print product_id_db['product_id'] #print g['id'] # 更新elm库存数据 app_helper.elm_modify_num(shop_id['shop_id'], item['product_id']) # 新的订单信息 r = { 'address': address, 'b_time': b_time, 'cart': b2, #cart, 'comment': comment, 'cost': '%.2f' % cost, 'coupon': coupon, 'coupon_disc': '%.2f' % coupon_disc, 'deadline': deadline, 'delivery_fee': '%.2f' % delivery_fee, 'due': '%.2f' % due, 'e_time': e_time, 'first_disc': '%.2f' % first_disc, 'history': history, 'lock': lock, 'man': man, 'next_status': next_status, 'order_id': order_id, 'order_source': 'elm', 'paid2_tick': paid2_tick, 'paid2_time': paid2_time, 'paid_tick': paid_tick, 'paid_time': paid_time, 'pay': '%.2f' % pay, 'pay_type': pay_type, 'retry': retry, 'shop': shop_id['shop_id'], 'status': status, 'total': '%.2f' % total, 'uname': uname, 'user': user, 'elm_order_id': elm_order_id, 'user_note': user_note, 'type': 'HOUR', 'credit_total': '0.00', # 余额支付金额 2015-11-24 'wxpay_total': '0.00', # 微信支付金额 'alipay_total': '0.00', # 支付宝支付金额 'use_credit': '0.00', # 部分支付时,余额支付金额 'due3': '0.00', # 第3方应付金额 use_credit + due3 = due } # 检查是否有b3商品, 3种情况 # 1. b2, b3 都有,拆单 # 2. 只有b3,站点改为B3站点,保留收货站点 # 3. 只有b2,保持订单不变 #print b2 #print b3 if len(b3) > 0 and (len(b2) - len(b3)) > 0: # 情况1 print "elm 拆单" r4 = r.copy() r4['order_id'] = r4['order_id'] + u'-b3' r4['shop_0'] = r['shop'] r4['shop'] = ObjectId(setting.B3_shop) r4['cart'] = b3 r4['status'] = status r4['elm_order_id'] = elm_order_id # 饿了吗 订单号 r4['paid_time'] = app_helper.time_str() r4['paid_tick'] = int(time.time()) r4['history'] = [(app_helper.time_str(), 'elm_port', 'elm-拆单')] r4['total'] = '%.2f' % b3_total r4['cost'] = '0.00' r4['coupon_disc'] = '0.00' r4['first_disc'] = '0.00' r4['delivery_fee'] = '0.00' r4['due'] = '0.00' db.order_app.insert_one(r4) # 增加子订单 elif len(b3) > 0: # 情况 2 print "elm 订单改到B3站点" db.order_app.update_one({'order_id': order_id}, { '$set': { 'shop_0': r['shop'], 'shop': ObjectId(setting.B3_shop), } }) else: # 情况3,什么都不做 print "elm 订单保持不变" print 'elm *********** order_id: ', order_id '''将查询的订单详情插入U掌柜数据库中''' db.order_app.insert_one(r) return 'ok' else: print 'elm ???????????? elm 订单拉取失败' print dict return 'error'