C#微信支付完成前端回调通知notify_url完整版源码|CSframework.com原创文章
C#微信支付完成前端回调通知notify_url完整版源码|CSframework.com原创文章
XML Code: <xml> <appid><![CDATA[wx44495463a43b7c]]></appid> <bank_type><![CDATA[CMB_CREDIT]]></bank_type> <cash_fee><![CDATA[20]]></cash_fee> <fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[N]]></is_subscribe> <mch_id><![CDATA[1527472222]]></mch_id> <nonce_str><![CDATA[6OQ37L7i6JN1PRLD]]></nonce_str> <openid><![CDATA[oCohp1HF7xLcx-o5QdA-hLc2ios8]]></openid> <out_trade_no><![CDATA[15557331433589231953]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code> <sign><![CDATA[6C6A7CB3F3C742D0AE56687A10F4EA31]]></sign> <time_end><![CDATA[20190415203040]]></time_end> <total_fee>20</total_fee><trade_type> <![CDATA[APP]]></trade_type> <transaction_id><![CDATA[4200000290201904150837155038]]></transaction_id> </xml> //来源:C/S框架网(www.csframework.com) QQ:23404761 微信回调接口设计要求: 1,notify_url:回调通知接口HTTP地址,POST请求,不能是IP地址(必须是域名)不能带端口,预设80端口。 参考: http://www.XXXX.com/notify_url.aspx 2,必须是外网能访问HTTP地址,POST方式,微信服务器POST XML数据过来,请使用PostMan工具调试。 3,微信回调的接口中完成更改商户数据库的订单状态,操作成功给微信返回xml数据,这样微信后台就认为这笔订单交易成功,不会再次回调接口。 详情参考微信API接口说明: 后端完整版源码: C# Code: protected void Page_Load(object sender, EventArgs e) { try { string ip = GetWebClientIp();//获取客户端IP String xmlData = GetPostStr();//获取请求数据 DBHelper.WriteLog("WX-Callback", "xmlData:" + xmlData, ip); if (String.IsNullOrWhiteSpace(xmlData)) { this.Response.Write("请求数据不能为空!");//返回微信服务器 return; } //把数据重新返回给客户端 DataSet ds = new DataSet(); StringReader stram = new StringReader(xmlData); XmlTextReader datareader = new XmlTextReader(stram); ds.ReadXml(datareader); if (ds.Tables[0].Rows[0]["return_code"].ToString() == "SUCCESS") { string wx_appid = "";//微信开放平台审核通过的应用APPID string wx_mch_id = "";//微信支付分配的商户号 string wx_nonce_str = "";//随机字符串,不长于32位 string wx_sign = "";//签名,详见签名算法 string wx_result_code = "";//SUCCESS/FAIL string wx_return_code = ""; string wx_openid = "";//用户在商户appid下的唯一标识 string wx_is_subscribe = "";//用户是否关注公众账号,Y-关注,N-未关注,仅在公众账号类型支付有效 string wx_trade_type = "";// APP string wx_bank_type = "";// 银行类型,采用字符串类型的银行标识,银行类型见银行列表 string wx_fee_type = "";// 货币类型,符合ISO4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型 string wx_transaction_id = "";//微信支付订单号 string wx_out_trade_no = "";//商户系统的订单号,与请求一致。 string wx_time_end = "";// 支付完成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则 int wx_total_fee = -1;// 订单总金额,单位为分 int wx_cash_fee = -1;//现金支付金额订单现金支付金额,详见支付金额 #region 数据解析,注意signstr组合排序,从小到大排列,最后添加key密钥 //列 是否存在 string signstr = "";//需要前面的字符串 //wx_appid if (ds.Tables[0].Columns.Contains("appid")) { wx_appid = ds.Tables[0].Rows[0]["appid"].ToString(); if (!string.IsNullOrEmpty(wx_appid)) { signstr += "appid=" + wx_appid; } } //wx_bank_type if (ds.Tables[0].Columns.Contains("bank_type")) { wx_bank_type = ds.Tables[0].Rows[0]["bank_type"].ToString(); if (!string.IsNullOrEmpty(wx_bank_type)) { signstr += "&bank_type=" + wx_bank_type; } } //wx_cash_fee if (ds.Tables[0].Columns.Contains("cash_fee")) { wx_cash_fee = Convert.ToInt32(ds.Tables[0].Rows[0]["cash_fee"].ToString()); signstr += "&cash_fee=" + wx_cash_fee; } //wx_fee_type if (ds.Tables[0].Columns.Contains("fee_type")) { wx_fee_type = ds.Tables[0].Rows[0]["fee_type"].ToString(); if (!string.IsNullOrEmpty(wx_fee_type)) { signstr += "&fee_type=" + wx_fee_type; } } //wx_is_subscribe if (ds.Tables[0].Columns.Contains("is_subscribe")) { wx_is_subscribe = ds.Tables[0].Rows[0]["is_subscribe"].ToString(); if (!string.IsNullOrEmpty(wx_is_subscribe)) { signstr += "&is_subscribe=" + wx_is_subscribe; } } //wx_mch_id if (ds.Tables[0].Columns.Contains("mch_id")) { wx_mch_id = ds.Tables[0].Rows[0]["mch_id"].ToString(); if (!string.IsNullOrEmpty(wx_mch_id)) { signstr += "&mch_id=" + wx_mch_id; } } //wx_nonce_str if (ds.Tables[0].Columns.Contains("nonce_str")) { wx_nonce_str = ds.Tables[0].Rows[0]["nonce_str"].ToString(); if (!string.IsNullOrEmpty(wx_nonce_str)) { signstr += "&nonce_str=" + wx_nonce_str; } } //wx_openid if (ds.Tables[0].Columns.Contains("openid")) { wx_openid = ds.Tables[0].Rows[0]["openid"].ToString(); if (!string.IsNullOrEmpty(wx_openid)) { signstr += "&openid=" + wx_openid; } } //wx_out_trade_no if (ds.Tables[0].Columns.Contains("out_trade_no")) { wx_out_trade_no = ds.Tables[0].Rows[0]["out_trade_no"].ToString(); if (!string.IsNullOrEmpty(wx_out_trade_no)) { signstr += "&out_trade_no=" + wx_out_trade_no; } } //wx_result_code if (ds.Tables[0].Columns.Contains("result_code")) { wx_result_code = ds.Tables[0].Rows[0]["result_code"].ToString(); if (!string.IsNullOrEmpty(wx_result_code)) { signstr += "&result_code=" + wx_result_code; } } //wx_return_code if (ds.Tables[0].Columns.Contains("return_code")) { wx_return_code = ds.Tables[0].Rows[0]["return_code"].ToString(); if (!string.IsNullOrEmpty(wx_return_code)) { signstr += "&return_code=" + wx_return_code; } } //wx_sign if (ds.Tables[0].Columns.Contains("sign")) { wx_sign = ds.Tables[0].Rows[0]["sign"].ToString(); } //wx_time_end if (ds.Tables[0].Columns.Contains("time_end")) { wx_time_end = ds.Tables[0].Rows[0]["time_end"].ToString(); if (!string.IsNullOrEmpty(wx_time_end)) { signstr += "&time_end=" + wx_time_end; } } //wx_total_fee if (ds.Tables[0].Columns.Contains("total_fee")) { wx_total_fee = Convert.ToInt32(ds.Tables[0].Rows[0]["total_fee"].ToString()); signstr += "&total_fee=" + wx_total_fee; } //wx_trade_type if (ds.Tables[0].Columns.Contains("trade_type")) { wx_trade_type = ds.Tables[0].Rows[0]["trade_type"].ToString(); if (!string.IsNullOrEmpty(wx_trade_type)) { signstr += "&trade_type=" + wx_trade_type; } } //wx_transaction_id if (ds.Tables[0].Columns.Contains("transaction_id")) { wx_transaction_id = ds.Tables[0].Rows[0]["transaction_id"].ToString(); if (!string.IsNullOrEmpty(wx_transaction_id)) { signstr += "&transaction_id=" + wx_transaction_id; } } #endregion //追加key 密钥 signstr += "&key=" + System.Web.Configuration.WebConfigurationManager.AppSettings["wx_key"].ToString(); string md5 = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(signstr, "MD5").ToUpper(); //签名正确 if (wx_sign == md5) { //签名正确,更新本地数据库订单状态 bool success = DBHelper.UpdateOrderState(wx_out_trade_no, wx_transaction_id, wx_total_fee); if (success) { DBHelper.WriteLog("WX-Callback", "回调更改订单状态成功!", ip); this.Response.Write(this.CreateResult(true, ""));//返回微信服务器 } else { string refData = "out_trade_no=" + wx_out_trade_no + ",total_fee=" + wx_total_fee.ToString(); DBHelper.WriteLog("WX-Callback", "回调更改订单状态失败!" + refData, ip); this.Response.Write(this.CreateResult(false, "更改订单状态失败"));//返回微信服务器 } } else { DBHelper.WriteLog("WX-Callback", "回调接口发现签名错误!", ip); this.Response.Write(this.CreateResult(false, "回调接口发现签名错误!"));//返回微信服务器 } } else { this.Response.Write(this.CreateResult(false, "回调函数发现微信接口返回FAIL"));//返回微信服务器 } } catch (Exception ex) { this.Response.Write(ex.Message); } } //来源:C/S框架网(www.csframework.com) QQ:23404761 C# Code: /// <summary> /// 创建返回的XML数据 /// </summary> /// <param name="success"></param> /// <param name="failMessage"></param> /// <returns></returns> private string CreateResult(bool success, string failMessage) { if (success) failMessage = ""; //SUCCESS/FAIL string result = "" + "<xml>" + " <return_code><![CDATA[" + (success ? "SUCCESS" : "FAIL") + "]]></return_code>" + " <return_msg><![CDATA[" + (success ? "OK" : failMessage) + "]]></return_msg>" + "</xml>"; return result; } //来源:C/S框架网(www.csframework.com) QQ:23404761 C# Code: /// <summary> /// 获得Post过来的XML数据 /// </summary> /// <returns></returns> private string GetPostStr() { Int32 intLen = Convert.ToInt32(Request.InputStream.Length); byte[] b = new byte[intLen]; Request.InputStream.Read(b, 0, intLen); return System.Text.Encoding.UTF8.GetString(b); } //来源:C/S框架网(www.csframework.com) QQ:23404761 C# Code: /// <summary> /// 获取客户端IP /// </summary> /// <returns></returns> public static string GetWebClientIp() { string userIP = "IP"; try { if (System.Web.HttpContext.Current == null || System.Web.HttpContext.Current.Request == null || System.Web.HttpContext.Current.Request.ServerVariables == null) return ""; string CustomerIP = ""; //CDN加速后取到的IP CustomerIP = System.Web.HttpContext.Current.Request.Headers["Cdn-Src-Ip"]; if (!string.IsNullOrEmpty(CustomerIP)) return CustomerIP; CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (!String.IsNullOrEmpty(CustomerIP)) return CustomerIP; if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null) { CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (CustomerIP == null) CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } else { CustomerIP = System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (string.Compare(CustomerIP, "unknown", true) == 0) return System.Web.HttpContext.Current.Request.UserHostAddress; return CustomerIP; } catch { } return userIP; } //来源:C/S框架网(www.csframework.com) QQ:23404761 交易历史记录(tb_PayTransList)表结构: SQL Code: CREATE TABLE [dbo].[tb_PayTransList] ( [isid] [int] NOT NULL IDENTITY(1, 1), [TransID] [varchar] (32) COLLATE Chinese_PRC_CI_AS NOT NULL, [TransType] [nvarchar] (10) COLLATE Chinese_PRC_CI_AS NULL, [MerID] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL, [MerDate] [datetime] NULL, [Account] [varchar] (32) COLLATE Chinese_PRC_CI_AS NULL, [ItemID] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL, [ItemName] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NULL, [RefID] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL, [RefBeginDate] [datetime] NULL, [RefEndDate] [datetime] NULL, [Amount] [float] NULL, [PayType] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL, [Remark] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NULL, [FlagTrans] [int] NULL, [CreateTime] [datetime] NULL, [WxPreOrderID] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL, [WxPreOrderTime] [datetime] NULL, [WxCallbackTime] [datetime] NULL, [WxNoncestr] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL, [WxTS] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL, [WxSign] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL, [WxTransactionID] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ) ON [PRIMARY] GO ALTER TABLE [dbo].[tb_PayTransList] ADD CONSTRAINT [PK_tb_PayTransList] PRIMARY KEY CLUSTERED ([TransID]) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_tb_PayTransList] ON [dbo].[tb_PayTransList] ([isid]) ON [PRIMARY] GO CREATE UNIQUE NONCLUSTERED INDEX [IX_tb_PayTransList_1] ON [dbo].[tb_PayTransList] ([MerID]) ON [PRIMARY] GO CREATE NONCLUSTERED INDEX [IX_tb_PayTransList_2] ON [dbo].[tb_PayTransList] ([Account]) ON [PRIMARY] GO //来源:C/S框架网(www.csframework.com) QQ:23404761 usp_Wallet_WXCallbackUpdate 存储过程: SQL Code: --转换为分进行对比,更新交易状态、回调时间 UPDATE dbo.tb_PayTransList SET FlagTrans=2,WxCallbackTime=GETDATE(),WxTransactionID=@WxTransactionID WHERE MerID=@OrderID AND Amount*100=@Amount AND WxCallbackTime IS NULL //来源:C/S框架网(www.csframework.com) QQ:23404761 DBHelper类,引用多数据库底层接口IDatabase。 参考: C#多数据库组件包支持MSSQL+Oracle+MySQL+用户操作手册 C# Code: using CSFramework.DB; using System; using System.Collections.Generic; using System.Linq; using System.Web; /// <summary> /// DBHelper数据层 /// </summary> public static class DBHelper { //日志数据库 private static IDatabase CreateLogDB() { string conn_log = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["Simidata_LogDB"].ToString(); return DatabaseFactory.CreateDatabase(DatabaseType.SqlServer, conn_log); } //业务数据库 private static IDatabase CreateSimidataDB() { string conn_log = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["Simidata"].ToString(); return DatabaseFactory.CreateDatabase(DatabaseType.SqlServer, conn_log); } /// <summary> /// 写日志 /// </summary> /// <param name="logType">日志类型</param> /// <param name="content">内容</param> /// <param name="ip">IP</param> public static void WriteLog(string logType, string content, string ip) { string sql = "INSERT INTO dbo.sys_Log(TS,IP,LogType,LogContent) SELECT GETDATE(),@IP,@LogType,@LogContent"; IDatabase db = CreateLogDB(); CommandHelper cmd = db.CreateCommand(sql); cmd.AddParam("@IP", ip); cmd.AddParam("@LogType", logType); cmd.AddParam("@LogContent", content); db.ExecuteCommand(cmd.Command); } /// <summary> /// 更新本地数据库订单状态 /// </summary> /// <param name="orderID">订单编号</param> /// <param name="success">true/false</param> /// <param name="WxTransactionID">微信交易号</param> /// <param name="amount">金额(分)</param> /// <returns></returns> public static bool UpdateOrderState(string orderID, string WxTransactionID, int amount) { IDatabase db = CreateSimidataDB(); CommandHelper cmd = db.CreateSqlProc("usp_Wallet_WXCallbackUpdate"); cmd.AddParam("@OrderID", orderID); cmd.AddParam("@WxTransactionID", WxTransactionID); cmd.AddParam("@Amount", amount);//--单位(分) object o = db.ExecuteScalar(cmd.Command); return o == null ? false : o.ToString().ToUpper() == "OK"; } } //来源:C/S框架网(www.csframework.com) QQ:23404761 使用PostMan测试notify_url地址: 必须返回XML格式的数据给微信服务器: C# Code: <xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg> </xml> 商户本地数据库的日志信息: <本文完> CSFramework.微信后端服务器WebApi开发框架-标准版V1.0 适用开发:快速构建支持多种客户端的服务端程序,支持APP、B/S、C/S跨平台移动终端等。 运行平台:Windows + .NET Framework 4.5 开发工具:Visual Studio 2015+,C#语言 数据库:Microsoft SQLServer 2008R2+(支持多数据库:Oracle/MySql) 一、产品介绍CSFramework.WebApi是服务端快速开发框架(后端框架),借助ASP.NET WebAPI底层架构的强大编程能力,封装成为可复用的以及可定制开发的服务端软件模板,CSFramework.WebApi提供可复用的软件架构和开发包,为用户快速轻松搭建基于HTTP协议、HTTPS协议以及支持多种客户端(如:APP、B/S、C/S、微信公众号、微信小程序等)各种跨平台移动终端的服务端应用程序。 服务端应用开发、后端接口开发是软件项目重要工作环节,服务端注重业务逻辑、数据处理和数据分析、算法等方面的设计和服务,前端主要体现在用户体验、界面操作和数据采集方面。前端软件系统和后端服务架构共同搭建跨平台大型数据管理应用系统。 扫一扫加微信:
参考文档:
C#实现UDP穿透NAT(UDP打洞)完整版(原) C#.Net 上传图片,限制图片大小,检查类型完整版 C#.Net组件开发(高级篇) - 全部源码下载 C#.NET MVC WebApi后台开发框架入门完整版下载 Adobe Photoshop CS6完整版(1.18GB)安装程序下载与破解 微信支付后台服务器返回的接口通知notify_url(回调接口设计)-C/S框架网 LianLianPay连连支付数字签名验签工具C#源码 CSFramework WebApi服务端框架开发微信支付接口成功案例 C# 格式化CodeHighlighter生成的SQL脚本高亮着色源码(CSFramework.com原创) 模拟搜索引擎中文自动分词算法精华(CSFramework特别提供C#源码) 原创:C#源码 GridMovetor按回车自动跳到下一列或自动新增记录(www.csframework.com) C#源码-Csharp某橱柜销售企业ERP管理系统-源码下载 C#源码-网上银行在线安全支付源码-源码下载 C#源码-微信营销系统(第三方微信平台)C#完整源代码-源码下载 C#源码-医疗管理系统CS(winform)版本-源码下载
其它资料:
什么是C/S结构? | C/S框架核心组成部分 | C/S框架-WebService部署图 | C/S框架-权限管理 | C/S结构系统框架 - 5.1旗舰版介绍 | C/S结构系统框架 - 功能介绍 | C/S结构系统框架 - 产品列表 | C/S结构系统框架 - 应用展示(图) | 三层体系架构详解 | C/S架构轻量级快速开发框架 | C/S框架网客户案例 | WebApi快速开发框架 | C/S框架代码生成器 | 用户授权注册软件系统 | 版本自动升级软件 | 数据库底层应用框架 | CSFramework.CMS内容管理系统 | |