1. 程式人生 > 其它 >.Net6+Furion+Sqlsugar+SenparcSdk開發微信公眾號系列之七:生成帶引數的二維碼

.Net6+Furion+Sqlsugar+SenparcSdk開發微信公眾號系列之七:生成帶引數的二維碼

一、說明

為了滿足使用者渠道推廣分析和使用者帳號繫結等場景的需要,公眾平臺提供了生成帶引數二維碼的介面。使用該介面可以獲得多個帶不同場景值的二維碼,使用者掃描後,公眾號可以接收到事件推送。使用介面過程中有任何問題,可以前往微信開放社群 #公眾號 專區發帖交流。

目前有2種類型的二維碼:

1、臨時二維碼,是有過期時間的,最長可以設定為在二維碼生成後的30天(即2592000秒)後過期,但能夠生成較多數量。臨時二維碼主要用於帳號繫結等不要求二維碼永久儲存的業務場景 2、永久二維碼,是無過期時間的,但數量較少(目前為最多10萬個)。永久二維碼主要用於適用於帳號繫結、使用者來源統計等場景。

使用者掃描帶場景值二維碼時,可能推送以下兩種事件:

如果使用者還未關注公眾號,則使用者可以關注公眾號,關注後微信會將帶場景值關注事件推送給開發者。

如果使用者已經關注公眾號,在使用者掃描後會自動進入會話,微信也會將帶場景值掃描事件推送給開發者。

獲取帶引數的二維碼的過程包括兩步,首先建立二維碼ticket,然後憑藉 ticket 到指定 URL 換取二維碼。

二、規範化API介面

因為是webapi所以我們介面返回要規範化,furion提供api返回規範化處理:Startup.cs修改AddInject()為AddInjectWithUnifyResult()

這個規範化處理是全域性的,但是我們/wx介面是不能規範化處理的,所以我們要在/wx介面上加[NonUnify]特性,取消規範化處理

三、資料庫設計

新建一個二維碼錶

建表語句

-- ----------------------------
-- Table structure for QrCode
-- ----------------------------
DROP TABLE IF EXISTS "QrCode";
CREATE TABLE "QrCode" (
  "Id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  "ActionName" int NOT NULL,
  "ExpireSeconds" int NOT NULL,
  "SceneId" int NOT NULL,
  "Ticket" varchar(500) NOT NULL,
  "CodeUrl" varchar(500) NOT NULL,
  "ReceiveInfo" text NOT NULL,
  "CreatedTime" datetime,
  "ExpiredTime" datetime
);

建立實體,這裡的ReceiveInfo欄位我們是用的json儲存,sqlsugar完美支援json儲存,只需要在實體上加上[SugarColumn(IsJson = true)]

using Senparc.Weixin.MP;
using SqlSugar;
using System;

namespace WeiXinApi.Core
{
    /// <summary>
    /// 二維碼錶
    ///</summary>
    [SugarTable("QrCode")]
    public class QrCode
    {
        /// <summary>
        /// id 
        ///</summary>
        [SugarColumn(ColumnName = "Id", IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }
        /// <summary>
        /// 二維碼型別 
        ///</summary>
        [SugarColumn(ColumnName = "ActionName")]
        public QrCode_ActionName ActionName { get; set; }
        /// <summary>
        /// 過期時間 
        ///</summary>
        [SugarColumn(ColumnName = "ExpireSeconds")]
        public int ExpireSeconds { get; set; }
        /// <summary>
        /// SceneId 
        ///</summary>
        [SugarColumn(ColumnName = "SceneId")]
        public int SceneId { get; set; }
        /// <summary>
        /// ticket 
        ///</summary>
        [SugarColumn(ColumnName = "Ticket")]
        public string Ticket { get; set; }
        /// <summary>
        /// 二維碼地址 
        ///</summary>
        [SugarColumn(ColumnName = "CodeUrl")]
        public string CodeUrl { get; set; }

        /// <summary>
        /// 建立時間
        /// </summary>

        [SugarColumn(ColumnName = "CreatedTime")]
        public DateTime CreatedTime { get; set; }

        /// <summary>
        /// 過期時間
        /// </summary>
        [SugarColumn(ColumnName = "ExpiredTime")]
        public DateTime? ExpiredTime { get; set; }

        /// <summary>
        /// 回覆設定 
        ///</summary>
        [SugarColumn(ColumnName = "ReceiveInfo", IsJson = true)]
        public ReceiveInfo ReceiveInfo { get; set; }


        /// <summary>
        /// 是否過期
        /// </summary>
        [SugarColumn(IsIgnore = true)]
        public bool IsExpired { get; set; } = false;

    }

    public class ReceiveInfo
    {
        /// <summary>
        /// 回覆型別:文字,圖片等 
        ///</summary>
        public ReceiveType ReceiveType { get; set; }

        /// <summary>
        /// 回覆內容 
        ///</summary>
        public string ReceiveString { get; set; }
    }
}

四、介面設計

新建如下結構

QRInput

namespace WeiXinApi.Application.Services
{
    public class QRInput
    {
        /// <summary>
        /// 二維碼型別
        /// </summary>
        public QrCode_ActionName ActionName { get; set; }

        /// <summary>
        /// 過期時間
        /// </summary>
        public int ExpireSeconds { get; set; }

        /// <summary>
        /// 回覆設定
        /// </summary>
        [Required(ErrorMessage = "回覆設定必填")]
        public ReceiveInfo? ReceiveInfo { get; set; }
    }
}

介面

using Furion.RemoteRequest;
using Mapster;

namespace WeiXinApi.Application.Services
{
    public class QRService : BaseService
    {
        /// <summary>
        /// 生成二維碼
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost("qr/add")]
        public async Task<dynamic> Add(QRInput input)
        {
            var qrCode = input.Adapt<QrCode>();

            var ticks = SystemTime.Now.Ticks.ToString();
            var sceneId = int.Parse(ticks.Substring(ticks.Length - 7, 7));
            var qrResult = await QrCodeApi.CreateAsync(AppId, input.ExpireSeconds, sceneId, input.ActionName);
            var qrCodeUrl = QrCodeApi.GetShowQrCodeUrl(qrResult.ticket);
            qrCode.Ticket = qrResult.ticket;
            qrCode.CodeUrl = qrCodeUrl;
            qrCode.SceneId = sceneId;
            qrCode.CreatedTime = DateTime.Now;
            if (input.ActionName == QrCode_ActionName.QR_SCENE)
            {
                qrCode.ExpiredTime = qrCode.CreatedTime.AddSeconds(input.ExpireSeconds);
            }
            await DbContext.Db.Insertable(qrCode).ExecuteCommandAsync();//插入資料庫
            return qrCodeUrl;
        }

        /// <summary>
        /// 二維碼列表
        /// </summary>
        /// <returns></returns>
        [HttpGet("qr/page")]
        public async Task<dynamic> Page(int pageNumber = 1, int pageSize = 20)
        {
            var result = await DbContext.Db.Queryable<QrCode>()
                .Mapper(it =>
                {
                    if (it.ActionName == QrCode_ActionName.QR_SCENE)//判斷是否過期
                    {
                        it.IsExpired = it.ExpiredTime < DateTime.Now;
                    }

                })
                .ToPageListAsync(pageNumber, pageSize);
            return result;
        }
    }
}

 測試新增介面,返回的url可以正常顯示二維碼

獲取二維碼測試,成功顯示剛才新增的二維碼資訊

五、本章Gitee連結