Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add wx v3api #439

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions body_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@ func (bm BodyMap) SetBodyMap(key string, value func(b BodyMap)) BodyMap {
return bm
}

func (bm BodyMap) SetSlice(key string, value func(b BodyMap)) BodyMap {
_bm := make(BodyMap)
value(_bm)
bm[key] = _bm
return bm
}

// 设置 FormFile
func (bm BodyMap) SetFormFile(key string, file *File) BodyMap {
bm[key] = file
Expand Down
23 changes: 21 additions & 2 deletions doc/wechat_v3.md
Original file line number Diff line number Diff line change
Expand Up @@ -343,9 +343,28 @@ wechat.V3DecryptCombineNotifyCipherText()
* 终止合作关系:`client.V3PartnershipsTerminate()`
* 查询合作关系列表:`client.V3PartnershipsList()`
* <font color='#07C160' size='4'>支付有礼</font>
* 待实现-[文档](https://pay.weixin.qq.com/docs/merchant/apis/gift-activity/activity/create-full-send-act.html)
* 创建全场满额送活动:`client.V3PayGiftActivityCreate()`
* 获取支付有礼活动列表:`client.V3PayGiftActivityList()`
* 获取活动详情:`client.V3PayGiftActivityDetail()`
* 获取活动指定商品列表:`client.V3PayGiftActivityGoods()`
* 终止活动:`client.V3PayGiftActivityTerminate()`
* 获取活动发券商户号:`client.V3PayGiftActivityMerchant()`
* 新增活动发券商户号:`client.V3PayGiftActivityMerchantAdd()`
* 删除活动发券商户号:`client.V3PayGiftActivityMerchantDelete()`
* <font color='#07C160' size='4'>电子发票</font>
* 待实现-[文档](https://pay.weixin.qq.com/docs/merchant/apis/fapiao/fapiao-card-template/create-fapiao-card-template.html)
* 创建电子发票卡券模板:`client.V3InvoiceCardTemplateCreate()`
* 配置开发选项:`client.V3InvoiceMerchantDevConfig()`
* 查询商户配置的开发选项:`client.V3InvoiceMerchantDevConfigQuery()`
* 查询电子发票:`client.V3InvoiceQuery()`
* 获取抬头填写链接:`client.V3InvoiceUserTitleUrl()`
* 获取用户填写的抬头:`client.V3InvoiceUserTitle()`
* 获取商户开票基础信息:`client.V3InvoiceMerchantBaseInfo()`
* 获取商户可开具的商品和服务税收分类编码对照表:`client.V3InvoiceMerchantTaxCodes()`
* 开具电子发票:`client.V3InvoiceCreate()`
* 冲红电子发票:`client.V3InvoiceReverse()`
* 获取发票下载信息:`client.V3InvoiceFileUrl()`
* 上传电子发票文件:`client.V3InvoiceUploadFile()`
* 将电子发票插入微信用户卡包:`client.V3InvoiceInsertCard()`
* <font color='#07C160' size='4'>分账</font>
* 请求分账:`client.V3ProfitShareOrder()`
* 查询分账结果:`client.V3ProfitShareOrderQuery()`
Expand Down
3 changes: 2 additions & 1 deletion pkg/xhttp/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ func defaultClient() *Client {
KeepAlive: 30 * time.Second,
}),
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
MaxIdleConns: 100,
MaxIdleConnsPerHost: 1000,
MaxConnsPerHost: 3000,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
Expand Down
6 changes: 5 additions & 1 deletion release_note.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
版本号:v1.5.107
修改记录:
(1) gopay:golang.org/x/crypto 版本升级到 v0.31.0。
(2) 微信V3:新增掌纹支付相关接口。
(2) gopay:xhttp transport 的默认 MaxIdleConnsPerHost 设置为 1000,MaxConnsPerHost 设置为 3000。
(3) 微信V3:新增掌纹支付相关接口。
(4) 微信V3:补充 支付有礼相关接口。
(5) 微信V3:补充 电子发票相关接口。
(6) 支付宝V3:补充 支付宝的若干v3接口。

版本号:v1.5.106
修改记录:
Expand Down
210 changes: 210 additions & 0 deletions wechat/v3/activity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
package wechat

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

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

// 创建全场满额送活动
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityCreate(ctx context.Context, bm gopay.BodyMap) (*PayGiftActivityCreateRsp, error) {
if err := bm.CheckEmptyError("activity_base_info", "award_send_rule"); err != nil {
return nil, err
}
authorization, err := c.authorization(MethodPost, v3PayGiftActivityCreate, bm)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdPost(ctx, bm, v3PayGiftActivityCreate, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityCreateRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityCreate{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 获取支付有礼活动列表
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityList(ctx context.Context, bm gopay.BodyMap) (*PayGiftActivityListRsp, error) {
uri := v3PayGiftActivityList + "?" + bm.EncodeURLParams()
authorization, err := c.authorization(MethodGet, uri, nil)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdGet(ctx, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityListRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityList{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 获取活动详情
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityDetail(ctx context.Context, activityId string) (*PayGiftActivityDetailRsp, error) {
uri := fmt.Sprintf(v3PayGiftActivityDetail, activityId)
authorization, err := c.authorization(MethodGet, uri, nil)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdGet(ctx, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityDetailRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityDetail{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 获取活动指定商品列表
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityGoods(ctx context.Context, activityId string, bm gopay.BodyMap) (*PayGiftActivityGoodsRsp, error) {
uri := fmt.Sprintf(v3PayGiftActivityGoods, activityId) + "?" + bm.EncodeURLParams()
authorization, err := c.authorization(MethodGet, uri, nil)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdGet(ctx, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityGoodsRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityGoods{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 终止活动
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityTerminate(ctx context.Context, activityId string) (*PayGiftActivityTerminateRsp, error) {
uri := fmt.Sprintf(v3PayGiftActivityTerminate, activityId)
authorization, err := c.authorization(MethodPost, uri, nil)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdPost(ctx, nil, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityTerminateRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityTerminate{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 获取活动发券商户号
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityMerchant(ctx context.Context, activityId string, bm gopay.BodyMap) (*PayGiftActivityMerchantRsp, error) {
uri := fmt.Sprintf(v3PayGiftActivityMerchant, activityId) + "?" + bm.EncodeURLParams()
authorization, err := c.authorization(MethodGet, uri, nil)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdGet(ctx, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityMerchantRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityMerchant{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 新增活动发券商户号
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityMerchantAdd(ctx context.Context, activityId string, bm gopay.BodyMap) (*PayGiftActivityMerchantAddRsp, error) {
if err := bm.CheckEmptyError("merchant_id_list", "add_request_no"); err != nil {
return nil, err
}
uri := fmt.Sprintf(v3PayGiftActivityMerchantAdd, activityId)
authorization, err := c.authorization(MethodPost, uri, bm)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdPost(ctx, bm, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityMerchantAddRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityMerchantAdd{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}

// 删除活动发券商户号
// Code = 0 is success
func (c *ClientV3) V3PayGiftActivityMerchantDelete(ctx context.Context, activityId string, bm gopay.BodyMap) (*PayGiftActivityMerchantDeleteRsp, error) {
if err := bm.CheckEmptyError("merchant_id_list", "delete_request_no"); err != nil {
return nil, err
}
uri := fmt.Sprintf(v3PayGiftActivityMerchantDelete, activityId)
authorization, err := c.authorization(MethodPost, uri, bm)
if err != nil {
return nil, err
}
res, si, bs, err := c.doProdPost(ctx, bm, uri, authorization)
if err != nil {
return nil, err
}
wxRsp := &PayGiftActivityMerchantDeleteRsp{Code: Success, SignInfo: si, Response: &PayGiftActivityMerchantDelete{}}
if res.StatusCode != http.StatusOK {
wxRsp.Code = res.StatusCode
wxRsp.Error = string(bs)
return wxRsp, nil
}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
return wxRsp, c.verifySyncSign(si)
}
3 changes: 1 addition & 2 deletions wechat/v3/applyment_for_sub.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ func (c *ClientV3) V3Apply4SubQueryByBusinessCode(ctx context.Context, businessC
if err != nil {
return nil, err
}
wxRsp := &Apply4SubQueryRsp{Code: Success, SignInfo: si}
wxRsp.Response = new(Apply4SubQuery)
wxRsp := &Apply4SubQueryRsp{Code: Success, SignInfo: si, Response: &Apply4SubQuery{}}
if err = json.Unmarshal(bs, wxRsp.Response); err != nil {
return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs))
}
Expand Down
10 changes: 5 additions & 5 deletions wechat/v3/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ const (
v3PartnerTransferMerchantQuery = "/v3/partner-transfer/batches/out-batch-no/%s" // out_batch_no 商家批次单号查询批次单 GET
v3PartnerTransferMerchantDetail = "/v3/partner-transfer/batches/out-batch-no/%s/details/out-detail-no/%s" // out_batch_no、out_detail_no 商家明细单号查询明细单 GET

// 余额
// 平台收付通(余额查询)
v3MerchantBalance = "/v3/merchant/fund/balance/%s" // account_type 查询账户实时余额 GET
v3MerchantDayBalance = "/v3/merchant/fund/dayendbalance/%s" // account_type 查询账户日终余额 GET
v3EcommerceBalance = "/v3/ecommerce/fund/balance/%s" // sub_mchid 查询特约商户账户实时余额 GET
Expand All @@ -266,12 +266,12 @@ const (
v3Apply4SubQuerySettlement = "/v3/apply4sub/sub_merchants/%s/settlement" // sub_mchid 查询结算账户 GET
v3Apply4SubMerchantsApplication = "/v3/apply4sub/sub_merchants/%s/application/%s" // sub_mchid、application_no 查询结算账户修改申请状态

// 电商收付通(商户进件)
// 平台收付通(商户进件)
v3EcommerceApply = "/v3/ecommerce/applyments/" // 二级商户进件 POST
v3EcommerceApplyQueryById = "/v3/ecommerce/applyments/%d" // applyment_id 通过申请单ID查询申请状态 GET
v3EcommerceApplyQueryByNo = "/v3/ecommerce/applyments/out-request-no/%s" // out_request_no 通过业务申请编号查询申请状态 GET

// 电商收付通(分账)
// 平台收付通(分账)
v3EcommerceProfitShare = "/v3/ecommerce/profitsharing/orders" // 请求分账 POST
v3EcommerceProfitShareQuery = "/v3/ecommerce/profitsharing/orders" // 查询分账结果 GET
v3EcommerceProfitShareReturn = "/v3/ecommerce/profitsharing/returnorders" // 请求分账回退 POST
Expand All @@ -281,12 +281,12 @@ const (
v3EcommerceProfitShareAddReceiver = "/v3/ecommerce/profitsharing/receivers/add" // 添加分账接收方 POST
v3EcommerceProfitShareDeleteReceiver = "/v3/ecommerce/profitsharing/receivers/delete" // 删除分账接收方 POST

// 电商收付通(补差)
// 平台收付通(补差)
v3EcommerceSubsidies = "/v3/ecommerce/subsidies/create" // 请求补差 POST
v3EcommerceSubsidiesReturn = "/v3/ecommerce/subsidies/return" // 请求补差回退 POST
v3EcommerceSubsidiesCancel = "/v3/ecommerce/subsidies/cancel" // 取消补差 POST

// 电商收付通(退款)
// 平台收付通(退款)
v3CommerceRefund = "/v3/ecommerce/refunds/apply" // 申请退款 POST
v3CommerceRefundQueryById = "/v3/ecommerce/refunds/id/%s" // refund_id 通过微信支付退款单号查询退款 GET
v3CommerceRefundQueryByNo = "/v3/ecommerce/refunds/out-refund-no/%s" // out_refund_no 通过商户退款单号查询退款 GET
Expand Down
Loading
Loading