feat: 实现微信小程序发货信息录入功能
- IWechatService 添加 UploadShippingInfoAsync 接口 - WechatService 实现调用微信 upload_shipping_info API - PaymentNotifyService 支付成功后自动调用发货接口 - 发货失败时保存到 Redis 等待重试(3天过期) - 添加 WechatShippingRequest/WechatShippingResult 模型
This commit is contained in:
parent
113247a1e3
commit
27613ab5b2
|
|
@ -30,10 +30,6 @@
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="" style="width: 100%; margin: 44rpx 32rpx;">
|
|
||||||
<image :src="$img1('my/ic_alipay.png')" style="width: 320rpx; height: 96rpx;" mode=""></image>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="center"
|
<view class="center"
|
||||||
style="width: 686rpx; height: 92rpx; margin: 46rpx auto 0; background-color: #333333; border-radius: 16rpx;"
|
style="width: 686rpx; height: 92rpx; margin: 46rpx auto 0; background-color: #333333; border-radius: 16rpx;"
|
||||||
@click="pay" :class="{ 'btn-active': isPaying }">
|
@click="pay" :class="{ 'btn-active': isPaying }">
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,14 @@ public interface IWechatService
|
||||||
/// <param name="width">二维码宽度,默认430</param>
|
/// <param name="width">二维码宽度,默认430</param>
|
||||||
/// <returns>小程序码图片字节数组,失败返回null</returns>
|
/// <returns>小程序码图片字节数组,失败返回null</returns>
|
||||||
Task<byte[]?> GetWxaCodeUnlimitAsync(string scene, string? page = null, int width = 430);
|
Task<byte[]?> GetWxaCodeUnlimitAsync(string scene, string? page = null, int width = 430);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传微信小程序发货信息
|
||||||
|
/// 调用微信API upload_shipping_info 将订单标记为已发货
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request">发货信息请求</param>
|
||||||
|
/// <returns>发货结果</returns>
|
||||||
|
Task<WechatShippingResult> UploadShippingInfoAsync(WechatShippingRequest request);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System.Text.Json;
|
||||||
using HoneyBox.Core.Interfaces;
|
using HoneyBox.Core.Interfaces;
|
||||||
using HoneyBox.Model.Data;
|
using HoneyBox.Model.Data;
|
||||||
using HoneyBox.Model.Entities;
|
using HoneyBox.Model.Entities;
|
||||||
|
using HoneyBox.Model.Models.Auth;
|
||||||
using HoneyBox.Model.Models.Lottery;
|
using HoneyBox.Model.Models.Lottery;
|
||||||
using HoneyBox.Model.Models.Mall;
|
using HoneyBox.Model.Models.Mall;
|
||||||
using HoneyBox.Model.Models.Payment;
|
using HoneyBox.Model.Models.Payment;
|
||||||
|
|
@ -21,6 +22,8 @@ public class PaymentNotifyService : IPaymentNotifyService
|
||||||
private readonly IWechatPayConfigService _wechatPayConfigService;
|
private readonly IWechatPayConfigService _wechatPayConfigService;
|
||||||
private readonly IPaymentService _paymentService;
|
private readonly IPaymentService _paymentService;
|
||||||
private readonly ILotteryEngine _lotteryEngine;
|
private readonly ILotteryEngine _lotteryEngine;
|
||||||
|
private readonly IWechatService _wechatService;
|
||||||
|
private readonly IRedisService _redisService;
|
||||||
private readonly ILogger<PaymentNotifyService> _logger;
|
private readonly ILogger<PaymentNotifyService> _logger;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -51,6 +54,8 @@ public class PaymentNotifyService : IPaymentNotifyService
|
||||||
IWechatPayConfigService wechatPayConfigService,
|
IWechatPayConfigService wechatPayConfigService,
|
||||||
IPaymentService paymentService,
|
IPaymentService paymentService,
|
||||||
ILotteryEngine lotteryEngine,
|
ILotteryEngine lotteryEngine,
|
||||||
|
IWechatService wechatService,
|
||||||
|
IRedisService redisService,
|
||||||
ILogger<PaymentNotifyService> logger)
|
ILogger<PaymentNotifyService> logger)
|
||||||
{
|
{
|
||||||
_dbContext = dbContext;
|
_dbContext = dbContext;
|
||||||
|
|
@ -59,6 +64,8 @@ public class PaymentNotifyService : IPaymentNotifyService
|
||||||
_wechatPayConfigService = wechatPayConfigService;
|
_wechatPayConfigService = wechatPayConfigService;
|
||||||
_paymentService = paymentService;
|
_paymentService = paymentService;
|
||||||
_lotteryEngine = lotteryEngine;
|
_lotteryEngine = lotteryEngine;
|
||||||
|
_wechatService = wechatService;
|
||||||
|
_redisService = redisService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,22 +425,24 @@ public class PaymentNotifyService : IPaymentNotifyService
|
||||||
// 记录支付流水
|
// 记录支付流水
|
||||||
await RecordPaymentAsync(user.Id, orderNo, notifyData.TotalFee / 100m, attach);
|
await RecordPaymentAsync(user.Id, orderNo, notifyData.TotalFee / 100m, attach);
|
||||||
|
|
||||||
|
bool processResult;
|
||||||
|
|
||||||
// 根据attach类型路由处理
|
// 根据attach类型路由处理
|
||||||
// attach格式: order_{type} 或 infinite_{type} 或固定字符串
|
// attach格式: order_{type} 或 infinite_{type} 或固定字符串
|
||||||
if (attach == OrderAttachType.UserRecharge)
|
if (attach == OrderAttachType.UserRecharge)
|
||||||
{
|
{
|
||||||
// 余额充值
|
// 余额充值
|
||||||
return await ProcessRechargeOrderAsync(orderNo);
|
processResult = await ProcessRechargeOrderAsync(orderNo);
|
||||||
}
|
}
|
||||||
else if (attach == OrderAttachType.OrderListSend)
|
else if (attach == OrderAttachType.OrderListSend)
|
||||||
{
|
{
|
||||||
// 发货运费订单
|
// 发货运费订单
|
||||||
return await ProcessShippingFeeOrderAsync(orderNo);
|
processResult = await ProcessShippingFeeOrderAsync(orderNo);
|
||||||
}
|
}
|
||||||
else if (attach == OrderAttachType.OrderProduct)
|
else if (attach == OrderAttachType.OrderProduct)
|
||||||
{
|
{
|
||||||
// 钻石商品订单
|
// 钻石商品订单
|
||||||
return await ProcessDiamondOrderAsync(orderNo, user.Id);
|
processResult = await ProcessDiamondOrderAsync(orderNo, user.Id);
|
||||||
}
|
}
|
||||||
else if (attach.StartsWith("order_"))
|
else if (attach.StartsWith("order_"))
|
||||||
{
|
{
|
||||||
|
|
@ -445,39 +454,53 @@ public class PaymentNotifyService : IPaymentNotifyService
|
||||||
// 类型 4 是抽卡机
|
// 类型 4 是抽卡机
|
||||||
if (orderType == 4)
|
if (orderType == 4)
|
||||||
{
|
{
|
||||||
return await ProcessCardExtractorOrderByOrderNoAsync(orderNo);
|
processResult = await ProcessCardExtractorOrderByOrderNoAsync(orderNo);
|
||||||
}
|
}
|
||||||
// 其他类型按一番赏处理
|
else
|
||||||
return await ProcessLotteryOrderByOrderNoAsync(orderNo);
|
|
||||||
}
|
|
||||||
// 如果不是数字格式,尝试匹配旧格式
|
|
||||||
if (LotteryOrderTypes.Contains(attach))
|
|
||||||
{
|
{
|
||||||
return await ProcessLotteryOrderByOrderNoAsync(orderNo);
|
// 其他类型按一番赏处理
|
||||||
|
processResult = await ProcessLotteryOrderByOrderNoAsync(orderNo);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else if (LotteryOrderTypes.Contains(attach))
|
||||||
|
{
|
||||||
|
// 如果不是数字格式,尝试匹配旧格式
|
||||||
|
processResult = await ProcessLotteryOrderByOrderNoAsync(orderNo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_logger.LogWarning("未知的order_类型: Attach={Attach}, OrderNo={OrderNo}", attach, orderNo);
|
_logger.LogWarning("未知的order_类型: Attach={Attach}, OrderNo={OrderNo}", attach, orderNo);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (attach.StartsWith("infinite_"))
|
else if (attach.StartsWith("infinite_"))
|
||||||
{
|
{
|
||||||
// 无限赏类订单 (infinite_2, infinite_7, infinite_8, infinite_9 等)
|
// 无限赏类订单 (infinite_2, infinite_7, infinite_8, infinite_9 等)
|
||||||
return await ProcessInfiniteOrderByOrderNoAsync(orderNo);
|
processResult = await ProcessInfiniteOrderByOrderNoAsync(orderNo);
|
||||||
}
|
}
|
||||||
else if (LotteryOrderTypes.Contains(attach))
|
else if (LotteryOrderTypes.Contains(attach))
|
||||||
{
|
{
|
||||||
// 兼容旧格式 order_yfs, order_lts 等
|
// 兼容旧格式 order_yfs, order_lts 等
|
||||||
return await ProcessLotteryOrderByOrderNoAsync(orderNo);
|
processResult = await ProcessLotteryOrderByOrderNoAsync(orderNo);
|
||||||
}
|
}
|
||||||
else if (InfiniteOrderTypes.Contains(attach))
|
else if (InfiniteOrderTypes.Contains(attach))
|
||||||
{
|
{
|
||||||
// 兼容旧格式 order_wxs, order_fbs 等
|
// 兼容旧格式 order_wxs, order_fbs 等
|
||||||
return await ProcessInfiniteOrderByOrderNoAsync(orderNo);
|
processResult = await ProcessInfiniteOrderByOrderNoAsync(orderNo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_logger.LogWarning("未知的订单类型: Attach={Attach}, OrderNo={OrderNo}", attach, orderNo);
|
_logger.LogWarning("未知的订单类型: Attach={Attach}, OrderNo={OrderNo}", attach, orderNo);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理成功后,调用微信发货接口
|
||||||
|
if (processResult && !string.IsNullOrEmpty(notifyData.OpenId))
|
||||||
|
{
|
||||||
|
await UploadWechatShippingInfoAsync(notifyData.OpenId, orderNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return processResult;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -1407,5 +1430,76 @@ public class PaymentNotifyService : IPaymentNotifyService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传微信发货信息
|
||||||
|
/// 支付成功后调用微信接口将订单标记为已发货
|
||||||
|
/// </summary>
|
||||||
|
private async Task UploadWechatShippingInfoAsync(string openId, string orderNo)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new WechatShippingRequest
|
||||||
|
{
|
||||||
|
OpenId = openId,
|
||||||
|
OrderNo = orderNo
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = await _wechatService.UploadShippingInfoAsync(request);
|
||||||
|
|
||||||
|
if (result.Success)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("微信发货成功: OrderNo={OrderNo}", orderNo);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("微信发货失败: OrderNo={OrderNo}, ErrCode={ErrCode}, ErrMsg={ErrMsg}",
|
||||||
|
orderNo, result.ErrorCode, result.ErrorMessage);
|
||||||
|
|
||||||
|
// 发货失败,存入Redis等待重试
|
||||||
|
if (result.NeedRetry)
|
||||||
|
{
|
||||||
|
await SaveShippingRetryInfoAsync(openId, orderNo, result.ErrorCode, result.ErrorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "调用微信发货接口异常: OrderNo={OrderNo}", orderNo);
|
||||||
|
// 异常情况也存入Redis等待重试
|
||||||
|
await SaveShippingRetryInfoAsync(openId, orderNo, -1, ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存发货重试信息到Redis
|
||||||
|
/// </summary>
|
||||||
|
private async Task SaveShippingRetryInfoAsync(string openId, string orderNo, int errorCode, string? errorMessage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var key = $"post_order:{orderNo}";
|
||||||
|
var retryData = new
|
||||||
|
{
|
||||||
|
openid = openId,
|
||||||
|
order_num = orderNo,
|
||||||
|
error_code = errorCode,
|
||||||
|
error_msg = errorMessage ?? "unknown",
|
||||||
|
retry_count = 0,
|
||||||
|
last_retry_time = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
|
||||||
|
create_time = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonSerializer.Serialize(retryData);
|
||||||
|
// 设置过期时间为3天
|
||||||
|
await _redisService.SetStringAsync(key, json, TimeSpan.FromDays(3));
|
||||||
|
|
||||||
|
_logger.LogInformation("发货重试信息已保存到Redis: OrderNo={OrderNo}, Key={Key}", orderNo, key);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "保存发货重试信息失败: OrderNo={OrderNo}", orderNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -947,4 +947,201 @@ public class WechatService : IWechatService
|
||||||
var random = new Random().Next(1000, 9999);
|
var random = new Random().Next(1000, 9999);
|
||||||
return $"{prefix}{merchantPrefix}{projectPrefix}{payType}{timestamp}{random}";
|
return $"{prefix}{merchantPrefix}{projectPrefix}{payType}{timestamp}{random}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传微信小程序发货信息
|
||||||
|
/// 调用微信API upload_shipping_info 将订单标记为已发货
|
||||||
|
/// </summary>
|
||||||
|
public async Task<WechatShippingResult> UploadShippingInfoAsync(WechatShippingRequest request)
|
||||||
|
{
|
||||||
|
const string uploadShippingUrl = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info";
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 1. 参数验证
|
||||||
|
if (string.IsNullOrEmpty(request.OpenId))
|
||||||
|
{
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMessage = "OpenId不能为空"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(request.OrderNo))
|
||||||
|
{
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMessage = "订单号不能为空"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 获取商户配置(根据订单号匹配)
|
||||||
|
var merchantConfig = await GetMerchantConfigByOrderNoAsync(request.OrderNo);
|
||||||
|
if (merchantConfig == null)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("发货失败:未找到订单对应的商户配置, OrderNo={OrderNo}", request.OrderNo);
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMessage = "未找到商户配置",
|
||||||
|
NeedRetry = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var mchId = request.MchId ?? merchantConfig.MchId;
|
||||||
|
var appId = request.AppId ?? merchantConfig.AppId;
|
||||||
|
|
||||||
|
// 3. 获取access_token
|
||||||
|
var accessToken = await GetAccessTokenAsync(appId);
|
||||||
|
if (string.IsNullOrEmpty(accessToken))
|
||||||
|
{
|
||||||
|
_logger.LogWarning("发货失败:获取access_token失败, OrderNo={OrderNo}", request.OrderNo);
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMessage = "获取access_token失败",
|
||||||
|
NeedRetry = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 构建请求参数
|
||||||
|
var itemDesc = request.ItemDesc ?? GetDefaultItemDesc(request.OrderNo);
|
||||||
|
var uploadTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss") + "+08:00";
|
||||||
|
|
||||||
|
var requestBody = new
|
||||||
|
{
|
||||||
|
order_key = new
|
||||||
|
{
|
||||||
|
order_number_type = 1, // 使用商户订单号
|
||||||
|
mchid = mchId,
|
||||||
|
out_trade_no = request.OrderNo
|
||||||
|
},
|
||||||
|
logistics_type = request.LogisticsType, // 4=虚拟商品
|
||||||
|
delivery_mode = 1, // 1=统一发货
|
||||||
|
shipping_list = new[]
|
||||||
|
{
|
||||||
|
new { item_desc = itemDesc }
|
||||||
|
},
|
||||||
|
upload_time = uploadTime,
|
||||||
|
payer = new
|
||||||
|
{
|
||||||
|
openid = request.OpenId
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var jsonContent = JsonSerializer.Serialize(requestBody, new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
||||||
|
});
|
||||||
|
|
||||||
|
_logger.LogInformation("调用微信发货接口: OrderNo={OrderNo}, MchId={MchId}, OpenId={OpenId}",
|
||||||
|
request.OrderNo, mchId, request.OpenId);
|
||||||
|
|
||||||
|
// 5. 发送请求
|
||||||
|
var url = $"{uploadShippingUrl}?access_token={accessToken}";
|
||||||
|
var content = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
|
||||||
|
var response = await _httpClient.PostAsync(url, content);
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
_logger.LogDebug("微信发货接口响应: {Response}", responseContent);
|
||||||
|
|
||||||
|
// 6. 解析响应
|
||||||
|
using var jsonDoc = JsonDocument.Parse(responseContent);
|
||||||
|
var root = jsonDoc.RootElement;
|
||||||
|
|
||||||
|
var errCode = root.TryGetProperty("errcode", out var errCodeProp) ? errCodeProp.GetInt32() : -1;
|
||||||
|
var errMsg = root.TryGetProperty("errmsg", out var errMsgProp) ? errMsgProp.GetString() : "未知错误";
|
||||||
|
|
||||||
|
if (errCode == 0)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("微信发货成功: OrderNo={OrderNo}", request.OrderNo);
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
ErrorCode = 0,
|
||||||
|
ErrorMessage = "ok"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("微信发货失败: OrderNo={OrderNo}, ErrCode={ErrCode}, ErrMsg={ErrMsg}",
|
||||||
|
request.OrderNo, errCode, errMsg);
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = errCode,
|
||||||
|
ErrorMessage = errMsg,
|
||||||
|
NeedRetry = ShouldRetry(errCode)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "微信发货HTTP请求异常: OrderNo={OrderNo}", request.OrderNo);
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMessage = $"HTTP请求异常: {ex.Message}",
|
||||||
|
NeedRetry = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "微信发货异常: OrderNo={OrderNo}", request.OrderNo);
|
||||||
|
return new WechatShippingResult
|
||||||
|
{
|
||||||
|
Success = false,
|
||||||
|
ErrorCode = -1,
|
||||||
|
ErrorMessage = $"发货异常: {ex.Message}",
|
||||||
|
NeedRetry = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据订单号获取商户配置
|
||||||
|
/// </summary>
|
||||||
|
private async Task<WechatPayMerchantConfig?> GetMerchantConfigByOrderNoAsync(string orderNo)
|
||||||
|
{
|
||||||
|
// 直接使用现有的 GetMerchantConfigAsync 方法获取默认商户配置
|
||||||
|
// 该方法已经从数据库读取配置并支持缓存
|
||||||
|
return await GetMerchantConfigAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取默认商品描述
|
||||||
|
/// </summary>
|
||||||
|
private static string GetDefaultItemDesc(string orderNo)
|
||||||
|
{
|
||||||
|
// 发货订单(FH_开头)使用不同的描述
|
||||||
|
if (orderNo.StartsWith("FH_", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return "本单购买的商品正在打包,请联系客服获取物流信息";
|
||||||
|
}
|
||||||
|
return "本单购买商品已发放至[小程序盒柜]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断是否需要重试
|
||||||
|
/// </summary>
|
||||||
|
private static bool ShouldRetry(int errCode)
|
||||||
|
{
|
||||||
|
// 以下错误码可以重试
|
||||||
|
// 40001: access_token无效(可能过期)
|
||||||
|
// -1: 系统繁忙
|
||||||
|
return errCode switch
|
||||||
|
{
|
||||||
|
40001 => true, // access_token无效
|
||||||
|
-1 => true, // 系统繁忙
|
||||||
|
42001 => true, // access_token过期
|
||||||
|
_ => false
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -288,8 +288,10 @@ public class ServiceModule : Module
|
||||||
var wechatPayConfigService = c.Resolve<IWechatPayConfigService>();
|
var wechatPayConfigService = c.Resolve<IWechatPayConfigService>();
|
||||||
var paymentService = c.Resolve<IPaymentService>();
|
var paymentService = c.Resolve<IPaymentService>();
|
||||||
var lotteryEngine = c.Resolve<ILotteryEngine>();
|
var lotteryEngine = c.Resolve<ILotteryEngine>();
|
||||||
|
var wechatService = c.Resolve<IWechatService>();
|
||||||
|
var redisService = c.Resolve<IRedisService>();
|
||||||
var logger = c.Resolve<ILogger<PaymentNotifyService>>();
|
var logger = c.Resolve<ILogger<PaymentNotifyService>>();
|
||||||
return new PaymentNotifyService(dbContext, wechatPayService, wechatPayV3Service, wechatPayConfigService, paymentService, lotteryEngine, logger);
|
return new PaymentNotifyService(dbContext, wechatPayService, wechatPayV3Service, wechatPayConfigService, paymentService, lotteryEngine, wechatService, redisService, logger);
|
||||||
}).As<IPaymentNotifyService>().InstancePerLifetimeScope();
|
}).As<IPaymentNotifyService>().InstancePerLifetimeScope();
|
||||||
|
|
||||||
// 注册充值服务
|
// 注册充值服务
|
||||||
|
|
|
||||||
|
|
@ -46,3 +46,66 @@ public class WechatMobileResult
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ErrorMessage { get; set; }
|
public string? ErrorMessage { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 微信小程序发货信息请求
|
||||||
|
/// </summary>
|
||||||
|
public class WechatShippingRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 用户OpenId
|
||||||
|
/// </summary>
|
||||||
|
public string OpenId { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 商户订单号
|
||||||
|
/// </summary>
|
||||||
|
public string OrderNo { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 商户号(可选,不传则根据订单号自动匹配)
|
||||||
|
/// </summary>
|
||||||
|
public string? MchId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 小程序AppId(可选,不传则使用默认配置)
|
||||||
|
/// </summary>
|
||||||
|
public string? AppId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 商品描述(可选,默认为"本单购买商品已发放至[小程序盒柜]")
|
||||||
|
/// </summary>
|
||||||
|
public string? ItemDesc { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 物流类型:1=实体物流,2=同城配送,3=虚拟商品,4=用户自提
|
||||||
|
/// 默认为4(虚拟商品场景)
|
||||||
|
/// </summary>
|
||||||
|
public int LogisticsType { get; set; } = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 微信小程序发货信息结果
|
||||||
|
/// </summary>
|
||||||
|
public class WechatShippingResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 是否成功
|
||||||
|
/// </summary>
|
||||||
|
public bool Success { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 错误码(0表示成功)
|
||||||
|
/// </summary>
|
||||||
|
public int ErrorCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 错误信息
|
||||||
|
/// </summary>
|
||||||
|
public string? ErrorMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否需要重试(发货失败时为true)
|
||||||
|
/// </summary>
|
||||||
|
public bool NeedRetry { get; set; }
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user