Wechat app poster generation

Time:2021-3-6

Recently, there is a need to generate sharing posters so that users can save the pictures locally and share them with their friends. I thought it was a very simple demand, but I never thought that wechat would be such a pit.
The initial idea is as follows:

The background obtains the corresponding small program code according to the parameters passed by the small program, and then synthesizes with the background image, and transfers the image in Base64 format to the small program, so that the image can be saved. But after trying, there are two pits

  • Pit 1: small program on Base64 image support is not friendly, the image simulator can be displayed, the real machine can not be displayed
  • Pit 2: small program canvas drawing must use network images or local images, but if you directly in the wx.drawImage Pass in the picture link, the real machine will show the failure

Google has filled these two holes. Record here. If there is any mistake, please spray it gently.

The first is to solve the problem of Base64 images. Since the small program does not support it well, we should save it on the server. Here is the simple code of laravel synthetic images:

public function getPoster(Request $request)
{
    $token = $request->input('token');
    $uid = MembersToken::getUidByToken($token);
    if (file_exists(public_path() . '/poster/' . $uid . '.png')) {
        return response()->json([
            'status' => 'success',
            'data' => '/poster/' . $uid . '.png'
        ]);
    }

    $access_token = Cache::get('access_token');
    if (!$access_token) {
        $appid = config('wechat.appid');
        $secret = config('wechat.secret');
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
        $data = curl_request($url);
        $data = json_decode($data,true);

        if (isset($data['errcode']) || empty($data)) {
            throw new ApiException(200,$data['errmsg'],null,[],600001);
        }
        $access_token = $data['access_token'];
        $expires_in = $data['expires_in'];
        Cache::put('access_token',$access_token,120);
    }

    //Get applet code
    $code_url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $access_token;
    $post = [
        "page" => "pages/maps/maps",
        "scene" => $uid,
    ];
    $data = curl_request($code_url, $post);
    $data = base64_encode($data);
    $data = Image::make($data)->resize(200, 200);

    //Insert QR code into background image
    $img = Image::make(public_path().'/img/book.png');
    $img->insert($data, 'bottom-right', 0, 0);
    $res = $img->save(public_path() . '/poster/' . $uid . '.png');
    return response()->json([
        'status' => 'success',
        'data' => '/poster/' . $uid . '.png'
    ]);

}

After the applet obtains the image path, it can use canvas drawing to display the image, or directly use image tag. In order to prevent other processing of the image in the future, I used canvas.

At this point, if you directly use the image path from the background, you will encounter a second pit: the image cannot be displayed on the real machine. So we need to use it first wx.downloadFile Download the picture. Well, the code is almost like this:

/***********************************************/
/**Call the interface to get the image path... The code is too bad to omit... **/
/**********************************************/
wx.downloadFile({
  url: app.globalData.domain + res.data.data,
  success: function (res) {
    var path = res.tempFilePath
    var width = _this.data.windowW;
    var height = _this.data.windowH - 50;
    const ctx = wx.createCanvasContext('poster');
    ctx.drawImage(path, 0, 0, width, height);
    ctx.draw(true);
    wx.hideLoading();
  }, 
  fail: function (res) {
    /***/
  }
})

At this point, the picture should be able to display on the real machine normally. The next step is to download the pictures to the local area. After solving the above two problems, there is no big problem. Simply paste the code:

saveImg: function () {
var _this = this;
var windowW = _this.data.windowW;
var windowH = _this.data.windowH - 50;
wx.canvasToTempFilePath({
  x: 0,
  y: 0,
  width: windowW,
  height: windowH,
  destWidth: windowW,
  destHeight: windowH,
  canvasId: 'poster',
  success: function (res) {
    wx.saveImageToPhotosAlbum({
      filePath: res.tempFilePath,
      success(res) {
        /***/
      },
      fail(res) {
        /***/
      },
      complete(res) {
        /***/
      }
    })
  }
});

Recommended Today

Rich text editor ueditor

Rich text editor ueditor 1. Integrating ueditor with spspring boot 1.1 introduction to ueditor Ueditor developed by BaiduOfficial website https://ueditor.baidu.com/web…github https://github.com/fex-team/u…Official documents http://fex.baidu.com/ueditor/… 1.2. Download Download link from official website https://ueditor.baidu.com/web…I use Java back-end, so download JSP version, UTF-8 version Download address of development versionhttps://github.com/fex-team/u… Post download directory structure There is a DDoS vulnerability in […]