关于微信支付,网上太多例子,由于步骤比较繁琐,对于小白来说坑较多,现总结一下完整流程
1.首先要到微信开放平台创建移动应用,提交审核,通过后得到AppID和AppSecret
2.申请开发者资质认证。
3.申请微信支付
申请成功会收到邮件,包含商户号wxPay_mchId和密码,用这个登录商户平台,开通APP支付,同时在商户平台->账户设置->API安全里填写的密钥得到wxPay_partnerKey
自此需要用到的AppID,AppSecret,mchId,partnerKey,notifyUrl(后台网站地址,自己设置)都获取完成,可将其放到配置文件或数据库。下面进入正式代码:
1.用户点击生成订单,APP将信息提交后台,后台生成完整订单返回APP,APP显示订单
PayOrder payOrder = new PayOrder();
payOrder.cname = cname;
payOrder.curUmno = curUmno;
payOrder.thisPay = Convert.ToDecimal(thispay);
payOrder.payType = payType;
payOrder.orderStatus = 0;
payOrder.orderNumber=WeiXinUtil.CreateNonce();//商户后台订单号,随机生成
payOrder.tradeType=tradeType;
payOrder.isDelete=0;
// payOrder.transactionId=;微信订单号支付完成后台异步填写
//payOrder.payDate支付完成后台异步填写
//payOrder.bankType支付完成后台异步填写
2.用户点击付款,将信息提交后台,后台组件下单对象(付款信息有APP传入,配置信息从配置文件或数据库读取),至少包含以下10个参数:
order.body
order.appid
order.mch_id
order.notify_url
order.attach
order.nonce_str
order.out_trade_no
order.total_fee
order.spbill_create_ip
order.trade_type
3.获取预支付订单id:getPrepay_id :string prepayid =getPrepay_id(order, pdd.getWxKey("wxPay_partnerKey"));//(wxPay_partnerKe重数据库或配置文件获取)
///
/// 获取prepay_id
///
public string getPrepay_id(Order order, string key)
{
string prepay_id = "";
string post_data = getUnifiedOrderXML(order, key);
string request_data = WeiXinUtil.PostXmlToUrl("https://api.mch.weixin.qq.com/pay/unifiedorder", post_data);
SortedDictionary
foreach (KeyValuePair
{
if (k.Key == "prepay_id")
{
prepay_id = k.Value;
break;
}
}
return prepay_id;
}
//获取统一下单数据
public static string getUnifiedOrderXML(Order order, string key)
{
string return_string = string.Empty;
Dictionary
sParams.Add("appid", order.appid);
sParams.Add("attach", order.attach);
sParams.Add("body", order.body);
sParams.Add("mch_id", order.mch_id);
sParams.Add("nonce_str", order.nonce_str);
sParams.Add("notify_url", order.notify_url);
sParams.Add("out_trade_no", order.out_trade_no);
sParams.Add("spbill_create_ip", order.spbill_create_ip);
sParams.Add("total_fee", order.total_fee.ToString());
sParams.Add("trade_type", order.trade_type);
order.sign = CreateSign(sParams, key);
sParams.Add("sign", order.sign);
//拼接成XML请求数据
StringBuilder sbPay = new StringBuilder();
foreach (KeyValuePair
{
if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
{
sbPay.Append("<" + k.Key + ">" + k.Key + ">");
}
else
{
sbPay.Append("<" + k.Key + ">" + k.Value + "" + k.Key + ">");
}
}
return_string = string.Format("
byte[] byteArray = Encoding.UTF8.GetBytes(return_string);
return_string = Encoding.GetEncoding("UTF-8").GetString(byteArray);
return return_string;
}
///
/// post数据到指定接口并返回数据
///
public static string PostXmlToUrl(string url, string postData)
{
string returnmsg = "";
using (System.Net.WebClient wc = new System.Net.WebClient())
{
wc.Encoding = System.Text.Encoding.UTF8;
returnmsg = wc.UploadString(url, "POST", postData);
}
return returnmsg;
}
///
/// 把XML数据转换为SortedDictionary
///
///
///
public static SortedDictionary
{
SortedDictionary
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlstring);
XmlElement root = doc.DocumentElement;
int len = root.ChildNodes.Count;
for (int i = 0; i < len; i++)
{
string name = root.ChildNodes[i].Name;
if (!sParams.ContainsKey(name))
{
sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim());
}
}
}
catch { }
return sParams;
}
//获取时间戳
public static string GetTimeStamp()
{
TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}
//创建随机字符串32位
public static string CreateNonce()
{
char[] constant = new char[]{
'0','1','2','3','4','5','6','7','8','9'
};
StringBuilder newRandom = new StringBuilder(constant.Length);
Random rd = new Random(Guid.NewGuid().GetHashCode());
for (int i = 0; i < 16; i++)
{
newRandom.Append(constant[rd.Next(constant.Length)]);
}
return newRandom.ToString();
}
//md5加密
public static string MD5(string data)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data);
bytes = md5.ComputeHash(bytes);
md5.Clear();
string s = string.Empty;
for (int i = 0; i < bytes.Length; i++)
{
s += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
}
return s.PadLeft(32, '0');
}
///
/// Builds the return XML.
///
/// The code.
/// The return MSG.
///
public static string BuildReturnXml(string code, string returnMsg)
{
return "
}
4.//获取到prepayid,在APP调起模块进行支付
交易完成后,异步后台处理(交易完成后回调地址会接收到微信异步通知,后台收到通知,需给微信回确认信息,否则微信会通知多次,异步通知的作用是确认订单缴费成功,不能有前台确认,为防止假冒信息只能后台确认,后台确认成功后才可以处理业务逻辑,比如发送短信通知等。)
public class NotifyHandlewx : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
Para_Comm CurMsg = new Para_Comm();
var request = context.Request;
var requestXml = WeiXinUtil.GetRequestXmlData(request);
var dic = WeiXinUtil.FromXml(requestXml);
var returnCode = WeiXinUtil.GetValueFromDic
pay_dictionaryDAL pdd=new pay_dictionaryDAL();
var key = pdd.getInfoByPayCode("wxKey");
var appid = pdd.getInfoByPayCode("wxAppId");
var mchid=pdd.getInfoByPayCode("wxTenamtNo");
var ReturnXml="";
if (!string.IsNullOrEmpty(returnCode) && returnCode == "SUCCESS")//通讯成功
{
var result = WeiXinUtil.WePayNotifyValidation(dic, key);
if (result)
{
var transactionid = WeiXinUtil.GetValueFromDic
if (!string.IsNullOrEmpty(transactionid))
{
//对数据表payOrder加锁
//查询业务状态,如果已经处理直接返回成功
PayOrderDAL pd = new PayOrderDAL();
bool handleStatus = pd.SearchStatus(transactionid);
if (handleStatus)
{
ReturnXml = WeiXinUtil.BuildReturnXml("SUCCESS", "OK");
context.Response.Write(ReturnXml);
return;
}
var queryXml = WeiXinUtil.BuildQueryRequest(transactionid, dic, key, appid, mchid);
var queryResult = WeiXinUtil.PostXmlToUrl("https://api.mch.weixin.qq.com/pay/orderquery", queryXml);
var queryReturnDic = WeiXinUtil.GetInfoFromXml(queryResult);
if (WeiXinUtil.ValidatonQueryResult(queryReturnDic))//查询成功
{
var status = WeiXinUtil.GetValueFromDic
if (!string.IsNullOrEmpty(status) && status == "SUCCESS")
{
//根据订单编号更新订单状态
string OrderNumber = WeiXinUtil.GetValueFromDic
string PayDate = WeiXinUtil.GetValueFromDic
string BankType = WeiXinUtil.GetValueFromDic
PayOrderDAL payOrderDAL = new PayOrderDAL();
if(payOrderDAL.updateOrderStatus(1, transactionid, PayDate, BankType, OrderNumber)){
Task task = new Task(() => {
List
if(null==list){
CurMsg.success=false;
}
else
{
string curUmno = list[0].curUmno;
long umno = Convert.ToInt32(curUmno.Substring(2, 8));
Advances advances = new Advances();
advances.umno = umno;
ut_umrelateDAL ud = new ut_umrelateDAL();
Object obj=ud.serchCidByUmno(umno);
if (null != obj)
{
advances.CustID = Convert.ToInt32(obj);
}
else
{
advances.CustID = 0;
}
advances.AdminID = "wx";
advances.debt = list[0].remain;
advances.PayMoney = list[0].thisPay;
advances.sumpay = list[0].sumMoney;
int lastbuyno = 0;
Para_Comm CurMsg1 = new Para_Comm();
AdvancesBLL.getLastsumpayByUmno(out CurMsg1, umno);
if(CurMsg1.success){
string[] sArray = CurMsg1.rcvdata.Split(':');
lastbuyno = Convert.ToInt32(sArray[1]);
}
advances.buyno = lastbuyno + 1;
advances.remark = "微信收费";
AdvancesBLL.Save_Advances(out CurMsg, advances, "insert");
//充值成功了,发送短信给客户
}
});
task.Start();
}
ReturnXml = WeiXinUtil.BuildReturnXml("SUCCESS", "OK");
}
}
else
ReturnXml=WeiXinUtil.BuildReturnXml("FAIL", "订单查询失败");
}
else
ReturnXml=WeiXinUtil.BuildReturnXml("FAIL", "支付结果中微信订单号不存在");
}
else
ReturnXml=WeiXinUtil.BuildReturnXml("FAIL", "签名失败");
}
else
{
string returnmsg;
dic.TryGetValue("return_msg", out returnmsg);
throw new Exception("异步通知错误:" + returnmsg);
}
context.Response.Write(ReturnXml);
}
5.支付交易完成,需到微信后台查询实际支付结果
public bool searchResult(string orderNumber)
{
pay_dictionaryDAL pdd = new pay_dictionaryDAL();
string key = pdd.getInfoByPayCode("wxKey");
string appid = pdd.getInfoByPayCode("wxAppId");
string mchid = pdd.getInfoByPayCode("wxTenamtNo");
string queryXml = WeiXinUtil.BuildQueryRequestByOrderNumber(orderNumber, key, appid, mchid);
string queryResult = WeiXinUtil.PostXmlToUrl("https://api.mch.weixin.qq.com/pay/orderquery", queryXml);
SortedDictionary
if (WeiXinUtil.ValidatonQueryResult(queryReturnDic))//查询成功
{
return true;
}
else
{
return false;
}
}
public static string BuildQueryRequestByOrderNumber(string orderNumber, string key, string appid, string mchid)
{
var dicParam = CreateQueryParamByOrderNumber(orderNumber, appid, mchid);
var signString = CreateURLParamString(dicParam);
var preString = signString + "&key=" + key;
var sign = Sign(preString, "utf-8").ToUpper();
dicParam.Add("sign", sign);
return BuildForm(dicParam);
}
///
/// Creates the query parameter.
///
/// The transaction identifier.
///
private static SortedDictionary
{
var dic = new SortedDictionary
{
{"appid", appid},//公众账号ID
{"mch_id", mchid},//商户号
{"nonce_str", Guid.NewGuid().ToString().Replace("-", "")},//随机字符串
{"transaction_id", transactionId}//微信订单号
};
return dic;
}
///
/// Creates the query parameter.
///
/// The transaction identifier.
///
private static SortedDictionary
{
var dic = new SortedDictionary
{
{"appid", appid},//公众账号ID
{"mch_id", mchid},//商户号
{"nonce_str", Guid.NewGuid().ToString().Replace("-", "")},//随机字符串
{"out_trade_no", orderNumber}//微信订单号
};
return dic;
}
6.返回支付结果,显示