爱招飞帮助手册 爱招飞帮助手册
首页
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 功能用法
    • 专用模板
    • 开发流程
    • 函数程序
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 系统工具
    • 系统管理
    • 数据库工具
    • 专用模板
    • 外部功能
    • 开发流程
    • 函数代码
  • 开发手册
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 功能用法
    • 专用模板
    • 开发流程
    • 函数程序
  • 开发手册
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 功能用法
    • 专用模板
    • 开发流程
    • 函数程序
  • 开发手册
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
    • 报表设计
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
    • RestAPI
    • WebSocket
  • 学习手册

    • 安装配置
    • 快速上手
    • 程序架构
    • 界面介绍
    • 功能介绍
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
    • 预设资料
    • RestAPI说明
    • WebSocket说明
    • MQTT说明
    • Python说明
    • 自定程序
    • 运行卫士
    • 自动化作业
    • 函数程序
    • 控件使用
  • 开发手册
  • FastERP
  • FastWeb
  • Smart
  • PinToo
  • Flying
  • TARS
  • 通用功能

    • Report
    • Script
    • Echarts
    • Chart
    • DB Install
    • HiDesk
    • HiNAT
    • FastBPM
    • ReportBuilder
首页
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 功能用法
    • 专用模板
    • 开发流程
    • 函数程序
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 系统工具
    • 系统管理
    • 数据库工具
    • 专用模板
    • 外部功能
    • 开发流程
    • 函数代码
  • 开发手册
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 功能用法
    • 专用模板
    • 开发流程
    • 函数程序
  • 开发手册
  • 学习手册

    • 基本入门
    • 功能介绍
    • 控件说明
    • 功能用法
    • 专用模板
    • 开发流程
    • 函数程序
  • 开发手册
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
    • 报表设计
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
    • RestAPI
    • WebSocket
  • 学习手册

    • 安装配置
    • 快速上手
    • 程序架构
    • 界面介绍
    • 功能介绍
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
  • 学习手册

    • 安装配置
    • 快速上手
    • 界面介绍
    • 功能介绍
    • 预设资料
    • RestAPI说明
    • WebSocket说明
    • MQTT说明
    • Python说明
    • 自定程序
    • 运行卫士
    • 自动化作业
    • 函数程序
    • 控件使用
  • 开发手册
  • FastERP
  • FastWeb
  • Smart
  • PinToo
  • Flying
  • TARS
  • 通用功能

    • Report
    • Script
    • Echarts
    • Chart
    • DB Install
    • HiDesk
    • HiNAT
    • FastBPM
    • ReportBuilder
  • FastWeb帮助主页
  • 学习手册

    • 基本入门

    • 功能介绍

    • 控件说明

    • 系统工具

    • 系统管理

    • 云服务工具

    • 数据库工具

    • 专用模板

    • 外部功能

      • 超级服务器
      • 压力测试
      • 配置中心
      • SSL证书
      • 本地打印
      • 图灵数据分析
      • 微信平台功能接入
        • 1. 准备工作
          • 1.1. 账号与资质准备
          • 1.2. 基础资料与配置
        • 2. FastWeb基本设置
        • 3. FastWeb微信接入开发
        • 4. 反向代理设置
        • 5. 微信公众号服务开发
    • 开发流程

    • 函数程序

  • 开发手册

目录

微信平台功能接入

# 微信平台功能接入

  FastWeb中提供了微信平台接入相关的功能,接入后,用户可以借助微信平台的相关功能,实现FastWeb与微信平台的整合运用。接下来将介绍微信功能接入的方法。

# 1. 准备工作

  在进行微信接入开发(比如微信公众号、微信网页应用、微信支付、企业微信等)前,需要先做好一系列准备工作,避免开发过程中因为权限、资质或环境问题卡住。以下是一个比较全面的准备清单:

# 1.1. 账号与资质准备

  • 微信公众号/小程序

    • 确认已经注册并完成认证(需要企业主体认证,个人主体权限有限)。
    • 确认账号类型:服务号、订阅号、小程序,功能权限差异很大。
  • 企业资质

    • 如果涉及支付或高级接口(如模版消息、微信支付),必须完成企业认证。
  • 开发者权限

    • 确保你有对应公众号/小程序的开发权限,可以进入微信公众平台/微信开放平台配置。

# 1.2. 基础资料与配置

  • AppID 和 AppSecret
    • 在公众平台开发设置里获取。
  • 服务器配置
    • 域名(必须是已备案的 https 域名,支持 TLS 1.2 及以上)。
    • 外网可访问的服务器,用于接收微信的回调(消息、事件、支付通知等)。
  • IP 白名单(部分接口需要配置)。

# 2. FastWeb基本设置

  在配置中心中可以对微信接入所需的项目进行设置。

# 3. FastWeb微信接入开发

  以下将以扫码为例,说明如何在FastWeb中进行开发,以实现扫码获取数据的功能。

  在使用下述代码前,用户应该要了解FastWeb中的JS交互模式,可参考URLFrame与JS的交互。

  微信平台开发的目标平台为移动终端,故在设计模块时,请在[系统工具]-[模块列表(APP)]中创建模块并进行设计。

  下面是例子,说明如何呼叫微信调出扫码的界面:

procedure btnScanCodeOnClick(sender: tobject);
var
  js: string = '';
begin
  //UGCM.wsctWeChatMiroApp_Scaner(wssid,UgAppEdit01.JSId,'scaner');
  js := js + 'wx.ready(function(){' + #13#10;
  js := js + '  wx.scanQRCode({' + #13#10;
  js := js + '    needResult: 1,' + #13#10; // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
  js := js + '    scanType: ["qrCode","barCode"],' + #13#10; // 可以指定扫二维码还是一维码,默认二者都有
  js := js + '    success: function (res) {' + #13#10;
  js := js + '    console.log("扫码成功", res);' + #13#10;
  js := js + '    setTimeout(() => {ajaxRequest('+UgAppEdit01.JSName+', "scaner", ["scanerresult=" +  encodeURIComponent(JSON.stringify(res))])}, 100)' + #13#10; //扫码结束后,会将扫码结果发送至此异步请求,以触发下一步的动作
  js := js + '    },' + #13#10;
  
  js := js + '    fail: function (res) {' + #13#10;
  js := js + '    console.error("扫码失败", res);' + #13#10;
  js := js + '    },' + #13#10; 
  
  js := js + '    complete: function () {' + #13#10;
  js := js + '    console.log("扫码结束");' + #13#10;
  js := js + '    }' + #13#10; 
  
  js := js + '  });' + #13#10;
  
  js := js + '});';
  UniSession.AddJS(js); //将js发送至控制台,以呼叫微信启用扫码
end;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

  当扫码结束后,会返回扫码的结果,通过下方的代码,可以将扫码的结果回填至FastWeb的编辑框。

procedure UgAppEdit01OnAjaxEvent(sender: tcomponent;eventname: string;params: tunistrings);
var 
 O:TJsonObject;
 S:String;
begin
  if SameText(EventName, 'sacnresult') then // webview内jssdk扫码
  begin
    O := TJsonObject(UGCM.ParseJSONValue(Params.Values['callbackdata']));
    try
      if O <> nil then
      begin
        UgAppEdit01.Text := UGCM.GetJSONString(O,'result');
        //if UgAppEdit01.Text <> '' then
        // btnQueryOnClick(nil);
      end;
    finally
      O.Free;
    end;
  end
  else if SameText(EventName, 'scaner') then // H5扫码
  begin
    O := TJsonObject(UGCM.ParseJSONValue(UGMM.HTTPDecode(Params.Values['scanerresult'])));
    try
      if O <> nil then
      begin
        S := UGCM.GetJSONString(O,'resultStr');
        UgAppEdit01.Text :=  Copy(S,Pos(',',S)+1,Length(S));
        //if UgAppEdit01.Text <> '' then
        // btnQueryOnClick(nil);
      end;
    finally
      O.Free;
    end;
  end
end;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

  上述方法对微信平台中接入的FastWeb网页都适用。

# 4. 反向代理设置

  如果用户的FastWeb服务端不能直接经由外网访问,则需要适用反向代理的方式,将这些服务接入外网供用户访问。

  微信平台接入通常需要开启Web服务与WebSocket服务。因此需要将FastWeb中的http服务与websocket服务通过反向代理搭建起来。

  建议使用一台中国大陆境内可供外网访问的Linux服务器来完成上述工作,需使用备案的域名,以满足微信服务接入的要求。使用Nginx来实现反向代理功能。Nginx反向代理的http与Websocket服务建议使用不同的域名做处理,且两个域名都需要申请SSL证书。以下是示例的配置方案:

# http配置
server
    {
        listen 443 ssl http2;
        #listen [::]:443 ssl http2;
        server_name wxserver.sample.com;
        index index.html index.htm index.php default.html default.htm default.php index.nginx-debian.html;
        root  /var/www/html;

        client_max_body_size 512M;
		#include blockip.conf;
        ssl_certificate /etc/nginx/ssl/wxserver.sample.com/fullchain.cer;
        ssl_certificate_key /etc/nginx/ssl/wxserver.sample.com/key.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
        ssl_session_cache builtin:1000 shared:SSL:10m;

		location  / {
				# 这里的 ip 是后端 http
				proxy_pass http://192.168.0.201:8802/;
				proxy_read_timeout  300;
				proxy_connect_timeout   300;
				proxy_redirect  off;

				# 代理参数,请照复制
				proxy_set_header Host $http_host;
				proxy_set_header X-Real-IP $remote_addr;
				proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
				proxy_set_header X-Forwarded-Proto $scheme;
		}
    }

# websocket配置	
server
    {
        listen 443 ssl http2;
        #listen [::]:443 ssl http2;
        server_name wsserver.sample.com;
        index index.html index.htm index.php default.html default.htm default.php index.nginx-debian.html;
        root  /var/www/html;

        client_max_body_size 512M;
		#include blockip.conf;
        ssl_certificate /etc/nginx/ssl/wsserver.sample.com/fullchain.cer;
        ssl_certificate_key /etc/nginx/ssl/wsserver.sample.com/key.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ciphers "TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
        ssl_session_cache builtin:1000 shared:SSL:10m;
		# websocket
		location / {
		    # 这里的 ip 是后端 websocket
			proxy_pass http://192.168.0.201:8804/;
			 
            # websocket代理的配置
			proxy_http_version 1.1;
			proxy_set_header Upgrade $http_upgrade;
			proxy_set_header Connection "upgrade";
			 
			proxy_set_header Host $host;
			proxy_set_header X-Real-IP $remote_addr;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;

			proxy_read_timeout 600s;
			proxy_send_timeout 600s;
			proxy_connect_timeout 600s;
		}
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

# 5. 微信公众号服务开发

  在使用微信公众号服务前,请先在FastWeb配置中心中配置好基础设置、微信公众号、数据库等环节的配置。勾选启用。

  FastWeb提供了推送接收消息的接口,通过向此接口发送消息,可以实现自定义配置的功能。

http://域名/WeixinServer/PushMessage
1

  FastWeb中微信服务器的功能实现逻辑在自定RestAPIReplyWechatMessage中,用户可以在该自定程序中编写代码,实现微信公众号自定义回复功能。支持回复的消息文本类型如下:

消息类型 说明
text 接收到的内容格式为文本消息
image 接收到的内容格式为图片消息
location 接收到的内容格式为位置信息
link 接收到的内容格式为链接
event 接收到的内容格式为事件(用户订阅公众号等事件)

  以下是ReplyWechatMessage的功能结构,将在其中进行注释说明。

function RestAPI:String;
var
  docout: TNativeXml;
  Articles,node:TXmlNode;
  MsgType,MsgText:string;
  touser, fromuser, msg: string;
  url:String;
  picurl:String;
var 
  event:string;
//使用文本回复消息的功能函数
function ReplyMsgText(Amsg:String):string;
begin
  Result := '';
  docout := TNativeXml.CreateName('xml',nil);
  try
    docout.Root.NodeNew('ToUserName').NodeAdd(docout.NodeNewTextType('ToUserName', touser, xeCData));
    docout.Root.NodeNew('FromUserName').NodeAdd(docout.NodeNewTextType('FromUserName', fromuser, xeCData));
    docout.Root.NodeNew('CreateTime').NodeAdd(docout.NodeNewTextType('CreateTime', IntToStr(DateTimeToUnix(now,false)), xeCData));
    docout.Root.NodeNew('MsgType').NodeAdd(docout.NodeNewTextType('MsgType', 'text', xeCData));
    docout.Root.NodeNew('Content').NodeAdd(docout.NodeNewTextType('Content', Amsg, xeCData));
    Result := docout.WriteToString;
  finally
    FreeAndNil(docout);
  end;
end;

begin 
  //获取要发送的用户信息,发送的消息类型                               
  touser := UGParams.Values['FromUserName'];
  fromuser := UGParams.Values['ToUserName'];
  msgtype :=  UGParams.Values['msgtype'];
  
  if msgtype = 'event' then
  begin
    event := UGParams.Values['event'];
    //用户订阅公众号事件
    if event = 'subscribe' then
    begin
      docout := TNativeXml.CreateName('xml',nil);
      try
        msg := '亲爱好朋友,感谢您的关注!';
        docout.Root.NodeNew('ToUserName').NodeAdd(docout.NodeNewTextType('ToUserName', touser, xeCData));
        docout.Root.NodeNew('FromUserName').NodeAdd(docout.NodeNewTextType('FromUserName', fromuser, xeCData));
        docout.Root.NodeNew('CreateTime').NodeAdd(docout.NodeNewTextType('CreateTime', IntToStr(DateTimeToUnix(now,false)), xeCData));
        docout.Root.NodeNew('MsgType').NodeAdd(docout.NodeNewTextType('MsgType', 'text', xeCData)); //
        docout.Root.NodeNew('Content').NodeAdd(docout.NodeNewTextType('Content', msg, xeCData));
        MsgText := docout.WriteToString;
      finally
        FreeAndNil(docout);
      end;
    end
    //用户取消订阅公众号事件
    else if event = 'unsubscribe' then
    begin
      docout := TNativeXml.CreateName('xml',nil);
      try
        msg := '感谢您的支持与厚爱,期待再次合作!';
        docout.Root.NodeNew('ToUserName').NodeAdd(docout.NodeNewTextType('ToUserName', touser, xeCData));
        docout.Root.NodeNew('FromUserName').NodeAdd(docout.NodeNewTextType('FromUserName', fromuser, xeCData));
        docout.Root.NodeNew('CreateTime').NodeAdd(docout.NodeNewTextType('CreateTime', IntToStr(DateTimeToUnix(now,false)), xeCData));
        docout.Root.NodeNew('MsgType').NodeAdd(docout.NodeNewTextType('MsgType', 'text', xeCData));
        docout.Root.NodeNew('Content').NodeAdd(docout.NodeNewTextType('Content', msg, xeCData));
        MsgText := docout.WriteToString;
      finally
        FreeAndNil(docout);
      end;
    end
    //用户点击菜单按钮事件
    else if event = 'CLICK' then
    begin
      msg := '无内容';
      if UGParams.Values['EventKey'] = 'about' then
        msg := '您点击了联系方式';
      docout := TNativeXml.CreateName('xml',nil);
      try
        docout.Root.NodeNew('ToUserName').NodeAdd(docout.NodeNewTextType('ToUserName', touser, xeCData));
        docout.Root.NodeNew('FromUserName').NodeAdd(docout.NodeNewTextType('FromUserName', fromuser, xeCData));
        docout.Root.NodeNew('CreateTime').NodeAdd(docout.NodeNewTextType('CreateTime', IntToStr(DateTimeToUnix(now,false)), xeCData));
        docout.Root.NodeNew('MsgType').NodeAdd(docout.NodeNewTextType('MsgType', 'text', xeCData));
        docout.Root.NodeNew('Content').NodeAdd(docout.NodeNewTextType('Content', msg, xeCData));
        MsgText := docout.WriteToString;
      finally
        FreeAndNil(docout);
      end;
    end
    //用户调用微信扫码事件
    else if (event = 'scancode_push') or (event = 'scancode_waitmsg') then
    begin
      docout := TNativeXml.CreateName('xml',nil);
      try
        msg := '扫码结果:'+ UGParams.Values['ScanType']+UGParams.Values['ScanResult'];
        docout.Root.NodeNew('ToUserName').NodeAdd(docout.NodeNewTextType('ToUserName', touser, xeCData));
        docout.Root.NodeNew('FromUserName').NodeAdd(docout.NodeNewTextType('FromUserName', fromuser, xeCData));
        docout.Root.NodeNew('CreateTime').NodeAdd(docout.NodeNewTextType('CreateTime', IntToStr(DateTimeToUnix(now,false)), xeCData));
        docout.Root.NodeNew('MsgType').NodeAdd(docout.NodeNewTextType('MsgType', 'text', xeCData));
        docout.Root.NodeNew('Content').NodeAdd(docout.NodeNewTextType('Content', msg, xeCData));
        MsgText := docout.WriteToString;
      finally
        FreeAndNil(docout);
      end;
    end;
  end
  //用户发送的内容为文本消息
  else if msgtype = 'text' then
  begin
      msg := UGParams.Values['Content'];
      //以下为一个示例,通过在微信公众号中发送文本消息JS001,触发JS001自定程序的执行
      if msg = 'JS001' then
      begin 
        try    
          UGCM.RunScript(msg);
          MsgText := ReplyMsgText(msg+'自定程序执行成功!');
        except
          MsgText := ReplyMsgText(msg+'自定程序执行失败!'+ExceptionMessage);
        end;
      end
      //以下为一个示例,向用户发送一个带预览图片的链接
      else if Pos(UpperCase('FastERP1操作手册'),UpperCase(msg)) > 0 then
      begin
        docout := TNativeXml.CreateName('xml',nil);
        try
          url := RequestInfo.Host;
          docout.Root.NodeNew('ToUserName').NodeAdd(docout.NodeNewTextType('ToUserName', touser, xeCData));
          docout.Root.NodeNew('FromUserName').NodeAdd(docout.NodeNewTextType('FromUserName', fromuser, xeCData));
          docout.Root.NodeNew('CreateTime').NodeAdd(docout.NodeNewTextType('CreateTime', IntToStr(DateTimeToUnix(now,false)), xeCData));
          docout.Root.NodeNew('MsgType').NodeAdd(docout.NodeNewTextType('MsgType', 'news', xeCData));
          docout.Root.NodeAdd(docout.NodeNewInt('ArticleCount', 1));
        
          Articles := docout.Root.NodeNew('Articles');
          node := Articles.NodeNew('item');
          node.NodeNew('Title').NodeAdd(docout.NodeNewTextType('Title', '爱招飞纺织印染业操作手册', xeCData)); 
          node.NodeNew('Description').NodeAdd(docout.NodeNewTextType('Description', '爱招飞纺织印染业操作手册、使用说明', xeCData)); 
          node.NodeNew('PicUrl').NodeAdd(docout.NodeNewTextType('PicUrl', 'https://www.isoface.cn/isoface/images/logo/isoface_02.png', xeCData)); 
          node.NodeNew('Url').NodeAdd(docout.NodeNewTextType('Url', url, xeCData)); 
          MsgText := docout.WriteToString;
        finally
          FreeAndNil(docout);
        end;
      end
      else
      begin
          MsgText := ReplyMsgText('已收到您的消息:['+msg+']')
      end
  end;
  result := MsgText;
end; 
begin
end.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
图灵数据分析
开发案例

← 图灵数据分析 开发案例→

Copyright © 2021-2025 爱招飞IsoFace | ALL Rights Reserved
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式