统一下单接口URL地址:https://api.mch.weixin.qq.com/pay/unifiedorder
1、提交支付的视图页面
@{
Layout = null;
ViewBag.Title = "订单支付";
string subNumber = ViewBag.SubNumber;//订单号
string errmsg = ViewBag.Errmsg;//失败信息
string json = ViewBag.Json;//jsapi支付请求json
string callBackUrl = ViewBag.CallBackUrl;//支付完成回调url
string hiscallBackUrl = ViewBag.HiscallBackUrl;//订单url
}
<script type="text/javascript" src="http://images.zhongmin.cn/js/jquery-1.9.1.min.js"></script>
<body onload="wxPay()">
<form id="form1">
<input type="hidden" id="hdnSubNumber" value="@subNumber" />
</form>
<script type="text/javascript">
function wxPay() {
if ('@errmsg' == null) {//判断是否下单成功
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
//公众号支付
WeixinJSBridge.invoke('getBrandWCPayRequest', '@json',
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
alert('支付完成!');
location.href = "@callBackUrl";//支付完成转到回调页面
}
else {
location.href = "@hiscallBackUrl?key=@subNumber";//失败,返回订单页面
}
});
WeixinJSBridge.log('pay ready.');
}, false)
} else {
alert('@errmsg'); //失败信息
}
}
</script>
</body>
2、Controller后台处理
public ActionResult Trade()
{
string subNumber = '';
ViewBag.HdnIsWxPay = "0";
if (!string.IsNullOrEmpty(Request.QueryString["key"]))
{
subNumber = Request.QueryString["key"].Trim();
try
{
WxPay();
}
catch (Exception ex)
{
throw ex;
}
}
return View();
}
private void WxPay()
{
WxPayHelper wxPayHelper = new WxPayHelper();
//先设置基本信息
wxPayHelper.SetAppId(Config.APPID); //微信AppId
wxPayHelper.Setmch_id(Config.SETMCH_ID);//商户id
wxPayHelper.SetPayKey(Config.PAYKEY);//签名
wxPayHelper.SetParameter("body", productName);//商品描述
wxPayHelper.SetParameter("out_trade_no", OrderID);//商户订单号
wxPayHelper.SetParameter("notify_url", Config.NOTURL);//下单结果回调地址
wxPayHelper.SetParameter("spbill_create_ip", Config.getIp());//终端IP
wxPayHelper.SetParameter("total_fee", allPrice);//价格,整数,需要转换成以‘分’为单位
wxPayHelper.SetParameter("trade_type", "JSAPI");//交易类型,JSAPI表示公众号支付
string wxOpenId = Session["weixinOpenId"];
ViewBag.WxOpenId = wxOpenId;
wxPayHelper.SetParameter("openid", wxOpenId);//获取openId
//先设置基本信息
Wxpay.WxPayHelper.UnifyReceive receiveModel = null;
string json = wxPayHelper.CreateBizPackage(out receiveModel);//获取json数据
string errmsg = receiveModel.ErrorInfo;
ViewBag.Errmsg = errmsg;
ViewBag.Json = json;
ViewBag.HiscallBackUrl = "";
ViewBag.SubNumber = subNumber;
ViewBag.CallBackUrl = "";
ViewBag.Openid = wxPayHelper.GetParameter("openid");
}
3.WxPayHelper微信支付下单
public class WxPayHelper
{
public WxPayHelper()
{
this.parameters = new Dictionary<string, string>();
this.AppId = "";
this.AppKey = "";
this.PayKey = "";
this.SignType = "MD5";
this.mch_id = "";
}
private Dictionary<string, string> parameters;
private string AppId;
private string AppKey;
private string PayKey;
private string SignType;
private string mch_id;
public void SetAppId(string str)
{
AppId = str;
}
public void SetPayKey(string str)
{
PayKey = str;
}
public void Setmch_id(string str)
{
mch_id = str;
}
public void SetParameter(string key, string value_ren)
{
parameters.Add(key, value_ren);
}
public string GetParameter(string key)
{
return parameters[key];
}
private Object CheckParameters()
{
if (parameters["body"] == "" || parameters["out_trade_no"] == ""
|| parameters["total_fee"] == "" || parameters["trade_type"] == "" || parameters["notify_url"] == null || parameters["spbill_create_ip"] == ""
)
{
return false;
}
return true;
}
public string GetPayPackage(out UnifyReceive receiveModel)
{
if (!parameters.ContainsKey("appid"))//判断是否包含指定的键
{
parameters.Add("appid", AppId);
}
if (!parameters.ContainsKey("nonce_str"))
{
parameters.Add("nonce_str", Wxpay.CommonUtil.CreateNoncestr());
}
if (!parameters.ContainsKey("mch_id"))
{
parameters.Add("mch_id", mch_id);
}
string unSignParaString = Wxpay.CommonUtil.FormatBizQueryParaMap(parameters);//拼接签名字符串
parameters.Add("sign", Wxpay.MD5SignUtil.Sign(unSignParaString, PayKey));//生成签名
//把 parameters 组装成xml 发送这个XML取得PrePay_Id
string xml = Wxpay.CommonUtil.ArrayToXml(parameters);
receiveModel = new UnifyReceive(HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder", xml));
return receiveModel.prepay_id;//获取预支付交易会话标识,该值有效期为2小时
}
// 生成jsapi支付请求json
public string CreateBizPackage(out UnifyReceive receiveModel)
{
Dictionary<string, string> nativeObj = new Dictionary<string, string>();
if ((bool)((CheckParameters())) == false)
{
throw new SDKRuntimeException("生成package参数缺失!");
}
nativeObj.Add("appId", AppId);
string prepay_id = GetPayPackage(out receiveModel);
nativeObj.Add("package", string.Format("prepay_id={0}", prepay_id));//订单详情扩展字符串
nativeObj.Add("timeStamp", ((DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000).ToString());//时间戳
nativeObj.Add("nonceStr", Wxpay.CommonUtil.CreateNoncestr());//随机字符串
nativeObj.Add("signType", SignType);//签名方式
string unSignParaString = Wxpay.CommonUtil.FormatBizQueryParaMap(nativeObj);//拼接字符串
nativeObj.Add("paySign", Wxpay.MD5SignUtil.Sign(unSignParaString, PayKey));//进行MD5签名
var entries = nativeObj.Select(d => string.Format("\"{0}\": \"{1}\"", d.Key, d.Value));
return "{" + string.Join(",", entries.ToArray()) + "}";
}
//post请求方法
public string HttpPost(string url, string param)
{
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(CheckValidationResult);//验证服务器证书回调自动验证
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Accept = "*/*";
request.Timeout = 15000;
request.AllowAutoRedirect = false;
StreamWriter requestStream = null;
WebResponse response = null;
string responseStr = null;
try
{
requestStream = new StreamWriter(request.GetRequestStream());
requestStream.Write(param);
requestStream.Close();
response = request.GetResponse();
if (response != null)
{
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
responseStr = reader.ReadToEnd();
reader.Close();
}
}
catch (Exception ex)
{
Tools.PublicConfig.log_Append("HttpPost 请求失败" + ex.Message, "Pay", "WxPay_V3.log");
}
finally
{
request = null;
requestStream = null;
response = null;
}
Tools.PublicConfig.log_Append("HttpPost 响应数据:" + responseStr, "Pay", "WxPay_V3.log");
return responseStr;
}
public bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{ // 总是接受
return true;
}
public class UnifyReceive
{
/// <summary>
/// SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
/// </summary>
public string return_code { get; set; }
/// <summary>
/// 返回信息,如非空,为错误原因
/// </summary>
public string return_msg { get; set; }
/// <summary>
/// 微信分配的公众账号ID
/// </summary>
public string appid { get; set; }
/// <summary>
/// 微信支付分配的商户号
/// </summary>
public string mch_id { get; set; }
/// <summary>
/// 随机字符串,不长于32位
/// </summary>
public string nonce_str { get; set; }
/// <summary>
/// 签名
/// </summary>
public string sign { get; set; }
/// <summary>
/// 业务结果
/// </summary>
public string result_code { get; set; }
private string _prepay_id = string.Empty;
/// <summary>
/// 预支付ID
/// </summary>
public string prepay_id
{
get { return _prepay_id; }
set { _prepay_id = value; }
}
/// <summary>
/// 交易类型
/// </summary>
public string trade_type { get; set; }
private string _code_url = string.Empty;
/// <summary>
/// 二维码链接
/// </summary>
public string code_url
{
get { return _code_url; }
set { _code_url = value; }
}
private string _error = string.Empty;
/// <summary>
/// 错误提示
/// </summary>
public string ErrorInfo
{
get { return _error; }
set { _error = value; }
}
public UnifyReceive(string xml)
{
try
{
XElement doc = XElement.Parse(xml);
return_code = doc.Element("return_code").Value;
if (return_code == "SUCCESS")
{
appid = doc.Element("appid").Value;
mch_id = doc.Element("mch_id").Value;
nonce_str = doc.Element("nonce_str").Value;
sign = doc.Element("sign").Value;
result_code = doc.Element("result_code").Value;
if (result_code == "SUCCESS")
{
trade_type = doc.Element("trade_type").Value;
prepay_id = doc.Element("prepay_id").Value;
if (trade_type == "NATIVE")
{
code_url = doc.Element("code_url").Value;
}
trade_type = doc.Element("trade_type").Value;
}
else
{
ErrorInfo = "err_code:" + doc.Element("err_code").Value + ";err_code_des" + doc.Element("err_code_des").Value;
}
}
else
{
return_msg = doc.Element("return_msg").Value;
ErrorInfo = return_msg;
}
}
catch (Exception ex)
{
ErrorInfo = "解析HttpPost响应:" + ex.Message;
}
}
}
}
4、用到的方法:
拼接字符串
public static string FormatBizQueryParaMap(Dictionary<string, string> paraMap)
{
string buff = "";
try
{
var result = from pair in paraMap orderby pair.Key select pair;
foreach (KeyValuePair<string, string> pair in result)
{
if (pair.Key != "")
{
string key = pair.Key;
string val = pair.Value;
buff += key + "=" + val + "&";
}
}
if (buff.Length != 0)
{
buff = buff.Substring(0, (buff.Length - 1));
}
}
catch (Exception e)
{
}
return buff;
}
MD5加密签名
public static String Sign(String content, String key)
{
String signStr = content + "&key=" + key;
return MD5Util.MD5(signStr).ToUpper();
}
转换为xml格式
public static string ArrayToXml(Dictionary<string, string> arr)
{
String xml = "<xml>";
foreach (KeyValuePair<string, string> pair in arr)
{
String key = pair.Key;
String val = pair.Value;
if (IsNumeric(val))
{
xml += "<" + key + ">" + val + "</" + key + ">";
}
else
xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
}
xml += "</xml>";
return xml;
}
随机字符串:
public static String CreateNoncestr()
{
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
Random rd = new Random();
for (int i = 0; i < 16; i++)
{
res += chars[rd.Next(chars.Length - 1)];
}
return res;
}
5、如果下单成功,前端开启微信支付监听WeixinJSBridgeReady
var json= '{"appId": "",//应用ID
"package": "",//订单详情扩展字符串
"timeStamp": "",//时间戳
"nonceStr": "",//随机字符串
"signType": "",//签名类型
"paySign": ""}'; //签名
function Wxpay()
{
document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
WeixinJSBridge.invoke('getBrandWCPayRequest',json,function(res){
WeixinJSBridge.log(res.err_msg);
switch (res.err_msg){
case 'get_brand_wcpay_request:cancel':
alert("取消支付");
break;
case 'get_brand_wcpay_request:fail':
alert("支付失败,可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等。");
break;
case 'get_brand_wcpay_request:ok':
alert("支付成功"); //支付成功,返回自定义页面
break;
}
});
}, false);
}
官方文档,微信内H5调起支付:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7
微信统一下单:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1