查看: 1758|回复: 0

[ASP.NET教程] .NET微信扫码支付接入(模式二-NATIVE)

发表于 2018-1-3 08:00:01

一、前言

经过两三天的琢磨总算完成了微信扫码支付功能,不得不感叹几句:

微信提供的DEMO不错,直接复制粘贴就可以跑起来了;
微信的配置平台我真是服了。公众平台、商户平台、开放平台,一个平台一套账户密码,大写的恶心
DEMO地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

.NET版DEMO中的Lib文件夹是关键,直接复制到自己的代码里,或者打成dll随个人意愿。

二、正文

Step1:肯定是产生商户订单号,然后传给微信后台,由微信去组成二维码字符串,然后返给你,你再把字符串做成图片;

  1. /// <summary>
  2. /// 获取二维码
  3. /// </summary>
  4. /// <param name="orderNumber"></param>
  5. /// <returns></returns>
  6. public string GetCodeUrl(string orderNumber)
  7. {
  8. var result = string.Empty;
  9. if (!string.IsNullOrEmpty(orderNumber))
  10. {
  11. var matchedItem = db.OrderInfoForProducts.FirstOrDefault(x => x.OrderNumber == orderNumber);
  12. if (matchedItem != null && matchedItem.IsPaid == false)
  13. {
  14. WxPayData data = new WxPayData();
  15. data.SetValue("body", "productBody");//商品描述
  16. data.SetValue("attach", "attach data");//附加数据
  17. data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//随机字符串
  18. data.SetValue("total_fee", price);//总金额
  19. data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
  20. data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易结束时间
  21. data.SetValue("goods_tag", "tag");//商品标记
  22. data.SetValue("trade_type", "NATIVE");//交易类型
  23. data.SetValue("product_id", WxPayApi.GenerateOutTradeNo());//商品ID
  24. result = WxPayApi.UnifiedOrder(data).GetValue("code_url").ToString();//调用统一下单接口
  25. }
  26. }
  27. return result;
  28. }
复制代码

在这里,我是把公司的商户订单号放在了attach字段上,因为公司的商户订单号比较长,超过了32位。out_trade_no与product_id字段最多32位,请慎重!

微信中的价格不能带小数,所以0.01元要写成100。

Step2: 成功返回二维码字符串之后就可以在生成图片了,我这边使用了ThoughtWorks.QRCode.dll来生成图片:

  1. /// <summary>
  2. /// 根据字符串得到相应的二维码
  3. /// </summary>
  4. /// <param name="qrInfo"></param>
  5. /// <param name="productName"></param>
  6. /// <param name="version"></param>
  7. /// <returns></returns>
  8. public static Image CreateQRCodeImage(string qrInfo, string productName, string version)
  9. {
  10. try
  11. {
  12. if (!string.IsNullOrEmpty(qrInfo))
  13. {
  14. QRCodeEncoder encoder = new QRCodeEncoder
  15. {
  16. QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
  17. QRCodeScale = 4,
  18. QRCodeVersion = 0,
  19. QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
  20. };
  21. //编码方式(注意:BYTE能支持中文,ALPHA_NUMERIC扫描出来的都是数字)
  22. //大小(值越大生成的二维码图片像素越高)
  23. //版本(注意:设置为0主要是防止编码的字符串太长时发生错误)
  24. //错误效验、错误更正(有4个等级)
  25. Image image = encoder.Encode(qrInfo, Encoding.GetEncoding("utf-8"));
  26. string filename = $"{productName}_{version}.png";
  27. var userLocalPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
  28. var docPath = Path.Combine(userLocalPath, @"Your Product\QRCode");
  29. if (!Directory.Exists(docPath))
  30. {
  31. Directory.CreateDirectory(docPath);
  32. }
  33. string filepath = Path.Combine(docPath, filename);
  34. using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write))
  35. {
  36. image.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
  37. fs.Close();
  38. image.Dispose();
  39. }
  40. return image;
  41. }
  42. }
  43. catch (Exception)
  44. {
  45. return null;
  46. }
  47. return null;
  48. }
复制代码

Step3: 当用户扫完二维码之后,微信会发起回调,这时候我们就可以处理自己的业务逻辑了。这里我的UpdatePayStatus返回的是一个空页面

  1. /// <summary>
  2. /// 回调函数
  3. /// </summary>
  4. public ActionResult UpdatePayStatus()
  5. {
  6. //接收从微信后台POST过来的数据
  7. System.IO.Stream s = Request.InputStream;
  8. int count = 0;
  9. byte[] buffer = new byte[1024];
  10. StringBuilder builder = new StringBuilder();
  11. while ((count = s.Read(buffer, 0, 1024)) > 0)
  12. {
  13. builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
  14. }
  15. s.Flush();
  16. s.Close();
  17. s.Dispose();
  18. //转换数据格式并验证签名
  19. WxPayData data = new WxPayData();
  20. try
  21. {
  22. data.FromXml(builder.ToString());
  23. }
  24. catch (WxPayException ex)
  25. {
  26. //若签名错误,则立即返回结果给微信支付后台
  27. WxPayData res = new WxPayData();
  28. res.SetValue("return_code", "FAIL");
  29. res.SetValue("return_msg", ex.Message);
  30. LogEntity signErrorLog = new LogEntity();
  31. signErrorLog.errorMessage = ex.Message;
  32. LogHelper.WriteLog(signErrorLog, null);
  33. Response.Write(res.ToXml());
  34. Response.End();
  35. }
  36. ProcessNotify(data);
  37. return View();
  38. }
  39. /// <summary>
  40. /// 处理回调数据
  41. /// </summary>
  42. /// <param name="data"></param>
  43. public void ProcessNotify(WxPayData data)
  44. {
  45. WxPayData notifyData = data;
  46. //检查支付结果中transaction_id是否存在
  47. if (!notifyData.IsSet("transaction_id"))
  48. {
  49. //若transaction_id不存在,则立即返回结果给微信支付后台
  50. WxPayData res = new WxPayData();
  51. res.SetValue("return_code", "FAIL");
  52. res.SetValue("return_msg", "支付结果中微信订单号不存在");
  53. LogEntity orderLog = new LogEntity();
  54. orderLog.errorMessage = "支付结果中微信订单号不存在";
  55. LogHelper.WriteLog(orderLog, null);
  56. Response.Write(res.ToXml());
  57. Response.End();
  58. }
  59. string transaction_id = notifyData.GetValue("transaction_id").ToString();
  60. //查询订单,判断订单真实性
  61. if (!QueryOrder(transaction_id))
  62. {
  63. //若订单查询失败,则立即返回结果给微信支付后台
  64. WxPayData res = new WxPayData();
  65. res.SetValue("return_code", "FAIL");
  66. res.SetValue("return_msg", "订单查询失败");
  67. LogEntity orderqueryLog = new LogEntity();
  68. orderqueryLog.errorMessage = "订单查询失败";
  69. LogHelper.WriteLog(orderqueryLog, null);
  70. Response.Write(res.ToXml());
  71. Response.End();
  72. }
  73. //查询订单成功
  74. else
  75. {
  76. WxPayData res = new WxPayData();
  77. res.SetValue("return_code", "SUCCESS");
  78. res.SetValue("return_msg", "OK");
  79. SetPaymentResult(data); //这里的参数是 data !!! 不是 res !!!
  80. Response.Write(res.ToXml());
  81. Response.End();
  82. }
  83. }
  84. /// <summary>
  85. /// 商户后台更新
  86. /// </summary>
  87. /// <param name="res"></param>
  88. private void SetPaymentResult(WxPayData res)
  89. {
  90. var isSucessFlagOne = res.GetValue("return_code").ToString();
  91. var isSuccessFlagTwo = res.GetValue("result_code").ToString();
  92. if (isSucessFlagOne == "SUCCESS" && isSuccessFlagTwo == "SUCCESS")
  93. {
  94. //自己的业务逻辑 !!!!
  95. }
  96. }
  97. //查询订单
  98. private bool QueryOrder(string transaction_id)
  99. {
  100. WxPayData req = new WxPayData();
  101. req.SetValue("transaction_id", transaction_id);
  102. WxPayData res = WxPayApi.OrderQuery(req);
  103. if (res.GetValue("return_code").ToString() == "SUCCESS" &&
  104. res.GetValue("result_code").ToString() == "SUCCESS")
  105. {
  106. return true;
  107. }
  108. else
  109. {
  110. return false;
  111. }
  112. }
复制代码

三、结尾

做完支付宝与微信扫码支付发现支付宝的接入要比微信方便很多,还有一个同步请求。而且吐槽个其它的,微信开放平台的审批速度要比支付宝的审批慢很多。还有微信支付最后上线前不需要非得用沙箱测试,做完之后直接一分钱一分钱测试即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。



回复

使用道具 举报