package bfpay import ( "encoding/json" "net/url" "server/util" "github.com/liangdas/mqant/log" ) const ( baseURL = "https://brl.bf-pay.com" payURL = "/gateway/api/commPay" withdrawURL = "/df/gateway/proxyrequest" mid = "2000611000770152" key = "afca030583d24e6faceceed3cddff3c9" ) var privateKeyPkCs8 = []byte(`-----BEGIN RSA PRIVATE KEY----- MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJ5hQDWLXdURqCIc Er3ID1D/ovQw2K+UaXP4vJ5t8d56gzFitOeCx92Qeu4wO8rINH599AZyiO3HuQM+ P7ueBqJyDmv/vOAOld+PwiTk42DVHlEj/h9kuGXV8vZfsU6BhgNGlq9bsSn0olbM kz2WX8Qw2CRnGbMZvYK73yEl83E1AgMBAAECgYA+9p6WKs+k0x4qYUq6E/yy0M4x kfGy66d4qVwjB8ZuEfpx+bG9j+pxFO0qIBbFKQ5lcyE+Ju50yT+uIGMp7UrpTYuX aU55OVFrUaLAt/XeyaKcOSPB9xK+ObRnKUrZ92FN/PU/tHkaRjFxPaNiZGqwbBcQ RdtcHpo/ZkooRvbWyQJBAM/tLpvLIwnC6Gi8JhGunSDwZFxbLyLW/S3x4b6S0IaC Uor/AsplshWs8VQ0L0edyShnyYcFpxw4t5oP0RtHCaMCQQDC/30hiwPJMfRZ/6oF ljV4nyN47rQssHG2EYo/HfL7tZn+URlcZ5oSSoM2Qe6cmzg4Vaoo+CRWwKbjsh/n d3dHAkA2uAV/DHuBEyEUhwdBugEx7PGMeJa0BX4FfFVbUMm9zEgquiei2hZ+q8+q yDz1DOomTwHzHaK3w5lV2vm9wvkfAkA7or1XI9e9kWyElb8exEiIIktL8dziiffM 0eJw2Sz1tB1rfMv/yaOCEo28az+ZX5M7D1/h9bnPWk3v9wrw1EWDAkBZNzIZ47TS Mj9ipSQDsSklZYPGquqlRsjRm7OcDZXC7zW6qs3mTPPuISRuMVhmFr3Lz3YMT1o/ S0Agrn9Dq3fM -----END RSA PRIVATE KEY-----`) // var privateKey = []byte(`-----BEGIN RSA PRIVATE KEY----- // MIICXgIBAAKBgQDgIesHgi+Qj0kkhwvJdGzt/QZDYR8VFzDxVgt5KdA8Ec1WCrhv // GrmIEF2aKaqnPesv4/xn/0cLrXizYnF7wbgy/rrSzDmbWKEB6GZZc8Xz9iTxqoDT // 2TpZclSUwKjeicdnw35PDGdBKKCbfLJeg9pXMs/L9VnY/QtDp03a3760owIDAQAB // AoGBANQkZoA54elzJej0Bd0NXNk5x8bY04Gz7LhRGBT71cQ1mWQaS42l/vvheack // TwlzGvu+UDbjMgzEid1IjV908XFVAnmJQxFxsHJt3HUz9qK5caXtqzwqP7Vt0Bl/ // Nt7wXhn1xq9gljLRuVV9+MoaF6punFuksqp4Qh/AAZ/zGVcJAkEA/ITUGawSY+AX // Gz1uAYadEnkA/Ce1rk/uL5OCSHxIvBLL3DmFp68E7+NTwyf2ilsnB0jtqOgBqrZ8 // KoVfUjsxtwJBAOM46RGxijUhcDEoIZYUE+M+ugWskekdpwq4W9y1sNFULUjdXkwn // UKeSlwTis8zFCw8mkZDOgNQzRsd0eFjm5HUCQQCt2MipD/TtO7bMsyML++Ahepr5 // /mCvLCpAKN62BpKQoKQm7pcclXrhqHDfV6D9KboZ4tRzx552KAIdyAqS81vLAkB7 // CVLy+L7MvDmC9KcTG/YU499YuTQdFahg3qknXt7Kypjmzq+D7vn2cyMBSzxu0feG // Ea1ayubpgIZ/9CpCgWwNAkEA+f/5Ilnb3Dn9fRhGAuhttUIA9+vec3BH6rKc9oW/ // JvLtLxuSpfg2D2D74nsZd48OVk+BJ0DqVeMb7sw6zjzH9A== // -----END RSA PRIVATE KEY-----`) var publicKey = []byte(`-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrTw3IoR3Q6oRukb6q0LR6dc/GRXVh0ngRPZzRsq87j6817v4HNjfsf2gYkefWK3AcEGyZT7uqji1C0drDfVy82HE68hYjmxgyXQO2YRjNZkYNHNPHD9EO4y5fr4qQsSMCYA1a7fgWqbqZiGPQgCSUvrpbFbJh53QxOWqpkrKoowIDAQAB-----END PUBLIC KEY-----`) var myPublicKey = []byte(`-----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeYUA1i13VEagiHBK9yA9Q/6L0 MNivlGlz+LyebfHeeoMxYrTngsfdkHruMDvKyDR+ffQGcojtx7kDPj+7ngaicg5r /7zgDpXfj8Ik5ONg1R5RI/4fZLhl1fL2X7FOgYYDRpavW7Ep9KJWzJM9ll/EMNgk ZxmzGb2Cu98hJfNxNQIDAQAB -----END PUBLIC KEY-----`) // Head represents the header of the request type Head struct { MchtId string `json:"mchtId"` // 商户编号,不参与签名 Version string `json:"version"` // 固定值“20”,不参与签名 Biz string `json:"biz"` // 固定值,支付方式,不参与签名 } // Body represents the body of the request type Body struct { OrderId string `json:"orderId"` // 订单号 OrderTime string `json:"orderTime"` // 订单时间yyyyMMddHHmmss Amount string `json:"amount"` // 总金额,以分为单位 CurrencyType string `json:"currencyType"` // 货币种类,三位字母代码 Goods string `json:"goods"` // 商品名称(不要带中文元素) NotifyUrl string `json:"notifyUrl"` // 接收推送通知的URL CallBackUrl string `json:"callBackUrl"` // 网页回调地址 Desc string `json:"desc,omitempty"` // 商品描述,logo地址 AppId string `json:"appId,omitempty"` // 产品标识 AppName string `json:"appName,omitempty"` // 产品名称 Operator string `json:"operator,omitempty"` // 印度UPI支付,用户的VPA账号 ExpireTime string `json:"expireTime,omitempty"` // 订单超时时间yyyyMMddHHmmss IP string `json:"ip,omitempty"` // 请求IP地址 Param string `json:"param,omitempty"` // 保留字段 UserId string `json:"userId,omitempty"` // 要求:小于32位 Phone string `json:"phone,omitempty"` // 手机号(币种是BRL,USDT,THB,PHP,USD,此参数可不传) Name string `json:"name,omitempty"` // 姓名(币种是BRL,USDT,THB,PHP,USD,此参数可不传) Email string `json:"email,omitempty"` // 邮箱(币种是BRL,USDT,THB,PHP,USD,此参数可不传) } type PayReq struct { Head Head `json:"head"` Body Body `json:"body"` Sign string `json:"sign"` // 签名信息 } type PayResp struct { Head struct { RespCode string `json:"respCode"` // 返回Code RespMsg string `json:"respMsg"` // 返回信息 } `json:"head"` // 响应报文头 Body struct { MchtId string `json:"mchtId"` // 商户ID OrderId string `json:"orderId"` // 商户订单号 PayUrl string `json:"payUrl"` // 支付URL地址 TradeId string `json:"tradeId,omitempty"` // 支付平台返回的交易流水号 Param string `json:"param,omitempty"` // 保留字段 } `json:"body,omitempty"` // 响应报文体, 在respCode为"0000"时返回 Sign string `json:"sign"` // 签名信息 } type PayCallbackReq struct { Head struct { RespCode string `json:"respCode"` // 返回Code RespMsg string `json:"respMsg"` // 返回信息 } `json:"head"` // 响应报文头 Body struct { Amount string `json:"amount"` // 金额 Biz string `json:"biz"` // 业务类型 ChargeTime string `json:"chargeTime"` // 充值时间 MchtId string `json:"mchtId"` // 商户ID OrderId string `json:"orderId"` // 商户订单号 Seq string `json:"seq"` // 序号 Status string `json:"status"` // 状态 TradeId string `json:"tradeId"` // 交易流水号 PayType string `json:"payType"` // 支付类型 } `json:"body"` // 响应报文体 Sign string `json:"sign"` // 签名信息 } type WithdrawReq struct { Head Head `json:"head"` Body string `json:"body"` } type WithdrawBody struct { BatchOrderNo string `json:"batchOrderNo"` // 商户代付批次号,值唯一 TotalNum int `json:"totalNum"` // 商户代付笔数,与detail代付明细集合数一致 TotalAmount string `json:"totalAmount"` // 商户代付总金额,单位:分,为detail代付明细集合中金额总和 NotifyUrl string `json:"notifyUrl,omitempty"` // 异步通知地址 Detail []Detail `json:"detail"` // 代付订单明细,Json数组格式 // AppId string `json:"appId,omitempty"` // 产品Id CurrencyType string `json:"currencyType"` // 币种BRL } type Detail struct { Seq string `json:"seq"` // 序号,商户自定义 Amount string `json:"amount"` // 金额,单位:分 AccType string `json:"accType"` // 固定值 0 CertType string `json:"certType"` // PIX账号类型或银行卡代付固定值 CertId string `json:"certId"` // PIX账号或银行卡相关值 // BankCardNo string `json:"bankCardNo,omitempty"` // 收款人的CPF或CNPJ(PIX代付必填) BankCardName string `json:"bankCardName"` // 收款用户姓名 // BankCode string `json:"bankCode,omitempty"` // 银行编码(银行卡代付时必传) // Mobile string `json:"mobile,omitempty"` // 银行账户绑定的手机号码 // Email string `json:"email,omitempty"` // 邮箱 // BankCardType string `json:"bankCardType,omitempty"` // 银行卡类型,1:借记卡2:信用卡 // CreditValid string `json:"creditValid,omitempty"` // 信用卡有效期,MMyy(信用卡时必填) // CreditCvv string `json:"creditCvv,omitempty"` // 卡背面后3位数字(信用卡时必填) // BankProvince string `json:"bankProvince,omitempty"` // 开户行所属省份 // BankCity string `json:"bankCity,omitempty"` // 开户行所属市 // BankLineCode string `json:"bankLineCode,omitempty"` // 联行号 // BankName string `json:"bankName,omitempty"` // 银行名称 // Remark string `json:"remark,omitempty"` // 备注 // FirstName string `json:"firstName,omitempty"` // 收款人名 // LastName string `json:"lastName,omitempty"` // 收款人姓 // CardYear string `json:"cardYear,omitempty"` // 卡年份 // CardMonth string `json:"cardMonth,omitempty"` // 卡月份 } type WithdrawResp struct { Head struct { RespCode string `json:"respCode"` // 返回Code } `json:"head"` // 响应报文头 Body string `json:"body,omitempty"` // 响应报文体,以字符串表示 Sign string `json:"sign,omitempty"` // 签名信息,假设存在时 } type WithdrawRespBody struct { Status string `json:"status"` // 订单受理状态 TradeId string `json:"tradeId"` // 平台批次号 BatchOrderNo string `json:"batchOrderNo"` // 商户批次号 MchtId string `json:"mchtId"` // 商户编号 Desc string `json:"desc,omitempty"` // 描述, 可选字段 } type WithdrawCallbackReq struct { Head struct { RespCode string `json:"respCode"` // 返回Code RespMsg string `json:"respMsg"` // 返回信息 } `json:"head"` // 响应报文头 Body string `json:"body,omitempty"` // 响应报文体,以字符串表示 Sign string `json:"sign,omitempty"` // 签名信息,假设存在时 } type WithdrawCallbackBody struct { BatchOrderNo string `json:"batchOrderNo"` // 商户批次号 TradeId string `json:"tradeId"` // 平台批次号 TotalNum string `json:"totalNum"` // 代付笔数 TotalAmount string `json:"totalAmount"` // 代付总金额 Status string `json:"status"` // 状态 Desc string `json:"desc,omitempty"` // 结果描述,可选字段 Detail []WithdrawCallbackDetail `json:"detail"` // 代付明细订单详情 } type WithdrawCallbackDetail struct { DetailId string `json:"detailId"` // 平台明细号 Seq string `json:"seq"` // 序号 Amount string `json:"amount"` // 金额 单位:分 Status string `json:"status"` // 状态 Desc string `json:"desc,omitempty"` // 结果描述 FinishTime string `json:"finishTime,omitempty"` // 代付完成时间(币种时间)格式: yyyyMMddHHmmss } func Decode(str string, ret interface{}) error { str2, err := url.QueryUnescape(str) if err != nil { log.Error("err:%v", err) return err } res, err := util.NewXRsa(publicKey, privateKeyPkCs8) if err != nil { log.Error("err:%v", err) return err } tmp, err := res.PrivateDecrypt(str2) if err != nil { log.Error("err:%v", err) return err } err = json.Unmarshal([]byte(tmp), ret) if err != nil { log.Error("err:%v", err) return err } return nil } func Encode(str string) string { res, err := util.NewXRsa(publicKey, privateKeyPkCs8) if err != nil { log.Error("err:%v", err) return "" } tmp, err := res.PublicEncrypt(str) if err != nil { log.Error("err:%v", err) return "" } return url.QueryEscape(tmp) }