支付模块完成

develop
old易 2024-01-25 16:37:04 +08:00
parent 8284b1c601
commit 3a88b98f15
20 changed files with 752 additions and 93 deletions

View File

@ -41,6 +41,38 @@ namespace New_College.Api.Controllers
/// <summary>
/// 智能填报预览图
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpGet]
public async Task<MessageModel<AIPerviewDto>> GetAIPerview([FromQuery] OneSubmitGoRequest request)
{
var test = (await _VolunteerTableServices.Query()).FirstOrDefault();
var pie = new List<PieChatsDto>();
pie.Add(new PieChatsDto() { name = "需冲刺", value = 560 });
pie.Add(new PieChatsDto() { name = "较稳妥", value = 1301 });
pie.Add(new PieChatsDto() { name = "可保底", value = 600 });
var ulist = new List<UniversityPerviewDto>();
ulist.Add(new UniversityPerviewDto() { Name = "985", Count = 7 });
ulist.Add(new UniversityPerviewDto() { Name = "211", Count = 18 });
ulist.Add(new UniversityPerviewDto() { Name = "双一流", Count = 56 });
ulist.Add(new UniversityPerviewDto() { Name = "省重点", Count = 42 });
ulist.Add(new UniversityPerviewDto() { Name = "公办", Count = 134 });
ulist.Add(new UniversityPerviewDto() { Name = "民办", Count = 10 });
return new MessageModel<AIPerviewDto>()
{
msg = "ok",
response = new AIPerviewDto()
{
pieChats = pie,
universities = ulist
},
success = true
};
}
/// <summary>
/// 查询扩缩招院校招生计划详情
/// </summary>

View File

@ -29,7 +29,7 @@ namespace New_College.Api.Controllers
{
var filestream = await v_OrderInfoServices.QrCodePay(query);
Response.Headers.Add("Content-Type", "image/png");
return File(filestream, "image/png");
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
@ -158,7 +159,7 @@ namespace New_College.Api.Controllers.Front
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> PayNotify()
public async Task<IActionResult> OldPayNotify()
{
logger.LogInformation("开始回调PayNotify");
DingHookHelper.DingTalkHookMessage("开始回调PayNotify", "开始回调PayNotify");
@ -172,6 +173,7 @@ namespace New_College.Api.Controllers.Front
var builder = reader.ReadToEnd();
//WebHookHelper.WebHookmarkdownSend(builder.ToString());
DingHookHelper.DingTalkHookMessage("xml", builder.ToString());
try
{
data.FromXml(builder.ToString());
@ -190,15 +192,15 @@ namespace New_College.Api.Controllers.Front
};
// WebHookHelper.WebHookmarkdownSend("Check sign success");
//检查支付结果中transaction_id是否存在
if (!data.IsSet("transaction_id"))
{
DingHookHelper.DingTalkHookMessage("回调PayNotify", "支付结果中微信订单号不存在");
//若transaction_id不存在则立即返回结果给微信支付后台
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", "支付结果中微信订单号不存在");
//WebHookHelper.WebHookmarkdownSend("支付结果中微信订单号不存在");
return Content(res.ToXml(), "text/xml");
}
//if (!data.IsSet("transaction_id"))
//{
// DingHookHelper.DingTalkHookMessage("回调PayNotify", "支付结果中微信订单号不存在");
// //若transaction_id不存在则立即返回结果给微信支付后台
// res.SetValue("return_code", "FAIL");
// res.SetValue("return_msg", "支付结果中微信订单号不存在");
// //WebHookHelper.WebHookmarkdownSend("支付结果中微信订单号不存在");
// return Content(res.ToXml(), "text/xml");
//}
// 执行订单状态操作
string out_trade_no = data.GetValue("out_trade_no").ToString();
logger.LogInformation("开始回调PayNotify" + out_trade_no);
@ -246,7 +248,188 @@ namespace New_College.Api.Controllers.Front
return Content(res.ToXml(), "text/xml");
}
[HttpPost]
[AllowAnonymous]
public async Task<WxPayCallbackViewModel> PayNotify()
{
var buffer = new MemoryStream();
Request.Body.CopyTo(buffer);
var str = Encoding.UTF8.GetString(buffer.GetBuffer());
DingHookHelper.DingTalkHookMessage("PayNotify-buffer", str);
var wxPayNotifyModel = JsonConvert.DeserializeObject<WxPayNotifyModel>(str);
var resource = wxPayNotifyModel?.resource ?? new WxPayResourceModel();
var decryptStr = AesGcmHelper.AesGcmDecrypt(resource.associated_data, resource.nonce, resource.ciphertext, WeixinConfig.APIv3Key);
var decryptModel = JsonConvert.DeserializeObject<WxPayResourceDecryptModel>(decryptStr);
var viewModel = new WxPayCallbackViewModel();
if (decryptModel != null&&decryptModel.trade_state== "SUCCESS")
{
DingHookHelper.DingTalkHookMessage("PayNotify-decryptModel", decryptModel.ToJson());
var info = await v_OrderInfoRepository.Query(x => x.out_trade_no == decryptModel.out_trade_no);
if (info.Count <= 0)
{
viewModel.message = "在自有平台未找到该订单号";
viewModel.code = "FAIL";
DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + decryptModel.out_trade_no);
return viewModel;
}
var oneinfo = info.FirstOrDefault();
oneinfo.Status = EnumOrderType.payoff;
var rep = await v_OrderInfoRepository.Update(oneinfo);
if (rep)
{
DingHookHelper.DingTalkHookMessage("支付回调成功", oneinfo.out_trade_no + ":修改为VIP");
//修改用户信息 修改为VIp
var customerinfo = await v_CustomerInfoRepository.QueryById(oneinfo.CustomerId);
customerinfo.IsVIP = true;
customerinfo.VipCode = oneinfo.CardNo;
await v_CustomerInfoRepository.Update(customerinfo);
var oldorderlist = await v_OrderInfoRepository.Query(c => c.CustomerId == oneinfo.CustomerId && c.Status == EnumOrderType.payment);
oldorderlist.ForEach(async a =>
{
a.Status = EnumOrderType.Cancel;
await v_OrderInfoRepository.Update(a);
});
//支付成功后根据用户code找到对应用户修改vip 状态
viewModel.message = "SUCCESS";
viewModel.code = "OK";
}
else
{
DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + decryptModel.out_trade_no);
viewModel.message = "在自有平台未找到该订单号";
viewModel.code = "FAIL";
}
return viewModel;
}
viewModel.code = "FAIL";
viewModel.message = "数据解密失败";
return new WxPayCallbackViewModel();
}
/// <summary>
/// 暂时不用有bug
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> NewPayNotify(WeChatPayCallobject model)
{
DingHookHelper.DingTalkHookMessage("开始回调PayNotify", "开始回调PayNotify");
// 处理微信支付回调数据
if (model.event_type == "TRANSACTION.SUCCESS")
{
DingHookHelper.DingTalkHookMessage("result_code", "SUCCESS");
// 订单支付成功处理逻辑
var info = await v_OrderInfoRepository.Query(x => x.out_trade_no == "");
if (info.Count <= 0)
{
DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + "");
//WebHookHelper.WebHookmarkdownSend("支付结果中微信订单号不存在");
return Content("\"return_code\", \"FAIL\"");
}
var oneinfo = info.FirstOrDefault();
oneinfo.Status = EnumOrderType.payoff;
var rep = await v_OrderInfoRepository.Update(oneinfo);
if (rep)
{
DingHookHelper.DingTalkHookMessage("支付回调成功", oneinfo.out_trade_no + ":修改为VIP");
//修改用户信息 修改为VIp
var customerinfo = await v_CustomerInfoRepository.QueryById(oneinfo.CustomerId);
customerinfo.IsVIP = true;
customerinfo.VipCode = oneinfo.CardNo;
await v_CustomerInfoRepository.Update(customerinfo);
var oldorderlist = await v_OrderInfoRepository.Query(c => c.CustomerId == oneinfo.CustomerId && c.Status == EnumOrderType.payment);
oldorderlist.ForEach(async a =>
{
a.Status = EnumOrderType.Cancel;
await v_OrderInfoRepository.Update(a);
});
//支付成功后根据用户code找到对应用户修改vip 状态
return Ok("SUCCESS");
}
else
{
// string attach = data.GetValue("attach").ToString();
// WebHookHelper.WebHookmarkdownSend(attach);
DingHookHelper.DingTalkHookMessage("回调PayNotify", "在自有平台未找到该订单号" + "");
//res.SetValue("return_code", "FAIL");
//res.SetValue("return_msg", "在自有平台未找到该订单号");
return Content("\"return_code\", \"FAIL\"");
}
}
//else if (model.result_code == "FAIL")
//{
// DingHookHelper.DingTalkHookMessage("result_code", "订单支付失败处理逻辑");
// 订单支付失败处理逻辑...
//}
return Content("SUCCESS");
}
}
public class WeChatPayCallobject
{
public string id { get; set; }
public DateTime create_time { get; set; }
public string resource_type { get; set; }
public string event_type { get; set; }
public string summary { get; set; }
public Resource resource { get; set; }
}
public class Resource
{
public string original_type { get; set; }
public string algorithm { get; set; }
public string ciphertext { get; set; }
public string associated_data { get; set; }
public string nonce { get; set; }
}
public class WeChatPayCallbackModel
{
public string return_code { get; set; }
public string return_msg { get; set; }
public string appid { get; set; }
public string mch_id { get; set; }
public string nonce_str { get; set; }
public string sign { get; set; }
public string result_code { get; set; }
public string openid { get; set; }
public string is_subscribe { get; set; }
public string trade_type { get; set; }
public string bank_type { get; set; }
public string total_fee { get; set; }
public string fee_type { get; set; }
public string transaction_id { get; set; }
public string out_trade_no { get; set; }
public string attach { get; set; }
public string time_end { get; set; }
}
}

View File

@ -3750,6 +3750,26 @@
备注
</summary>
</member>
<member name="P:New_College.Model.ViewModels.AIPerviewDto.universities">
<summary>
院校基础数量
</summary>
</member>
<member name="P:New_College.Model.ViewModels.AIPerviewDto.pieChats">
<summary>
适合我的大学饼图数据
</summary>
</member>
<member name="P:New_College.Model.ViewModels.UniversityPerviewDto.Name">
<summary>
标签
</summary>
</member>
<member name="P:New_College.Model.ViewModels.UniversityPerviewDto.Count">
<summary>
学校数量
</summary>
</member>
<member name="T:New_College.Model.ViewModels.WeixinConfig">
<summary>
微信小程序配置
@ -4735,6 +4755,11 @@
电话
</summary>
</member>
<member name="P:New_College.Model.ViewModels.OrderInfoQuery.CreateTime">
<summary>
</summary>
</member>
<member name="P:New_College.Model.ViewModels.SearchOrderQuery.CardNo">
<summary>
根据卡号查询
@ -7740,6 +7765,139 @@
招生计划Id列表逗号隔开
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayCallbackViewModel.code">
<summary>
返回状态码,错误码SUCCESS为清算机构接收成功其他错误码为失败。
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayCallbackViewModel.message">
<summary>
返回信息,如非空,为错误原因。
</summary>
</member>
<member name="T:New_College.Model.ViewModels.WxPayNotifyModel">
<summary>
微信支付结果回调通知实体
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayNotifyModel.id">
<summary>
通知的唯一ID
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayNotifyModel.create_time">
<summary>
通知创建时间,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONEYYYY-MM-DD表示年月日T出现在字符串中表示time元素的开头HH:mm:ss.表示时分秒TIMEZONE表示时区+08:00表示东八区时间领先UTC 8小时即北京时间。例如2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒。
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayNotifyModel.event_type">
<summary>
通知的类型支付成功通知的类型为TRANSACTION.SUCCESS
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayNotifyModel.resource_type">
<summary>
通知的资源数据类型支付成功通知为encrypt-resource
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayNotifyModel.resource">
<summary>
通知资源数据,json格式
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayNotifyModel.summary">
<summary>
回调摘要
</summary>
</member>
<member name="T:New_College.Model.ViewModels.WxPayResourceModel">
<summary>
微信支付回调通知结果resource实体
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceModel.algorithm">
<summary>
对开启结果数据进行加密的加密算法目前只支持AEAD_AES_256_GCM
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceModel.ciphertext">
<summary>
Base64编码后的开启/停用结果数据密文
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceModel.associated_data">
<summary>
附加数据
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceModel.original_type">
<summary>
原始回调类型为transaction
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceModel.nonce">
<summary>
加密使用的随机串
</summary>
</member>
<member name="T:New_College.Model.ViewModels.WxPayResourceDecryptModel">
<summary>
微信支付回调通知结果解密实体
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.appid">
<summary>
直连商户申请的公众号或移动应用appid
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.mchid">
<summary>
商户的商户号,由微信支付生成并下发。
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.out_trade_no">
<summary>
商户系统内部订单号只能是数字、大小写字母_-*且在同一个商户号下唯一。特殊规则最小字符长度为6
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.transaction_id">
<summary>
微信支付系统生成的订单号。
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.trade_state">
<summary>
交易状态,枚举值:
SUCCESS支付成功
REFUND转入退款
NOTPAY未支付
CLOSED已关闭
REVOKED已撤销付款码支付
USERPAYING用户支付中付款码支付
PAYERROR支付失败(其他原因,如银行返回失败)
ACCEPT已接收等待扣款
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.trade_state_desc">
<summary>
交易状态描述
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayResourceDecryptModel.payer">
<summary>
支付者信息
</summary>
</member>
<member name="T:New_College.Model.ViewModels.WxPayerResourceDecryptModel">
<summary>
支付用户信息实体
</summary>
</member>
<member name="P:New_College.Model.ViewModels.WxPayerResourceDecryptModel.openid">
<summary>
用户在直连商户appid下的唯一标识。
</summary>
</member>
<member name="P:New_College.Model.OccupationMapJobInfoRequest.OccupName">
<summary>
职位名称

View File

@ -120,6 +120,13 @@
服务器接口,因为是模板生成,所以首字母是大写的,自己可以重构下
</summary>
</member>
<member name="M:New_College.Api.Controllers.D_PlanMajorDescController.GetAIPerview(New_College.Model.ViewModels.OneSubmitGoRequest)">
<summary>
智能填报预览图
</summary>
<param name="request"></param>
<returns></returns>
</member>
<member name="M:New_College.Api.Controllers.D_PlanMajorDescController.GetMajorPlanPro(New_College.Model.ViewModels.MajorPlanProViewQuery)">
<summary>
查询扩缩招院校招生计划详情
@ -1003,12 +1010,19 @@
</summary>
<returns></returns>
</member>
<member name="M:New_College.Api.Controllers.Front.WeixinPayController.PayNotify">
<member name="M:New_College.Api.Controllers.Front.WeixinPayController.OldPayNotify">
<summary>
支付返回值
</summary>
<returns></returns>
</member>
<member name="M:New_College.Api.Controllers.Front.WeixinPayController.NewPayNotify(New_College.Api.Controllers.Front.WeChatPayCallobject)">
<summary>
暂时不用有bug
</summary>
<param name="model"></param>
<returns></returns>
</member>
<member name="F:New_College.Api.Controllers.HighSchoolRankController._d_HighSchoolRankServices">
<summary>
服务器接口,因为是模板生成,所以首字母是大写的,自己可以重构下

View File

@ -234,7 +234,7 @@
// APIv3APIv3
"APIv3Key": "brapuk6fon0wachiMlth2t3lb4a0h7ji",
//
"NotifyUrl": "https://pay.ycymedu.com/api/notify/transactions",
"NotifyUrl": "https://zytb.ycymedu.com/api/front/WeixinPay/PayNotify",
"PrivateKey": "/cert/apiclient_cert.p12", //
"SerialNumber": "1B304596B953D156B37863FF52FCAE40B458C9F2" //
}

View File

@ -234,7 +234,7 @@
// APIv3APIv3
"APIv3Key": "brapuk6fon0wachiMlth2t3lb4a0h7ji",
//
"NotifyUrl": "https://pay.ycymedu.com/api/notify/transactions",
"NotifyUrl": "https://zytb.ycymedu.com/api/front/WeixinPay/PayNotify",
"PrivateKey": "cert/apiclient_cert.p12", //
"SerialNumber": "1B304596B953D156B37863FF52FCAE40B458C9F2" //
}

View File

@ -0,0 +1,36 @@
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace New_College.Common.Helper
{
public class AesGcmHelper
{
private static string ALGORITHM = "AES/GCM/NoPadding";
private static int TAG_LENGTH_BIT = 128;
private static int NONCE_LENGTH_BYTE = 12;
//private static string AES_KEY = "yourkeyhere";//换成你的API V3密钥
public static string AesGcmDecrypt(string associatedData, string nonce, string ciphertext,string AES_KEY)
{
GcmBlockCipher gcmBlockCipher = new GcmBlockCipher(new AesEngine());
AeadParameters aeadParameters = new AeadParameters(
new KeyParameter(Encoding.UTF8.GetBytes(AES_KEY)),
128,
Encoding.UTF8.GetBytes(nonce),
Encoding.UTF8.GetBytes(associatedData));
gcmBlockCipher.Init(false, aeadParameters);
byte[] data = Convert.FromBase64String(ciphertext);
byte[] plaintext = new byte[gcmBlockCipher.GetOutputSize(data.Length)];
int length = gcmBlockCipher.ProcessBytes(data, 0, data.Length, plaintext, 0);
gcmBlockCipher.DoFinal(plaintext, length);
return Encoding.UTF8.GetString(plaintext);
}
}
}

View File

@ -6,9 +6,8 @@ using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using ZXing;
using ZXing.Common;
using QRCoder;
using RestSharp.Extensions;
namespace New_College.Common
{
public static class QrCodeHelper
@ -18,61 +17,25 @@ namespace New_College.Common
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
public static MemoryStream GerQrCodeStream(string url)
public static byte[] GerQrCodeStream(string url)
{
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 300, 300);
var bw = new ZXing.BarcodeWriterPixelData();
var pixelData = bw.Write(bitMatrix);
var bitmap = new System.Drawing.Bitmap(pixelData.Width, pixelData.Height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
var fileStream = new MemoryStream();
var bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, pixelData.Width, pixelData.Height), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try
{
// we assume that the row stride of the bitmap is aligned to 4 byte multiplied by the width of the image
System.Runtime.InteropServices.Marshal.Copy(pixelData.Pixels, 0, bitmapData.Scan0, pixelData.Pixels.Length);
}
finally
{
bitmap.UnlockBits(bitmapData);
// 创建 QRCodeGenerator 实例
QRCodeGenerator qrGenerator = new QRCodeGenerator();
// 创建 QRCodeData 实例
QRCodeData qrCodeDataObject = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
// 创建 PngByteQRCode 实例
PngByteQRCode qrCode = new PngByteQRCode(qrCodeDataObject);
// 获取二维码图片的字节数组
var qrCodeImageBytes = qrCode.GetGraphic(8); // 图片大小
return qrCodeImageBytes;
}
fileStream.Flush();//.net core 必须要加
fileStream.Position = 0;//.net core 必须要加
bitmap.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png);
fileStream.Seek(0, SeekOrigin.Begin);
return fileStream;
}
/// <summary>
/// 获取文字图片信息
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
public static MemoryStream GetTextImageStream(string text)
{
MemoryStream fileStream = new MemoryStream();
var fontSize = 14;
var wordLength = 0;
for (int i = 0; i < text.Length; i++)
{
byte[] bytes = Encoding.Default.GetBytes(text.Substring(i, 1));
wordLength += bytes.Length > 1 ? 2 : 1;
}
using (var bitmap = new System.Drawing.Bitmap(wordLength * fontSize + 20, 14 + 40, System.Drawing.Imaging.PixelFormat.Format32bppRgb))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.ResetTransform();//重置图像
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.DrawString(text, new Font("宋体", fontSize, FontStyle.Bold), Brushes.White, 10, 10);
bitmap.Save(fileStream, System.Drawing.Imaging.ImageFormat.Png);
}
}
fileStream.Seek(0, SeekOrigin.Begin);
return fileStream;
}
}
}

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace New_College.Common.Helper
{
public class WeChatPaySignatureValidator
{
private readonly string appId;
private readonly string mchId;
private readonly string apiKey;
//public WeChatPaySignatureValidator(string appId, string mchId, string apiKey)
//{
// this.appId = appId;
// this.mchId = mchId;
// this.apiKey = apiKey;
//}
public static bool VerifySignature(string returnCode, string returnMsg, string appId, string mchId, string nonceStr, string sign, string resultCode)
{
// 获取微信支付回调的全部参数,包括商户自定义参数等。
var allParams = new SortedDictionary<string, string>
{
{"return_code", returnCode},
{"return_msg", returnMsg},
{"appid", appId},
{"mch_id", mchId},
{"nonce_str", nonceStr},
{"sign", sign},
{"result_code", resultCode}
// 这里可以添加其他商户自定义的参数,并按照字典序排序。
};
// 将所有参数按照键值对的形式拼接成一个字符串。
var strToBeSigned = JoinByKey(allParams);
// 验证签名如果验证通过则返回true否则返回false。
return CheckSignature(strToBeSigned, WeixinConfig.APIv3Key);
}
private static string JoinByKey(SortedDictionary<string, string> dict)
{
var sb = new StringBuilder();
foreach (var kv in dict)
{
sb.Append(kv.Key);
sb.Append("=");
sb.Append(kv.Value);
sb.Append("&");
}
// 去掉最后一个"&"字符。
if (sb.Length > 0) sb.Length -= 1;
return sb.ToString();
}
private static bool CheckSignature(string strToBeSigned, string apiSecret)
{
// 使用商户的API密钥进行签名验证。这里使用SHA256算法进行加密。
using (var sha256 = SHA256.Create())
{
var dataToBeSigned = Encoding.UTF8.GetBytes(strToBeSigned);
var dataSigned = sha256.ComputeHash(dataToBeSigned);
var dataSignedBase64 = Convert.ToBase64String(dataSigned);
return apiSecret == dataSignedBase64; // 这里将签名结果与商户的API密钥进行比对。如果比对成功则签名验证通过。
}
}
}
}

View File

@ -26,10 +26,10 @@ namespace New_College.Common.Helper
/// 扫码支付-Native下单API
/// </summary>
/// <returns></returns>
public static async Task<MemoryStream> QrCodePay(string outorderNo, decimal Price, string title)
public static async Task<byte[]> QrCodePay(string outorderNo, decimal Price, string title)
{
////使用 Native 支付,输出二维码并展示
MemoryStream fileStream = null;//输出图片的URL
byte[] fileStream = null;//输出图片的URL
var price = (int)(Price * 100);
var name = title + "-扫码支付";
WechatPayHelper.pay_config = new WechatPayConfig()
@ -60,7 +60,7 @@ namespace New_College.Common.Helper
}
else
{
fileStream = QrCodeHelper.GetTextImageStream("Native Pay 未能通过签名验证,无法显示二维码");
// fileStream = QrCodeHelper.GetTextImageStream("Native Pay 未能通过签名验证,无法显示二维码");
}
return fileStream;
}

View File

@ -22,6 +22,7 @@
<PackageReference Include="NPOI" Version="2.6.0" />
<PackageReference Include="OSS.Clients.Pay.Wechat" Version="2.4.0" />
<PackageReference Include="PdfSharpCore" Version="1.3.62" />
<PackageReference Include="QRCoder" Version="1.4.3" />
<PackageReference Include="RestSharp" Version="106.15.0" />
<PackageReference Include="StackExchange.Redis" Version="2.1.30" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.5.0" />
@ -30,7 +31,6 @@
<PackageReference Include="Serilog.AspNetCore" Version="3.3.0-dev-00152" />
<PackageReference Include="WebApiClient.Extensions.DependencyInjection" Version="2.0.3" />
<PackageReference Include="WebApiClient.JIT" Version="1.1.3" />
<PackageReference Include="ZXing.Net" Version="0.16.9" />
</ItemGroup>

View File

@ -16,7 +16,7 @@ namespace New_College.IServices
{
Task<MemoryStream> QrCodePay(WeChatPayTransactionsNativeQuery viewModel);
Task<byte[]> QrCodePay(WeChatPayTransactionsNativeQuery viewModel);
Task<CreateOrderModel> CreateOrder(UniOrderQuery query);

View File

@ -0,0 +1,47 @@
using NPOI.OpenXmlFormats.Dml.Diagram;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace New_College.Model.ViewModels
{
public class AIPerviewDto
{
/// <summary>
/// 院校基础数量
/// </summary>
public List<UniversityPerviewDto> universities { get; set; }
/// <summary>
/// 适合我的大学饼图数据
/// </summary>
public List<PieChatsDto> pieChats { get; set; }
}
public class PieChatsDto
{
public string name { get; set; }
public int value { get; set; }
}
public class UniversityPerviewDto
{
/// <summary>
/// 标签
/// </summary>
public string Name { get; set; }
/// <summary>
/// 学校数量
/// </summary>
public int Count { get; set; }
}
}

View File

@ -93,6 +93,11 @@ namespace New_College.Model.ViewModels
/// </summary>
public string Phone { get; set; }
/// <summary>
///
/// </summary>
public DateTime CreateTime { get; set; }
}
public class SearchOrderQuery : BasePageRequest

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace New_College.Model.ViewModels
{
public class WxPayCallbackViewModel
{
/// <summary>
/// 返回状态码,错误码SUCCESS为清算机构接收成功其他错误码为失败。
/// </summary>
public string code { set; get; } = "SUCCESS";
/// <summary>
/// 返回信息,如非空,为错误原因。
/// </summary>
public string message { set; get; } = string.Empty;
}
}

View File

@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace New_College.Model.ViewModels
{
/// <summary>
/// 微信支付结果回调通知实体
/// </summary>
public class WxPayNotifyModel
{
/// <summary>
/// 通知的唯一ID
/// </summary>
public string id { set; get; }
/// <summary>
/// 通知创建时间,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONEYYYY-MM-DD表示年月日T出现在字符串中表示time元素的开头HH:mm:ss.表示时分秒TIMEZONE表示时区+08:00表示东八区时间领先UTC 8小时即北京时间。例如2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒。
/// </summary>
public string create_time { set; get; }
/// <summary>
/// 通知的类型支付成功通知的类型为TRANSACTION.SUCCESS
/// </summary>
public string event_type { set; get; }
/// <summary>
/// 通知的资源数据类型支付成功通知为encrypt-resource
/// </summary>
public string resource_type { set; get; }
/// <summary>
/// 通知资源数据,json格式
/// </summary>
public WxPayResourceModel resource { set; get; }
/// <summary>
/// 回调摘要
/// </summary>
public string summary { set; get; }
}
/// <summary>
/// 微信支付回调通知结果resource实体
/// </summary>
public class WxPayResourceModel
{
/// <summary>
/// 对开启结果数据进行加密的加密算法目前只支持AEAD_AES_256_GCM
/// </summary>
public string algorithm { set; get; }
/// <summary>
/// Base64编码后的开启/停用结果数据密文
/// </summary>
public string ciphertext { set; get; }
/// <summary>
/// 附加数据
/// </summary>
public string associated_data { set; get; }
/// <summary>
/// 原始回调类型为transaction
/// </summary>
public string original_type { set; get; }
/// <summary>
/// 加密使用的随机串
/// </summary>
public string nonce { set; get; }
}
/// <summary>
/// 微信支付回调通知结果解密实体
/// </summary>
public class WxPayResourceDecryptModel
{
/// <summary>
/// 直连商户申请的公众号或移动应用appid
/// </summary>
public string appid { set; get; }
/// <summary>
/// 商户的商户号,由微信支付生成并下发。
/// </summary>
public string mchid { set; get; }
/// <summary>
/// 商户系统内部订单号只能是数字、大小写字母_-*且在同一个商户号下唯一。特殊规则最小字符长度为6
/// </summary>
public string out_trade_no { set; get; }
/// <summary>
/// 微信支付系统生成的订单号。
/// </summary>
public string transaction_id { set; get; }
/// <summary>
/// 交易状态,枚举值:
/// SUCCESS支付成功
/// REFUND转入退款
/// NOTPAY未支付
/// CLOSED已关闭
/// REVOKED已撤销付款码支付
/// USERPAYING用户支付中付款码支付
/// PAYERROR支付失败(其他原因,如银行返回失败)
/// ACCEPT已接收等待扣款
/// </summary>
public string trade_state { get; set; }
/// <summary>
/// 交易状态描述
/// </summary>
public string trade_state_desc { get; set; }
/// <summary>
/// 支付者信息
/// </summary>
public WxPayerResourceDecryptModel payer { set; get; }
}
/// <summary>
/// 支付用户信息实体
/// </summary>
public class WxPayerResourceDecryptModel
{
/// <summary>
/// 用户在直连商户appid下的唯一标识。
/// </summary>
public string openid { get; set; }
}
}

View File

@ -120,7 +120,7 @@ namespace New_College.Services
var responselist = query.data.Select(c => new AIGOResponse()
{
AreaName = c.AreaName,
Rank = c.OrderSort > 9999 ? "--" : c.OrderSort.ToString(),
Rank = c.Rank > 9999 ? "--" : c.Rank.ToString(),
_985 = c._985,
_211 = c._211,
_SYL = c._SYL,

View File

@ -241,6 +241,7 @@ namespace New_College.Services
AreaName = info.AreaName,
Datainit = info.Datainit,
Expectedscore = info.Expectedscore,
Phone = info.Phone,
Rank = info.Rank,
IsVIP = info.IsVIP,
Subject = info.Subject,

View File

@ -59,7 +59,7 @@ namespace New_College.Services
/// 扫码支付-Native下单API
/// </summary>
/// <param name="viewModel"></param>
public async Task<MemoryStream> QrCodePay(WeChatPayTransactionsNativeQuery viewModel)
public async Task<byte[]> QrCodePay(WeChatPayTransactionsNativeQuery viewModel)
{
var orderNo = OrderGenerateHelper.GenerateOrderNo("ZY");//outorderNo//系统创建订单逻辑
Random rd = new Random();
@ -107,14 +107,17 @@ namespace New_College.Services
}
else
{
return QrCodeHelper.GetTextImageStream("baseResult<0无法显示二维码");
// return QrCodeHelper.GetTextImageStream("baseResult<0无法显示二维码");
return new byte[0];
}
}
catch (System.Exception ex)
{
_unitOfWork.RollbackTran();
// response.msg = "订单创建失败";
return QrCodeHelper.GetTextImageStream(ex.Message);
// return QrCodeHelper.GetTextImageStream(ex.Message);
throw ex;
}
@ -299,38 +302,24 @@ namespace New_College.Services
success = false,
msg = "获取失败"
};
var idsCard = info.data.Select(x => x.CardTypeId).ToList();
var idsCoustomer = info.data.Select(x => x.CustomerId).ToList();
var listCard = await v_VipCardTypeRepository.Query(x => idsCard.Contains(x.Id) && x.IsDelete == false);
var listCoustomer = await v_CustomerInfoRepository.Query(x => idsCoustomer.Contains(x.Id) && x.IsDelete == false);
PageModel<OrderInfoQuery> pageModel = new PageModel<OrderInfoQuery>() { };
List<OrderInfoQuery> list = new List<OrderInfoQuery>() { };
foreach (var item in info.data)
{
var CardOne = listCard.Where(x => x.Id == item.CardTypeId).FirstOrDefault();
if (CardOne == null)
continue;
var CoustomerOne = listCoustomer.Where(x => x.Id == item.CustomerId).FirstOrDefault();
if (CoustomerOne == null)
continue;
list.Add(new OrderInfoQuery()
{
CardId = item.Id,
PayPrice = item.PayPrice,
Price = item.Price,
CardNo = item.CardNo,
CardTypeName = CardOne.Name,
OrderId = item.OrderId,
CustomerName = CoustomerOne.NickName,
Name = item.Name,
//支付状态
StatusName = item.Status.GetDescription(),
out_trade_no = item.out_trade_no,
//支付方式
PayTypeName = item.PayType.GetDescription(),
Phone = CoustomerOne.Phone,
CreateTime = item.CreateTime.Value
});
}
pageModel.data = list;