Skip to content

Commit

Permalink
alipay interface management (#299)
Browse files Browse the repository at this point in the history
* 文档整理
* 支付宝个人代扣协议查询接口 response 补充字段
  • Loading branch information
iGoogle-ink authored Feb 17, 2023
1 parent 634398b commit a28cef4
Show file tree
Hide file tree
Showing 10 changed files with 397 additions and 253 deletions.
8 changes: 4 additions & 4 deletions alipay/funds_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (a *Client) FundTransOrderQuery(ctx context.Context, bm gopay.BodyMap) (ali
}

// alipay.fund.trans.refund(资金退回接口)
// 文档地址: https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.refund
// 文档地址: https://opendocs.alipay.com/open/02byvd
func (a *Client) FundTransRefund(ctx context.Context, bm gopay.BodyMap) (aliRsp *FundTransRefundResponse, err error) {
err = bm.CheckEmptyError("order_id", "out_request_no", "refund_amount")
if err != nil {
Expand Down Expand Up @@ -171,7 +171,7 @@ func (a *Client) FundAuthOrderVoucherCreate(ctx context.Context, bm gopay.BodyMa
}

// alipay.fund.auth.order.app.freeze(线上资金授权冻结接口)
// 文档地址: https://opendocs.alipay.com/apis/api_28/alipay.fund.auth.order.app.freeze
// 文档地址: https://opendocs.alipay.com/open/02f912
func (a *Client) FundAuthOrderAppFreeze(ctx context.Context, bm gopay.BodyMap) (payParam string, err error) {
err = bm.CheckEmptyError("out_order_no", "out_request_no", "order_title", "amount", "product_code")
if err != nil {
Expand Down Expand Up @@ -320,7 +320,7 @@ func (a *Client) FundBatchDetailQuery(ctx context.Context, bm gopay.BodyMap) (al
}

// alipay.fund.trans.app.pay(现金红包无线支付接口)
// 文档地址: https://opendocs.alipay.com/apis/api_28/alipay.fund.trans.app.pay
// 文档地址: https://opendocs.alipay.com/open/03rbyf
func (a *Client) FundTransAppPay(ctx context.Context, bm gopay.BodyMap) (aliRsp *FundTransAppPayResponse, err error) {
err = bm.CheckEmptyError("out_biz_no", "trans_amount", "product_code", "biz_scene")
if err != nil {
Expand Down Expand Up @@ -366,7 +366,7 @@ func (a *Client) FundTransPayeeBindQuery(ctx context.Context, bm gopay.BodyMap)
}

// alipay.fund.trans.page.pay(资金转账页面支付接口)
// 文档地址: https://opendocs.alipay.com/apis/api_1/alipay.fund.trans.page.pay
// 文档地址: https://opendocs.alipay.com/open/03rbye
func (a *Client) FundTransPagePay(ctx context.Context, bm gopay.BodyMap) (aliRsp *FundTransPagePayRsp, err error) {
err = bm.CheckEmptyError("out_biz_no", "trans_amount", "product_code", "biz_scene")
if err != nil {
Expand Down
79 changes: 72 additions & 7 deletions alipay/member_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,52 @@ import (
"github.com/go-pay/gopay/pkg/util"
)

// alipay.system.oauth.token(换取授权访问令牌)
// 文档地址:https://opendocs.alipay.com/open/02ailc
func (a *Client) SystemOauthToken(ctx context.Context, bm gopay.BodyMap) (aliRsp *SystemOauthTokenResponse, err error) {
if bm.GetString("code") == util.NULL && bm.GetString("refresh_token") == util.NULL {
return nil, errors.New("code and refresh_token are not allowed to be null at the same time")
}
if err = bm.CheckEmptyError("grant_type"); err != nil {
return nil, err
}
var (
bs []byte
aat string
)
if a.AppCertSN != util.NULL {
bm.Set("app_cert_sn", a.AppCertSN)
}
if a.AliPayRootCertSN != util.NULL {
bm.Set("alipay_root_cert_sn", a.AliPayRootCertSN)
}
// default use app_auth_token
if a.AppAuthToken != util.NULL {
aat = a.AppAuthToken
}
// if user set app_auth_token in body_map, use this
if bmAt := bm.GetString("app_auth_token"); bmAt != util.NULL {
aat = bmAt
}
if bs, err = systemOauthToken(ctx, a.AppId, a.privateKey, bm, "alipay.system.oauth.token", a.IsProd, a.SignType, aat); err != nil {
return nil, err
}
aliRsp = new(SystemOauthTokenResponse)
if err = json.Unmarshal(bs, aliRsp); err != nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
if aliRsp.ErrorResponse != nil {
info := aliRsp.ErrorResponse
return aliRsp, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
}
signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
aliRsp.SignData = signData
return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
}

// alipay.user.info.share(支付宝会员授权信息查询接口)
// body:此接口无需body参数
// 文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.info.share
// 文档地址:https://opendocs.alipay.com/open/02aild
func (a *Client) UserInfoShare(ctx context.Context, authToken string) (aliRsp *UserInfoShareResponse, err error) {
if authToken == "" {
return nil, errors.New("auth_token can not be null")
Expand All @@ -27,16 +70,39 @@ func (a *Client) UserInfoShare(ctx context.Context, authToken string) (aliRsp *U
if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
return aliRsp, err
if aliRsp.ErrorResponse != nil {
info := aliRsp.ErrorResponse
return aliRsp, fmt.Errorf(`{"code":"%s","msg":"%s","sub_code":"%s","sub_msg":"%s"}`, info.Code, info.Msg, info.SubCode, info.SubMsg)
}
signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
aliRsp.SignData = signData
return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
}

// alipay.user.info.auth(用户登陆授权)
// 注意:不支持自动验签
// 文档地址:https://opendocs.alipay.com/open/02aile
func (a *Client) UserInfoAuth(ctx context.Context, bm gopay.BodyMap) (html []byte, err error) {
err = bm.CheckEmptyError("scopes", "state")
if err != nil {
return nil, err
}
var bs []byte
if bs, err = a.doAliPay(ctx, bm, "alipay.user.info.auth"); err != nil {
return nil, err
}
if strings.Contains(string(bs), "<head>") {
return bs, nil
}
uiaErr := new(UserInfoAuthResponse)
if err = json.Unmarshal(bs, uiaErr); err != nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
return nil, bizErrCheck(*uiaErr.Response)
}

// alipay.user.certify.open.initialize(身份认证初始化服务)
// 文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.certify.open.initialize
// 文档地址:https://opendocs.alipay.com/open/02ahjy
func (a *Client) UserCertifyOpenInit(ctx context.Context, bm gopay.BodyMap) (aliRsp *UserCertifyOpenInitResponse, err error) {
err = bm.CheckEmptyError("outer_order_no", "biz_code", "identity_param", "merchant_config")
if err != nil {
Expand All @@ -59,8 +125,7 @@ func (a *Client) UserCertifyOpenInit(ctx context.Context, bm gopay.BodyMap) (ali
}

// alipay.user.certify.open.certify(身份认证开始认证)
// API文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.certify.open.certify
// 产品文档地址:https://opendocs.alipay.com/open/20181012100420932508/quickstart
// API文档地址:https://opendocs.alipay.com/open/02ahk0
func (a *Client) UserCertifyOpenCertify(ctx context.Context, bm gopay.BodyMap) (certifyUrl string, err error) {
err = bm.CheckEmptyError("certify_id")
if err != nil {
Expand All @@ -75,7 +140,7 @@ func (a *Client) UserCertifyOpenCertify(ctx context.Context, bm gopay.BodyMap) (
}

// alipay.user.certify.open.query(身份认证记录查询)
// 文档地址:https://opendocs.alipay.com/apis/api_2/alipay.user.certify.open.query
// 文档地址:https://opendocs.alipay.com/open/02ahjw
func (a *Client) UserCertifyOpenQuery(ctx context.Context, bm gopay.BodyMap) (aliRsp *UserCertifyOpenQueryResponse, err error) {
err = bm.CheckEmptyError("certify_id")
if err != nil {
Expand Down
47 changes: 41 additions & 6 deletions alipay/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,14 +270,14 @@ type OauthTokenInfo struct {

// ===================================================
type UserInfoShareResponse struct {
Response *UserInfoShare `json:"alipay_user_info_share_response"`
AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
SignData string `json:"-"`
Sign string `json:"sign"`
Response *UserInfoShare `json:"alipay_user_info_share_response"`
ErrorResponse *ErrorResponse `json:"error_response,omitempty"`
AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
SignData string `json:"-"`
Sign string `json:"sign"`
}

type UserInfoShare struct {
ErrorResponse
UserId string `json:"user_id,omitempty"`
Avatar string `json:"avatar,omitempty"`
Province string `json:"province,omitempty"`
Expand Down Expand Up @@ -874,6 +874,19 @@ type Token struct {
UserId string `json:"user_id,omitempty"`
}

// ===================================================
type OpenAuthTokenAppInviteCreateResponse struct {
Response *OpenAuthTokenAppInviteCreate `json:"alipay_open_auth_appauth_invite_create_response"`
AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
SignData string `json:"-"`
Sign string `json:"sign"`
}

type OpenAuthTokenAppInviteCreate struct {
ErrorResponse
TaskPageUrl string `json:"task_page_url,omitempty"`
}

// ===================================================
type OpenAuthTokenAppQueryResponse struct {
Response *AuthTokenAppQuery `json:"alipay_open_auth_token_app_query_response"`
Expand Down Expand Up @@ -1066,12 +1079,12 @@ type UserAgreementQueryRsp struct {

type UserAgreementQuery struct {
ErrorResponse
PrincipalId string `json:"principal_id"`
ValidTime string `json:"valid_time"`
AlipayLogonId string `json:"alipay_logon_id"`
InvalidTime string `json:"invalid_time"`
PricipalType string `json:"pricipal_type"`
DeviceId string `json:"device_id,omitempty"`
PrincipalId string `json:"principal_id"`
SignScene string `json:"sign_scene"`
AgreementNo string `json:"agreement_no"`
ThirdPartyType string `json:"third_party_type"`
Expand All @@ -1082,6 +1095,9 @@ type UserAgreementQuery struct {
ZmOpenId string `json:"zm_open_id,omitempty"`
ExternalLogonId string `json:"external_logon_id,omitempty"`
CreditAuthMode string `json:"credit_auth_mode,omitempty"`
SingleQuota string `json:"single_quota,omitempty"`
LastDeductTime string `json:"last_deduct_time,omitempty"`
NextDeductTime string `json:"next_deduct_time,omitempty"`
}

// ===================================================
Expand Down Expand Up @@ -2193,3 +2209,22 @@ type Receiver struct {
Account string `json:"account"`
Memo string `json:"memo"`
}

// ===================================================
type OpenAppApiQueryResponse struct {
Response *OpenAppApiQuery `json:"alipay_open_app_api_query_response"`
AlipayCertSn string `json:"alipay_cert_sn,omitempty"`
SignData string `json:"-"`
Sign string `json:"sign"`
}

type OpenAppApiQuery struct {
ErrorResponse
Apis []*Apis `json:"apis"`
}

type Apis struct {
ApiName string `json:"api_name,omitempty"`
FieldName string `json:"field_name,omitempty"`
PackageCode string `json:"package_code,omitempty"`
}
82 changes: 82 additions & 0 deletions alipay/third_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package alipay

import (
"context"
"encoding/json"
"errors"
"fmt"

"github.com/go-pay/gopay"
"github.com/go-pay/gopay/pkg/util"
)

// alipay.open.auth.token.app(换取应用授权令牌)
// 文档地址:https://opendocs.alipay.com/isv/04h3uf
func (a *Client) OpenAuthTokenApp(ctx context.Context, bm gopay.BodyMap) (aliRsp *OpenAuthTokenAppResponse, err error) {
if bm.GetString("code") == util.NULL && bm.GetString("refresh_token") == util.NULL {
return nil, errors.New("code and refresh_token are not allowed to be null at the same time")
}
err = bm.CheckEmptyError("grant_type")
if err != nil {
return nil, err
}
var bs []byte
if bs, err = a.doAliPay(ctx, bm, "alipay.open.auth.token.app"); err != nil {
return nil, err
}
aliRsp = new(OpenAuthTokenAppResponse)
if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
return aliRsp, err
}
signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
aliRsp.SignData = signData
return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
}

// alipay.open.auth.token.app.query(查询某个应用授权AppAuthToken的授权信息)
// 文档地址:https://opendocs.alipay.com/isv/04hgcp
func (a *Client) OpenAuthTokenAppQuery(ctx context.Context, bm gopay.BodyMap) (aliRsp *OpenAuthTokenAppQueryResponse, err error) {
err = bm.CheckEmptyError("app_auth_token")
if err != nil {
return nil, err
}
var bs []byte
if bs, err = a.doAliPay(ctx, bm, "alipay.open.auth.token.app.query"); err != nil {
return nil, err
}
aliRsp = new(OpenAuthTokenAppQueryResponse)
if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
return aliRsp, err
}
signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
aliRsp.SignData = signData
return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
}

// alipay.open.auth.appauth.invite.create(ISV向商户发起应用授权邀约)
// 文档地址:https://opendocs.alipay.com/isv/06evao
func (a *Client) OpenAuthTokenAppInviteCreate(ctx context.Context, bm gopay.BodyMap) (aliRsp *OpenAuthTokenAppInviteCreateResponse, err error) {
if err = bm.CheckEmptyError("auth_app_id"); err != nil {
return nil, err
}
var bs []byte
if bs, err = a.doAliPay(ctx, bm, "alipay.open.auth.appauth.invite.create"); err != nil {
return nil, err
}
aliRsp = new(OpenAuthTokenAppInviteCreateResponse)
if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
return aliRsp, err
}
signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
aliRsp.SignData = signData
return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
}
32 changes: 32 additions & 0 deletions alipay/third_dev.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package alipay

import (
"context"
"encoding/json"
"fmt"

"github.com/go-pay/gopay"
)

// alipay.open.app.api.query(查询应用可申请的接口出参敏感字段列表)
// 文档地址:https://opendocs.alipay.com/isv/04f74n
func (a *Client) OpenAppApiQuery(ctx context.Context, bm gopay.BodyMap) (aliRsp *OpenAppApiQueryResponse, err error) {
err = bm.CheckEmptyError("app_auth_token")
if err != nil {
return nil, err
}
var bs []byte
if bs, err = a.doAliPay(ctx, bm, "alipay.open.app.api.query"); err != nil {
return nil, err
}
aliRsp = new(OpenAppApiQueryResponse)
if err = json.Unmarshal(bs, aliRsp); err != nil || aliRsp.Response == nil {
return nil, fmt.Errorf("[%w], bytes: %s", gopay.UnmarshalErr, string(bs))
}
if err = bizErrCheck(aliRsp.Response.ErrorResponse); err != nil {
return aliRsp, err
}
signData, signDataErr := a.getSignData(bs, aliRsp.AlipayCertSn)
aliRsp.SignData = signData
return aliRsp, a.autoVerifySignByCert(aliRsp.Sign, signData, signDataErr)
}
Loading

0 comments on commit a28cef4

Please sign in to comment.