c# 微信开发 《微信支付》

首先要理解微信支付的流程。需二次握手。

先把订单信息,金额传给微信,微信返回相应信息,再调用微信支付。

详细的查看微信公众号的相关资料

 /// <summary>
        /// 新建一个普通订单
        /// </summary>
        /// <returns></returns>
        public Entity NewOrder(Entity en)
        {
            string WeiXinOpenID = en.GetValue("WeiXinOpenID").TryString();
            string AddressID = en.GetValue("AddressID").TryString();
            string OrderMessage = en.GetValue("OrderMessage").TryString();
            int OrderStatus = (int)OrderEnum.OrderStatus.待付款;
            string CommodityList = en.GetValue("CommodityList").TryString();
            string CouponRecordGuid = en.GetValue("CouponRecordGuid").TryString(); //优惠券
            decimal ManorMoney = en.GetValue("ManorMoney").TryDecimal(); //庄园币
 
            string OrderGuid = System.Guid.NewGuid().ToString();
            try
            {
                using (System.Transactions.TransactionScope scope = new System.Transactions.TransactionScope())
                {
                 

                    #region 支付信息
                    string PayRecordID = System.Guid.NewGuid().TryString();
                    int PayStatus = (int)OrderEnum.PayStatus.未支付;
                    string OrderNum = OrderServiceDA.NewOrder(OrderGuid, WeiXinOpenID, AddressID, OriginalTotalPrice, SaleTotalPrice, OrderMessage, OrderStatus);

                    //添加支付记录
                    OrderServiceDA.AddPayRecord(PayRecordID, SaleTotalPrice, WeiXinOpenID, OrderGuid, PayStatus);
     


                    decimal WeixinPayMoney = SaleTotalPrice - (ManorMoney + Couponvalue);
                    if (WeixinPayMoney > 0)
                    {
                        int PayType = (int)OrderEnum.PayType.微信支付;
                        OrderServiceDA.AddPayRecordWeixinDetail(PayRecordID, PayType, WeixinPayMoney, PayStatus);
                        OrderServiceDA.UpdatePayRecordPayType(PayRecordID, PayType);
                        WeixinPayService WeixinPayService = new WeixinPayService();
                        PaymentData payData = new PaymentData();
                        payData.SetValue("attach", OrderNum);
                        payData.SetValue("body", "微信在线支付");
                        payData.SetValue("out_trade_no", OrderNum);
                        payData.SetValue("trade_type", "JSAPI");
                        payData.SetValue("total_fee", (WeixinPayMoney * 100).ToInt32());//付款金额,单位分
                        payData.SetValue("openid", WeiXinOpenID);
                        PaymentData returnData = WeixinPayService.UnifiedOrder(payData);

                        string prepay_id = "";
                        string SignKey = "";
                        string TimeStamp = "";
                        string NonceStr = "";
                        string returnCode = returnData.GetValue("return_code").ToString();
                        if (returnCode.ToUpper().Equals("SUCCESS"))
                        {
                            #region 获取支付签名
                            //获取支付ID
                            prepay_id = returnData.GetValue("prepay_id").ToString();
                            PaymentData jsApiParam = new PaymentData();
                            NonceStr = WeixinPayService.GenerateNonceStr();
                            TimeStamp = WeixinPayService.GenerateTimeStamp();
                            jsApiParam.SetValue("appId", WeixinPayService.AppId);
                            jsApiParam.SetValue("timeStamp", TimeStamp);
                            jsApiParam.SetValue("nonceStr", NonceStr);
                            jsApiParam.SetValue("package", "prepay_id=" + prepay_id);
                            jsApiParam.SetValue("signType", "MD5");
                            SignKey = jsApiParam.MakeSign(WeixinPayService.SignKey);
                            #endregion
                        }
                        else
                        {
                            string ErrorMessage = returnData.GetValue("return_msg").ToString();
                            FaultException exception = new FaultException(ErrorMessage);
                            throw (exception);
                        }
//保存信息,用于前端再进行调起支付。 OrderServiceDA.UpdateWeixinPayRecord(PayRecordID, prepay_id, SignKey, TimeStamp, NonceStr); } else { if (ManorMoney == 0) { int PayType = (int)OrderEnum.PayType.优惠券; OrderServiceDA.UpdatePayRecordPayType(PayRecordID, PayType); } else { int PayType = (int)OrderEnum.PayType.庄园币; OrderServiceDA.UpdatePayRecordPayType(PayRecordID, PayType); } } #endregion scope.Complete(); } } catch (Exception ex) { Entity result = new Entity(new PropertyCollection()); result.AddSimple("Status", -10, typeof(int)); result.AddSimple("StatusText", ex.Message, typeof(string)); return result; } Entity resultEntity = new Entity(new PropertyCollection()); resultEntity.AddSimple("Status", 115, typeof(int)); resultEntity.AddSimple("StatusText", "操作成功.", typeof(string)); resultEntity.AddSimple("OrderGuid", OrderGuid, typeof(string)); return resultEntity; }

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TalentCloud.Common;
using TalentCloud.Base.Utils;
using TalentCloud.Agriculture.Services;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using TalentCloud.Common.Log;

namespace TalentCloud.Agriculture.Weixin.Services
{
    public class WeixinPayService
    {
        /// <summary>
        /// 微信分配的AppId
        /// </summary>
        public string AppId = TCConfigManager.GetConfig("WeixinPayAppid").TryToString();
        /// <summary>
        /// 公众号的支付密钥appsecret
        /// </summary>
        public string AppSecret = TCConfigManager.GetConfig("WeixinPayAppsecret").TryToString();
        /// <summary>
        /// 当前用户IP
        /// </summary>
        public string Ip = WCFClientInfo.ClientIP;
        /// <summary>
        /// 商户号
        /// </summary>
        public string MchId = TCConfigManager.GetConfig("MchId").TryToString();
        /// <summary>
        /// 签名Key
        /// </summary>
        public string SignKey = TCConfigManager.GetConfig("SignKey").TryToString();
        //=======【证书路径设置】===================================== 
        /* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)
        */
        public string CertPath = TCConfigManager.GetConfig("certPath").TrySafeString();
        /// <summary>
        /// 证书密码,windows上可以直接双击导入系统,导入过程中会提示输入证书密码,证书密码默认为您的商户ID
        /// </summary>
        public string CertPassword = TCConfigManager.GetConfig("certpsd").TrySafeString();
        /// <summary>
        /// 支付结果通知回调url,用于商户接收支付结果
        /// </summary>
        public string NOTIFY_URL =TCConfigManager.GetConfig("WebSite").TryToString()+ "/Weixin/PayCallback.aspx";

       
        /// <summary>
        ///   生成随机串,随机串包含字母或数字 @return 随机串
        /// </summary>
        /// <returns></returns>
        public string GenerateNonceStr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }

        /// <summary>
        /// 生成时间戳,标准北京时间,时区为东八区,自1970年1月1日 0点0分0秒以来的秒数
        /// </summary>
        /// <returns></returns>
        public string GenerateTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /// <summary>
        ///  * 统一下单
        ///* @param WxPaydata inputObj 提交给统一下单API的参数
        ///* @param int timeOut 超时时间
        ///* @throws WxPayException
        ///* @return 成功时返回,其他抛异常
        /// <returns></returns>
        public PaymentData UnifiedOrder(PaymentData inputObj, int timeOut = 15)
        {
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            //检测必填参数
            if (!inputObj.IsSet("out_trade_no"))
            {
                throw new Exception("缺少统一支付接口必填参数out_trade_no!");
            }
            else if (!inputObj.IsSet("body"))
            {
                throw new Exception("缺少统一支付接口必填参数body!");
            }
            else if (!inputObj.IsSet("total_fee"))
            {
                throw new Exception("缺少统一支付接口必填参数total_fee!");
            }
            else if (!inputObj.IsSet("trade_type"))
            {
                throw new Exception("缺少统一支付接口必填参数trade_type!");
            }

            //关联参数
            if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
            {
                throw new Exception("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
            }
            if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
            {
                throw new Exception("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
            }

            //异步通知url未设置,则使用配置文件中的url
            if (!inputObj.IsSet("notify_url"))
            {
                inputObj.SetValue("notify_url", NOTIFY_URL);//异步通知url
            }


            inputObj.SetValue("appid", AppId);//公众账号ID
            inputObj.SetValue("mch_id", MchId);//商户号
            inputObj.SetValue("spbill_create_ip", Ip);//终端ip                
            inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
            //签名
            inputObj.SetValue("sign", inputObj.MakeSign(SignKey));
            string xml = inputObj.ToXml();
            string response = HttpService.Post(xml, url, false, timeOut, "", "");
            PaymentData result = new PaymentData();
            result.FromXml(response);
            return result;
        }

        /// <summary>
        /// 申请退款
        /// </summary>
        /// <param name="inputObj">提交给申请退款API的参数</param>
        /// <param name="CertPath">证书路径</param>
        /// <param name="CertPassword">证书密码</param>
        /// <param name="timeOut">超时时间</param>
        /// <returns></returns>
        public PaymentData Refund(PaymentData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            //检测必填参数
            if (!inputObj.IsSet("out_trade_no") && !inputObj.IsSet("transaction_id"))
            {
                throw new Exception("退款申请接口中,out_trade_no、transaction_id至少填一个!");
            }
            else if (!inputObj.IsSet("out_refund_no"))
            {
                throw new Exception("退款申请接口中,缺少必填参数out_refund_no!");
            }
            else if (!inputObj.IsSet("total_fee"))
            {
                throw new Exception("退款申请接口中,缺少必填参数total_fee!");
            }
            else if (!inputObj.IsSet("refund_fee"))
            {
                throw new Exception("退款申请接口中,缺少必填参数refund_fee!");
            }
            else if (!inputObj.IsSet("op_user_id"))
            {
                throw new Exception("退款申请接口中,缺少必填参数op_user_id!");
            }

            inputObj.SetValue("appid", AppId);//公众账号ID
            inputObj.SetValue("mch_id", MchId);//商户号
            inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign(SignKey));//签名
            string xml = inputObj.ToXml();
            string response = HttpService.Post(xml, url, true, timeOut, CertPath, CertPassword);
            //将xml格式的结果转换为对象以返回
            PaymentData result = new PaymentData();
            result.FromXml(response);
            return result;
        }

        /// <summary>
        /// 企业付款接口( 开通条件:
        /// 1、商户号已入驻90日
        /// 2、商户号有30天连续正常交易
        /// 登录微信支付商户平台-产品中心,开通企业付款。)
        /// </summary>
        /// <param name="inputObj">参数</param>
        /// <param name="CertPath">证书路径</param>
        /// <param name="CertPassword">证书密码</param>
        /// <param name="timeOut">超时时间</param>
        /// <returns></returns>
        public PaymentData Transfers(PaymentData inputObj, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";

            #region 检测必要参数

            //检测必填参数
            if (!inputObj.IsSet("partner_trade_no") && !inputObj.IsSet("partner_trade_no"))
            {
                throw new Exception("企业付款接口中,缺少必填参数partner_trade_no!");
            }
            if (!inputObj.IsSet("openid"))
            {
                throw new Exception("企业付款接口中,缺少必填参数openid!");
            }
            if (!inputObj.IsSet("check_name"))
            {
                throw new Exception("企业付款接口中,缺少必填参数check_name!");
            }
            else
            {
                string checkName = inputObj.GetValue("check_name").ToString();
                switch (checkName)
                {
                    case "FORCE_CHECK":
                    case "OPTION_CHECK":
                        if (!inputObj.IsSet("check_name"))
                        {
                            throw new Exception("企业付款接口中,缺少必填参数re_user_name!");
                        }
                        break;
                    default:
                        break;
                }
            }
            if (!inputObj.IsSet("amount"))
            {
                throw new Exception("企业付款接口中,缺少必填参数amount!");
            }
            if (!inputObj.IsSet("desc"))
            {
                throw new Exception("企业付款接口中,缺少必填参数desc!");
            }
            if (!inputObj.IsSet("spbill_create_ip"))
            {
                throw new Exception("企业付款接口中,缺少必填参数spbill_create_ip!");
            }
            #endregion

            #region 添加公共参数
            inputObj.SetValue("mch_appid", AppId);//公众账号ID
            inputObj.SetValue("mchid", MchId);//商户号
            inputObj.SetValue("spbill_create_ip", Ip);//随机字符串
            inputObj.SetValue("nonce_str", Guid.NewGuid().ToString().Replace("-", ""));//随机字符串
            inputObj.SetValue("sign", inputObj.MakeSign(SignKey));//签名 
            #endregion
            string xml = inputObj.ToXml();
            var start = DateTime.Now;
            string response = HttpService.Post(xml, url, true, timeOut, CertPath, CertPassword);
            LogHelper.WriteFileLog("TransfersData", response);
            PaymentData result = new PaymentData();
            result.FromXml(response);

            return result;
        }


        #region 微信发红发,未事项,签名失败问题,未解决
        /// <summary>
        /// 微信红包
        /// </summary>
        public class PayWeiXin
        {
            public string nonce_str { get; set; }
            public string sign { get; set; }
            public string mch_billno { get; set; }
            public string mch_id { get; set; }
            public string wxappid { get; set; }
            public string nick_name { get; set; }
            public string send_name { get; set; }
            public string re_openid { get; set; }
            public int total_amount { get; set; }
            public int min_value { get; set; }
            public int max_value { get; set; }
            public int total_num { get; set; }
            public string wishing { get; set; }
            public string client_ip { get; set; }
            public string act_id { get; set; }
            public string act_name { get; set; }
            public string remark { get; set; }
            public string logo_imgurl { get; set; }
            public string share_content { get; set; }
            public string share_url { get; set; }
            public string share_imgurl { get; set; }

        }

        /// <summary>
        /// 调用微信支付接口,发送红包
        /// </summary>
        /// <param name="payForWeiXin"></param>
        /// <returns></returns>
        public string PayRedBag(PaymentData inputObj)
        {   ////商户号
            inputObj.SetValue("mch_id", MchId);
            //商户 appid 
            inputObj.SetValue("wxappid", AppId);
            inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串
            //签名
            inputObj.SetValue("sign", inputObj.MakeSign(SignKey));
            string xml = inputObj.ToXml();
            string result = string.Empty;
            try
            {
                result = PostPage("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack", xml);
                LogHelper.WriteFileLog("PayRedBagpostData", xml);
                LogHelper.WriteFileLog("PayRedBag", result);
            }
            catch (Exception ex)
            {
                LogHelper.WriteFileLog("PayRedBagError", ex.Message);
            }
            return result;
        }


        /// <summary>
        /// post微信请求
        /// </summary>
        /// <param name="posturl"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        public string PostPage(string posturl, string postData)
        {
            Stream outstream = null;
            Stream instream = null;
            StreamReader sr = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            Encoding encoding = Encoding.UTF8;
            byte[] data = encoding.GetBytes(postData);
            // 准备请求...  
            try
            {
                
                //CerPath证书路径
                string certPath = TCConfigManager.GetConfig("certPath").TrySafeString();
                //证书密码
                string password = TCConfigManager.GetConfig("certpsd").TrySafeString();
                
                X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, password, X509KeyStorageFlags.MachineKeySet);

                // 设置参数  
                request = WebRequest.Create(posturl) as HttpWebRequest;
                CookieContainer cookieContainer = new CookieContainer();
                request.CookieContainer = cookieContainer;
                request.AllowAutoRedirect = true;
                request.Method = "POST";
                request.ContentType = "text/xml";
                request.ContentLength = data.Length;
                request.ClientCertificates.Add(cert);
                outstream = request.GetRequestStream();
                outstream.Write(data, 0, data.Length);
                outstream.Close();
                //发送请求并获取相应回应数据  
                response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求  
                instream = response.GetResponseStream();
                sr = new StreamReader(instream, encoding);
                //返回结果网页(html)代码  
                string content = sr.ReadToEnd();
                string err = string.Empty;
                return content;

            }
            catch (Exception ex)
            {
                string err = ex.Message;
                return string.Empty;
            }
        }

        /// <summary>
        /// Md5加密
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static String Encrypt(String s)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
            bytes = md5.ComputeHash(bytes);
            md5.Clear();
            string ret = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
            }
            return ret.PadLeft(32, '0');
        }

        public string RandomStr(string str, int Length)
        {
            string result = string.Empty;
            Random rd = new Random();
            for (int i = 0; i < Length; i++)
            {
                result += str[rd.Next(str.Length)];
            }
            return result;
        }
        #endregion
    }
}
                //弹出微信支付页面
                WeixinJSBridge.invoke('getBrandWCPayRequest',
                    {
                        "appId": data.AppID,     //公众号名称,由商户传入
                        "timeStamp": data.TimeStamp,         //时间戳,自1970年以来的秒数
                        "nonceStr":  data.nonceStr, //随机串
                        "package": "prepay_id="+data.prepay_id,
                        "signType": "MD5",         //微信签名方式:
                        "paySign":  data.SignKey //微信签名
                    },
                    function (res) {
                        switch (res.err_msg) {
                            case "get_brand_wcpay_request:ok":
                                layer.open({
                                    content: '充值成功',
                                    skin: 'msg',
                                    time: 2 //2秒后自动关闭
                                });
                                browserHistory.push('/WeChat/dist/member/wallet/');
                                break;
                            case "get_brand_wcpay_request:cancel":
                                break;
                            case "get_brand_wcpay_request:fail":
                                layer.open({
                                    content: '充值失败!',
                                    skin: 'msg',
                                    time: 2 //2秒后自动关闭
                                });
                                break;
                            default:
                        }
                    });

  

public partial class PayCallback : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            StreamReader reader = new StreamReader(Request.InputStream, Encoding.UTF8);
            string postStr = reader.ReadToEnd();
            reader.Close();
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(postStr);
            string ReturnCode = doc.SelectSingleNode("//result_code").InnerText;//获取支付结果代码
            StringBuilder xmlStr = new StringBuilder();
            LogHelper.WriteFileLog("PayCallback", ReturnCode);
            if (ReturnCode.ToUpper().Equals("SUCCESS"))
            {
                string strOrderNo = doc.SelectSingleNode("//out_trade_no").InnerText;
                //获取微信支付流水号
                string weChatTransaction_Id = doc.SelectSingleNode("//transaction_id").InnerText;
                string WeiXinOpenID = doc.SelectSingleNode("//openid").InnerText;
                try
                {
                    //获取订单号
                    WeiXinService WeiXinService = new WeiXinService();
                    Entity result= WeiXinService.PayOrder(WeiXinOpenID, strOrderNo, weChatTransaction_Id);
                    string Status = result.GetValue("Status").ToString();
                    string StatusText = result.GetValue("StatusText").ToString();
                    LogHelper.WriteFileLog("Pay", WeiXinOpenID + "," + strOrderNo + "," + weChatTransaction_Id + "," + Status + "," + StatusText);
                }
                catch (Exception ex)
                {
                    LogHelper.WriteFileLog("PayError", ex.Message + "," + WeiXinOpenID + "," + strOrderNo + "," + weChatTransaction_Id);
                    //记录错误
                    throw ex;
                }

                #region 通知微信后台支付成功
                Response.ContentType = "text/xml";
                xmlStr.AppendLine("<xml>");
                xmlStr.AppendFormat("<return_code><![CDATA[SUCCESS]]></return_code>");
                xmlStr.AppendFormat("<return_msg><![CDATA[OK]]></return_msg>");
                xmlStr.AppendFormat("</xml>");
                #endregion
            }
            else
            {
                #region 通知微信后台支付失败
                Response.ContentType = "text/xml";
                xmlStr.AppendLine("<xml>");
                xmlStr.AppendFormat("<return_code><![CDATA[FAIL]]></return_code>");
                xmlStr.AppendFormat("<return_msg><![CDATA[支付失败]]></return_msg>");
                xmlStr.AppendFormat("</xml>");
                #endregion
            }
            Response.Write(xmlStr.ToString());
        }