微信公众号发起微信支付 c#

原文地址为: 微信公众号发起微信支付 c#

tenpay.dll:

MD5Util.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace tenpay
{
public class MD5Util
{
public MD5Util()
{
//
// TODO: 在此处添加构造函数逻辑
//
}

/** 获取大写的MD5签名结果 */
public static string GetMD5(string encypStr, string charset)
{
string retStr;
MD5CryptoServiceProvider m5
= new MD5CryptoServiceProvider();

//创建md5对象
byte[] inputBye;
byte[] outputBye;

//使用GB2312编码方式把字符串转化为字节数组.
try
{
inputBye
= Encoding.GetEncoding(charset).GetBytes(encypStr);
}
catch (Exception ex)
{
inputBye
= Encoding.GetEncoding("GB2312").GetBytes(encypStr);
}
outputBye
= m5.ComputeHash(inputBye);

retStr
= System.BitConverter.ToString(outputBye);
retStr
= retStr.Replace("-", "").ToUpper();
return retStr;
}
}
}

OrderDetail.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace tenpay
{
/// <summary>
/// 微信订单明细实体对象
/// </summary>
[Serializable]
public class OrderDetail
{
/// <summary>
/// 返回状态码,SUCCESS/FAIL 此字段是通信标识,非交易标识,交易是否成功需要查看trade_state来判断
/// </summary>
public string return_code = "";

/// <summary>
/// 返回信息返回信息,如非空,为错误原因 签名失败 参数格式校验错误
/// </summary>
public string return_msg = "";

/// <summary>
/// 公共号ID(微信分配的公众账号 ID)
/// </summary>
public string appid = "";

/// <summary>
/// 商户号(微信支付分配的商户号)
/// </summary>
public string mch_id = "";

/// <summary>
/// 随机字符串,不长于32位
/// </summary>
public string nonce_str = "";

/// <summary>
/// 签名
/// </summary>
public string sign = "";

/// <summary>
/// 业务结果,SUCCESS/FAIL
/// </summary>
public string result_code = "";

/// <summary>
/// 错误代码
/// </summary>
public string err_code = "";

/// <summary>
/// 错误代码描述
/// </summary>
public string err_code_des = "";

/// <summary>
/// 交易状态
///SUCCESS—支付成功
///REFUND—转入退款
///NOTPAY—未支付
///CLOSED—已关闭
///REVOKED—已撤销
///USERPAYING--用户支付中
///NOPAY--未支付(输入密码或确认支付超时) PAYERROR--支付失败(其他原因,如银行返回失败)
/// </summary>
public string trade_state = "";

/// <summary>
/// 微信支付分配的终端设备号
/// </summary>
public string device_info = "";

/// <summary>
/// 用户在商户appid下的唯一标识
/// </summary>
public string openid = "";

/// <summary>
/// 用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效
/// </summary>
public string is_subscribe = "";

/// <summary>
/// 交易类型,JSAPI、NATIVE、MICROPAY、APP
/// </summary>
public string trade_type = "";

/// <summary>
/// 银行类型,采用字符串类型的银行标识
/// </summary>
public string bank_type = "";

/// <summary>
/// 订单总金额,单位为分
/// </summary>
public string total_fee = "";

/// <summary>
/// 现金券支付金额<=订单总金额,订单总金额-现金券金额为现金支付金额
/// </summary>
public string coupon_fee = "";

/// <summary>
/// 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY
/// </summary>
public string fee_type = "";

/// <summary>
/// 微信支付订单号
/// </summary>
public string transaction_id = "";

/// <summary>
/// 商户系统的订单号,与请求一致。
/// </summary>
public string out_trade_no = "";

/// <summary>
/// 商家数据包,原样返回
/// </summary>
public string attach = "";

/// <summary>
/// 支付完成时间,格式为yyyyMMddhhmmss,如2009年12月27日9点10分10秒表示为20091227091010。
/// 时区为GMT+8 beijing。该时间取自微信支付服务器
/// </summary>
public string time_end = "";

}
}

QueryOrder.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace tenpay
{
/// <summary>
/// 微信订单查询接口请求实体对象
/// </summary>
[Serializable]
public class QueryOrder
{
/// <summary>
/// 公共号ID(微信分配的公众账号 ID)
/// </summary>
public string appid = "";

/// <summary>
/// 商户号(微信支付分配的商户号)
/// </summary>
public string mch_id = "";

/// <summary>
/// 微信订单号,优先使用
/// </summary>
public string transaction_id = "";

/// <summary>
/// 商户系统内部订单号
/// </summary>
public string out_trade_no = "";

/// <summary>
/// 随机字符串,不长于 32 位
/// </summary>
public string nonce_str = "";

/// <summary>
/// 签名,参与签名参数:appid,mch_id,transaction_id,out_trade_no,nonce_str,key
/// </summary>
public string sign = "";
}
}

UnifiedOrder.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace tenpay
{
/// <summary>
/// 微信统一接口请求实体对象
/// </summary>
[Serializable]
public class UnifiedOrder
{
/// <summary>
/// 公共号ID(微信分配的公众账号 ID)
/// </summary>
public string appid = "";
/// <summary>
/// 商户号(微信支付分配的商户号)
/// </summary>
public string mch_id = "";
/// <summary>
/// 微信支付分配的终端设备号
/// </summary>
public string device_info = "";
/// <summary>
/// 随机字符串,不长于 32 位
/// </summary>
public string nonce_str = "";
/// <summary>
/// 签名
/// </summary>
public string sign = "";
/// <summary>
/// 商品描述
/// </summary>
public string body = "";
/// <summary>
/// 附加数据,原样返回
/// </summary>
public string attach = "";
/// <summary>
/// 商户系统内部的订单号,32个字符内、可包含字母,确保在商户系统唯一,详细说明
/// </summary>
public string out_trade_no = "";
/// <summary>
/// 订单总金额,单位为分,不能带小数点
/// </summary>
public int total_fee = 0;
/// <summary>
/// 终端IP
/// </summary>
public string spbill_create_ip = "";
/// <summary>
/// 订 单 生 成 时 间 , 格 式 为yyyyMMddHHmmss,如 2009 年12 月 25 日 9 点 10 分 10 秒表示为 20091225091010。时区为 GMT+8 beijing。该时间取自商户服务器
/// </summary>
public string time_start = "";
/// <summary>
/// 交易结束时间
/// </summary>
public string time_expire = "";
/// <summary>
/// 商品标记 商品标记,该字段不能随便填,不使用请填空,使用说明详见第 5 节
/// </summary>
public string goods_tag = "";
/// <summary>
/// 接收微信支付成功通知
/// </summary>
public string notify_url = "";
/// <summary>
/// JSAPI、NATIVE、APP
/// </summary>
public string trade_type = "";
/// <summary>
/// 用户标识 trade_type 为 JSAPI时,此参数必传
/// </summary>
public string openid = "";
/// <summary>
/// 只在 trade_type 为 NATIVE时需要填写。
/// </summary>
public string product_id = "";
}
}

TenpayUtil.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace tenpay
{
public class TenpayUtil
{
/// <summary>
/// 统一支付接口
/// </summary>
const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";

/// <summary>
/// 网页授权接口
/// </summary>
const string access_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";

/// <summary>
/// 微信订单查询接口
/// </summary>
const string OrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery";

/// <summary>
/// 随机串
/// </summary>
public static string getNoncestr()
{
Random random
= new Random();
return MD5Util.GetMD5(random.Next(1000).ToString(), "GBK").ToLower().Replace("s", "S");
}

/// <summary>
/// 时间截,自1970年以来的秒数
/// </summary>
public static string getTimestamp()
{
TimeSpan ts
= DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
return Convert.ToInt64(ts.TotalSeconds).ToString();
}

/// <summary>
/// 网页授权接口
/// </summary>
public static string getAccess_tokenUrl()
{
return access_tokenUrl;
}

/// <summary>
/// 获取微信签名
/// </summary>
/// <param name="sParams"></param>
/// <returns></returns>
public string getsign(SortedDictionary<string, string> sParams, string key)
{
int i = 0;
string sign = string.Empty;
StringBuilder sb
= new StringBuilder();
foreach (KeyValuePair<string, string> temp in sParams)
{
if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign")
{
continue;
}
i
++;
sb.Append(temp.Key.Trim()
+ "=" + temp.Value.Trim() + "&");
}
sb.Append(
"key=" + key.Trim() + "");
string signkey = sb.ToString();
sign
= MD5Util.GetMD5(signkey, "utf-8");


return sign;
}

/// <summary>
/// post数据到指定接口并返回数据
/// </summary>
public string PostXmlToUrl(string url, string postData)
{
string returnmsg = "";
using (System.Net.WebClient wc = new System.Net.WebClient())
{
returnmsg
= wc.UploadString(url, "POST", postData);
}
return returnmsg;
}

/// <summary>
/// 获取prepay_id
/// </summary>
public string getPrepay_id(UnifiedOrder order, string key)
{
string prepay_id = "";
string post_data = getUnifiedOrderXml(order, key);
string request_data = PostXmlToUrl(UnifiedPayUrl, post_data);
SortedDictionary
<string, string> requestXML = GetInfoFromXml(request_data);
foreach (KeyValuePair<string, string> k in requestXML)
{
if (k.Key == "prepay_id")
{
prepay_id
= k.Value;
break;
}
}
return prepay_id;
}

/// <summary>
/// 获取微信订单明细
/// </summary>
public OrderDetail getOrderDetail(QueryOrder queryorder, string key)
{
string post_data = getQueryOrderXml(queryorder, key);
string request_data = PostXmlToUrl(OrderQueryUrl, post_data);
OrderDetail orderdetail
= new OrderDetail();
SortedDictionary
<string, string> requestXML = GetInfoFromXml(request_data);
foreach (KeyValuePair<string, string> k in requestXML)
{
switch (k.Key)
{
case "retuen_code":
orderdetail.result_code
= k.Value;
break;
case "return_msg":
orderdetail.return_msg
= k.Value;
break;
case "appid":
orderdetail.appid
= k.Value;
break;
case "mch_id":
orderdetail.mch_id
= k.Value;
break;
case "nonce_str":
orderdetail.nonce_str
= k.Value;
break;
case "sign":
orderdetail.sign
= k.Value;
break;
case "result_code":
orderdetail.result_code
= k.Value;
break;
case "err_code":
orderdetail.err_code
= k.Value;
break;
case "err_code_des":
orderdetail.err_code_des
= k.Value;
break;
case "trade_state":
orderdetail.trade_state
= k.Value;
break;
case "device_info":
orderdetail.device_info
= k.Value;
break;
case "openid":
orderdetail.openid
= k.Value;
break;
case "is_subscribe":
orderdetail.is_subscribe
= k.Value;
break;
case "trade_type":
orderdetail.trade_type
= k.Value;
break;
case "bank_type":
orderdetail.bank_type
= k.Value;
break;
case "total_fee":
orderdetail.total_fee
= k.Value;
break;
case "coupon_fee":
orderdetail.coupon_fee
= k.Value;
break;
case "fee_type":
orderdetail.fee_type
= k.Value;
break;
case "transaction_id":
orderdetail.transaction_id
= k.Value;
break;
case "out_trade_no":
orderdetail.out_trade_no
= k.Value;
break;
case "attach":
orderdetail.attach
= k.Value;
break;
case "time_end":
orderdetail.time_end
= k.Value;
break;
default:
break;
}
}
return orderdetail;
}

/// <summary>
/// 把XML数据转换为SortedDictionary<string, string>集合
/// </summary>
/// <param name="strxml"></param>
/// <returns></returns>
protected SortedDictionary<string, string> GetInfoFromXml(string xmlstring)
{
SortedDictionary
<string, string> sParams = new SortedDictionary<string, string>();
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;
}

/// <summary>
/// 微信统一下单接口xml参数整理
/// </summary>
/// <param name="order">微信支付参数实例</param>
/// <param name="key">密钥</param>
/// <returns></returns>
protected string getUnifiedOrderXml(UnifiedOrder order, string key)
{
string return_string = string.Empty;
SortedDictionary
<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add(
"appid", order.appid);
sParams.Add(
"attach", order.attach);
sParams.Add(
"body", order.body);
sParams.Add(
"device_info", order.device_info);
sParams.Add(
"mch_id", order.mch_id);
sParams.Add(
"nonce_str", order.nonce_str);
sParams.Add(
"notify_url", order.notify_url);
sParams.Add(
"openid", order.openid);
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
= getsign(sParams, key);
sParams.Add(
"sign", order.sign);

//拼接成XML请求数据
StringBuilder sbPay = new StringBuilder();
foreach (KeyValuePair<string, string> k in sParams)
{
if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
{
sbPay.Append(
"<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");
}
else
{
sbPay.Append(
"<" + k.Key + ">" + k.Value + "</" + k.Key + ">");
}
}
return_string
= string.Format("<xml>{0}</xml>", sbPay.ToString());
byte[] byteArray = Encoding.UTF8.GetBytes(return_string);
return_string
= Encoding.GetEncoding("GBK").GetString(byteArray);
return return_string;

}

/// <summary>
/// 微信订单查询接口XML参数整理
/// </summary>
/// <param name="queryorder">微信订单查询参数实例</param>
/// <param name="key">密钥</param>
/// <returns></returns>
protected string getQueryOrderXml(QueryOrder queryorder, string key)
{
string return_string = string.Empty;
SortedDictionary
<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add(
"appid", queryorder.appid);
sParams.Add(
"mch_id", queryorder.mch_id);
sParams.Add(
"transaction_id", queryorder.transaction_id);
sParams.Add(
"out_trade_no", queryorder.out_trade_no);
sParams.Add(
"nonce_str", queryorder.nonce_str);
queryorder.sign
= getsign(sParams, key);
sParams.Add(
"sign", queryorder.sign);

//拼接成XML请求数据
StringBuilder sbPay = new StringBuilder();
foreach (KeyValuePair<string, string> k in sParams)
{
if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
{
sbPay.Append(
"<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");
}
else
{
sbPay.Append(
"<" + k.Key + ">" + k.Value + "</" + k.Key + ">");
}
}
return_string
= string.Format("<xml>{0}</xml>", sbPay.ToString().TrimEnd(','));
return return_string;
}
}
}

 看官网例子:

function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : "wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":" 1395712654", //时间戳,自1970年以来的秒数
"nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串
"package" : "prepay_id=u802345jgfjsdfgsdg888",
"signType" : "MD5", //微信签名方式:
"paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {} // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
}
);
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}

主要是prepay_idpaySign的获取。类库tenpay.dll的作用就是获取这两个东西的。

大致流程:获取公众号的code——》获取预定单号的openid——》获取prepay_id。

1.根据自己的业务逻辑生成内部订单

    protected void btnPay_Click(object sender, EventArgs e)
{
if (Fetch.GetUserCookie() == null)
{
Response.Redirect(
"/App/Login.aspx?url=/App/indexPay.aspx");
return;
}

int salePrice = Utility.StrToInt(OrderAmount, 0);
OnLineOrder onlineOrder
= new OnLineOrder();
onlineOrder.ShareID
= 13;
onlineOrder.OrderID
= PayHelper.GetOrderIDByPrefix("WX");

#region 订单处理

if (Fetch.GetUserCookie() == null)
{
onlineOrder.OperUserID
= 0;
}
else
{
onlineOrder.OperUserID
= Fetch.GetUserCookie().UserID;
}
onlineOrder.Accounts
= Fetch.GetUserCookie().Accounts;
onlineOrder.CardTotal
= 1;
onlineOrder.CardTypeID
= salePrice / 10; //< 30 ? 1 : salePrice < 60 ? 2 : salePrice < 120 ? 3 : 4;
onlineOrder.OrderAmount = salePrice;
onlineOrder.IPAddress
= GameRequest.GetUserIP();

//生成订单
Message umsg = treasureFacade.RequestOrder(onlineOrder);
if (!umsg.Success)
{
RenderAlertInfo(
true, umsg.Content, 2);
return;
}
#endregion

//发起微信支付

Response.Redirect(
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公众号appid&redirect_uri=http://你的网站/App/Pay/PayOrder.aspx?showwxpaytitle=1&response_type=code&scope=snsapi_base&state=" + OrderAmount + "_" + onlineOrder.OrderID + "#wechat_redirect");

}

2.进入公众号配置网页授权获取用户基本信息

这样配置后就可以调用微信的接口获取到公众号的code

Response.Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公众号appid&redirect_uri=http://你的网站/App/Pay/PayOrder.aspx?showwxpaytitle=1&response_type=code&scope=snsapi_base&state=" + OrderAmount + "_" + onlineOrder.OrderID + "#wechat_redirect");

访问https://open.weixin.qq.com/connect/oauth2/authorize接口,成功后会跳转到设置的redirect_uri页面,其中会包含code参数,接下来就到redirect_uri页面(我这里就是PayOrder.aspx了)简单的获取code参数:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Game.Utils;
using System.Web.Script.Serialization;
using tenpay;
using System.Configuration;
using System.Text;

public partial class App_Pay_PayOrder : System.Web.UI.Page
{
protected string code = GameRequest.GetQueryString("code");
protected string state = GameRequest.GetQueryString("state");
protected string OrderAmount = "";
protected string OrderID = "";
protected string OrderTime = "";
protected string OrderGive = "";
protected string ImagePath = "";
protected string appId = "";
protected string timeStamp = "";
protected string nonceStr = "";
protected string prepay_id = "";
protected string paySign = "";

protected void Page_Load(object sender, EventArgs e)
{
LoadOrder();
}

private void LoadOrder()
{
string[] values = state.Split('_');
if (values.Length == 2)
{
OrderAmount
= values[0];
OrderID
= values[1];
}
OrderTime
= (new DataControl()).SelectValue("select ApplayDate from OnLineOrder where OrderId='" + OrderID + "'", "DBTreasure", "").ToString();
ImagePath
= (new DataControl()).SelectValue("select ImagePath from CartTypeImage where CardTypeId=" + OrderAmount, "DBTreasure", "").ToString();
}

public struct authorization
{
public string access_token { get; set; } //属性的名字,必须与json格式字符串中的"key"值一样。
public string expires_in { get; set; }
public string refresh_token { get; set; }
public string openid { get; set; }
public string scope { get; set; }
}

protected void btnPay_Click(object sender, EventArgs e)
{
try
{
TenpayUtil tenpay
= new TenpayUtil();
string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString();
string AppSecret = ConfigurationManager.AppSettings["AppSecret"].ToString();
string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString();
appId
= ConfigurationManager.AppSettings["AppId"].ToString();

string post_data = "appid=" + appId + "&secret=" + AppSecret + "&code=" + code + "&grant_type=authorization_code";
string requestData = tenpay.PostXmlToUrl(TenpayUtil.getAccess_tokenUrl(), post_data);

JavaScriptSerializer js
= new JavaScriptSerializer(); //实例化一个能够序列化数据的类
authorization auth = js.Deserialize<authorization>(requestData); //将json数据转化为对象类型并赋值给auth


UnifiedOrder order
= new UnifiedOrder();
order.appid
= appId;
order.attach
= "vinson";
order.body
= OrderAmount + "拍币";
order.device_info
= "";
order.mch_id
= mch_id;
order.nonce_str
= TenpayUtil.getNoncestr();
order.notify_url
= "http://你的网站/App/Shop/pay.aspx";
order.openid
= auth.openid;
order.out_trade_no
= OrderID;
order.trade_type
= "JSAPI";
order.spbill_create_ip
= Page.Request.UserHostAddress;
order.total_fee
= int.Parse(OrderAmount) * 100;
//order.total_fee = 1;

prepay_id
= tenpay.getPrepay_id(order, paySignKey);

timeStamp
= TenpayUtil.getTimestamp();
nonceStr
= TenpayUtil.getNoncestr();

SortedDictionary
<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add(
"appId", appId);
sParams.Add(
"timeStamp", timeStamp);
sParams.Add(
"nonceStr", nonceStr);
sParams.Add(
"package", "prepay_id=" + prepay_id);
sParams.Add(
"signType", "MD5");
paySign
= tenpay.getsign(sParams, paySignKey);

}
catch (Exception ex)
{
Response.Write(ex.ToString());
return;
}

Response.Redirect(
"http://你的网站/App/Pay/pay.aspx?showwxpaytitle=1&appId=" + appId + "&timeStamp=" + timeStamp + "&nonceStr=" + nonceStr + "&prepay_id=" + prepay_id + "&signType=MD5&paySign=" + paySign + "&OrderID=" + OrderID);

}
}
View Code

上面一句

protected string code = GameRequest.GetQueryString("code");

就获取到了传过来的code参数。

然后调用网页授权接口https://api.weixin.qq.com/sns/oauth2/access_token 获取openid

这个接口返回的数据是json类型的,使用JavaScriptSerializer类和结构体把openid取出:

    public struct authorization
{
public string access_token { get; set; } //属性的名字,必须与json格式字符串中的"key"值一样。
public string expires_in { get; set; }
public string refresh_token { get; set; }
public string openid { get; set; }
public string scope { get; set; }
}
            TenpayUtil tenpay = new TenpayUtil();
string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString();
string AppSecret = ConfigurationManager.AppSettings["AppSecret"].ToString();
string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString();
appId
= ConfigurationManager.AppSettings["AppId"].ToString();

string post_data = "appid=" + appId + "&secret=" + AppSecret + "&code=" + code + "&grant_type=authorization_code";
string requestData = tenpay.PostXmlToUrl(TenpayUtil.getAccess_tokenUrl(), post_data);

JavaScriptSerializer js
= new JavaScriptSerializer(); //实例化一个能够序列化数据的类
authorization auth = js.Deserialize<authorization>(requestData); //将json数据转化为对象类型并赋值给auth

AppIdAppSecret是公众号里面给的,mch_id是通过微信支付申请后微信发邮件给的,paySignKey是自己设置的证书密阴

 
 
TenpayUtil.getAccess_tokenUrl()="https://api.weixin.qq.com/sns/oauth2/access_token"
 
 

这样转化后就可以得到openid

order.openid = auth.openid;

终于到重头戏获取prepay_id了

            UnifiedOrder order = new UnifiedOrder();
order.appid
= appId;
order.attach
= "vinson";
order.body
= OrderAmount + "拍币";
order.device_info
= "";
order.mch_id
= mch_id;
order.nonce_str
= TenpayUtil.getNoncestr();
order.notify_url
= "http://你的网站/App/Shop/pay.aspx";
order.openid
= auth.openid;
order.out_trade_no
= OrderID;
order.trade_type
= "JSAPI";
order.spbill_create_ip
= Page.Request.UserHostAddress;
order.total_fee
= int.Parse(OrderAmount) * 100;
//order.total_fee = 1;

prepay_id
= tenpay.getPrepay_id(order, paySignKey);

对象类型UnifiedOrder方便把多个参数融合一个对象中,看看tenpay.getPrepay_id(order, paySignKey)方法:

        /// <summary>
/// 获取prepay_id
/// </summary>
public string getPrepay_id(UnifiedOrder order, string key)
{
string prepay_id = "";
string post_data = getUnifiedOrderXml(order, key);
string request_data = PostXmlToUrl(UnifiedPayUrl, post_data);
SortedDictionary
<string, string> requestXML = GetInfoFromXml(request_data);
foreach (KeyValuePair<string, string> k in requestXML)
{
if (k.Key == "prepay_id")
{
prepay_id
= k.Value;
break;
}
}
return prepay_id;
}
接口UnifiedPayUrl="https://api.mch.weixin.qq.com/pay/unifiedorder"

这个接口的参数是xml格式的,返回来的数据也是xml格式的

 
 
        /// <summary>
/// 微信统一下单接口xml参数整理
/// </summary>
/// <param name="order">微信支付参数实例</param>
/// <param name="key">密钥</param>
/// <returns></returns>
protected string getUnifiedOrderXml(UnifiedOrder order, string key)
{
string return_string = string.Empty;
SortedDictionary
<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add(
"appid", order.appid);
sParams.Add(
"attach", order.attach);
sParams.Add(
"body", order.body);
sParams.Add(
"device_info", order.device_info);
sParams.Add(
"mch_id", order.mch_id);
sParams.Add(
"nonce_str", order.nonce_str);
sParams.Add(
"notify_url", order.notify_url);
sParams.Add(
"openid", order.openid);
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
= getsign(sParams, key);
sParams.Add(
"sign", order.sign);

//拼接成XML请求数据
StringBuilder sbPay = new StringBuilder();
foreach (KeyValuePair<string, string> k in sParams)
{
if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
{
sbPay.Append(
"<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");
}
else
{
sbPay.Append(
"<" + k.Key + ">" + k.Value + "</" + k.Key + ">");
}
}
return_string
= string.Format("<xml>{0}</xml>", sbPay.ToString());
byte[] byteArray = Encoding.UTF8.GetBytes(return_string);
return_string
= Encoding.GetEncoding("GBK").GetString(byteArray);
return return_string;

}
 
 

所有参数准备完毕,就剩下最后的微信签名paySign了:

            prepay_id = tenpay.getPrepay_id(order, paySignKey);

timeStamp
= TenpayUtil.getTimestamp();
nonceStr
= TenpayUtil.getNoncestr();

SortedDictionary
<string, string> sParams = new SortedDictionary<string, string>();
sParams.Add(
"appId", appId);
sParams.Add(
"timeStamp", timeStamp);
sParams.Add(
"nonceStr", nonceStr);
sParams.Add(
"package", "prepay_id=" + prepay_id);
sParams.Add(
"signType", "MD5");
paySign
= tenpay.getsign(sParams, paySignKey);

这里要注意了:appId这些参数的大小写一定要和js那边的参数大小写一致!稍微有所不同都会提示“商户签名错误”。

 
 
<script type="text/javascript">
var appId = "<%=appId %>";
var timeStamp = "<%=timeStamp %>";
var nonceStr = "<%=nonceStr %>";
var prepay_id = "<%=prepay_id %>";
var paySign = "<%=paySign %>";
var OrderID="<%=OrderID %>";
//alert("appId:" + appId + ",timeStamp:" + timeStamp + ",nonceStr:" + nonceStr + ",prepay_id:" + prepay_id + ",paySign:" + paySign);
//return;
function onBridgeReady() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": appId, //公众号名称,由商户传入
"timeStamp": timeStamp, //时间戳,自1970年以来的秒数
"nonceStr": nonceStr, //随机串
"package": "prepay_id=" + prepay_id,
"signType": "MD5", //微信签名方式:
"paySign": paySign //微信签名
},
function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
$(
function () {
$.ajax({
contentType:
"application/json",
url:
"/WS/vinson.asmx/payWeiXin",
data:
"{OrderID:'" + OrderID + "'}",
type:
"POST",
dataType:
"json",
success:
function (json) {
json
= eval("(" + json.d + ")");
if (json.success == "success") {
$(
"#tip").text("支付成功,正在跳转......");
window.location
= "http://你的网站/App/Shop/successful.aspx";
}
else {
$(
"#tip").text(json.msg);
alert(json.msg);
window.location
= "http://你的网站/App/indexPay.aspx";
}
},
error:
function (err, ex) {
alert(err.responseText);
}
});
})
}
// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
else {
alert(
"交易取消");
window.location
="http://www.你的网站.cn/App/indexPay.aspx";
}
}
);
}
if (typeof WeixinJSBridge == "undefined") {
if (document.addEventListener) {
document.addEventListener(
'WeixinJSBridgeReady', onBridgeReady, false);
}
else if (document.attachEvent) {
document.attachEvent(
'WeixinJSBridgeReady', onBridgeReady);
document.attachEvent(
'onWeixinJSBridgeReady', onBridgeReady);
}
}
else {
onBridgeReady();
}
</script>
 
 

要发起微信支付,还要到公众号设置支付授权目录:

一切准备就绪,就可以真正的发起微信支付了:


转载请注明本文地址: 微信公众号发起微信支付 c#

猜你喜欢

转载自blog.csdn.net/zhengxiuchen86/article/details/81411134