簽名:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_0.shtmlhtml
統一下單接口:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtmlgit
首先聲明,我這個是爲APP支付提供的接口!!!json
參考資料裏面講的比較詳細,也有官方的文檔,不過文檔不全,致使個人調試程序一直出現問題,請求微信的統一下單接口老是報400錯誤(Bad Request)。api
簽名生成參考官方代碼,代碼以下,裏面有我標註的請求接口報400錯誤緣由的代碼微信
using System; using System.IO; using System.Net.Http; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; namespace HttpHandlerDemo { // 使用方法 // HttpClient client = new HttpClient(new HttpHandler("{商戶號}", "{商戶證書序列號}")); // ... // var response = client.GetAsync("https://api.mch.weixin.qq.com/v3/certificates"); public class HttpHandler : DelegatingHandler { private readonly string merchantId; private readonly string serialNo; public HttpHandler(string merchantId, string merchantSerialNo) { InnerHandler = new HttpClientHandler(); this.merchantId = merchantId; this.serialNo = merchantSerialNo; } protected async override Task<HttpResponseMessage> SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { var auth = await BuildAuthAsync(request); string value = $"WECHATPAY2-SHA256-RSA2048 {auth}"; request.Headers.Add("Authorization", value); request.Headers.Add("Accept", "application/json");//若是缺乏這句代碼就會致使下單接口請求失敗,報400錯誤(Bad Request) request.Headers.Add("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");//若是缺乏這句代碼就會致使下單接口請求失敗,報400錯誤(Bad Request) return await base.SendAsync(request, cancellationToken); } protected async Task<string> BuildAuthAsync(HttpRequestMessage request) { string method = request.Method.ToString(); string body = ""; if (method == "POST" || method == "PUT" || method == "PATCH") { var content = request.Content; body = await content.ReadAsStringAsync();//debug的時候在這裏打個斷點,看看body的值是多少,若是跟你傳入的參數不一致,說明是有問題的,必定參考個人方法 } string uri = request.RequestUri.PathAndQuery; var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); string nonce = Path.GetRandomFileName(); string message = $"{method}\n{uri}\n{timestamp}\n{nonce}\n{body}\n"; string signature = Sign(message); return $"mchid=\"{merchantId}\",nonce_str=\"{nonce}\",timestamp=\"{timestamp}\",serial_no=\"{serialNo}\",signature=\"{signature}\""; } protected string Sign(string message) { // NOTE: 私鑰不包括私鑰文件起始的-----BEGIN PRIVATE KEY----- // 亦不包括結尾的-----END PRIVATE KEY----- string privateKey = "{你的私鑰}"; byte[] keyData = Convert.FromBase64String(privateKey); using (CngKey cngKey = CngKey.Import(keyData, CngKeyBlobFormat.Pkcs8PrivateBlob)) using (RSACng rsa = new RSACng(cngKey)) { byte[] data = System.Text.Encoding.UTF8.GetBytes(message); return Convert.ToBase64String(rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1)); } } } }
var url = "https://api.mch.weixin.qq.com/v3/pay/transactions/app"; var req = new GenerateOrderModelForWxPay { appid = WxPayConst.appid, mchid = WxPayConst.mchid, description = "商品名稱", amount = new WxPayAmountModel { total = 1 }, out_trade_no = orderNumber, notify_url = "https://xxx.com/api/WxPayCallback" }; HttpClient client = new HttpClient(new HttpHandler("{商戶號}", "{商戶證書序列號}")); //GET 方式 var response = client.GetAsync("https://api.mch.weixin.qq.com/v3/certificates"); // POST 方式 var bodyJson = new StringContent(req.ToJson(), Encoding.UTF8, "application/json"); //必定要這樣傳遞參數,否則在加密簽名的時候獲取到的參數就是\\u0這種形式的數據了,不是傳遞的這樣的數據了,致使加密的結果不正確 var response = await client.PostAsync(url, bodyJson); // 讀取統一下單以後的返回結果,這樣讀取出來的直接就是結果,或者錯誤緣由,你們必定要這麼搞啊!!!多麼痛的領悟,會有具體的錯誤信息的。 var respStr = await resp.Content.ReadAsStringAsync();//這裏面就包含prepay_id了
你們必定看接口規則裏面的說明,我就是沒有看,致使我搞了一天沒有搞通,下面貼兩個截圖
app