微信小程序码开发注意事项
hugo
18 Sep 2020
后端
Source Code: set_unlimited_wxacode
用法:
class Model < ApplicationRecord
SLUG_LENGTH = 24
# https://github.com/norman/friendly_id
extend FriendlyId
friendly_id :slug
# https://github.com/FooBarWidget/default_value_for
default_value_for :slug do
loop do
new_slug = SecureRandom.urlsafe_base64(SLUG_LENGTH)
break new_slug unless Model.exists?(slug: new_slug)
end
end
has_one_attached :wxacode
set_unlimited_wxacode :wxacode, page: "pages/package-bookable/detail" # default scene: id=xx
set_unlimited_wxacode :wxacode, page: "pages/package-bookable/detail", scene: :slug, is_hyaline: true, width: 1280, auto_color: true
set_unlimited_wxacode :wxacode, page: "pages/package-bookable/detail", scene: -> { "id=#{slug}" }
set_unlimited_wxacode :wxacode, page: "pages/package-bookable/detail", scene: -> { "id=#{id}&kind=#{kind}" }, line_color: { r: "133", g: "166", b: "111" }
end
Model.friendly.find params[:id] # id is a slug string
- scene 最大32个可见字符,只支持数字、大小写英文以及部分特殊字
!#$&'()*+,/:;=?@-._~
irb> 'restaurant'.size # => 10
irb> 'id='.size # => 3
irb> '&kind='.size # => 6
irb> 32 - (10 + 3 + 6) # => 13,9万亿
irb> SecureRandom.urlsafe_base64(24) # => "CyR78WW0r8Mz3vD-n2YvnpCqdASk3tGo"
irb> "CyR78WW0r8Mz3vD-n2YvnpCqdASk3tGo".size # => 32, The length of the result string is about 4/3 of 24
- page 必须是已经发布的小程序存在的页面(否则报错),例如
pages/index/index
,根路径前不要填加/
,不能携带参数(参数请放在scene字段里) - 调用分钟频率受限(5000次/分钟),如需大量小程序码,建议预生成
Why slug?
静态页面的小程序码 [https://domain.com/pages/about_us](https://domain.com/pages/about_us)
or https://domain.com/pages/tos
Ref
wxacode.getUnlimited: 获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。
小程序端
假如生成小程序码时的 scene 参数是 id=xx&kind=yy
Page({
onLoad (query) {
// Good:
console.log(query) // => { scene: "id%3D2%xxkind%3Dyy" }
// Bad:
console.log(uni.getLaunchOptionsSync()); // 只在冷启动时有效,小程序未被销毁时拿到的数据保持不变
// {
// path: "pages/package-bookable/detail",
// query: {
// scene: "id%3D2%26kind%3Dwinery"
// },
// referrerInfo: {},
// scene: 1047,
// shareTicket: undefined
// }
let id, kind, scene;
if (options.scene) {
scene = resolveQrcodeScene(options.scene);
({ id, kind } = scene);
} else {
// wx.navigateTo({ url: 'pages/package-bookable/detail?id=xx&kind=yy' })
({ id, kind } = options);
}
// use id and kind to fetch data
},
resolveQrcodeScene(scene) {
// scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
scene = decodeURIComponent(scene);
const arr = scene.split('&');
const obj = {};
arr.forEach(item => {
const [k, v] = item.split('=');
obj[k] = v;
});
return obj;
}
})
Ref
- wx.getLaunchOptionsSync(): 获取小程序启动时的参数。与 App.onLaunch 的回调参数一致。
- wx.getEnterOptionsSync(): 获取本次小程序启动时的参数。如果当前是冷启动,则返回值与 App.onLaunch 的回调参数一致;如果当前是热启动,则返回值与 App.onShow 一致。
小程序内扫码
小程序内扫码非本小程序的小程序码返回:
{
charSet: "UTF-8"
errMsg: "scanCode:ok"
rawData: "bGMxc3lxblU4Yl9IMEltMlBtSlJUN3NlbmU9N2Y0ZDdjMWM="
result: "*"
scanType: "WX_CODE"
}
小程序内扫码本小程序的小程序码返回:
{
charSet: "UTF-8"
errMsg: "scanCode:ok"
path: "pages/package-wine/detail?scene=id%3D1"
rawData: "bDAyNFJ6JkxrM1FuQXY9I3YqdzsyKTI="
scanType: "WX_CODE"
}
小程序内扫码普通二维码,二维码数据会在 result
里返回:
{
charSet: "UTF-8"
errMsg: "scanCode:ok"
rawData: "aHR0cHM6Ly9jbGkuaW0vbW9iIw=="
result: "https://cli.im/mob#"
scanType: "QR_CODE"
}
处理代码示例:
const data = await uni.scanCode({ onlyFromCamera: true });
if (data.path) {
this.$nav.nav('/' + data.path);
} else {
this.$nav.navigateBack(); // or navigate to homepage
}
wx.scanCode(Object object): 调起客户端扫码界面进行扫码
首次提交审核注意事项
手动上传一份小程序码,关联到有分享海报的数据上。
> record = Model.find # or Model.each do { ... }
> record.wxacode = ActiveStorage::Blob.last
手动更新小程序码:
$ cap production rails:console
ruby> record = Model.find
ruby> record.set_wxacode_with_unlimited_wxacode # replace `wxacode` with column param in `set_unlimited_wxacode :column`