服务器

我用了一台阿里云服务器,任何能在互联网上被访问到的服务都可以。服务器的 IP 地址是 42.120.40.68。在本地电脑,使用命令行工具可以登录到服务器。Windows 推荐使用 Cmder 作为命令行工具,macOS 用户可以使用系统自带的终端(Terminal)。

ssh wanghao@42.120.40.68

wanghao 是在我的服务器上的某个用户的名字,这个用户是我自己创建的。一开始,你可以使用服务器的超级管理员:root 登录到你的服务器,然后你可以创建新的用户,为用户分配权限等等。

主机名

配置一个主机名,指向服务器的 IP 地址,这个主机名就是访问本地开发环境用的主机名。我让 sandbox.ninghao.net这个主机名指向了我的服务器:42.120.40.68

验证主机名是否已经解析到指定的服务器,可以在命令行下面用 ping 命令测试一下:

→ ping sandbox.ninghao.net
PING sandbox.ninghao.net (42.120.40.68): 56 data bytes

用 ping 命令测试 sandbox.ninghao.net 的时候,返回的 IP 地址就是我的服务器的 IP 地址。

Nginx 代理

在服务器上安装 Nginx,再去配置一台 Nginx 代理服务器。我的服务器操作系统是 CentOS 7.x,安装 Nginx ,执行:

# 安装包含 Nginx 的仓库
sudo yum install epel-release -y

# 安装 Nginx
sudo yum install nginx -y

# 启动 Nginx
sudo systemctl start nginx

# 开机自启动 Nginx
sudo systemctl enable nginx

代理配置

在 Nginx 的配置目录的下面,创建一个新的配置文件,放在 /etc/nginx/conf.d,这个目录是 /etc/nginx/nginx.conf 配置文件里面设置的。配置文件所在的目录可能会有变化,比如有可能在 /etc/nginx/sites-enabled 。具体配置文件所在的目录,你要根据自己的实际情况,检查 Nginx 的主配置,就是 nginx.conf 里面的配置。

/etc/nginx/conf.d/sandbox.ninghao.net.conf:

upstream tunnel {
  server 127.0.0.1:7689;
}

server {
  listen       		    443 ssl;
  server_name               sandbox.ninghao.net;
  ssl                       on;
  client_max_body_size      128m;
  ssl_certificate           /etc/nginx/ssl/sandbox.ninghao.net/214241634170706.pem;
  ssl_certificate_key       /etc/nginx/ssl/sandbox.ninghao.net/214241634170706.key;
  ssl_session_timeout       5m;
  ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers               AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
  ssl_prefer_server_ciphers on;

  location / {
    proxy_set_header  X-Real-IP  $remote_addr;
    proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header  Host $http_host;
    proxy_redirect    off;
    expires           off;
    sendfile          off;
    proxy_pass        http://tunnel;
  }
}

上面配置了一台服务器,里面用到了 ssl ,这样服务器就支持使用 https 来传输数据了,这是现代网站或应用并且要做的事情。配置 ssl ,你需要申请 ssl 证书,在阿里云,你可以申请免费的 ssl 证书,或者使用 Let’s Encrypt ,也可以免费申请到证书。

有了证书,就按上面的配置,证书一般有两个文件,把它们存储在服务器上的某个目录的下面,然后分别设置 ssl_certificate 与 ssl_certificate_key 指令的值。

.key 与 .pem 只是证书惯用的文件扩展名,这个扩展名不重要,重要的是文件里面的内容。.key 指的是证书的密钥,.pem 是证书内容。用 Let’s Encrypt 申请的证书,证书文件的扩展名应该是 .cert。

证书密钥

证书密钥文件的扩展名一般是 .key,这个文件里的内容应该作为 Nginx 服务器配置里的 ssl_certificate_key 指令的值。文件里的内容像下面这样:

-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAiDnt/zboVuY23iQBYcocvJSewGDol87FoLOquz61L8rNKc5p
...
-----END RSA PRIVATE KEY-----
证书内容

证书内容文件的扩展名一般是 .pem 或者 .cert,文件要作为 Nginx 服务器配置里的 ssl_certificate 指令的值。文件里的内容像下面这样:

-----BEGIN CERTIFICATE-----
MIIFgjCCBGqgAwIBAgIQdtV9VRMTtKBDDfN3UO3ujTANBgkqhkiG9w0BAQsFADCB
...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFYjCCBEqgAwIBAgIQTEzYoPxP6q4VVKh/CQ7ahzANBgkqhkiG9w0BAQsFADCB
...
-----END CERTIFICATE-----

重新启动

对 Nginx 服务做了新的配置,要重新加载或者重新启动 Nginx 才能让新的配置生效。执行:

# 检查配置文件是否正常
sudo nginx -t

# 重新加载 Nginx
sudo systemctl reload nginx

开发环境

搭建微信支付的开发环境,要保证开发环境可以在互联网上被访问到。因为微信支付系统会通过应用支付的结果,如果开发环境在互联网上不能被访问到,也就收不到这个支付结果。在开发很多其它外部服务的时候,都需要这样做,比如支付宝,微信公众号等等。下面介绍的方法同样适用于搭建开发这些服务的环境。

我用的方法是使用了一台能在互联网上被访问到的服务器,在上面用 Nginx 配置一个代理,把请求转发到服务器的某个端口上。然后用 ssh 在本地跟服务器之间打一个通道,通道用的端口就是配置 Nginx 的时候,设置的上游服务(upstream)的端口。再去设置一个主机名,让它指向服务器,服务器会把请求转发到通道用的端口,这样实际提供服务的就是我们在本地上搭建的开发环境了。

 

 

[bdbtn]https://pan.7gen.top/ali/os/%E3%80%90%E4%B8%8D%E5%BF%98%E5%88%9D%E5%BF%83%E8%87%AA%E7%94%A8%E7%89%88%E3%80%91%5B%E5%A4%AA%E9%98%B3%E8%B0%B7%E5%9B%BE%E6%A0%87%5D%20Win10_21H1_19043.1151%20X64%20%E6%97%A0%E6%9B%B4%E6%96%B0%5B%E7%B2%BE%E7%AE%80%E7%89%88%5D%5B2.15G%5D(2021.8.1).iso[/bdbtn]

创建项目

文章里我会在一个 Node.js 应用里实施微信扫码支付的功能,要用的框架是 Adonis.js。确定本地电脑上已经安装好了 Node.js v9.x.x(主要是因为代码里用到了 spread 操作符),推荐使用 NVM 来管理安装的 Node.js,这样可以很容易切换使用不同版本的 Node.js。有了 Node.js,再去安装框架需要的命令行工具。

安装框架命令行

npm install @adonisjs/cli --global

创建项目

使用安装好的 Adonis 框架的命令行工具,去创建一个基于 Adonis 框架的 Node.js 应用。

adonis new ninghao-sandbox-v2

完成以后进入到项目所在的目录,再去运行一下项目。

cd ninghao-sandbox-v2
adonis serve --dev

打开浏览器,访问一下 localhost:3333,可以打开创建的 Adonis 项目。

微信支付:开发准备与实施扫码支付细节手册(上)

图:Anna Paschenko

开通微信支付服务,准备一个可以在互联网上被访问到的开发环境,就可以为应用开发微信支付功能了。下面就一起了解一下搭建开发微信支付环境的方法,然后在一个 Node.js 应用里实现微信支付的扫码支付(Native)功能。

内容比较多,所以分成两个部分,这是上半部分,主要介绍的是微信支付开发前的一些准备工作,在本地搭建一个开发微信支付的环境。文章配套有个视频版本,宁皓网会员可以在线观看:

  1. 命令行工具:Windows 下载安装完整版的 Cmder,macOS 使用系统自带的终端(Terminal),当我在文章里提到打开命令行工具的时候,指的就是打开命令行界面(CLI),意思就是让你打开这两个工具里的其中的一个(Cmder / Terminal)。

课程发布:《Node.js 应用:Websocket》

介绍了开发具有实时功能的应用需要的 Websocket。客户端(比如浏览器)与服务端之间可以在实时沟通交流。

在服务端可以注册一些通信用的频道(Channel),每个频道下面月可以添加多个主题(Topic)。然后在客户端那里可以选择去订阅频道或者主题,这样在客户端与服务端之间就可以通过这个频道进行通信,客户端有什么事可以发送给服务端,服务端收到消息可以决定如何去处理。在服务端可以做广播,广播的消息在所有的客户端上都可以实时得到。

比如某个用户在某篇文章上发表了一条评论,服务端收到评论可以做一下广播,这样正在浏览这篇文章的其他用户不需要刷新页面就可以看到新的评论。在课程里我们会用一个聊天功能来演示如何使用 Websocket。

道别,姥爷

“王皓啊,这次要跟你道别了,我的好外孙。” 姥爷紧紧地用两只手抓住我的右臂。8 年前,姥爷随二姨一家搬到济南。那天,我走进站台,见到了远处的姥爷。头戴礼帽,手里拄着几年前他来济南时买的拐杖,里面好像还藏着一把剑。其实姥爷不太需要那把拐杖,我猜他应该是喜欢那个酷酷地感觉才这样的。我走近了,姥爷看到了我,顿了一下手里的拐杖,躲了一下脚,暴出一句粗话(山东口音),“他妈的,我还以为再也见不到你了。”

60 几年前,姥爷跟我现在相似的年纪。为了不让全家饿死,他背上了几块姥姥做的煎饼,拿了几块钱,跳上火车,从山东出发,去往一个他只在别人的家信上看到的一个地方,东北的黑龙江省伊春市,这也是后来我出生的地方。姥爷特别在乎自己的健康状况,你带给他的健康药,他都会很仔细地询问具体的吃法。有天深夜,他哆哆嗦嗦地走进二姨二姨父的房间,“你们快看看吧,我好像没脉了。” 已过鲐背之年的姥爷,身体向来很好。后来才发现,他是把氨茶碱当作安眠药吃了。

姥爷受儒家教育,年轻时对子女都非常严厉,吃饭时筷子怎么拿,给人家倒水时手应该放在哪里。年老以后也是非常注重礼节,对晚辈也是一样。每次我去看他,说几句话以后,他会让我出去跟二姨父聊天,然后他会安静地坐在一旁陪着,直到我离开。他早已不再是生活中的主角,大部分时间都是这样安静地坐着。

六月十号,我到二姨家去探望姥爷,“有一个月没来了吧,挺想你的”。我带了一盒小雪买的保护眼睛的药给他,他很开心,向我询问药的吃法,让我转告小雪,表示感谢,我们还自拍合了影。离开以后我就打算下个月十号再来看看姥爷,不过在月底的时候我买了盒蚊香送过去,说了几句话以后我又出来跟二姨二姨父聊天,他像往常一样坐在沙发那里陪着我们,不过两三分钟以后便回到自己屋子里去了。

七月八号,我在屋子里正在写些东西,电话静了音,我听到在客厅的小雪接了一个电话,问:“你们在哪里,好的 …”,听她的语气,我就知道有事发生,打开门,小雪说:“快去二姨那,姥爷可能不行了”。姥爷已经九十四岁,这种事情在我心里也早有些准备,但真的发生了,还是心慌慌。我好像早有预感,两天前我梦到了姥爷,我们一起坐在一艘船上,像是去旅行。

我骑车赶去,坐在他的床边,他双手紧紧抓住我的胳膊,“王皓啊,这次要跟你道别了,我的好外孙”。第二天,亲戚们从各地赶来与姥爷告别。第三天,姥爷见到了从南方赶火车回来的孙女,五分钟以后便撒手离开了这个世界。

进京

屋子里坐着百十来号人,他们参与的项目影响着上亿人的娱乐、学习、工作还有生活。想到这,突然有种不寒而栗的感觉。

Luke 在微信上跟我说:“12/5 下午会在北京办公室举办一场 Flutter Live Beijing 的活动,要不要过来参加一下?” ,Luke 和他的团队在谷歌北京办公室负责 Flutter 在国内的一些工作。

第一次听到 Flutter 应该是在朋友圈里看到的。因为我删掉了所有新闻类应用,屏蔽了平时习惯性打开的新闻和视频网站。只剩下浏览器没办法删,安卓手机打开浏览器就会出现新闻。iOS 好一点,只有使用百度的时候,才会看到新闻。

看新闻是一种瘾,你不屑地点开一个带诱惑图像与标题的新闻,再抬眼看别处的时候就是半小时之后了。越看越想看,越看越觉得自个儿傻。这个瘾又很难戒掉,因为它无处不在,太容易得到,随便哪里的新闻内容都足够填补我们的每一分钟的空余时间。

现在我们的时间几乎可以被一部手机安排的满满的,各种应用能满足我们所有的需求。也就是它们占据了我们每天所有的剩余时间。我们不再有自己独立的思考时间,发呆的时间。放下手机,上床睡觉。第二天仍然是类似的轮回。我们可以试试不定期地找一天,弄个 24 小时不动手机的活动。

人工智能,机器学习,我们的行为、习惯、喜好都不断地在被这些应用学习着。所以它能推荐我们更想看到的内容,甚至能做出预测。我媳妇不只一次跟我说,“淘宝真是神奇,我就是某天想了一下某个东西,第二天它就出现在了淘宝的页面上。”

我们出门不再带着现金,也不再恐惧找不到路。打开 12306 应用,订两张高铁票,再用携程找个旅馆,即可开启一段国内旅行。随便到达哪个陌生的城市,都可以像本地人一样,使用城市的公交系统,找到隐藏在胡同里的餐馆。

我很好奇谷歌办公室长啥样,里面的人是怎么工作的,还能结识一群新的朋友。所以我就应邀去了这次在北京举办的 Flutter 交流活动。

行程都是由小雪(媳妇)安排,她订好了车票还有旅馆。住的地方是在杨梅斜竹街上的一家汉庭,这条街据说明朝时就有了。很便宜,200 多点一天,人不多,店家给升级成了家庭房。附近有吃有喝,距离故宫也很近。街上有家叫铃木食堂的餐厅可以试一下,做的米饭挺好吃的。

在北京坐地铁得下载一个叫易通行的应用,上海用的是 Metro,杭州直接用支付宝。可能是有什么利益保护吧,不然还是直接用支付宝更方便一些。

济南到北京坐高铁的话只需要两小时,体感上,跟在济南本地逛个街没啥区别。从家坐公交到车站半小时,留上半小时,再坐两小时火车就到了。下了火车,地铁到前门站,然后全部都是徒步,正好逛逛。这几天没打过一次滴滴。第一天走了 19 公里,小朋友也是跟着一起走,出门她也很兴奋。

这次我们体验了一下北京传统小吃,卤煮,爆肚,羊蝎子。卤煮跟羊蝎子应该是本地人经常吃的东西,因为我看店里大部分都是本地人。路过一家卤煮店(陈记卤煮小肠),提前看了一眼大众点评,上面有两样推荐卤煮火烧还有卤煮小肠。头一回来,之前没吃过,点菜的时候我装作是老顾客,故意不看菜单,“给我来个卤煮火烧还有卤煮小肠”,伙计答:“卤煮火烧还有卤煮小肠是一回事,你告诉我要几碗就行了”。

伙计气场自信而强大,我却灰溜溜地要了两碗,店主递给我一张小纸条,上面写着 “二”。我拿着小纸条走到做卤煮的师傅跟前,我跟他之间是一口大锅,里边是各种卤煮。在我之前排着还有别人,我跟师傅说了句:“两碗”,给他看了一下店主给我的 “二” 字纸条,他没回应,继续为排在我前面的人加工卤煮。都做完了,我以为轮到我了,就站在那口锅的跟前儿,见他磨蹭着往锅里填东西,没有给我做的意思。我说:“还要等吗?”,师傅:“您得给我票儿啊 ~ ”。我又灰溜溜地把那个 “二” 字票交给了他。

小雪从网上看到说北京的豆浆不叫豆浆,叫豆汁,味道也很特别,一般人儿降不了它。她在路边儿买了一杯,天儿太冷,我们躲进附近的咖啡馆,她先是递给女儿喝了一口,女儿咧咧嘴,自己又尝了一口,表情很复杂,我又吸了一口。顿时将我推回到小时候,出现在家里的酸菜缸跟前。这个豆汁的味道跟酸菜缸里腌出来的酸菜汤是一个味儿。回过神来,迅速撤离咖啡馆,将其弃之。往后一整天,时不时地还会回想起家里的那口酸菜缸。

一个真实的商业网站案例(课程已发布)

最近做了一个关于搭建商业网站的迷你系列课程。这是一个真实的案例,网站运行在阿里云 ECS 服务器上,并搭配了负载均衡,提高网站的响应速度。

年前的时候,于哥微信跟我说他自己的服务器到期了,忘记了续费,网站被删除掉了,问我还能再把网站找回来吧。阿里云服务器在过期以后,数据会保留一阵子,看来是很久以后才知道的。不然及时续费,网站还是可以继续使用的。

10 几年前,通过朋友介绍,我帮于哥搭建了一个作品展示网站。 因为自己本身也喜好摄影,所以看到专业的摄影师由衷地敬仰,总想着巴结巴结。后来我们也成为了朋友,一直保持联系,也一块儿探讨有没有合作的可能。比如做个商业摄影在线教育怎么样?

7 年前我不再帮别人搭建网站,专心做自己的网站。以前为别人做的网站也都交待给所有者自己管理。龙哥的网站也是一样。其实也不用怎么管,就是平时续续服务器还有域名的费用。

这期间一直也有人找我搭建网站,我觉得这种展示类型的网站一直是有市场的,但是在国内一直也没看到有太好的产品能帮助大家方便地创建这种网站。国外就有很多,比如 wix.com,squarespace.com 等等,都是帮助需要网站的人快速自助搭建一个漂亮的网站。wix 很多年前就已经是上市公司了。WordPress.com 也是一个非常好的例子。

我遇到的情况大部分都是找自由职业者定制网站,这其实存在不少问题。首先是价格,如果称得上定制,价格就一定是贵的,便宜的一定不行。大部分企业或个人对网站功能的需求都不高,主要看的是网站页面的设计,也就是对于开发并没有什么难度,主要是设计要下功夫。

自由职业者的收费会低一些,但是不算稳定,存在一定风险。专业的机构收费太高,一般的小型企业或个人根本负担不起。所以大家做网站都相信熟人推荐,作为自由职业者,你只要服务好一个客户,他就一定会把你推荐给别人。

企业展示产品,个人展示作品,这种类型的网站最好能有一家稳定的服务商来提供。开发个自助搭建网站的产品,按年收费,一定有市场。做成一定的规模,稳定性就会好,价格也会便宜,比如一年几百块,任何想要拥有独立网站的客户都是愿意付的。

十年前,我帮客户设计个网站,制作周期需要一周的时间,收费在 2000 左右,往后每年收 500 的维护费用。对于自由职业者来说,收入有限,因为自己的时间有限。一定要做成无人监管,可批量复制的服务。如果你能开发出这样的产品,每个客户每年 600 , 有 500 个客户就不用去上班了。如果是 5000 客户,买房子娶媳妇都不用父母操心了。第二年还有三分之一的人会续费。

于哥知道我不再帮别人搭建网站了,也就没好意思直接让我帮他做个网站,他想让我推荐个人帮他再做一个。后来我想他找别人做还得花不少钱,我就跟他说,我帮你弄个得了。

春季课程预览

春季课程已经开始更新了,这一季的内容都很实用。包含构建电子商务网站,开发集成微信支付与支付宝,开发微信 / 支付宝电商小程序(正在每周更新)。年费会员现在就可以加入学习群,提前下载网站或应用的源代码。

构建电子商务网站

构建自己独立的电子商务网站更能体现自己的品牌,界面与服务流程都可以自己定制,更重要的是客户是你自己的。而且有些情况,你可能不太希望把自己的产品放到其它平台上去销售,你可能受不了其它平台的各种限制或者不认同他们的品牌等等。

开源软件世界里为构建电子商务网站提供了很多方案,有专注电商的,比如 Magento,OpenCart,还可以通过内容管理系统的电子商务功能插件解决,比如 WordPress、Drupal 这些系统都提供了相关的电商插件。

我更偏向选择综合性质的平台搭建电商网站,除了电商功能,这些平台提供了更多的可能性。在  WordPress 平台上,最受欢迎的电商插件是 WooCommerce,如今这个插件已经并入 Automattic 公司。这家公司的创始人就是 WordPress 系统当初的作者,旗下拥有 WordPress.com。

在 Drupal 平台上,电商解决方案应该选择 Commerce 模块。Drupal + Commerce 这个组合能创建更为复杂的电商系统。因为他们太灵活了,所以我们需要花更多的时间去学习。

这次《构建电子商务网站》这个系列课程,我选择了 WordPress + WooCommerce 这个组合。我希望创建一个极简风格的电商网站,界面上要淡化不重要的元素,或直接去掉没那么重要的元素,把用户的注意力导向产品或服务本身。

OpenWrt 内网下发 IPv6

2018 年 4 月,工业和信息化部发布了关于贯彻落实《推进互联网协议第六版 (IPv6) 规模部署行动计划》的通知,大力推广下一代互联网技术 IPv6。

时至今日,高校教育网以及各大运营商已经基本支持了 IPv6 地址的分配。然而绝大多数家庭的路由器还不能支持自动下发,因此并没有享受到下一代互联网的快感。

这里主要介绍使用 OpenWrt/LEDE 来解决内网设备分配 IPv6 的问题。

想要让路由器下的设备获得 IPv6 地址通常有三种方式:relay(中继)、NAT(地址转换)、Passthrough(穿透)。下面分三个部分谈谈具体的配置方案。

中继模式(relay)

OpenWrt 早在 15.05 就内置了 relay 协议,具体是通过 odhcpd 来实现的。

这种方案可以让子网设备分到公网 IPv6 的地址,是最为科学的,然而 odhcpd 的实现有很多 bug,在实际使用中有时候会掉线,需要重启服务才能解决,因此在部分设备上体验不佳。

具体操作如下

进入路由器终端

$ ssh root@192.168.1.1

编辑 dhcp 配置文件,修改如下

$ vi /etc/config/dhcp

config dhcp 'lan'
    option interface 'lan'
    option start '100'
    option limit '150'
    option leasetime '12h'
    option ra 'relay'
    option ndp 'relay'
    option dhcpv6 'relay'
    option ra_management '1'

config dhcp 'wan'
    option interface 'wan'
    option ignore '1'

config dhcp 'wan6'
    option interface 'wan'
    option ra 'relay'
    option ndp 'relay'
    option dhcpv6 'relay'
    option master '1'

编辑 network 文件,将地址第一个字母 f 修改为 d

$ vi /etc/config/network

config globals 'globals'
    option ula_prefix 'dd53:abcd:abcd::/48'

最后重启即可

穿透模式(Passthrough)

Passthrough 的原理是将内外网进行桥接,然后对 IPv4 流量采用 NAT 方式进行转发,稳定性相当好,唯一的缺点就是路由器自身会失去 IPv6 的访问,因此如果想在路由器上做离线下载等功能就会非常麻烦。

配置如下

安装 ebtables 和 kmod-ebtables-ipv6 模块

$ opkg update 
$ opkg install ebtables kmod-ebtables-ipv6

设置 IPv4 转发

$ interface=`ip -6 route | grep "default from" | awk '{print $7}'` 
$ ebtables -t broute -A BROUTING -p ! ipv6 -j DROP -i $interface 

内外网桥接

$ brctl addif br-lan $interface

杀死 odhcpd

$ /etc/init.d/odhcpd stop 
$ /etc/init.d/odhcpd disable 

点击 LAN 接口的 edit 按钮进入设置,在 IPv6 Settings 选项卡中勾上 Always announce default router

做完这些步骤,稍等一会儿子网设备就会分到相应的公网 IPv6 地址了