You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#region Apache License Version 2.0
/*----------------------------------------------------------------
Copyright 2022 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.
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.
Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md
----------------------------------------------------------------*/
#endregion Apache License Version 2.0
/*----------------------------------------------------------------
Copyright (C) 2023 Senparc
文件名ProfitsharingApis.cs
文件功能描述微信支付V3分账接口
创建标识Senparc - 20210920
修改标识Senparc - 20220511
修改描述v0.6.2.1 修复 CreateProfitsharingAsync 接口路径问题
----------------------------------------------------------------*/
using Senparc.CO2NET.Extensions;
using Senparc.CO2NET.Helpers;
using Senparc.CO2NET.Trace;
using Senparc.Weixin.Entities;
using Senparc.Weixin.TenPayV3.Apis.Entities;
using Senparc.Weixin.TenPayV3.Apis.Profitsharing;
using Senparc.Weixin.TenPayV3.Entities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Senparc.Weixin.TenPayV3.Apis
{
/// <summary>
/// 微信支付V3分账接口
/// https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_1.shtml 下的【分账】所有接口
/// </summary>
public class ProfitsharingApis
{
private ISenparcWeixinSettingForTenpayV3 _tenpayV3Setting;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="senparcWeixinSettingForTenpayV3"></param>
public ProfitsharingApis(ISenparcWeixinSettingForTenpayV3 senparcWeixinSettingForTenpayV3 = null)
{
_tenpayV3Setting = senparcWeixinSettingForTenpayV3 ?? Senparc.Weixin.Config.SenparcWeixinSetting.TenpayV3Setting;
}
/// <summary>
/// 返回可用的微信支付地址(自动判断是否使用沙箱)
/// </summary>
/// <param name="urlFormat">如:<code>https://api.mch.weixin.qq.com/{0}pay/unifiedorder</code></param>
/// <returns></returns>
// TODO: 重复使用
private static string ReurnPayApiUrl(string urlFormat)
{
return string.Format(urlFormat, Senparc.Weixin.Config.UseSandBoxPay ? "sandboxnew/" : "");
}
#region 分账接口
/// <summary>
/// 请求分账接口
/// <para>微信订单支付成功后,商户发起分账请求,将结算后的资金分到分账接收方</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_1.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间单位为ms</param>
/// <returns></returns>
public async Task<CreateProfitsharingReturnJson> CreateProfitsharingAsync(CreateProfitsharingRequestData data, int timeOut = Config.TIME_OUT)
{
foreach(var each in data.receivers)
{
if (each.type == "MERCHANT_ID" && each.name == null)
{
throw new TenpayApiRequestException($"当 {nameof(each.type)} 为 {each.type} 时,{nameof(each.name)} 必填!");
}
}
// TODO: name 敏感信息加密
var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/profitsharing/orders");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<CreateProfitsharingReturnJson>(url, data, timeOut);
}
/// <summary>
/// 查询分账结果接口
/// <para>发起分账请求后,可调用此接口查询分账结果。</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_7_2.shtml </para>
/// </summary>
/// <param name="transaction_id">微信支付订单号</param>
/// <param name="out_order_no">商户系统内部的分账单号,在商户系统内部唯一</param>
/// <param name="timeOut">超时时间单位为ms </param>
/// <returns></returns>
public async Task<QueryProfitsharingReturnJson> QueryProfitsharingAsync(string transaction_id, string out_order_no, int timeOut = Config.TIME_OUT)
{
var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/profitsharing/orders/{out_order_no}?&transaction_id={transaction_id}");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<QueryProfitsharingReturnJson>(url, null, timeOut, ApiRequestMethod.GET);
}
/// <summary>
/// 请求分账回退接口
/// <para>如果订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款。/para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_3.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间单位为ms </param>
/// <returns></returns>
public async Task<ReturnProfitsharingReturnJson> ReturnProfitsharingAsync(ReturnProfitsharingRequestData data, int timeOut = Config.TIME_OUT)
{
var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/profitsharing/return-orders");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<ReturnProfitsharingReturnJson>(url, data, timeOut);
}
/// <summary>
/// 查询分账回退结果接口
/// <para>商户需要核实回退结果,可调用此接口查询回退结果。</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_4.shtml </para>
/// </summary>
/// <param name="out_return_no">调用回退接口提供的商户系统内部的回退单号</param>
/// <param name="out_order_no">商户系统内部的分账单号,在商户系统内部唯一</param>
/// <param name="timeOut">超时时间单位为ms </param>
/// <returns></returns>
public async Task<QueryReturnProfitsharingReturnJson> QueryReturnProfitsharingAsync(string out_return_no, string out_order_no, int timeOut = Config.TIME_OUT)
{
var url = ReurnPayApiUrl($"{Senparc.Weixin.Config.TenPayV3Host}/{{0}}v3/profitsharing/return-orders/{out_return_no}?&out_order_no={out_return_no}");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<QueryReturnProfitsharingReturnJson>(url, null, timeOut, ApiRequestMethod.GET);
}
/// <summary>
/// 解冻剩余资金接口
/// <para>不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给特约商户</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_5.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间单位为ms </param>
/// <returns></returns>
public async Task<UnfreezeProfitsharingReturnJson> UnfreezeProfitsharingAsync(UnfreezeProfitsharingRequestData data, int timeOut = Config.TIME_OUT)
{
var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/profitsharing/orders/unfreeze");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<UnfreezeProfitsharingReturnJson>(url, data, timeOut);
}
/// <summary>
/// 查询剩余待分金额接口
/// <para>可调用此接口查询订单剩余待分金额。</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_6.shtml </para>
/// </summary>
/// <param name="transaction_id">微信支付订单号</param>
/// <param name="timeOut">超时时间单位为ms</param>
/// <returns></returns>
public async Task<QueryProfitsharingAmountsReturnJson> QueryProfitsharingAmountsAsync(string transaction_id, int timeOut = Config.TIME_OUT)
{
var url = ReurnPayApiUrl($"{Senparc.Weixin.Config.TenPayV3Host}/{{0}}v3/profitsharing/transactions/{transaction_id}/amounts");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<QueryProfitsharingAmountsReturnJson>(url, null, timeOut, ApiRequestMethod.GET);
}
/// <summary>
/// 添加分账接收方接口
/// <para>商户发起添加分账接收方请求,建立分账接收方列表。后续可通过发起分账请求,将分账方商户结算后的资金,分到该分账接收方</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_8.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间单位为ms </param>
/// <returns></returns>
public async Task<AddProfitsharingReceiverReturnJson> AddProfitsharingReceiverAsync(AddProfitsharingReceiverRequestData data, int timeOut = Config.TIME_OUT)
{
// TODO: name 敏感信息加密
if (data.type == "MERCHANT_ID" && data.name == null)
{
throw new TenpayApiRequestException($"当 {nameof(data.type)} 为 {data.type} 时,{nameof(data.name)} 必填!");
}
var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/profitsharing/receivers/add");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<AddProfitsharingReceiverReturnJson>(url, data, timeOut);
}
/// <summary>
/// 删除分账接收方接口
/// <para>商户发起删除分账接收方请求。删除后,不支持将分账方商户结算后的资金,分到该分账接收方</para>
/// <para>更多详细请参考 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_9.shtml </para>
/// </summary>
/// <param name="data">微信支付需要POST的Data数据</param>
/// <param name="timeOut">超时时间单位为ms </param>
/// <returns></returns>
public async Task<DeleteProfitsharingReceiverReturnJson> DeleteProfitsharingAsync(DeleteProfitsharingReceiverRequestData data, int timeOut = Config.TIME_OUT)
{
var url = ReurnPayApiUrl(Senparc.Weixin.Config.TenPayV3Host + "/{0}v3/profitsharing/receivers/delete");
TenPayApiRequest tenPayApiRequest = new(_tenpayV3Setting);
return await tenPayApiRequest.RequestAsync<DeleteProfitsharingReceiverReturnJson>(url, data, timeOut);
}
#endregion
}
}