项目需求:学校学生网上缴费项目,刚来公司实习网上百度了各种资料,感谢很多大神避免了很多大坑。

本次扫码支付为:电脑生成二维码,手机微信扫码进行付款。建议开发前下载官方demo熟悉及后续有用到里面代码:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

1.微信公众平台→支付配置→支付授权目录(授权目录就是指你要进行支付的目录)添加你的项目发布文件网址,手上暂无公司微信公众平台账号,百度上下有什么详细说明就不再说明了。

2.新建MVC项目→新建文件夹Resources将官方demo中的business和lib文件夹复制过来

3.打开lib文件夹里的config,在这里配置基础信息和支付回调地址

4.新建WxPay页面,此页面展示付款二维码,采用了jquery.qrcode.min.js生成二维码,贴部分重要代码

<script language="javascript">
$(function () {
GetWXQRCode();
}); function GetWXQRCode() {
//$('#QRCode').css('display', ''); //去除隐藏
//$('#paytitle').html('微信支付');
$('#tradeno').html('');
$('#paymoney').html('');
$.ajax({
type: "post",
url: "/StudentIndex/GetWXQRCode",
data: {
time: new Date(),
productId: "考试费用",
idcard: '@ViewBag.idcard',
},
success: function (json) {
if (json.result) {
$("#QRCode").qrcode(json.str); //生成二维码
$("#tradeno").html(json.no); //订单编号
$('#paymoney').html(json.money);
}
else {
$("#QRCode").html("二维码生成失败");
}
},
error: function (json) {
$("#QRCode").html("二维码生成错误");
}
})
} <div class="i_ma">
<div class="i_name">
微信支付
<p>WeChat Payment</p>
</div>
<div class="space_hx">&nbsp;</div> <div>订单编号:<p id="tradeno"></p></div>
<div>考试费用:<p id="paymoney"></p></div>
<div id="QRCode">
</div> </div> <div class="space_hx">&nbsp;</div>

5.控制器内添加生成二维码方法,这里面的idcard是学生身份证,添加到附加数据内便于后面查询订单时判断是谁缴了费

 //生成微信支付二维码
[HttpPost]
public ActionResult GetWXQRCode(string idcard)
{
object objResult = "";
string tradeno;
string paymoney;
string strProductID = Request.Form["productId"]; //商品ID
string strQRCodeStr = GetWXPayUrl(strProductID, idcard, out tradeno, out paymoney);
//Session["outtradeno"] = outtradeno;
if (!string.IsNullOrWhiteSpace(strProductID))
{
objResult = new { result = true, str = strQRCodeStr, no = tradeno, money = paymoney };
}
else
{
objResult = new { result = false };
} return Json(objResult);
} //生成直接微信支付url,支付url有效期为10分钟,模式二
public string GetWXPayUrl(string productId, string idcard, out string out_trade_no, out string money)
{
WxPayData data = new WxPayData();
data.SetValue("body", "分类考试学费");//商品描述
data.SetValue("attach", idcard);//附加数据
out_trade_no = WxPayApi.GenerateOutTradeNo();
//Session["out_trade_no"] = out_trade_no;
data.SetValue("out_trade_no", out_trade_no);//随机字符串
string total = Convert.ToInt32((context.receiptInfoModel.OrderBy(x => x.ID).FirstOrDefault().PayMoney * )).ToString();
money = context.receiptInfoModel.OrderBy(x => x.ID).FirstOrDefault().PayMoney + "元";
data.SetValue("total_fee", total);//总金额
data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
data.SetValue("time_expire", DateTime.Now.AddMinutes().ToString("yyyyMMddHHmmss"));//交易结束时间
data.SetValue("goods_tag", "商品的备忘,可以自定义");//商品标记
data.SetValue("trade_type", "NATIVE");//交易类型
data.SetValue("product_id", productId);//商品ID
WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口
string url = result.GetValue("code_url").ToString();//获得统一下单接口返回的二维码链接
PreWxPayOrder(idcard, out_trade_no);
return url;
} //生成二维码同时,生成预支付订单
public void PreWxPayOrder(string idcard, string out_trade_no)
{
WxPayOrderModel model = new WxPayOrderModel();
model.StudentCard = idcard;
model.OrderNo = out_trade_no;
model.OrderTime = DateTime.Now;
model.Status = ;
model.OrderType = "微信";
context.wxpayOrderModel.Add(model);
context.SaveChanges();
//Log.Info("生成预支付订单","订单号:"+out_trade_no);
}

6.新建wxpayok页面(此页面是config里配置的支付回调url),视图不需要改动,在控制器里添加接收微信返回的数据

        //接收微信返回信息
public ActionResult WxPayOK()
{
//接收从微信后台POST过来的数据
System.IO.Stream s = Request.InputStream;
int count = ;
byte[] buffer = new byte[];
StringBuilder builder = new StringBuilder();
while ((count = s.Read(buffer, , )) > )
{
builder.Append(Encoding.UTF8.GetString(buffer, , count));
}
s.Flush();
s.Close();
s.Dispose(); //转换数据格式并验证签名
WxPayData data = new WxPayData();
try
{
data.FromXml(builder.ToString());
}
catch (WxPayException ex)
{
//若签名错误,则立即返回结果给微信支付后台
WxPayData res = new WxPayData();
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", ex.Message);
Log.Error("签名错误", "Sign check error : " + res.ToXml());
Response.Write(res.ToXml());
Response.End();
} ProcessNotify(data); return View();
} //微信支付后台返回的数据
public void ProcessNotify(WxPayData data)
{
WxPayData notifyData = data; //检查支付结果中transaction_id是否存在
if (!notifyData.IsSet("transaction_id"))
{
WxPayData res = new WxPayData();
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", "支付结果中微信订单号不存在");
Log.Error("ERROR", "订单号不存在");
Response.Write(res.ToXml());
Response.End();
}
else
{
string transaction_id = notifyData.GetValue("transaction_id").ToString();
if (!QueryOrder(transaction_id))
{
WxPayData res = new WxPayData();
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", "订单查询失败");
Log.Error("ERROR", "订单查询失败");
Response.Write(res.ToXml());
Response.End();
}
else
{
WxPayData res = new WxPayData();
res.SetValue("return_code", "SUCCESS");
res.SetValue("return_msg", "OK");
//Log.Info("success", "支付成功");
AddWayPayRecord(data.GetValue("out_trade_no").ToString(), data.GetValue("transaction_id").ToString(), data.GetValue("attach").ToString());
Response.Write(res.ToXml());
Response.End();
}
}
} //查询订单
public bool QueryOrder(string transaction_id)
{
WxPayData req = new WxPayData();
req.SetValue("transaction_id", transaction_id);
WxPayData res = WxPayApi.OrderQuery(req);
if (res.GetValue("return_code").ToString() == "SUCCESS" &&
res.GetValue("result_code").ToString() == "SUCCESS")
{
return true;
}
else
{
return false;
}
} //微信支付完成添加记录 tradeno:订单号
public void AddWayPayRecord(string tradeno, string tranid, string idcard)
{
lock (wxlock)//线程同步
{
WxPayOrderModel wxpayOrderModel = context.wxpayOrderModel.FirstOrDefault(x => x.OrderNo == tradeno && x.OrderType == "微信" && x.StudentCard == idcard && x.Status == );
if (wxpayOrderModel != null)
{
wxpayOrderModel.Status = ;
context.Entry(wxpayOrderModel).State = System.Data.EntityState.Modified;
context.SaveChanges(); StudentModel studentModel = context.studentModel.Where(a => a.identityCard == wxpayOrderModel.StudentCard).FirstOrDefault();
PayModel payModel = context.payModel.FirstOrDefault(x => x.studentid == studentModel.candidateNum);
Random rd = new Random(); if (payModel == null)
{
PayModel paymodel = new PayModel();
paymodel.paycount = context.receiptInfoModel.OrderBy(x => x.ID).FirstOrDefault().PayMoney;
paymodel.ordernumber = tradeno;
paymodel.paytime = DateTime.Now;
paymodel.PayOddNum = tranid;
context.payModel.Add(paymodel);
context.SaveChanges();
}
}
}
}

7.这时候页面也接收到微信返回的数据同时也添加到数据库中,页面上得给用户一个友好提示,告诉他支付成功了。在wxpay页面里加个ajax实时轮询数据库

        $(function () {
setInterval(GetWxPayResult, );
function GetWxPayResult() {
var no = $("#tradeno").text();
$.ajax({
url: "/StudentIndex/WxPayResult",
type: "post",
data: {
idcard: '@ViewBag.idcard',
tradeno:no,
},
success: function (json) {
if (json.result) {
document.location.href = "/StudentIndex/WxPayisOK?idcard=@ViewBag.idcard"+"&&tradeno="+no;
}
else {
}
},
error: function (json) {
alert("错误");
}
})
}
})

同时控制器里需要加上对应的方法,判断支付成功后跳转到一个新的页面wxpayisok

        //ajax轮询支付结果
public ActionResult WxPayResult(string idcard, string tradeno)
{
object data = "";
StudentModel studentModel = context.studentModel.FirstOrDefault(x => x.identityCard == idcard);
PayModel model = context.payModel.FirstOrDefault(x => x.studentid == studentModel.candidateNum);
if (model != null)
{
data = new { result = true };
}
return Json(data);
} //支付完成
public ActionResult WxPayisOK(string idcard, string tradeno)
{
StudentModel studentModel = context.studentModel.FirstOrDefault(x => x.identityCard == idcard);
PayModel model = context.payModel.FirstOrDefault(x => x.studentid == studentModel.candidateNum); if (model != null)
{
return Content("<Script>alert('缴费成功!');window.location.href='/StudentIndex/StudentIndex';</Script>");
}
else
{
return Content("<Script>alert('缴费失败!请保留好支付凭证前往缴费处申请退款');window.location.href='/StudentIndex/StudentIndex';</Script>");
}
}

结尾:第一次写博客有些乱,微信支付安全性还需要提高,项目部署也没经过大批量测试,就直接上线。

到现在也经历过两次几千人的缴费,一分钟缴费好几次,也碰到过网络延迟问题缴费成功后没及时更新数据库和一个浏览器打开两次微信支付界面导致两次缴费只算一次的各种问题。

C# MVC微信扫码支付的更多相关文章

  1. MVC 微信扫码支付

    微信扫码支付有两种模式, 模式一和模式二, 两者具体的区别可参考官网文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 微 ...

  2. Net MVC微信扫码支付

    微信扫码支付+Asp.Net MVC 这里的扫码支付指的是PC网站上面使用微信支付,也就是官方的模式二,网站是Asp.net MVC,整理如下. 一.准备工作 使用的微信API中的统一下单方法,关键的 ...

  3. .NET MVC结构框架下的微信扫码支付模式二 API接口开发测试

    直接上干货 ,我们的宗旨就是为人民服务.授人以鱼不如授人以渔.不吹毛求疵.不浮夸.不虚伪.不忽悠.一切都是为了社会共同进步,繁荣昌盛,小程序猿.大程序猿.老程序猿还是嫩程序猿,希望这个社会不要太急功近 ...

  4. ASP.NET Core Web 支付功能接入 微信-扫码支付篇

    这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入微信-扫码支付及异步通知功能. 开发环境:Win 10 x64.VS2017 15.6.4..NET Core SDK ...

  5. 【转载】ASP.NET Core Web 支付功能接入 微信-扫码支付篇

    转自:http://www.cnblogs.com/essenroc/p/8630730.html 这篇文章将介绍ASP.NET Core中使用 开源项目 Payment,实现接入微信-扫码支付及异步 ...

  6. asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1

    2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...

  7. 微信支付-微信公众号支付,微信H5支付,微信APP支付,微信扫码支付

    在支付前,如果使用第三方MVC框架,则使用重写模式,服务器也需要配置该项 if (!-e $request_filename){ rewrite ^/(.*)$ /index.php/$ last; ...

  8. JAVA微信扫码支付模式二功能实现完整例子

    概述 本例子实现微信扫码支付模式二的支付功能,应用场景是,web网站微信扫码支付.实现从点击付费按钮.到弹出二维码.到用户用手机微信扫码支付.到手机上用户付费成功.web网页再自动调整到支付成功后的页 ...

  9. ASP.NET Core Web 支付功能接入 微信-扫码支付篇(转)

    原文 https://www.cnblogs.com/essenroc/p/8630730.html // 随着版本更迭,新版本可能无法完全适用,请参考仓库内的示例. 这篇文章将介绍ASP.NET C ...

随机推荐

  1. Jmeter正则表达式提取器(转载)

    转载自 http://blog.csdn.net/qq_35885203 使用jmeter来测试时,经常会碰到需要上下文传输数据的情况,如登录后生成的token,在其他页面的操作,都需传入这个toke ...

  2. centos7安装mysql客户端

    1.判断是否已安装 [root@k8s-master master]# which mysql /usr/bin/which: no mysql in (/usr/local/sbin:/usr/lo ...

  3. 《Spring_Four》第三次作业——基于Jsoup的大学生考试信息展示系统的原型设计与开发

    <Spring_Four团队>第三次团队项目——基于Jsoup的大学生考试信息展示系统的原型设计与开发 一.实验目的与要求 (1)掌握软件原型开发技术: (2)学习使用软件原型开发工具:本 ...

  4. C++ 50学习 之提高对 C++的认识

    转自Effective C++ 理解设计目标. 1.和 C 的兼容性. 2.效率. C++在效率上可以和 C 匹 敌 ---- 二者相差大约在 5%之内. 3.和传统开发工具及环境的兼容性. 4.解决 ...

  5. 《DOM Scripting》学习笔记-——第三章 DOM

    <Dom Scripting>学习笔记 第三章 DOM 本章内容: 1.节点的概念. 2.四个DOM方法:getElementById, getElementsByTagName, get ...

  6. JQEUERY案例

    案例效果: 点击显示全部奶粉品牌前: 点击后: 源码: <!DOCTYPE html><html><head> <meta charset="utf ...

  7. MFC笔记3

    1. C6有默认的提示代码功能,但是其默认的快捷键是Ctrl + Space,这一般情况下是切换输入法快捷键,所以,只需重新设置一下快捷键就可以实现提示代码功能,具体设置位置如下: 工具(T) -&g ...

  8. JAVA中的配置文件XML

    一:概念 1.XML  Extensible markup Language 可拓展标记语言 2.功能:存储数据(配置文件,在网络中传输数据) 3.html和xml的区别 3.1xml标记全是自定义的 ...

  9. 【Django】RROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)

    刚刚启动项目的时候,突然报了这个错误.之前一直正常 后来百度一下,让我在window的host文件下,把被注释的127.0.0.1   localhost这个的注释取消 然鹅并木有用 直接用cmd连接 ...

  10. Mysql 提升大数据表的拷贝效率

    工作上会经常遇到量级比较大的数据表  :场景: 该数据表需要进行alter操作 比如增加一个字段,减少一个字段. 这个在一个几万级别数据量的数据表可以直接进行alter表操作,但是要在一个接近1000 ...