微信原生支付 Native扫码支付( V3.3.7 版本)
原文:微信原生支付 Native扫码支付( V3.3.7 版本)
[尊重别人的劳动成果,转载请注明出处:一缕晨光工作室,www.wispdawn.com]
前言
辛苦研究三天,遇到各种困难,最终还是克服了,把我的理解和思路分享给需要帮助的人,如果你觉的好,请帮我分享一下,谢谢。 在没有做之前,我以为和支付宝,以及银联一样,会在官网找到相应的demo,照葫芦画瓢即可,没有什么复杂的,真正去做的时候,发现各种错误,很多时候都莫名其妙找不到北, 在网上搜了不知道多少遍,有V3版的,不过都是js api版本的,没有找到原生扫码支付,下了几个V2版本的微信支付c#demo,感觉乱糟糟的。官网只提供了一个php版本的demo 研究了一天没有结果,第二天我决定从官网的php的原生扫码支付,根据他的逻辑,用c#写出来,下面就是所有思路及代码,文章最后我放上整个解决方案压缩包。
想实现扫码支付需要三大步骤
- 生成二维码,二维码包含产品ID
- 微信公众平台->微信支付->配置支付回调URL(自己开发回调页面)
- 开发支付成功后通知页面
最终效果如图
下面一步一步讲解
这步骤比较简单,根据官网文档 ,需要固定的参数,其中签名算法已经写好,如下代码
下图是用于生成二维码字符串,
public string CreateQRCodeUrl(string productid)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("appid", helper.GetAppId);
dic.Add("mch_id", helper.GetMch_Id);
dic.Add("nonce_str", TenpayUtil.getNoncestr());
dic.Add("product_id", productid);
dic.Add("time_stamp", TenpayUtil.getTimestamp());
dic.Add("sign",helper.GetSign(dic)); string url = WxPayHelper.FormatBizQueryParaMap(dic, false);//这里不要url编码
return "weixin://wxpay/bizpayurl?" + url;
}
生成微信二维码字符串
最终生成的url
weixin://wxpay/bizpayurl?appid=wxed94e****9b4bc&mch_id=122468****&nonce_str=877A9BA7A98F75B90A9D49F53F15A858& product_id=1&sign=B2A03B1B6583972FF67C8AD3D7414DD1&time_stamp=1420466744
有了文本想生成二维码就简单了,起初我是采用ThoughtWorks.QRCode.dll,后来发现一值报错,超出数组范围,估计是字符串太长了,最后选择使用一个开源项目 Gma.QrCodeNet.Encoding.dll,速度很快。
代码如下
WxPayHelper helper = new WxPayHelper();
public void ProcessRequest(HttpContext context)
{
if (context.Request["buynum"]!=null)
{
string proId ="";//示例代码写死了,自己根据业务处理
string qrurl = CreateQRCodeUrl(proId); QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
Gma.QrCodeNet.Encoding.QrCode qrCode = new Gma.QrCodeNet.Encoding.QrCode();
qrEncoder.TryEncode(qrurl, out qrCode);
using (MemoryStream ms = new MemoryStream())
{
var renderer = new GraphicsRenderer(new FixedModuleSize(, QuietZoneModules.Two));
renderer.WriteToStream(qrCode.Matrix, ImageFormat.Png, ms);
context.Response.ContentType = "image/png";
context.Response.OutputStream.Write(ms.GetBuffer(), , (int)ms.Length);
}
}
}
生成二维码
前台js调用
$(function () {
$("#txtKey").keyup(function () {
var num=$(this).val();//这里设置购买数量
$("#qrDiv").html("<img src=QrCode.ashx?buynum="+num+" height=200 width=200 /> ");
});
});
这个页面主要任务是当扫码二维码的时候,微信向这个页面post XML数据,其中包含产品id,即二维码上的产品id ,我们需要根据产品id,查询产品名称,总价格,以及一些附属信息, 我们需要再次把这些参数post给微信统一支付接口,如果数据正确,微信会给我们生成一个prepay_id 预支付id,我们再次把prepay_id post给微信,整个流程即是这样子的,其实产品id就相当于一个订单号,唯一性,当然你也可以根据产品id,在这个页面里面下单,业务根据自己需要处理。
页面代码如下
log4net.ILog logger = WxV3.Helper.LogHelper.GetInstance().Log;
WxV3.Helper.WxPayHelper helper = new Helper.WxPayHelper();
protected void Page_Load(object sender, EventArgs e)
{
//1.接受微信平台post 过来的XML信息
//2.验证签名,从XML中获取ProductID,获取产品信息
//2.1设置out_trade_no,total_fee,notify_url,trade_type,product_id 参数,提交统一接口
//3.提交统一接口后获取PrepayId
//4.将PrepayId 和return 根据参数拼接生xml信息(其中包含生成的package参数)输出
if (Request.RequestType == "POST")
{
try
{
StreamReader reader = new StreamReader(Request.InputStream);
String xmlData = reader.ReadToEnd();
helper.ReceivePostXmlData(xmlData);
logger.Info("接收post来的xmlData=" + xmlData);
if (helper.CheckSign())
{
logger.Info("签名验证通过");
string proId = helper.GetProductId();
logger.Info("产品id=" + proId); switch (proId)
{
case "": #region 业务处理
helper.SetParameter("body", "一缕晨光CMS系统");
helper.SetParameter("out_trade_no", DateTime.Now.ToString("yyyyMMddHHmmss") + CommonUtil.BuildRandomStr());
helper.SetParameter("total_fee", "");//这里单位是分
helper.SetParameter("notify_url", "http://www.wispdawn.com/WxV3/NativeNotify.aspx");
helper.SetParameter("trade_type", "NATIVE");
string prepay_id = helper.GetPrepayId();
logger.Info("prepay_id=" + prepay_id);
if (!string.IsNullOrEmpty(prepay_id))
{
helper.SetReturnParameter("return_code", "SUCCESS");
helper.SetReturnParameter("result_code", "SUCCESS");
helper.SetReturnParameter("prepay_id", prepay_id);
helper.SetReturnParameter("appid", helper.GetAppId);
helper.SetReturnParameter("mch_id", helper.GetMch_Id);
helper.SetReturnParameter("nonce_str", TenpayUtil.getNoncestr());
}
else
{
helper.SetReturnParameter("return_code", "SUCCESS");//返回状态码
helper.SetReturnParameter("result_code", "FAIL");//业务结果
helper.SetReturnParameter("err_code_des", "预订单生产失败");
}
#endregion break;
default:
helper.SetReturnParameter("return_code", "SUCCESS");//返回状态码
helper.SetReturnParameter("result_code", "FAIL");//业务结果
helper.SetReturnParameter("err_code_des", "此商品无效");//业务结果
break;
}
}
else
{
helper.SetReturnParameter("return_code", "FAIL");
helper.SetReturnParameter("return_msg", "签名失败");
logger.Info("签名验证没有通过");
}
string xmlStr = helper.GetReturnXml();
logger.Info("返回xml=" + xmlStr);
Response.ContentType = "text/xml";
Response.Clear();
Response.Write(xmlStr);
Response.End();
}
catch (Exception ex)
{
logger.Error("异常了", ex);
}
}
}
NativeCallBack代码
这个页面用来处理成功通知的,微信把交易的结果依xml形式post该页面,当你收到消息后,如果成功了,你可以根据此来修改数据库,或者更新状态,等等。我做到这步时候,需要实现扫码二维码,支付成功后,3秒后调整, 实现思路是这样的,在二维码页面,setinterval get后台数据库是否已经支付,如果已经支付则执行settimeout 3秒后调整到成功页面。目前我是这样实现的,不知道别人怎么实现的。
通知代码如下。
log4net.ILog logger = WxV3.Helper.LogHelper.GetInstance().Log;
WxV3.Helper.WxPayHelper helper = new Helper.WxPayHelper();
protected void Page_Load(object sender, EventArgs e)
{
if (Request.RequestType == "POST")
{
try
{
StreamReader reader = new StreamReader(Request.InputStream);
String xmlData = reader.ReadToEnd();
helper.ReceivePostXmlData(xmlData);
logger.Info("Notify_接收post来的xmlData=" + xmlData);
if (helper.CheckSign())
{
Dictionary<string, string> dicBack = helper.GetParameter();//获取所有参数
if (dicBack!=null&&dicBack.Keys.Contains("return_code"))
{
if (dicBack["return_code"] == "SUCCESS")
{
logger.Info("return_code=SUCCESS");
if (dicBack["result_code"]=="SUCCESS")
{
logger.Info("result_code=SUCCESS");
string out_trade_no = dicBack["out_trade_no"];//商户订单号
logger.Info("out_trade_no="+out_trade_no); //1.验证商户订单号是否被处理
//2.处理过直接返回成功,否则返回
//此处根据out_trade_no 处理业务数据 //处理业务数据结束 logger.Info("Notify_验证签名成功");
helper.SetReturnParameter("return_code", "SUCCESS");
helper.SetReturnParameter("return_msg", "");
}
}
if (dicBack["return_code"]=="FAIL")
{
logger.Info("Notify_验证签名成功");
helper.SetReturnParameter("return_code", "SUCCESS");
helper.SetReturnParameter("return_msg", dicBack["return_msg"]);
}
}
}
else
{
logger.Info("Notify_验证签名失败");
helper.SetReturnParameter("return_code", "FAIL");
helper.SetReturnParameter("return_msg", "签名失败");
}
string xmlStr = helper.GetReturnXml();
logger.Info("Notify_返回xml=" + xmlStr);
Response.ContentType = "text/xml";
Response.Clear();
Response.Write(xmlStr);
Response.End();
}
catch (Exception ex)
{
logger.Error("Notify_异常了", ex);
}
}
}
NativeNotify页面代码
如果你也是需要扫描原生支付,可以直接下载本解决方案,只需要把 WxPayHelper构造函数中的参数修改下即可使用
public WxPayHelper()
{
this.parameters = new Dictionary<string, string>();
this.returnParameter = new Dictionary<string, string>();
this.appid = "wxed94e6985d29****";//appid
this.mch_id = "122468****"; //微信支付商户号
this.PartnerKey = "ASD2Ssaghh3df4570erdssd4we33****";//这里是商户的partnerkey
}
本文主要讲解整个思路,详细请看代码,点击下载本解决方案
尊重别人的劳动成功,转载请注明出处:一缕晨光工作室,www.wispdawn.com
微信原生支付 Native扫码支付( V3.3.7 版本)的更多相关文章
- 微信支付Native扫码支付模式二之CodeIgniter集成篇
CI:3.0.5 微信支付API类库来自:https://github.com/zhangv/wechat-pay 请先看一眼官方场景及支付时序图:https://pay.weixin.qq.com/ ...
- asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1
2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...
- 微信支付之扫码支付、公众号支付、H5支付、小程序支付相关业务流程分析总结
前言 很久以来,一直想写一篇微信支付有关的总结文档:一方面是总结自己的一些心得,另一方面也可以帮助别人,但是因种种原因未能完全理解透彻微信支付的几大支付方式,今天有幸做一些总结上的文章,也趁此机会,将 ...
- php实现支付宝在线支付和扫码支付demo
### php实现支付宝在线支付和扫码支付demo 背景:在做一个公众号时增加了h5端,需要接入支付,非微信环境,选择了支付宝,以下简单记录下实现过程,并做了简单的封装,拿来即可使用,注意:本项目只是 ...
- 支付宝支付之扫码支付(电脑网站支付)、H5支付(手机网站支付)相关业务流程分析总结
前言 在上一篇文章<微信支付之扫码支付.公众号支付.H5支付.小程序支付相关业务流程分析总结>中,分析和总结了微信支付相关支付类型的业务流程,这里作为与微信支付平起平坐不相伯仲的支付宝支付 ...
- [支付]微信NATIVE扫码支付JAVA实现
步骤: 1.预订单 2.接受微信返回的url 3.将url转为二维码显示到页面上 4.扫码支付 5.接收微信的异步通知,在这步修改订单的状态 6.收到异步通知的同时给微信返回指定数据,告知对方已成功处 ...
- java实现微信支付之扫码支付
本文直接从代码调用微信扫码支付讲起.账号配置,参数生成等请参考官方文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 微信 ...
- 微信支付之扫码支付开发:我遇到的坑及解决办法(附:Ecshop 微信支付插件)
前段时间帮一个朋友的基于ecshop开发的商城加入微信扫描支付功能,本以为是很简单的事儿——下载官方sdk或开发帮助文档,按着里面的做就ok了,谁知折腾了两三天的时间才算搞定,中间也带着疑问在网上找了 ...
- asp.net core 微信公众号支付(扫码支付,H5支付,公众号支付,app支付)之3
在微信公众号中访问手机网站,当需要调用支付时候无法使用H5支付,只有使用微信公众号支付,使用公众号支付用户必须关注该公众号同时该公众号必须开通公众号支付功能. 1.获取用户的OpenId ,参考之前写 ...
随机推荐
- php+sqlite cms
1 phpSQLiteCMS 最新版本 phpSQLiteCMS 2.0.4 http://phpsqlitecms.net/ 2 taoCMS 最新版本 [2.5Beta5下载地址] 需要php ...
- ORACLE—002:Create创作型
--用于工作的积累SQL ORACLE另外还有的类型.储过程.函数等的输入输入出. 以下看下创建. 使用方法 CREATE OR REPLACE TYPE 类型名称 AS OBJECT( 字段1 ...
- jQuery 完成ajax传jsonObject数据,并在后台处理
效果图: 1.js文件封装的几个js工具 <span style="font-family:KaiTi_GB2312;font-size:18px;">//兼容ie i ...
- [原创].NET 业务框架开发实战之八 业务层Mapping的选择策略
原文:[原创].NET 业务框架开发实战之八 业务层Mapping的选择策略 .NET 业务框架开发实战之八 业务层Mapping的选择策略 前言:在上一篇文章中提到了mapping,感觉很像在重新实 ...
- [创意标题] spoj 11354 Amusing numbers
意甲冠军: 给k(1<=k<=10^15),先询问k 大只包含数字5和6的数目是多少 实例 1那是,5 ,3那是,55 .4那是,56 思考: 首先,我们可以找到.有许多2这是头号,有两个 ...
- 房费制 它 结账BUG
声明:以下内容仅仅是对在桌子上的卡与卡表的后面,适合学生的表! 最近,我们已经开始做VB.NET系统重构版,在这里跟大家聊聊我在机房收费系统中发现的漏洞. 在机房收费系统中有这样一个窗口--结 ...
- Swift开发学习(两):Playground
Swift开发学习:Playground 大约 对于软件用户.游戏玩家,我一直提倡用户体验.也是用户,是各种开发工具的使用者.也会喜欢用户体验做得好的工具软件.这次苹果想开发人员所想,提供了一个能够玩 ...
- linux命令之删除
linux删除文件夹非常easy,非常多人还是习惯用rmdir,只是一旦文件夹非空,就陷入深深的苦恼之中,如今使用rm -rf命令就可以. 直接rm就能够了,只是要加两个參数-rf 即:rm -r ...
- MEF初体验之十二:Composition Batch
一个MEF容器实例是不可变的.如果catalog支持改变(像观察一个目录的改变)或是如果你的代码在运行时添加或移除部件,改变都可能发生.以前,你不得不作出改变并在组合容器上调用它的组合方法.在Prev ...
- 对LevelDB的“升级版”存储引擎RocksDB的调研成果
Google的leveldb是个非常优秀的存储引擎.但还是有一些不尽人意的地方,比方leveldb不支持多线程合并.对key范围查找的支持还非常easy,未做优化措施,等等.而Facebook的Roc ...