Kay
2023/05/11阅读:42主题:默认主题
Shopify App
背景
Shopify
是一家加拿大的科技公司,旨在帮助企业或个人快速建立在线商店.2021
年第四季度,一度成为了全球第三大电子商务平台.在国外也是构建电商独立站的首选.
优势
-
易用性
Shopify
平台提供了丰富的主题模板,商家可以通过简单的拖放操作,轻松地创建和定制网站页面,而无需编写代码. -
可靠性
Shopify
平台具有强大的基础架构和安全性措施,包括24x7监控、备份和灾难恢复等功能,以确保商家的数据始终安全. -
扩展性
Shopify App Store
提供了海量的应用程序,覆盖了各种功能领域,例如市场营销、物流、客户支持等。商家可以根据自己的需求,选择并使用这些应用程序和插件,以满足不同的业务需求.
Shopify app

图中展现的是一款商品评论插件,如果商家想在自己的商品详情页添加一个用户评论功能,只需要Shopify
应用商店点一下安装按钮,就能立马在自己的商城里应用这个功能.
插件不只是提供了一个漂亮的UI
界面,而是一个终极的产品形态.在插件内,包含了前端的UI
交互、后端的逻辑运算、数据库的存储、运维等等一整套服务.
对于商户而言,他不需要懂任何代码,只需要一件安装,就能快速享受到这一整套服务带来的好处.
对于开发者而言,他只需要将自身业务中一些优秀的组件抽离出来,放在Shopify
应用商店上出售,就能实现技术变现.
整体的流程:

从上面的流程可以看出,App
需要对两方提供服务.
-
App
需要开发C端用户使用的产品功能 -
App
需要开发商对产品的管理功能
以上图描述的评论插件举例,页面上展示所有评论的UI和功能都属于c
端的功能.
同时商户需要一个地方去管理这些用户评论,比如某些不良评论需要屏蔽,这就是后台管理系统做产品支撑.
因此开发一款App
的任务划分成两部份:
-
c
端功能的开发 -
后台管理系统的开发
C端应用
通过执行下面cli
命令下载C端应用的模版代码,然后使用html
、css
和js
开发应用功能.
npm run shopify app generate extension
后台管理系统
插件的后台管理系统集成在了Shopify
后台,一旦插件部署上线,就可以在Shopify
后台直接访问插件的后台管理系统(外观如下).

后台管理系统通过执行下面cli
命令生成模版配置.
npm init @shopify/app@latest
后台管理系统的前端功能通过react
框架和Polaris
组件库开发,在与Shopify
后台进行交互的过程中使用了GraphQL Admin API
.
传统的前后端交互采用的都是REST API
,后端定义各式各样的接口,前端按照接口的规范来请求接口获取数据.此时如果某个接口缺少一个字段,就需要后端程序员在代码中手动加上.
而GraphQL
允许客户端指定希望从服务器获取哪些数据,并以预期的格式返回.此时后端只需要定义一个接口,就能满足前端的所有查询要求,极大的简化了双方的工作量.
例如下面案例中使用GraphQL
语法查询产品表中前3
条产品数据,并且产品数据只需要返回id
和title
属性.
const queryString = `{
products (first: 3) {
edges {
node {
id
title
}
}
}
}`;
const client = new shopify.clients.Graphql({session});
const products = await client.query({
data: queryString,
});
一个GraphQL
查询是一个被发往服务端的字符串,该字符串在服务端被解释和执行后返回JSON
数据给客户端.
服务端需要解析GraphQL
字符串,将其转化成AST
语法树才能执行,因此它会以牺牲服务器的性能作为代价.
关联查询
{
user(id: "1") {
name
orders(first: 3) {
edges {
cursor
node {
id
amount
status
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
前言
Shopify Functions
顾名思义它是一个函数.只要是函数,它都会包含三个基本要素.
-
输入: 给函数传递的参数 -
函数体: 函数的计算逻辑 -
输出: 函数返回的结果
Shopify Functions
不是普通函数,更像是一种定义在云端
的函数.
它和Serverless
架构中下的云函数是不太一样的,我们一般谈论Serverless
架构中的事件驱动计算服务,都是在云端环境上部署一些计算服务.
编写这类服务时可以让开发者无需关心服务器、操作系统等底层架构,全部精力集中在业务层开发.它可以响应特定的触发器(例如 HTTP 请求、消息队列、文件上传等)
Shopify Functions
这种函数它是不能通过手动方式去触发的,它会在User Journey
的旅途中由Shopify
控制触发它.

例如上图一个购物车页面,如果我们在插件中实现了一个Shopify Functions
,当用户点击这个checkout
按钮时,触发表单提交,Shopify
服务器接受表单的请求.
此时Shopify
服务器如何检测到商店安装了Shopify Functions
,它就会去执行Shopify Functions
.
输入就是购物车里面的商品数据,函数体开发者可以自由定义.比如实现一个梯度折扣的功能,遍历购物车内的商品数量,最后按照折扣返回商品结果.
Delivery Customization API | 商家可以创建自定义送货选项.比如修改快递的描述、针对某款商品隐藏某些快递方式. |
Order Discount API | 创建一种类型折扣应用于购物车中整个订单商品 |
Product Discount API | 创建一种类型折扣应用于购物车中特定的产品或者变体 |
Payment Customization API | 允许商家通过API管理支付方式.例如针对某些国家或者用户隐藏某类支付方式 |
实现
-
创建项目
npm run shopify app generate extension -- --type product_discounts --name=product-discount
-
编写 input.graphql
//input.graphql
query Input {
cart {
lines {
quantity
merchandise {
__typename
...on ProductVariant {
id
}
}
}
}
discountNode {
metafield(namespace: "$app:volume-discount", key: "function-configuration") {
value
}
}
}
-
编写函数
import { DiscountApplicationStrategy } from "../generated/api";
/**
* @type {FunctionResult}
*/
const EMPTY_DISCOUNT = {
discountApplicationStrategy: DiscountApplicationStrategy.First,
discounts: [],
};
export default (input) => {
const configuration = JSON.parse(
input?.discountNode?.metafield?.value ?? "{}"
);
if (!configuration.quantity || !configuration.percentage) {
return EMPTY_DISCOUNT;
}
const targets = input.cart.lines
.filter(line => line.quantity >= configuration.quantity &&
line.merchandise.__typename == "ProductVariant")
.map(line => {
const variant = /** @type {ProductVariant} */ (line.merchandise);
return /** @type {Target} */ ({
productVariant: {
id: variant.id
}
});
});
if (!targets.length) {
console.error("No cart lines qualify for volume discount.");
return EMPTY_DISCOUNT;
}
return {
discounts: [
{
targets,
value: {
percentage: {
value: configuration.percentage.toString()
}
}
}
],
discountApplicationStrategy: DiscountApplicationStrategy.First
};
};
-
部署
cd ../.. && npm run deploy
Value
IDN折扣功能实现
Checkout UI extension
why
Checkout
顾名思义就是下单,它承担了电商体系下最核心的支付任务.
Shopify
在国外这么流行,除了低代码建站,扩展性强,多渠道销售这些优势以外,安全性强是不容忽视的重要特征.
Shopify
之前为了保证电商支付的安全性,一直采用非常保守的策略.
在以前,整个Checkout
功能都是以黑盒的形式包装了起来,开发者只能通过链接或者form
表单的形式跳转到Shopify
提供的支付网关,而接下来的所有用户行为都直接被Shopify
接管.
Shopify
将Checkout
用黑盒的形式进行封装,一方面确实保证了支付的安全性,但另一方面也被众多开发者诟病.
开发者希望Shopify
能在Checkout
环节开放出更多的权限和接口,而这些开放的功能能打开大家的想象空间,能够在Checkout
环节加入自定义个性化的功能设计,从而推动商品的营销.
开放虽然能促进多样性的发展,但同时也将安全性暴露在大众面前.Shopify
历经了多年的打磨,在保证开放性和安全性共存的前提下,于2022年万众期待下高调的推出了Checkout UI extension
.
WHAT
Checkout UI extension
主要解决什么什么问题呢?
以前Shopify
出于安全考虑,没有将Checkout
开放出来给开发者使用.
如今如果有人想在Checkout
环节开发个性化的功能,那么你可以依据Checkout UI extension
的文档规范,以app
的形式开发自定义功能并最终发布到应用商店.
最终商家通过安装app
,就能在自己电商的Checkout
加入自定义功能.
HOW
Checkout UI extension
给了开发者能自定义功能的自由,但这个自由存在界限.
Checkout UI extension
并没有将Checkout
的源代码暴露出来,而是提供了一个个 Extension points
.
Extension points
类似于页面上的一个个插槽,而app
开发的这些功能就能插入到这些插槽当中.

从上图中可以看出,Extension points
用两种颜色标明.一类是蓝色,蓝色是Static extension points
.而另一类是红色,红色是Dynamic extension points
;
那怎么样去理解静态和动态区别呢?
静态扩展点是指Shopify
在设计API
时提前定义好的扩展点,这些扩展点可以被使用者自由添加或更改。使用静态扩展点的开发者可以在这些点上创建定制化的功能.
静态扩展点的位置是定死的,触发条件也是定死的,它会和具体的下单特征进行绑定.
动态扩展点的位置是活的,触发条件也是活的,它不会和具体的下单特征进行绑定.
代码实现
-
创建扩展
npm run shopify app generate extension -- --type checkout_ui --name=my-checkout-ui-extension
-
注册扩展点
// shopify.function.extension.toml
type = "checkout_ui_extension"
name = "my-checkout-ui-extension"
extension_points = [
'Checkout::Dynamic::Render'
]
[capabilities]
api_access = true
-
启动项目
yarn dev
-
进入项目文件夹 src/index.jsx
里面编写插件的逻辑
import React, { useEffect, useState } from "react";
import {
render,
Banner
} from "@shopify/checkout-ui-extensions-react";
render("Checkout::Dynamic::Render", () => <App />);
function App() {
const [showError, setShowError] = useState(false);
return (
{showError && (
<Banner status="critical">
There was an issue adding this product. Please try again.
</Banner>
)}
)}
-
部署插件
npm run deploy
Value
优惠券
AU处方
pre-purchase product offers
survey-overview

作者介绍