using System; using System.Web; using WingServerCommon.Service; using WingInterfaceLibrary.Interface; using System.Threading.Tasks; using WingInterfaceLibrary.DTO.Payment; using WingInterfaceLibrary.Request.Payment; using WingInterfaceLibrary.Result; using System.Collections.Generic; using WingInterfaceLibrary.Interface.DBInterface; using WingInterfaceLibrary.DB.Request; using WingServerCommon.Log; using WingPaymentService.Common; using WingInterfaceLibrary.Enum; using WingInterfaceLibrary.Request; using WingPaymentService.Common.WeChat; using WingInterfaceLibrary.Request.Courses; namespace WingPaymentService.Service { public class PaymentService : JsonRpcService, IPaymentService { private IEducationService _educationService; private IAuthenticationService _authenticationService; private IPaymentDBService _paymentDBService; private AlipayCommon _alipayCommon; private WeChatCommon _weChatCommon; public override void Load(JsonRpcClientPool jsonRpcClientPool) { _alipayCommon = new AlipayCommon(); _weChatCommon = new WeChatCommon(); base.Load(jsonRpcClientPool); _paymentDBService = GetProxy(); _authenticationService = GetProxy(); _educationService = GetProxy(); } /// /// 购买接口 /// /// /// public async Task CreateOrderAsync(CreateOrderRequest request) { var dbRequest = new CreateOrderDBRequest(); dbRequest.OrderAmount = request.OrderAmount; dbRequest.OrderTitle = request.OrderTitle; dbRequest.OrderType = request.OrderType; if (string.IsNullOrWhiteSpace(request.OrderUserCode)) { request.OrderUserCode = await ValidateTokenAsync(request.Token); if (string.IsNullOrWhiteSpace(request.OrderUserCode)) { ThrowCustomerException(CustomerRpcCode.UserNotFind, "UserNotFind"); } } dbRequest.OrderUserCode = request.OrderUserCode; dbRequest.PayStatus = PayStatusEnum.NoPay; dbRequest.PayTime = DateTime.UtcNow; dbRequest.ProductCode = request.ProductCode; dbRequest.TPORderCode = request.TPORderCode; return await _paymentDBService.CreateOrderAsync(dbRequest); } /// /// 订单详情接口 /// /// /// public async Task GetOrderDetailAsync(GetOrderDetailRequest request) { return await _paymentDBService.GetOrderDetailAsync(new GetOrderDetailDBRequest { OrderCode = request.OrderCode }); } /// /// 订单列表接口 /// /// /// public async Task> GetOrderPagesAsync(GetOrderPagesRequest request) { return await _paymentDBService.GetOrderPagesAsync(new GetOrderPagesDBRequest { CurrentPage = request.PageIndex, PageSize = request.PageSize, KeyWord = request.KeyWord }); } /// /// 发起支付请求 /// /// /// public async Task GoToPayAsync(GoToPayRequest request) { if (!string.IsNullOrWhiteSpace(request.OrderCode)) { var orderInfo = await _paymentDBService.GetOrderDetailAsync(new GetOrderDetailDBRequest { OrderCode = request.OrderCode }); if (orderInfo != null && orderInfo.OrderAmount > 0) { string recordCode = Guid.NewGuid().ToString("N"); (string payUrl, string recordContent) payContent = (string.Empty,string.Empty); switch (request.PayType) { case PayTypeEnum.Alipay_PAGE: payContent = _alipayCommon.AlipayPagePay(orderInfo.OrderTitle, orderInfo.OrderAmount, orderInfo.Code, recordCode); break; case PayTypeEnum.Alipay_WAP: payContent = _alipayCommon.AlipayWapPay(orderInfo.OrderTitle, orderInfo.OrderAmount, orderInfo.Code, recordCode); break; case PayTypeEnum.WeChat_PAGE: payContent = await _weChatCommon.GetWebPayUrlAsync(orderInfo.OrderTitle, orderInfo.OrderAmount, orderInfo.Code, recordCode, string.Empty, string.Empty); break; case PayTypeEnum.WeChat_WAP: payContent = await _weChatCommon.GetWapPayUrlAsync(orderInfo.OrderTitle, orderInfo.OrderAmount, orderInfo.Code, recordCode, string.Empty, string.Empty); break; } await CreatePayStatusReq(recordCode, payContent.recordContent); if (!string.IsNullOrWhiteSpace(payContent.payUrl)) { return new PayInfoDTO { IsSuccess = true, PayUrl = payContent.payUrl }; } } } return new PayInfoDTO { IsSuccess = false, PayUrl = string.Empty }; } /// /// 支付后回调 /// /// 来源 /// 请求信息 /// public async Task PayCallbackAsync(string src, string request) { bool isSuccess = false; try { switch (src) { case "alipay": isSuccess = await AlipayCallback(request); break; case "wechat": isSuccess = await WeChatCallback(request); break; } return new PayCallbackDTO { IsSuccess = isSuccess }; } catch (Exception ex) { Logger.WriteLineError($"PayCallback error {ex}"); return new PayCallbackDTO { IsSuccess = false }; } } /// /// 支付宝回调 /// /// /// private async Task AlipayCallback(string request) { Dictionary keyValuePairs = new Dictionary(); var uriParams = HttpUtility.UrlDecode(request); if (uriParams != null) { var paramsArr = uriParams.Split('&'); foreach (string param in paramsArr) { var keyValue = param.Split('='); var key = keyValue[0]; var value = keyValue.Length > 1 ? keyValue[1] : string.Empty; keyValuePairs.Add(key, value); } } var payOutTradeNo = keyValuePairs.GetValueOrDefault("out_trade_no"); var totalAmount = keyValuePairs.GetValueOrDefault("total_amount"); var payRecordCode = keyValuePairs.GetValueOrDefault("pay_record_code"); var payStatus = keyValuePairs.GetValueOrDefault("trade_status") == "TRADE_SUCCESS" ? WingInterfaceLibrary.Enum.PayStatusEnum.Paid : WingInterfaceLibrary.Enum.PayStatusEnum.NoPay; var payTime = DateTime.UtcNow; return await PayRecordWriteRes(payOutTradeNo, payRecordCode, totalAmount, payStatus, payTime, request); } /// /// 微信回调 /// /// /// private async Task WeChatCallback(string request) { //转换数据格式, 取消签名校验,签名调用方自己调用,兼容支付和退款 WxPayData data = new WxPayData(); var paramValues = data.FromXml(request, false);//回调不用签名校验 var payOutTradeNo = paramValues.GetValueOrDefault("out_trade_no")?.ToString(); var totalAmount = (double.Parse(paramValues.GetValueOrDefault("total_fee")?.ToString()) / 100).ToString("0.00"); var payRecordCode = paramValues.GetValueOrDefault("pay_record_code")?.ToString(); var payStatus = paramValues.GetValueOrDefault("result_code")?.ToString() == "SUCCESS" ? PayStatusEnum.Paid : PayStatusEnum.NoPay; var payTime = DateTime.UtcNow; return await PayRecordWriteRes(payOutTradeNo, payRecordCode, totalAmount, payStatus, payTime, request); } /// /// 支付记录 /// /// 订单编码 /// 支付记录编码 /// 支付金额 /// 支付状态 /// 支付时间 /// 支付原始请求 /// private async Task PayRecordWriteRes(string orderCode, string payRecordCode, string totalAmount, PayStatusEnum payStatus, DateTime payTime, string res) { if (string.IsNullOrWhiteSpace(payRecordCode)) { Logger.WriteLineError("Pay record code is empty"); return false; } await UpdatePayStatusRes(payRecordCode, payStatus, res, payTime); if (string.IsNullOrWhiteSpace(orderCode)) { Logger.WriteLineError("Order code is empty"); return false; } if (payStatus == PayStatusEnum.Paid) { return await UpdateOrderStatus(orderCode, payStatus, totalAmount, payTime); } return false; } private async Task UpdateOrderStatus(string orderCode, PayStatusEnum payStatus, string totalAmount, DateTime payTime) { var orderInfo = await _paymentDBService.GetOrderDetailAsync(new GetOrderDetailDBRequest { OrderCode = orderCode }); if (orderInfo.OrderAmount.ToString("0.00") != totalAmount) { Logger.WriteLineError($"OrderCode:{orderInfo.Code} pay status {payStatus}, total amount error, order amount {orderInfo.OrderAmount.ToString("0.00")} paid amount {totalAmount}"); return false; } var result = await _paymentDBService.UpdateOrderAsync(new UpdateOrderDBRequest { OrderCode = orderCode, PayStatus = payStatus }); await _educationService.PaymentCallbackAsync(new PaymentCallbackRequest { PaymentOrderCode = orderCode, PayStatus = payStatus, PayTime = payTime }); return result.IsSuccess; } private async Task CreatePayStatusReq(string paymentRecordCode, string payReqContent) { var createRecordInfo = new CreatePaymentRecordDBRequest(); createRecordInfo.PayReqContent = payReqContent; return await _paymentDBService.CreatePaymentRecordAsync(createRecordInfo); } private async Task UpdatePayStatusRes(string paymentRecordCode, PayStatusEnum payStatus, string payResContent, DateTime payTime) { var updateRecordInfo = new UpdatePaymentRecordDBRequest(); updateRecordInfo.Code = paymentRecordCode; updateRecordInfo.PayTime = payTime; updateRecordInfo.PayStatus = payStatus; updateRecordInfo.PayResContent = payResContent; return await _paymentDBService.UpdatePaymentRecordAsync(updateRecordInfo); } /// /// 客户端用户验证 /// /// /// User Code private async Task ValidateTokenAsync(string token) { var request = new TokenRequest() { Token = token }; var result = await _authenticationService.GetTokenAsync(request); return result.ClientId; //return User code } private void ThrowCustomerException(CustomerRpcCode customerRpcCodeEnum, string msg) { ThrowRpcException((int)customerRpcCodeEnum, msg); } } }