|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Web;
|
|
|
|
|
|
using System.Runtime.Serialization;
|
|
|
using System.IO;
|
|
|
using System.Text;
|
|
|
using System.Net;
|
|
|
|
|
|
using Furion.Logging;
|
|
|
using SqlSugar;
|
|
|
using Enyim.Caching;
|
|
|
using System.Security.Cryptography;
|
|
|
/// <summary>
|
|
|
///JsApiPay 的摘要说明
|
|
|
/// </summary>
|
|
|
|
|
|
public static class JsApiPay
|
|
|
{
|
|
|
|
|
|
public static string WithDrawsToWx(string appid, string mchid, string serialNo, string openID, string partnerTradeNo, decimal totalFee)
|
|
|
{
|
|
|
|
|
|
SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
|
|
|
dic.Add("appid", appid);
|
|
|
dic.Add("out_batch_no", partnerTradeNo);
|
|
|
dic.Add("batch_name", DateTime.Now.ToString("D") + "提现记录");
|
|
|
dic.Add("batch_remark", DateTime.Now.ToString("D") + "提现记录");
|
|
|
dic.Add("total_amount", totalFee);
|
|
|
dic.Add("total_num", 1);
|
|
|
|
|
|
List<object> list = new List<object>();
|
|
|
SortedDictionary<string, object> dic1 = new SortedDictionary<string, object>();
|
|
|
dic1.Add("out_detail_no", partnerTradeNo);
|
|
|
dic1.Add("transfer_amount", totalFee);
|
|
|
dic1.Add("transfer_remark", "提现记录");
|
|
|
dic1.Add("openid", openID);
|
|
|
|
|
|
list.Add(dic1);
|
|
|
dic.Add("transfer_detail_list", list);
|
|
|
|
|
|
var url = "https://api.mch.weixin.qq.com/v3/transfer/batches";
|
|
|
string transactionsResponse = WxV3PostJson(url, Newtonsoft.Json.JsonConvert.SerializeObject(dic), mchid, serialNo);
|
|
|
//Log.Info("商户转账到零钱返回:" , transactionsResponse);
|
|
|
return transactionsResponse; ;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// V3版本请求接口
|
|
|
/// </summary>
|
|
|
/// <param name="url">微信的接口地址</param>
|
|
|
/// <param name="postData">post请求的数据,json格式 </param>
|
|
|
/// <param name="privateKey">apiclient_key.pem中的内容,不要-----BEGIN PRIVATE KEY----- -----END PRIVATE KEY-----</param>
|
|
|
/// <param name="merchantId">发起请求的商户(包括直连商户、服务商或渠道商)的商户号 mchid</param>
|
|
|
/// <param name="serialNo">商户证书号</param>
|
|
|
/// <param name="method"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string WxV3PostJson(string url, string postData, string mchId, string serialNo)
|
|
|
{
|
|
|
|
|
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
|
|
request.Method = "POST";
|
|
|
request.ContentType = "application/json;charset=UTF-8";
|
|
|
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
|
|
|
request.Accept = "application/json";
|
|
|
//Log.Info("发起开始申请商户转账到零钱请求", "发起请求1");
|
|
|
string Authorization = GetAuthorization(url, "POST", postData, mchId, serialNo);
|
|
|
request.Headers.Add("Authorization", Authorization);
|
|
|
//Log.Info("返回申请商户转账到零钱结果", Authorization);
|
|
|
byte[] paramJsonBytes;
|
|
|
paramJsonBytes = System.Text.Encoding.UTF8.GetBytes(postData);
|
|
|
request.ContentLength = paramJsonBytes.Length;
|
|
|
Stream writer;
|
|
|
try
|
|
|
{
|
|
|
writer = request.GetRequestStream();
|
|
|
}
|
|
|
catch (Exception)
|
|
|
{
|
|
|
writer = null;
|
|
|
Console.Write("连接服务器失败!");
|
|
|
}
|
|
|
writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
|
|
|
writer.Close();
|
|
|
HttpWebResponse response;
|
|
|
try
|
|
|
{
|
|
|
response = (HttpWebResponse)request.GetResponse();
|
|
|
}
|
|
|
catch (WebException ex)
|
|
|
{
|
|
|
response = ex.Response as HttpWebResponse;
|
|
|
}
|
|
|
Stream resStream = response.GetResponseStream();
|
|
|
StreamReader reader = new StreamReader(resStream);
|
|
|
string text = reader.ReadToEnd();
|
|
|
return text;
|
|
|
}
|
|
|
private static string GetAuthorization(string url, string method, string jsonParame, string mchId, string serialNo)
|
|
|
{
|
|
|
var uri = new Uri(url);
|
|
|
string urlPath = uri.PathAndQuery;
|
|
|
string nonce = Guid.NewGuid().ToString();
|
|
|
var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
|
|
|
//数据签名 HTTP请求方法\n接口地址的url\n请求时间戳\n请求随机串\n请求报文主体\n
|
|
|
method = string.IsNullOrEmpty(method) ? "" : method;
|
|
|
string message = string.Format("{0}\n{1}\n{2}\n{3}\n{4}\n", method, urlPath, timestamp, nonce, jsonParame);
|
|
|
|
|
|
//Log.Info("请求message:", message);
|
|
|
//string signTxt = Sign(message, privateKey);
|
|
|
string signTxt = Sign(message);
|
|
|
|
|
|
|
|
|
//Authorization和格式
|
|
|
string authorzationTxt = string.Format("WECHATPAY2-SHA256-RSA2048 mchid=\"{0}\",nonce_str=\"{1}\",timestamp=\"{2}\",serial_no=\"{3}\",signature=\"{4}\"",
|
|
|
mchId,
|
|
|
nonce,
|
|
|
timestamp,
|
|
|
serialNo,
|
|
|
signTxt
|
|
|
);
|
|
|
return authorzationTxt;
|
|
|
|
|
|
}
|
|
|
|
|
|
private static string Sign(string message)
|
|
|
{
|
|
|
// NOTE: 私钥不包括私钥文件起始的-----BEGIN PRIVATE KEY-----
|
|
|
// 亦不包括结尾的-----END PRIVATE KEY-----
|
|
|
string privateKey = "{你的私钥}";
|
|
|
byte[] keyData = Convert.FromBase64String(privateKey);
|
|
|
|
|
|
var rsa = RSA.Create();
|
|
|
rsa.ImportPkcs8PrivateKey(keyData, out _);
|
|
|
byte[] data = System.Text.Encoding.UTF8.GetBytes(message);
|
|
|
return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|