微信公众号发起微信支付 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_id和paySign的获取。类库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

AppId和AppSecret是公众号里面给的,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>

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

一切准备就绪,就可以真正的发起微信支付了:
时间: 2024-08-12 06:27:49

微信公众号发起微信支付 c#的相关文章

app-APP要加入微信支付我要准备什么?已有微信公众号在微信上实现了支付APP支付我要准备什么?

问题描述 APP要加入微信支付我要准备什么?已有微信公众号在微信上实现了支付APP支付我要准备什么? APP要加入微信支付我要准备什么?已有微信公众号在微信上实现了支付APP支付我要准备什么? 解决方案 app支付_微信支付

微信公众号之微信买单

微信开发交流群:148540125 欢迎留言.转发.打赏 文章首发地址:http://www.jianshu.com/p/e28eb52830c5 微信极速开发系列文章:http://www.jianshu.com/p/a172a1b69fdd 首先来看看微信支付都有哪些产品 此篇文章聊聊微信买单. 微信买单是一款商户可自助开通.无需开发的微信支付收款产品,支持顾客使用信用卡支付. 功能特点 1.商户可自助开通,无需开发,1分钟上线微信支付: 2.顾客扫"收款码"付钱,支持信用卡: 3

微信公众号和微信文章纳入搜狗百科词条

据海峡经济网消息,搜狗百科宣布整合搜狗微信搜索独有资源,首次将微信公众号及内容纳入词条查询结果,新增深度实用的微信公众号内容知识,更好地满足了用户个性化需求.用户使用搜狗搜索APP.WAP页面查询该关键词时,在搜狗百科词条页面,该词条页面的目录及词条末尾,即可发现"微信文章"和"公众账号"快捷入口. 原文标题:搜狗百科推出特色服务:微信公众号内容纳入词条查询结果,地址在这http://www.hxjjw.com.cn/news/bzgg/20141029/14911

打通微信公众号 搜狗微信搜索 正式上线!

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 搜狗与微信合作,打通微信公众平台与文章的检索(weixin.sogou.com).这一消息早就在大家的猜测之中,早前搜狗并购搜搜的时候我就开始猜测搜狗的下一步棋会不会以打通微信为主,没想到搜狗落实的比我想象中还要快! 目前国内IT圈内资讯网比较有名的有Chinaz.A5以及一些名人博客,但自从百度百家被百度首页强推之后,无形中把用户的关注度也

微信公众平台教程,注册申请、认证、开发、推广营销,教你怎么用微信公众号

微信公众平台教程 微信公众平台上至少有580多万公众号,8亿的微信用户参与其中,如此聚宝盆如何挖掘呢?本微信公众平台教程,以ytkah自己的使用体会教你怎么用微信公众号,包括微信公众平台注册申请.认证.开发.推广营销.成功案例,公众平台消息导出,关注用户备份,图文消息排版美化,图片尺寸,微信菜单设置,使用技巧等   教程目录 微信公众平台分类 微信公众平台注册,微信公众平台申请 微信公众平台登录 微信公众平台认证 微信公众平台开发 微信公众平台推广,微信公众平台营销   微信公众平台分类 服务号

api-android关注微信公众号

问题描述 android关注微信公众号 碗豆荚APP,有个按钮关注微信公众号功能,点击就启动了微信,并在微信中弹出了这个框,请问谁知道微信API是哪个? 解决方案 AutodeskADN 欢迎大家关注我们的微信公众号Android开发学习之微信公众号界面微信判断当前用户是否关注某个公众号 解决方案二: 1.打开微信只是调用Android的API而已,http://blog.csdn.net/yudajun/article/details/8512970 2.下面那个绿色的也只是一个悬浮层 没有微

微信公众号转载文章成被告 原告要求其在纸媒登道歉声明

微信公众号转 原创文章被告侵权文.图/记者张翔宇通讯员刘香霞微信是当下最火爆的自媒体平台之一.微信世界里,除了大量个人微信外,也包括一些个人.自媒体联盟.机构媒体.企业运营的微信公众号.微信公众号数量迅速壮大,发布的信息形形色色,其中不乏转载 他人原创作品及报刊等媒体发表作品的.微信公众号转载他人原创作品是否侵犯著作权呢?昨日,中山首宗微信侵权纠纷案件开庭审理,中山一家科技公司 认为本地另一家公司的微信公众号擅自转载其原创作品,侵犯了其著作权,要求对方赔礼道歉及索赔1元.昨日因被告没有到庭,法院

微信公众号普遍盈利模式分享

当一个微信公众号经营到具备了一定的粉丝量后,大多数人考虑以及纠结的是该去如何盈利,如何将粉丝流量转换成人民币完成变现闭环! 下面这里分享一些微信公众号普遍盈利模式,只是分享,排序不分先后,目的是给大家一些参考,能否结合自己的公众号做延伸,具体怎么去利用这些粉丝盈利还需要结合各自结合实际情况,因为没有一个放之天下皆行的完美解决方案. 软文广告 毋庸置疑,软文广告是目前所有大小公众号自媒体最简单的盈利收入方式,钞票多少可自己谈.但前提是,在你公众号上打软文广告要有实际效果,现在广告主也越来越聪明了,

微信支付PHP SDK之微信公众号支付代码详解_php实例

这里假设你已经申请完微信支付 1. 微信后台配置  如图 我们先进行测试,所以先把测试授权目录和 测试白名单添加上.测试授权目录是你要发起微信请求的哪个文件所在的目录. 例如jsapi 发起请求一般是jsapi.php所在目录 为测试目录,测试白名单即开发人员的微信号. 正式的支付授权目录不能和测试的一样否则会报错.不填写或者填错授权目录以及测试白名单都会报错. 报错样例: NaNsystem:access_denied 不在测试白名单 2. 配置 lib/WxPay.Config.php文件