Documentation ¶
Overview ¶
Package mch 包含微信支付 sdk.
##### 接口形式 ########################################################
各接口一般形如:
X(ctx context.Context, config Config, req *XRequest, opts ...Option) (resp *XResponse, err error)
其中 X 是接口名称,各参数说明如下:
ctx 上下文 config 微信支付配置,此项是包含接口必须的参数,如应用 ID/商户 ID 等 req 请求 opts 额外选项,如非默认的 http client,签名方式等 resp 响应 err 错误,只有当通讯成功且业务结果成功时,返回空 err
##### https ########################################################
有些接口(例如退款接口)需要客户端证书方可方可调用,最简便的方法是在 DefaultOptions 中统一使用带客户端证书的 http client:
import ( "github.com/huangjunwen/wx-driver/mch" "github.com/huangjunwen/wx-driver/utils" "time" ) mch.DefaultOptions = mch.MustOptions( mch.UseClient(&http.Client{ Transport: &http.Transport{ TLSClientConfig: utils.MustTLSConfig(certPEM, keyPEM, nil), }, Timeout: 30 * time.Second, }), )
##### 签名 ########################################################
目前签名不允许小写,因为安全规范中要求大写,mch 模块中就不做额外的 ToUpper 操作了
##### 金额说明 ########################################################
接口里有各种金额,如:
- 标价金额 total_fee / 标价货币 fee_type
- 现金支付金额 cash_fee / 现金支付货币 cash_fee_type
- 退款金额 refund_fee / 退款货币 refund_fee_type
- 现金退款金额 cash_refund_fee / 现金退款货币 cash_refund_fee_type
- 优惠金额
标价货币和退款货币必须一致,现金支付货币跟现金退款货币也是一致的(即用户实际使用什么货币支付,则接受什么样的货币退款),并且满足:
refund_fee/total_fee == cash_refund_fee/cash_fee
即退款金额和标价金额确定退款比例,然后按此比例乘以用户实际现金支付金额得出现金退款金额
例如:
- 标价金额 1 美元
- 优惠金额 0.5 美元
- 现金支付 3.5 人民币 (== 0.5 美元,按汇率 7 来算)
则若退款:
- 退款金额 0.6 美元 (退 60%)
- 现金退款金额 2.1 人民币(== 3.5 人民币 * 0.6)
Index ¶
- Constants
- Variables
- func CloseOrder(ctx context.Context, config conf.MchConfig, req *CloseOrderRequest, ...) error
- func HandleMchXML(handler func(context.Context, MchXML) error, options *Options) http.Handler
- func HandleSignedMchXML(handler func(context.Context, MchXML) error, selector conf.MchConfigSelector, ...) http.Handler
- func JSReq(config conf.MchConfig, prepayID string) map[string]string
- func JSReqEx(config conf.MchConfig, prepayID string, signType SignType) map[string]string
- func OrderNotify(handler func(context.Context, *OrderQueryResponse) error, ...) http.Handler
- func RefundNotify(handler func(context.Context, *RefundQueryResponse) error, ...) http.Handler
- func SignMchXML(x MchXML, signType SignType, mchKey string) string
- type CloseOrderRequest
- type MchBusinessError
- type MchXML
- type Option
- type Options
- type OrderQueryRequest
- type OrderQueryResponse
- type RefundInfo
- type RefundQueryRequest
- type RefundQueryResponse
- type RefundRequest
- type RefundResponse
- type RefundStatus
- type SignType
- type TradeState
- type TradeType
- type UnifiedOrderRequest
- type UnifiedOrderResponse
Constants ¶
const ( // URLBaseDefault 默认接入点 URLBaseDefault = "https://api.mch.weixin.qq.com" // URLBaseHK 建议东南亚接入点 URLBaseHK = "https://apihk.mch.weixin.qq.com" // URLBaseUS 建议其它地区接入点 URLBaseUS = "https://apius.mch.weixin.qq.com" )
Variables ¶
var ( // TradeTypeInvalid 表示无效交易类型 TradeTypeInvalid = TradeType{""} // TradeTypeJSAPI 表示公众号/小程序交易类型 TradeTypeJSAPI = TradeType{"JSAPI"} // TradeTypeNATIVE 表示扫码交易类型 TradeTypeNATIVE = TradeType{"NATIVE"} // TradeTypeAPP 表示 app 交易类型 TradeTypeAPP = TradeType{"APP"} // TradeTypeMWEB 表示 H5 交易类型 TradeTypeMWEB = TradeType{"MWEB"} )
var ( // TradeStateInvalid 表示无效交易状态 TradeStateInvalid = TradeState{""} // TradeStateNOTPAY 表示未支付 TradeStateNOTPAY = TradeState{"NOTPAY"} // TradeStateCLOSED 表示已关闭;NOTPAY 关单 -> CLOSED TradeStateCLOSED = TradeState{"CLOSED"} // TradeStatePAYERROR 表示支付错误(如银行返回失败);NOTPAY -> PAYERROR TradeStatePAYERROR = TradeState{"PAYERROR"} // TradeStateSUCCESS 表示支付成功;NOTPAY -> SUCCESS TradeStateSUCCESS = TradeState{"SUCCESS"} // TradeStateREFUND 表示进入退款;SUCCESS 发起退款 -> REFUND TradeStateREFUND = TradeState{"REFUND"} // TradeStateUSERPAYING 表示用户支付中? TradeStateUSERPAYING = TradeState{"USERPAYING"} // TradeStateREVOKED 表示已撤销(刷卡支付) TradeStateREVOKED = TradeState{"REVOKED"} )
var ( // RefundStatusInvalid 表示无效退款状态 RefundStatusInvalid = RefundStatus{""} // RefundStatusPROCESSING 表示退款处理中 RefundStatusPROCESSING = RefundStatus{"PROCESSING"} // RefundStatusPROCESSING 表示退款成功;PROCESSING -> SUCCESS RefundStatusSUCCESS = RefundStatus{"SUCCESS"} // RefundStatusREFUNDCLOSE 表示退款关闭;PROCESSING -> REFUNDCLOSE RefundStatusREFUNDCLOSE = RefundStatus{"REFUNDCLOSE"} // RefundStatusCHANGE 表示退款异常,需要手动处理;PROCESSING -> CHANGE RefundStatusCHANGE = RefundStatus{"CHANGE"} )
var ( SignTypeInvalid = SignType{""} SignTypeMD5 = SignType{"MD5"} SignTypeHMACSHA256 = SignType{"HMAC-SHA256"} )
var ( ErrOrderQueryMissingID = errors.New("Missing transaction_id/out_trade_no in OrderQueryRequest") ErrOrderQueryNoOutTradeNo = errors.New("No out_trade_no is returned from OrderQueryResponse") ErrOrderQueryNoTradeState = errors.New("No trade_state is returned from OrderQueryResponse") ErrOrderQueryNoTransactionID = errors.New("No transaction_id is returned from OrderQueryResponse") ErrOrderQueryNoOpenID = errors.New("No openid is returned from OrderQueryResponse") ErrOrderQueryNoTradeType = errors.New("No trade_type is returned from OrderQueryResponse") ErrOrderQueryNoBankType = errors.New("No bank_type is returned from OrderQueryResponse") ErrOrderQueryNoTimeEnd = errors.New("No time_end is returned from OrderQueryResponse") ErrOrderQueryNoTotalFee = errors.New("No total_fee is returned from OrderQueryResponse") ErrOrderQueryNoCashFee = errors.New("No cash_fee is returned from OrderQueryResponse") )
var ( ErrRefundMissingOutRefundNo = errors.New("Missing out_refund_no in RefundRequest") ErrRefundMissingID = errors.New("Missing transaction_id/out_trade_no in RefundRequest") ErrRefundMissingTotalFee = errors.New("Missing total_fee in RefundRequest") ErrRefundMissingRefundFee = errors.New("Missing refund_fee in RefundRequest") ErrRefundNoTransactionID = errors.New("No transaction_id is returned from RefundResponse") ErrRefundNoOutTradeNo = errors.New("No out_trade_no is returned from RefundResponse") ErrRefundNoRefundID = errors.New("No refund_id is returned from RefundResponse") ErrRefundNoOutRefundNo = errors.New("No out_refund_no is returned from RefundResponse") ErrRefundNoTotalFee = errors.New("No total_fee is returned from RefundResponse") ErrRefundNoCashFee = errors.New("No cash_fee is returned from RefundResponse") ErrRefundNoRefundFee = errors.New("No refund_fee is returned from RefundResponse") ErrRefundNoCashRefundFee = errors.New("No cash_refund_fee is returned from RefundResponse") )
var ( ErrRefundQueryMissingID = errors.New("Missing refund_id/out_refund_no/transaction_id/out_trade_no in RefundQueryRequest") ErrRefundQueryNoOutTradeNo = errors.New("No out_trade_no is returned from RefundQueryResponse") ErrRefundQueryNoTransactionID = errors.New("No transaction_id is returned from RefundQueryResponse") ErrRefundQueryNoTotalFee = errors.New("No total_fee is returned from RefundQueryResponse") ErrRefundQueryNoCashFee = errors.New("No cash_fee is returned from RefundQueryResponse") ErrRefundQueryNoRefundCount = errors.New("No refund_count is returned from RefundQueryResponse") )
var ( ErrUnifiedOrderMissingOutTradeNo = errors.New("Missing out_trade_no in UnifiedOrderRequest") ErrUnifiedOrderMissingTotalFee = errors.New("Missing total_fee in UnifiedOrderRequest") ErrUnifiedOrderMissingBody = errors.New("Missing body in UnifiedOrderRequest") ErrUnifiedOrderMissingNotifyUrl = errors.New("Missing notify_url in UnifiedOrderRequest") ErrUnifiedOrderMissingTradeType = errors.New("Missing trade_type in UnifiedOrderRequest") ErrUnifiedOrderMissingOpenID = errors.New("Missing openid in UnifiedOrderRequest since trade_type is JSAPI") ErrUnifiedOrderBadTradeType = errors.New("Bad trade_type is returned from UnifiedOrderResponse") ErrUnifiedOrderNoPrepayID = errors.New("No prepay_id is returned from UnifiedOrderResponse") ErrUnifiedOrderNoCodeUrl = errors.New("No code_url is returned from UnifiedOrderResponse") ErrUnifiedOrderNoMWebUrl = errors.New("No mweb_url is returned from UnifiedOrderResponse") )
var ( // DefaultOptions 为 mch 模块的默认设置,可修改它影响该模块下的默认行为, DefaultOptions = &Options{ urlBase: URLBaseDefault, signType: SignTypeMD5, } )
var (
ErrCloseOrderMissingOutTradeNo = errors.New("Missing out_trade_no in CloseOrderRequest")
)
Functions ¶
func CloseOrder ¶
func CloseOrder(ctx context.Context, config conf.MchConfig, req *CloseOrderRequest, opts ...Option) error
CloseOrder 关闭订单接口
func HandleMchXML ¶
HandleMchXML 处理 mch xml 回调,若 handler 返回非 nil error,则该 http.Handler 返回 FAIL return_code 给微信
NOTE: 最终用户一般不需要使用该函数
func HandleSignedMchXML ¶
func HandleSignedMchXML(handler func(context.Context, MchXML) error, selector conf.MchConfigSelector, options *Options) http.Handler
HandleSignedMchXML 处理带签名的 mch xml 回调,需要传入一个 ConfigurationSelector 用于选择配置
NOTE: 最终用户一般不需要使用该函数
func JSReqEx ¶
JSReqEx 返回拉起微信支付所需的 JS 参数(公众号支付/小程序支付),signType 必须保持和统一下单一致, 若均使用 DefaultOptions,可以直接使用 JSReq
func OrderNotify ¶
func OrderNotify(handler func(context.Context, *OrderQueryResponse) error, selector conf.MchConfigSelector, options *Options) http.Handler
OrderNotify 创建一个处理支付结果通知的 http.Handler; 传入 handler 的参数包括上下文和查询订单接口返回的 Response;handler 处理过后若成功应该返回 nil,若失败则应该返回一个非 nil error 对象,该 error 的 String() 将会返回给外部
NOTE:请使用与在统一下单一样的签名类型,否则签名会可能不通过
func RefundNotify ¶
func RefundNotify(handler func(context.Context, *RefundQueryResponse) error, selector conf.MchConfigSelector, options *Options) http.Handler
RefundNotify 创建一个处理退款结果通知的 http.Handler; 传入 handler 的参数包括上下文和查询退款接口返回的 Response;handler 处理过后若成功应该返回 nil,若失败则应该返回一个非 nil error 对象,该 error 的 String() 将会返回给外部
Types ¶
type CloseOrderRequest ¶
type CloseOrderRequest struct { // ----- 必填字段 ----- OutTradeNo string // out_trade_no String(32) 商户系统内部订单号 同一个商户号下唯一 }
CloseOrderRequest 是关闭订单接口请求
type MchBusinessError ¶
type MchBusinessError struct { // ResultCode 业务结果 SUCCESS/FAIL ResultCode string // ErrCode 错误代码, 当 ResultCode 为FAIL时返回错误代码 ErrCode string // ErrCodeDes 错误代码描述 ErrCodeDes string }
MchBusinessError 是微信支付业务错误
type MchXML ¶
MchXML 代表微信支付接口的 xml 数据,形如:
<xml> <fieldName1>fieldValue1</fieldName1> <fieldName2>fieldValue2</fieldName2> ... </xml>
为一层 xml,字段名唯一:这是由签名算法决定的,假如字段名不唯一,例如:
<xml> <fieldName1>fieldValue1</fieldName1> <fieldName1>fieldValue2</fieldName1> ... </xml>
那么签名算法该使用
fieldName1=fieldValue1&fieldName1=fieldValue2
还是
fieldName1=fieldValue2&fieldName1=fieldValue1
进行签名呢?因此可以使用 map
func PostMchXML ¶
func PostMchXML(ctx context.Context, config conf.MchConfig, path string, reqXML MchXML, options *Options) (MchXML, error)
PostMchXML 调用 mch xml 接口,大致过程如下:
- 添加公共字段 appid/mch_id/mch_id/nonce_str/sign_type
- 签名并添加 sign
- 调用 api,等待结果或错误
- 检查 return_code/return_msg
- 验证签名
- 验证 appid/mch_id
- 检查 result_code
NOTE: 最终用户一般不需要使用该函数
func (MchXML) MarshalXML ¶
MarshalXML 实现 xml.Marshaler 接口
func (MchXML) UnmarshalXML ¶
UnmarshalXML 实现 xml.Unmarshaler 接口
type Option ¶
Option 代表调用微信支付接口时的单个选项
func UseMiddleware ¶
UseMiddleware 设置中间件
func UseURLBase ¶
UseURLBase 设置 API 地址前缀,默认为 "https://api.mch.weixin.qq.com"
type Options ¶
type Options struct {
// contains filtered or unexported fields
}
Options 包含微信支付接口时的选项,NOTE: 某些选项未必对所有接口都有意义
func (*Options) Client ¶
func (options *Options) Client() utils.HTTPClient
Client 返回 HTTPClient,依次:options.client > DefaultOptions.client > utils.DefaultHTTPClient > http.DefaultClient
NOTE: 即使 options 为 nil 指针该方法仍能有效返回
func (*Options) Middleware ¶
Middleware 返回用于回调接口的服务端中间件,依次:options.middleware > DefaultOptions.middleware > noopMiddleware; 该中间件会被安装到所有回调接口的最外层,应用可以使用它来实现诸如记录请求响应的功能
NOTE: 即使 options 为 nil 指针该方法仍能有效返回
func (*Options) SignType ¶
SignType 返回签名方式,依次:options.signType > DefaultOptions.signType > MD5
NOTE: 即使 options 为 nil 指针该方法仍能有效返回
func (*Options) URLBase ¶
URLBase 返回 API 地址前缀,依次:options.urlBase > DefaultOptions.urlBase > "https://api.mch.weixin.qq.com"
NOTE: 即使 options 为 nil 指针该方法仍能有效返回
type OrderQueryRequest ¶
type OrderQueryRequest struct { // ----- 必填字段 ----- // 以下二选一 TransactionID string // transaction_id String(32) 微信支付订单号 建议优先使用 OutTradeNo string // out_trade_no String(32) 商户系统内部订单号 同一个商户号下唯一 }
OrderQueryRequest 为查询订单接口请求
type OrderQueryResponse ¶
type OrderQueryResponse struct { // ----- 原始数据 ----- MchXML MchXML // ----- 必返回字段 ----- OutTradeNo string // out_trade_no String(32) 商户系统内部订单号 同一个商户号下唯一 TradeState TradeState // trade_state String(32) 交易状态 // ----- 支付完成后(SUCCESS, REFUND) 必返回字段 ----- TransactionID string // transaction_id String(32) 微信支付订单号 OpenID string // openid String(128) 用户标识 TradeType TradeType // trade_type String(16) 交易类型 BankType string // bank_type String(16) 付款银行 TimeEnd time.Time // time_end String(14) 订单支付时间 TotalFee uint64 // total_fee Int 标价金额 CashFee uint64 // cash_fee Int 现金支付金额 // ----- 支付完成后可能返回的字段 ----- FeeType string // fee_type String(16) 标价币种 CashFeeType string // cash_fee_type String(16) 现金支付币种 Rate uint64 // rate String(16) 汇率 标价币种与支付币种兑换比例乘以10^8 // ----- 其它字段 ----- DeviceInfo string // device_info String(32) 设备号 TradeStateDesc string // trade_state_desc String(256) 交易状态描述 IsSubscribe string // is_subscribe String(1) Y/N 是否关注公众账号 仅在公众账号类型支付有效 Attach string // attach String(127) 附加数据 }
OrderQueryResponse 为查询订单接口响应
func OrderQuery ¶
func OrderQuery(ctx context.Context, config conf.MchConfig, req *OrderQueryRequest, opts ...Option) (*OrderQueryResponse, error)
OrderQuery 查询订单接口
type RefundInfo ¶
type RefundInfo struct { // ----- 必返回字段 ----- RefundID string // refund_id_$n String(32) 微信退款单号 OutRefundNo string // out_refund_no_$n String(64) 商户退款单号 RefundFee uint64 // refund_fee_$n Int 退款金额 RefundStatus RefundStatus // refund_status_$n String(16) 退款状态 // ----- 其它字段 ----- RefundChannel string // refund_channel_$n String(16) 退款渠道 RefundAccount string // refund_account_$n String(30) 退款资金来源 RefundRecvAccout string // refund_recv_accout_$n String(64) 退款入账账户 RefundSuccessTime time.Time // refund_success_time_$n String(20) 退款成功时间 (2016-07-25 15:26:26) }
RefundInfo 为查询退款接口响应中的单笔退款单信息
type RefundQueryRequest ¶
type RefundQueryRequest struct { // ----- 必填字段 ----- // 以下四选一,优先级为 refund_id > out_refund_no > transaction_id > out_trade_no RefundID string // refund_id String(32) 微信退款单号 OutRefundNo string // out_refund_no String(64) 商户退款单号 TransactionID string // transaction_id String(32) 微信订单号 OutTradeNo string // out_trade_no String(32) 商户订单号 // ----- 选填字段 ----- Offset uint // offset Int 偏移量 }
RefundQueryRequest 为查询退款接口请求
type RefundQueryResponse ¶
type RefundQueryResponse struct { // ----- 原始数据 ----- MchXML MchXML // ----- 必返回字段 ----- OutTradeNo string // out_trade_no String(32) 商户订单号 TransactionID string // transaction_id String(32) 微信订单号 TotalFee uint64 // total_fee Int 标价金额 CashFee uint64 // cash_fee Int 现金支付金额 RefundCount uint64 // refund_count 当前返回退款单数 Refunds []RefundInfo // 退款单信息 // ----- 其它字段 ----- TotalRefundCount uint64 // total_refund_count Int 订单总退款次数 FeeType string // fee_type String(16) 标价币种 CashFeeType string // cash_fee_type String(16) 现金支付币种 Rate uint64 // rate String(16) 汇率 标价币种与支付币种兑换比例乘以10^8 }
RefundQueryRequest 为查询退款接口响应
func RefundQuery ¶
func RefundQuery(ctx context.Context, config conf.MchConfig, req *RefundQueryRequest, opts ...Option) (*RefundQueryResponse, error)
RefundQuery 查询退款
type RefundRequest ¶
type RefundRequest struct { // ----- 必填字段 ----- OutRefundNo string // out_refund_no String(64) 商户退款单号,商户系统内部唯一 // 以下二选一 TransactionID string // transaction_id String(32) 微信订单号 OutTradeNo string // out_trade_no String(32) 商户订单号,商户系统内部唯一 // 金额字段 TotalFee uint64 // total_fee Int 标价金额 单位为分 RefundFee uint64 // refund_fee Int 退款金额 (NOTE: 此退款金额的币种跟标价金额是一致的) // ----- 选填字段 ----- RefundFeeType string // refund_fee_type String(8) 退款币种,必须与标价金额一致 RefundDesc string // refund_desc String(80) 退款原因 NotifyUrl string // notify_url String(256) 异步接收微信支付退款结果通知的回调地址 }
RefundRequest 为申请退款接口请求
type RefundResponse ¶
type RefundResponse struct { // ----- 原始数据 ----- MchXML MchXML // ----- 必返回字段 ----- TransactionID string // transaction_id String(32) 微信订单号 OutTradeNo string // out_trade_no String(32) 商户订单号 RefundID string // refund_id String(32) 微信退款单号 OutRefundNo string // out_refund_no String(64) 商户退款单号 TotalFee uint64 // total_fee Int 标价金额 CashFee uint64 // cash_fee Int 现金支付金额 RefundFee uint64 // refund_fee Int 退款金额 CashRefundFee uint64 // cash_refund_fee Int 现金退款金额 // ----- 选传字段 ----- FeeType string // fee_type String(16) 标价币种 CashFeeType string // cash_fee_type String(16) 现金支付币种 Rate uint64 // rate String(16) 汇率 标价币种与支付币种兑换比例乘以10^8 RefundFeeType string // refund_fee_type String(8) 退款币种 CashRefundFeeType string // cash_refund_fee_type String(8) 现金退款金额币种 }
RefundRequest 为申请退款接口响应
func Refund ¶
func Refund(ctx context.Context, config conf.MchConfig, req *RefundRequest, opts ...Option) (*RefundResponse, error)
Refund 申请退款接口,该接口需要客户端证书的 client
type RefundStatus ¶
type RefundStatus struct {
// contains filtered or unexported fields
}
RefundStatus 表示退款状态
type TradeState ¶
type TradeState struct {
// contains filtered or unexported fields
}
TradeState 表示交易状态
type TradeType ¶
type TradeType struct {
// contains filtered or unexported fields
}
TradeType 表示交易方式
type UnifiedOrderRequest ¶
type UnifiedOrderRequest struct { // ----- 必填字段 ----- OutTradeNo string // out_trade_no String(32) 商户系统内部订单号 同一个商户号下唯一 TotalFee uint64 // total_fee Int 标价金额 单位为分 Body string // body String(128) 商品描述 <商场名>-<商品名> NotifyUrl string // notify_url String(256) 通知地址 TradeType TradeType // trade_type String(16) 交易类型 // ----- 特定条件必填字段 ----- OpenID string // openid String(128) 用户标识 trade_type 为 JSAPI 时必填 // ----- 选填字段 ----- ProductID string // product_id String(32) 商户自定义商品 ID trade_type 为 NATIVE 时必传 DeviceInfo string // device_info String(32) 设备号 SpbillCreateIp string // spbill_create_ip String(16) 终端IP Detail string // detail String(6000) 商品详情 Attach string // attach String(127) 附加数据 FeeType string // fee_type String(16) 标价币种 TimeStart time.Time // time_start String(14) 交易起始时间 格式如 20091225091010 TimeExpire time.Time // time_expire String(14) 交易结束时间 GoodsTag string // goods_tag String(32) 订单优惠标记 LimitPay string // limit_pay String(32)指定支付方式 }
UnifiedOrderRequest 为统一下单接口请求
type UnifiedOrderResponse ¶
type UnifiedOrderResponse struct { // ----- 原始数据 ----- MchXML MchXML // ----- 必返回字段 ----- TradeType TradeType // trade_type String(16) 交易类型 PrepayID string // prepay_id String(64) 预支付交易会话标识 // ----- 特定条件返回字段 ----- CodeUrl string // code_url String(64) 二维码链接 trade_type 为 NATIVE 时有返回 MWebUrl string // mweb_url String(64) 支付跳转链接 trade_type 为 MWEB 时有返回 可通过访问该url来拉起微信客户端 // ----- 其它字段 DeviceInfo string // device_info String(32) 设备号 }
UnifiedOrderResponse 为统一下单接口响应
func UnifiedOrder ¶
func UnifiedOrder(ctx context.Context, config conf.MchConfig, req *UnifiedOrderRequest, opts ...Option) (*UnifiedOrderResponse, error)
UnifiedOrder 统一下单接口