微信小程式支付功能的開發的時候坑比較多,不過對於錢的事謹慎也是好事。網上關於小程式支付的實例很多,但是大多多少有些問題,C#開發的更少。此篇文檔的目的是講開發過程中遇到的問題做一個備註,也方便其他開發的同學作為參考! 1、首先建議把官方文檔支付部分看上三遍,每個細節都不要放過,因為任何一個點和微信要 ...
微信小程式支付功能的開發的時候坑比較多,不過對於錢的事謹慎也是好事。網上關於小程式支付的實例很多,但是大多多少有些問題,C#開發的更少。此篇文檔的目的是講開發過程中遇到的問題做一個備註,也方便其他開發的同學作為參考!
1、首先建議把官方文檔支付部分看上三遍,每個細節都不要放過,因為任何一個點和微信要求不符都會導致支付不成功。https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=3_1
2、經過驗證的微信支付功能,會需要一些商戶號、支付秘鑰等,不要搞混。
3、經常遇到的是“簽名錯誤”,請仔細看需要傳送的xml參數及取值規則是否符合微信規則。微信有個驗證工具可以驗證發送的xml欄位是否合法。
下麵上代碼:
web.config
<add key="ConnectionString" value="server=127.0.0.1;database=;uid=sa;pwd="/>
<add key="ConnectionString2" value="server=127.0.0.1;database=codematic2;uid=sa;pwd=1"/>
<add key="appid" value=""/>//appid
<add key="secret" value=""/>//小程式秘鑰
<add key="mch_id" value=""/>//商戶號
<add key="key" value=""/>//支付秘鑰
<add key="ip" value=""/>//伺服器IP
<add key="PayResulturl" value=""/>//微信返回接收信息的url地址
</appSettings>
支付後臺xiadan.ashx
<%@ WebHandler Language="C#" Class="xiadan" %>
using System;
using System.Web;
using System.Net;
using System.IO;
using System.Configuration;
using Maticsoft.Model;
using Maticsoft.BLL;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.Collections.Generic;
using System.Data;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Linq;
using Newtonsoft.Json;
public class xiadan : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
string openid = context.Request.Params["openid"];
string ordertime = context.Request.Params["ordertime"];
string appid = ConfigurationManager.AppSettings["appid"];
string secret = ConfigurationManager.AppSettings["secret"];
string key = ConfigurationManager.AppSettings["key"];
string mch_id = ConfigurationManager.AppSettings["mch_id"];
string ip = ConfigurationManager.AppSettings["ip"];
string PayResulturl = ConfigurationManager.AppSettings["PayResulturl"];
string roomid = context.Request.Params["roomid"];
string aa = "-押金";////商品描述交易欄位格式根據不同的應用場景按照以下格式:APP——需傳入應用市場上的APP名字-實際商品名稱,天天愛消除-游戲充值。
string strcode = aa;
byte[] buffer = Encoding.UTF8.GetBytes(strcode);
string body = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
string totalfee = context.Request.Params["totalfee"];
string output = "";
if ((context.Request.Params["openid"] != null) && (context.Request.Params["openid"] != ""))
{
//OrderInfo order = new OrderInfo();
//order.appid = appid;
System.Random Random = new System.Random();
var dic = new Dictionary<string, string>
{
{"appid", appid},
{"mch_id", mch_id},
{"nonce_str", GetRandomString(20)/*Random.Next().ToString()*/},
{"body",body},
{"out_trade_no",roomid + DateTime.Now.ToString("yyyyMMddHHmmssfff") + Random.Next(999).ToString()},//商戶自己的訂單號碼
{"total_fee",totalfee},
{"spbill_create_ip",ip},//伺服器的IP地址
{"notify_url",PayResulturl},//非同步通知的地址,不能帶參數
{"trade_type","JSAPI" },
{"openid",openid}
};
//加入簽名
dic.Add("sign", GetSignString(dic));
var sb = new StringBuilder();
sb.Append("<xml>");
foreach (var d in dic)
{
sb.Append("<" + d.Key + ">" + d.Value + "</" + d.Key + ">");
}
sb.Append("</xml>");
var xml = new XmlDocument();
// xml.LoadXml(GetPostString("https://api.mch.weixin.qq.com/pay/unifiedorder", sb.ToString()));
CookieCollection coo = new CookieCollection();
Encoding en = Encoding.GetEncoding("UTF-8");
HttpWebResponse response = CreatePostHttpResponse("https://api.mch.weixin.qq.com/pay/unifiedorder", sb.ToString(), en);
//列印返回值
Stream stream = response.GetResponseStream(); //獲取響應的字元串流
StreamReader sr = new StreamReader(stream); //創建一個stream讀取流
string html = sr.ReadToEnd(); //從頭讀到尾,放到字元串html
//Console.WriteLine(html);
xml.LoadXml(html);
//對請求返回值 進行處理
var root = xml.DocumentElement;
DataSet ds = new DataSet();
StringReader stram = new StringReader(html);
XmlTextReader reader = new XmlTextReader(stram);
ds.ReadXml(reader);
string return_code = ds.Tables[0].Rows[0]["return_code"].ToString();
if (return_code.ToUpper() == "SUCCESS")
{
//通信成功
string result_code = ds.Tables[0].Rows[0]["result_code"].ToString();//業務結果
if (result_code.ToUpper() == "SUCCESS")
{
var res = new Dictionary<string, string>
{
{"appId", appid},
{"timeStamp", GetTimeStamp()},
{"nonceStr", dic["nonce_str"]},
{"package", "prepay_id="+ds.Tables[0].Rows[0]["prepay_id"].ToString()},
{"signType", "MD5"}
};
//在伺服器上簽名
res.Add("paySign", GetSignString(res));
// string signapp = res.ToString();
string signapp = JsonConvert.SerializeObject(res);
if ((context.Request.Params["openid"] != null) && (context.Request.Params["openid"] != ""))
{
//存儲訂單信息
Maticsoft.Model.order_history oh = new Maticsoft.Model.order_history();
//oh.shop_id =
oh.room_id = Convert.ToInt32(roomid);
oh.pay_price = Convert.ToDecimal(totalfee);
oh.out_trade_no = dic["out_trade_no"];
oh.order_timestart = Convert.ToDateTime(ordertime);
oh.openid = openid;
oh.creating_date = DateTime.Now;
Maticsoft.BLL.order_history bll = new Maticsoft.BLL.order_history();
bll.Add(oh);
}
context.Response.Write(signapp);
}
}
}
context.Response.Write(output);
}
public bool IsReusable
{
get
{
return false;
}
}
public string GetMd5Hash(String input)
{
if (input == null)
{
return null;
}
MD5 md5Hash = MD5.Create();
// 將輸入字元串轉換為位元組數組並計算哈希數據
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// 創建一個 Stringbuilder 來收集位元組並創建字元串
StringBuilder sBuilder = new StringBuilder();
// 迴圈遍歷哈希數據的每一個位元組並格式化為十六進位字元串
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString());
}
// 返回十六進位字元串
return sBuilder.ToString();
}
/// <summary>
/// 對象序列化成 XML String
/// </summary>
public static string XmlSerialize<T>(T obj)
{
string xmlString = string.Empty;
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
xmlSerializer.Serialize(ms, obj);
xmlString = Encoding.UTF8.GetString(ms.ToArray());
}
return xmlString;
}
/// <summary>
/// 從字元串里隨機得到,規定個數的字元串.
/// </summary>
/// <param name="allChar"></param>
/// <param name="CodeCount"></param>
/// <returns></returns>
public static string GetRandomString(int CodeCount)
{
string allChar = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,i,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z";
string[] allCharArray = allChar.Split(',');
string RandomCode = "";
int temp = -1;
Random rand = new Random();
for (int i = 0; i < CodeCount; i++)
{
if (temp != -1)
{
rand = new Random(temp * i * ((