zoukankan      html  css  js  c++  java
  • C# 微信小程序支付(ASP.NET Core WebApi )

    支付效果展示

     

    1、获取openid

      方式一:可以通过wx.login方式获取openid

      官方文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

     wx.login({
          success: res => {
            // 发送 res.code 到后台换取 openId, sessionKey, unionId
            if (res.code) {
              console.log('临时登录凭证code:'+res.code);
              wx.request({
                url: 'https://api.weixin.qq.com/sns/jscode2session',
                data: {
                  //填上自己的小程序唯一标识
                  appid: 'wxdf1bb7bb7ba9XXXX',
                  //填上自己的小程序的 app secret
                  secret: '4b4f1a2b1ae40c01b29aa1e595d6XXXX',
                  grant_type: 'authorization_code',
                  js_code: res.code
                },
                method: 'GET',
                header: { 'content-type': 'application/json' },
                success: function (openIdRes) {
                  console.info(openIdRes);
                  console.info("登录成功返回的openId:" + openIdRes.data.openid);
                  console.info("登录成功返回的session_key:" + openIdRes.data.session_key);
                },
                fail: function (error) {
                  console.info(error);
                }
              })
            }
          }
        })

      方式二:通过后台获取openid,前台需要传入code(临时登录凭证)这里我们讲述支付代码用的是方式二(appid、secret最好不要放在js文件里面)

     private static string sendGet(string js_code)
     {
                string url = string.Format("https://api.weixin.qq.com/sns/jscode2session?appid=" + _appid + "&secret=" + _secret + "&grant_type=authorization_code&js_code=" + js_code + "");
                WebClient wc = new WebClient();
                Encoding enc = Encoding.GetEncoding("UTF-8");
                Byte[] pageData = wc.DownloadData(url);
                string re = enc.GetString(pageData);
                return re;
     }

    2、统一下单

      官方文档:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

        [Route("api/[controller]")]
        [ApiController]
        public class PaymentController : ControllerBase
        {
    
            //所需值
            public readonly static string _appid = "wx76bf5470a329XXXX";//小程序ID
            public readonly static string _secret = "17ccaa4f1da1d23c248a25884c7bXXXX";//小程序App/Secret
            public readonly static string _mch_id = "150301XXXX";//商户号
            public readonly static string _key = "49992dd11dd54545bead167681abXXXX";//微信支付的Key/Secret
    
            /// <summary>
            /// 模拟wx统一下单
            /// </summary>
            /// <param name="openid">前台获取用户标识</param>
            /// <returns></returns>
            [HttpGet]
            public string GetAll(string openid, decimal amount)
            {
                if (openid == null)
                {
                    return "";
                }
                return Getprepay_id(_appid, "支付测试", "JSAPI支付测试", _mch_id, GetRandomString(30), "http://www.weixin.qq.com/wxpay/pay.php", openid, getRandomTime(), Convert.ToInt32(amount * 100));
            }
    
            [HttpGet("{js_code}")]
            public string GetOpenId(string js_code)
            {
                if (js_code == null)
                {
                    return "";
                }
                return sendGet(js_code);
            }
    
            //微信统一下单获取prepay_id & 再次签名返回数据
            private static string Getprepay_id(string appid, string attach, string body, string mch_id, string nonce_str, string notify_url, string openid, string bookingNo, int total_fee)
            {
                var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信统一下单请求地址
                string strA = "appid=" + appid + "&attach=" + attach + "&body=" + body + "&mch_id=" + mch_id + "&nonce_str=" + nonce_str + "&notify_url=" + notify_url + "&openid=" + openid + "&out_trade_no=" + bookingNo + "&spbill_create_ip=61.50.221.43&total_fee=" + total_fee + "&trade_type=JSAPI";
                string strk = strA + "&key=" + _key;  //key为商户平台设置的密钥key(假)
                string strMD5 = MD5(strk).ToUpper();//MD5签名
    
                //签名
                var formData = "<xml>";
                formData += "<appid>" + appid + "</appid>";//appid  
                formData += "<attach>" + attach + "</attach>"; //附加数据(描述)
                formData += "<body>" + body + "</body>";//商品描述
                formData += "<mch_id>" + mch_id + "</mch_id>";//商户号  
                formData += "<nonce_str>" + nonce_str + "</nonce_str>";//随机字符串,不长于32位。  
                formData += "<notify_url>" + notify_url + "</notify_url>";//通知地址
                formData += "<openid>" + openid + "</openid>";//openid
                formData += "<out_trade_no>" + bookingNo + "</out_trade_no>";//商户订单号
                formData += "<spbill_create_ip>61.50.221.43</spbill_create_ip>";//终端IP
                formData += "<total_fee>" + total_fee + "</total_fee>";//支付金额单位为(分)
                formData += "<trade_type>JSAPI</trade_type>";//交易类型(JSAPI--公众号支付)
                formData += "<sign>" + strMD5 + "</sign>"; //签名
                formData += "</xml>";
    
                //请求数据
                var getdata = sendPost(url, formData);
    
                //获取xml数据
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(getdata);
                //xml格式转json
                string json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc);
    
                JObject jo = (JObject)JsonConvert.DeserializeObject(json);
                string prepay_id = jo["xml"]["prepay_id"]["#cdata-section"].ToString();
    
                //时间戳
                string _time = getTime().ToString();
    
                //再次签名返回数据至小程序
                string strB = "appId=" + appid + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + _time + "&key=" + _key;
    
                //wx自己写的一个类
                PaymentEntity payment = new PaymentEntity();
                payment.timeStamp = _time;
                payment.nonceStr = nonce_str;
                payment.package = "prepay_id=" + prepay_id;
                payment.paySign = MD5(strB).ToUpper();
                payment.signType = "MD5";
    
                //向小程序返回json数据
                return JsonConvert.SerializeObject(payment);
            }
    
            /// <summary>
            /// 生成随机串    
            /// </summary>
            /// <param name="length">字符串长度</param>
            /// <returns></returns>
            private static string GetRandomString(int length)
            {
                const string key = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
                if (length < 1)
                    return string.Empty;
    
                Random rnd = new Random();
                byte[] buffer = new byte[8];
    
                ulong bit = 31;
                ulong result = 0;
                int index = 0;
                StringBuilder sb = new StringBuilder((length / 5 + 1) * 5);
    
                while (sb.Length < length)
                {
                    rnd.NextBytes(buffer);
    
                    buffer[5] = buffer[6] = buffer[7] = 0x00;
                    result = BitConverter.ToUInt64(buffer, 0);
    
                    while (result > 0 && sb.Length < length)
                    {
                        index = (int)(bit & result);
                        sb.Append(key[index]);
                        result = result >> 5;
                    }
                }
                return sb.ToString();
            }
    
            /// <summary>
            /// 生成订单号
            /// </summary>
            /// <returns></returns>
            private static string getRandomTime()
            {
                Random rd = new Random();//用于生成随机数
                string DateStr = DateTime.Now.ToString("yyyyMMddHHmmssMM");//日期
                string str = DateStr + rd.Next(10000).ToString().PadLeft(4, '0');//带日期的随机数
                return str;
            }
    
            /// <summary>
            /// MD5签名方法  
            /// </summary>  
            /// <param name="inputText">加密参数</param>  
            /// <returns></returns>  
            private static string MD5(string inputText)
            {
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] fromData = System.Text.Encoding.UTF8.GetBytes(inputText);
                byte[] targetData = md5.ComputeHash(fromData);
                string byte2String = null;
    
                for (int i = 0; i < targetData.Length; i++)
                {
                    byte2String += targetData[i].ToString("x2");
                }
    
                return byte2String;
            }
    
            /// <summary>
            /// wx统一下单请求数据
            /// </summary>
            /// <param name="URL">请求地址</param>
            /// <param name="urlArgs">参数</param>
            /// <returns></returns>
            private static string sendPost(string URL, string urlArgs)
            {
    
                WebClient wCient = new WebClient();
                wCient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
                byte[] postData = System.Text.Encoding.UTF8.GetBytes(urlArgs);
                byte[] responseData = wCient.UploadData(URL, "POST", postData);
    
                string returnStr = System.Text.Encoding.UTF8.GetString(responseData);//返回接受的数据 
                return returnStr;
            }
    
            /// <summary>
            /// 获取时间戳
            /// </summary>
            /// <returns></returns>
            private static long getTime()
            {
                TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                return Convert.ToInt64(ts.TotalSeconds);
    
            }
    
            private static string sendGet(string js_code)
            {
                string url = string.Format("https://api.weixin.qq.com/sns/jscode2session?appid=" + _appid + "&secret=" + _secret + "&grant_type=authorization_code&js_code=" + js_code + "");
                WebClient wc = new WebClient();
                Encoding enc = Encoding.GetEncoding("UTF-8");
                Byte[] pageData = wc.DownloadData(url);
                string re = enc.GetString(pageData);
                return re;
            }
    
        }

    3、发起微信支付

      上面后台代码会返回timeStamp、nonceStr、package、signType、paySign拿到数据后传递给wx.requestPayme(Object object)

      官方文档:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html

    JS

    // pages/home/home.js
    Page({
      data: {
        amount: 0
      },
      inputvalue: function(e) {
        if (e.detail.value == "") {
          this.setData({
            amount: 0,
    
          })
        } else {
          this.setData({
            amount: e.detail.value,
          })
        }
      },
      //得到openid
      payment: function() {
        console.log(this.data.amount);
        var that = this;
        wx.login({
          success: res => {
            if (res.code) {
              //console.log('临时登录凭证code:' + res.code);
              wx.request({
                url: 'https://localhost:44302/api/payment/' + res.code,
                method: 'GET',
                header: {
                  'content-type': 'application/json'
                },
                success: function(openIdRes) {
                  console.info(openIdRes);
                  var openid = openIdRes.data.openid;
                  console.info("登录成功返回的openId:" + openid);
                  that.generateOrder(openid)
                },
                fail: function(error) {
                  console.info(error);
                }
              })
            }
          }
        })
      },
      //生成商户订单
      generateOrder: function(openid) {
        var that = this;
        wx.request({
          url: 'https://localhost:44302/api/payment',
          data: {
            openid: openid + '',
            amount: that.data.amount
          },
          method: 'GET',
          header: {
            'content-type': 'application/json'
          },
          success: function (param) {
            that.zf(param);
          },
          fail: function(error) {
            console.info(error);
          }
        })
      },
      //支付
      zf: function (param) {
        var that = this;
        console.log("发起支付")
        console.log(param)
        wx.requestPayment({
          timeStamp: param.data.timeStamp,
          nonceStr: param.data.nonceStr,
          package: param.data.package,
          signType: param.data.signType,
          paySign: param.data.paySign,
          success: function (res) {
            console.log("success");
            console.log(res);
          },
          fail: function (res) {
            console.log("fail")
            console.log(res);
          },
          complete: function (res) {
            console.log("complete");
            console.log(res)
          }
        })
      }
    })

     WXML

    <!--pages/home/home.wxml-->
    <input class="weui-input" style="margin-left: 20px;margin-right:20px;" type="number" bindinput="inputvalue" placeholder="¥请输入充值金额" />
      <view class='add_btn'>
        <button style="100vw;margin-top:20px;" bindtap="payment" class="btn"> 支付 </button>
      </view>

    WXSS

    .add_btn {
      width: 100%;
      display: flex;
    }
    
    .btn {
      background: #0072c6;
      color: #fff;
      float: right;
      border-radius: 0px 4px 0px 0px;
    }

      源代码:

      链接:https://pan.baidu.com/s/1m4feS-XvdQsHYlWql8zQAA
      提取码:da9l
      后续会陆续更新其他资料,喜欢请关注哦!

      原文参考:https://www.cnblogs.com/oneall/p/9548722.html

  • 相关阅读:
    Java--强制转化
    Java--成绩分类
    建造者模式的应用
    抽象工厂模式的应用
    工厂模式
    第几天
    Stacking Plates(存档待续.....(没有写思路和程序))
    圆的面积
    公孙策和陆湘湘对话(少年包青天第二部第二十集末尾和第二十一集开头部分)
    简单接口回调例子
  • 原文地址:https://www.cnblogs.com/duhaoran/p/12867126.html
Copyright © 2011-2022 走看看