c#版在pc端发起微信扫码支付
等了好久,微信官方终于发布了.net的demo。
主要代码:
/**
* 生成直接支付url,支付url有效期为2小时,模式二
* @param productId 商品ID
* @return 模式二URL
*/
public string GetPayUrl(string productId, string body, string attach, int total_fee, string goods_tag)
{
Log.Info(this.GetType().ToString(), "Native pay mode 2 url is producing..."); WxPayData data = new WxPayData();
data.SetValue("body", body);//商品描述
data.SetValue("attach", attach);//附加数据
data.SetValue("out_trade_no", productId);//随机字符串
data.SetValue("total_fee", total_fee);//总金额
data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
data.SetValue("time_expire", DateTime.Now.AddMinutes().ToString("yyyyMMddHHmmss"));//交易结束时间
data.SetValue("goods_tag", 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();//获得统一下单接口返回的二维码链接 Log.Info(this.GetType().ToString(), "Get native pay mode 2 url : " + url);
return url;
}
配置信息:
public class Config
{
//=======【基本信息设置】=====================================
/* 微信公众号信息配置
* APPID:绑定支付的APPID(必须配置)
* MCHID:商户号(必须配置)
* KEY:商户支付密钥,参考开户邮件设置(必须配置)
* APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置)
*/
public const string APPID = "你的微信公众号APPID";
public const string MCHID = "你的微信公众号的商户号";
public const string KEY = "你的微信公众号的商户支付密钥";
public const string APPSECRET = "你的微信公众号的APPSECRET"; //=======【证书路径设置】=====================================
/* 证书路径,注意应该填写绝对路径(仅退款、撤销订单时需要)
*/
public const string SSLCERT_PATH = "cert/apiclient_cert.p12";
public const string SSLCERT_PASSWORD = ""; //=======【支付结果通知url】=====================================
/* 支付结果通知回调url,用于商户接收支付结果
*/
public const string NOTIFY_URL = "http://你的网站/Pay/ResultNotifyPage.aspx"; //=======【商户系统后台机器IP】=====================================
/* 此参数可手动配置也可在程序中自动获取
*/
public const string IP = "你的服务器IP"; //=======【代理服务器设置】===================================
/* 默认IP和端口号分别为0.0.0.0和0,此时不开启代理(如有需要才设置)
*/
public const string PROXY_URL = ""; //=======【上报信息配置】===================================
/* 测速上报等级,0.关闭上报; 1.仅错误时上报; 2.全量上报
*/
public const int REPORT_LEVENL = ; //=======【日志级别】===================================
/* 日志等级,0.不输出日志;1.只输出错误信息; 2.输出错误和正常信息; 3.输出错误信息、正常信息和调试信息
*/
public const int LOG_LEVENL = ;
}
不使用代理要注释HttpService.cs里面post和get方法的下面代码:
//设置代理服务器
//WebProxy proxy = new WebProxy(); //定义一个网关对象
//proxy.Address = new Uri(Config.PROXY_URL); //网关服务器端口:端口
//request.Proxy = proxy;
统一下单:
/**
*
* 统一下单
* @param WxPaydata inputObj 提交给统一下单API的参数
* @param int timeOut 超时时间
* @throws WxPayException
* @return 成功时返回,其他抛异常
*/
public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = )
{
string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//检测必填参数
if (!inputObj.IsSet("out_trade_no"))
{
throw new WxPayException("缺少统一支付接口必填参数out_trade_no!");
}
else if (!inputObj.IsSet("body"))
{
throw new WxPayException("缺少统一支付接口必填参数body!");
}
else if (!inputObj.IsSet("total_fee"))
{
throw new WxPayException("缺少统一支付接口必填参数total_fee!");
}
else if (!inputObj.IsSet("trade_type"))
{
throw new WxPayException("缺少统一支付接口必填参数trade_type!");
} //关联参数
if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid"))
{
throw new WxPayException("统一支付接口中,缺少必填参数openid!trade_type为JSAPI时,openid为必填参数!");
}
if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id"))
{
throw new WxPayException("统一支付接口中,缺少必填参数product_id!trade_type为JSAPI时,product_id为必填参数!");
} //异步通知url未设置,则使用配置文件中的url
if (!inputObj.IsSet("notify_url"))
{
inputObj.SetValue("notify_url", Config.NOTIFY_URL);//异步通知url
} inputObj.SetValue("appid", Config.APPID);//公众账号ID
inputObj.SetValue("mch_id", Config.MCHID);//商户号
inputObj.SetValue("spbill_create_ip", Config.IP);//终端ip
inputObj.SetValue("nonce_str", GenerateNonceStr());//随机字符串 //签名
inputObj.SetValue("sign", inputObj.MakeSign());
string xml = inputObj.ToXml(); var start = DateTime.Now; Log.Debug("WxPayApi", "UnfiedOrder request : " + xml);
string response = HttpService.Post(xml, url, false, timeOut);
Log.Debug("WxPayApi", "UnfiedOrder response : " + response); var end = DateTime.Now;
int timeCost = (int)((end - start).TotalMilliseconds); WxPayData result = new WxPayData();
result.FromXml(response); ReportCostTime(url, timeCost, result);//测速上报 return result;
}
看我的调用例子:
MakeQRCode.aspx页面照抄:
public partial class Pay_MakeQRCode : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(base.Request.QueryString["data"]))
{
string str = base.Request.QueryString["data"];
Bitmap image = new QRCodeEncoder
{
QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M,
QRCodeVersion = ,
QRCodeScale =
}.Encode(str, Encoding.Default);
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);
base.Response.BinaryWrite(ms.GetBuffer());
base.Response.End();
}
}
}
这个页面是用来生成二维码的,需要引入ThoughtWorks.QRCode.dll组件。
我使用模式二,回调页面是ResultNotifyPage.aspx,就是在配置信息那里填写的那个回调页面。
protected void Page_Load(object sender, EventArgs e)
{
ResultNotify resultNotify = new ResultNotify(this);
WxPayData res = resultNotify.ProcessNotify2();
if (res.GetValue("return_code") == "SUCCESS")
{
//查询微信订单信息
string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString();
string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString();
string appId = ConfigurationManager.AppSettings["AppId"].ToString(); QueryOrder queryorder = new QueryOrder();
queryorder.appid = appId;
queryorder.mch_id = mch_id;
queryorder.transaction_id = res.GetValue("transaction_id").ToString();
queryorder.out_trade_no = "";
queryorder.nonce_str = TenpayUtil.getNoncestr(); TenpayUtil tenpay = new TenpayUtil();
OrderDetail orderdeatil = tenpay.getOrderDetail(queryorder, paySignKey);
//写微信记录
(new vinson()).WriteReturnWXDetail(orderdeatil);
//写充值记录
FilliedOnline(orderdeatil.out_trade_no);
} Response.Write(res.ToXml());
Response.End();
}
扫码支付成功后会异步到这个页面执行代码,我们自己的业务逻辑就要写在这里。使用微信官方的ProcessNotify()函数可不行,我们稍微修改下就好了。增加ProcessNotify2函数:
public WxPayData ProcessNotify2()
{
WxPayData notifyData = GetNotifyData(); //检查支付结果中transaction_id是否存在
if (!notifyData.IsSet("transaction_id"))
{
//若transaction_id不存在,则立即返回结果给微信支付后台
WxPayData res = new WxPayData();
res.SetValue("transaction_id", "");
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", "支付结果中微信订单号不存在");
return res;
} string transaction_id = notifyData.GetValue("transaction_id").ToString(); //查询订单,判断订单真实性
if (!QueryOrder(transaction_id))
{
//若订单查询失败,则立即返回结果给微信支付后台
WxPayData res = new WxPayData();
res.SetValue("transaction_id", transaction_id);
res.SetValue("return_code", "FAIL");
res.SetValue("return_msg", "订单查询失败");
return res;
}
//查询订单成功
else
{
WxPayData res = new WxPayData();
res.SetValue("transaction_id", transaction_id);
res.SetValue("return_code", "SUCCESS");
res.SetValue("return_msg", "OK");
return res;
}
}
返回WxPayData对象,这样一判断
if (res.GetValue("return_code") == "SUCCESS")
表示支付成功,就可以进入我们的业务逻辑。
然后我们还要对当前订单查单,获取订单的相关信息,之前微信未出demo的时候我自己写了个查单的,就直接用了,关键WxPayData对象会返回微信的订单号:res.GetValue("transaction_id").ToString()。
完事后还要发送信息回给微信,通知微信后台不要继续发送异步请求了:
Response.Write(res.ToXml());
Response.End();
这个代码比较重要了。
再说说放置二维码的页面:
<div class="g-body">
<div class="g-wrap">
<div class="m-weixin">
<div class="m-weixin-header">
<p><strong>请您及时付款,以便订单尽快处理!订单号:<asp:Label ID="trade_no" runat="server" Text="Label"></asp:Label></strong></p>
<p>请您在提交订单后1小时内支付,否则订单会自动取消。</p>
</div>
<div class="m-weixin-main">
<h1 class="m-weixin-title">
<img alt="微信支付" src="../images/wxlogo_pay.png"/>
</h1>
<p class="m-weixin-money"><font>扫一扫付款</font><br/><strong>¥<asp:Label ID="money" runat="server" Text="Label"></asp:Label></strong></p>
<p>
<img id="payQRImg" width="260" height="260" class="m-weixin-code" style="position: absolute;" src="<%=ImageUrl %>" alt="二维码" style="border-width:0px;" />
<img class="m-weixin-demo" src="../images/wxwebpay_guide.png" alt="扫一扫" />
<img style="margin-top:300px;" src="../images/weixin_1.png" alt="请使用微信扫描二维码以完成支付" />
</p>
<p id="we_ok" style="display:none;">
<input value="完成" style="width: 300px; height: 50px; background: rgb(21, 164, 21) none repeat scroll 0% 0%; color: white; font-size: 30px; border: medium none; cursor: pointer;" type="button" />
</p>
</div>
</div>
</div>
</div>
写个js查单支付情况进行显示:
$(function () {
var success = "<%=success %>";
if (success == "error") {
$(".g-body").hide();
}
}) var iCount = setInterval(check, 2000); //每隔2秒执行一次check函数。 function check() {
$.ajax({
contentType: "application/json",
url: "/WebService/vinson.asmx/queryWeiXin",
data: "{OrderID:'" + $("#trade_no").text() + "'}",
type: "POST",
dataType: "json",
success: function (json) {
json = eval("(" + json.d + ")");
if (json.success == "success") {
clearInterval(iCount);
$(".m-weixin-money font").html("已成功付款");
$("#payQRImg").remove();
$(".m-weixin-demo").before('<img alt="" src="../images/wx_ok.jpg" width="200">');
$(".m-weixin-demo").next().remove();
$("#we_ok").show();
}
},
error: function (err, ex) {
}
});
}
是的,我又写了个给ajax使用的查单函数queryWeiXin。
我这里才是生成订单和二维码:
恩,还有啥呢,恩,看看效果吧:
支付成功后:
恩,完事。
c#版在pc端发起微信扫码支付的更多相关文章
- Java SpringMVC实现PC端网页微信扫码支付完整版
一:前期微信支付扫盲知识 前提条件是已经有申请了微信支付功能的公众号,然后我们需要得到公众号APPID和微信商户号,这个分别在微信公众号和微信支付商家平台上面可以发现.其实在你申请成功支付功能之后,微 ...
- PC端网站微信扫码登录
需求分析:用户通过扫描我们网页的二维码,如果已经绑定我们平台的账户,即成功进入首页,否则提示先绑定个人微信账号. 1.绑定微信账号:是通过关注微信公众号实现绑定个人微信账号.首先通过后台接口获取到ti ...
- 【微信开发】PC端 微信扫码支付成功之后自动跳转
场景: PC端 微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实现方法: html部分: ...
- PHP PC端微信扫码支付【模式二】详细教程-附带源码(转)
博主写这破玩意儿的时候花了大概快两天时间才整体的弄懂逻辑,考虑了一下~还是把所有代码都放出来给大家~抱着开源大无私的精神!谁叫我擅长拍黄片呢?同时也感谢我刚入行时候那些无私帮过我的程序员们! 首先还是 ...
- PC端微信扫码支付和支付宝跳转支付
import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; impo ...
- C#版微信公众号支付|微信H5支付|微信扫码支付问题汇总及解决方案总结
最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存.代码在文章结尾处,有需要的 ...
- 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结
最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...
- 微信支付-微信公众号支付,微信H5支付,微信APP支付,微信扫码支付
在支付前,如果使用第三方MVC框架,则使用重写模式,服务器也需要配置该项 if (!-e $request_filename){ rewrite ^/(.*)$ /index.php/$ last; ...
- 微信扫码支付springboot版本
发布时间:2018-11-06 技术:springboot+freemarker 概述 该项目是一个采用springboot构建的web项目,主要实现了微信扫码支付功能.包含最基本的创建订单, ...
随机推荐
- iOS流量精灵完结版
从一开始的激动,到现在的三期完结持续了将近三个半月时间,心态也开始变的坦然. 开发期间没有兑现自己的若言,没有写下所有的感悟和困难.我没有借口可言,唯一能说的只能说自己太懒....哈哈 总体来说流量监 ...
- 2014年4月份第1周51Aspx源码发布详情
基于Extjs4+MVC4权限管理源码 2014-3-31 [VS2012]源码描述: 20140331更新:修改部门管理中bug 20140303更新:增加部门管理模块,主要包含部门添加,编辑,删 ...
- Android ContentResolve使用
在Android中使用ContentResolve访问其他程序的数据: http://developer.android.com/reference/android/content/ContentPr ...
- HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)
题意:告诉一张带权图,不存在环,存下每个点能够到的最大的距离,就是一个长度为n的序列,然后求出最大值-最小值不大于Q的最长子序列的长度. 做法1:两步,第一步是根据图计算出这个序列,大姐头用了树形DP ...
- viewPager动态加载listview数据
废话不多说,先上效果图.(代码见附件) 代码是修改自某大神的,我做了很多修改,之前只能向右滑动,现在可以左右无限滑动,只要数据没加载完就可以一直滑动.过程不算复杂,代码主要的地方都有注释. 附件dem ...
- C++中的vector
opencv中用到了很多vector 整理一下 vector容器是一个模板类,可以存放任何类型的对象(但必须是同一类对象).vector对象可以在运行时高效地添加元素,并且vector中元素是连续存 ...
- [原创]cocos2d-x研习录-第二阶 概念类之场景类(CCScene)
场景类CCScene是Cocos2D-x在屏幕显示的内容,相当于游戏关卡或界面.CCDirector任何时候只能显示一个场景CCScene,游戏中可能存在若干场景,CCDirector通过场景切换达到 ...
- 一个链式调用 setTimeout的例子
<div> 现在时间是:<input type="text" id="name1" size="16" value=&qu ...
- Oracle常见的几种等待事件
1. CPU time CPU time其实不是真正的等待事件.是衡量CPU是否瓶颈的一个重要指标.一般来讲,一个良好的系统,CPU TIME 应该排在TOP 5 TIME Event的最前面. 当然 ...
- 一些关于HTTP协议、表单和……的备忘
几个概念 Ajax是一种技术.asp.net是一个库.json是一种数据格式.jquery是js的库(源码).ror是ruby on rails.python,就是python.Ajax和AJAX,后 ...