Skip to content

Commit

Permalink
Feature/add wx v3api (#439)
Browse files Browse the repository at this point in the history
* add new api
  • Loading branch information
iGoogle-ink authored Dec 20, 2024
1 parent f199fb6 commit def59a1
Show file tree
Hide file tree
Showing 11 changed files with 1,042 additions and 20 deletions.
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

0 comments on commit def59a1

Please sign in to comment.