等了好久,微信官方终于发布了.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端发起微信扫码支付的更多相关文章

  1. Java SpringMVC实现PC端网页微信扫码支付完整版

    一:前期微信支付扫盲知识 前提条件是已经有申请了微信支付功能的公众号,然后我们需要得到公众号APPID和微信商户号,这个分别在微信公众号和微信支付商家平台上面可以发现.其实在你申请成功支付功能之后,微 ...

  2. PC端网站微信扫码登录

    需求分析:用户通过扫描我们网页的二维码,如果已经绑定我们平台的账户,即成功进入首页,否则提示先绑定个人微信账号. 1.绑定微信账号:是通过关注微信公众号实现绑定个人微信账号.首先通过后台接口获取到ti ...

  3. 【微信开发】PC端 微信扫码支付成功之后自动跳转

    场景: PC端   微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实现方法: html部分: ...

  4. PHP PC端微信扫码支付【模式二】详细教程-附带源码(转)

    博主写这破玩意儿的时候花了大概快两天时间才整体的弄懂逻辑,考虑了一下~还是把所有代码都放出来给大家~抱着开源大无私的精神!谁叫我擅长拍黄片呢?同时也感谢我刚入行时候那些无私帮过我的程序员们! 首先还是 ...

  5. PC端微信扫码支付和支付宝跳转支付

    import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; impo ...

  6. C#版微信公众号支付|微信H5支付|微信扫码支付问题汇总及解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存.代码在文章结尾处,有需要的 ...

  7. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

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

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

  9. 微信扫码支付springboot版本

    发布时间:2018-11-06   技术:springboot+freemarker   概述 该项目是一个采用springboot构建的web项目,主要实现了微信扫码支付功能.包含最基本的创建订单, ...

随机推荐

  1. GCC编译器编译链接

    在gcc编译器环境下,常见的文件扩展名的含义如下: .c:C源程序,经过预编译后的源程序也为.c文件,它可以通过-E参数输出. .h:头文件 .s:经过编译得到的汇编程序代码,它可以通过-S参数输出. ...

  2. iOS求职之OC面试题

    1.Objective-C的类可以多重继承么?可以采用多个协议么? 答:不可以多重继承,可以采用多个协议. 2.#import和#include的区别是什么?#import<> 跟 #im ...

  3. The Layout Process on Mac OSX and iOS

    First we will recap the steps it takes to bring views on screen with Auto Layout enabled. When you’r ...

  4. CSS行内元素和块级元素的居中

    一.水平居中 行内元素和块级元素不同,对于行内元素,只需在父元素中设置text-align=center即可; 对于块级元素有以下几种居中方式: 1.将元素放置在table中,再将table的marg ...

  5. SQLAlchemy一对多总结

    1.SQLAlchemy之一对多关系 1.1 创建单表 class Test(Base): __tablename__ = 'user' nid = Colume(Integer,primary_ke ...

  6. Python培训12期-day2作业-购物车

    #!/usr/bin/env python import sys import os import getpass 商品={ '图书': { "<Puppet实战>": ...

  7. Nagios NSclient Failed to get CPU value: \238(_total)\6: Failed to get mutex :(

    一台Windows Server 2012的nsclient出现以下的错误,表示无法获得CPU信息 2016-08-08 10:31:33: e:..\..\..\..\trunk\modules\C ...

  8. 多线程下HttpContext.Current 的问题

    在项目中需要记录文本日志,为了加快响应速度所以用到了多线程. 但是以前的方法是不支持多线程的,程序运行错误. 追踪代码发现提示HttpContext为空. 1.HttpContext.Current表 ...

  9. JS URL参数传递 谷歌乱码解决

    //第一个页面 var name=encodeURIComponent("参数"); var url="test1.html?name="+name; //第二 ...

  10. pooling方法修改方案

    http://blog.csdn.net/malefactor/article/details/51078135#0-tsina-1-38411-397232819ff9a47a7b7e80a4061 ...