You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
11 KiB
250 lines
11 KiB
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) |
|
}
|
|
|