2018-08-13更新生成二维码的方法

  在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付、H5支付、公众号支付、App支付等,本人使用的是asp.net mvc core2.0框架开发,core技术目前国内用的不算多,所以本人总结使用asp.net mvc core开发微信支付的一些经验,之前都在博客园学习,没有写过文章,文笔差,欢迎指正。

  首先定义个微信支付参数保存的类,本人定义类如下,具体参数意义就只有去参考微信官方文档了,后台接口开发都将用到这边的参数,若支付不使用公众号支付和app支付的话appSecret参数将不用获取。

public class WxPayConfig
{
public static WxPayConfig Instance = new WxPayConfig(); public string appid = "";//APPID public string mchid = "";//商户号 public string key = "";//商户API密钥 public string appSecret = "";//公众号支付和app支付时候将用到 public string notify_url = "http://www.baidu.com/Pay/WxNotify";//回调页地址 public string api_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信支付调用接口地址
}

  首先说一下扫码支付大体流程,首先微信得开通商户平台得扫码支付功能具体在 https://pay.weixin.qq.com上登陆,填写相关才材料开通扫码支付,开通完成后支付产品里将出现已开通的支付列表,然后使用获取到的参数拼接成对应格式的xml文件上传到微信服务器,如果配置正常服务器将返回一串xml文本,获取xml文本中的code_url地址,将该地址转为图片二维码展示在网站中。

1.申请扫码支付接口


2.配置微信扫码支付回调链接(貌似不配置扫码支付也可以用)


3.编写扫码支付服务, 扫码支付需要用到的appid,mchid,key 等参数,代码如下


首先在nuget中安装Senparc.Weixin.MP

扫码支付服务类方法:

/// <summary>
/// 获取微信扫码支付URL
/// </summary>
/// <param name="out_trade_no">订单号</param>
/// <param name="body">描述</param>
/// <param name="total_fee">总价</param>
/// <param name="ip">客户IP</param>
/// <param name="product_id">商品id</param>
/// <returns></returns>
public string GetWxSMPayUrl(string out_trade_no, string body, string total_fee, string ip, string product_id)
{
Senparc.Weixin.MP.TenPayLibV3.RequestHandler packageReqHandler = new Senparc.Weixin.MP.TenPayLibV3.RequestHandler();
#region 构造请求参数
packageReqHandler.SetParameter("appid", wxPayConfig.appid);//APPID
packageReqHandler.SetParameter("mch_id", wxPayConfig.mchid);//商户号
packageReqHandler.SetParameter("nonce_str", Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr());//随机串
packageReqHandler.SetParameter("body", body);
packageReqHandler.SetParameter("out_trade_no", out_trade_no);//订单号
packageReqHandler.SetParameter("total_fee", (int)(Convert.ToDecimal(total_fee) * 100) + ""); //金额,以分为单位
packageReqHandler.SetParameter("spbill_create_ip", ip);//IP
packageReqHandler.SetParameter("notify_url", wxPayConfig.notify_url); //回调地址
packageReqHandler.SetParameter("trade_type", "NATIVE");//扫码支付
packageReqHandler.SetParameter("product_id", product_id);//商品ID
packageReqHandler.SetParameter("sign", packageReqHandler.CreateMd5Sign("key", wxPayConfig.key));//商户API密钥(签名)
#endregion //将参数转为xml字符串
string data = packageReqHandler.ParseXML();
//发起post异步请求,获取返回的内容
var result = PostWithStringFile(wxPayConfig.api_url, data);
Log.Info("【GetWxSMPayUrl】订单:" + out_trade_no + ",请求得到的xml:" + result, "微信支付"); //解析xml,获取扫码需要的mweb_url。
var res = System.Xml.Linq.XDocument.Parse(result);
try
{
string mweb_url = res.Element("xml").Element("code_url").Value;
Log.Info("【GetWxSMPayUrl】订单:" + out_trade_no + ",请求得到的url:" + mweb_url, "微信支付");
return mweb_url;
}
catch (Exception ex)
{
Log.Info("【GetWxSMPayUrl】订单:" + out_trade_no + ",异常:" + ex.ToString(), "微信支付");
return "";
}
}

  后台控制器中代码参考

/// <summary>
/// ajax请求生成订单,插入订单到数据库,
/// </summary>
/// <param name="body"></param>
/// <param name="total_fee"></param>
/// <param name="product_id"></param>
/// <returns></returns>
public IActionResult GetWxSMPayUrl(string body, string total_fee, string product_id)
{
string no = DateTime.Now.ToString("yyyyMMddHHmmssfff");//构造订单号
//订单相关逻辑代码 //订单相关逻辑代码结束 //构造支付地址信息
WxPayService wxPayService = new WxPayService(); //服务类,自行优化
//获取请求ip
var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault();
if (string.IsNullOrEmpty(ip))
{
ip = HttpContext.Connection.RemoteIpAddress.ToString();
}
string code_url = wxPayService.GetWxSMPayUrl(no, body, total_fee, ip, product_id);
return Content(code_url); //返回支付的Url,前端ajax请求得到该url后,将该url赋值到存放图片的src中 }

  如果业务正常运行ajax将请求得到一串url,后台控制器中添加一个可以根据参数生成二维码图片文件的action,首先在nuget中添加QRCode引用,代码例如

该段代码无效
[HttpGet]
/// <summary>
/// 生成二维码,生成微信扫码支付二维码
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public FileResult MakeQRCode(string data)
{
if (string.IsNullOrEmpty(data))
throw new ArgumentException("data"); //初始化二维码生成工具
QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
qrCodeEncoder.QRCodeVersion = 0;
qrCodeEncoder.QRCodeScale = 4; //将字符串生成二维码图片
Bitmap image = qrCodeEncoder.Encode(data, System.Text.Encoding.Default); //保存为PNG到内存流
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); return File(ms.ToArray(), "image/jpeg");
}
该段代码无效结束

  以上生成二维码的方法是在.net framework下的,而且缺少一个dll的引用,在core平台下无效,替换为如下而在.net core平台应该使用如下方法:

在Home控制器中添加MakeQRCode的方法,代码如下:

public FileResult MakeQRCode(string data)
{
var image = QRCoderHelper.CreateQrcode(data);
MemoryStream ms = new MemoryStream();
image.Save(ms, System.DrawingCore.Imaging.ImageFormat.Jpeg);
return File(ms.ToArray(), "image/jpeg");
}
QRCoderHelper.cs需要引用NUGET里的ZKWeb.Fork.QRCoder,注:如果之前在NUGET中引用了QRCode请将他移除不然无法使用
QRCoderHelper
代码内容如下
using System;
using System.DrawingCore;
using System.DrawingCore.Drawing2D;
using System.DrawingCore.Imaging;
using System.IO;
using QRCoder; public class QRCoderHelper
{
/// <summary>
/// 生成二维码
/// </summary>
/// <returns></returns>
public static Bitmap CreateQrcode(string codeToken, int version = )
{
EncoderParameter myEncoderParameter;
EncoderParameters myEncoderParameters;
QRCodeGenerator qrGenerator = new QRCodeGenerator();
// 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
QRCodeData qrCodeData = qrGenerator.CreateQrCode(codeToken, QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData);
// 设置设置二维码版本,取值范围1-40,值越大尺寸越大,可存储的信息越大(实测9(297*297),10(330*330),20(660*600),每个挡位33左右,3个挡位100个像素)
Bitmap qrCodeImage = qrCode.GetGraphic(version);
Encoder myEncoder = Encoder.Quality;
myEncoderParameters = new EncoderParameters();
myEncoderParameter = new EncoderParameter(myEncoder, 25L);
myEncoderParameters.Param[] = myEncoderParameter;
return qrCodeImage;
}
}
 

  该action作用为请求该方法传入data参数,返回的是该参数值的二维码图片文件,前端src指向该action并加上之前获取得到的code_url信息,格式如下, /Home/MakeQRCode?data=xxxxx,如果img标签正确显示了扫码的图片,那么就大功告成了,支付完成,但是还有支付回调更新订单的逻辑要写。

效果如下:

  这里再贴上微信支付回调的代码

/// <summary>
/// 微信支付异步回调
/// </summary>
/// <returns></returns>
public IActionResult WxNotify()
{
try
{
//使用微信工具获取ResponseHandler
ResponseHandler wxResponseHandler = new ResponseHandler(HttpContext);
string out_trade_no = wxResponseHandler.GetParameter("out_trade_no");//订单号
string total_fee = wxResponseHandler.GetParameter("total_fee");//订单金额,单位分
total_fee = (Convert.ToDecimal(total_fee) / 100).ToString("#0.00");//订单金额,单位元
Log.Info("微信测试收到数据,订单号:" + out_trade_no + "订单金额:" + total_fee, "【微信支付回调】"); //验证订单是否有支付过逻辑
    
//验证订单信息,获取支付配置
WxPayConfig payConfigModel = new WxPayConfig();//后面去可以去配置或者数据库中获取
//验证是否通过微信安全认证
WxPayService wxPayService = new WxPayService();
bool vxCheck = wxPayService.WxPayCheck(wxResponseHandler);//使用sdk去验证
if (vxCheck)
{
//更新订单
//ProcessOrder(out_trade_no);
Log.Info("微信验证成功" + out_trade_no, "【微信支付回调】");
return SuccessRes("");
}
else
{
Log.Info("微信测试失败" + out_trade_no, "【微信支付回调】");
return ErrRes("微信测试失败");
}
}
catch (Exception ex)
{
Log.Error("微信测试回调异常", ex, "【微信支付回调】");
return ErrRes("微信测试回调异常");
} }

  具体业务逻辑实现得看自己的需求,日志类Log和返回成功或者错误信息可自由替换。

附上方法中用到post请求方法

/// <summary>
/// post请求,将字符串转为流上传到url中
/// </summary>
/// <param name="url"></param>
/// <param name="file"></param>
/// <returns></returns>
public string PostWithStringFile(string url, string file)
{
var formDataBytes = file == null ? new byte[0] : Encoding.UTF8.GetBytes(file);//将xml字符串转为字节流
MemoryStream ms = new MemoryStream(formDataBytes);//将字节流转为内存流
StreamContent streamContent = new StreamContent(ms);//封装为StreamContent对象
//发起post异步请求,获取返回的内容
var result = httpClient.PostAsync(wxPayConfig.api_url, streamContent).Result.Content.ReadAsStringAsync().Result;
return result;
} //以及服务类包含字段
#region 字段
public WxPayConfig wxPayConfig = new WxPayConfig();//微信配置文件
public HttpClient httpClient = new HttpClient();//http请求客户端
#endregion

  

附上写日志的一个老师傅写类库Sky.Logger,在项目中添加引用即可使用日志:链接: https://pan.baidu.com/s/1eHdNGZN0pmNHsO_yHzgE_g 密码: ta2x

欢迎指正。

QRCoderHelper

asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1的更多相关文章

  1. 浅析微信支付:微信支付简单介绍(小程序、公众号、App、H5)

    本文是[浅析微信支付]系列文章的第二篇,主要讲解一下普通商户接入的支付方式以及其中的不同之处. 上篇文章讲了本系列的大纲,没有看过的朋友们可以看一下. 浅析微信支付:前篇大纲 微信支付是集成在微信客户 ...

  2. 微信公众号授权,支付,退款总结【shoucang】

    1.支付前准备 1.1首先两个平台接入账户. 商户平台:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F 公众平台: ...

  3. PHP微信公众号JSAPI网页支付(上)

    一.使用场景以及说明 使用场景:商户已有H5商城网站,用户通过消息或扫描二维码在微信内打开网页时,可以调用微信支付完成下单购买的流程. 说明:1.用户打开图文消息或者扫描二维码,在微信内置浏览器打开网 ...

  4. PHP微信公众号JSAPI网页支付(下)

    上一篇PHP微信公众号JSAPI网页支付(上)中讲到了公众号平台的相关设置以及支付的大致流程. 这一篇重点讲支付后,异步接受回调通知,以及处理后同步通知微信服务器. 首先梳理下整个jsapi支付的流程 ...

  5. 一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app

    一步一步教你用 Vue.js + Vuex 制作专门收藏微信公众号的 app 转载 作者:jrainlau 链接:https://segmentfault.com/a/1190000005844155 ...

  6. 微信公众号与APP微信第三方登录账号打通

    一个项目同时开发了APP和微信服务号,需要做到APP和微信服务号的账号互通同步,也就是说一个账号在2个地方都可以用,当然这个前提是保证你公司自己的服务器的数据库用的是同一套. 为保证用户数据的唯一性, ...

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

    在微信公众号中访问手机网站,当需要调用支付时候无法使用H5支付,只有使用微信公众号支付,使用公众号支付用户必须关注该公众号同时该公众号必须开通公众号支付功能. 1.获取用户的OpenId ,参考之前写 ...

  8. asp.net core 微信APP支付(扫码支付,H5支付,公众号支付,app支付)之4

    微信app支付需要以下参数,类封装如下 public class WxPayModel { /// <summary> /// 应用ID /// </summary> publ ...

  9. ASP.NET CORE小试牛刀:干货(完整源码)

    扯淡 .NET Core 的推出让开发者欣喜万分,从封闭到拥抱开源十分振奋人心.对跨平台的支持,也让咱.NET开发者体验了一把 Write once,run any where 的感觉!近期离职后,时 ...

随机推荐

  1. HashMap分析及散列的冲突处理

    1,Hashing过程 像二分查找.AVL树查找,这些查找算法的时间复杂度为O(logn),而对于哈希表而言,我们一般说它的查找时间复杂度为O(1).那它是怎么实现的呢?这就是一个Hashing过程. ...

  2. DHCP服务洪水攻击

    1.攻击原理 动态主机设置协议是一个局域网的网络协议,使用UDP协议工作,主要有两个用途: 为内部网络或网络服务供应商自动分配IP地址给用户,以作为内部网络管理员对所有计算机做中央管理的手段. 在正常 ...

  3. 绕过CDN查看网站真实IP的一些办法

    验证是否存在CDN最简单的办法 通过在线的多地ping,通过每个地区ping的结果得到IP. 看这些IP是否一致,如果都是一样的,极大可能不存在cdn,但不绝对. 如果这些IP大多数都不太一样或者规律 ...

  4. Linux 查看文件编码

    查看某个文件的编码格式:使用 vi 编辑器 打开文件: 按 Esc 输入 ” : set fileencoding “ 就会显示出来 文件的编码格式 : set fileencoding

  5. TCP 链接 存在大量 close_wait 等待

    大量 close_wait 等待 调整linux下 /etc/sysctl.conf参数,里面设置参数: # net.ipv4.tcp_keepalive_time 然后执行 # sysctl -p

  6. VS2017的安装和配置

    VS2017专业版安装文件下载:链接:https://pan.baidu.com/s/1tJRYdj_9LzvTSDF5TkkMRg   提取码:tgh5    一些窗口:菜单栏--->视图 字 ...

  7. 打包pyinstaller

    安装:pip3 install pyinstaller 了解几个常用命令 参数 用处 -F 将程序打包成一个文件 -w 去除黑框 -i 添加程序图标 我们将需要打包的test.py文件放到桌面上,之后 ...

  8. 字体选择框QFontComboBox

    self.combobox_2 = QFontComboBox(self)  # 实例化字体列表框 combobox.currentFont()  返回字体选择框中当前的字体 self.combobo ...

  9. CF115B Lawnmower(贪心)

    CF115B Lawnmower \(solution:\) 很明显的一道贪心题,奇数行只能向左走,偶数行只能向右走,每一行的起点应该在上一行就已确定,而这一行的终点只和(这一行最后一棵草(相对于你走 ...

  10. java 两个list 交集 并集 差集 去重复并集

    前提需要明白List是引用类型,引用类型采用引用传递. 我们经常会遇到一些需求求集合的交集.差集.并集.例如下面两个集合: List<String> list1 = new ArrayLi ...