LifePayment/LifePayment.Application/User/OssSTSHelper.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
LifePayment/LifePayment.Domain/WeChat/WxRechargeInfo.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
LifePayment/LifePayment.Host/LifePaymentService.HttpApi.xml | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
LifePayment/LifePayment.HttpApi/LifePay/ACOOLYNotifyController.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
LifePayment/LifePayment.HttpApi/LifePay/AccountController.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
LifePayment/LifePayment.HttpApi/LifePay/AliPayNotifyController.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
LifePayment/LifePayment.HttpApi/LifePay/WxPayNotifyController.cs | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
LifePayment/LifePayment.Application/User/OssSTSHelper.cs
New file @@ -0,0 +1,62 @@ using Aliyun.Acs.Core; using Aliyun.Acs.Core.Auth.Sts; using Aliyun.Acs.Core.Http; using Aliyun.Acs.Core.Profile; using LifePayment.Domain.Shared; namespace LifePayment.Application { public class OssSTSHelper { private const int TokenExpireTime = 3600; private const string RoleSessionName = "SessionTest"; private const string PolicyFile = @"{ ""Version"": ""1"", ""Statement"": [ { ""Effect"": ""Allow"", ""Action"": ""oss:PutObject"", ""Resource"": [ ""acs:oss:*:*:waterdroptest2/*"", ""acs:oss:*:*:parkmanagement/*"", ""acs:oss:*:*:jurenlian/*"" ] } ] }"; private readonly OssSettings ossSettings; public OssSTSHelper(OssSettings ossSettings) { this.ossSettings = ossSettings; } public OssSTSReponse GetOssSTS() { string regionId = "cn-hangzhou"; IClientProfile profile = DefaultProfile.GetProfile(regionId, ossSettings.OssAccessKeyId, ossSettings.OssAccessSecret); DefaultAcsClient client = new DefaultAcsClient(profile); AssumeRoleRequest request = new AssumeRoleRequest(); request.Method = MethodType.POST; request.RoleArn = ossSettings.OssRoleRan; request.RoleSessionName = RoleSessionName; request.Policy = PolicyFile; request.DurationSeconds = TokenExpireTime; AssumeRoleResponse response = client.GetAcsResponse(request); OssSTSReponse result = new OssSTSReponse() { Expiration = response.Credentials.Expiration, OssAccessKeyId = response.Credentials.AccessKeyId, OssAccessSecret = response.Credentials.AccessKeySecret, SecurityToken = response.Credentials.SecurityToken, RequestId = response.RequestId }; return result; } } } LifePayment/LifePayment.Domain/WeChat/WxRechargeInfo.cs
New file @@ -0,0 +1,219 @@ using LifePayment.Domain.Shared; using Newtonsoft.Json; using System.ComponentModel.DataAnnotations; namespace LifePayment.Application.Contracts { public class WxRechargeInfo { /// <summary> /// 充值单号 /// </summary> public string RechargeNo { get; set; } /// <summary> /// 充值码地址 /// </summary> public string RechargeCodeUrl { get; set; } } public class WxRechargeInput { /// <summary> /// 充值金额,单位为元。 /// </summary> public decimal Amount { get; set; } /// <summary> /// 商品描述 /// </summary> public string Description { get; set; } = "微信充值"; /// <summary> /// 备注 /// </summary> public string Remark { get; set; } } public class WxRechargeNotifyInput { /// <summary> /// 通知Id /// </summary> [JsonProperty("id")] [Required] public string Id { get; set; } /// <summary> /// 通知创建时间 /// </summary> [JsonProperty("create_time")] [Required] public string CreateTime { get; set; } /// <summary> /// 通知类型 /// </summary> [JsonProperty("event_type")] [Required] public string EventType { get; set; } /// <summary> /// 通知数据类型 /// </summary> [JsonProperty("resource_type")] [Required] public string ResourceType { get; set; } /// <summary> /// 通知数据 /// </summary> [JsonProperty("resource")] [Required] public Resource Resource { get; set; } /// <summary> /// 回调摘要 /// </summary> [JsonProperty("summary")] [Required] public string Summary { get; set; } } public class Resource { /// <summary> /// 加密算法类型 /// </summary> [JsonProperty("algorithm")] [Required] public string Algorithm { get; set; } /// <summary> /// 数据密文 /// </summary> [JsonProperty("Ciphertext")] [Required] public string Ciphertext { get; set; } /// <summary> /// 附加数据 /// </summary> [JsonProperty("associated_data")] public string AssociatedData { get; set; } /// <summary> /// 原始类型 /// </summary> [JsonProperty("original_type")] [Required] public string OriginalType { get; set; } /// <summary> /// 随机串 /// </summary> [JsonProperty("nonce")] [Required] public string Nonce { get; set; } } public class WxPayNotice { /// <summary> /// 应用Id /// </summary> [JsonProperty("appid")] public string Appid { get; set; } /// <summary> /// 商户号 /// </summary> [JsonProperty("mchid")] public string Mchid { get; set; } /// <summary> /// 商户订单号 /// </summary> [JsonProperty("out_trade_no")] public string OutTradeNo { get; set; } /// <summary> /// 微信支付订单号 /// </summary> [JsonProperty("transaction_id")] public string TransactionId { get; set; } /// <summary> /// 交易类型 /// </summary> [JsonProperty("trade_type")] public string TradeType { get; set; } /// <summary> /// 交易状态 /// </summary> [JsonProperty("trade_state")] public string TradeState { get; set; } /// <summary> /// 交易状态描述 /// </summary> [JsonProperty("trade_state_desc")] public string TradeStateDesc { get; set; } /// <summary> /// 付款银行 /// </summary> [JsonProperty("bank_type")] public string BankType { get; set; } /// <summary> /// 附加数据 /// </summary> [JsonProperty("attach")] public string Attach { get; set; } /// <summary> /// 支付完成时间 /// </summary> [JsonProperty("success_time")] public string SuccessTime { get; set; } /// <summary> /// 支付者 /// </summary> [JsonProperty("payer")] public Payer Payer { get; set; } /// <summary> /// 订单金额 /// </summary> [JsonProperty("amount")] public Amount Amount { get; set; } /// <summary> /// 场景信息 /// </summary> [JsonProperty("scene_info")] public SceneInfo SceneInfo { get; set; } /// <summary> /// 优惠功能 /// </summary> [JsonProperty("promotion_detail")] public PromotionDetail PromotionDetail { get; set; } } public class WxRechargeNotifyResult { /// <summary> /// 返回状态码(错误码,SUCCESS为接收成功,其他错误码为失败) /// </summary> public string Code { get; set; } /// <summary> /// 返回信息,如非空,为错误原因 /// </summary> public string Message { get; set; } } } LifePayment/LifePayment.Host/LifePaymentService.HttpApi.xml
@@ -19,6 +19,18 @@ <returns></returns> <exception cref="T:Volo.Abp.UserFriendlyException"></exception> </member> <member name="M:LifePayment.HttpApi.ACOOLYNotifyController.ACOOLYNotify"> <summary> ACOOLY回调通知 </summary> <returns></returns> </member> <member name="M:LifePayment.HttpApi.AliPayNotifyController.AliRechargeNotify"> <summary> 支付宝充值回调通知 </summary> <returns></returns> </member> <member name="M:LifePayment.HttpApi.AreaController.GetAreaList"> <summary> 获取省市区 @@ -266,5 +278,12 @@ <param name="input"></param> <returns></returns> </member> <member name="M:LifePayment.HttpApi.WxPayNotifyController.WxRechargeNotify(LifePayment.Application.Contracts.WxRechargeNotifyInput)"> <summary> 微信支付回调通知 </summary> <param name="input"></param> <returns></returns> </member> </members> </doc> LifePayment/LifePayment.HttpApi/LifePay/ACOOLYNotifyController.cs
New file @@ -0,0 +1,124 @@ using LifePayment.Application.Contracts; using LifePayment.Domain.Shared; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.IO; using System.Text; using System.Threading.Tasks; using Volo.Abp; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Uow; namespace LifePayment.HttpApi { [Route("api/[controller]/[action]")] [ApiController] [IgnoreAntiforgeryToken] public class ACOOLYNotifyController : AbpController { private readonly ILifePayService _lifePayService; private readonly ILogger<ACOOLYNotifyController> _logger; public ACOOLYNotifyController( ILogger<ACOOLYNotifyController> logger, ILifePayService lifePayService) { _logger = logger; _lifePayService = lifePayService; } /// <summary> /// ACOOLY回调通知 /// </summary> /// <returns></returns> [HttpPost] [UnitOfWork] [AllowAnonymous] public async Task ACOOLYNotify() { _logger.LogError("ACOOLY回调通知开始进入"); var body = string.Empty; using (var reader = new StreamReader(Request.Body, Encoding.UTF8)) { body = await reader.ReadToEndAsync(); } if (body.IsNullOrEmpty()) { _logger.LogError("ACOOLY回调通知Input为null"); throw new UserFriendlyException("ACOOLY回调通知Input为null"); } var baseInfo = JsonConvert.DeserializeObject<ACOOLYRequestBaseResponse>(body); var orderNo = string.Empty; var status = LifePayOrderStatusEnum.待确认; var acoolyOrderNo = string.Empty; _logger.LogError("ACOOLY回调通处理类型:" + baseInfo.Service); _logger.LogError("ACOOLY回调内容:" + body); switch (baseInfo.Service) { case ACOOLYConstant.Sevice.ConfirmElectricOrder: var confirmElectricOrderResponse = JsonConvert.DeserializeObject<ConfirmElectricOrderResponse>(body); orderNo = confirmElectricOrderResponse.ElectricChargeOrder.OutOrderNo; acoolyOrderNo = confirmElectricOrderResponse.ElectricChargeOrder.BusiOrderNo; _logger.LogError("ACOOLY回调通处理结果状态:" + confirmElectricOrderResponse.ElectricChargeOrder.Status); if (!confirmElectricOrderResponse.Success || (confirmElectricOrderResponse.Code != ACOOLYConstant.Code.SUCCESS && confirmElectricOrderResponse.Code != ACOOLYConstant.Code.PROCESSING)) { status = LifePayOrderStatusEnum.已失败; } else if (confirmElectricOrderResponse.ElectricChargeOrder.Status == ACOOLYConstant.Code.SUCCESS) { status = LifePayOrderStatusEnum.已完成; } else if (confirmElectricOrderResponse.ElectricChargeOrder.Status == ACOOLYConstant.Code.PROCESSING) { status = LifePayOrderStatusEnum.待确认; } else { status = LifePayOrderStatusEnum.已失败; } break; case ACOOLYConstant.Sevice.ConfirmPhoneOrder: var confirmPhoneOrderResponse = JsonConvert.DeserializeObject<ConfirmPhoneOrderResponse>(body); orderNo = confirmPhoneOrderResponse.PhoneChargeOrder.OutOrderNo; acoolyOrderNo = confirmPhoneOrderResponse.PhoneChargeOrder.BusiOrderNo; _logger.LogError("ACOOLY回调通处理结果状态:" + confirmPhoneOrderResponse.PhoneChargeOrder.Status); if (!confirmPhoneOrderResponse.Success || (confirmPhoneOrderResponse.Code != ACOOLYConstant.Code.SUCCESS && confirmPhoneOrderResponse.Code != ACOOLYConstant.Code.PROCESSING)) { status = LifePayOrderStatusEnum.已失败; } else if (confirmPhoneOrderResponse.PhoneChargeOrder.Status == ACOOLYConstant.Code.SUCCESS) { status = LifePayOrderStatusEnum.已完成; } else if (confirmPhoneOrderResponse.PhoneChargeOrder.Status == ACOOLYConstant.Code.PROCESSING) { status = LifePayOrderStatusEnum.待确认; } else { status = LifePayOrderStatusEnum.已失败; } break; default: break; } await _lifePayService.ACOOLYOrderNotifyHandler(orderNo, acoolyOrderNo, status); } } } LifePayment/LifePayment.HttpApi/LifePay/AccountController.cs
@@ -1,4 +1,6 @@ using LifePayment.Application.Contracts; using LifePayment.Application; using LifePayment.Application.Contracts; using LifePayment.Domain.Shared; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; @@ -15,19 +17,19 @@ public class AccountController : AbpController { private readonly IAccountService _accountService; private readonly OssSettings ossSettings; private readonly IWebClientInfoProvider _webClientInfoProvider; public AccountController( IAccountService accountService, IOptionsMonitor<OssSettings> optionsMonitor, IWebClientInfoProvider webClientInfoProvider ) { _accountService = accountService; this.ossSettings = optionsMonitor.CurrentValue; _webClientInfoProvider = webClientInfoProvider; } @@ -60,7 +62,12 @@ return await _accountService.LifePayPhoneMesssageCodeLogin(input); } [HttpPost] public OssSTSReponse GetOssSTS() { OssSTSHelper ossSTSHelper = new OssSTSHelper(this.ossSettings); return ossSTSHelper.GetOssSTS(); } #endregion LifePayment/LifePayment.HttpApi/LifePay/AliPayNotifyController.cs
New file @@ -0,0 +1,130 @@ using LifePayment.Application.Contracts; using LifePayment.Domain.Shared; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Uow; namespace LifePayment.HttpApi { [Route("api/[controller]/[action]")] [ApiController] [IgnoreAntiforgeryToken] //[Authorize(AuthenticationSchemes = AliPaySignAuthenticationDefaults.AuthenticationScheme)] public class AliPayNotifyController : AbpController { private readonly ILifePayService _lifePayService; private readonly ILogger<AliPayNotifyController> _logger; public AliPayNotifyController( ILogger<AliPayNotifyController> logger, ILifePayService lifePayService) { _logger = logger; _lifePayService = lifePayService; } /// <summary> /// 支付宝充值回调通知 /// </summary> /// <returns></returns> [HttpPost] [UnitOfWork] public async Task<ContentResult> AliRechargeNotify() { _logger.LogError($"生活管家支付宝充值回调通知:进入支付宝回调"); var request = await this.HttpContext.Request.ReadFormAsync(); var requestToDic = request.ToDictionary(r => r.Key, r => r.Value.ToString()); var serializeRequest = JsonConvert.SerializeObject(requestToDic); _logger.LogError($"生活管家支付宝充值回调通知:{serializeRequest}"); //var serializeRequest = "{\"gmt_create\":\"2025-02-25 13:18:59\",\"charset\":\"UTF-8\",\"seller_email\":\"zfb1@818nb.com\",\"subject\":\"生活缴费-话费\",\"sign\":\"Sp06G1GxrAfDvoHPz9l3DJ20SxhvRzEGFeCGu4LHrSWmEG4OY7MHMx+iJi54ETbdXV0YsyDH9JZD7PWN3HCpEq/wGO4Wh4VSYSe7lqxD6r4f/HFiB0YlrdQoSzjZgYPzLjy6bcdlKRRHOeDkgs2i7TfvIsxWxHs9t0xuS0RlkpdZfb7d7m0EuZ/3v2Cbsj5AHjxb1S2PkO0oQyriYgGQdmkPqILZHwieST+tNEHS4dGFKYu2nkfctAGjWIDv/hKQNY7jEUxsEeG0SnK4TPU8zNplFR9/aKM0Wfwp1pdlaiP2u/d8vOtNh5q+emvaYbKrUkIEFBok8pDLNDta7ZjtVw==\",\"invoice_amount\":\"0.01\",\"buyer_open_id\":\"071xYXDfXBLAI9U11jg_WrH1K6hWq8HYGz0u85xBivf3Sce\",\"notify_id\":\"2025022501222131904087711494539601\",\"fund_bill_list\":\"[{\\\"amount\\\":\\\"0.01\\\",\\\"fundChannel\\\":\\\"ALIPAYACCOUNT\\\"}]\",\"notify_type\":\"trade_status_sync\",\"trade_status\":\"TRADE_SUCCESS\",\"receipt_amount\":\"0.01\",\"buyer_pay_amount\":\"0.01\",\"app_id\":\"2021004171602214\",\"sign_type\":\"RSA2\",\"seller_id\":\"2088050542042301\",\"gmt_payment\":\"2025-02-25 13:19:03\",\"notify_time\":\"2025-02-25 13:44:34\",\"merchant_app_id\":\"2021004171602214\",\"version\":\"1.0\",\"out_trade_no\":\"JF202502251318555214671\",\"total_amount\":\"0.01\",\"trade_no\":\"2025022522001487711401331043\",\"auth_app_id\":\"2021004171602214\",\"buyer_logon_id\":\"130****2238\",\"point_amount\":\"0.00\"}"; var input = JsonConvert.DeserializeObject<AliRechargeNotifyInput>(serializeRequest); if (input.OutTradeNo.StartsWith("JF") && Regex.IsMatch(input.OutTradeNo, @"^JF\d+$")) { if (input.TradeStatus == LifePaymentConstant.AliPayStatus.支付成功) { await _lifePayService.LifePaySuccessHandler(input.OutTradeNo, input.TradeNo); } } return new ContentResult { Content = "success", }; } #if DEBUG [HttpGet] [UnitOfWork] [AllowAnonymous] public async Task<ContentResult> TestAliRechargeNotify(string outTradeNo, string tradeNo, bool success) { if (outTradeNo.StartsWith("JF") && Regex.IsMatch(outTradeNo, @"^JF\d+$")) { if (success) { await _lifePayService.LifePaySuccessHandler(outTradeNo, tradeNo); } } return new ContentResult { Content = "success", }; } #endif /// <summary> /// 单笔转账到支付宝账户、单笔转账到银行卡、C2C现金红包、B2C现金红包单据状态变更后触发的通知 /// </summary> /// <returns></returns> //[HttpPost] //[UnitOfWork] //public async Task<ContentResult> NotifyOrderChanged() //{ // var request = await this.HttpContext.Request.ReadFormAsync(); // var requestToDic = request.ToDictionary(r => r.Key, r => r.Value.ToString()); // var serializeRequest = JsonConvert.SerializeObject(requestToDic); // _logger.LogError($"单笔转账回调:{serializeRequest}"); // if (requestToDic["msg_method"] == "alipay.fund.trans.order.changed") // { // var input = JsonConvert.DeserializeObject<FundOrderChangedInput>(serializeRequest); // if (input.BizContent != null) // { // if (input.BizContent.OutBizNo.Contains(RequestCode.AlipayCharge)) // { // await _walletService.FundTransOrderChangedForRecharge(input.BizContent); // } // else // { // await _walletService.FundTransOrderChangedForSingleTransfer(input.BizContent); // } // } // } // return new ContentResult // { // Content = "success", // }; //} } } LifePayment/LifePayment.HttpApi/LifePay/WxPayNotifyController.cs
New file @@ -0,0 +1,75 @@ using LifePayment.Application.Contracts; using LifePayment.Domain; using LifePayment.Domain.Shared; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System; using System.Text.RegularExpressions; using System.Threading.Tasks; using Volo.Abp.AspNetCore.Mvc; using Volo.Abp.Uow; namespace LifePayment.HttpApi { [Route("api/[controller]/[action]")] [ApiController] [IgnoreAntiforgeryToken] // [Authorize(AuthenticationSchemes = WxPaySignAuthenticationDefaults.AuthenticationScheme)] public class WxPayNotifyController : AbpController { private readonly IWxPayApi _wxPayApi; private readonly ILifePayService _lifePayService; private readonly ILogger<WxPayNotifyController> _logger; public WxPayNotifyController( IWxPayApi wxPayApi, ILogger<WxPayNotifyController> logger, ILifePayService lifePayService) { _wxPayApi = wxPayApi; _logger = logger; _lifePayService = lifePayService; } /// <summary> /// 微信支付回调通知 /// </summary> /// <param name="input"></param> /// <returns></returns> [HttpPost] [UnitOfWork] public async Task<WxRechargeNotifyResult> WxRechargeNotify(WxRechargeNotifyInput input) { try { _logger.LogError($"生活管家微信充值回调通知:进入微信回调"); var data = _wxPayApi.AesGcmDecrypt(input.Resource.AssociatedData, input.Resource.Nonce, input.Resource.Ciphertext); var wxPayNotice = JsonConvert.DeserializeObject<WxPayNotice>(data); if (wxPayNotice.OutTradeNo.StartsWith("JF") && Regex.IsMatch(wxPayNotice.OutTradeNo, @"^JF\d+$")) { if (wxPayNotice.TradeState == LifePaymentConstant.WxPayStatus.支付成功) { await _lifePayService.LifePaySuccessHandler(wxPayNotice.OutTradeNo, wxPayNotice.TransactionId); } } } catch (Exception ex) { await CurrentUnitOfWork.RollbackAsync(); return new WxRechargeNotifyResult { Code = "FAIL", Message = ex.Message, }; } return new WxRechargeNotifyResult { Code = "SUCCESS", }; } } }