|
@@ -1,14 +1,18 @@
|
|
|
-using Microsoft.AspNetCore.Cors;
|
|
|
+using Lib.AspNetCore.ServerSentEvents;
|
|
|
+using Microsoft.AspNetCore.Cors;
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
using Microsoft.Extensions.Options;
|
|
|
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
|
|
|
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
|
|
|
using System;
|
|
|
+using System.Text;
|
|
|
using System.Text.Json;
|
|
|
using System.Threading.Tasks;
|
|
|
+using System.Web;
|
|
|
using TEAMModelOS.Filter;
|
|
|
using TEAMModelOS.SDK.DI;
|
|
|
using TEAMModelOS.SDK.Extension;
|
|
|
+using TEAMModelOS.SDK.Models;
|
|
|
|
|
|
namespace TEAMModelOS.Controllers
|
|
|
{/// <summary>
|
|
@@ -21,58 +25,114 @@ namespace TEAMModelOS.Controllers
|
|
|
private readonly DingDing _dingDing;
|
|
|
private readonly WeChatPayFactory _weChatPayFactory;
|
|
|
private readonly SnowflakeId _snowflakeId;
|
|
|
- public WeChatPayController(WeChatPayFactory weChatPayFactory, SnowflakeId snowflakeId,DingDing dingDing) {
|
|
|
+ private readonly ServerSentEventsService _sse;
|
|
|
+ private readonly AzureCosmosFactory _azureCosmosFactory;
|
|
|
+ public WeChatPayController(WeChatPayFactory weChatPayFactory, SnowflakeId snowflakeId,DingDing dingDing, ServerSentEventsService sse, AzureCosmosFactory azureCosmosFactory) {
|
|
|
_weChatPayFactory = weChatPayFactory;
|
|
|
_snowflakeId=snowflakeId;
|
|
|
_dingDing = dingDing;
|
|
|
+ _sse = sse;
|
|
|
+ _azureCosmosFactory = azureCosmosFactory;
|
|
|
}
|
|
|
+ [EnableCors("AllowSpecificOrigin")]
|
|
|
+ [HttpPost("sse-bind")]
|
|
|
+ public async Task<IActionResult> SSEBind(JsonElement json)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ if (!json.TryGetProperty("client_id", out JsonElement _client_id))
|
|
|
+ {
|
|
|
+ return Ok(new { code = 400, msg = "客户端参数错误" });
|
|
|
+ }
|
|
|
+ if (!json.TryGetProperty("order_no", out JsonElement _order_no))
|
|
|
+ {
|
|
|
+ return Ok(new { code = 400, msg = "订单号错误" });
|
|
|
+ }
|
|
|
+ IServerSentEventsClient sseClient;
|
|
|
+ if ((sseClient = _sse.GetClient(new Guid($"{_client_id}"))) != null)
|
|
|
+ {
|
|
|
+ Azure.Response response = await _azureCosmosFactory.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemStreamAsync($"{_order_no}", new Azure.Cosmos.PartitionKey("TMDOrder"));
|
|
|
+ if (response.Status==200)
|
|
|
+ {
|
|
|
+ TMDOrder order= JsonDocument.Parse(response.Content).RootElement.ToObject<TMDOrder>();
|
|
|
+ if (order!=null)
|
|
|
+ {
|
|
|
+ order.process=1;
|
|
|
+ order.client_id=$"{_client_id}";
|
|
|
+ await _azureCosmosFactory.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync(order, new Azure.Cosmos.PartitionKey(order.code));
|
|
|
+ return Ok(new { code = 200, msg = "绑定成功" });
|
|
|
+ }
|
|
|
+ else { return Ok(new { code = 404, msg = "订单不存在" }); }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Ok(new { code = 404, msg = "订单不存在" });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return Ok(new { code = 400, msg = "客户端不存在" });
|
|
|
+ }
|
|
|
+ } catch (Exception ex) {
|
|
|
+ return Ok(new { code = 500, msg = ex.Message });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
[EnableCors("AllowSpecificOrigin")]
|
|
|
[HttpPost("pay-qrcode-url")]
|
|
|
public async Task<IActionResult> QrcodeUrl(JsonElement json) {
|
|
|
//jwt, 产品序列号
|
|
|
var client= _weChatPayFactory.GetWechatTenpayClient();
|
|
|
|
|
|
- string orderId = $"1595321354-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}";
|
|
|
- int total =0;
|
|
|
- if (json.TryGetProperty("total", out JsonElement _total) && _total.ValueKind.Equals(JsonValueKind.Number))
|
|
|
+ TMDOrder order= json.ToObject<TMDOrder>();
|
|
|
+ if (order!=null && !string.IsNullOrWhiteSpace(order.order_no) && order.amount>0)
|
|
|
{
|
|
|
- total=_total.GetInt32();
|
|
|
- }
|
|
|
- else {
|
|
|
- return Ok(new { code = 400, errorCode ="400", errorMessage = "必须设置金额" });
|
|
|
- }
|
|
|
- if (total<=0) {
|
|
|
- return Ok(new { code = 400, errorCode = "400", errorMessage = "必须设置金额" });
|
|
|
- }
|
|
|
- var request = new CreatePayTransactionNativeRequest()
|
|
|
- {
|
|
|
- OutTradeNumber =orderId,
|
|
|
- AppId = "wx0e64117a6937dc02",
|
|
|
- Description =json.TryGetProperty("description", out JsonElement _Description) ? _Description.ToString(): "订单描述",
|
|
|
- ExpireTime = DateTimeOffset.Now.AddMinutes(10),
|
|
|
- NotifyUrl = "https://test.teammodel.cn/wechat/pay-notify",
|
|
|
- Amount = new CreatePayTransactionNativeRequest.Types.Amount()
|
|
|
+
|
|
|
+ var request = new CreatePayTransactionNativeRequest()
|
|
|
+ {
|
|
|
+ OutTradeNumber =order.order_no,
|
|
|
+ AppId = "wx0e64117a6937dc02",
|
|
|
+ Description =order.item_desc,
|
|
|
+ ExpireTime = DateTimeOffset.Now.AddMinutes(10),
|
|
|
+ NotifyUrl = "https://test.teammodel.cn/wechat/pay-notify",
|
|
|
+ Amount = new CreatePayTransactionNativeRequest.Types.Amount()
|
|
|
+ {
|
|
|
+ Total = order.amount
|
|
|
+ }
|
|
|
+ };
|
|
|
+ var response = await client.ExecuteCreatePayTransactionNativeAsync(request);
|
|
|
+ if (response.IsSuccessful())
|
|
|
{
|
|
|
- Total = total
|
|
|
+ order.qrcode_url=response.QrcodeUrl;
|
|
|
+ order.id=order.id;
|
|
|
+ order.pk="TMDOrder";
|
|
|
+ order.code="TMDOrder";
|
|
|
+ order.ttl=-1;
|
|
|
+ order.qrcode_time=DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
|
|
+ await _azureCosmosFactory.GetCosmosClient().GetContainer(Constant.TEAMModelOS,Constant.Normal).UpsertItemAsync(order,new Azure.Cosmos.PartitionKey(order.code));
|
|
|
+ return Redirect($"https://teammodeltest.blob.core.chinacloudapi.cn/0-public/index_cn.html?order_no={order.order_no}&amount={order.amount}&count=1&buyer_name={HttpUtility.UrlEncode(order.buyer_name, Encoding.UTF8)}&item_desc={HttpUtility.UrlEncode(order.item_desc, Encoding.UTF8)}&buyer_tmid={order.buyer_tmid}&item_desc={HttpUtility.UrlEncode(order.return_url, Encoding.UTF8)}&buyer_email={HttpUtility.UrlEncode(order.buyer_email, Encoding.UTF8)}");
|
|
|
+ //return Ok(new { code = 200, qrcodeUrl = response.QrcodeUrl, orderId = orderId });
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Ok(new { code = 400, errorCode = response.ErrorCode, errorMessage = response.ErrorMessage });
|
|
|
}
|
|
|
- };
|
|
|
- var response = await client.ExecuteCreatePayTransactionNativeAsync(request);
|
|
|
- if (response.IsSuccessful())
|
|
|
- {
|
|
|
- return Ok(new { code = 200, qrcodeUrl= response.QrcodeUrl, orderId = orderId });
|
|
|
}
|
|
|
else {
|
|
|
- return Ok(new { code = 400, errorCode = response.ErrorCode, errorMessage = response.ErrorMessage });
|
|
|
+ return Ok(new { code = 400, errorCode = "400", errorMessage = "参数错误" });
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
+ [EnableCors("AllowSpecificOrigin")]
|
|
|
[ProducesDefaultResponseType]
|
|
|
[HttpPost("pay-notify")]
|
|
|
public async Task<IActionResult> PayNotify(JsonElement json)
|
|
|
{
|
|
|
try {
|
|
|
+ IServerSentEventsClient sseClient;
|
|
|
await _dingDing.SendBotMsg($"微信支付通知(原始数据):{json.ToJsonString()}", GroupNames.成都开发測試群組);
|
|
|
var client = _weChatPayFactory.GetWechatTenpayClient();
|
|
|
var callbackModel = client.DeserializeEvent(json.ToJsonString());
|
|
|
+ string orderId = "";
|
|
|
if ("TRANSACTION.SUCCESS".Equals(callbackModel.EventType))
|
|
|
{
|
|
|
/* 根据事件类型,解密得到支付通知敏感数据 */
|
|
@@ -94,7 +154,31 @@ namespace TEAMModelOS.Controllers
|
|
|
callbackResource.Scene,
|
|
|
callbackResource.PromotionList
|
|
|
};
|
|
|
+ orderId= callbackResource.OutTradeNumber;
|
|
|
await _dingDing.SendBotMsg($"微信支付通知(解析数据):{data.ToJsonString()}", GroupNames.成都开发測試群組);
|
|
|
+ Azure.Response response = await _azureCosmosFactory.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemStreamAsync(orderId, new Azure.Cosmos.PartitionKey("TMDOrder"));
|
|
|
+ if (response.Status==200)
|
|
|
+ {
|
|
|
+ TMDOrder order = JsonDocument.Parse(response.Content).RootElement.ToObject<TMDOrder>();
|
|
|
+ if (order!=null)
|
|
|
+ {
|
|
|
+ order.process=3;
|
|
|
+ order.transaction_id=callbackResource.TransactionId;
|
|
|
+ order.status=1;
|
|
|
+ order.msg=callbackResource.TradeStateDescription;
|
|
|
+ order.pay_time=callbackResource.SuccessTime.ToUnixTimeMilliseconds();
|
|
|
+ order.pay_amount=callbackResource.Amount.Total;
|
|
|
+ order.pay_type=callbackResource.TradeType;
|
|
|
+ order.openid=callbackResource.Payer.OpenId;
|
|
|
+ await _azureCosmosFactory.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync(order, new Azure.Cosmos.PartitionKey(order.code));
|
|
|
+ if (!string.IsNullOrWhiteSpace(order.client_id)) {
|
|
|
+ if ((sseClient = _sse.GetClient(new Guid(order.client_id))) != null)
|
|
|
+ {
|
|
|
+ await sseClient.SendEventAsync(new { data, grant_type = "pay_success" }.ToJsonString());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
else {
|
|
|
await _dingDing.SendBotMsg($"微信支付通知(解析数据)支付失败结果:{callbackModel.EventType}", GroupNames.成都开发測試群組);
|
|
@@ -103,8 +187,62 @@ namespace TEAMModelOS.Controllers
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
await _dingDing.SendBotMsg($"微信支付通知异常:{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
|
|
|
+ return Ok();
|
|
|
}
|
|
|
return Ok();
|
|
|
}
|
|
|
}
|
|
|
+ public class TMDOrder :CosmosEntity{
|
|
|
+ public string merchant_id { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 下单时间
|
|
|
+ /// </summary>
|
|
|
+ public long timestamp { get; set; }
|
|
|
+ public string lang_type { get; set; }
|
|
|
+ public string order_no { get; set; }
|
|
|
+ public int amount { get; set; }
|
|
|
+ public string item_desc { get; set; }
|
|
|
+ public string buyer_name { get; set; }
|
|
|
+ public string buyer_tmid { get; set; }
|
|
|
+ public string buyer_email { get; set; }
|
|
|
+ public string return_url { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 微信支付二维码
|
|
|
+ /// </summary>
|
|
|
+ public string qrcode_url { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 微信支付流水号
|
|
|
+ /// </summary>
|
|
|
+ public string transaction_id { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 0未支付,1支付成功,2支付失败
|
|
|
+ /// </summary>
|
|
|
+ public int status { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 扫码状态 0未连接,1已连接,2已过期 3已扫码支付
|
|
|
+ /// </summary>
|
|
|
+ public int process { get; set; }
|
|
|
+ public long qrcode_time { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 支付结果文字描述
|
|
|
+ /// </summary>
|
|
|
+ public string msg { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 通知时间
|
|
|
+ /// </summary>
|
|
|
+ public long pay_time { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 微信支付金额
|
|
|
+ /// </summary>
|
|
|
+ public int pay_amount { get; set; }
|
|
|
+ /// <summary>
|
|
|
+ /// 支付方式 tradeType
|
|
|
+ /// </summary>
|
|
|
+ public string pay_type { get; set;}
|
|
|
+ /// <summary>
|
|
|
+ /// 微信支付的openid
|
|
|
+ /// </summary>
|
|
|
+ public string openid { get; set; }
|
|
|
+ public string client_id { get; set; }
|
|
|
+ }
|
|
|
}
|