富友支付支持
This commit is contained in:
92
pkg/fuiou/scan.go
Normal file
92
pkg/fuiou/scan.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package fuiou
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// PreCreate 主扫统一下单(C扫B,生成用户扫码支付的二维码)。
|
||||
// orderType: 订单类型,WECHAT=微信主扫、ALIPAY=支付宝主扫。
|
||||
// reservedExpireMinute: 订单有效期分钟(reserved 字段,不参与签名)。
|
||||
func (c *Client) PreCreate(orderNo, amount, goodsDesc, termIP, orderType, reservedExpireMinute string) (*PreCreateResponse, error) {
|
||||
req := &PreCreateRequest{
|
||||
Version: "1.0",
|
||||
InsCd: c.InsCd,
|
||||
MchntCd: c.MchntCd,
|
||||
TermId: c.TermId,
|
||||
RandomStr: generateRandomStr(),
|
||||
OrderType: orderType,
|
||||
MchntOrderNo: orderNo,
|
||||
OrderAmt: amount,
|
||||
GoodsDesc: goodsDesc,
|
||||
TermIp: termIP,
|
||||
TxnBeginTs: time.Now().Format("20060102150405"),
|
||||
NotifyUrl: c.NotifyURL,
|
||||
ReservedExpireMinute: reservedExpireMinute,
|
||||
}
|
||||
|
||||
sign, err := c.Sign(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("签名失败: %w", err)
|
||||
}
|
||||
req.Sign = sign
|
||||
|
||||
var resp PreCreateResponse
|
||||
if err := c.DoRequest("/preCreate", req, &resp); err != nil {
|
||||
return nil, fmt.Errorf("请求富友失败: %w", err)
|
||||
}
|
||||
|
||||
if resp.ResultCode != "000000" {
|
||||
c.logger.Error("富友主扫下单失败",
|
||||
zap.String("order_no", orderNo),
|
||||
zap.String("result_code", resp.ResultCode),
|
||||
zap.String("result_msg", resp.ResultMsg),
|
||||
)
|
||||
return nil, fmt.Errorf("富友主扫下单失败: %s", resp.ResultMsg)
|
||||
}
|
||||
|
||||
c.logger.Info("富友主扫下单成功",
|
||||
zap.String("order_no", orderNo),
|
||||
zap.String("order_type", orderType),
|
||||
)
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// CommonQuery 主动查询订单状态。
|
||||
// orderType: 订单类型,须与下单时一致。
|
||||
func (c *Client) CommonQuery(orderNo, orderType string) (*CommonQueryResponse, error) {
|
||||
req := &CommonQueryRequest{
|
||||
Version: "1.0",
|
||||
InsCd: c.InsCd,
|
||||
MchntCd: c.MchntCd,
|
||||
TermId: c.TermId,
|
||||
RandomStr: generateRandomStr(),
|
||||
OrderType: orderType,
|
||||
MchntOrderNo: orderNo,
|
||||
}
|
||||
|
||||
sign, err := c.Sign(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("签名失败: %w", err)
|
||||
}
|
||||
req.Sign = sign
|
||||
|
||||
var resp CommonQueryResponse
|
||||
if err := c.DoRequest("/commonQuery", req, &resp); err != nil {
|
||||
return nil, fmt.Errorf("请求富友失败: %w", err)
|
||||
}
|
||||
|
||||
if resp.ResultCode != "000000" {
|
||||
c.logger.Error("富友订单查询失败",
|
||||
zap.String("order_no", orderNo),
|
||||
zap.String("result_code", resp.ResultCode),
|
||||
zap.String("result_msg", resp.ResultMsg),
|
||||
)
|
||||
return nil, fmt.Errorf("富友订单查询失败: %s", resp.ResultMsg)
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
@@ -4,6 +4,12 @@ package fuiou
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// 主扫统一下单与订单查询的订单类型常量
|
||||
const (
|
||||
OrderTypeWechat = "WECHAT" // 微信主扫
|
||||
OrderTypeAlipay = "ALIPAY" // 支付宝主扫
|
||||
)
|
||||
|
||||
// WxPreCreateRequest wxPreCreate 下单请求(3.3接口)
|
||||
// 所有非 reserved 字段必须出现在 XML 中(含空值),否则富友验签不通过
|
||||
type WxPreCreateRequest struct {
|
||||
@@ -77,3 +83,68 @@ type NotifyResponse struct {
|
||||
ResultCode string `xml:"result_code"` // 结果码
|
||||
ResultMsg string `xml:"result_msg"` // 结果消息
|
||||
}
|
||||
|
||||
// PreCreateRequest 主扫统一下单请求(C扫B)
|
||||
// 所有非 reserved 字段必须出现在 XML 中(含空值),否则富友验签不通过
|
||||
type PreCreateRequest struct {
|
||||
XMLName xml.Name `xml:"xml"`
|
||||
Version string `xml:"version"` // 版本号: 1.0
|
||||
InsCd string `xml:"ins_cd"` // 机构号
|
||||
MchntCd string `xml:"mchnt_cd"` // 商户号
|
||||
TermId string `xml:"term_id"` // 终端号
|
||||
RandomStr string `xml:"random_str"` // 随机字符串
|
||||
Sign string `xml:"sign"` // 签名
|
||||
OrderType string `xml:"order_type"` // 订单类型: WECHAT=微信主扫
|
||||
MchntOrderNo string `xml:"mchnt_order_no"` // 商户订单号
|
||||
CurrType string `xml:"curr_type"` // 货币类型(可选)
|
||||
OrderAmt string `xml:"order_amt"` // 订单金额(分)
|
||||
TermIp string `xml:"term_ip"` // 终端IP
|
||||
TxnBeginTs string `xml:"txn_begin_ts"` // 交易起始时间,格式 yyyyMMddHHmmss
|
||||
NotifyUrl string `xml:"notify_url"` // 回调地址
|
||||
GoodsDesc string `xml:"goods_des"` // 商品描述
|
||||
GoodsDetail string `xml:"goods_detail"` // 商品详情(可选)
|
||||
AddnInf string `xml:"addn_inf"` // 附加数据(可选)
|
||||
ReservedExpireMinute string `xml:"reserved_expire_minute"` // 订单有效期分钟(reserved,不参与签名)
|
||||
}
|
||||
|
||||
// PreCreateResponse 主扫统一下单响应
|
||||
type PreCreateResponse struct {
|
||||
ResultCode string `xml:"result_code"` // 结果码: 000000=成功
|
||||
ResultMsg string `xml:"result_msg"` // 结果消息
|
||||
InsCd string `xml:"ins_cd"` // 机构号
|
||||
MchntCd string `xml:"mchnt_cd"` // 商户号
|
||||
RandomStr string `xml:"random_str"` // 随机字符串
|
||||
Sign string `xml:"sign"` // 签名
|
||||
QrCode string `xml:"qr_code"` // 二维码内容
|
||||
ReservedFyTraceNo string `xml:"reserved_fy_trace_no"` // 富友流水号
|
||||
}
|
||||
|
||||
// CommonQueryRequest 订单查询请求
|
||||
type CommonQueryRequest struct {
|
||||
XMLName xml.Name `xml:"xml"`
|
||||
Version string `xml:"version"` // 版本号: 1.0
|
||||
InsCd string `xml:"ins_cd"` // 机构号
|
||||
MchntCd string `xml:"mchnt_cd"` // 商户号
|
||||
TermId string `xml:"term_id"` // 终端号
|
||||
RandomStr string `xml:"random_str"` // 随机字符串
|
||||
Sign string `xml:"sign"` // 签名
|
||||
OrderType string `xml:"order_type"` // 订单类型
|
||||
MchntOrderNo string `xml:"mchnt_order_no"` // 商户订单号
|
||||
}
|
||||
|
||||
// CommonQueryResponse 订单查询响应
|
||||
type CommonQueryResponse struct {
|
||||
ResultCode string `xml:"result_code"` // 结果码: 000000=成功
|
||||
ResultMsg string `xml:"result_msg"` // 结果消息
|
||||
InsCd string `xml:"ins_cd"` // 机构号
|
||||
MchntCd string `xml:"mchnt_cd"` // 商户号
|
||||
RandomStr string `xml:"random_str"` // 随机字符串
|
||||
Sign string `xml:"sign"` // 签名
|
||||
OrderType string `xml:"order_type"` // 订单类型
|
||||
MchntOrderNo string `xml:"mchnt_order_no"` // 商户订单号
|
||||
TransStat string `xml:"trans_stat"` // 交易状态
|
||||
OrderAmt string `xml:"order_amt"` // 订单金额(分)
|
||||
TransactionId string `xml:"transaction_id"` // 交易流水号
|
||||
ReservedTxnFinTs string `xml:"reserved_txn_fin_ts"` // 交易完成时间(reserved)
|
||||
ReservedFyTraceNo string `xml:"reserved_fy_trace_no"` // 富友流水号(reserved)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user