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

本次扫码支付为:电脑生成二维码,手机微信扫码进行付款。建议开发前下载官方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. leetcode169

    public class Solution { public int MajorityElement(int[] nums) { Dictionary<int, int> dic = ne ...

  2. 同步锁Lock(互斥锁)

    同步锁作用: 在我当前包含(lock.acquire() 和 lock.release()之间 )的代码没有执行完成,不进行线程切换,必须等我执行完了,下一个线程才能继续执行(为什么要用同步锁,假如我 ...

  3. mysql 表结构

    1.登录数据库>mysql -u root -p 数据库名称 2.查询所有数据表>show tables; 3.查询表的字段信息>desc 表名称; 4.1添加表字段 alter t ...

  4. H5地理位置信息、微信摇一摇

    geolocation window.navigator.geolocation 1.getCurrentPosition() // 获取当前的位置信息 2.watchPosition() // 监视 ...

  5. SpringBoot打成jar包的配置方式

    pom.xml中添加Springboot插件 <build> <plugins> <plugin> <groupId>org.springframewo ...

  6. Unity 2017 Game Optimization 新版

    英文原版,PDF格式带目录,非常不错的关于性能优化的书籍 扫码时备注或说明中留下邮箱 付款后如未回复请至https://shop135452397.taobao.com/ 联系店主

  7. [leetcode]31. Next Permutation下一个排列

    Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...

  8. java 远程debug

    在启动jar包添加如下参数16091是端口 java -Xdebug -Xrunjdwp:transport=dt_socket,address=16091,server=y,suspend=n -j ...

  9. kubernetes promethues预警、报警

    k8s addon中prometheus为测试事例,官方推荐生产环境使用Prometheus Operator and kube-prometheus. 1.clone 源码 git clone ht ...

  10. Linux top命令中CPU信息的详解(转)

    add by zhj: 下面的文章解释的很好了,这里再说明一下top命令中wa的含义,我们知道,当IO阻塞时,操作系统会把进程改为阻塞态,将CPU调度到运行其它进程. CPU在空闲状态下,会检查是否有 ...