Laravel 下设置又拍云上传图片 SDK 签名 url 的写法

这两天在用 Laravel 给微信小程序的项目写 API 接口,其中小程序端上传图片采用又拍云云存储,而官方提供了又拍云的微信小程序上传SDK,于是就直接拿来用了。

又拍云小程序SDK (Github)

关于怎样引入SDK就不说了,主要是讲一下怎样配置,如果想直接看结果,可以直接跳到页尾。

const upyun = new Upyun({
  bucket: 'sdkimg',  // 这里填你注册的又拍云bucket名字
  operator: 'tester', // 这里填你注册的又拍云bucket名字
  getSignatureUrl: 'http://localhost:8080',  //这里后面会讲到
})

按照 Github 上的说明

使用又拍云微信小程序 SDK 需要实现一个在服务器进行签名的接口,并将该接口地址作为 getSignatureUrl 传入构造函数,

该接口接受 GET 请求,并接受一个参数 data,计算并返回带有 signature 字段的响应

signature 的计算公式是

Base64 (HMAC-SHA1 (, )
其中,md5_password 是操作员密码的 MD5 值

但是,折腾了半天,我也不太清楚这里面的data是一个什么样的存在。下面到了见证奇迹的时刻?

源代码分析

在官方的Github中为我们提供了一个本地的node服务器,对应的文件名是demo-server.js。代码如下

  'use strict'

  const crypto = require('crypto')
  const url = require('url')
  const qs = require('querystring')
  const http = require('http')

  const md5Password = md5('grjxv2mxELR3')
  console.log('password md5', md5Password)

  const server = http.createServer((req, res) => {
    const query = qs.parse(url.parse(req.url).query)
    console.log('query', query)

    const signature = base64Sha1(query.data, md5Password)
    console.log('signature', signature)

    res.writeHead(200, {
      'Content-Type': 'application/json'
    })
    res.end(JSON.stringify({signature}))
  })

  server.listen(8080, () => {
    console.log('Server listen on http://localhost:8080')
  })

  function md5 (str) {
    return crypto.createHash('md5').update(str, 'utf8').digest('hex')
  }

  function base64Sha1 (str, secret) {
    return crypto.createHmac('sha1',secret).update(str,'utf8').digest().toString('base64')
  }

在上面代码中,可以看到SDK调用上传时会传入一些参数,然后再进行加密。我们再找到upyun-wxapp-sdk.js文件中第42行开始,代码如下

  Upyun.prototype.getSignature = function (data, cb) {
      wx.request({
        url: this.getSignatureUrl,
        data: {
          data: data
        },
        success: function (res) {
          cb(null, res.data.signature)
        },
        fail: function (err) {
          cb(err)
        }
      })
    }

可以看出,又拍云SDK会获取getSignatureUrl的地址,并对这个地址发起get请求,同时传递data参数,继而在demo-server.js文件中进行相关的加密处理。熟悉了这个过程之后,我们Laravel端的代码写起来也就比较简单了。

Laravel 代码


// routes/api.php  路由

//这里我使用了dingo/api的包,因此是$api->的写法,未使用的可直接更换为常规写法即可
$api->get('signature', 'UtilsController@upSignature'); // 返回又拍云的验证

// UtilsController.php 控制器代码

<?php

namespace App\Http\Controllers;

class UtilsController extends Controller
{

    public function upSignature()
    {

        /*
        * config('upyun.operator.password') 为又拍云的operator的密码
        * 这里可以直接改为密码字符串,不过为了更加保密和灵活,我写成了配置文件。
        * 然后在env中可以动态配置
        */

        $md5Password = md5(config('upyun.operator.password'));

        $signature = base64_encode(hash_hmac("sha1", request()->data, $md5Password, true));

        return ['signature' => $signature];
    }
}

// config/upyun.php

<?php

return [
    'operator' => [
        'name'     => env('UPYUN_OPERATOR_NAME', ''),
        'password' => env('UPYUN_OPERATOR_PASSWORD', ''),
    ]
];

然后将写好的signature地址替换掉getSignatureUrl里的http://localhost:8080就可以上传成功了。

其实,我写这篇文章的目的是与其看文档,Google搜索半天,还不如我看源码解决问题来的快??

本作品采用《CC 协议》,转载必须注明作者和本文链接
There's nothing wrong with having a little fun.
Epona
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!