# -*- coding: utf-8

''' 封装银联的相关交互 '''

import datetime
import requests
import hashlib

import urlparse

import config as config


def trade(order_id, amount, order_time):
    ''' 交易接口

    参数

        order_id - 交易ID
        amount - 交易实际金额
        order_time - 交易时间,datetime类型

    返回

        成功 - 返回结果字典
        失败 - 返回None

    '''

    order_timeout = datetime.datetime.now() + datetime.timedelta(minutes=5)

    req = {
        'version': config.version,
        'charset': config.charset,
        'transType': '01',
        'merId': config.mer_id,
        'backEndUrl': config.mer_backend_url,
        'orderTime': datetime.datetime.strftime(order_time, "%Y%m%d%H%M%S"),
        'orderTimeout': datetime.datetime.strftime(order_timeout, "%Y%m%d%H%M%S"),
        'orderNumber': str(order_id),
        # 要求金额字段为 包含角和分、没有小数点的字符串
        'orderAmount': str(amount * 100),
    }

    r = requests.post(config.trade_url, build_req(req))

    if r.status_code == 200:
        return parse_response(r.text)
    else:
        return None


def query(order_id, order_time):
    ''' 查询接口

    参数

        order_id - 交易ID
        order_time - 交易时间,datetime类型

    返回

        成功 - 返回结果字典
        失败 - 返回None

    '''

    req = {
        'version': config.version,
        'charset': config.charset,
        'transType': '01',
        'merId': config.mer_id,
        'backEndUrl': config.mer_backend_url,
        'orderTime': datetime.datetime.strftime(datetime.datetime.now(), "%Y%m%d%H%M%S"),
        'orderNumber': str(order_id),
    }

    r = requests.post(config.query_url, build_req(req))
    if r.status_code == 200:
        return parse_response(r.text)
    else:
        return None


def parse_response(text):
    ''' 处理后台回调返回

    参数

        text - http POST请求包体

    返回

        成功 - 返回结果字典
        失败 - 返回None

    '''

    urlparse.parse_qs(text.encode('ASCII'))

    d = build_dict(text)

    if verify_response(text):
        return d

    return None


def build_sign_str(d):
    ''' 生成升序排列的字符串

    0 - 普通模式
    1 - 签名模式

    '''

    req = []
    for key in sorted(d.keys()):
        if key not in [config.field_signature, config.field_sign_method] and d[key] != '':
            req.append("%s=%s" % (key, d[key]))

    return '&'.join(req)


def build_dict(text):
    d = urlparse.parse_qs(text.encode('ASCII'))

    ret = {}
    for key in d.keys():
        if isinstance(d[key], list) and len(d[key]) == 1:
            ret[key] = d[key][0]
        else:
            ret[key] = d[key]

    return ret


def build_req(d):
    ''' 对输入参数字典,进行签名处理,并生成字符串'''

    req_str = build_sign_str(d)
    d[config.field_sign_method] = config.sign_method
    d[config.field_signature] = build_signature(req_str)

    return d


def build_signature(text):
    ''' 进行签名 '''

    sign_str = text + "&" + hashlib.md5(config.secret_key).hexdigest().lower()
    return hashlib.md5(sign_str).hexdigest().lower()


def verify_response(text):
    ''' 验证返回 '''

    d = build_dict(text)

    rep_str = build_sign_str(d)
    signature = build_signature(rep_str)

    return signature == d.get('signature', '')

if __name__ == '__main__':
    order_id = datetime.datetime.strftime(datetime.datetime.now(), "%H%M%S%f")
    order_time = datetime.datetime.now()

    print '----- begin trade -----'

    print trade(order_id, 1000, order_time)

    print '----- begin query -----'

    print query(order_id, order_time=order_time)