Files
baseapi/platformapi/wxpayapi/wxpayapi.go
richboo111 15d19c09f6 1
2022-10-25 09:35:33 +08:00

666 lines
23 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package wxpayapi
import (
"bytes"
"crypto/hmac"
"crypto/md5"
"crypto/sha256"
"crypto/tls"
"encoding/xml"
"fmt"
"net/http"
"sort"
"strings"
"time"
"git.rosy.net.cn/baseapi"
"git.rosy.net.cn/baseapi/platformapi"
"git.rosy.net.cn/baseapi/utils"
"github.com/clbanning/mxj"
)
const (
prodURL = "https://api.mch.weixin.qq.com"
sandboxURL = "https://api.mch.weixin.qq.com/sandboxnew"
)
const (
ResponseCodeSuccess = "SUCCESS"
ResponseCodeFail = "FAIL"
sigKey = "sign"
sigTypeKey = "sign_type"
sigTypeMd5 = "MD5"
sigTypeSha256 = "HMAC-SHA256"
specialAction = "mmpaymkttransfers/promotion/transfers"
)
const (
FeeTypeCNY = "CNY"
)
const (
TradeTypeJSAPI = "JSAPI" // JSAPI支付或小程序支付
TradeTypeNative = "NATIVE"
TradeTypeAPP = "APP"
TradeTypeMicroPay = "MICROPAY"
OptYes = "Y"
OptNo = "N"
Relation = "PARTNER"
AccountTypeWx = "PERSONAL_WECHATID"
AccountTypeOpen = "PERSONAL_OPENID"
CheckName = "NO_CHECK"
)
var (
specialSignActions = map[string]string{
"secapi/pay/multiprofitsharing": "secapi/pay/multiprofitsharing",
"pay/profitsharingaddreceiver": "pay/profitsharingaddreceiver",
"pay/profitsharingremovereceiver": "pay/profitsharingremovereceiver",
"secapi/pay/profitsharingreturn": "secapi/pay/profitsharingreturn",
"secapi/pay/profitsharingfinish": "secapi/pay/profitsharingfinish",
}
)
type API struct {
appID string
appKey string
mchID string
client *http.Client
config *platformapi.APIConfig
}
type RequestBase struct {
XMLName xml.Name `json:"-" xml:"xml"`
AppID string `json:"appid" xml:"appid,omitempty"`
MchID string `json:"mch_id" xml:"mch_id,omitempty"`
// 企业付款基础参数不一样
AppID2 string `json:"mch_appid,omitempty" xml:"mch_appid,omitempty"`
MchID2 string `json:"mchid,omitempty" xml:"mchid,omitempty"`
DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
SignType string `json:"sign_type,omitempty" xml:"sign_type,omitempty"`
}
type IRequestBase interface {
SetAppID(action, appID string)
SetMchID(action, mchID string)
SetNonceStr(nonceStr string)
SetSign(sign string)
SetSignType(signType string)
}
func (r *RequestBase) SetAppID(action, appID string) {
if action != specialAction {
r.AppID = appID
} else {
r.AppID2 = appID
}
}
func (r *RequestBase) SetMchID(action, mchID string) {
if action != specialAction {
r.MchID = mchID
} else {
r.MchID2 = mchID
}
}
func (r *RequestBase) SetNonceStr(nonceStr string) {
r.NonceStr = nonceStr
}
func (r *RequestBase) SetSign(sign string) {
r.Sign = sign
}
func (r *RequestBase) SetSignType(signType string) {
r.SignType = signType
}
type OrderQueryParam struct {
RequestBase
TransactionID string `json:"transaction_id" xml:"transaction_id"`
OutTradeNo string `json:"out_trade_no" xml:"out_trade_no"`
}
type OrderInfo struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
AppID string `json:"appid" xml:"appid"`
DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
ResultCode string `json:"result_code" xml:"result_code"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
Attach string `json:"attach"`
BankType string `json:"bank_type"`
CashFee string `json:"cash_fee"`
CashFeeType string `json:"cash_fee_type"`
FeeType string `json:"fee_type"`
IsSubscribe string `json:"is_subscribe"`
OpenID string `json:"openid"`
OutTradeNo string `json:"out_trade_no"`
TimeEnd string `json:"time_end"`
TotalFee string `json:"total_fee"`
TradeState string `json:"trade_state"`
TradeStateDesc string `json:"trade_state_desc"`
TradeType string `json:"trade_type"`
TransactionID string `json:"transaction_id"`
}
type CreateOrderSceneInfo struct {
ID string `json:"id"`
Name string `json:"name"`
AreaCode string `json:"area_code"`
Address string `json:"address"`
}
type CreateOrderParam struct {
RequestBase
Body string `json:"body" xml:"body"`
NotifyURL string `json:"notify_url" xml:"notify_url"`
OutTradeNo string `json:"out_trade_no" xml:"out_trade_no"`
SpbillCreateIP string `json:"spbill_create_ip" xml:"spbill_create_ip"`
TradeType string `json:"trade_type" xml:"trade_type"`
TotalFee int `json:"total_fee" xml:"total_fee"`
// SubAppID string `json:"sub_appid" xml:"sub_appid,omitempty"`
SubMchID string `json:"sub_mch_id" xml:"sub_mch_id,omitempty"`
Detail CData `json:"detail.omitempty" xml:"detail,omitempty"`
Attach string `json:"attach,omitempty" xml:"attach,omitempty"`
FeeType string `json:"fee_type,omitempty" xml:"fee_type,omitempty"`
TimeStart string `json:"time_start,omitempty" xml:"time_start,omitempty"`
TimeExpire string `json:"time_expire,omitempty" xml:"time_expire,omitempty"`
GoodsTag string `json:"goods_tag,omitempty" xml:"goods_tag,omitempty"`
ProductID string `json:"product_id,omitempty" xml:"product_id,omitempty"`
LimitPay string `json:"limit_pay,omitempty" xml:"limit_pay,omitempty"`
OpenID string `json:"openid,omitempty" xml:"openid,omitempty"`
Receipt string `json:"receipt,omitempty" xml:"receipt,omitempty"`
SceneInfo string `json:"scene_info,omitempty" xml:"scene_info,omitempty"`
ProfitSharing string `json:"profit_sharing,omitempty" xml:"profit_sharing,omitempty"`
}
type CloseOrderParam struct {
RequestBase
OutTradeNo string `json:"out_trade_no" xml:"out_trade_no"`
}
type CreateOrderResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
AppID string `json:"appid" xml:"appid"`
DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
ResultCode string `json:"result_code" xml:"result_code"`
ResultMsg string `json:"result_msg" xml:"result_msg"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
TradeType string `json:"trade_type"`
PrepayID string `json:"prepay_id"`
CodeURL string `json:"code_url"`
}
type PayRefundParam struct {
RequestBase
TransactionID string `json:"transaction_id,omitempty" xml:"transaction_id,omitempty"`
OutTradeNo string `json:"out_trade_no,omitempty" xml:"out_trade_no,omitempty"`
OutRefundNo string `json:"out_refund_no" xml:"out_refund_no"`
TotalFee int `json:"total_fee" xml:"total_fee"`
RefundFee int `json:"refund_fee" xml:"refund_fee"`
RefundFeeType string `json:"refund_fee_type,omitempty" xml:"refund_fee_type,omitempty"`
RefundDesc CData `json:"refund_desc,omitempty" xml:"refund_desc,omitempty"`
NotifyURL string `json:"notify_url,omitempty" xml:"notify_url,omitempty"`
}
type PayRefundResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
AppID string `json:"appid" xml:"appid"`
DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
ResultCode string `json:"result_code" xml:"result_code"`
ResultMsg string `json:"result_msg" xml:"result_msg"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
CashFee string `json:"cash_fee"`
CashRefundFee string `json:"cash_refund_fee"`
CouponRefundCount string `json:"coupon_refund_count"`
CouponRefundFee string `json:"coupon_refund_fee"`
OutRefundNo string `json:"out_refund_no"`
OutTradeNo string `json:"out_trade_no"`
RefundChannel string `json:"refund_channel"`
RefundFee string `json:"refund_fee"`
RefundID string `json:"refund_id"`
TotalFee string `json:"total_fee"`
TransactionID string `json:"transaction_id"`
}
type MultiProfitSharingParam struct {
RequestBase
TransactionID string `json:"transaction_id" xml:"transaction_id"`
OutOrderNo string `json:"out_order_no" xml:"out_order_no"`
Receivers CData `json:"receivers" xml:"receivers"`
}
type MultiProfitSharingResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
ResultCode string `json:"result_code" xml:"result_code"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
AppID string `json:"appid" xml:"appid"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
TransactionID string `json:"transaction_id" xml:"transaction_id"`
OutOrderNo string `json:"out_order_no" xml:"out_order_no"`
OrderID string `json:"order_id" xml:"order_id"`
}
type TransfersParam struct {
RequestBase
PartnerTradeNo string `json:"partner_trade_no" xml:"partner_trade_no"`
OpenID string `json:"openid" xml:"openid"`
CheckName string `json:"check_name" xml:"check_name"`
ReUserName string `json:"re_user_name,omitempty" xml:"re_user_name,omitempty"`
Amount int `json:"amount" xml:"amount"`
Desc string `json:"desc" xml:"desc"`
SpbillCreateIP string `json:"spbill_create_ip" xml:"spbill_create_ip"`
}
type TransfersResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
ResultCode string `json:"result_code" xml:"result_code"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
AppID string `json:"appid" xml:"appid"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
DeviceInfo string `json:"device_info,omitempty" xml:"device_info,omitempty"`
PartnerTradeNo string `json:"partner_trade_no" xml:"partner_trade_no"`
PaymentNo string `json:"payment_no" xml:"payment_no"`
PaymentTime string `json:"payment_time" xml:"payment_time"`
}
type ProfitSharingReceiverParam struct {
RequestBase
Receiver CData `json:"receiver" xml:"receiver"`
}
type ProfitSharingReceiverResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
ResultCode string `json:"result_code" xml:"result_code"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
AppID string `json:"appid" xml:"appid"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
Receiver string `json:"receiver" xml:"receiver"`
}
type ReturnProfitSharingParam struct {
RequestBase
// OrderID string `json:"order_id" xml:"order_id"`
OutOrderNo string `json:"out_order_no" xml:"out_order_no"`
OutReturnNo string `json:"out_return_no" xml:"out_return_no"`
ReturnAccountType string `json:"return_account_type" xml:"return_account_type"`
ReturnAccount string `json:"return_account" xml:"return_account"`
ReturnAmount int `json:"return_amount" xml:"return_amount"`
Description string `json:"description" xml:"description"`
}
type ReturnProfitSharingResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ErrorCode string `json:"error_code,omitempty" xml:"error_code,omitempty"`
ErrorMsg string `json:"error_msg,omitempty" xml:"error_msg,omitempty"`
AppID string `json:"appid" xml:"appid"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
OrderID string `json:"order_id" xml:"order_id"`
OutOrderNo string `json:"out_order_no" xml:"out_order_no"`
OutReturnNo string `json:"out_return_no" xml:"out_return_no"`
ReturnNo string `json:"return_no" xml:"return_no"`
ReturnAccountType string `json:"return_account_type" xml:"return_account_type"`
ReturnAccount string `json:"return_account" xml:"return_account"`
ReturnAmount int `json:"return_amount" xml:"return_amount"`
Description string `json:"description" xml:"description"`
Result string `json:"result" xml:"result"`
FailReason string `json:"fail_reason,omitempty" xml:"fail_reason,omitempty"`
FinishTime string `json:"finish_time" xml:"finish_time"`
}
type FinishProfitSharingParam struct {
RequestBase
TransactionID string `json:"transaction_id" xml:"transaction_id"`
OutOrderNo string `json:"out_order_no" xml:"out_order_no"`
Description string `json:"description" xml:"description"`
}
type FinishProfitSharingResult struct {
ReturnCode string `json:"return_code" xml:"return_code"`
ReturnMsg string `json:"return_msg" xml:"return_msg"`
ResultCode string `json:"result_code" xml:"result_code"`
ErrCode string `json:"err_code,omitempty" xml:"err_code,omitempty"`
ErrCodeDes string `json:"err_code_des,omitempty" xml:"err_code_des,omitempty"`
AppID string `json:"appid" xml:"appid"`
MchID string `json:"mch_id" xml:"mch_id"`
NonceStr string `json:"nonce_str" xml:"nonce_str"`
Sign string `json:"sign" xml:"sign"`
TransactionID string `json:"transaction_id" xml:"transaction_id"`
OutOrderNo string `json:"out_order_no" xml:"out_order_no"`
OrderID string `json:"order_id" xml:"order_id"`
}
func New(appID, appKey, mchID string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
appID: appID,
appKey: appKey,
mchID: mchID,
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
}
func NewWithCertificate(appID, appKey, mchID string, certPEMBlock, keyPEMBlock interface{}, config ...*platformapi.APIConfig) (a *API) {
var certs tls.Certificate
var err error
if binCertPEMBlock, ok := certPEMBlock.([]byte); ok {
certs, err = tls.X509KeyPair(binCertPEMBlock, keyPEMBlock.([]byte))
} else {
certs, err = tls.LoadX509KeyPair(certPEMBlock.(string), keyPEMBlock.(string))
}
if err == nil {
// pool := x509.NewCertPool()
// pool.AppendCertsFromPEM(rootCa.([]byte))
a = New(appID, appKey, mchID, config...)
a.client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{
// RootCAs: pool,
Certificates: []tls.Certificate{certs},
},
}
} else {
baseapi.SugarLogger.Warnf("NewWithCertificate failed with err:%v", err)
}
return a
}
func (a *API) GetAppID() string {
return a.appID
}
func (a *API) GetMchID() string {
return a.mchID
}
func (a *API) signParam(signType string, 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))
}
}
}
sort.Sort(sort.StringSlice(valueList))
valueList = append(valueList, fmt.Sprintf("key=%s", a.appKey))
sig = strings.Join(valueList, "&")
var binSig []byte
if signType == sigTypeSha256 {
mac := hmac.New(sha256.New, []byte(a.appKey))
mac.Write([]byte(sig))
binSig = mac.Sum(nil)
} else {
binSig2 := md5.Sum([]byte(sig))
binSig = binSig2[:]
}
sig = fmt.Sprintf("%X", binSig)
// baseapi.SugarLogger.Debug(sig)
return sig
}
func mustMarshalXML(obj interface{}) []byte {
byteArr, err := xml.Marshal(obj)
if err != nil {
panic(fmt.Sprintf("err when Marshal obj:%v with error:%v", obj, err))
}
return byteArr
}
func (a *API) AccessAPI(action string, requestParam IRequestBase) (retVal map[string]interface{}, err error) {
requestParam.SetAppID(action, a.appID)
requestParam.SetMchID(action, a.mchID)
requestParam.SetNonceStr(utils.GetUUID())
var sigType string
if specialSignActions[action] != "" {
sigType = sigTypeSha256
requestParam.SetSignType(sigType)
} else if action == specialAction {
sigType = sigTypeMd5
} else {
sigType = sigTypeMd5
requestParam.SetSignType(sigType)
}
signStr := a.signParam(sigType, utils.Struct2FlatMap(requestParam))
requestParam.SetSign(signStr)
fullURL := utils.GenerateGetURL(prodURL, action, nil)
//var responseStr string
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodPost, fullURL, bytes.NewReader(mustMarshalXML(requestParam)))
return request
},
a.config,
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
//responseStr = bodyStr
if jsonResult1 == nil {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
}
retVal, errLevel, err = a.checkResultAsMap(jsonResult1[platformapi.KeyData].(string))
return errLevel, err
})
if err == nil {
if utils.Interface2String(retVal["result_code"]) != ResponseCodeSuccess {
err = utils.NewErrorCode(utils.Interface2String(retVal["err_code_des"]), utils.Interface2String(retVal["err_code"]))
if err != nil {
}
retVal = nil
}
}
return retVal, err
}
func (a *API) parseXmlStrAsMap(xmlStr string) (result map[string]interface{}, errLevel string, err error) {
mv, err := mxj.NewMapXml([]byte(xmlStr))
if err != nil {
errLevel = platformapi.ErrLevelGeneralFail
} else {
result = mv["xml"].(map[string]interface{})
}
return result, errLevel, err
}
func (a *API) checkResultAsMap(xmlStr string) (result map[string]interface{}, errLevel string, err error) {
result, errLevel, err = a.parseXmlStrAsMap(xmlStr)
if err == nil {
returnCode := utils.Interface2String(result["return_code"])
if returnCode != ResponseCodeSuccess {
errLevel = platformapi.ErrLevelGeneralFail
err = utils.NewErrorCode(utils.Interface2String(result["return_msg"]), returnCode)
result = nil
}
}
return result, errLevel, err
}
func SceneInfoList2String(sceneList []*CreateOrderSceneInfo) (str string) {
return string(utils.MustMarshal(sceneList))
}
func Time2PayTime(t time.Time) (str string) {
return t.Format("20060102150405")
}
func PayTime2Time(str string) (t time.Time) {
t, _ = time.ParseInLocation("20060102150405", str, time.Local)
return t
}
func (a *API) mapData2Err(mapData map[string]interface{}) (err error) {
if resultCode := utils.Interface2String(mapData["result_code"]); resultCode != ResponseCodeSuccess {
err = utils.NewErrorCode(utils.Interface2String(mapData["err_code_des"]), utils.Interface2String(mapData["err_code"]))
}
return err
}
func (a *API) translateResult(mapData map[string]interface{}, dataPtr interface{}) (err error) {
if err = a.mapData2Err(mapData); err == nil && dataPtr != nil {
err = utils.Map2StructByJson(mapData, dataPtr, false)
}
return err
}
func (a *API) OrderQuery(transactionID, outTradeNo string) (orderInfo *OrderInfo, err error) {
param := &OrderQueryParam{
TransactionID: transactionID,
OutTradeNo: outTradeNo,
}
retVal, err := a.AccessAPI("pay/orderquery", param)
if err == nil {
err = a.translateResult(retVal, &orderInfo)
}
return orderInfo, err
}
func (a *API) CreateUnifiedOrder(param *CreateOrderParam) (createOrderResult *CreateOrderResult, err error) {
retVal, err := a.AccessAPI("pay/unifiedorder", param)
if err == nil {
err = a.translateResult(retVal, &createOrderResult)
}
return createOrderResult, err
}
// 关闭订单
// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_3
// 注意订单生成后不能马上调用关单接口最短调用时间间隔为5分钟。
// 此函数好像可以重复操作,且关闭一个不存在的订单也不会报错的样
func (a *API) CloseOrder(outTradeNo string) (err error) {
retVal, err := a.AccessAPI("pay/closeorder", &CloseOrderParam{
OutTradeNo: outTradeNo,
})
if err == nil {
err = a.translateResult(retVal, nil)
}
return err
}
func (a *API) PayRefund(param *PayRefundParam) (refundResult *PayRefundResult, err error) {
if a.client.Transport == nil {
return nil, fmt.Errorf("没有配置证书,不能退款")
}
retVal, err := a.AccessAPI("secapi/pay/refund", param)
if err == nil {
err = a.translateResult(retVal, &refundResult)
}
return refundResult, err
}
//请求多次分账
//https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_6&index=2
func (a *API) MultiProfitSharing(param *MultiProfitSharingParam) (result *MultiProfitSharingResult, err error) {
retVal, err := a.AccessAPI("secapi/pay/multiprofitsharing", param)
if err == nil {
err = a.translateResult(retVal, &result)
}
return result, err
}
//企业付款
//https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
func (a *API) Transfers(param *TransfersParam) (result *TransfersResult, err error) {
retVal, err := a.AccessAPI(specialAction, param)
if err == nil {
err = a.translateResult(retVal, &result)
}
return result, err
}
//添加分账接收方
//https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_3&index=4
func (a *API) AddProfitSharingReceiver(param *ProfitSharingReceiverParam) (result *ProfitSharingReceiverResult, err error) {
retVal, err := a.AccessAPI("pay/profitsharingaddreceiver", param)
if err == nil {
err = a.translateResult(retVal, &result)
}
return result, err
}
//删除分账接收方
//https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_4&index=5
func (a *API) DeleteProfitSharingReceiver(param *ProfitSharingReceiverParam) (result *ProfitSharingReceiverResult, err error) {
retVal, err := a.AccessAPI("pay/profitsharingremovereceiver", param)
if err == nil {
err = a.translateResult(retVal, &result)
}
return result, err
}
//分账回退
//https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_7&index=7
func (a *API) ReturnProfitSharing(param *ReturnProfitSharingParam) (result *ReturnProfitSharingResult, err error) {
retVal, err := a.AccessAPI("secapi/pay/profitsharingreturn", param)
if err == nil {
err = a.translateResult(retVal, &result)
}
return result, err
}
//完结分账
//https://pay.weixin.qq.com/wiki/doc/api/allocation.php?chapter=27_5&index=6
func (a *API) FinishProfitSharing(param *FinishProfitSharingParam) (result *FinishProfitSharingResult, err error) {
retVal, err := a.AccessAPI("secapi/pay/profitsharingfinish", param)
if err == nil {
err = a.translateResult(retVal, &result)
}
return result, err
}