SHOPLINE Funtcion 支付方式自定义

应用场景

你可以使用 SHOPLINE Functions 来自定义买家结账时使用的支付方式,包括隐藏、重新排序以及重命名支付方式。

前提条件

业务流程

通过 SHOPLINE Functions 实现支付方式自定义的工作流程如下:

  1. 创建并发布支付自定义函数;

  2. 创建好函数自定义规则的创建和详情页面,商家可以在相关页面进行函数自定义规则的创建和修改;

  3. 商家在「SHOPLINE Admin 后台-设置-收款-定制化设置」模块发现并启用该函数,选中函数/具体规则后,跳转到相应页面,设置好函数自定义规则并启用;

  4. 买家访问该店铺的结算页时,将执行函数逻辑,并按函数输出的指令调整结算页支付方式列表;

1. 创建支付自定义函数

在你实现的支付自定义函数中,你的函数的输入,包含两个部分:

  • 当前结账页的信息(包括但不限于:客户、商品、地址、物流、金额等信息);

  • 商家配置的函数自定义规则(假设你的函数逻辑为:结账金额低于{特定值}时,隐藏{某个}支付方式,在运行时你能获取到商家启用函数时配置的具体的规则值);

函数的输出,将用来描述你如何调整结账页的支付方式列表,当前支持以下指令:

  • 隐藏

  • 排序

  • 重命名

具体的字段信息,可通过在 CLI 下载函数模板,获取支付自定义的 input 等相关参数:

接下来,本教程将以创建一个「根据结账金额隐藏支付方式」的函数为例,来为你展示具体要如何创建一个支付自定义函数;
确保你已经处于开发函数环节;

1.1.定义需要的函数输入

请按需定义好的函数需要的输入到 input.graphql

  • 「根据结账金额隐藏特定支付方式」的函数中,只需要结账金额进行规则匹配,所以我们在 input 的结账信息中只声明获取 checkout.cost.totalAmount.amount

  • 我希望给商家相对灵活的函数自定义规则,而商家函数自定义规则是存储在 namespace: "payment-customization", key: "function-configuration"paymentCustomizations.metafield 中,所以需要声明获取;

query Input {  
  checkout {  
    cost {  
      totalAmount {  
        amount  
      }  
    }  
  }  
  paymentCustomizations {  
    metafield(namespace: "payment-customization", key: "function-configuration") {  
      value, type  
    }  
  }  
}

1.2. 编写函数核心逻辑

在函数入口文件 main.goPaymentCustomizationFunction 方法中,编写你的函数逻辑:

func PaymentCustomizationFunction(input *module.PaymentCustomizationFunctionRequest) (output module.PaymentCustomizationFunctionResponse) {  
    // 你可以从 req 中获取 结账信息 和 商家保存的函数自定义规则
    // 以下为举例的伪代码
    // 1. 先从 input 的 checkout 中获取到结账金额 
    totalAmount := getTotalAmountFromInputCheckout(input.checkout)
    // 2. 先从 input 的 paymentCustomizations 中获取商家配置的 函数自定义规则
    thresholdAmount, cmpRule, forPaymentMethodName := parseMerchantRuleFromInputPaymentCustomizations(input.paymentCustomizations)
    // 3. 根据 结账金额 和 函数自定义规则,判断规则是否生效
    ruleMatch := (cmpRule == 'gt' && totalAmount > thresholdAmount) || 
        (cmpRule == 'lt' && totalAmount < thresholdAmount)
    if !ruleMatch {
        return
    }
    
    for _, p := input.paymentMethods {
        if p.Name == forPaymentMethodName {
        // 4. 构造隐藏支付方式的指令,并添加到 result.Operations
            output.Operations = append(output.Operations, Operation{
                Hide: HideOperation{PaymentMethodId: p.Id}
            })
        }
    }
    return  
}

1.3. 配置函数自定义规则页面路由

shopline.function.extension.toml 配置函数自定义规则页面路由,在页面路由中,允许使用:functionId:id这两个占位符:

  • :functionId: 当前 function 的唯一 ID

  • :id:当前函数自定义规则的唯一ID
    需要配置以下页面路由:

  • create:对应函数自定义规则创建页面,商家在创建函数自定义规则时,将跳转到该页面。

  • details:对应函数自定义规则详情页面,商家在访问已存在的函数自定义规则时,将跳转到该页面。

完成的路径拼接规则为:{你的应用地址}{你配置的函数自定义规则页面路由}

举例:

[ui.paths]
create = "/payment-customization/:functionId/new"
details = "/payment-customization/:functionId/:id"

以以上例子为例:
当你的应用地址为 example.partnerdomain/payment/customizationcreate路 径为 /payment-customization/:functionId/new,则商家新增函数自定义规则时,将跳转到:example.partnerdomain/payment/customization/payment-customization/{you-functionId}/new 页面;

1.4. 发布函数

请参考函数发布流程,将你的函数发布到开发商店和应用;

2. 搭建函数自定义规则页面

商家将在创建/查看函数自定义规则时,跳转到你在 shopline.function.extension.toml 配置的 create/details 路由,你需要你的域名的对应路由下,搭建你的「函数自定义规则页面」,用来让商家维护和查看函数自定义规则。
这里将描述在你搭建的函数自定义规则页面,该如何与SHOPLINE交互;
提示: 建议你使用App Bridge为商家打造熟悉且一致的用户体验;

2.1. 新增函数自定义规则页面

以下是一个示例的新增函数自定义规则页面,你可以根据你的实际需求,搭建你的页面;

当商家在你的页面创建函数自定义规则时,你需要调用新增支付自定义接口,将商家的配置函数自定义规则保存到SHOPLINE;
具体的规则需要保存在 metafield_info 字段中,typevalue 可以由你自由定义;最终这些信息会在函数执行时,通过 input.paymentCustomizations 字段传递;

2.2. 函数自定义规则详情页面

以下是一个示例的函数自定义规则详情页面,你可以根据你的实际需求,搭建你的页面;

建议在该页面,支持以下功能:

  • 显示当前函数自定义规则的详细配置,函数自定义规则信息可以通过查询支付自定义获取;

  • 提供当前函数自定义规则的激活/关闭、更新和删除能力;

3. 商家如何使用函数

商家安装 Payment Functions 应用后,能在「设置-收款-定制化设置」模块发现该应用已发布的函数:
设置-收款-定制化设置:

「定制化设置-添加」:
将会展示所有已安装的可选的支付自定义函数;点击任一函数,将会跳转到对应的新增函数自定义规则页面;

「定制化设置-管理」:
点击管理,将进去支付自定义的管理页面;这里将展示当前店铺关联的所有支付自定义函数规则,支持对函数的停用、启用、删除;

点击任一支付自定义函数规则,将会跳转到对应的函数自定义规则详情页面;该页面完全由开发者自行搭建,建议在该页面中支持对自定义函数规则的维护;

4. 在结账页生效

商家配置并激活相应的支付自定义函数规则后,买家将在结账页看到该支付自定义函数处理之后的支付方式列表;

4.1. 支付自定义函数的执行时机

支付自定义函数将会在结账页所有非支付自定义函数逻辑处理完后,进行执行;
支付自定义函数的执行不会阻断结账页的访问,当支付自定义函数执行出错或者超时时,结账页将会正常返回;
不同的函数/规则的执行是完全独立的,某个函数执行的结果,不会影响其他函数执行的输入;所有的函数的输入都是固定的(支付自定义函数执行前的结账信息);

举例:
结算页有一个支付方式 A,你在 F1 函数中,将它重命名为 NEW_A
在另外一个 F2 函数执行环境的 input中,它的名称仍是 A
在最终处理函数执行结果,重新整理支付方式列表时,它才会被重命名为 NEW_A

4.2. Output处理逻辑

结账页将会处理所有支付自定义函数的运行结果,针对不同的operation类型,会有不同的处理方式;
所有的operation类型中,均需要返回PaymentMethodId用来描述当前operation所操作的支付方式;

你可以在 input.paymentMethods 中找到当前结账页将展示的所有支付方式;该结构的 Id 字段,即是operation中需要的PaymentMethodId

4.2.1 HideOperation

HideOperation结构定义如下:

type HideOperation struct {  
    PaymentMethodId *string `json:"paymentMethodId"`  
}

HideOperation用于隐藏特定的支付方式,当函数运行返回了HideOperation时,PaymentMethodId所指向的支付方式将会被隐藏;

4.2.2 RenameOperation

RenameOperation结构定义如下:

type RenameOperation struct {  
    Name            *string `json:"name"`  
    PaymentMethodId *string `json:"paymentMethodId"`  
}

RenameOperation用于重命名特定的支付方式,当函数运行返回了RenameOperation时,会将PaymentMethodId所指向的支付方式名称替换为{Name}

4.2.3 MoveOperation

MoveOperation结构定义如下:

type MoveOperation struct {  
    Index           *int64  `json:"index"`  
    PaymentMethodId *string `json:"paymentMethodId"`  
}

MoveOperation用于将支付方式插入到指定位置,当函数运行返回了MoveOperation时,会将PaymentMethodId所指向的支付方式插入到index={Index}index0 开始)的位置,{Index} 前的支付方式排序不变,{Index} 后的支付方式顺延一位;

例如:
原始排序:A B C D E F
MoveOperation={PaymentMethodId: “E”, Index: 1}
最终排序:A E B C D F

4.2.4 多个支付自定义函数结果的优先级处理

在处理函数直接结果时,如果出现多个 operation 同时操作同一个支付方式,则需要处理不同结果间的优先级:
处理支付方式列表时,output 严格按照支付自定义函数规则更新时间顺序生效处理,对于覆盖式的 operation(例如 renamemove),相当于更新时间越晚的支付自定义函数规则的运行结果优先级越高;

4.3. 最终效果

处理前:


处理后: