18 September 2020

微信小程序码开发注意事项

微信小程序码开发注意事项

后端

Gem: bswechatmini_program

Source Code: setunlimitedwxacode

用法:

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

小程序内扫码

小程序内扫码非本小程序的小程序码返回:

{
  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`
Untitled
read more
4 May 2019

Rails中Cookie和Session的关联

上一节介绍了warden是如何验证用户的登录授权身份,但是对于cookie和session之间是如何生成的,是如何产生关联的,然后是怎么通过保存session数据到cookie中的还有点模糊。总结分享下Rails中是如何处理cookie和session的。

Rubyonrailscookies
read more
20 April 2019
DSL

DSL-让你的 Ruby 代码更加优雅

DSL是Ruby这门语言较为广泛的用途之一,不过如果不熟悉Ruby的元编程的话,难免会被这类语法弄得一脸蒙蔽。今天主要就来看看DSL它是个什么东西,它在Ruby社区中地位怎么样,以及如何实现一门简单的DSL。

Capistranologo
read more
11 April 2019

Ruby中的闭包-代码块

在许多编程语言中都会有闭包这个概念。今天主要来谈谈Ruby中的闭包,它在这门语言中地位如何,以什么形式存在,主要用途有哪些?

Closure
read more
1 April 2019

[译] 你的 Rails 应用正确建立索引了吗

原文 Faster Rails: Is Your Database Properly Indexed?

我的 Rails 应用正常流畅的工作了好几个月后,随着产品的增长和用户开始涌入,Web 请求开始变得缓慢,数据库 CPU 使用率开始上升。然而我并没有做过什么更改,为什么应用就开始变慢了?

这个问题是否有解决办法? 或者说在 Rails 下不支持大规模地扩展?

sql
read more
30 March 2019

Eval家族的那些事儿

许多编程语言都会附带eval的功能,通常会出现在动态语言中,它就有点像是一个微型的解释器,可以在运行时解释代码片段。这篇文章主要以Ruby为例,详细介绍Ruby中的eval家族。

Eval Ruby
read more
19 March 2019
C

Memory allocation strategy for struct and union in C programming language

If you are writing program by C programming language, you may need to care about how many memories to allocate, and when you should deallocate them. That is a heavy work for programmers, but at the same time it is very interesting. You will recognize that when defining a float variable, how many memories we need to allocate? Why a function can modify extern variables by passing the pointer of them?

C Bg
read more
12 March 2019

关于散列表的一些思考

散列表(也叫Hash表)是一种应用较为广泛的数据结构,几乎所有的高级编程语言都内置了散列表这种数据结构。然而散列表在不同的编程语言中称呼不一样,在JavaScript中被称为对象,在Ruby中被称为哈希,而在Python中被称为字典。即便称呼不同,语法不同,它们的原理基本相通。

Hash
read more
12 March 2019

Rack Middleware

Rack官网对于Rack的介绍比较简单,只是介绍了Rack的作用和基本的使用。不过也可能因为不复杂,所以才用简单的几段话介绍了Rack。虽然我们不用了解middleware的调用原理也可以开发出能使用的middleware,但是总有点不知所以然的感觉,所以抽空总结了下Rack中middleware的调用原理。

1553048590181
read more
28 February 2019

浅谈循环之硬件级实现

现代编程语言中循环是十分常见的功能,几乎任何编程语言都有类似forwhile这样的循环语句,不过在计算机底层就没有那么幸福了,许多的硬件其实并没有提供硬件级别的循环。不过硬件级别的限制,似乎并没有影响到我们日常的工作,今天就主要来看看循环的本质是什么。

1548571442207878
read more