新西兰网站制作公司

新西兰网站制作公司

489
views

新西兰华人网页设计公司|我们的后端工程师David总结的静态站点加速访问经验,通过 Google CDN 加速,如何让你的网站在一秒钟内打开

Marketplacefull stack developer Kevin wrote the post • 0 comments • 489 views • 2020-04-05 13:33 • added this tag no more than 24h

大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,需要将客户的网站提高访问速度,用到了 Google Cloud Platform的cdn。
 
如果更近一步,除了新西兰本地外,想要让大陆地区访问速度更加快一些的话,我们可以考虑将站点内容放在 Google Cloud Platform 的 Storage 中,并且使用 Google CDN 进行全网加速(主要是因为国内大部分线路可以不绕路使用到香港边缘节点).

本文假设:

你有 Google Cloud Platform 账户,并懂得一些基本操作
在自己的机器上安装了 Google Cloud SDK,如果没有的话,参考 《挂载 Google Storage 到 VPS 文件系统》
账户中已经验证好了自己的域名,如果没有的话,参考 Domain ownership verification
获取 SSL 证书
除非希望托管一个 HTTP 的网站,否则一个证书是必不可少的,Google 不会帮你自动完成这一步。

有多种方式可以获取一个 SSL 证书,如果目前手头没有的话,我们通过 Let’s Encrypt 申请一个好了,首先获取 certbot:$ git clone https://github.com/certbot/certbot.git
$ cd certbot
由于我自己的一些原因(在迁移前域名解析到 GitHub Pages 上的,不能通过改变解析的方式验证,否则会造成博客访问中断),这里我使用了 DNS 的方式进行获取:$ ./certbot-auto certonly --manual  --preferred-challenges=dns  --email [email protected] --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d nova.moe
之后会看到一个修改域名 TXT 记录的要求,类似如下:
 

Please deploy a DNS TXT record under the name _acme-challenge.nova.moe with the following value: J50GNXkhGmKCfn-0LQJcknVGtPEAQ_U_WajcLXgqWqo
 
 
 
此时我们只需要做一个 _acme-challenge 的 TXT 解析,内容为上述的 J50G...qo 即可。

如果没有遇到的问题的话我们就可以看到生成好的证书信息,类似如下:
 IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/nova.moe/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/nova.moe/privkey.pem
 
此时通过任何你喜欢的方式把 fullchain.pem 和 privkey.pem 下载到自己本地。

创建 Storage 桶,配置权限,导入文件
创建 Storage 桶

新建一个 Storage 容器,名称就是你希望的域名
 
 

 
 
 
配置权限

由于是对外提供内容的网站,我们需要把 Public Access 设置为 Public 并且为网站配置优化,具体方法如下:

 
 
 
 
 
 
点击最右边的选项,选择 Edit bucket permissions,添加一个 allUsers 账户,权限为 Storage Object Viewer

还是那个选项,选择 Edit website configuration,按照如下填入 index.html 和你的站点 404 页面(比如我的就是 404.html)
 
 

 
 
 
 
导入文件

注意,这里不要参考 《挂载 Google Storage 到 VPS 文件系统》,挂载到本地目录后上传,因为这样会导致文件的 meta 信息错误,导致本来该渲染为图片的地方变成了 octec-stream,本来该是网页的地方变成了 octec-stream ,本来… 然后访问任何页面都是弹出一个下载框了。

正确方法是使用 gsutil 来上传,语法如下:$ gsutil cp -r dir gs://my-bucket其中 dir 就是源目录,假设我的博客放在 /var/www/nova.moe/ 目录下 ,my-bucket 是目标 Storage 桶地址,比如我的就是 gs://nova.moe,整理一下就是:$ gsutil /var/www/nova.moe/* -r dir gs://www.yourdomain.com
可能有同学想到这里如果用 gsutil rsync 的话会不会更好一些,毕竟有增量同步之类的。

不是这样的,这样做的话即不能保留 meta 信息,也不会增量同步,相关描述如下:

Note that by default, the gsutil rsync command does not copy the ACLs of objects being synchronized and instead will use the default bucket ACL (see gsutil help defacl).

The gsutil rsync command copies changed files in their entirety and does not employ the rsync delta-transfer algorithm to transfer portions of a changed file. This is because cloud objects are immutable and no facility exists to read partial cloud object checksums or perform partial overwrites.
 
 
 
设置 Load Balancer

创建一个 HTTP/HTTPS 的 Load Balancer,Backend 创建一个 Backend Bucket,选择刚刚创建的 Storage 桶并勾选 Enable Cloud CDN:

 
 
 
Frontend 那一块选择 HTTPS:
 

 
 
然后导入 SSL 证书,其中 Public Key 和 Chain 全部上传 fullchain.pem, Private Key 就上传 privkey.pem :
 

 
 
 
创建好了之后有一个 Overview,类似如下:
 

 
 
延迟对比

GitHub Pages

 
 
Google Cloud Platform + Google CDN
 

 
 
已知问题 / 缺陷

这样子做的话,每次更新站点的同步也是一个问题,尤其是对于像我这样的 Hexo 用户而言,本地不想安装 SDK,传完文件后手动上服务器 gsutil cp 会很麻烦。

Google Cloud Platform 的 Load Balancer 并不能做 Force SSL,也就是说如果在 HTTPS 只选择了 443 端口的话,用户未添加 https:// 前缀的情况下访问的返回会是 404,如果同时也添加了 80 端口的话,直接访问也不会自动跳转到 https 上面。

一个比较大众化的解决方案是开一个 Compute instance 监听 80 端口专门用来做 SSL 重定向,但这样便失去了便捷性同时也会导致价格无意义地升高(无脑猜测 Google 团队到现在还不提供这个功能是有一定动机的,关于这个的 issue tracker:Redirect all HTTP traffic to HTTPS when using the HTTP(S) Load Balancer 从 15 年到现在还没有一个正式的答复),另一个思路是将域名加入 Preload List,但是现在的网站结构似乎并不能上 List,目前我正在寻找一个更加可靠的解决方案并不定期更新本文,相关更新会优先在 Twitter 上通知,欢迎关注。

2018-08-16 更新:最终我还是选择了新建一个 Compute instance 的方式解决(可以参考:利用 GCE 建立一个 Anycast 网络,超快的香港节点,Google Cloud CDN),Nginx 配置中稍微需要注意一下,Google CDN 会给后端传一个 X-Forwarded-Proto ,鉴于 Google CDN 的 SSL 只到边缘服务器就截止了(其实还是一个 Half-baked SSL),所以后端 Nginx 还是监听在 80 端口的,如果需要 SSL 重定向的话,需要加入以下内容:
 if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
 Google Load Balancer

我们知道,业界 Load Balancer 一般有以下实现方案:

一个 Anycast IP(比如 Google LB)
一个普通 IP(比如 Ucloud LB)
一个 CNAME 分区解析(比如 AWS ELB)

且不讨论 CNAME 那个看上去像是一个没钱 Anycast 的解决方案,而且如果用给 APEX 解析的话,在没有特殊加成(APEX FLATTEN)的情况会把 MX 记录炸穿(然后你就无法收邮件了),前者看上去是一个比较用户友好的方式,因为你只需要 A 记录到一个 IP 就可以了,绿色无害。

GFE

在了解 Google LB 之前,我们需要了解一个名词——GFE,感谢 Snowden 的 PPT,我们可以有一个直观的图示:

 

 
 
 
所有到 Google 的流量会在 GFE 上 SSL Offload(应该叫 SSL 卸载?),并且后端全部是在 Google 内网内以 HTTP 的方式进行传输。

在 Google Infrastructure Security Design Overview 中,我们也可以看到:

When a service wants to make itself available on the Internet, it can register itself with an infrastructure service called the Google Front End (GFE). The GFE ensures that all TLS connections are terminated using correct certificates and following best practices such as supporting perfect forward secrecy.


Google LB 也是一样,使用 GFE 作为面相用户的前端,将 SSL 流量在 GFE 上终结,然后以 HTTP 的方式回到后端的 Service 上。

使用一个统一的入口好处有很多,比如 GCP 就提供了一个统一的位置修改 SSL Policy:
 

 
可以自己选择心水的 Cipher Suite 和最低 TLS 版本等,和 Cloudflare 差不多(但是要让 Ucloud LB 做到这一点似乎就太困难了,他们基于 HAProxy 搞的 ULB 到本文发布时还不支持 TLS 1.3,而且要改 Cipher Suite 需要提工单)。

Premium IP

GCP 上的 IP 分为两种,一种是 Premium ,一种是 Standard,默认是前者,Google LB 也只能用 Premium。

Premium 使用的是冷土豆路由,所发送的数据包会保持在 Google 的内网内,并且在尽可能靠近用户的 PoP 离开。
 

 
 
 
  view all
大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,需要将客户的网站提高访问速度,用到了 Google Cloud Platform的cdn。
 
如果更近一步,除了新西兰本地外,想要让大陆地区访问速度更加快一些的话,我们可以考虑将站点内容放在 Google Cloud Platform 的 Storage 中,并且使用 Google CDN 进行全网加速(主要是因为国内大部分线路可以不绕路使用到香港边缘节点).

本文假设:

你有 Google Cloud Platform 账户,并懂得一些基本操作
在自己的机器上安装了 Google Cloud SDK,如果没有的话,参考 《挂载 Google Storage 到 VPS 文件系统》
账户中已经验证好了自己的域名,如果没有的话,参考 Domain ownership verification
获取 SSL 证书
除非希望托管一个 HTTP 的网站,否则一个证书是必不可少的,Google 不会帮你自动完成这一步。

有多种方式可以获取一个 SSL 证书,如果目前手头没有的话,我们通过 Let’s Encrypt 申请一个好了,首先获取 certbot:
$ git clone https://github.com/certbot/certbot.git
$ cd certbot

由于我自己的一些原因(在迁移前域名解析到 GitHub Pages 上的,不能通过改变解析的方式验证,否则会造成博客访问中断),这里我使用了 DNS 的方式进行获取:
$ ./certbot-auto certonly --manual  --preferred-challenges=dns  --email [email protected] --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d nova.moe

之后会看到一个修改域名 TXT 记录的要求,类似如下:
 

Please deploy a DNS TXT record under the name _acme-challenge.nova.moe with the following value: J50GNXkhGmKCfn-0LQJcknVGtPEAQ_U_WajcLXgqWqo
 
 
 
此时我们只需要做一个 _acme-challenge 的 TXT 解析,内容为上述的 J50G...qo 即可。

如果没有遇到的问题的话我们就可以看到生成好的证书信息,类似如下:
 
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/nova.moe/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/nova.moe/privkey.pem

 
此时通过任何你喜欢的方式把 fullchain.pem 和 privkey.pem 下载到自己本地。

创建 Storage 桶,配置权限,导入文件
创建 Storage 桶

新建一个 Storage 容器,名称就是你希望的域名
 
 

 
 
 
配置权限

由于是对外提供内容的网站,我们需要把 Public Access 设置为 Public 并且为网站配置优化,具体方法如下:

 
 
 
 
 
 
点击最右边的选项,选择 Edit bucket permissions,添加一个 allUsers 账户,权限为 Storage Object Viewer

还是那个选项,选择 Edit website configuration,按照如下填入 index.html 和你的站点 404 页面(比如我的就是 404.html)
 
 

 
 
 
 
导入文件

注意,这里不要参考 《挂载 Google Storage 到 VPS 文件系统》,挂载到本地目录后上传,因为这样会导致文件的 meta 信息错误,导致本来该渲染为图片的地方变成了 octec-stream,本来该是网页的地方变成了 octec-stream ,本来… 然后访问任何页面都是弹出一个下载框了。

正确方法是使用 gsutil 来上传,语法如下:
$ gsutil cp -r dir gs://my-bucket
其中 dir 就是源目录,假设我的博客放在 /var/www/nova.moe/ 目录下 ,my-bucket 是目标 Storage 桶地址,比如我的就是 gs://nova.moe,整理一下就是:
$ gsutil /var/www/nova.moe/* -r dir gs://www.yourdomain.com

可能有同学想到这里如果用 gsutil rsync 的话会不会更好一些,毕竟有增量同步之类的。

不是这样的,这样做的话即不能保留 meta 信息,也不会增量同步,相关描述如下:

Note that by default, the gsutil rsync command does not copy the ACLs of objects being synchronized and instead will use the default bucket ACL (see gsutil help defacl).

The gsutil rsync command copies changed files in their entirety and does not employ the rsync delta-transfer algorithm to transfer portions of a changed file. This is because cloud objects are immutable and no facility exists to read partial cloud object checksums or perform partial overwrites.
 
 
 
设置 Load Balancer

创建一个 HTTP/HTTPS 的 Load Balancer,Backend 创建一个 Backend Bucket,选择刚刚创建的 Storage 桶并勾选 Enable Cloud CDN:

 
 
 
Frontend 那一块选择 HTTPS:
 

 
 
然后导入 SSL 证书,其中 Public Key 和 Chain 全部上传 fullchain.pem, Private Key 就上传 privkey.pem :
 

 
 
 
创建好了之后有一个 Overview,类似如下:
 

 
 
延迟对比

GitHub Pages

 
 
Google Cloud Platform + Google CDN
 

 
 
已知问题 / 缺陷

这样子做的话,每次更新站点的同步也是一个问题,尤其是对于像我这样的 Hexo 用户而言,本地不想安装 SDK,传完文件后手动上服务器 gsutil cp 会很麻烦。

Google Cloud Platform 的 Load Balancer 并不能做 Force SSL,也就是说如果在 HTTPS 只选择了 443 端口的话,用户未添加 https:// 前缀的情况下访问的返回会是 404,如果同时也添加了 80 端口的话,直接访问也不会自动跳转到 https 上面。

一个比较大众化的解决方案是开一个 Compute instance 监听 80 端口专门用来做 SSL 重定向,但这样便失去了便捷性同时也会导致价格无意义地升高(无脑猜测 Google 团队到现在还不提供这个功能是有一定动机的,关于这个的 issue tracker:Redirect all HTTP traffic to HTTPS when using the HTTP(S) Load Balancer 从 15 年到现在还没有一个正式的答复),另一个思路是将域名加入 Preload List,但是现在的网站结构似乎并不能上 List,目前我正在寻找一个更加可靠的解决方案并不定期更新本文,相关更新会优先在 Twitter 上通知,欢迎关注。

2018-08-16 更新:最终我还是选择了新建一个 Compute instance 的方式解决(可以参考:利用 GCE 建立一个 Anycast 网络,超快的香港节点,Google Cloud CDN),Nginx 配置中稍微需要注意一下,Google CDN 会给后端传一个 X-Forwarded-Proto ,鉴于 Google CDN 的 SSL 只到边缘服务器就截止了(其实还是一个 Half-baked SSL),所以后端 Nginx 还是监听在 80 端口的,如果需要 SSL 重定向的话,需要加入以下内容:
 
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}

 Google Load Balancer

我们知道,业界 Load Balancer 一般有以下实现方案:

一个 Anycast IP(比如 Google LB)
一个普通 IP(比如 Ucloud LB)
一个 CNAME 分区解析(比如 AWS ELB)

且不讨论 CNAME 那个看上去像是一个没钱 Anycast 的解决方案,而且如果用给 APEX 解析的话,在没有特殊加成(APEX FLATTEN)的情况会把 MX 记录炸穿(然后你就无法收邮件了),前者看上去是一个比较用户友好的方式,因为你只需要 A 记录到一个 IP 就可以了,绿色无害。

GFE

在了解 Google LB 之前,我们需要了解一个名词——GFE,感谢 Snowden 的 PPT,我们可以有一个直观的图示:

 

 
 
 
所有到 Google 的流量会在 GFE 上 SSL Offload(应该叫 SSL 卸载?),并且后端全部是在 Google 内网内以 HTTP 的方式进行传输。

在 Google Infrastructure Security Design Overview 中,我们也可以看到:


When a service wants to make itself available on the Internet, it can register itself with an infrastructure service called the Google Front End (GFE). The GFE ensures that all TLS connections are terminated using correct certificates and following best practices such as supporting perfect forward secrecy.



Google LB 也是一样,使用 GFE 作为面相用户的前端,将 SSL 流量在 GFE 上终结,然后以 HTTP 的方式回到后端的 Service 上。

使用一个统一的入口好处有很多,比如 GCP 就提供了一个统一的位置修改 SSL Policy:
 

 
可以自己选择心水的 Cipher Suite 和最低 TLS 版本等,和 Cloudflare 差不多(但是要让 Ucloud LB 做到这一点似乎就太困难了,他们基于 HAProxy 搞的 ULB 到本文发布时还不支持 TLS 1.3,而且要改 Cipher Suite 需要提工单)。

Premium IP

GCP 上的 IP 分为两种,一种是 Premium ,一种是 Standard,默认是前者,Google LB 也只能用 Premium。

Premium 使用的是冷土豆路由,所发送的数据包会保持在 Google 的内网内,并且在尽可能靠近用户的 PoP 离开。
 

 
 
 
 
589
views

新西兰电商网站开发公司|我们的后端工程师David总结的独立电商购物网站整合支付接口的经验,如何让大陆的买家在你的网站上通过微信支付和支付宝付款

Marketplacefull stack developer Kevin wrote the post • 0 comments • 589 views • 2020-04-05 12:56 • added this tag no more than 24h

大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,有机会接触到 Stripe 的工作流程,事情很简单,对于优秀的服务,我们应该付出使用他们的成本(这样他们可以继续提供优质的服务),对于商户来说收钱就是一个比较有意思的部分了,鉴于大多数网友都是付钱,本文决定分享一下 Stripe 整合支付宝来收钱的方法,且本文不是网上很多出现的那种引用 checkout.js 的过期的方法(许多人都互相转来转去,看了一圈下来都是这个),而是使用 Stripe.js 来完成。
 

Stripe 目前收款方式有两种,简单来说,我们分为 Easy 难度和 Hard 难度,前者只支持信用卡,储蓄卡和 Apple Pay,而后者则支持多种支付方式,最终的效果图如下:


Easy 模式——使用 「Checkout」
Easy 模式即使用他们写好的页面,被称为「Checkout」,对于商户来说需要在后台定义好产品(Products),生成 sku 后写一个按钮出发脚本自动跳转过去,页面上需要写的内容如下:<!-- Load Stripe.js on your website. -->
<script src="https://js.stripe.com/v3"></script>
<!-- Create a button that your customers click to complete their purchase. Customize the styling to suit your branding. -->
<button
style="background-color:#6772E5;color:#FFF;padding:8px 12px;border:0;border-radius:4px;font-size:1em"
id="checkout-button-sku_xxxxxxxxxxx"
role="link"
>
Checkout
</button>
<div id="error-message"></div>
<script>
(function() {
var stripe = Stripe('pk_test_xxxxxxxxxxxx');
var checkoutButton = document.getElementById('checkout-button-sku_G40GQYkIX4a8c4');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
stripe.redirectToCheckout({
items: [{sku: 'sku_xxxxxxxxxxx', quantity: 1}],
// Do not rely on the redirect to the successUrl for fulfilling
// purchases, customers may not always reach the success_url after
// a successful payment.
// Instead use one of the strategies described in
// https://stripe.com/docs/paymen ... lment
successUrl: 'https://xxx.xxx.xx/success',
cancelUrl: 'https://xxx.xxx.xx/canceled',
})
.then(function (result) {
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer.
var displayError = document.getElementById('error-message');
displayError.textContent = result.error.message;
}
});
});
})();
</script>

这样在用户点了按钮之后就会出现一个 Stripe 的支付页面:


这样就可以用了,用户在付款完成之后就会跳转回到 successUrl,同时 Stripe 可以给你预先定义好的接口(WebHook)发一个 POST 请求告知,大致逻辑如下(其实官方有示范):\Stripe\Stripe::setApiKey('sk_test_xxxxxxxxxxxxxx');

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = 'whsec_xxxxxxxxxxxxxxx';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}

// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
// 授权用户
$target_customer = \Stripe\Customer::retrieve($session['customer']);
$target_email = $target_customer['email'];
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}


这样就可以获取到用户的信息并且给用户提供/升级服务了,很方便是不是?
不过呢,「Checkout」只支持卡和 Apple Pay,对于喜欢见到付钱就想扫一扫的用户来说并不友好,所以我们需要使用一些别的方法。
Hard 模式——使用「STRIPE ELEMENTS」
为了照顾没有信用卡,遇见码就开始掏手机准备打开或绿或蓝应用准备开始扫一扫的用户来说,我们需要加入支付宝的支持功能。
首先确认你的账户中 Alipay 是连接上并且处于激活状态的,没有这一点等于没戏(也就不用继续往下看了)。


如果你的 Stripe 已经连接上了支付宝,接下来我们就可以开始整合了。
首先我们明白一下对于商户来说,逻辑是怎么样的:


首先由于 Stripe 并不是原生支持支付宝,所以所有这种非信用卡交易都被挂了称为「Source」的东西下,可以理解为一个插件或者一个临时的钱包,以下一段是具体的逻辑,请仔细阅读:
当用户需要付款的时候,用户会先通过 JS 创建一个 「Source」对象,并指定类型为「Alipay」,这个时候 Stripe.js 会带领用户去支付宝的付款页面进行支付,如果付款成功了,那么这个「Source」的状态会从 charge.pending 变成 source.chargeable ,可以理解为用户给临时钱包付了钱,在有了这个状态之后我们可以调用 Stripe 对这个 Source 扣款(Charge),把临时钱包的钱扣到自己 Stripe 账户上,然后就完成了付款的过程。
用户逻辑
我们先来看用户的逻辑部分:
用户的逻辑是,在对应的购买页面上应该有一个 Button,上面写上「立即购买」,这样用户只要一摸那个按钮,就可以看到支付宝的付款页面了,为了满足这个需要,我们需要这么做,在对应的页面上放个 Button:<button id="checkout-button">
立即购买
</button>

然后引用 stripe.js 并写一点 JS 来完成接下来的事情:<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
(function() {
var stripe = Stripe('pk_xxxxxxxxxxxxxx');
var checkout-button = document.getElementById('checkout-button');
checkout-button.addEventListener('click', function () {
stripe.createSource({
type: 'alipay',
amount: 1988,
currency: 'hkd',
// 这里你需要渲染出一些用户的信息,不然后期没法知道是谁在付钱
owner: {
email: '{$user_email}',
},
redirect: {
return_url: 'https://xxx.xxx.xx/buy',
},
}).then(function(result) {
window.location.replace(result.source.redirect.url);
});
});
})();
</script>
其中,owner 和 owner 下的 email 建议填写,不然付款后可能不好找到究竟是哪个用户付了钱,如果正巧你们不用 email 来标识用户,那也可以写点别的,对于 owner 来说有以下字段可供选择:
  "owner": {
"address": null,
"email": "[email protected]",
"name": null,
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": null,
"verified_phone": null
},
此外,如果你还希望在 Source 中包含一些其他的内容的话,可以自由地使用 metadata ,并在内部包含一系列键值对。由于 createSource 执行完成后会返回一个包含 Source 对象,类似如下:{
"id": "src_16xhynE8WzK49JbAs9M21jaR",
"object": "source",
"amount": 1099,
"client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
"created": 1445277809,
"currency": "usd",
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": "null",
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": "null",
"verified_phone": null
},
"redirect": {
"return_url": "https://shop.example.com/crtA6B28E1",
"status": "pending",
"url": "https://hooks.stripe.com/redir ... ot%3B
},
"statement_descriptor": null,
"status": "pending",
"type": "alipay",
"usage": "single_use",
"alipay": {
"statement_descriptor": null,
"native_url": null
}
}
其中的 redirect 只要访问了就会自动被 Stripe 跳转到支付宝家的支付页面上,所以我们最后会有一行:
window.location.replace(result.source.redirect.url);
将用户跳转过去,然后用户扫码付钱:


用户这边的事情就结束了。
服务器逻辑
用户的事情结束了,服务器端就需要开始处理用户的请求了,一个简单的方法如下,在用户付款完成后 Stripe 会跳转回我们 JS 中定义的 return_url 并附带一些参数,类似如下:https://xxx.xxx.xx/buy?client_secret=src_client_secret_xxxxxxxxx&source=src_xxxxxxxxx

这个时候我们可以通过服务端来解析 src_xxxxxxxxx 得知是谁在付钱,并完成后续的操作:\Stripe\Stripe::setApiKey('sk_xxxxxxxxxxxxxx');

// 获取 URL 中 source 字段
$source_id = filter_input(INPUT_GET, 'source', FILTER_SANITIZE_URL);
$source_object = \Stripe\Source::retrieve($source_id);

// 先确认一下用户付了钱,别有 Object 就直接开始整...
$status = $source_object->redirect->status;
if($status == "failed")
{
// 如果用户没有付钱,我们该怎么做?
}
else {
// 从临时钱包从把钱扣了~
\Stripe\Charge::create([
'amount' => 1988,
'currency' => 'hkd',
'source' => $source_id,
]);
// 有了 Object 之后我们可以提取出对应的用户邮件地址或者别的信息,比如邮件地址可以这样提取
$user_email = $source_object->owner->email;
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}
顺便可以登录 Stripe 后台看看~


微信实现

其实也非常的简单,只需要将上一步的type改为wechat,同时返回source中的source.wechat.qr_code_url转为二维码就好了
 
var wechatCallback = function (source) {
generateQRCode(source.wechat.qr_code_url);
}
function generateQRCode(value) {
var qrEle = document.getElementById("qrcode");
var qrcode = new QRCode(qrEle, {
width: 100,
height: 100
});
qrcode.makeCode(value);
qrEle.style.display = 'inline-block';
}二维码出来后, 扫码就会得到如下结果
 

 
不过这种方法只是说可以用而已,最好的方法可以参考 Best Practices for Using Sources 来接受 Webhook 多次验证,但这个就不在本文的范围内了。

由于是第一次接触支付领域,上述步骤中可能还是会有不少坑或者啥的(所以别直接在生产环境照抄,写完之后一定要多 Review 几遍逻辑漏洞),不过这个至少是一个可用最小模型了,还有不少可以改进的地方,比如浏览器端的函数其实可以异步拉起,这样可以在网页上弄一个 Modal 弹窗,看上去更加用户友好一些。
 
 
补充说明(04/06/2020):
 
关于注册 Stripe 账号

和注册支付宝账号一个道理,首先注册账号,然后绑定自己银行卡,BUT, 就像前面提到的,不支持中国,所以就算注册成功,也没法激活,也就没法收款。

 
 
 
对于中国商家怎么办呢,我能想到的就只有这3个办法:

自己去支持国家去办理张银行卡
使用国外的朋友银行卡
使用Atlas

对于James来说,因为他是新西兰kiwi,所以他可以创建他的主账号,然后添加我的stripe账号到他team memeber账号列表中,这样我就可以访问他账户下所有开发者需要的权限。邀请成功后,Dashboard页面

 

 
Stripe.js & Elements

当然对于如果你觉得Checkout的方式集成度太高,不够灵活,那Stripe.js是你最好的选择。

Stripe.js其实就是客户端的一个JS核心类库,Elements是它的UI类库,其实上面的Checkout代码就是Stripe使用两者给我们封装好了的,避免我们直接接触敏感信息,但是其实质都是一样的,都是用来创建source。这里就直接贴出客户端的代码了(这里没有用到Elements做UI,因为就是一个按钮支付,太简单,所以没用到):var stripe = Stripe('pk_live_xxxx');

function alipay(amount) {
showLoading();
stripe.createSource({
type: 'alipay',
amount: parseInt(amount),
currency: 'gbp', // usd, eur,
redirect: {
return_url: 'https://xxx.eu/pay/result.html'
},
}).then(function (response) {
hideLoading();
if (response.error) {
alert(response.error.message);
}
else {
processStripeResponse(response.source);
}
});
}

function processStripeResponse(source) {
window.location.href = source.redirect.url;
}





  view all
大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,有机会接触到 Stripe 的工作流程,事情很简单,对于优秀的服务,我们应该付出使用他们的成本(这样他们可以继续提供优质的服务),对于商户来说收钱就是一个比较有意思的部分了,鉴于大多数网友都是付钱,本文决定分享一下 Stripe 整合支付宝来收钱的方法,且本文不是网上很多出现的那种引用 checkout.js 的过期的方法(许多人都互相转来转去,看了一圈下来都是这个),而是使用 Stripe.js 来完成。
 

Stripe 目前收款方式有两种,简单来说,我们分为 Easy 难度和 Hard 难度,前者只支持信用卡,储蓄卡和 Apple Pay,而后者则支持多种支付方式,最终的效果图如下:


Easy 模式——使用 「Checkout」
Easy 模式即使用他们写好的页面,被称为「Checkout」,对于商户来说需要在后台定义好产品(Products),生成 sku 后写一个按钮出发脚本自动跳转过去,页面上需要写的内容如下:
<!-- Load Stripe.js on your website. -->
<script src="https://js.stripe.com/v3"></script>
<!-- Create a button that your customers click to complete their purchase. Customize the styling to suit your branding. -->
<button
style="background-color:#6772E5;color:#FFF;padding:8px 12px;border:0;border-radius:4px;font-size:1em"
id="checkout-button-sku_xxxxxxxxxxx"
role="link"
>
Checkout
</button>
<div id="error-message"></div>
<script>
(function() {
var stripe = Stripe('pk_test_xxxxxxxxxxxx');
var checkoutButton = document.getElementById('checkout-button-sku_G40GQYkIX4a8c4');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
stripe.redirectToCheckout({
items: [{sku: 'sku_xxxxxxxxxxx', quantity: 1}],
// Do not rely on the redirect to the successUrl for fulfilling
// purchases, customers may not always reach the success_url after
// a successful payment.
// Instead use one of the strategies described in
// https://stripe.com/docs/paymen ... lment
successUrl: 'https://xxx.xxx.xx/success',
cancelUrl: 'https://xxx.xxx.xx/canceled',
})
.then(function (result) {
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer.
var displayError = document.getElementById('error-message');
displayError.textContent = result.error.message;
}
});
});
})();
</script>


这样在用户点了按钮之后就会出现一个 Stripe 的支付页面:


这样就可以用了,用户在付款完成之后就会跳转回到 successUrl,同时 Stripe 可以给你预先定义好的接口(WebHook)发一个 POST 请求告知,大致逻辑如下(其实官方有示范):
\Stripe\Stripe::setApiKey('sk_test_xxxxxxxxxxxxxx');

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = 'whsec_xxxxxxxxxxxxxxx';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}

// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
// 授权用户
$target_customer = \Stripe\Customer::retrieve($session['customer']);
$target_email = $target_customer['email'];
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}



这样就可以获取到用户的信息并且给用户提供/升级服务了,很方便是不是?
不过呢,「Checkout」只支持卡和 Apple Pay,对于喜欢见到付钱就想扫一扫的用户来说并不友好,所以我们需要使用一些别的方法。
Hard 模式——使用「STRIPE ELEMENTS」
为了照顾没有信用卡,遇见码就开始掏手机准备打开或绿或蓝应用准备开始扫一扫的用户来说,我们需要加入支付宝的支持功能。
首先确认你的账户中 Alipay 是连接上并且处于激活状态的,没有这一点等于没戏(也就不用继续往下看了)。


如果你的 Stripe 已经连接上了支付宝,接下来我们就可以开始整合了。
首先我们明白一下对于商户来说,逻辑是怎么样的:


首先由于 Stripe 并不是原生支持支付宝,所以所有这种非信用卡交易都被挂了称为「Source」的东西下,可以理解为一个插件或者一个临时的钱包,以下一段是具体的逻辑,请仔细阅读:
当用户需要付款的时候,用户会先通过 JS 创建一个 「Source」对象,并指定类型为「Alipay」,这个时候 Stripe.js 会带领用户去支付宝的付款页面进行支付,如果付款成功了,那么这个「Source」的状态会从 charge.pending 变成 source.chargeable ,可以理解为用户给临时钱包付了钱,在有了这个状态之后我们可以调用 Stripe 对这个 Source 扣款(Charge),把临时钱包的钱扣到自己 Stripe 账户上,然后就完成了付款的过程。
用户逻辑
我们先来看用户的逻辑部分:
用户的逻辑是,在对应的购买页面上应该有一个 Button,上面写上「立即购买」,这样用户只要一摸那个按钮,就可以看到支付宝的付款页面了,为了满足这个需要,我们需要这么做,在对应的页面上放个 Button:
<button id="checkout-button">
立即购买
</button>


然后引用 stripe.js 并写一点 JS 来完成接下来的事情:
<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
(function() {
var stripe = Stripe('pk_xxxxxxxxxxxxxx');
var checkout-button = document.getElementById('checkout-button');
checkout-button.addEventListener('click', function () {
stripe.createSource({
type: 'alipay',
amount: 1988,
currency: 'hkd',
// 这里你需要渲染出一些用户的信息,不然后期没法知道是谁在付钱
owner: {
email: '{$user_email}',
},
redirect: {
return_url: 'https://xxx.xxx.xx/buy',
},
}).then(function(result) {
window.location.replace(result.source.redirect.url);
});
});
})();
</script>

其中,owner 和 owner 下的 email 建议填写,不然付款后可能不好找到究竟是哪个用户付了钱,如果正巧你们不用 email 来标识用户,那也可以写点别的,对于 owner 来说有以下字段可供选择:
  
"owner": {
"address": null,
"email": "[email protected]",
"name": null,
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": null,
"verified_phone": null
},

此外,如果你还希望在 Source 中包含一些其他的内容的话,可以自由地使用 metadata ,并在内部包含一系列键值对。由于 createSource 执行完成后会返回一个包含 Source 对象,类似如下:
{
"id": "src_16xhynE8WzK49JbAs9M21jaR",
"object": "source",
"amount": 1099,
"client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
"created": 1445277809,
"currency": "usd",
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": "null",
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": "null",
"verified_phone": null
},
"redirect": {
"return_url": "https://shop.example.com/crtA6B28E1",
"status": "pending",
"url": "https://hooks.stripe.com/redir ... ot%3B
},
"statement_descriptor": null,
"status": "pending",
"type": "alipay",
"usage": "single_use",
"alipay": {
"statement_descriptor": null,
"native_url": null
}
}

其中的 redirect 只要访问了就会自动被 Stripe 跳转到支付宝家的支付页面上,所以我们最后会有一行:
window.location.replace(result.source.redirect.url);
将用户跳转过去,然后用户扫码付钱:


用户这边的事情就结束了。
服务器逻辑
用户的事情结束了,服务器端就需要开始处理用户的请求了,一个简单的方法如下,在用户付款完成后 Stripe 会跳转回我们 JS 中定义的 return_url 并附带一些参数,类似如下:
https://xxx.xxx.xx/buy?client_secret=src_client_secret_xxxxxxxxx&source=src_xxxxxxxxx


这个时候我们可以通过服务端来解析 src_xxxxxxxxx 得知是谁在付钱,并完成后续的操作:
\Stripe\Stripe::setApiKey('sk_xxxxxxxxxxxxxx');

// 获取 URL 中 source 字段
$source_id = filter_input(INPUT_GET, 'source', FILTER_SANITIZE_URL);
$source_object = \Stripe\Source::retrieve($source_id);

// 先确认一下用户付了钱,别有 Object 就直接开始整...
$status = $source_object->redirect->status;
if($status == "failed")
{
// 如果用户没有付钱,我们该怎么做?
}
else {
// 从临时钱包从把钱扣了~
\Stripe\Charge::create([
'amount' => 1988,
'currency' => 'hkd',
'source' => $source_id,
]);
// 有了 Object 之后我们可以提取出对应的用户邮件地址或者别的信息,比如邮件地址可以这样提取
$user_email = $source_object->owner->email;
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}

顺便可以登录 Stripe 后台看看~


微信实现

其实也非常的简单,只需要将上一步的type改为wechat,同时返回source中的source.wechat.qr_code_url转为二维码就好了
 

var wechatCallback = function (source) {
generateQRCode(source.wechat.qr_code_url);
}
function generateQRCode(value) {
var qrEle = document.getElementById("qrcode");
var qrcode = new QRCode(qrEle, {
width: 100,
height: 100
});
qrcode.makeCode(value);
qrEle.style.display = 'inline-block';
}
二维码出来后, 扫码就会得到如下结果
 

 
不过这种方法只是说可以用而已,最好的方法可以参考 Best Practices for Using Sources 来接受 Webhook 多次验证,但这个就不在本文的范围内了。

由于是第一次接触支付领域,上述步骤中可能还是会有不少坑或者啥的(所以别直接在生产环境照抄,写完之后一定要多 Review 几遍逻辑漏洞),不过这个至少是一个可用最小模型了,还有不少可以改进的地方,比如浏览器端的函数其实可以异步拉起,这样可以在网页上弄一个 Modal 弹窗,看上去更加用户友好一些。
 
 
补充说明(04/06/2020):
 
关于注册 Stripe 账号

和注册支付宝账号一个道理,首先注册账号,然后绑定自己银行卡,BUT, 就像前面提到的,不支持中国,所以就算注册成功,也没法激活,也就没法收款。

 
 
 
对于中国商家怎么办呢,我能想到的就只有这3个办法:

自己去支持国家去办理张银行卡
使用国外的朋友银行卡
使用Atlas

对于James来说,因为他是新西兰kiwi,所以他可以创建他的主账号,然后添加我的stripe账号到他team memeber账号列表中,这样我就可以访问他账户下所有开发者需要的权限。邀请成功后,Dashboard页面

 

 
Stripe.js & Elements

当然对于如果你觉得Checkout的方式集成度太高,不够灵活,那Stripe.js是你最好的选择。

Stripe.js其实就是客户端的一个JS核心类库,Elements是它的UI类库,其实上面的Checkout代码就是Stripe使用两者给我们封装好了的,避免我们直接接触敏感信息,但是其实质都是一样的,都是用来创建source。这里就直接贴出客户端的代码了(这里没有用到Elements做UI,因为就是一个按钮支付,太简单,所以没用到):
var stripe = Stripe('pk_live_xxxx');

function alipay(amount) {
showLoading();
stripe.createSource({
type: 'alipay',
amount: parseInt(amount),
currency: 'gbp', // usd, eur,
redirect: {
return_url: 'https://xxx.eu/pay/result.html'
},
}).then(function (response) {
hideLoading();
if (response.error) {
alert(response.error.message);
}
else {
processStripeResponse(response.source);
}
});
}

function processStripeResponse(source) {
window.location.href = source.redirect.url;
}





 
540
views

新西兰网站开发公司|我们的ios开发工程师Mia分享如何学习设计?如何提升自己对物体深层次的理解。

Othersfull stack developer Kevin wrote the post • 0 comments • 540 views • 2020-04-05 03:25 • added this tag no more than 24h

关于我

刚入坑移动端开发的时候,大部分精力都放在了App功能的技术实现度上,对App相关的设计其实没有过多的关注,因为首先你必须实现了功能,才有精力去研究设计、打磨细节。

高中的时候学过一段时间美术,传统的美术老三样素描、速写、水粉,有一些绘画基础,大学并不是设计相关专业,但选修课学习了一些和设计相关的软件,比如:3DMax、CAD、Dreamweaver、Flash。大学期间报了一个班,学习了PS、CorelDRAW,拿了一个平面设计师资格证,然而这个证并没有什么卵用。

时隔这么多年,那些曾经学过的技能也早已忘的一干二净,从去年开始才慢慢的重新拾起来。

关于设计这块,因为我并不是专业的设计师,有些想法可能比较粗浅,这里只是简单的提供一个学习建议,不好的地方还欢迎大家指正。

美术基础
设计师最好有一定的绘画功底,因为它最能直接的表达出你大脑的想法,自我头脑风暴输出、与他人进行设计沟通,这些都是绘画能给你带来的,当你无法通过你的手来表现出你想法的时候,你会非常痛苦。



其实画画真的没你想象的那么难,很多艺考美术生考试前集训3-4个月也能考上一个艺术院校,所以,建议每天抽出那么一点时间去做绘画功底的积累,不仅有助于你的设计,更能提高审美,一举两得的事何乐而不为。在这里推荐一本我也在跟着画过的一本书《30天学会绘画》,这本书适合没有美术基础的小伙伴,为了练习入手了一个数位板,刚开始特别不习惯,配合PS电脑上比较难控制。现在很多画画的内容都在一个手绘本上完成,不依赖电脑,更能随心所欲利用碎片时间来练习,初学者建议先在本子上绘画。



学习绘画的目的是通过动手实践去锻炼我们的思考能力,刚开始画的不好没关系,重点是带着思考去不断的练习,每一次实践都应该让你感受到自己对物体深层次的理解。



绘画不仅可以帮助你建立原型设计草图的能力,更能增进你界面的排版和配色能力。

当然很多并没有很强的绘画能力,却也是远近闻名的设计大师,比如:山本耀司、可可·加布里埃·夏奈尔,我想说的是绘画仅是一种设计思考表现手段和工具,要看什么设计,对绘画依赖比较严重。



关于软件
提到设计相关的软件,最基础的还是PS,不是有句话,学好PS走遍天下都不怕,可见它的强大之处,哈哈~,说到PS那你一定知道Sketch,扁平化设计的流行和屏幕分辨率的提升推动了Sketch这款软件的流行,它可以帮你快速完成移动端界面的设计工作,除此之外还可以熟悉一下AI,AI可以更方便快捷的绘制矢量图形,配合PS使用很棒。熟练掌握PS、AI之后,可以再进阶学习AE、C4D等动效和3D制作工具,丰富我们的设计成果。



理论基础
设计中的理论基础包括:字体、色彩、排版等很多方面,需要我们自己去多看多学多研究,推荐两本烂大街的书《写给大家看的设计书》、《文字设计的原理》。除此之外还有很多设计师聚集的网站,比如:Dribbble、Behance、优设网、站酷网、UI中国等等。



说了这么多,自认为设计师除了要多练习,更要勤看书,好的设计师应该大部分都是书虫吧。

最后
推荐一篇干货满满的临摹文章以及我收集的一些设计相关的网站和工具

关于临摹的四个阶段

设计/摄影/图站
创造狮导航
Dribbble
Behance
站酷
设计师网址
牛大拿
UI中国
字由
MyFont
千库网
摄图网
图虫网
图片压缩
包图网
花瓣
UIgradients
优优教程网
阿里巴巴图标库
EASYICON图标库
Noun图标库
TOICON图标库
WORLDVECTOR
FreeDownloads
ICONFINDER
ICONS8
UEDC
网易用户体验中心
阿里巴巴UED
阿里巴巴中国站
淘宝前端FED
腾讯CDC
新浪UED
百度UXC
原型工具

墨刀
Axure
Sketch
Mockplus
XIAOPIN

最后
 
按照我们老板的给我派发的kpi,如果你准备开发一个ios 的app,请到我们的在线商店直接购买,我们公司支持kiwikiwifly这个平台的担保交易。 view all
关于我

刚入坑移动端开发的时候,大部分精力都放在了App功能的技术实现度上,对App相关的设计其实没有过多的关注,因为首先你必须实现了功能,才有精力去研究设计、打磨细节。

高中的时候学过一段时间美术,传统的美术老三样素描、速写、水粉,有一些绘画基础,大学并不是设计相关专业,但选修课学习了一些和设计相关的软件,比如:3DMax、CAD、Dreamweaver、Flash。大学期间报了一个班,学习了PS、CorelDRAW,拿了一个平面设计师资格证,然而这个证并没有什么卵用。

时隔这么多年,那些曾经学过的技能也早已忘的一干二净,从去年开始才慢慢的重新拾起来。

关于设计这块,因为我并不是专业的设计师,有些想法可能比较粗浅,这里只是简单的提供一个学习建议,不好的地方还欢迎大家指正。

美术基础
设计师最好有一定的绘画功底,因为它最能直接的表达出你大脑的想法,自我头脑风暴输出、与他人进行设计沟通,这些都是绘画能给你带来的,当你无法通过你的手来表现出你想法的时候,你会非常痛苦。



其实画画真的没你想象的那么难,很多艺考美术生考试前集训3-4个月也能考上一个艺术院校,所以,建议每天抽出那么一点时间去做绘画功底的积累,不仅有助于你的设计,更能提高审美,一举两得的事何乐而不为。在这里推荐一本我也在跟着画过的一本书《30天学会绘画》,这本书适合没有美术基础的小伙伴,为了练习入手了一个数位板,刚开始特别不习惯,配合PS电脑上比较难控制。现在很多画画的内容都在一个手绘本上完成,不依赖电脑,更能随心所欲利用碎片时间来练习,初学者建议先在本子上绘画。



学习绘画的目的是通过动手实践去锻炼我们的思考能力,刚开始画的不好没关系,重点是带着思考去不断的练习,每一次实践都应该让你感受到自己对物体深层次的理解。



绘画不仅可以帮助你建立原型设计草图的能力,更能增进你界面的排版和配色能力。

当然很多并没有很强的绘画能力,却也是远近闻名的设计大师,比如:山本耀司、可可·加布里埃·夏奈尔,我想说的是绘画仅是一种设计思考表现手段和工具,要看什么设计,对绘画依赖比较严重。



关于软件
提到设计相关的软件,最基础的还是PS,不是有句话,学好PS走遍天下都不怕,可见它的强大之处,哈哈~,说到PS那你一定知道Sketch,扁平化设计的流行和屏幕分辨率的提升推动了Sketch这款软件的流行,它可以帮你快速完成移动端界面的设计工作,除此之外还可以熟悉一下AI,AI可以更方便快捷的绘制矢量图形,配合PS使用很棒。熟练掌握PS、AI之后,可以再进阶学习AE、C4D等动效和3D制作工具,丰富我们的设计成果。



理论基础
设计中的理论基础包括:字体、色彩、排版等很多方面,需要我们自己去多看多学多研究,推荐两本烂大街的书《写给大家看的设计书》、《文字设计的原理》。除此之外还有很多设计师聚集的网站,比如:Dribbble、Behance、优设网、站酷网、UI中国等等。



说了这么多,自认为设计师除了要多练习,更要勤看书,好的设计师应该大部分都是书虫吧。

最后
推荐一篇干货满满的临摹文章以及我收集的一些设计相关的网站和工具

关于临摹的四个阶段

设计/摄影/图站
创造狮导航
Dribbble
Behance
站酷
设计师网址
牛大拿
UI中国
字由
MyFont
千库网
摄图网
图虫网
图片压缩
包图网
花瓣
UIgradients
优优教程网
阿里巴巴图标库
EASYICON图标库
Noun图标库
TOICON图标库
WORLDVECTOR
FreeDownloads
ICONFINDER
ICONS8
UEDC
网易用户体验中心
阿里巴巴UED
阿里巴巴中国站
淘宝前端FED
腾讯CDC
新浪UED
百度UXC
原型工具

墨刀
Axure
Sketch
Mockplus
XIAOPIN

最后
 
按照我们老板的给我派发的kpi,如果你准备开发一个ios 的app,请到我们的在线商店直接购买,我们公司支持kiwikiwifly这个平台的担保交易。
489
views

新西兰华人网页设计公司|我们的后端工程师David总结的静态站点加速访问经验,通过 Google CDN 加速,如何让你的网站在一秒钟内打开

Marketplacefull stack developer Kevin wrote the post • 0 comments • 489 views • 2020-04-05 13:33 • added this tag no more than 24h

大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,需要将客户的网站提高访问速度,用到了 Google Cloud Platform的cdn。
 
如果更近一步,除了新西兰本地外,想要让大陆地区访问速度更加快一些的话,我们可以考虑将站点内容放在 Google Cloud Platform 的 Storage 中,并且使用 Google CDN 进行全网加速(主要是因为国内大部分线路可以不绕路使用到香港边缘节点).

本文假设:

你有 Google Cloud Platform 账户,并懂得一些基本操作
在自己的机器上安装了 Google Cloud SDK,如果没有的话,参考 《挂载 Google Storage 到 VPS 文件系统》
账户中已经验证好了自己的域名,如果没有的话,参考 Domain ownership verification
获取 SSL 证书
除非希望托管一个 HTTP 的网站,否则一个证书是必不可少的,Google 不会帮你自动完成这一步。

有多种方式可以获取一个 SSL 证书,如果目前手头没有的话,我们通过 Let’s Encrypt 申请一个好了,首先获取 certbot:$ git clone https://github.com/certbot/certbot.git
$ cd certbot
由于我自己的一些原因(在迁移前域名解析到 GitHub Pages 上的,不能通过改变解析的方式验证,否则会造成博客访问中断),这里我使用了 DNS 的方式进行获取:$ ./certbot-auto certonly --manual  --preferred-challenges=dns  --email [email protected] --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d nova.moe
之后会看到一个修改域名 TXT 记录的要求,类似如下:
 

Please deploy a DNS TXT record under the name _acme-challenge.nova.moe with the following value: J50GNXkhGmKCfn-0LQJcknVGtPEAQ_U_WajcLXgqWqo
 
 
 
此时我们只需要做一个 _acme-challenge 的 TXT 解析,内容为上述的 J50G...qo 即可。

如果没有遇到的问题的话我们就可以看到生成好的证书信息,类似如下:
 IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/nova.moe/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/nova.moe/privkey.pem
 
此时通过任何你喜欢的方式把 fullchain.pem 和 privkey.pem 下载到自己本地。

创建 Storage 桶,配置权限,导入文件
创建 Storage 桶

新建一个 Storage 容器,名称就是你希望的域名
 
 

 
 
 
配置权限

由于是对外提供内容的网站,我们需要把 Public Access 设置为 Public 并且为网站配置优化,具体方法如下:

 
 
 
 
 
 
点击最右边的选项,选择 Edit bucket permissions,添加一个 allUsers 账户,权限为 Storage Object Viewer

还是那个选项,选择 Edit website configuration,按照如下填入 index.html 和你的站点 404 页面(比如我的就是 404.html)
 
 

 
 
 
 
导入文件

注意,这里不要参考 《挂载 Google Storage 到 VPS 文件系统》,挂载到本地目录后上传,因为这样会导致文件的 meta 信息错误,导致本来该渲染为图片的地方变成了 octec-stream,本来该是网页的地方变成了 octec-stream ,本来… 然后访问任何页面都是弹出一个下载框了。

正确方法是使用 gsutil 来上传,语法如下:$ gsutil cp -r dir gs://my-bucket其中 dir 就是源目录,假设我的博客放在 /var/www/nova.moe/ 目录下 ,my-bucket 是目标 Storage 桶地址,比如我的就是 gs://nova.moe,整理一下就是:$ gsutil /var/www/nova.moe/* -r dir gs://www.yourdomain.com
可能有同学想到这里如果用 gsutil rsync 的话会不会更好一些,毕竟有增量同步之类的。

不是这样的,这样做的话即不能保留 meta 信息,也不会增量同步,相关描述如下:

Note that by default, the gsutil rsync command does not copy the ACLs of objects being synchronized and instead will use the default bucket ACL (see gsutil help defacl).

The gsutil rsync command copies changed files in their entirety and does not employ the rsync delta-transfer algorithm to transfer portions of a changed file. This is because cloud objects are immutable and no facility exists to read partial cloud object checksums or perform partial overwrites.
 
 
 
设置 Load Balancer

创建一个 HTTP/HTTPS 的 Load Balancer,Backend 创建一个 Backend Bucket,选择刚刚创建的 Storage 桶并勾选 Enable Cloud CDN:

 
 
 
Frontend 那一块选择 HTTPS:
 

 
 
然后导入 SSL 证书,其中 Public Key 和 Chain 全部上传 fullchain.pem, Private Key 就上传 privkey.pem :
 

 
 
 
创建好了之后有一个 Overview,类似如下:
 

 
 
延迟对比

GitHub Pages

 
 
Google Cloud Platform + Google CDN
 

 
 
已知问题 / 缺陷

这样子做的话,每次更新站点的同步也是一个问题,尤其是对于像我这样的 Hexo 用户而言,本地不想安装 SDK,传完文件后手动上服务器 gsutil cp 会很麻烦。

Google Cloud Platform 的 Load Balancer 并不能做 Force SSL,也就是说如果在 HTTPS 只选择了 443 端口的话,用户未添加 https:// 前缀的情况下访问的返回会是 404,如果同时也添加了 80 端口的话,直接访问也不会自动跳转到 https 上面。

一个比较大众化的解决方案是开一个 Compute instance 监听 80 端口专门用来做 SSL 重定向,但这样便失去了便捷性同时也会导致价格无意义地升高(无脑猜测 Google 团队到现在还不提供这个功能是有一定动机的,关于这个的 issue tracker:Redirect all HTTP traffic to HTTPS when using the HTTP(S) Load Balancer 从 15 年到现在还没有一个正式的答复),另一个思路是将域名加入 Preload List,但是现在的网站结构似乎并不能上 List,目前我正在寻找一个更加可靠的解决方案并不定期更新本文,相关更新会优先在 Twitter 上通知,欢迎关注。

2018-08-16 更新:最终我还是选择了新建一个 Compute instance 的方式解决(可以参考:利用 GCE 建立一个 Anycast 网络,超快的香港节点,Google Cloud CDN),Nginx 配置中稍微需要注意一下,Google CDN 会给后端传一个 X-Forwarded-Proto ,鉴于 Google CDN 的 SSL 只到边缘服务器就截止了(其实还是一个 Half-baked SSL),所以后端 Nginx 还是监听在 80 端口的,如果需要 SSL 重定向的话,需要加入以下内容:
 if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}
 Google Load Balancer

我们知道,业界 Load Balancer 一般有以下实现方案:

一个 Anycast IP(比如 Google LB)
一个普通 IP(比如 Ucloud LB)
一个 CNAME 分区解析(比如 AWS ELB)

且不讨论 CNAME 那个看上去像是一个没钱 Anycast 的解决方案,而且如果用给 APEX 解析的话,在没有特殊加成(APEX FLATTEN)的情况会把 MX 记录炸穿(然后你就无法收邮件了),前者看上去是一个比较用户友好的方式,因为你只需要 A 记录到一个 IP 就可以了,绿色无害。

GFE

在了解 Google LB 之前,我们需要了解一个名词——GFE,感谢 Snowden 的 PPT,我们可以有一个直观的图示:

 

 
 
 
所有到 Google 的流量会在 GFE 上 SSL Offload(应该叫 SSL 卸载?),并且后端全部是在 Google 内网内以 HTTP 的方式进行传输。

在 Google Infrastructure Security Design Overview 中,我们也可以看到:

When a service wants to make itself available on the Internet, it can register itself with an infrastructure service called the Google Front End (GFE). The GFE ensures that all TLS connections are terminated using correct certificates and following best practices such as supporting perfect forward secrecy.


Google LB 也是一样,使用 GFE 作为面相用户的前端,将 SSL 流量在 GFE 上终结,然后以 HTTP 的方式回到后端的 Service 上。

使用一个统一的入口好处有很多,比如 GCP 就提供了一个统一的位置修改 SSL Policy:
 

 
可以自己选择心水的 Cipher Suite 和最低 TLS 版本等,和 Cloudflare 差不多(但是要让 Ucloud LB 做到这一点似乎就太困难了,他们基于 HAProxy 搞的 ULB 到本文发布时还不支持 TLS 1.3,而且要改 Cipher Suite 需要提工单)。

Premium IP

GCP 上的 IP 分为两种,一种是 Premium ,一种是 Standard,默认是前者,Google LB 也只能用 Premium。

Premium 使用的是冷土豆路由,所发送的数据包会保持在 Google 的内网内,并且在尽可能靠近用户的 PoP 离开。
 

 
 
 
  view all
大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,需要将客户的网站提高访问速度,用到了 Google Cloud Platform的cdn。
 
如果更近一步,除了新西兰本地外,想要让大陆地区访问速度更加快一些的话,我们可以考虑将站点内容放在 Google Cloud Platform 的 Storage 中,并且使用 Google CDN 进行全网加速(主要是因为国内大部分线路可以不绕路使用到香港边缘节点).

本文假设:

你有 Google Cloud Platform 账户,并懂得一些基本操作
在自己的机器上安装了 Google Cloud SDK,如果没有的话,参考 《挂载 Google Storage 到 VPS 文件系统》
账户中已经验证好了自己的域名,如果没有的话,参考 Domain ownership verification
获取 SSL 证书
除非希望托管一个 HTTP 的网站,否则一个证书是必不可少的,Google 不会帮你自动完成这一步。

有多种方式可以获取一个 SSL 证书,如果目前手头没有的话,我们通过 Let’s Encrypt 申请一个好了,首先获取 certbot:
$ git clone https://github.com/certbot/certbot.git
$ cd certbot

由于我自己的一些原因(在迁移前域名解析到 GitHub Pages 上的,不能通过改变解析的方式验证,否则会造成博客访问中断),这里我使用了 DNS 的方式进行获取:
$ ./certbot-auto certonly --manual  --preferred-challenges=dns  --email [email protected] --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d nova.moe

之后会看到一个修改域名 TXT 记录的要求,类似如下:
 

Please deploy a DNS TXT record under the name _acme-challenge.nova.moe with the following value: J50GNXkhGmKCfn-0LQJcknVGtPEAQ_U_WajcLXgqWqo
 
 
 
此时我们只需要做一个 _acme-challenge 的 TXT 解析,内容为上述的 J50G...qo 即可。

如果没有遇到的问题的话我们就可以看到生成好的证书信息,类似如下:
 
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/nova.moe/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/nova.moe/privkey.pem

 
此时通过任何你喜欢的方式把 fullchain.pem 和 privkey.pem 下载到自己本地。

创建 Storage 桶,配置权限,导入文件
创建 Storage 桶

新建一个 Storage 容器,名称就是你希望的域名
 
 

 
 
 
配置权限

由于是对外提供内容的网站,我们需要把 Public Access 设置为 Public 并且为网站配置优化,具体方法如下:

 
 
 
 
 
 
点击最右边的选项,选择 Edit bucket permissions,添加一个 allUsers 账户,权限为 Storage Object Viewer

还是那个选项,选择 Edit website configuration,按照如下填入 index.html 和你的站点 404 页面(比如我的就是 404.html)
 
 

 
 
 
 
导入文件

注意,这里不要参考 《挂载 Google Storage 到 VPS 文件系统》,挂载到本地目录后上传,因为这样会导致文件的 meta 信息错误,导致本来该渲染为图片的地方变成了 octec-stream,本来该是网页的地方变成了 octec-stream ,本来… 然后访问任何页面都是弹出一个下载框了。

正确方法是使用 gsutil 来上传,语法如下:
$ gsutil cp -r dir gs://my-bucket
其中 dir 就是源目录,假设我的博客放在 /var/www/nova.moe/ 目录下 ,my-bucket 是目标 Storage 桶地址,比如我的就是 gs://nova.moe,整理一下就是:
$ gsutil /var/www/nova.moe/* -r dir gs://www.yourdomain.com

可能有同学想到这里如果用 gsutil rsync 的话会不会更好一些,毕竟有增量同步之类的。

不是这样的,这样做的话即不能保留 meta 信息,也不会增量同步,相关描述如下:

Note that by default, the gsutil rsync command does not copy the ACLs of objects being synchronized and instead will use the default bucket ACL (see gsutil help defacl).

The gsutil rsync command copies changed files in their entirety and does not employ the rsync delta-transfer algorithm to transfer portions of a changed file. This is because cloud objects are immutable and no facility exists to read partial cloud object checksums or perform partial overwrites.
 
 
 
设置 Load Balancer

创建一个 HTTP/HTTPS 的 Load Balancer,Backend 创建一个 Backend Bucket,选择刚刚创建的 Storage 桶并勾选 Enable Cloud CDN:

 
 
 
Frontend 那一块选择 HTTPS:
 

 
 
然后导入 SSL 证书,其中 Public Key 和 Chain 全部上传 fullchain.pem, Private Key 就上传 privkey.pem :
 

 
 
 
创建好了之后有一个 Overview,类似如下:
 

 
 
延迟对比

GitHub Pages

 
 
Google Cloud Platform + Google CDN
 

 
 
已知问题 / 缺陷

这样子做的话,每次更新站点的同步也是一个问题,尤其是对于像我这样的 Hexo 用户而言,本地不想安装 SDK,传完文件后手动上服务器 gsutil cp 会很麻烦。

Google Cloud Platform 的 Load Balancer 并不能做 Force SSL,也就是说如果在 HTTPS 只选择了 443 端口的话,用户未添加 https:// 前缀的情况下访问的返回会是 404,如果同时也添加了 80 端口的话,直接访问也不会自动跳转到 https 上面。

一个比较大众化的解决方案是开一个 Compute instance 监听 80 端口专门用来做 SSL 重定向,但这样便失去了便捷性同时也会导致价格无意义地升高(无脑猜测 Google 团队到现在还不提供这个功能是有一定动机的,关于这个的 issue tracker:Redirect all HTTP traffic to HTTPS when using the HTTP(S) Load Balancer 从 15 年到现在还没有一个正式的答复),另一个思路是将域名加入 Preload List,但是现在的网站结构似乎并不能上 List,目前我正在寻找一个更加可靠的解决方案并不定期更新本文,相关更新会优先在 Twitter 上通知,欢迎关注。

2018-08-16 更新:最终我还是选择了新建一个 Compute instance 的方式解决(可以参考:利用 GCE 建立一个 Anycast 网络,超快的香港节点,Google Cloud CDN),Nginx 配置中稍微需要注意一下,Google CDN 会给后端传一个 X-Forwarded-Proto ,鉴于 Google CDN 的 SSL 只到边缘服务器就截止了(其实还是一个 Half-baked SSL),所以后端 Nginx 还是监听在 80 端口的,如果需要 SSL 重定向的话,需要加入以下内容:
 
if ($http_x_forwarded_proto = "http") {
return 301 https://$host$request_uri;
}

 Google Load Balancer

我们知道,业界 Load Balancer 一般有以下实现方案:

一个 Anycast IP(比如 Google LB)
一个普通 IP(比如 Ucloud LB)
一个 CNAME 分区解析(比如 AWS ELB)

且不讨论 CNAME 那个看上去像是一个没钱 Anycast 的解决方案,而且如果用给 APEX 解析的话,在没有特殊加成(APEX FLATTEN)的情况会把 MX 记录炸穿(然后你就无法收邮件了),前者看上去是一个比较用户友好的方式,因为你只需要 A 记录到一个 IP 就可以了,绿色无害。

GFE

在了解 Google LB 之前,我们需要了解一个名词——GFE,感谢 Snowden 的 PPT,我们可以有一个直观的图示:

 

 
 
 
所有到 Google 的流量会在 GFE 上 SSL Offload(应该叫 SSL 卸载?),并且后端全部是在 Google 内网内以 HTTP 的方式进行传输。

在 Google Infrastructure Security Design Overview 中,我们也可以看到:


When a service wants to make itself available on the Internet, it can register itself with an infrastructure service called the Google Front End (GFE). The GFE ensures that all TLS connections are terminated using correct certificates and following best practices such as supporting perfect forward secrecy.



Google LB 也是一样,使用 GFE 作为面相用户的前端,将 SSL 流量在 GFE 上终结,然后以 HTTP 的方式回到后端的 Service 上。

使用一个统一的入口好处有很多,比如 GCP 就提供了一个统一的位置修改 SSL Policy:
 

 
可以自己选择心水的 Cipher Suite 和最低 TLS 版本等,和 Cloudflare 差不多(但是要让 Ucloud LB 做到这一点似乎就太困难了,他们基于 HAProxy 搞的 ULB 到本文发布时还不支持 TLS 1.3,而且要改 Cipher Suite 需要提工单)。

Premium IP

GCP 上的 IP 分为两种,一种是 Premium ,一种是 Standard,默认是前者,Google LB 也只能用 Premium。

Premium 使用的是冷土豆路由,所发送的数据包会保持在 Google 的内网内,并且在尽可能靠近用户的 PoP 离开。
 

 
 
 
 
589
views

新西兰电商网站开发公司|我们的后端工程师David总结的独立电商购物网站整合支付接口的经验,如何让大陆的买家在你的网站上通过微信支付和支付宝付款

Marketplacefull stack developer Kevin wrote the post • 0 comments • 589 views • 2020-04-05 12:56 • added this tag no more than 24h

大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,有机会接触到 Stripe 的工作流程,事情很简单,对于优秀的服务,我们应该付出使用他们的成本(这样他们可以继续提供优质的服务),对于商户来说收钱就是一个比较有意思的部分了,鉴于大多数网友都是付钱,本文决定分享一下 Stripe 整合支付宝来收钱的方法,且本文不是网上很多出现的那种引用 checkout.js 的过期的方法(许多人都互相转来转去,看了一圈下来都是这个),而是使用 Stripe.js 来完成。
 

Stripe 目前收款方式有两种,简单来说,我们分为 Easy 难度和 Hard 难度,前者只支持信用卡,储蓄卡和 Apple Pay,而后者则支持多种支付方式,最终的效果图如下:


Easy 模式——使用 「Checkout」
Easy 模式即使用他们写好的页面,被称为「Checkout」,对于商户来说需要在后台定义好产品(Products),生成 sku 后写一个按钮出发脚本自动跳转过去,页面上需要写的内容如下:<!-- Load Stripe.js on your website. -->
<script src="https://js.stripe.com/v3"></script>
<!-- Create a button that your customers click to complete their purchase. Customize the styling to suit your branding. -->
<button
style="background-color:#6772E5;color:#FFF;padding:8px 12px;border:0;border-radius:4px;font-size:1em"
id="checkout-button-sku_xxxxxxxxxxx"
role="link"
>
Checkout
</button>
<div id="error-message"></div>
<script>
(function() {
var stripe = Stripe('pk_test_xxxxxxxxxxxx');
var checkoutButton = document.getElementById('checkout-button-sku_G40GQYkIX4a8c4');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
stripe.redirectToCheckout({
items: [{sku: 'sku_xxxxxxxxxxx', quantity: 1}],
// Do not rely on the redirect to the successUrl for fulfilling
// purchases, customers may not always reach the success_url after
// a successful payment.
// Instead use one of the strategies described in
// https://stripe.com/docs/paymen ... lment
successUrl: 'https://xxx.xxx.xx/success',
cancelUrl: 'https://xxx.xxx.xx/canceled',
})
.then(function (result) {
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer.
var displayError = document.getElementById('error-message');
displayError.textContent = result.error.message;
}
});
});
})();
</script>

这样在用户点了按钮之后就会出现一个 Stripe 的支付页面:


这样就可以用了,用户在付款完成之后就会跳转回到 successUrl,同时 Stripe 可以给你预先定义好的接口(WebHook)发一个 POST 请求告知,大致逻辑如下(其实官方有示范):\Stripe\Stripe::setApiKey('sk_test_xxxxxxxxxxxxxx');

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = 'whsec_xxxxxxxxxxxxxxx';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}

// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
// 授权用户
$target_customer = \Stripe\Customer::retrieve($session['customer']);
$target_email = $target_customer['email'];
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}


这样就可以获取到用户的信息并且给用户提供/升级服务了,很方便是不是?
不过呢,「Checkout」只支持卡和 Apple Pay,对于喜欢见到付钱就想扫一扫的用户来说并不友好,所以我们需要使用一些别的方法。
Hard 模式——使用「STRIPE ELEMENTS」
为了照顾没有信用卡,遇见码就开始掏手机准备打开或绿或蓝应用准备开始扫一扫的用户来说,我们需要加入支付宝的支持功能。
首先确认你的账户中 Alipay 是连接上并且处于激活状态的,没有这一点等于没戏(也就不用继续往下看了)。


如果你的 Stripe 已经连接上了支付宝,接下来我们就可以开始整合了。
首先我们明白一下对于商户来说,逻辑是怎么样的:


首先由于 Stripe 并不是原生支持支付宝,所以所有这种非信用卡交易都被挂了称为「Source」的东西下,可以理解为一个插件或者一个临时的钱包,以下一段是具体的逻辑,请仔细阅读:
当用户需要付款的时候,用户会先通过 JS 创建一个 「Source」对象,并指定类型为「Alipay」,这个时候 Stripe.js 会带领用户去支付宝的付款页面进行支付,如果付款成功了,那么这个「Source」的状态会从 charge.pending 变成 source.chargeable ,可以理解为用户给临时钱包付了钱,在有了这个状态之后我们可以调用 Stripe 对这个 Source 扣款(Charge),把临时钱包的钱扣到自己 Stripe 账户上,然后就完成了付款的过程。
用户逻辑
我们先来看用户的逻辑部分:
用户的逻辑是,在对应的购买页面上应该有一个 Button,上面写上「立即购买」,这样用户只要一摸那个按钮,就可以看到支付宝的付款页面了,为了满足这个需要,我们需要这么做,在对应的页面上放个 Button:<button id="checkout-button">
立即购买
</button>

然后引用 stripe.js 并写一点 JS 来完成接下来的事情:<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
(function() {
var stripe = Stripe('pk_xxxxxxxxxxxxxx');
var checkout-button = document.getElementById('checkout-button');
checkout-button.addEventListener('click', function () {
stripe.createSource({
type: 'alipay',
amount: 1988,
currency: 'hkd',
// 这里你需要渲染出一些用户的信息,不然后期没法知道是谁在付钱
owner: {
email: '{$user_email}',
},
redirect: {
return_url: 'https://xxx.xxx.xx/buy',
},
}).then(function(result) {
window.location.replace(result.source.redirect.url);
});
});
})();
</script>
其中,owner 和 owner 下的 email 建议填写,不然付款后可能不好找到究竟是哪个用户付了钱,如果正巧你们不用 email 来标识用户,那也可以写点别的,对于 owner 来说有以下字段可供选择:
  "owner": {
"address": null,
"email": "[email protected]",
"name": null,
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": null,
"verified_phone": null
},
此外,如果你还希望在 Source 中包含一些其他的内容的话,可以自由地使用 metadata ,并在内部包含一系列键值对。由于 createSource 执行完成后会返回一个包含 Source 对象,类似如下:{
"id": "src_16xhynE8WzK49JbAs9M21jaR",
"object": "source",
"amount": 1099,
"client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
"created": 1445277809,
"currency": "usd",
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": "null",
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": "null",
"verified_phone": null
},
"redirect": {
"return_url": "https://shop.example.com/crtA6B28E1",
"status": "pending",
"url": "https://hooks.stripe.com/redir ... ot%3B
},
"statement_descriptor": null,
"status": "pending",
"type": "alipay",
"usage": "single_use",
"alipay": {
"statement_descriptor": null,
"native_url": null
}
}
其中的 redirect 只要访问了就会自动被 Stripe 跳转到支付宝家的支付页面上,所以我们最后会有一行:
window.location.replace(result.source.redirect.url);
将用户跳转过去,然后用户扫码付钱:


用户这边的事情就结束了。
服务器逻辑
用户的事情结束了,服务器端就需要开始处理用户的请求了,一个简单的方法如下,在用户付款完成后 Stripe 会跳转回我们 JS 中定义的 return_url 并附带一些参数,类似如下:https://xxx.xxx.xx/buy?client_secret=src_client_secret_xxxxxxxxx&source=src_xxxxxxxxx

这个时候我们可以通过服务端来解析 src_xxxxxxxxx 得知是谁在付钱,并完成后续的操作:\Stripe\Stripe::setApiKey('sk_xxxxxxxxxxxxxx');

// 获取 URL 中 source 字段
$source_id = filter_input(INPUT_GET, 'source', FILTER_SANITIZE_URL);
$source_object = \Stripe\Source::retrieve($source_id);

// 先确认一下用户付了钱,别有 Object 就直接开始整...
$status = $source_object->redirect->status;
if($status == "failed")
{
// 如果用户没有付钱,我们该怎么做?
}
else {
// 从临时钱包从把钱扣了~
\Stripe\Charge::create([
'amount' => 1988,
'currency' => 'hkd',
'source' => $source_id,
]);
// 有了 Object 之后我们可以提取出对应的用户邮件地址或者别的信息,比如邮件地址可以这样提取
$user_email = $source_object->owner->email;
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}
顺便可以登录 Stripe 后台看看~


微信实现

其实也非常的简单,只需要将上一步的type改为wechat,同时返回source中的source.wechat.qr_code_url转为二维码就好了
 
var wechatCallback = function (source) {
generateQRCode(source.wechat.qr_code_url);
}
function generateQRCode(value) {
var qrEle = document.getElementById("qrcode");
var qrcode = new QRCode(qrEle, {
width: 100,
height: 100
});
qrcode.makeCode(value);
qrEle.style.display = 'inline-block';
}二维码出来后, 扫码就会得到如下结果
 

 
不过这种方法只是说可以用而已,最好的方法可以参考 Best Practices for Using Sources 来接受 Webhook 多次验证,但这个就不在本文的范围内了。

由于是第一次接触支付领域,上述步骤中可能还是会有不少坑或者啥的(所以别直接在生产环境照抄,写完之后一定要多 Review 几遍逻辑漏洞),不过这个至少是一个可用最小模型了,还有不少可以改进的地方,比如浏览器端的函数其实可以异步拉起,这样可以在网页上弄一个 Modal 弹窗,看上去更加用户友好一些。
 
 
补充说明(04/06/2020):
 
关于注册 Stripe 账号

和注册支付宝账号一个道理,首先注册账号,然后绑定自己银行卡,BUT, 就像前面提到的,不支持中国,所以就算注册成功,也没法激活,也就没法收款。

 
 
 
对于中国商家怎么办呢,我能想到的就只有这3个办法:

自己去支持国家去办理张银行卡
使用国外的朋友银行卡
使用Atlas

对于James来说,因为他是新西兰kiwi,所以他可以创建他的主账号,然后添加我的stripe账号到他team memeber账号列表中,这样我就可以访问他账户下所有开发者需要的权限。邀请成功后,Dashboard页面

 

 
Stripe.js & Elements

当然对于如果你觉得Checkout的方式集成度太高,不够灵活,那Stripe.js是你最好的选择。

Stripe.js其实就是客户端的一个JS核心类库,Elements是它的UI类库,其实上面的Checkout代码就是Stripe使用两者给我们封装好了的,避免我们直接接触敏感信息,但是其实质都是一样的,都是用来创建source。这里就直接贴出客户端的代码了(这里没有用到Elements做UI,因为就是一个按钮支付,太简单,所以没用到):var stripe = Stripe('pk_live_xxxx');

function alipay(amount) {
showLoading();
stripe.createSource({
type: 'alipay',
amount: parseInt(amount),
currency: 'gbp', // usd, eur,
redirect: {
return_url: 'https://xxx.eu/pay/result.html'
},
}).then(function (response) {
hideLoading();
if (response.error) {
alert(response.error.message);
}
else {
processStripeResponse(response.source);
}
});
}

function processStripeResponse(source) {
window.location.href = source.redirect.url;
}





  view all
大家好,我是新西兰软件开发公司local fern的程序员David,最近因工作需要,有机会接触到 Stripe 的工作流程,事情很简单,对于优秀的服务,我们应该付出使用他们的成本(这样他们可以继续提供优质的服务),对于商户来说收钱就是一个比较有意思的部分了,鉴于大多数网友都是付钱,本文决定分享一下 Stripe 整合支付宝来收钱的方法,且本文不是网上很多出现的那种引用 checkout.js 的过期的方法(许多人都互相转来转去,看了一圈下来都是这个),而是使用 Stripe.js 来完成。
 

Stripe 目前收款方式有两种,简单来说,我们分为 Easy 难度和 Hard 难度,前者只支持信用卡,储蓄卡和 Apple Pay,而后者则支持多种支付方式,最终的效果图如下:


Easy 模式——使用 「Checkout」
Easy 模式即使用他们写好的页面,被称为「Checkout」,对于商户来说需要在后台定义好产品(Products),生成 sku 后写一个按钮出发脚本自动跳转过去,页面上需要写的内容如下:
<!-- Load Stripe.js on your website. -->
<script src="https://js.stripe.com/v3"></script>
<!-- Create a button that your customers click to complete their purchase. Customize the styling to suit your branding. -->
<button
style="background-color:#6772E5;color:#FFF;padding:8px 12px;border:0;border-radius:4px;font-size:1em"
id="checkout-button-sku_xxxxxxxxxxx"
role="link"
>
Checkout
</button>
<div id="error-message"></div>
<script>
(function() {
var stripe = Stripe('pk_test_xxxxxxxxxxxx');
var checkoutButton = document.getElementById('checkout-button-sku_G40GQYkIX4a8c4');
checkoutButton.addEventListener('click', function () {
// When the customer clicks on the button, redirect
// them to Checkout.
stripe.redirectToCheckout({
items: [{sku: 'sku_xxxxxxxxxxx', quantity: 1}],
// Do not rely on the redirect to the successUrl for fulfilling
// purchases, customers may not always reach the success_url after
// a successful payment.
// Instead use one of the strategies described in
// https://stripe.com/docs/paymen ... lment
successUrl: 'https://xxx.xxx.xx/success',
cancelUrl: 'https://xxx.xxx.xx/canceled',
})
.then(function (result) {
if (result.error) {
// If `redirectToCheckout` fails due to a browser or network
// error, display the localized error message to your customer.
var displayError = document.getElementById('error-message');
displayError.textContent = result.error.message;
}
});
});
})();
</script>


这样在用户点了按钮之后就会出现一个 Stripe 的支付页面:


这样就可以用了,用户在付款完成之后就会跳转回到 successUrl,同时 Stripe 可以给你预先定义好的接口(WebHook)发一个 POST 请求告知,大致逻辑如下(其实官方有示范):
\Stripe\Stripe::setApiKey('sk_test_xxxxxxxxxxxxxx');

// You can find your endpoint's secret in your webhook settings
$endpoint_secret = 'whsec_xxxxxxxxxxxxxxx';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
$event = \Stripe\Webhook::constructEvent(
$payload, $sig_header, $endpoint_secret
);
} catch(\UnexpectedValueException $e) {
// Invalid payload
http_response_code(400);
exit();
} catch(\Stripe\Exception\SignatureVerificationException $e) {
// Invalid signature
http_response_code(400);
exit();
}

// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
$session = $event->data->object;
// 授权用户
$target_customer = \Stripe\Customer::retrieve($session['customer']);
$target_email = $target_customer['email'];
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}



这样就可以获取到用户的信息并且给用户提供/升级服务了,很方便是不是?
不过呢,「Checkout」只支持卡和 Apple Pay,对于喜欢见到付钱就想扫一扫的用户来说并不友好,所以我们需要使用一些别的方法。
Hard 模式——使用「STRIPE ELEMENTS」
为了照顾没有信用卡,遇见码就开始掏手机准备打开或绿或蓝应用准备开始扫一扫的用户来说,我们需要加入支付宝的支持功能。
首先确认你的账户中 Alipay 是连接上并且处于激活状态的,没有这一点等于没戏(也就不用继续往下看了)。


如果你的 Stripe 已经连接上了支付宝,接下来我们就可以开始整合了。
首先我们明白一下对于商户来说,逻辑是怎么样的:


首先由于 Stripe 并不是原生支持支付宝,所以所有这种非信用卡交易都被挂了称为「Source」的东西下,可以理解为一个插件或者一个临时的钱包,以下一段是具体的逻辑,请仔细阅读:
当用户需要付款的时候,用户会先通过 JS 创建一个 「Source」对象,并指定类型为「Alipay」,这个时候 Stripe.js 会带领用户去支付宝的付款页面进行支付,如果付款成功了,那么这个「Source」的状态会从 charge.pending 变成 source.chargeable ,可以理解为用户给临时钱包付了钱,在有了这个状态之后我们可以调用 Stripe 对这个 Source 扣款(Charge),把临时钱包的钱扣到自己 Stripe 账户上,然后就完成了付款的过程。
用户逻辑
我们先来看用户的逻辑部分:
用户的逻辑是,在对应的购买页面上应该有一个 Button,上面写上「立即购买」,这样用户只要一摸那个按钮,就可以看到支付宝的付款页面了,为了满足这个需要,我们需要这么做,在对应的页面上放个 Button:
<button id="checkout-button">
立即购买
</button>


然后引用 stripe.js 并写一点 JS 来完成接下来的事情:
<script src="https://js.stripe.com/v3/"></script>
<script type="text/javascript">
(function() {
var stripe = Stripe('pk_xxxxxxxxxxxxxx');
var checkout-button = document.getElementById('checkout-button');
checkout-button.addEventListener('click', function () {
stripe.createSource({
type: 'alipay',
amount: 1988,
currency: 'hkd',
// 这里你需要渲染出一些用户的信息,不然后期没法知道是谁在付钱
owner: {
email: '{$user_email}',
},
redirect: {
return_url: 'https://xxx.xxx.xx/buy',
},
}).then(function(result) {
window.location.replace(result.source.redirect.url);
});
});
})();
</script>

其中,owner 和 owner 下的 email 建议填写,不然付款后可能不好找到究竟是哪个用户付了钱,如果正巧你们不用 email 来标识用户,那也可以写点别的,对于 owner 来说有以下字段可供选择:
  
"owner": {
"address": null,
"email": "[email protected]",
"name": null,
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": null,
"verified_phone": null
},

此外,如果你还希望在 Source 中包含一些其他的内容的话,可以自由地使用 metadata ,并在内部包含一系列键值对。由于 createSource 执行完成后会返回一个包含 Source 对象,类似如下:
{
"id": "src_16xhynE8WzK49JbAs9M21jaR",
"object": "source",
"amount": 1099,
"client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU",
"created": 1445277809,
"currency": "usd",
"flow": "redirect",
"livemode": true,
"owner": {
"address": null,
"email": null,
"name": "null",
"phone": null,
"verified_address": null,
"verified_email": null,
"verified_name": "null",
"verified_phone": null
},
"redirect": {
"return_url": "https://shop.example.com/crtA6B28E1",
"status": "pending",
"url": "https://hooks.stripe.com/redir ... ot%3B
},
"statement_descriptor": null,
"status": "pending",
"type": "alipay",
"usage": "single_use",
"alipay": {
"statement_descriptor": null,
"native_url": null
}
}

其中的 redirect 只要访问了就会自动被 Stripe 跳转到支付宝家的支付页面上,所以我们最后会有一行:
window.location.replace(result.source.redirect.url);
将用户跳转过去,然后用户扫码付钱:


用户这边的事情就结束了。
服务器逻辑
用户的事情结束了,服务器端就需要开始处理用户的请求了,一个简单的方法如下,在用户付款完成后 Stripe 会跳转回我们 JS 中定义的 return_url 并附带一些参数,类似如下:
https://xxx.xxx.xx/buy?client_secret=src_client_secret_xxxxxxxxx&source=src_xxxxxxxxx


这个时候我们可以通过服务端来解析 src_xxxxxxxxx 得知是谁在付钱,并完成后续的操作:
\Stripe\Stripe::setApiKey('sk_xxxxxxxxxxxxxx');

// 获取 URL 中 source 字段
$source_id = filter_input(INPUT_GET, 'source', FILTER_SANITIZE_URL);
$source_object = \Stripe\Source::retrieve($source_id);

// 先确认一下用户付了钱,别有 Object 就直接开始整...
$status = $source_object->redirect->status;
if($status == "failed")
{
// 如果用户没有付钱,我们该怎么做?
}
else {
// 从临时钱包从把钱扣了~
\Stripe\Charge::create([
'amount' => 1988,
'currency' => 'hkd',
'source' => $source_id,
]);
// 有了 Object 之后我们可以提取出对应的用户邮件地址或者别的信息,比如邮件地址可以这样提取
$user_email = $source_object->owner->email;
// 然后这里自己根据 email 找到对应用户完成接下来的步骤,比如把文件通过邮件发给用户,给用户头像加个 Buff 啥的~
}

顺便可以登录 Stripe 后台看看~


微信实现

其实也非常的简单,只需要将上一步的type改为wechat,同时返回source中的source.wechat.qr_code_url转为二维码就好了
 

var wechatCallback = function (source) {
generateQRCode(source.wechat.qr_code_url);
}
function generateQRCode(value) {
var qrEle = document.getElementById("qrcode");
var qrcode = new QRCode(qrEle, {
width: 100,
height: 100
});
qrcode.makeCode(value);
qrEle.style.display = 'inline-block';
}
二维码出来后, 扫码就会得到如下结果
 

 
不过这种方法只是说可以用而已,最好的方法可以参考 Best Practices for Using Sources 来接受 Webhook 多次验证,但这个就不在本文的范围内了。

由于是第一次接触支付领域,上述步骤中可能还是会有不少坑或者啥的(所以别直接在生产环境照抄,写完之后一定要多 Review 几遍逻辑漏洞),不过这个至少是一个可用最小模型了,还有不少可以改进的地方,比如浏览器端的函数其实可以异步拉起,这样可以在网页上弄一个 Modal 弹窗,看上去更加用户友好一些。
 
 
补充说明(04/06/2020):
 
关于注册 Stripe 账号

和注册支付宝账号一个道理,首先注册账号,然后绑定自己银行卡,BUT, 就像前面提到的,不支持中国,所以就算注册成功,也没法激活,也就没法收款。

 
 
 
对于中国商家怎么办呢,我能想到的就只有这3个办法:

自己去支持国家去办理张银行卡
使用国外的朋友银行卡
使用Atlas

对于James来说,因为他是新西兰kiwi,所以他可以创建他的主账号,然后添加我的stripe账号到他team memeber账号列表中,这样我就可以访问他账户下所有开发者需要的权限。邀请成功后,Dashboard页面

 

 
Stripe.js & Elements

当然对于如果你觉得Checkout的方式集成度太高,不够灵活,那Stripe.js是你最好的选择。

Stripe.js其实就是客户端的一个JS核心类库,Elements是它的UI类库,其实上面的Checkout代码就是Stripe使用两者给我们封装好了的,避免我们直接接触敏感信息,但是其实质都是一样的,都是用来创建source。这里就直接贴出客户端的代码了(这里没有用到Elements做UI,因为就是一个按钮支付,太简单,所以没用到):
var stripe = Stripe('pk_live_xxxx');

function alipay(amount) {
showLoading();
stripe.createSource({
type: 'alipay',
amount: parseInt(amount),
currency: 'gbp', // usd, eur,
redirect: {
return_url: 'https://xxx.eu/pay/result.html'
},
}).then(function (response) {
hideLoading();
if (response.error) {
alert(response.error.message);
}
else {
processStripeResponse(response.source);
}
});
}

function processStripeResponse(source) {
window.location.href = source.redirect.url;
}





 
540
views

新西兰网站开发公司|我们的ios开发工程师Mia分享如何学习设计?如何提升自己对物体深层次的理解。

Othersfull stack developer Kevin wrote the post • 0 comments • 540 views • 2020-04-05 03:25 • added this tag no more than 24h

关于我

刚入坑移动端开发的时候,大部分精力都放在了App功能的技术实现度上,对App相关的设计其实没有过多的关注,因为首先你必须实现了功能,才有精力去研究设计、打磨细节。

高中的时候学过一段时间美术,传统的美术老三样素描、速写、水粉,有一些绘画基础,大学并不是设计相关专业,但选修课学习了一些和设计相关的软件,比如:3DMax、CAD、Dreamweaver、Flash。大学期间报了一个班,学习了PS、CorelDRAW,拿了一个平面设计师资格证,然而这个证并没有什么卵用。

时隔这么多年,那些曾经学过的技能也早已忘的一干二净,从去年开始才慢慢的重新拾起来。

关于设计这块,因为我并不是专业的设计师,有些想法可能比较粗浅,这里只是简单的提供一个学习建议,不好的地方还欢迎大家指正。

美术基础
设计师最好有一定的绘画功底,因为它最能直接的表达出你大脑的想法,自我头脑风暴输出、与他人进行设计沟通,这些都是绘画能给你带来的,当你无法通过你的手来表现出你想法的时候,你会非常痛苦。



其实画画真的没你想象的那么难,很多艺考美术生考试前集训3-4个月也能考上一个艺术院校,所以,建议每天抽出那么一点时间去做绘画功底的积累,不仅有助于你的设计,更能提高审美,一举两得的事何乐而不为。在这里推荐一本我也在跟着画过的一本书《30天学会绘画》,这本书适合没有美术基础的小伙伴,为了练习入手了一个数位板,刚开始特别不习惯,配合PS电脑上比较难控制。现在很多画画的内容都在一个手绘本上完成,不依赖电脑,更能随心所欲利用碎片时间来练习,初学者建议先在本子上绘画。



学习绘画的目的是通过动手实践去锻炼我们的思考能力,刚开始画的不好没关系,重点是带着思考去不断的练习,每一次实践都应该让你感受到自己对物体深层次的理解。



绘画不仅可以帮助你建立原型设计草图的能力,更能增进你界面的排版和配色能力。

当然很多并没有很强的绘画能力,却也是远近闻名的设计大师,比如:山本耀司、可可·加布里埃·夏奈尔,我想说的是绘画仅是一种设计思考表现手段和工具,要看什么设计,对绘画依赖比较严重。



关于软件
提到设计相关的软件,最基础的还是PS,不是有句话,学好PS走遍天下都不怕,可见它的强大之处,哈哈~,说到PS那你一定知道Sketch,扁平化设计的流行和屏幕分辨率的提升推动了Sketch这款软件的流行,它可以帮你快速完成移动端界面的设计工作,除此之外还可以熟悉一下AI,AI可以更方便快捷的绘制矢量图形,配合PS使用很棒。熟练掌握PS、AI之后,可以再进阶学习AE、C4D等动效和3D制作工具,丰富我们的设计成果。



理论基础
设计中的理论基础包括:字体、色彩、排版等很多方面,需要我们自己去多看多学多研究,推荐两本烂大街的书《写给大家看的设计书》、《文字设计的原理》。除此之外还有很多设计师聚集的网站,比如:Dribbble、Behance、优设网、站酷网、UI中国等等。



说了这么多,自认为设计师除了要多练习,更要勤看书,好的设计师应该大部分都是书虫吧。

最后
推荐一篇干货满满的临摹文章以及我收集的一些设计相关的网站和工具

关于临摹的四个阶段

设计/摄影/图站
创造狮导航
Dribbble
Behance
站酷
设计师网址
牛大拿
UI中国
字由
MyFont
千库网
摄图网
图虫网
图片压缩
包图网
花瓣
UIgradients
优优教程网
阿里巴巴图标库
EASYICON图标库
Noun图标库
TOICON图标库
WORLDVECTOR
FreeDownloads
ICONFINDER
ICONS8
UEDC
网易用户体验中心
阿里巴巴UED
阿里巴巴中国站
淘宝前端FED
腾讯CDC
新浪UED
百度UXC
原型工具

墨刀
Axure
Sketch
Mockplus
XIAOPIN

最后
 
按照我们老板的给我派发的kpi,如果你准备开发一个ios 的app,请到我们的在线商店直接购买,我们公司支持kiwikiwifly这个平台的担保交易。 view all
关于我

刚入坑移动端开发的时候,大部分精力都放在了App功能的技术实现度上,对App相关的设计其实没有过多的关注,因为首先你必须实现了功能,才有精力去研究设计、打磨细节。

高中的时候学过一段时间美术,传统的美术老三样素描、速写、水粉,有一些绘画基础,大学并不是设计相关专业,但选修课学习了一些和设计相关的软件,比如:3DMax、CAD、Dreamweaver、Flash。大学期间报了一个班,学习了PS、CorelDRAW,拿了一个平面设计师资格证,然而这个证并没有什么卵用。

时隔这么多年,那些曾经学过的技能也早已忘的一干二净,从去年开始才慢慢的重新拾起来。

关于设计这块,因为我并不是专业的设计师,有些想法可能比较粗浅,这里只是简单的提供一个学习建议,不好的地方还欢迎大家指正。

美术基础
设计师最好有一定的绘画功底,因为它最能直接的表达出你大脑的想法,自我头脑风暴输出、与他人进行设计沟通,这些都是绘画能给你带来的,当你无法通过你的手来表现出你想法的时候,你会非常痛苦。



其实画画真的没你想象的那么难,很多艺考美术生考试前集训3-4个月也能考上一个艺术院校,所以,建议每天抽出那么一点时间去做绘画功底的积累,不仅有助于你的设计,更能提高审美,一举两得的事何乐而不为。在这里推荐一本我也在跟着画过的一本书《30天学会绘画》,这本书适合没有美术基础的小伙伴,为了练习入手了一个数位板,刚开始特别不习惯,配合PS电脑上比较难控制。现在很多画画的内容都在一个手绘本上完成,不依赖电脑,更能随心所欲利用碎片时间来练习,初学者建议先在本子上绘画。



学习绘画的目的是通过动手实践去锻炼我们的思考能力,刚开始画的不好没关系,重点是带着思考去不断的练习,每一次实践都应该让你感受到自己对物体深层次的理解。



绘画不仅可以帮助你建立原型设计草图的能力,更能增进你界面的排版和配色能力。

当然很多并没有很强的绘画能力,却也是远近闻名的设计大师,比如:山本耀司、可可·加布里埃·夏奈尔,我想说的是绘画仅是一种设计思考表现手段和工具,要看什么设计,对绘画依赖比较严重。



关于软件
提到设计相关的软件,最基础的还是PS,不是有句话,学好PS走遍天下都不怕,可见它的强大之处,哈哈~,说到PS那你一定知道Sketch,扁平化设计的流行和屏幕分辨率的提升推动了Sketch这款软件的流行,它可以帮你快速完成移动端界面的设计工作,除此之外还可以熟悉一下AI,AI可以更方便快捷的绘制矢量图形,配合PS使用很棒。熟练掌握PS、AI之后,可以再进阶学习AE、C4D等动效和3D制作工具,丰富我们的设计成果。



理论基础
设计中的理论基础包括:字体、色彩、排版等很多方面,需要我们自己去多看多学多研究,推荐两本烂大街的书《写给大家看的设计书》、《文字设计的原理》。除此之外还有很多设计师聚集的网站,比如:Dribbble、Behance、优设网、站酷网、UI中国等等。



说了这么多,自认为设计师除了要多练习,更要勤看书,好的设计师应该大部分都是书虫吧。

最后
推荐一篇干货满满的临摹文章以及我收集的一些设计相关的网站和工具

关于临摹的四个阶段

设计/摄影/图站
创造狮导航
Dribbble
Behance
站酷
设计师网址
牛大拿
UI中国
字由
MyFont
千库网
摄图网
图虫网
图片压缩
包图网
花瓣
UIgradients
优优教程网
阿里巴巴图标库
EASYICON图标库
Noun图标库
TOICON图标库
WORLDVECTOR
FreeDownloads
ICONFINDER
ICONS8
UEDC
网易用户体验中心
阿里巴巴UED
阿里巴巴中国站
淘宝前端FED
腾讯CDC
新浪UED
百度UXC
原型工具

墨刀
Axure
Sketch
Mockplus
XIAOPIN

最后
 
按照我们老板的给我派发的kpi,如果你准备开发一个ios 的app,请到我们的在线商店直接购买,我们公司支持kiwikiwifly这个平台的担保交易。