微信APP支付完整版

关于微信支付,网上太多例子,由于步骤比较繁琐,对于小白来说坑较多,现总结一下完整流程

1.首先要到微信开放平台创建移动应用,提交审核,通过后得到AppID和AppSecret微信APP支付完整版_第1张图片

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 requestXML = WeiXinUtil.GetInfoFromXml(request_data);
            foreach (KeyValuePair k in requestXML)
            {
                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 = new 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 k in sParams)
            {
                if (k.Key == "attach" || k.Key == "body" || k.Key == "sign")
                {
                    sbPay.Append("<" + k.Key + ">");
                }
                else
                {
                    sbPay.Append("<" + k.Key + ">" + k.Value + "");
                }
            }
            return_string = string.Format("{0}", sbPay.ToString());
            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 GetInfoFromXml(string xmlstring)
        {
            SortedDictionary sParams = new 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(dic, "return_code");
        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(dic, "transaction_id");

                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(dic, "result_code");

                        if (!string.IsNullOrEmpty(status) && status == "SUCCESS")
                        {
                            //根据订单编号更新订单状态
                            string OrderNumber = WeiXinUtil.GetValueFromDic(dic, "out_trade_no");
                            string PayDate = WeiXinUtil.GetValueFromDic(dic, "time_end");
                            string BankType = WeiXinUtil.GetValueFromDic(dic, "bank_type");
                            PayOrderDAL payOrderDAL = new PayOrderDAL();
                            if(payOrderDAL.updateOrderStatus(1, transactionid, PayDate, BankType, OrderNumber)){
                                Task task = new Task(() => {
                                    List list=payOrderDAL.GetListByOrderNumber(OrderNumber,1);
                                    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 queryReturnDic = WeiXinUtil.GetInfoFromXml(queryResult);
            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 CreateQueryParam(string transactionId,string appid,string mchid)
        {
            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 CreateQueryParamByOrderNumber(string orderNumber, string appid, string mchid)
        {
            var dic = new SortedDictionary
        {
            {"appid", appid},//公众账号ID
            {"mch_id", mchid},//商户号
            {"nonce_str", Guid.NewGuid().ToString().Replace("-", "")},//随机字符串
            {"out_trade_no", orderNumber}//微信订单号
        };
            return dic;
        }

6.返回支付结果,显示

你可能感兴趣的:(C#,微信支付)