NewGaoKaoApi/New_College.Common/Helper/WeChatPayV3Helper.cs

213 lines
8.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OSS.Clients.Pay.Wechat;
using OSS.Clients.Pay.Wechat.Basic;
using StackExchange.Redis;
namespace New_College.Common.Helper
{
public static class WeChatPayV3
{
/// <summary>
/// 扫码支付-Native下单API
/// </summary>
/// <returns></returns>
public static async Task<byte[]> QrCodePay(string outorderNo, decimal Price, string title)
{
////使用 Native 支付,输出二维码并展示
byte[] fileStream = null;//输出图片的URL
var price = (int)(Price * 100);
var name = title + "-扫码支付";
WechatPayHelper.pay_config = new WechatPayConfig()
{
app_id = WeixinConfig.Appid,
mch_id = WeixinConfig.MCHID,
api_key = WeixinConfig.Secret,
api_v3_key = WeixinConfig.KEY,
cert_path = WeixinConfig.PrivateKey,
cert_password = WeixinConfig.MCHID
};
var nResp = await new WechatNativePayReq()
{
description = name,
out_trade_no = outorderNo,
notify_url = WeixinConfig.NotifyUrl,
amount = new WechatPayAmount() { currency = "CNY", total = price }
}
// .SetContextConfig(new WechatPayConfig(){}) // 可以设置当前上下文的配置信息,设置后本次请求将使用此配置,方便多应用的用户
//.AddOptionalBodyPara("attach","附加数据") // 添加可选参数
.SendAsync();//
//系统创建订单逻辑
//var result = await basePayApis.NativeAsync(requestData);
////进行安全签名验证
if (!string.IsNullOrEmpty(nResp.code_url))
{
fileStream = QrCodeHelper.GerQrCodeStream(nResp.code_url);
}
else
{
// fileStream = QrCodeHelper.GetTextImageStream("Native Pay 未能通过签名验证,无法显示二维码");
}
return fileStream;
}
/**
*
* 统一下单
* @param WxPaydata inputObj 提交给统一下单API的参数
* @param int timeOut 超时时间
* @throws WePayException
* @return 成功时返回,其他抛异常
*/
public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 60)
{
string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//检测必填参数
if (!inputObj.IsSet("out_trade_no"))
{
throw new Exception("缺少统一支付接口必填参数out_trade_no");
}
else if (!inputObj.IsSet("body"))
{
throw new Exception("缺少统一支付接口必填参数body");
}
else if (!inputObj.IsSet("total_fee"))
{
throw new Exception("缺少统一支付接口必填参数total_fee");
}
else if (!inputObj.IsSet("trade_type"))
{
throw new Exception("缺少统一支付接口必填参数trade_type");
}
//关联参数
if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
{
throw new Exception("统一支付接口中缺少必填参数openidtrade_type为JSAPI时openid为必填参数");
}
if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
{
throw new Exception("统一支付接口中缺少必填参数product_idtrade_type为JSAPI时product_id为必填参数");
}
//异步通知url未设置则使用配置文件中的url
if (!inputObj.IsSet("notify_url"))
{
inputObj.SetValue("notify_url", WeixinConfig.NotifyUrl);//异步通知url
}
inputObj.SetValue("appid", WeixinConfig.Appid);//公众账号ID
inputObj.SetValue("mch_id", WeixinConfig.MCHID);//商户号
inputObj.SetValue("spbill_create_ip", WePayConfig.IP);//终端ip
inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
//签名
inputObj.SetValue("sign", inputObj.MakeSign());
string xml = inputObj.ToXml();
var start = DateTime.Now;
// Log.Info("XcxPayApi", "UnfiedOrder request : " + xml);
string response = HttpPost(xml, url, "application/xml", timeOut);
//Log.Info("XcxPayApi", "UnfiedOrder response : " + response);
// WebHookHelper.WebHookmarkdownSend(response);
var end = DateTime.Now;
int timeCost = (int)((end - start).TotalMilliseconds);
WxPayData result = new WxPayData();
result.FromXml(response);
// ReportCostTime(url, timeCost, result);//测速上报网络不好时使用
return result;
}
/// <summary>
/// 生成随机数
/// </summary>
/// <returns></returns>
public static string GenerateNonceStr()
{
return Guid.NewGuid().ToString().Replace("-", "");
}
/// <summary>
/// POST请求
/// </summary>
/// <param name="postData"></param>
/// <param name="url"></param>
/// <param name="contentType">application/xml、application/json、application/text、application/x-www-form-urlencoded</param>
/// <param name="timeOut"></param>
/// <param name="headers"></param>
/// <returns></returns>
public static string HttpPost(string postData, string url, string contentType = null, int timeOut = 30, Dictionary<string, string> headers = null)
{
postData = postData ?? "";
var httpClientHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true
};
using (HttpClient httpClient = new HttpClient(httpClientHandler))
{
if (headers != null)
{
foreach (var header in headers)
httpClient.DefaultRequestHeaders.Add(header.Key, header.Value);
}
using (HttpContent client = new StringContent(postData, Encoding.UTF8))
{
if (contentType != null)
client.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
HttpResponseMessage response = httpClient.PostAsync(url, client).Result;
return response.Content.ReadAsStringAsync().Result;
}
}
}
}
/// <summary>
///
/// </summary>
public class WePayConfig
{
//=======【商户系统后台机器IP】=====================================
/* 此参数可手动配置也可在程序中自动获取
*/
public const string IP = "8.8.8.8";
//=======【代理服务器设置】===================================
/* 默认IP和端口号分别为0.0.0.0和0此时不开启代理如有需要才设置
*/
public const string PROXY_URL = "";
//=======【上报信息配置】===================================
/* 测速上报等级0.关闭上报; 1.仅错误时上报; 2.全量上报
*/
public const int REPORT_LEVENL = 1;
//=======【日志级别】===================================
/* 日志等级0.不输出日志1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息
*/
public const int LOG_LEVENL = 3;
}
}