1. 程式人生 > >.net Core 呼叫微信Jsapi介面,H5解析二維碼

.net Core 呼叫微信Jsapi介面,H5解析二維碼

專案裡需要用到掃描二維碼,自己實現,不會。

找到了兩種解決方案:

  1. 通過reqrcode.js,這是一個前端解析二維碼內容的js庫。如果二維碼比較清晰,用這種效果也不錯
  2. 呼叫微信掃一掃功能,這種效果很好。但是除錯介面超級麻煩。

具體實現:前端程式碼(vue)(前端用到 vux

<template>
<div class="main">
  <group title="印表機引數" label-width="5.5em">
      <x-input title="名稱" placeholder="輸入印表機名稱" v-model
="model.name" :required="true" @on-change="check" ref="name"></x-input> <x-input title="MAC地址" placeholder="輸入MAC地址" v-model="model.mac" @on-change="check" ref="mac"> <a slot="right-full-height" class="scan" @click="scan()" title="掃碼"><x-icon type="android-expand"
size="32"></x-icon></a> </x-input> <cell title="城市" :value="city"></cell> <cell title="經緯度" :value="location"></cell> </group> <iframe id="geoPage" width=0 height=0 frameborder=0 style="display:none;" scrolling="no" src="https://apis.map.qq.com/tools/geolocation?key=212121U3F2Q&referer=3Dprint"
></iframe> <x-button type="primary" @click.native="add()" :disabled.sync="disabled"> 新增印表機</x-button> <input type="file" accept="image/*" capture="camera" @change="show($event)" v-show="false" ref="file"> </div> </template> <script> import {Group, XInput, XButton, Alert, Range, XSwitch, Cell, InlineXSwitch, ChinaAddressV4Data} from 'vux' export default { components: {Group, XInput, XButton, Alert, Range, XSwitch, Cell, InlineXSwitch, ChinaAddressV4Data}, data () { return { addressData: ChinaAddressV4Data, disabled: true, city: '', location: '', sys: false, // 掃一掃呼叫 model: { name: '', mac: '', status: false, citys: [], city: '', address: '', memory: '', temperature: 0, modelName: '', location: '', ver: '', step: 0, plantTemperature: '', userId: 0 } } }, mounted () { // this.getLocation() let that = this window.addEventListener('message', function (event) {   var loc = event.data if (loc) { that.city = loc.nation + ' ' + loc.province + ' ' + loc.city that.location = loc.lat + ' , ' + loc.lng that.model.address = that.city that.model.location = that.location } console.log('location', loc) }, false) this.initConifig() }, methods: { add () { let that = this this.model.userId = sessionStorage["userId"] this.model.status = this.model.status ? 1 : 0 this.model.city = this.model.citys.join() // console.log(this.model.city) console.log(this.$store.state.user) this.Ajax.post('/api/services/app/Print/Create', this.model).then(function (result) { // console.log(that.model) if (result.success) { that.go('/user/prints') } else { that.$vux.toast.show({text: result.error.message, type: 'cancel'}) } }) }, check () { this.disabled = !(this.model.name !== '' && this.model.mac !== '') }, initConifig () { let that = this /* global wx */ this.Ajax.get('/WX/GetConfig?url=' + location.href).then((r) => { let data = r.result console.log(data) wx.config({ debug: false, // 開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出看傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。 appId: data.appId, // 必填,公眾號的唯一標識 timestamp: data.timestamp, // 必填,生成簽名的時間戳 nonceStr: data.noncestr, // 必填,生成簽名的隨機串 signature: data.signature, // 必填,簽名,見附錄1 jsApiList: ['scanQRCode'] // 必填,需要使用的JS介面列表,所有JS介面2 }) that.sys = true wx.error((r) => { console.log(r) that.sys = false alert('微信呼叫異常:' + r.errMsg) }) }) }, wxScan () { let that = this /* global wx */ wx.scanQRCode({ needResult: 1, desc: 'scanQRCode desc', success: (r) => { console.log(r) let msg = r.resultStr if (msg.length === 29) { let mac = msg.substring(17, 29) let arrs = [] console.log(mac) for (let i = 0; i < 6; i++) { arrs.push(mac.substring(i * 2, i * 2 + 2)) } that.model.mac = arrs.join(':') console.log(msg, that.model.mac) } else { that.$vux.toast.show({text: 'mac解析失敗:' + msg, type: 'cancel'}) } } }) }, scan () { if (this.sys) { this.wxScan() } else { this.$refs.file.click() } }, go (link) { this.$router.push({path: link}) }, show (send) { // var file = console.log(send) /* global qrcode */ let file = send.target.files[0] qrcode.decode(this.getUrl(file)) var that = this qrcode.callback = function (msg) { if (msg.length === 29) { let mac = msg.substring(17, 29) let arrs = [] console.log(mac) for (let i = 0; i < 6; i++) { arrs.push(mac.substring(i * 2, i * 2 + 2)) } that.model.mac = arrs.join(':') console.log(msg, that.model.mac) } else { that.$vux.toast.show({text: 'mac解析失敗:' + msg, type: 'cancel'}) } } }, getUrl (file) { let url = null if (window.createObjectURL !== undefined) { url = window.createObjectURL(file) } else if (window.URL !== undefined) { url = window.URL.createObjectURL(file) } else if (window.webkitURL !== undefined) { url = window.webkitURL.createObjectURL(file) } return url }, getLocation () { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function (p) { console.log(p) }) } else { alert('不支援定位') } } } } </script> <style scoped> .ptitle{ background: #efeff4;padding: 10px 20px; font-size: 16px; font-weight: bold; border-bottom: #d8d8dd;} a.add:hover{ color: #4086ff;fill: #4086ff;cursor: pointer;} .main{padding: 0 10px;} a.scan{ fill: #4086ff; cursor: pointer;} </style>

通用.net core 微信授權獲取方法。

using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;

namespace PrintServe.Web.Host.Core
{
    public static class WXApi
    {
        /// <summary>
        /// 過期時間
        /// </summary>
        public static DateTime OutDateTime { get; set; }
        /// <summary>
        /// 憑據
        /// </summary>
        public static string Token { get; set; }
        /// <summary>
        /// 船票
        /// </summary>
        public static string Ticket { get; set; }
        /// <summary>
        /// 獲取微信api介面船票
        /// </summary>
        /// <param name="url">請求頁面地址</param>
        /// <param name="appId">開發者Id</param>
        /// <param name="secret">開發者密碼</param>
        /// <returns></returns>
        public static dynamic  GetConfig(string url,string appId,string secret)
        {
            var timestamp = CreatenTimestamp();
            var noncestr = CreatenNonce_str();
            var ticket = Ticket;
            if (DateTime.Now > OutDateTime)
            {
                var token = GetToken(appId, secret);
                if (!string.IsNullOrEmpty(token))
                {
                    OutDateTime = DateTime.Now.AddMinutes(90);
                    Token = token;
                    Ticket = GetTickect(Token);
                    ticket = Ticket;
                }
            }
            var signature = GetSignature(ticket, noncestr, timestamp, url, out var str);
            return new
            {
                ticket,
                appId,
                url,
                timestamp,
                noncestr,
                signature,
                str
            };
        }
        /// <summary>
        /// 獲取憑據
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public static string GetToken(string appid,string secret)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}",appid,secret);
            var client = new HttpClient();
            var result = client.GetAsync(url).Result;
            if (!result.IsSuccessStatusCode) return string.Empty;
            var jsTicket = result.Content.ReadAsStringAsync().Result;
            var v = JsonConvert.DeserializeObject<dynamic>(jsTicket);
            return v.access_token.ToString();
        }
        /// <summary>
        /// 獲取船票
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static string GetTickect(string token)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi", token);
            var client = new HttpClient();
            var result = client.GetAsync(url).Result;
            if (!result.IsSuccessStatusCode) return string.Empty;
            var jsTicket = result.Content.ReadAsStringAsync().Result;
            var v = JsonConvert.DeserializeObject<dynamic>(jsTicket);
            return v.ticket.ToString();
        }
        /// <summary>
        /// 獲取時間戳
        /// </summary>
        /// <returns></returns>
        public static long CreatenTimestamp()
        {
            return (DateTime.Now.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
        }

        ///  <summary>
        ///  簽名演算法
        /// 本程式碼來自開源微信SDK專案:https://github.com/night-king/weixinSDK
        ///  </summary>
        ///  <param name="jsapi_ticket">jsapi_ticket</param>
        ///  <param name="noncestr">隨機字串(必須與wx.config中的nonceStr相同)</param>
        ///  <param name="timestamp">時間戳(必須與wx.config中的timestamp相同)</param>
        ///  <param name="url">當前網頁的URL,不包含#及其後面部分(必須是呼叫JS介面頁面的完整URL)</param>
        /// <param name="string1"></param>
        /// <returns></returns>
        public static string GetSignature(string jsapi_ticket, string noncestr, long timestamp, string url, out string string1)
        {
            url = url.Split('#')[0];
            var string1Builder = new StringBuilder();
            string1Builder.Append("jsapi_ticket=").Append(jsapi_ticket).Append("&")
                .Append("noncestr=").Append(noncestr).Append("&")
                .Append("timestamp=").Append(timestamp).Append("&")
                .Append("url=").Append(url);
            string1 = string1Builder.ToString();
            return Sha1(string1);
        }
        /// <summary>
        /// 建立隨機字串
        ///本程式碼來自開源微信SDK專案:https://github.com/night-king/weixinSDK
        /// </summary>
        /// <returns></returns>
        public static string CreatenNonce_str()
        {
            var strs = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
            Random r = new Random();
            var sb = new StringBuilder();
            var length = strs.Length;
            for (int i = 0; i < 15; i++)
            {
                sb.Append(strs[r.Next(length - 1)]);
            }
            return sb.ToString();
        }
        /// <summary>
        /// HMAC-SHA1加密演算法
        /// </summary>
        /// <param name="str">加密字串</param>
        /// <returns></returns>
        public static string Sha1(string str)
        {
            var sha1 = SHA1.Create();
            var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(str));
            string byte2String = string.Empty;
            foreach (var t in hash)
            {
                byte2String += t.ToString("x2");
            }
            return byte2String;
        }
    }
}

controller呼叫

using System;
using Abp.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using PrintServe.Configuration;
using PrintServe.Web.Host.Core;

namespace PrintServe.Web.Host.Controllers
{
    public class WXController : AbpController
    {
        private readonly IConfigurationRoot _configuration;
        public WXController(IHostingEnvironment env)
        {
            _configuration = env.GetAppConfiguration();
        }
        public dynamic GetConfig(string url)
        {
            var appId = _configuration["wx:appid"];
            var secret = _configuration["wx:secret"];
//            Logger.Error("出現異常");
            return WXApi.GetConfig(url,appId,secret);
        }
        [HttpGet]
        public string Test(string input)
        {
            return WXApi.Sha1(input);
        }
       
    }
}

在主頁面要新增微信介面js呼叫

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0">
    <title>3D列印</title>
    <script src="./static/js/reqrcode.js"></script>
    <!-- <script src="./static/js/vconsole.min.js"></script> -->
    <!-- <script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script> -->
    <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
  </head>
  <body>
    <div id="app-box"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

呼叫微信api介面:

1:Ip,和域名都要加到微信公眾平臺裡,缺一不可,在這裡被坑了很久。

設定域名,一個月只能設定3次,要慎重。

2:除錯時候,最好在開發機器上用花生殼繫結個域名,以便開發。本地沒有域名,不能除錯。可以下載微信開發者工具,進行除錯,錯誤提示比較清晰。

微信開發者工具地址:地址

參考文章:

微信公眾號開發之調起微信掃一掃介面

微信公眾號開發:呼叫微信掃一掃功能

qrcode.js的識別解析二維碼圖片和生成二維碼圖片