.Net微信电脑网站支付(api v2)

news/2024/5/19 22:08:30 标签: 微信, asp.net, .netcore

商户或企业前往微信开放平台申请开通微信支付,需要注意的是微信支付功能不对个人用户开放。开通支付功能后,会获取到以下微信支付相关的配置信息:

  • appid:是微信公众账号或开放平台APP的唯一标识,在公众平台申请公众账号或者在开放平台申请APP账号后,微信会自动分配对应的appid,用于标识该应用。
  • mch_id:商户申请微信支付后,由微信支付分配的商户收款账号。
  • key:交易过程用于生成签名的密钥,可以前往:微信商户平台(pay.weixin.qq.com)–>账户中心–>账户设置–>API安全–>密钥设置
  • appsecret:AppSecret是APPID对应的接口密码,用于获取接口调用凭证access_token时使用,不参与微信支付过程。

一、支付流程

支付流程.png

二、协议规则

使用微信API接口时,必须遵循以下规则:

  • 传输方式:为保证交易安全性,采用HTTPS传输
  • 提交方式:采用POST方法提交
  • 数据格式:提交和返回数据都为XML格式,根节点名为xml
  • 字符编码:微信支付API v2仅支持UTF-8字符编码。
  • 签名算法:MD5/HMAC-SHA256

三、签名算法

微信支付使用的是MD5/HMAC-SHA256对数据进行签名和验证。
首先将所有发送或接受的非空数据按URL键值对(key1=value1&key2=value2)的形式,按参数名ASCII码从小到大排序(字典序)拼接成字符串,然后将用于微信签名的key拼接在最后,最后使用MD5/HMAC-SHA256对字符串签名得到sign值。需要注意的是:

  • 参数必须按ASCII码从小到大排序。
  • 为空参数不参与签名。
  • 参数名区分大小写。
  • 验证调签名时,sign参数不参与签名。将生成的签名与该sign值作校验。

四、异步通知

微信后台支付成功后,会调用商户后台的异步通知接口,将支付结果发送给商户后台。商户后台根据获取到的支付结果,处理业务平台逻辑。在处理时需要注意一下几点:

  • 同样的异步通知微信可能发送多次,必须采用数据锁进行并发控制,避免数据混乱。
  • 商户后台在处理通知时,需要先判断该通知是否已经处理成功。如果处理成功,直接返回成功信息。
  • 微信后台没有接受到通知接口返回的成功信息,会按照一定的频率重新发送通知,知道成功为止(通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)。

五、集成SDK

前往微信开放平台下载 SDK与DEMO ,将Demo中的business、lib放入项目中使用。

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using QRCoder;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using WxPayAPI;
using Microsoft.Extensions.Logging;
using System.Text;

namespace WxPay.Demo.Controllers
{
    public class PayController : Controller
    {
        private readonly ILogger<HomeController> _logger;

        public PayController(ILogger<HomeController> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 生成直接支付url,支付url有效期为2小时。
        /// </summary>
        /// <returns></returns>
        public IActionResult Order()
        {
            WxPayData data = new WxPayData();
            data.SetValue("body", "测试商品");//商品描述
            data.SetValue("attach", "test");//附加数据
            data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//商户订单号,随机字符串。
            data.SetValue("total_fee", Convert.ToInt32(0.01 * 100));//订单总金额,单位为分。
            data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
            data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易结束时间
            data.SetValue("goods_tag", "jjj");//商品标记
            data.SetValue("trade_type", "NATIVE");//交易类型
            data.SetValue("product_id", Guid.NewGuid().ToString("N"));//商品ID

            WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口
            _logger.LogInformation("UnifiedOrder:\r\n" + result.ToXml());
            string url = result.GetValue("code_url").ToString();//获得统一下单接口返回的二维码链接


            //使用QRCoder生成二维码
            var qrGenerator = new QRCodeGenerator();
            var qrCodeData = qrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.Q);
            var qrCode = new QRCode(qrCodeData);
            var image = qrCode.GetGraphic(6);
            using (var ms = new MemoryStream())
            {
                image.Save(ms, ImageFormat.Jpeg);
                return File(ms.ToArray(), "image/jpeg");
            }
        }

        private static object _locker = new object();
        public IActionResult Notify()
        {
            //1.签名验证
            //2.判断订单是否已经处理,如果处理直接返回成功。
            //3.处理业务平台订单
            //4.向微信后台 返回处理结果。
            WxPayData res = new WxPayData();

            lock (_locker)
            {
                var body = HttpContext.Request.BodyReader.AsStream();
                int count = 0;
                byte[] buffer = new byte[1024];
                StringBuilder builder = new StringBuilder();
                while ((count = body.Read(buffer, 0, 1024)) > 0)
                {
                    builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
                }
                var xml = builder.ToString();
                _logger.LogInformation("Notify:\r\n" + xml);

                try
                {
                    //转换数据格式并验证签名
                    WxPayData data = new WxPayData();
                    var dics = data.FromXml(xml.ToString());
                    if (dics["return_code"] == "SUCCESS")
                    {
                        //处理业务平台订单....
                        var appid = dics["appid"];//公众账号ID
                        var mch_id = dics["mch_id"];//商户号
                        var out_trade_no = dics["out_trade_no"];//商户订单号
                        var total_fee = dics["total_fee"];//订单总金额,单位为分。
                        var time_end = dics["time_end"];//支付完成时间
                        var transaction_id = dics["transaction_id"];//微信支付订单号

                        res.SetValue("return_code", "SUCCESS");//返回状态码:SUCCESS/FAIL
                        res.SetValue("return_msg", "");//返回信息
                    }
                    else
                    {
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "");
                    }
                }
                catch (WxPayException ex)
                {
                    //若签名错误,则立即返回结果给微信支付后台
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", ex.Message);
                }
            }

            return Content(res.ToXml(), "text/xml");
        }
    }
}

http://www.niftyadmin.cn/n/1786121.html

相关文章

KEIL的warning和#error使用

在keil当中有时候需要编译一些条件&#xff0c;当编译的条件过多有时会忘记&#xff0c;这个时候用# warning 和# error&#xff1b;可以很清晰的看见哪些条件编译了和没编译。 #ifndef TEST# warning "TEST is not defined" #else# warning "TEST is defined&…

vue文件格式化

1.vue文件格式化需要安装以下插件&#xff1a; ESLintPrettierVetur 2.添加.prettierrc文件&#xff1a; {"semi": false, //格式化时不加分号"singleQuote": true, //用单引号替换双引号"prettier.spaceBeforeFunctionParen": true, //让函数…

C++小项目学习----通讯录的实现

#include "iostream" #include "string" using namespace std;//1.显示起始菜单 void showmenu() {cout << "************" << endl;cout << "1.添加联系人" << endl;cout << "2.显示联系人"…

asp.netmvc应用程序生命周期

asp.net runtime接管http请求后&#xff0c;http runtime会通过HttpApplicationFactory创建或则从HttpApplication池中获取一个空闲的HttpApplication。然后http请求进入HttpApplication管道进行处理&#xff0c;处理结束后返回结果。 1.web站点启动时&#xff0c;Global.asax…

Ubuntu下的ADB命令调试

sudo apt-get install android-tools-adb 输入上述命令安装adb&#xff0c;然后先在终端输入命令adb version 。有显示代表安装好了ADB调试工具. 用usb连上手机&#xff0c;一定要进入开发者选项&#xff0c;打开USB打开调试&#xff0c;否则会一直找不到设备。 查看ADB版本…

HLS协议(m3u8)

HLS(HTTP Live Streaming)是苹果公司提出的基于HTTP动态流传输协议。客户端可以根据网络带宽的变化&#xff0c;智能切换至对应码率、分辨率的媒体流进行播放&#xff0c;支持音视频的点播和直播。HLS可以通过HTTPS对媒体加密传输和身份认证。 HLS由服务器组件、分发组件、客户…

程序的内存模型

首先程序分为4大块&#xff1a;全局区&#xff0c;代码区&#xff0c;堆&#xff0c;栈。 在程序运行之前呢&#xff1f;程序分为程序区和代码区。 代码区 代码区就是我们写的代码&#xff0c;这玩意儿为啥要单独分出来呢&#xff1f;当我们的程序生成了可执行文件exe&#…

HttpClient使用

以京训钉开发平台接口文档为例&#xff0c;使用HttpClient类请求调用其接口&#xff0c;对数据进行增删改查等操作。 文档地址&#xff1a;https://www.yuque.com/bjjnts/jxd/bo1osz using System; using System.Collections.Generic; using System.Linq; using System.Net.Ht…