feat(work): 新增收银台收款工具相关接口

This commit is contained in:
Fu Diwei
2025-09-16 20:30:22 +08:00
parent 8db3a17f64
commit 2c9a54d2b1
30 changed files with 1970 additions and 12 deletions

View File

@@ -0,0 +1,6 @@
{
"start_time": 1680000000,
"end_time": 1680003600,
"cursor": "CURSOR",
"limit": 50
}

View File

@@ -0,0 +1,29 @@
{
"errcode": 0,
"errmsg": "ok",
"has_more": 1,
"next_cursor": "CURSOR",
"invoice_list": [
{
"order_id": "ORDERID",
"custom_corpid": "wwxx",
"apply_time": 1680000000,
"invoice_type": 0,
"paid_price": 9000,
"invoice_status": 1,
"invoice_title": "发票抬头",
"tax_number": "TAXPAYERID",
"send_way": 1,
"contact_name": "张三",
"contact_tel": "12345678901",
"contact_addr": "广东省|广州市|海珠区",
"contact_postcode": "200240",
"receive_email": "jack@qq.com",
"company_addr": "广东省广州市海珠区媒体港",
"company_tel": "187XXXXXXXX",
"bank_name": "中国邮政储蓄银行股份有限公司广州市天河支行",
"bank_account_number": "17631364174811341",
"invoice_note": "开票备注"
}
]
}

View File

@@ -0,0 +1,6 @@
{
"order_id": "ORDERID",
"oper_userid": "USERID",
"invoice_status": 1,
"invoice_note": "NOTE"
}

View File

@@ -0,0 +1,6 @@
{
"order_id": "T0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,6 @@
{
"order_id": "T0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,67 @@
{
"errcode": 0,
"errmsg": "ok",
"pay_order": {
"order_id": "ORDERID",
"create_time": 1671161338,
"custom_corpid": "ww0***********7e21",
"buy_content": "BUYCONTENT",
"origin_price": 10000,
"paid_price": 9000,
"order_status": 2,
"order_from": 1,
"creator": "CREATOR",
"pay_type": 1,
"custom_corp_name": "测试企业",
"pay_channel": 1,
"channel_order_id": "4200001711202212169932901772",
"paid_time": 1671161378,
"business_type": 2,
"income_type": 1,
"income_time": 1672111778,
"income_amount": 2,
"product_list": {
"third_app": {
"order_type": 0,
"buy_info_list": [
{
"suiteid": "SUITEID",
"appid": 1,
"edition_id": "版本名字",
"user_count": 10,
"duration_days": 365,
"origin_price": 10000,
"paid_price": 9000,
"take_effect_date": "20221220"
}
]
},
"customized_app": {
"order_type": 2,
"buy_info_list": [
{
"suiteid": "SUITEID",
"user_count": 10,
"duration_days": 365,
"origin_price": 10000,
"paid_price": 9000,
"take_effect_date": "20221220"
}
]
},
"promotion_case": {
"order_type": 0,
"case_id": "CASEID",
"promotion_edition_name": "版本名字",
"buy_info_list": [
{
"suiteid": "SUITEID",
"appid": 1,
"user_count": 10,
"take_effect_date": "20221220"
}
]
}
}
}
}

View File

@@ -0,0 +1,10 @@
{
"business_type": 1,
"start_time": 1670643437,
"end_time": 1671507437,
"cursor": "tJzlB9tdqfh-g7i_J-ehOz_TWcd7dSKa39_AqCIeMFw",
"limit": 0,
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,20 @@
{
"errcode": 0,
"errmsg": "ok",
"next_cursor": "5f0uN2RNNsR8Dj0G08XUSg==",
"has_more": 1,
"pay_order_list": [
{
"order_id": "ORDERID",
"create_time": 1672220217,
"custom_corpid": "wx9***********65f9",
"buy_content": "BUYCONTENT",
"origin_price": 1000,
"paid_price": 9000,
"order_status": 1,
"order_from": 1,
"creator": "CREATOR",
"pay_type": 2
}
]
}

View File

@@ -0,0 +1,78 @@
{
"business_type": 1,
"custom_corpid": "wx979abee1572365f9",
"pay_type": 1,
"bank_receipt_media_id": "MEDIA_ID_XXX",
"creator": "CREATOR",
"product_list": {
"third_app": {
"order_type": 0,
"buy_info_list": [
{
"suiteid": "wx63bea8582b858ee7",
"appid": 1,
"edition_id": "sp7fd5170a8e807a44",
"duration_days": 1,
"take_effect_date": "20221220",
"user_count": 10,
"discount_info": {
"discount_type": 2,
"discount_amount": 0,
"discount_ratio": 75,
"discount_remarks": "老客户优惠"
}
},
{
"suiteid": "wx46b0217691d307f7",
"appid": 1,
"edition_id": "spb5625fc505870d09",
"duration_days": 1,
"user_count": 10
}
],
"notify_custom_corp": 1
},
"customized_app": {
"order_type": 0,
"buy_info_list": [
{
"suiteid": "dk6e2ed1be411f395a",
"duration_days": 30,
"take_effect_date": "20221220",
"user_count": 10,
"total_price": 250000
},
{
"suiteid": "dk9b5e63db2d5d98a0",
"duration_days": 10,
"take_effect_date": "20221220",
"user_count": 20,
"total_price": 2500
}
],
"notify_custom_corp": 1
},
"promotion_case": {
"order_type": 0,
"case_id": "slne7508097f40c4f8e",
"promotion_edition_name": "固定单价",
"duration_days": 30,
"take_effect_date": "20221230",
"buy_info_list": [
{
"suiteid": "wx8838a73b0f57a7b5",
"appid": 2,
"user_count": 10
},
{
"suiteid": "wx15ab15f7b1ced876",
"user_count": 20
}
],
"notify_custom_corp": 1
}
},
"nonce_str": "129031823",
"ts": 1548302135,
"sig": "mPOwVW/vQ74xN+b+Yu1KMa9RrmhKJaJjAtXHTof+EpU="
}

View File

@@ -0,0 +1,8 @@
{
"errcode": 0,
"errmsg": "ok",
"order_id": "N00000F24364063FC57FACFC5C6A0",
"order_url": "https://open.work.weixin.qq.com/payforapp/PREORDERT0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
"origin_price": 1000,
"paid_price": 900
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using Xunit;

View File

@@ -0,0 +1,121 @@
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Xunit;
namespace SKIT.FlurlHttpClient.Wechat.Work.UnitTests
{
public partial class TestCase_RequestSigningTests
{
[Fact(DisplayName = "测试用例:收银台收款工具接口请求签名")]
public async Task TestPayToolRequestSignature()
{
var httpClient = new HttpClient(new MockHttpMessageHandler(new HttpClientHandler()));
var mockClient = new WechatWorkClient(new WechatWorkClientOptions()
{
PayToolApiSecret = "at23pxnPBNQY3JiA8N5U1gabiQqxZwqH_Gihg7a_wrULmlOPVP-iiRjv9JWYPrDk"
}, new MockHttpClient());
// 简单数据结构
{
var request = new Models.CgibinPayToolCloseOrderRequest()
{
OrderId = "T0Rkc2g3dWlQNzFLNTRXMDJBV25BNi95OVZZbjBPOE11N2FCWkc0STJRdz0=",
NonceString = "129031823",
Timestamp = 1548302135
};
_ = await mockClient.ExecuteCgibinPayToolCloseOrderAsync(request);
Assert.Equal("jzjAGcoLbquKfNVlpqzBJDSdUASP8J7PebdFB6CUnRg=", request.Signature);
}
// 复杂数据结构
{
var request = new Models.CgibinPayToolOpenOrderRequest()
{
BusinessType = 1,
CustomCorpId = "wx979abee1572365f9",
PayType = 1,
BandReceiptMediaId = "MEDIA_ID_XXX",
CreatorUserId = "CREATOR",
Product = new Models.CgibinPayToolOpenOrderRequest.Types.Product()
{
ThirdPartyApp = new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp()
{
OrderType = 0,
BuyInfoList = new List<Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo>()
{
new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo()
{
SuiteId = "wx63bea8582b858ee7",
AppId = 1,
EditionId = "sp7fd5170a8e807a44",
DurationDays = 1,
TakeEffectDateString = "20221220",
UserCount = 10,
DiscountInfo = new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo.Types.DiscountInfo()
{
DiscountType = 2,
DiscountAmount = 0,
DiscountRatio = 75,
DiscountRemarks = "老客户优惠"
}
},
new Models.CgibinPayToolOpenOrderRequest.Types.Product.Types.ThirdPartyApp.Types.BuyInfo()
{
SuiteId = "wx46b0217691d307f7",
AppId = 1,
EditionId = "spb5625fc505870d09",
DurationDays = 1,
UserCount = 10,
}
},
IsNotifyCustomCorp = true
}
},
NonceString = "129031823",
Timestamp = 1548302135
};
_ = await mockClient.ExecuteCgibinPayToolOpenOrderAsync(request);
Assert.Equal("5c6ZV2YFUWSA+2t4i92wUi4INQPYj3m6DArzLXkwxxk=", request.Signature);
}
}
}
partial class TestCase_RequestSigningTests
{
public class MockHttpClient : HttpClient
{
public MockHttpClient()
: base(new MockHttpMessageHandler(new HttpClientHandler()))
{
}
}
public class MockHttpMessageHandler : DelegatingHandler
{
public MockHttpMessageHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
string mockResponseContent = "{\"errcode\":0}";
byte[] mockResponseBytes = Encoding.UTF8.GetBytes(mockResponseContent);
var resp = new HttpResponseMessage
{
RequestMessage = request,
StatusCode = HttpStatusCode.NoContent,
Content = new ByteArrayContent(mockResponseBytes),
};
resp.Headers.TryAddWithoutValidation("Content-Length", mockResponseBytes.Length.ToString());
return Task.FromResult(resp);
}
}
}
}