mirror of
https://github.com/silenceper/wechat.git
synced 2026-02-13 17:22:26 +08:00
feat: create mini program virtual payment (#709)
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## 包说明
|
## 包说明
|
||||||
|
|
||||||
- analysis 数据分析相关API
|
- analysis 数据分析相关 API
|
||||||
|
|
||||||
## 快速入门
|
## 快速入门
|
||||||
|
|
||||||
@@ -18,4 +18,35 @@ cfg := &miniConfig.Config{
|
|||||||
}
|
}
|
||||||
miniprogram := wc.GetMiniProgram(cfg)
|
miniprogram := wc.GetMiniProgram(cfg)
|
||||||
miniprogram.GetAnalysis().GetAnalysisDailyRetain()
|
miniprogram.GetAnalysis().GetAnalysisDailyRetain()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 小程序虚拟支付
|
||||||
|
#### `注意:需要传入 Appkey 的值`
|
||||||
|
相关文档:[小程序虚拟支付](https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html)
|
||||||
|
```go
|
||||||
|
wc := wechat.NewWechat()
|
||||||
|
miniprogram := wc.GetMiniProgram(&miniConfig.Config{
|
||||||
|
AppID: "xxx",
|
||||||
|
AppSecret: "xxx",
|
||||||
|
AppKey: "xxx",
|
||||||
|
Cache: cache.NewRedis(&redis.Options{
|
||||||
|
Addr: "",
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
virtualPayment := miniprogram.GetVirtualPayment()
|
||||||
|
virtualPayment.SetSessionKey("xxx")
|
||||||
|
// 查询用户余额
|
||||||
|
var (
|
||||||
|
res *virtualPayment.QueryUserBalanceResponse
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if res, err = virtualPayment.QueryUserBalance(context.TODO(), &virtualPayment.QueryUserBalanceRequest{
|
||||||
|
OpenID: "xxx",
|
||||||
|
Env: virtualPayment.EnvProduction,
|
||||||
|
UserIP: "xxx",
|
||||||
|
}); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Package config 小程序config配置
|
// Package config 小程序 config 配置
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -9,5 +9,6 @@ import (
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
AppID string `json:"app_id"` // appid
|
AppID string `json:"app_id"` // appid
|
||||||
AppSecret string `json:"app_secret"` // appSecret
|
AppSecret string `json:"app_secret"` // appSecret
|
||||||
|
AppKey string `json:"app_key"` // appKey
|
||||||
Cache cache.Cache
|
Cache cache.Cache
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,15 +20,16 @@ import (
|
|||||||
"github.com/silenceper/wechat/v2/miniprogram/tcb"
|
"github.com/silenceper/wechat/v2/miniprogram/tcb"
|
||||||
"github.com/silenceper/wechat/v2/miniprogram/urllink"
|
"github.com/silenceper/wechat/v2/miniprogram/urllink"
|
||||||
"github.com/silenceper/wechat/v2/miniprogram/urlscheme"
|
"github.com/silenceper/wechat/v2/miniprogram/urlscheme"
|
||||||
|
"github.com/silenceper/wechat/v2/miniprogram/virtualpayment"
|
||||||
"github.com/silenceper/wechat/v2/miniprogram/werun"
|
"github.com/silenceper/wechat/v2/miniprogram/werun"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MiniProgram 微信小程序相关API
|
// MiniProgram 微信小程序相关 API
|
||||||
type MiniProgram struct {
|
type MiniProgram struct {
|
||||||
ctx *context.Context
|
ctx *context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMiniProgram 实例化小程序API
|
// NewMiniProgram 实例化小程序 API
|
||||||
func NewMiniProgram(cfg *config.Config) *MiniProgram {
|
func NewMiniProgram(cfg *config.Config) *MiniProgram {
|
||||||
defaultAkHandle := credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, credential.CacheKeyMiniProgramPrefix, cfg.Cache)
|
defaultAkHandle := credential.NewDefaultAccessToken(cfg.AppID, cfg.AppSecret, credential.CacheKeyMiniProgramPrefix, cfg.Cache)
|
||||||
ctx := &context.Context{
|
ctx := &context.Context{
|
||||||
@@ -38,7 +39,7 @@ func NewMiniProgram(cfg *config.Config) *MiniProgram {
|
|||||||
return &MiniProgram{ctx}
|
return &MiniProgram{ctx}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAccessTokenHandle 自定义access_token获取方式
|
// SetAccessTokenHandle 自定义 access_token 获取方式
|
||||||
func (miniProgram *MiniProgram) SetAccessTokenHandle(accessTokenHandle credential.AccessTokenHandle) {
|
func (miniProgram *MiniProgram) SetAccessTokenHandle(accessTokenHandle credential.AccessTokenHandle) {
|
||||||
miniProgram.ctx.AccessTokenHandle = accessTokenHandle
|
miniProgram.ctx.AccessTokenHandle = accessTokenHandle
|
||||||
}
|
}
|
||||||
@@ -68,17 +69,17 @@ func (miniProgram *MiniProgram) GetBusiness() *business.Business {
|
|||||||
return business.NewBusiness(miniProgram.ctx)
|
return business.NewBusiness(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPrivacy 小程序隐私协议相关API
|
// GetPrivacy 小程序隐私协议相关 API
|
||||||
func (miniProgram *MiniProgram) GetPrivacy() *privacy.Privacy {
|
func (miniProgram *MiniProgram) GetPrivacy() *privacy.Privacy {
|
||||||
return privacy.NewPrivacy(miniProgram.ctx)
|
return privacy.NewPrivacy(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetQRCode 小程序码相关API
|
// GetQRCode 小程序码相关 API
|
||||||
func (miniProgram *MiniProgram) GetQRCode() *qrcode.QRCode {
|
func (miniProgram *MiniProgram) GetQRCode() *qrcode.QRCode {
|
||||||
return qrcode.NewQRCode(miniProgram.ctx)
|
return qrcode.NewQRCode(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTcb 小程序云开发API
|
// GetTcb 小程序云开发 API
|
||||||
func (miniProgram *MiniProgram) GetTcb() *tcb.Tcb {
|
func (miniProgram *MiniProgram) GetTcb() *tcb.Tcb {
|
||||||
return tcb.NewTcb(miniProgram.ctx)
|
return tcb.NewTcb(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
@@ -103,7 +104,7 @@ func (miniProgram *MiniProgram) GetContentSecurity() *content.Content {
|
|||||||
return content.NewContent(miniProgram.ctx)
|
return content.NewContent(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetURLLink 小程序URL Link接口
|
// GetURLLink 小程序 URL Link 接口
|
||||||
func (miniProgram *MiniProgram) GetURLLink() *urllink.URLLink {
|
func (miniProgram *MiniProgram) GetURLLink() *urllink.URLLink {
|
||||||
return urllink.NewURLLink(miniProgram.ctx)
|
return urllink.NewURLLink(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
@@ -123,12 +124,17 @@ func (miniProgram *MiniProgram) GetShortLink() *shortlink.ShortLink {
|
|||||||
return shortlink.NewShortLink(miniProgram.ctx)
|
return shortlink.NewShortLink(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSURLScheme 小程序URL Scheme接口
|
// GetSURLScheme 小程序 URL Scheme 接口
|
||||||
func (miniProgram *MiniProgram) GetSURLScheme() *urlscheme.URLScheme {
|
func (miniProgram *MiniProgram) GetSURLScheme() *urlscheme.URLScheme {
|
||||||
return urlscheme.NewURLScheme(miniProgram.ctx)
|
return urlscheme.NewURLScheme(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOpenAPI openApi管理接口
|
// GetOpenAPI openApi 管理接口
|
||||||
func (miniProgram *MiniProgram) GetOpenAPI() *openapi.OpenAPI {
|
func (miniProgram *MiniProgram) GetOpenAPI() *openapi.OpenAPI {
|
||||||
return openapi.NewOpenAPI(miniProgram.ctx)
|
return openapi.NewOpenAPI(miniProgram.ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVirtualPayment 小程序虚拟支付
|
||||||
|
func (miniProgram *MiniProgram) GetVirtualPayment() *virtualpayment.VirtualPayment {
|
||||||
|
return virtualpayment.NewVirtualPayment(miniProgram.ctx)
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ func NewShortLink(ctx *context.Context) *ShortLink {
|
|||||||
// ShortLinker 请求结构体
|
// ShortLinker 请求结构体
|
||||||
type ShortLinker struct {
|
type ShortLinker struct {
|
||||||
|
|
||||||
// pageUrl 通过 Short Link 进入的小程序页面路径,必须是已经发布的小程序存在的页面,可携带 query,最大1024个字符
|
// pageUrl 通过 Short Link 进入的小程序页面路径,必须是已经发布的小程序存在的页面,可携带 query,最大 1024 个字符
|
||||||
PageURL string `json:"page_url"`
|
PageURL string `json:"page_url"`
|
||||||
|
|
||||||
// pageTitle 页面标题,不能包含违法信息,超过20字符会用... 截断代替
|
// pageTitle 页面标题,不能包含违法信息,超过 20 字符会用... 截断代替
|
||||||
PageTitle string `json:"page_title"`
|
PageTitle string `json:"page_title"`
|
||||||
|
|
||||||
// isPermanent 生成的 Short Link 类型,短期有效:false,永久有效:true
|
// isPermanent 生成的 Short Link 类型,短期有效:false,永久有效:true
|
||||||
@@ -67,7 +67,7 @@ func (shortLink *ShortLink) generate(shortLinkParams ShortLinker) (string, error
|
|||||||
return res.Link, nil
|
return res.Link, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateShortLinkPermanent 生成永久shortLink
|
// GenerateShortLinkPermanent 生成永久 shortLink
|
||||||
func (shortLink *ShortLink) GenerateShortLinkPermanent(PageURL, pageTitle string) (string, error) {
|
func (shortLink *ShortLink) GenerateShortLinkPermanent(PageURL, pageTitle string) (string, error) {
|
||||||
return shortLink.generate(ShortLinker{
|
return shortLink.generate(ShortLinker{
|
||||||
PageURL: PageURL,
|
PageURL: PageURL,
|
||||||
@@ -76,7 +76,7 @@ func (shortLink *ShortLink) GenerateShortLinkPermanent(PageURL, pageTitle string
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateShortLinkTemp 生成临时shortLink
|
// GenerateShortLinkTemp 生成临时 shortLink
|
||||||
func (shortLink *ShortLink) GenerateShortLinkTemp(PageURL, pageTitle string) (string, error) {
|
func (shortLink *ShortLink) GenerateShortLinkTemp(PageURL, pageTitle string) (string, error) {
|
||||||
return shortLink.generate(ShortLinker{
|
return shortLink.generate(ShortLinker{
|
||||||
PageURL: PageURL,
|
PageURL: PageURL,
|
||||||
|
|||||||
134
miniprogram/virtualpayment/constant.go
Normal file
134
miniprogram/virtualpayment/constant.go
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* Copyright silenceper/wechat Author(https://silenceper.com/wechat/). All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You can obtain one at https://github.com/silenceper/wechat.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package virtualpayment
|
||||||
|
|
||||||
|
const (
|
||||||
|
// EnvProduction 环境 0-正式环境 1-沙箱环境
|
||||||
|
EnvProduction Env = 0
|
||||||
|
// EnvSandbox 环境 0-正式环境 1-沙箱环境
|
||||||
|
EnvSandbox Env = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Success 错误码 0、成功
|
||||||
|
Success ErrCode = 0
|
||||||
|
// SystemError 错误码 -1、系统错误
|
||||||
|
SystemError ErrCode = -1
|
||||||
|
// OpenIDError 错误码 268490001、openid 错误
|
||||||
|
OpenIDError ErrCode = 268490001
|
||||||
|
// RequestParamError 错误码 268490002、请求参数字段错误,具体看 errmsg
|
||||||
|
RequestParamError ErrCode = 268490002
|
||||||
|
// SignError 错误码 268490003、签名错误
|
||||||
|
SignError ErrCode = 268490003
|
||||||
|
// RepeatOperationError 错误码 268490004、重复操作(赠送和代币支付相关接口会返回,表示之前的操作已经成功)
|
||||||
|
RepeatOperationError ErrCode = 268490004
|
||||||
|
// OrderRefundedError 错误码 268490005、订单已经通过 cancel_currency_pay 接口退款,不支持再退款
|
||||||
|
OrderRefundedError ErrCode = 268490005
|
||||||
|
// InsufficientBalanceError 错误码 268490006、代币的退款/支付操作金额不足
|
||||||
|
InsufficientBalanceError ErrCode = 268490006
|
||||||
|
// SensitiveContentError 错误码 268490007、图片或文字存在敏感内容,禁止使用
|
||||||
|
SensitiveContentError ErrCode = 268490007
|
||||||
|
// TokenNotPublishedError 错误码 268490008、代币未发布,不允许进行代币操作
|
||||||
|
TokenNotPublishedError ErrCode = 268490008
|
||||||
|
// SessionKeyExpiredError 错误码 268490009、用户 session_key 不存在或已过期,请重新登录
|
||||||
|
SessionKeyExpiredError ErrCode = 268490009
|
||||||
|
// BillGeneratingError 错误码 268490011、账单数据生成中,请稍后调用本接口获取
|
||||||
|
BillGeneratingError ErrCode = 268490011
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// OrderStatusInit 订单状态 当前状态 0-订单初始化(未创建成功,不可用于支付)
|
||||||
|
OrderStatusInit OrderStatus = 0
|
||||||
|
// OrderStatusCreated 订单状态 当前状态 1-订单创建成功
|
||||||
|
OrderStatusCreated OrderStatus = 1
|
||||||
|
// OrderStatusPaid 订单状态 当前状态 2-订单已经支付,待发货
|
||||||
|
OrderStatusPaid OrderStatus = 2
|
||||||
|
// OrderStatusDelivering 订单状态 当前状态 3-订单发货中
|
||||||
|
OrderStatusDelivering OrderStatus = 3
|
||||||
|
// OrderStatusDelivered 订单状态 当前状态 4-订单已发货
|
||||||
|
OrderStatusDelivered OrderStatus = 4
|
||||||
|
// OrderStatusRefunded 订单状态 当前状态 5-订单已经退款
|
||||||
|
OrderStatusRefunded OrderStatus = 5
|
||||||
|
// OrderStatusClosed 订单状态 当前状态 6-订单已经关闭(不可再使用)
|
||||||
|
OrderStatusClosed OrderStatus = 6
|
||||||
|
// OrderStatusRefundFailed 订单状态 当前状态 7-订单退款失败
|
||||||
|
OrderStatusRefundFailed OrderStatus = 7
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// baseSite 基础网址
|
||||||
|
baseSite = "https://api.weixin.qq.com"
|
||||||
|
|
||||||
|
// queryUserBalance 查询虚拟支付余额
|
||||||
|
queryUserBalance = "/xpay/query_user_balance"
|
||||||
|
|
||||||
|
// currencyPay 扣减代币(一般用于代币支付)
|
||||||
|
currencyPay = "/xpay/currency_pay"
|
||||||
|
|
||||||
|
// queryOrder 查询创建的订单(现金单,非代币单)
|
||||||
|
queryOrder = "/xpay/query_order"
|
||||||
|
|
||||||
|
// cancelCurrencyPay 代币支付退款 (currency_pay 接口的逆操作)
|
||||||
|
cancelCurrencyPay = "/xpay/cancel_currency_pay"
|
||||||
|
|
||||||
|
// notifyProvideGoods 通知已经发货完成(只能通知现金单),正常通过 xpay_goods_deliver_notify 消息推送返回成功就不需要调用这个 api 接口。这个接口用于异常情况推送不成功时手动将单改成已发货状态
|
||||||
|
notifyProvideGoods = "/xpay/notify_provide_goods"
|
||||||
|
|
||||||
|
// presentCurrency 代币赠送接口,由于目前不支付按单号查赠送单的功能,所以当需要赠送的时候可以一直重试到返回 0 或者返回 268490004(重复操作)为止
|
||||||
|
presentCurrency = "/xpay/present_currency"
|
||||||
|
|
||||||
|
// downloadBill 下载账单
|
||||||
|
downloadBill = "/xpay/download_bill"
|
||||||
|
|
||||||
|
// refundOrder 退款 对使用 jsapi 接口下的单进行退款
|
||||||
|
refundOrder = "/xpay/refund_order"
|
||||||
|
|
||||||
|
// createWithdrawOrder 创建提现单
|
||||||
|
createWithdrawOrder = "/xpay/create_withdraw_order"
|
||||||
|
|
||||||
|
// queryWithdrawOrder 查询提现单
|
||||||
|
queryWithdrawOrder = "/xpay/query_withdraw_order"
|
||||||
|
|
||||||
|
// startUploadGoods 启动批量上传道具任务
|
||||||
|
startUploadGoods = "/xpay/start_upload_goods"
|
||||||
|
|
||||||
|
// queryUploadGoods 查询批量上传道具任务状态
|
||||||
|
queryUploadGoods = "/xpay/query_upload_goods"
|
||||||
|
|
||||||
|
// startPublishGoods 启动批量发布道具任务
|
||||||
|
startPublishGoods = "/xpay/start_publish_goods"
|
||||||
|
|
||||||
|
// queryPublishGoods 查询批量发布道具任务状态
|
||||||
|
queryPublishGoods = "/xpay/query_publish_goods"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// signature user mode signature
|
||||||
|
signature = "signature"
|
||||||
|
|
||||||
|
// paySignature payment signature
|
||||||
|
paySignature = "pay_sig"
|
||||||
|
|
||||||
|
// accessToken access_token authorization tokens
|
||||||
|
accessToken = "access_token"
|
||||||
|
|
||||||
|
// EmptyString empty string
|
||||||
|
EmptyString = ""
|
||||||
|
)
|
||||||
32
miniprogram/virtualpayment/doc.go
Normal file
32
miniprogram/virtualpayment/doc.go
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright silenceper/wechat Author(https://silenceper.com/wechat/). All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You can obtain one at https://github.com/silenceper/wechat.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package virtualpayment mini program virtual payment
|
||||||
|
package virtualpayment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/silenceper/wechat/v2/miniprogram/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewVirtualPayment 实例化小程序虚拟支付 API
|
||||||
|
func NewVirtualPayment(ctx *context.Context) *VirtualPayment {
|
||||||
|
return &VirtualPayment{
|
||||||
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
}
|
||||||
427
miniprogram/virtualpayment/domain.go
Normal file
427
miniprogram/virtualpayment/domain.go
Normal file
@@ -0,0 +1,427 @@
|
|||||||
|
/*
|
||||||
|
* Copyright silenceper/wechat Author(https://silenceper.com/wechat/). All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You can obtain one at https://github.com/silenceper/wechat.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package virtualpayment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/silenceper/wechat/v2/miniprogram/context"
|
||||||
|
"github.com/silenceper/wechat/v2/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VirtualPayment mini program virtual payment
|
||||||
|
// https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/virtual-payment.html#_2-3-%E6%9C%8D%E5%8A%A1%E5%99%A8API
|
||||||
|
type VirtualPayment struct {
|
||||||
|
ctx *context.Context
|
||||||
|
sessionKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Env Environment 0 - Production environment 1 - Sandbox environment
|
||||||
|
type Env int
|
||||||
|
|
||||||
|
// ErrCode error code
|
||||||
|
type ErrCode int
|
||||||
|
|
||||||
|
// OrderStatus 订单状态
|
||||||
|
type OrderStatus int
|
||||||
|
|
||||||
|
// CommonRequest common request parameters
|
||||||
|
type CommonRequest struct {
|
||||||
|
OpenID string `json:"openid"` // The user's openID
|
||||||
|
Env Env `json:"env"` // Environment 0 - Production environment 1 - Sandbox environment
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaymentRequest payment request parameters
|
||||||
|
type PaymentRequest struct {
|
||||||
|
SignData string `json:"sign_data"` // 具体支付参数见 signData, 该参数需以 string 形式传递,例如 signData: '{"offerId":"123","buyQuantity":1,"env":0,"currencyType":"CNY","platform":"android","productId":"testproductId","goodsPrice":10,"outTradeNo":"xxxxxx","attach":"testdata"}'
|
||||||
|
Mode string `json:"mode"` // 支付模式,枚举值:short_series_goods: 道具直购,short_series_coin: 代币充值
|
||||||
|
PaySig string `json:"pay_sig"` // 支付签名,具体生成方式见下方说明
|
||||||
|
Signature string `json:"signature"` // 用户态签名,具体生成方式见下方说明
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignData 签名数据
|
||||||
|
type SignData struct {
|
||||||
|
OfferID string `json:"offerId"` // 在米大师侧申请的应用 id, mp-支付基础配置中的 offerid
|
||||||
|
BuyQuantity int `json:"buyQuantity"` // 购买数量
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
CurrencyType string `json:"currencyType"` // 币种 默认值:CNY 人民币
|
||||||
|
Platform string `json:"platform,omitempty"` // 申请接入时的平台,platform 与应用 id 有关 默认值:android 安卓平台
|
||||||
|
ProductID string `json:"productId,omitempty"` // 道具 ID, **该字段仅 mode=short_series_goods 时可用**
|
||||||
|
GoodsPrice int `json:"goodsPrice"` // 道具单价 (分), **该字段仅 mode=short_series_goods 时可用**, 用来校验价格与后台道具价格是否一致,避免用户在业务商城页看到的价格与实际价格不一致导致投诉
|
||||||
|
OutTradeNo string `json:"outTradeNo"` // 业务订单号,每个订单号只能使用一次,重复使用会失败 (极端情况不保证唯一,不建议业务强依赖唯一性). 要求 8-32 个字符内,只能是数字、大小写字母、符号 _-|*@组成,不能以下划线 (_) 开头
|
||||||
|
Attach string `json:"attach"` // 透传数据,发货通知时会透传给开发者
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUserBalanceRequest 查询用户代币余额,请求参数
|
||||||
|
// 1. 需要用户态签名与支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type QueryUserBalanceRequest struct {
|
||||||
|
CommonRequest
|
||||||
|
UserIP string `json:"user_ip"` // 用户 ip,例如:1.1.1.1
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUserBalanceResponse 查询虚拟支付余额 响应参数
|
||||||
|
type QueryUserBalanceResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
Balance int `json:"balance"` // 代币总余额,包括有价和赠送部分
|
||||||
|
PresentBalance int `json:"present_balance"` // 赠送账户的代币余额
|
||||||
|
SumSave int `json:"sum_save"` // 累计有价货币充值数量
|
||||||
|
SumPresent int `json:"sum_present"` // 累计赠送无价货币数量
|
||||||
|
SumBalance int `json:"sum_balance"` // 历史总增加的代币金额
|
||||||
|
SumCost int `json:"sum_cost"` // 历史总消耗代币金额
|
||||||
|
FirstSaveFlag int `json:"first_save_flag"` // 是否满足首充活动标记。0:不满足。1:满足
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrencyPayRequest 扣减代币(一般用于代币支付)
|
||||||
|
// 1. 需要用户态签名与支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type CurrencyPayRequest struct {
|
||||||
|
CommonRequest
|
||||||
|
UserIP string `json:"user_ip"` // 用户 ip,例如:1.1.1.1
|
||||||
|
Amount int `json:"amount"` // 支付的代币数量
|
||||||
|
OrderID string `json:"order_id"` // 商户订单号,需要保证唯一性
|
||||||
|
PayItem string `json:"payitem"` // 物品信息。记录到账户流水中。如:[{"productid":"物品 id", "unit_price": 单价,"quantity": 数量}]
|
||||||
|
Remark string `json:"remark"` // 备注信息。需要在账单中展示
|
||||||
|
DeviceType string `json:"device_type"` // 平台类型 1-安卓 2-苹果
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayItem 物品信息
|
||||||
|
type PayItem struct {
|
||||||
|
ProductID string `json:"productid"` // 物品 id
|
||||||
|
UnitPrice int `json:"unit_price"` // 单价
|
||||||
|
Quantity int `json:"quantity"` // 数量
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrencyPayResponse 扣减代币(一般用于代币支付)响应参数
|
||||||
|
type CurrencyPayResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
OrderID string `json:"order_id"` // 商户订单号
|
||||||
|
Balance int `json:"balance"` // 总余额,包括有价和赠送部分
|
||||||
|
UsedPresentAmount int `json:"used_present_amount"` // 使用赠送部分的代币数量
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryOrderRequest 查询创建的订单(现金单,非代币单),请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type QueryOrderRequest struct {
|
||||||
|
CommonRequest
|
||||||
|
OrderID string `json:"order_id,omitempty"` // 商户订单号 创建的订单号
|
||||||
|
WxOrderID string `json:"wx_order_id,omitempty"` // 微信内部单号 (与 order_id 二选一)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OrderItem 订单信息
|
||||||
|
type OrderItem struct {
|
||||||
|
OrderID string `json:"order_id"` // 商户订单号
|
||||||
|
CreateTime int64 `json:"create_time"` // 订单创建时间
|
||||||
|
UpdateTime int64 `json:"update_time"` // 订单更新时间
|
||||||
|
Status OrderStatus `json:"status"` // 订单状态 当前状态 0-订单初始化(未创建成功,不可用于支付)1-订单创建成功 2-订单已经支付,待发货 3-订单发货中 4-订单已发货 5-订单已经退款 6-订单已经关闭(不可再使用)7-订单退款失败
|
||||||
|
BizType int `json:"biz_type"` // 业务类型 0-短剧
|
||||||
|
OrderFee int `json:"order_fee"` // 订单金额,单位:分
|
||||||
|
CouponFee int `json:"coupon_fee"` // 优惠金额,单位:分
|
||||||
|
PaidFee int `json:"paid_fee"` // 用户支付金额,单位:分
|
||||||
|
OrderType int `json:"order_type"` // 订单类型 0-支付单 1-退款单
|
||||||
|
RefundFee int `json:"refund_fee"` // 当类型为退款单时表示退款金额,单位分
|
||||||
|
PaidTime int64 `json:"paid_time"` // 支付/退款时间,unix秒级时间戳
|
||||||
|
ProvideTime int64 `json:"provide_time"` // 发货时间,unix 秒级时间戳
|
||||||
|
BizMeta string `json:"biz_meta"` // 业务自定义数据 订单创建时传的信息
|
||||||
|
EnvType int `json:"env_type"` // 环境类型 1-现网 2-沙箱
|
||||||
|
Token string `json:"token"` // 下单时米大师返回的 token
|
||||||
|
LeftFee int `json:"left_fee"` // 支付单类型时表示此单经过退款还剩余的金额,单位:分
|
||||||
|
WxOrderID string `json:"wx_order_id"` // 微信内部单号
|
||||||
|
ChannelOrderID string `json:"channel_order_id"` // 渠道订单号,为用户微信支付详情页面上的商户单号
|
||||||
|
WxPayOrderID string `json:"wxpay_order_id"` // 微信支付交易单号,为用户微信支付详情页面上的交易单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryOrderResponse 查询创建的订单(现金单,非代币单)响应参数
|
||||||
|
type QueryOrderResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
Order *OrderItem `json:"order"` // 订单信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelCurrencyPayRequest 取消订单(现金单,非代币单),请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type CancelCurrencyPayRequest struct {
|
||||||
|
CommonRequest
|
||||||
|
UserIP string `json:"user_ip"` // 用户 ip,例如:1.1.1.1
|
||||||
|
PayOrderID string `json:"pay_order_id"` // 支付单号 代币支付 (调用 currency_pay 接口时) 时传的 order_id
|
||||||
|
OrderID string `json:"order_id"` // 本次退款单的单号
|
||||||
|
Amount int `json:"amount"` // 退款金额
|
||||||
|
DeviceType int `json:"device_type"` // 平台类型 1-安卓 2-苹果
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelCurrencyPayResponse 取消订单(现金单,非代币单)响应参数
|
||||||
|
type CancelCurrencyPayResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
OrderID string `json:"order_id"` // 退款订单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyProvideGoodsRequest 通知发货,请求参数
|
||||||
|
// 通知已经发货完成(只能通知现金单),正常通过 xpay_goods_deliver_notify 消息推送返回成功就不需要调用这个 api 接口。这个接口用于异常情况推送不成功时手动将单改成已发货状态
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type NotifyProvideGoodsRequest struct {
|
||||||
|
OrderID string `json:"order_id,omitempty"` // 商户订单号 下单时传的单号
|
||||||
|
WxOrderID string `json:"wx_order_id,omitempty"` // 微信内部单号 (与 order_id 二选一)
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyProvideGoodsResponse 通知发货响应参数
|
||||||
|
type NotifyProvideGoodsResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
}
|
||||||
|
|
||||||
|
// PresentCurrencyRequest 赠送代币,请求参数
|
||||||
|
// 代币赠送接口,由于目前不支付按单号查赠送单的功能,所以当需要赠送的时候可以一直重试到返回 0 或者返回 268490004(重复操作)为止
|
||||||
|
// 1. 需要用户态签名与支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type PresentCurrencyRequest struct {
|
||||||
|
CommonRequest
|
||||||
|
OrderID string `json:"order_id"` // 赠送单号,商户订单号,需要保证唯一性
|
||||||
|
Amount int `json:"amount"` // 赠送的代币数量
|
||||||
|
DeviceType string `json:"device_type"` // 平台类型 1-安卓 2-苹果
|
||||||
|
}
|
||||||
|
|
||||||
|
// PresentCurrencyResponse 赠送代币响应参数
|
||||||
|
type PresentCurrencyResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
Balance int `json:"balance"` // 赠送后用户的代币余额
|
||||||
|
OrderID string `json:"order_id"` // 赠送单号
|
||||||
|
PresentBalance int `json:"present_balance"` // 用户收到的总赠送金额
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadBillRequest 下载账单,请求参数
|
||||||
|
// 用于下载小程序账单,第一次调用触发生成下载 url,可以间隔轮训来获取最终生成的下载 url。账单中金额相关字段是以分为单位。
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type DownloadBillRequest struct {
|
||||||
|
BeginDs string `json:"begin_ds"` // 账单开始日期,格式为 yyyymmdd 起始时间(如 20230801)
|
||||||
|
EndDs string `json:"end_ds"` // 账单结束日期,格式为 yyyymmdd 结束时间(如 20230801)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadBillResponse 下载账单响应参数
|
||||||
|
type DownloadBillResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
URL string `json:"url"` // 账单下载地址
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefundOrderRequest 退款,请求参数
|
||||||
|
// 对使用 jsapi 接口下的单进行退款
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type RefundOrderRequest struct {
|
||||||
|
CommonRequest
|
||||||
|
OrderID string `json:"order_id"` // 商户订单号,需要保证唯一性
|
||||||
|
WxOrderID string `json:"wx_order_id"` // 微信内部单号 (与 order_id 二选一)
|
||||||
|
RefundOrderID string `json:"refund_order_id"` // 退款单号,本次退款时需要传的单号,长度为 [8,32],字符只允许使用字母、数字、'_'、'-'
|
||||||
|
LeftFee int `json:"left_fee"` // 退款金额,单位:分 当前单剩余可退金额,单位分,可以通过调用 query_order 接口查到
|
||||||
|
RefundFee int `json:"refund_fee"` // 退款金额,单位:分 需要 (0,left_fee] 之间
|
||||||
|
BizMeta string `json:"biz_meta"` // 商家自定义数据,传入后可在 query_order 接口查询时原样返回,长度需要 [0,1024]
|
||||||
|
RefundReason string `json:"refund_reason"` // 退款原因,当前仅支持以下值 0-暂无描述 1-产品问题,影响使用或效果不佳 2-售后问题,无法满足需求 3-意愿问题,用户主动退款 4-价格问题 5:其他原因
|
||||||
|
ReqFrom string `json:"req_from"` // 退款来源,当前仅支持以下值 1-人工客服退款,即用户电话给客服,由客服发起退款流程 2-用户自己发起退款流程 3-其它
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefundOrderResponse 退款响应参数
|
||||||
|
type RefundOrderResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
RefundOrderID string `json:"refund_order_id"` // 退款单号
|
||||||
|
RefundWxOrderID string `json:"refund_wx_order_id"` // 退款单的微信侧单号
|
||||||
|
PayOrderID string `json:"pay_order_id"` // 该退款单对应的支付单单号
|
||||||
|
PayWxOrderID string `json:"pay_wx_order_id"` // 该退款单对应的支付单微信侧单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWithdrawOrderRequest 创建提现单,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type CreateWithdrawOrderRequest struct {
|
||||||
|
WithdrawNO string `json:"withdraw_no"` // 提现单单号,长度为 [8,32],字符只允许使用字母、数字、'_'、'-'
|
||||||
|
WithdrawAmount string `json:"withdraw_amount"` // 提现的金额,单位元,例如提现 1 分钱请使用 0.01
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWithdrawOrderResponse 创建提现单响应参数
|
||||||
|
type CreateWithdrawOrderResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
WithdrawNO string `json:"withdraw_no"` // 提现单单号
|
||||||
|
WxWithdrawNO string `json:"wx_withdraw_no"` // 提现单的微信侧单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryWithdrawOrderRequest 查询提现单,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type QueryWithdrawOrderRequest struct {
|
||||||
|
WithdrawNO string `json:"withdraw_no"` // 提现单单号,长度为 [8,32],字符只允许使用字母、数字、'_'、'-' (与 wx_withdraw_no 二选一)
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryWithdrawOrderResponse 查询提现单响应参数
|
||||||
|
type QueryWithdrawOrderResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
WithdrawNO string `json:"withdraw_no"` // 提现单单号
|
||||||
|
Status int `json:"status"` // 提现单的微信侧单号 1-创建成功,提现中 2-提现成功 3-提现失败
|
||||||
|
WithdrawAmount string `json:"withdraw_amount"` // 提现的金额,单位元,例如提现 1 分钱请使用 0.01
|
||||||
|
WxWithdrawNo string `json:"wx_withdraw_no"` // 提现单的微信侧单号
|
||||||
|
WithdrawSuccessTimestamp int64 `json:"withdraw_success_timestamp"` // 提现单成功的秒级时间戳,unix 秒级时间戳
|
||||||
|
CreateTime string `json:"create_time"` // 提现单创建时间
|
||||||
|
FailReason string `json:"failReason"` // 提现失败的原因
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartUploadGoodsRequest 启动批量上传道具任务,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type StartUploadGoodsRequest struct {
|
||||||
|
UploadItem []*UploadItem `json:"upload_item"` // 道具信息
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
}
|
||||||
|
|
||||||
|
// UploadItem 道具信息
|
||||||
|
type UploadItem struct {
|
||||||
|
ID string `json:"id"` // 道具 id,长度 (0,64],字符只允许使用字母、数字、'_'、'-'
|
||||||
|
Name string `json:"name"` // 道具名称,长度 (0,1024]
|
||||||
|
Price int `json:"price"` // 道具单价,单位分,需要大于 0
|
||||||
|
Remark string `json:"remark"` // 道具备注,长度 (0,1024]
|
||||||
|
ItemURL string `json:"item_url"` // 道具图片的 url 地址,当前仅支持 jpg,png 等格式
|
||||||
|
UploadStatus int `json:"upload_status,omitempty"` // 上传状态 0-上传中 1-id 已经存在 2-上传成功 3-上传失败
|
||||||
|
ErrMsg string `json:"errmsg,omitempty"` // 上传失败的原因
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartUploadGoodsResponse 启动批量上传道具任务响应参数
|
||||||
|
type StartUploadGoodsResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUploadGoodsRequest 查询批量上传道具任务,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type QueryUploadGoodsRequest struct {
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUploadGoodsResponse 查询批量上传道具任务响应参数
|
||||||
|
type QueryUploadGoodsResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
UploadItem []*UploadItem `json:"upload_item"` // 道具信息列表
|
||||||
|
Status int `json:"status"` // 任务状态 0-无任务在运行 1-任务运行中 2-上传失败或部分失败(上传任务已经完成)3-上传成功
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartPublishGoodsRequest 启动批量发布道具任务,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type StartPublishGoodsRequest struct {
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
PublishItem []*PublishItem `json:"publish_item"` // 道具信息 发布的商品列表
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublishItem 道具信息
|
||||||
|
type PublishItem struct {
|
||||||
|
ID string `json:"id"` // 道具 id,添加到开发环境时传的道具 id,长度 (0,64],字符只允许使用字母、数字、'_'、'-'
|
||||||
|
PublishStatus int `json:"publish_status,omitempty"` // 发布状态 0-上传中 1-id 已经存在 2-发布成功 3-发布失败
|
||||||
|
ErrMsg string `json:"errmsg,omitempty"` // 发布失败的原因
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartPublishGoodsResponse 启动批量发布道具任务响应参数
|
||||||
|
type StartPublishGoodsResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryPublishGoodsRequest 查询批量发布道具任务,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type QueryPublishGoodsRequest struct {
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryPublishGoodsResponse 查询批量发布道具任务响应参数
|
||||||
|
type QueryPublishGoodsResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
PublishItem []*PublishItem `json:"publish_item"` // 道具信息列表
|
||||||
|
Status int `json:"status"` // 任务状态 0-无任务在运行 1-任务运行中 2-上传失败或部分失败(上传任务已经完成)3-上传成功
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncXPayGoodsDeliverNotifyRequest 异步通知发货,请求参数
|
||||||
|
// 1. 使用支付签名
|
||||||
|
// POST,请求参数为 json 字符串,Content-Type 为 application/json
|
||||||
|
type AsyncXPayGoodsDeliverNotifyRequest struct {
|
||||||
|
ToUserName string `json:"ToUserName"` // 小程序的原始 ID
|
||||||
|
FromUserName string `json:"FromUserName"` // 发送方帐号(一个 OpenID)该事件消息的 openid,道具发货场景固定为微信官方的 openid
|
||||||
|
CreateTime int `json:"CreateTime"` // 消息发送时间(整型)
|
||||||
|
MsgType string `json:"MsgType"` // 消息类型,此时固定为:event
|
||||||
|
Event string `json:"Event"` // 事件类型,此时固定为:xpay_goods_deliver_notify
|
||||||
|
Openid string `json:"openid"` // 用户 openid
|
||||||
|
OutTradeNo string `json:"OutTradeNo"` // 业务订单号
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
WechatPayInfo *WeChatPayInfo `json:"WechatPayInfo"` // 微信支付订单信息
|
||||||
|
GoodsInfo *GoodsInfo `json:"GoodsInfo"` // 道具信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// WeChatPayInfo 微信支付信息 非微信支付渠道可能没有
|
||||||
|
type WeChatPayInfo struct {
|
||||||
|
MchOrderNo string `json:"MchOrderNo"` // 商户订单号
|
||||||
|
TransactionID string `json:"TransactionId"` // 微信支付订单号
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoodsInfo 道具参数信息
|
||||||
|
type GoodsInfo struct {
|
||||||
|
ProductID string `json:"ProductId"` // 道具 ID
|
||||||
|
Quantity int `json:"Quantity"` // 数量
|
||||||
|
OrigPrice int `json:"OrigPrice"` // 物品原始价格(单位:分)
|
||||||
|
ActualPrice int `json:"ActualPrice"` // 物品实际支付价格(单位:分)
|
||||||
|
Attach string `json:"Attach"` // 透传信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncXPayGoodsDeliverNotifyResponse 异步通知发货响应参数
|
||||||
|
type AsyncXPayGoodsDeliverNotifyResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncXPayCoinPayNotifyRequest 异步通知代币支付推送,请求参数
|
||||||
|
type AsyncXPayCoinPayNotifyRequest struct {
|
||||||
|
ToUserName string `json:"ToUserName"` // 小程序的原始 ID
|
||||||
|
FromUserName string `json:"FromUserName"` // 发送方帐号(一个 OpenID)该事件消息的 openid,道具发货场景固定为微信官方的 openid
|
||||||
|
CreateTime int `json:"CreateTime"` // 消息发送时间(整型)
|
||||||
|
MsgType string `json:"MsgType"` // 消息类型,此时固定为:event
|
||||||
|
Event string `json:"Event"` // 事件类型,此时固定为:xpay_goods_deliver_notify
|
||||||
|
Openid string `json:"openid"` // 用户 openid
|
||||||
|
OutTradeNo string `json:"OutTradeNo"` // 业务订单号
|
||||||
|
Env Env `json:"env"` // 环境 0-正式环境 1-沙箱环境
|
||||||
|
WechatPayInfo *WeChatPayInfo `json:"WechatPayInfo"` // 微信支付订单信息
|
||||||
|
CoinInfo *CoinInfo `json:"GoodsInfo"` // 道具信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// CoinInfo 代币信息
|
||||||
|
type CoinInfo struct {
|
||||||
|
Quantity int `json:"Quantity"` // 数量
|
||||||
|
OrigPrice int `json:"OrigPrice"` // 物品原始价格(单位:分)
|
||||||
|
ActualPrice int `json:"ActualPrice"` // 物品实际支付价格(单位:分)
|
||||||
|
Attach string `json:"Attach"` // 透传信息
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsyncXPayCoinPayNotifyResponse 异步通知代币支付推送响应参数
|
||||||
|
type AsyncXPayCoinPayNotifyResponse struct {
|
||||||
|
util.CommonError
|
||||||
|
}
|
||||||
|
|
||||||
|
// URLParams url parameter
|
||||||
|
type URLParams struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
AccessToken string `json:"access_token"`
|
||||||
|
PaySign string `json:"paySign"`
|
||||||
|
Signature string `json:"signature"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
}
|
||||||
558
miniprogram/virtualpayment/virtualpayment.go
Normal file
558
miniprogram/virtualpayment/virtualpayment.go
Normal file
@@ -0,0 +1,558 @@
|
|||||||
|
/*
|
||||||
|
* Copyright silenceper/wechat Author(https://silenceper.com/wechat/). All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* You can obtain one at https://github.com/silenceper/wechat.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package virtualpayment
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/silenceper/wechat/v2/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetSessionKey 设置 sessionKey
|
||||||
|
func (s *VirtualPayment) SetSessionKey(sessionKey string) {
|
||||||
|
s.sessionKey = sessionKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUserBalance 查询虚拟支付余额
|
||||||
|
func (s *VirtualPayment) QueryUserBalance(ctx context.Context, in *QueryUserBalanceRequest) (out *QueryUserBalanceResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: queryUserBalance,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "QueryUserBalance"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrencyPay currency pay 扣减代币(一般用于代币支付)
|
||||||
|
func (s *VirtualPayment) CurrencyPay(ctx context.Context, in *CurrencyPayRequest) (out *CurrencyPayResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: currencyPay,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "CurrencyPay"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryOrder 查询创建的订单(现金单,非代币单)
|
||||||
|
func (s *VirtualPayment) QueryOrder(ctx context.Context, in *QueryOrderRequest) (out *QueryOrderResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: queryOrder,
|
||||||
|
Signature: EmptyString,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "QueryOrder"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CancelCurrencyPay 取消订单 代币支付退款 (currency_pay 接口的逆操作)
|
||||||
|
func (s *VirtualPayment) CancelCurrencyPay(ctx context.Context, in *CancelCurrencyPayRequest) (out *CancelCurrencyPayResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: cancelCurrencyPay,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "CancelCurrencyPay"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotifyProvideGoods 通知发货
|
||||||
|
// 通知已经发货完成(只能通知现金单),正常通过 xpay_goods_deliver_notify 消息推送返回成功就不需要调用这个 api 接口。这个接口用于异常情况推送不成功时手动将单改成已发货状态
|
||||||
|
func (s *VirtualPayment) NotifyProvideGoods(ctx context.Context, in *NotifyProvideGoodsRequest) (out *NotifyProvideGoodsResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: notifyProvideGoods,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "NotifyProvideGoods"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// PresentCurrency 代币赠送接口,由于目前不支付按单号查赠送单的功能,所以当需要赠送的时候可以一直重试到返回 0 或者返回 268490004(重复操作)为止
|
||||||
|
func (s *VirtualPayment) PresentCurrency(ctx context.Context, in *PresentCurrencyRequest) (out *PresentCurrencyResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: presentCurrency,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "PresentCurrency"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DownloadBill 下载订单交易账单
|
||||||
|
func (s *VirtualPayment) DownloadBill(ctx context.Context, in *DownloadBillRequest) (out *DownloadBillResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: downloadBill,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "DownloadBill"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefundOrder 退款 对使用 jsapi 接口下的单进行退款
|
||||||
|
func (s *VirtualPayment) RefundOrder(ctx context.Context, in *RefundOrderRequest) (out *RefundOrderResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: refundOrder,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "RefundOrder"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateWithdrawOrder 创建提现单
|
||||||
|
func (s *VirtualPayment) CreateWithdrawOrder(ctx context.Context, in *CreateWithdrawOrderRequest) (out *CreateWithdrawOrderResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: createWithdrawOrder,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "CreateWithdrawOrder"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryWithdrawOrder 查询提现单
|
||||||
|
func (s *VirtualPayment) QueryWithdrawOrder(ctx context.Context, in *QueryWithdrawOrderRequest) (out *QueryWithdrawOrderResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: queryWithdrawOrder,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "QueryWithdrawOrder"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartUploadGoods 开始上传商品
|
||||||
|
func (s *VirtualPayment) StartUploadGoods(ctx context.Context, in *StartUploadGoodsRequest) (out *StartUploadGoodsResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: startUploadGoods,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "StartUploadGoods"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryUploadGoods 查询上传商品
|
||||||
|
func (s *VirtualPayment) QueryUploadGoods(ctx context.Context, in *QueryUploadGoodsRequest) (out *QueryUploadGoodsResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: queryUploadGoods,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "QueryUploadGoods"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartPublishGoods 开始发布商品
|
||||||
|
func (s *VirtualPayment) StartPublishGoods(ctx context.Context, in *StartPublishGoodsRequest) (out *StartPublishGoodsResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: startPublishGoods,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "StartPublishGoods"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryPublishGoods 查询发布商品
|
||||||
|
func (s *VirtualPayment) QueryPublishGoods(ctx context.Context, in *QueryPublishGoodsRequest) (out *QueryPublishGoodsResponse, err error) {
|
||||||
|
var jsonByte []byte
|
||||||
|
if jsonByte, err = json.Marshal(in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
params = URLParams{
|
||||||
|
Path: queryPublishGoods,
|
||||||
|
Content: string(jsonByte),
|
||||||
|
Signature: EmptyString,
|
||||||
|
}
|
||||||
|
address string
|
||||||
|
)
|
||||||
|
if address, err = s.requestAddress(params); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var response []byte
|
||||||
|
if response, err = util.PostJSONContext(ctx, address, in); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用通用方法返回错误
|
||||||
|
if err = util.DecodeWithError(response, out, "QueryPublishGoods"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// hmacSha256 hmac sha256
|
||||||
|
func (s *VirtualPayment) hmacSha256(key, data string) string {
|
||||||
|
h := hmac.New(sha256.New, []byte(key))
|
||||||
|
h.Write([]byte(data))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaySign pay sign
|
||||||
|
func (s *VirtualPayment) PaySign(url, data string) (string, error) {
|
||||||
|
if strings.TrimSpace(s.ctx.Config.AppKey) == "" {
|
||||||
|
return "", errors.New("appKey is empty")
|
||||||
|
}
|
||||||
|
return s.hmacSha256(s.ctx.Config.AppKey, url+"&"+data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature user signature
|
||||||
|
func (s *VirtualPayment) Signature(data string) (string, error) {
|
||||||
|
if strings.TrimSpace(s.sessionKey) == "" {
|
||||||
|
return "", errors.New("sessionKey is empty")
|
||||||
|
}
|
||||||
|
return s.hmacSha256(s.sessionKey, data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PaySignature pay sign and signature
|
||||||
|
func (s *VirtualPayment) PaySignature(url, data string) (paySign, signature string, err error) {
|
||||||
|
if paySign, err = s.PaySign(url, data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if signature, err = s.Signature(data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// requestURL .组合 URL
|
||||||
|
func (s *VirtualPayment) requestAddress(params URLParams) (url string, err error) {
|
||||||
|
switch params.Path {
|
||||||
|
case queryUserBalance:
|
||||||
|
case currencyPay:
|
||||||
|
case cancelCurrencyPay:
|
||||||
|
if params.PaySign, params.Signature, err = s.PaySignature(params.Path, params.Content); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case queryOrder:
|
||||||
|
case notifyProvideGoods:
|
||||||
|
case presentCurrency:
|
||||||
|
case downloadBill:
|
||||||
|
case refundOrder:
|
||||||
|
case createWithdrawOrder:
|
||||||
|
case queryWithdrawOrder:
|
||||||
|
case startUploadGoods:
|
||||||
|
case queryUploadGoods:
|
||||||
|
case startPublishGoods:
|
||||||
|
case queryPublishGoods:
|
||||||
|
if params.PaySign, err = s.PaySign(params.Path, params.Content); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = errors.New("path is not exist")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.AccessToken, err = s.ctx.GetAccessToken(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
url = baseSite + params.Path + "?" + accessToken + "=" + params.AccessToken
|
||||||
|
if params.PaySign != EmptyString {
|
||||||
|
url += "&" + paySignature + "=" + params.PaySign
|
||||||
|
}
|
||||||
|
if params.Signature != EmptyString {
|
||||||
|
url += "&" + signature + "=" + params.Signature
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ const (
|
|||||||
PermanentMaterialTypeImage PermanentMaterialType = "image"
|
PermanentMaterialTypeImage PermanentMaterialType = "image"
|
||||||
// PermanentMaterialTypeVideo 永久素材视频类型(video)
|
// PermanentMaterialTypeVideo 永久素材视频类型(video)
|
||||||
PermanentMaterialTypeVideo PermanentMaterialType = "video"
|
PermanentMaterialTypeVideo PermanentMaterialType = "video"
|
||||||
// PermanentMaterialTypeVoice 永久素材语音类型 (voice)
|
// PermanentMaterialTypeVoice 永久素材语音类型(voice)
|
||||||
PermanentMaterialTypeVoice PermanentMaterialType = "voice"
|
PermanentMaterialTypeVoice PermanentMaterialType = "voice"
|
||||||
// PermanentMaterialTypeNews 永久素材图文类型(news)
|
// PermanentMaterialTypeNews 永久素材图文类型(news)
|
||||||
PermanentMaterialTypeNews PermanentMaterialType = "news"
|
PermanentMaterialTypeNews PermanentMaterialType = "news"
|
||||||
@@ -278,7 +278,7 @@ type ArticleList struct {
|
|||||||
Item []ArticleListItem `json:"item"`
|
Item []ArticleListItem `json:"item"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArticleListItem 用于ArticleList的item节点
|
// ArticleListItem 用于 ArticleList 的 item 节点
|
||||||
type ArticleListItem struct {
|
type ArticleListItem struct {
|
||||||
MediaID string `json:"media_id"`
|
MediaID string `json:"media_id"`
|
||||||
Content ArticleListContent `json:"content"`
|
Content ArticleListContent `json:"content"`
|
||||||
@@ -287,14 +287,14 @@ type ArticleListItem struct {
|
|||||||
UpdateTime int64 `json:"update_time"`
|
UpdateTime int64 `json:"update_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArticleListContent 用于ArticleListItem的content节点
|
// ArticleListContent 用于 ArticleListItem 的 content 节点
|
||||||
type ArticleListContent struct {
|
type ArticleListContent struct {
|
||||||
NewsItem []Article `json:"news_item"`
|
NewsItem []Article `json:"news_item"`
|
||||||
UpdateTime int64 `json:"update_time"`
|
UpdateTime int64 `json:"update_time"`
|
||||||
CreateTime int64 `json:"create_time"`
|
CreateTime int64 `json:"create_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// reqBatchGetMaterial BatchGetMaterial请求参数
|
// reqBatchGetMaterial BatchGetMaterial 请求参数
|
||||||
type reqBatchGetMaterial struct {
|
type reqBatchGetMaterial struct {
|
||||||
Type PermanentMaterialType `json:"type"`
|
Type PermanentMaterialType `json:"type"`
|
||||||
Count int64 `json:"count"`
|
Count int64 `json:"count"`
|
||||||
@@ -337,7 +337,7 @@ type ResMaterialCount struct {
|
|||||||
NewsCount int64 `json:"news_count"` // 图文总数量
|
NewsCount int64 `json:"news_count"` // 图文总数量
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMaterialCount 获取素材总数.
|
// GetMaterialCount 获取素材总数。
|
||||||
func (material *Material) GetMaterialCount() (res ResMaterialCount, err error) {
|
func (material *Material) GetMaterialCount() (res ResMaterialCount, err error) {
|
||||||
var accessToken string
|
var accessToken string
|
||||||
accessToken, err = material.GetAccessToken()
|
accessToken, err = material.GetAccessToken()
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CommonError 微信返回的通用错误json
|
// CommonError 微信返回的通用错误 json
|
||||||
type CommonError struct {
|
type CommonError struct {
|
||||||
apiName string
|
apiName string
|
||||||
ErrCode int64 `json:"errcode"`
|
ErrCode int64 `json:"errcode"`
|
||||||
@@ -17,7 +17,7 @@ func (c *CommonError) Error() string {
|
|||||||
return fmt.Sprintf("%s Error , errcode=%d , errmsg=%s", c.apiName, c.ErrCode, c.ErrMsg)
|
return fmt.Sprintf("%s Error , errcode=%d , errmsg=%s", c.apiName, c.ErrCode, c.ErrMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCommonError 新建CommonError错误,对于无errcode和errmsg的返回也可以返回该通用错误
|
// NewCommonError 新建 CommonError 错误,对于无 errcode 和 errmsg 的返回也可以返回该通用错误
|
||||||
func NewCommonError(apiName string, code int64, msg string) *CommonError {
|
func NewCommonError(apiName string, code int64, msg string) *CommonError {
|
||||||
return &CommonError{
|
return &CommonError{
|
||||||
apiName: apiName,
|
apiName: apiName,
|
||||||
@@ -26,7 +26,7 @@ func NewCommonError(apiName string, code int64, msg string) *CommonError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeWithCommonError 将返回值按照CommonError解析
|
// DecodeWithCommonError 将返回值按照 CommonError 解析
|
||||||
func DecodeWithCommonError(response []byte, apiName string) (err error) {
|
func DecodeWithCommonError(response []byte, apiName string) (err error) {
|
||||||
var commError CommonError
|
var commError CommonError
|
||||||
err = json.Unmarshal(response, &commError)
|
err = json.Unmarshal(response, &commError)
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ func PostJSON(uri string, obj interface{}) ([]byte, error) {
|
|||||||
return PostJSONContext(context.Background(), uri, obj)
|
return PostJSONContext(context.Background(), uri, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostJSONWithRespContentType post json数据请求,且返回数据类型
|
// PostJSONWithRespContentType post json 数据请求,且返回数据类型
|
||||||
func PostJSONWithRespContentType(uri string, obj interface{}) ([]byte, string, error) {
|
func PostJSONWithRespContentType(uri string, obj interface{}) ([]byte, string, error) {
|
||||||
jsonBuf := new(bytes.Buffer)
|
jsonBuf := new(bytes.Buffer)
|
||||||
enc := json.NewEncoder(jsonBuf)
|
enc := json.NewEncoder(jsonBuf)
|
||||||
@@ -216,7 +216,7 @@ func PostXML(uri string, obj interface{}) ([]byte, error) {
|
|||||||
return io.ReadAll(response.Body)
|
return io.ReadAll(response.Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// httpWithTLS CA证书
|
// httpWithTLS CA 证书
|
||||||
func httpWithTLS(rootCa, key string) (*http.Client, error) {
|
func httpWithTLS(rootCa, key string) (*http.Client, error) {
|
||||||
var client *http.Client
|
var client *http.Client
|
||||||
certData, err := os.ReadFile(rootCa)
|
certData, err := os.ReadFile(rootCa)
|
||||||
@@ -235,7 +235,7 @@ func httpWithTLS(rootCa, key string) (*http.Client, error) {
|
|||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// pkcs12ToPem 将Pkcs12转成Pem
|
// pkcs12ToPem 将 Pkcs12 转成 Pem
|
||||||
func pkcs12ToPem(p12 []byte, password string) tls.Certificate {
|
func pkcs12ToPem(p12 []byte, password string) tls.Certificate {
|
||||||
blocks, err := pkcs12.ToPEM(p12, password)
|
blocks, err := pkcs12.ToPEM(p12, password)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|||||||
Reference in New Issue
Block a user