package tonglianpayapi

import (
	"crypto/md5"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi"
	"net/http"
	"sort"
	"strings"
)

const (
	prodURL     = "https://vsp.allinpay.com/apiweb"
	prodURL2    = "https://syb.allinpay.com/apiweb"
	sepcAction  = "unitorder/pay"
	sepcAction2 = "h5unionpay/unionorder"

	sigKey           = "sign"
	PayTypeWxXcx     = "W06" // 小程序支付
	PayTypeWxCode    = "W01" // 微信支付
	PayTypeZfbApp    = "A03" // 支付宝小程序
	PayTypeZfbQrcode = "A01" // 支付宝支付
	PayTypeZfbJS     = "A02"
	PayTypeH5        = "H5"

	ResponseCodeSuccess = "SUCCESS"
	ResponseCodeFail    = "FAIL"
)

type API struct {
	appID  string
	cusID  string
	appKey string

	client *http.Client
	config *platformapi.APIConfig
}

func New(appID, appKey, cusID string, config ...*platformapi.APIConfig) *API {
	curConfig := platformapi.DefAPIConfig
	if len(config) > 0 {
		curConfig = *config[0]
	}
	return &API{
		appID:  appID,
		appKey: appKey,
		cusID:  cusID,
		client: &http.Client{Timeout: curConfig.ClientTimeout},
		config: &curConfig,
	}
}

func (a *API) signParam(params map[string]interface{}) (sig string) {
	var valueList []string
	for k, v := range params {
		if k != sigKey {
			if str := fmt.Sprint(v); str != "" {
				valueList = append(valueList, fmt.Sprintf("%s=%s", k, str))
			}
		}
	}
	valueList = append(valueList, fmt.Sprintf("key=%s", a.appKey))
	sort.Sort(sort.StringSlice(valueList))
	sig = strings.Join(valueList, "&")
	binSig := md5.Sum([]byte(sig))
	sig = fmt.Sprintf("%X", binSig)
	return sig
}

type CreateUnitorderOrderParam struct {
	CusID     string `json:"cusid"`
	AppID     string `json:"appid"`
	Trxamt    int    `json:"trxamt"`    //交易金额 单位为分
	Reqsn     string `json:"reqsn"`     //商户交易单号
	NotifyUrl string `json:"notifyUrl"` //接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
	Acct      string `json:"acct"`
	PayType   string `json:"paytype"`
	SubAppID  string `json:"subAppID"`
}

type CreateUnitOrderOrderResult struct {
	RetCode   string `json:"retCode"`
	RetMsg    string `json:"retMsg"`
	CusID     string `json:"cusID"`
	AppID     string `json:"appID"`
	TrxID     string `json:"trxID"`
	ChnltrxID string `json:"chnltrxID"`
	Reqsn     string `json:"reqsn"`
	RandomStr string `json:"randomStr"`
	TrxStatus string `json:"trxStatus"`
	FinTime   string `json:"finTime"`
	ErrMsg    string `json:"errMsg"`
	PayInfo   string `json:"payInfo"`
	Sign      string `json:"sign"`
}

type PayInfo struct {
	AppID     string `json:"appID"`
	TimeStamp string `json:"timeStamp"`
	NonceStr  string `json:"nonceStr"`
	Package   string `json:"package"`
	SignType  string `json:"signType"`
	PaySign   string `json:"paySign"`
}

type PayRefundParam struct {
	CusID     string `json:"cusid"`
	AppID     string `json:"appid"`
	Trxamt    int    `json:"trxamt"` //交易金额 单位为分
	Reqsn     string `json:"reqsn"`  //商户交易单号
	OldReqsn  string `json:"oldReqsn"`
	Remark    string `json:"remark"`
	RandomStr string `json:"randomStr"`
	Sign      string `json:"sign"`
	TrxID     string `json:"trxID"`
	OldTrxID  string `json:"oldTrxID"`
}

type PayRefundResult struct {
	RetCode   string `json:"retCode"`
	RetMsg    string `json:"retMsg"`
	CusID     string `json:"cusID"`
	AppID     string `json:"appID"`
	TrxID     string `json:"trxID"`
	Reqsn     string `json:"reqsn"`
	TrxStatus string `json:"trxStatus"`
	FinTime   string `json:"finTime"`
	ErrMsg    string `json:"errMsg"`
	RandomStr string `json:"randomStr"`
	Sign      string `json:"sign"`
	Fee       string `json:"fee"`
	TrxCode   string `json:"trxCode"`
}

type CreateH5UnitorderOrderParam struct {
	Trxamt    int    `json:"trxamt"`    //交易金额 单位为分
	Reqsn     string `json:"reqsn"`     //商户交易单号
	NotifyUrl string `json:"notifyUrl"` //接收微信支付异步通知回调地址，通知url必须为直接可访问的url，不能携带参数。
	Charset   string `json:"charset"`
	Returl    string `json:"returl"`
	Body      string `json:"body"`
}

// OnlinePayParam 扫码枪扫码支付参数
type OnlinePayParam struct {
	//参数    									参数名称			可空         备注
	Orgid         string `json:"orgid"`         // 集团/代理商商户号	   	是    	共享集团号/代理商参数时必填
	Cusid         string `json:"cusid"`         // 商户号实际交易的商户号   否
	Appid         string `json:"appid"`         // 应用ID平台分配的APPID  	否
	Version       string `json:"version"`       // 版本号接口版本号    	可
	Randomstr     string `json:"randomstr"`     // 随机字符串     		否    	商户自行生成的随机字符串
	Trxamt        string `json:"trxamt"`        // 交易金额单位为分 	   	否
	Reqsn         string `json:"reqsn"`         // 商户交易单号		   	否 		保证商户平台唯一
	Body          string `json:"body"`          // 订单商品名称，为空则以商户名作为商品名称 是
	Remark        string `json:"remark"`        // 备注 					是 		禁止出现+，空格，/，?，%，#，&， = 这几类特殊符号
	Authcode      string `json:"authcode"`      // 支付授权码如微信, 支付宝, 银联的付款二维码 否
	LimitPay      string `json:"limit_pay"`     // 支付限制    no_credit--指定不能使用信用卡支付    是    32    暂时只对微信支付和支付宝, 支付宝支付有效, 仅支持no_credit
	GoodsTag      string `json:"goods_tag"`     // 订单优惠标记 订单优惠标记，用于区分订单是否可以享受优惠，字段内容在微信后台配置券时进行设置，说明详见代金券或立减优惠 是 只对微信支付有效
	Benefitdetail string `json:"benefitdetail"` // 优惠信息Benefitdetail的json字符串, 注意是String 填写格式详见附录5.8 是
	SubAppid      string `json:"sub_appid"`     // 微信子appid 微信小程序/微信公众号/APP的appid  是 只对微信支付有效
	Chnlstoreid   string `json:"chnlstoreid"`   //  渠道门店编号    商户在支付渠道端的门店编号 对于支付宝支付，支付宝门店编号 对于微信支付，微信门店编号
	Subbranch     string `json:"subbranch"`     // 门店号        是    4
	Idno          string `json:"idno"`          // 证件号实名交易必填.填了此字段就会验证证件号和姓名 是 暂只支持支付宝
	Extendparams  string `json:"extendparams"`  //   拓展参数    json字符串，注意是String一般用于渠道的活动参数填写    是        参考5.9拓展参数附录说明
	Truename      string `json:"truename"`      // 付款人真实姓名实名交易必填.填了此字段就会验证证件号和姓名  是 暂只支持支付宝
	Asinfo        string `json:"asinfo"`        // 分账信息 格式:cusid:type:amount cusid:type:amount… 其中 cusid:接收分账的通联商户号 type分账类型（01：按金额  02：按比率） 如果分账类型为02，则分账比率为0.5表示50%。如果分账类型为01，则分账金额以元为单位表示 是
	Fqnum         string `json:"fqnum"`         //  分期
	NotifyUrl     string `json:"notify_url"`    // 交易结果通知地址 接收交易结果的通知回调地址，通知url必须为直接可访问的url，不能携带参数。 https只支持默认端口 是
	Signtype      string `json:"signtype"`      /// 签名方式 是
	Unpid         string `json:"unpid"`         // 银联pid 仅支持代理商/服务商角色调用
	Sign          string `json:"sign"`          // 签名 详见安全规范 否
	Terminfo      string `json:"terminfo"`      // 终端信息终端信息的json字符串 详见附录5.10终端字段说明 否
	Operatorid    string `json:"operatorid"`    // 收银员号 是
}
type TerminfoBase struct {
	Termno         string `json:"termno"`         // 终端号         必填
	Devicetype     string `json:"devicetype"`     // 设备类型       必填
	Termsn         string `json:"termsn"`         // 终端序列号
	Encryptrandnum string `json:"encryptrandnum"` // 加密随机因子
	Secrettext     string `json:"secrettext"`     // 密文数据
	Appversion     string `json:"appversion"`     // 终端程序版本号
	Longitude      string `json:"longitude"`      // 经度   银联扫码必送
	Latitude       string `json:"latitude"`       // 纬度   银联扫码必送
	Deviceip       string `json:"deviceip"`       // 终端Ip 如微信支付宝交易经纬度未上送，该字段必送
}

// OnlinePayResult 扫码枪支付返回参数
type OnlinePayResult struct {
	Retcode string `json:"retcode"` // SUCCESS/FAIL
	Retmsg  string `json:"retmsg"`  // 返回码说明
}
type OnlinePayRetMsg struct {
	Cusid     string `json:"cusid"`     // 商户号实际交易的商户号   否
	Appid     string `json:"appid"`     // 应用ID平台分配的APPID  	否
	Trxid     string `json:"trxid"`     // 收银宝平台的交易流水号
	Chnltrxid string `json:"chnltrxid"` // 例如微信,支付宝平台的交易单号
	Reqsn     string `json:"reqsn"`     // 商户的交易订单号
	Trxstatus string `json:"trxstatus"` // 交易的状态,
	Acct      string `json:"acct"`      //  微信支付-用户的微信openid支付宝支付-用户user_id
	Trxcode   string `json:"trxcode"`   // 交易类型
	Fintime   string `json:"fintime"`   // yyyyMMddHHmmss
	Errmsg    string `json:"errmsg"`    // 失败的原因说明
	Randomstr string `json:"randomstr"` // 随机生成的字符串
	Initamt   string `json:"initamt"`   // 原交易金额
	Trxamt    string `json:"trxamt"`    // 实际交易金额
	Fee       string `json:"fee"`       // 手续费
	Cmid      string `json:"cmid"`      // 渠道子商户号
	Chnlid    string `json:"chnlid"`    // 渠道号
	Chnldata  string `json:"chnldata"`  // 渠道信息
	Accttype  string `json:"accttype"`  // 借贷标识
	Sign      string `json:"sign"`      // 签名
}

// PayTransactionStatusQuery 交易状态查询
type PayTransactionStatusQuery struct {
	Orgid     string `json:"orgid"`     // 集团/代理商商户号	   	是    	共享集团号/代理商参数时必填
	Cusid     string `json:"cusid"`     // 商户号实际交易的商户号   否
	Appid     string `json:"appid"`     // 应用ID平台分配的APPID  	否
	Version   string `json:"version"`   // 版本号接口版本号    	可
	Reqsn     string `json:"reqsn"`     // 商户交易单号		   	否 		保证商户平台唯一
	Trxid     string `json:"trxid"`     // 收银宝平台的交易流水号
	Randomstr string `json:"randomstr"` // 随机字符串     		否    	商户自行生成的随机字符串
	Signtype  string `json:"signtype"`  /// 签名方式 是
	Sign      string `json:"sign"`      // 签名 详见安全规范 否
}
type PayTransactionStatusResult struct {
	Cusid     string `json:"cusid"`     // 商户号实际交易的商户号   否
	Appid     string `json:"appid"`     // 应用ID平台分配的APPID  	否
	Trxid     string `json:"trxid"`     // 收银宝平台的交易流水号
	Chnltrxid string `json:"chnltrxid"` // 例如微信,支付宝平台的交易单号
	Reqsn     string `json:"reqsn"`     // 商户的交易订单号
	Trxcode   string `json:"trxcode"`   // 交易类型
	Trxamt    string `json:"trxamt"`    // 实际交易金额
	Trxstatus string `json:"trxstatus"` // 交易的状态,
	Acct      string `json:"acct"`      // 支付平台用户标识
	Fintime   string `json:"fintime"`   // yyyyMMddHHmmss
	Randomstr string `json:"randomstr"` // 随机生成的字符串
	Errmsg    string `json:"errmsg"`    // 失败的原因说明
	Cmid      string `json:"cmid"`      // 渠道子商户号
	Chnlid    string `json:"chnlid"`    // 渠道号
	Initamt   string `json:"initamt"`   // 原交易金额
	Fee       string `json:"fee"`       // 手续费
	Chnldata  string `json:"chnldata"`  // 渠道信息
	Accttype  string `json:"accttype"`  // 借贷标识
	Bankcode  string `json:"bankcode"`  // 所属银行
	Logonid   string `json:"logonid"`   // 买家账号
	Sign      string `json:"sign"`      // 签名
}

// OnLineOrderRefundParam 订单退款参数
type OnLineOrderRefundParam struct {
	Orgid   string `json:"orgid"`   // 集团/代理商商户号	   		是    	共享集团号/代理商参数时必填
	Cusid   string `json:"cusid"`   // 商户号实际交易的商户号  	否
	Appid   string `json:"appid"`   // 应用ID平台分配的APPID  	否
	Version string `json:"version"` // 版本号接口版本号    		可

	Trxamt        string `json:"trxamt"`        // 交易金额单位为分 	   		否
	Reqsn         string `json:"reqsn"`         // 商户交易单号		   		否 		保证商户平台唯一
	Oldreqsn      string `json:"oldreqsn"`      // 原交易订单号 			是
	Oldtrxid      string `json:"oldtrxid"`      // 原交易流水 				是
	Remark        string `json:"remark"`        // 备注 					是 		禁止出现+，空格，/，?，%，#，&， = 这几类特殊符号
	Benefitdetail string `json:"benefitdetail"` // 优惠信息
	Randomstr     string `json:"randomstr"`     // 随机字符串     		否    	商户自行生成的随机字符串
	Signtype      string `json:"signtype"`      /// 签名方式 是
	Sign          string `json:"sign"`          // 签名 详见安全规范 否
}
type OnLineOrderRefundResult struct {
	Cusid     string `json:"cusid"`     // 商户号实际交易的商户号   否
	Appid     string `json:"appid"`     // 应用ID平台分配的APPID  	否
	Trxid     string `json:"trxid"`     // 收银宝平台的交易流水号
	Reqsn     string `json:"reqsn"`     // 商户的交易订单号
	Trxstatus string `json:"trxstatus"` // 交易的状态,
	Fintime   string `json:"fintime"`   // yyyyMMddHHmmss
	Errmsg    string `json:"errmsg"`    // 失败的原因说明
	Fee       string `json:"fee"`       // 手续费
	Trxcode   string `json:"trxcode"`   // 交易类型
	Randomstr string `json:"randomstr"` // 随机生成的字符串
	Chnltrxid string `json:"chnltrxid"` // 例如微信,支付宝平台的交易单号
	Chnldata  string `json:"chnldata"`  // 渠道信息
	Bankcode  string `json:"bankcode"`  // 所属银行
	Sign      string `json:"sign"`      // 签名
}

// AddTermReq 添加采集设备
type AddTermReq struct {
	Orgid   string `json:"orgid"`   // 集团/代理商商户号	   		是    	共享集团号/代理商参数时必填
	Cusid   string `json:"cusid"`   // 商户号实际交易的商户号  	否
	Appid   string `json:"appid"`   // 应用ID平台分配的APPID  	否
	Version string `json:"version"` // 版本号接口版本号    		可

	Termno      string `json:"termno"`      // 8位数字,商户下唯一  否
	Devicetype  string `json:"devicetype"`  // 设备类型  否
	Termsn      string `json:"termsn"`      // 终端序列号 终端类型（device_type）填写为 02、03、04、05、06、08、09 或 10时，必须填写终端序列号。
	Operation   string `json:"operation"`   // 本次操作标识，取值范围：00：新增；01：修改；02：注销；（注销时，仅需上送termno字段）
	Termstate   string `json:"termstate"`   // 取值范围：00：启用；01：注销；注：终端注销时非必填
	Termaddress string `json:"termaddress"` // 终端地址
	Signtype    string `json:"signtype"`
	Sign        string `json:"sign"`
}

// AddTermQuery 采集设备查询
type AddTermQuery struct {
	Orgid     string `json:"orgid"`   // 集团/代理商商户号	   		是    	共享集团号/代理商参数时必填
	Cusid     string `json:"cusid"`   // 商户号实际交易的商户号  	否
	Appid     string `json:"appid"`   // 应用ID平台分配的APPID  	否
	Version   string `json:"version"` // 版本号接口版本号    		可
	Termno    string `json:"termno"`  // 8位数字,商户下唯一  否
	Signtype  string `json:"signtype"`
	Sign      string `json:"sign"`
	Querytype string `json:"querytype"`
}
