.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鏈接

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章