创建微信小程序订单的ngnix配置

对于 POST/tuo-fair-backend/wx-mini-trade/create-order 这个接口,需要在tuo-fair-backend的代理拦截中,在
auth_request /tuo-account/authenticates/check;
之后加上这些配置:

auth_request_set $auth_openid $upstream_http_x_wx_openid;
auth_request_set $auth_union $upstream_http_x_wx_unionid;
auth_request_set $auth_session_key $upstream_http_x_wx_session_key;

proxy_set_header X-Wx-Openid $auth_openid;
proxy_set_header X-Wx-Unionid $auth_union;
proxy_set_header X-Wx-Session-Key $auth_session_key;



微信支付证书相关

我们在【商户平台】->【自助服务】中设立了API证书及密钥 专区,包括了商户证书如何升级,申请,下载等问题的解答。下面是商户技术人员可能关心的一些问题。

什么是私钥?什么是证书?

数字签名通常定义了两种运算: 签名和验签。发送者用自己的私钥对消息的哈希值进行签名,接收者用对方的公钥进行验签。因此,在使用数字签名时,需要通信的双方都要事先生成公钥、私钥,并且完成双方的公钥交换。其中,私钥是只能由拥有者使用的不公开密钥,公钥是可以公开的密钥。

由于公钥本身并不含有拥有者的身份信息,使用时无法确认它是真实有效的。所以需要证书认证机构(简称 CA)在核实公钥拥有者的信息后,将公钥拥有者的身份信息(如商户号、公司名称等),公钥、签发者信息、有效期以及扩展信息等进行签名,制作成“证书”。

如何获取API证书?

请参考什么是API证书?如何获取API证书?

什么是商户证书?什么是平台证书?

  • “商户证书”是指由商户申请的,包含商户的商户号、公司名称、公钥信息的证书。
  • ”平台证书”是指由微信支付负责申请的,包含微信支付平台标识、公钥信息的证书。

商户在调用 API 时用自身的私钥签名,微信支付使用商户证书中的公钥来验签。微信支付在响应的报文中使用自身的私钥签名,商户使用平台证书中的公钥来验签。

为什么微信支付APIv3要用第三方CA的证书?

主要是为了符合监管的要求,保证更高的安全级别。《中华人民共和国电子签名法》、《金融电子认证规范》及《非银行支付机构网络支付业务管理办法》中规定 “电子签名需要第三方认证的,由依法设立的电子认证服务提供者提供认证服务。”,所以需使用第三方 CA 来确保数字证书的唯一性、完整性及交易的不可抵赖性。

什么是证书序列号

每个证书都有一个由CA颁发的唯一编号,即证书序列号。

如何查看证书序列号?

登陆商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号。

商户API证书和微信支付平台证书均可以使用第三方的证书解析工具,查看证书内容。或者使用openssl命令行工具查看证书序列号。

$ openssl x509 -in 1900009191_20180326_cert.pem -noout -serial
serial=1DDE55AD98ED71D6EDD4A4A16996DE7B47773A8C

如何在程序中加载证书

推荐使用微信支付提供的SDK。你也可以查看下列编程语言的示例代码。

/**
* Java
* 获取证书。
*
* @param filename 证书文件路径  (required)
* @return X509证书
*/
public static X509Certificate getCertificate(String filename) throws IOException {
InputStream fis = new FileInputStream(filename);
BufferedInputStream bis = new BufferedInputStream(fis);

try {
  CertificateFactory cf = CertificateFactory.getInstance("X509");
  X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
  cert.checkValidity();
  return cert;
  } catch (CertificateExpiredException e) {
    throw new RuntimeException("证书已过期", e);
  } catch (CertificateNotYetValidException e) {
    throw new RuntimeException("证书尚未生效", e);
  } catch (CertificateException e) {
    throw new RuntimeException("无效的证书文件", e);
  } finally {
    bis.close();
  }
}

为什么平台证书只提供API下载?

主要是为了确保在更换平台证书时,不影响商户使用微信支付的各种功能。以下场景中,微信支付会更换平台证书:

  • 证书到期后,必须更换。(目前是五年)
  • 证书到期前,例行更换。(每年一次)

为什么平台证书下载接口返回的平台证书需要加密?

主要是为了防御“中间人攻击”。

由于验证应答报文的签名和加密敏感信息时,必须使用到平台证书。平台证书是商户认证微信支付身份时最关键的要素。因此,要通过签名和加密等多重机制来保障商户获取的到平台证书没有被“中间人”篡改。

商户在调用下载接口获取平台证书时,应进行以下四步操作,以保证证书的真实性:

  • 使用与平台共享的对称密钥,解密报文中的证书(必须)
  • 通过解密得到的证书,来验证报文的签名(必须)
  • 使用证书查看工具,核对证书的颁发者为Tenpay.com Root CA。详见如何区分API证书的类型?(强烈推荐)
  • 通过证书信任链验证平台证书(强烈推荐)

如何通过证书信任链验证平台证书?

下面介绍如何使用openssl工具,通过证书信任链验证平台证书。

首先,从微信支付商户平台下载平台证书信任链 CertTrustChain.p7b ,并将它转换为pem证书格式。

openssl pkcs7 -print_certs -in CertTrustChain.p7b -inform der -out CertTrustChain.pem

然后,-CAfile file指定受信任的证书,验证下载的平台证书

openssl verify -verbose -CAfile ./CertTrustChain.pem ./WeChatPayPlatform.pem 

如何通过证书信任链验证平台证书?

商户上送敏感信息时使用了微信支付平台公钥加密。为了能使用正确的密钥解密,微信支付要求商户在请求的HTTP头部中包括证书序列号 ,以声明加密所用的密钥对和平台证书。详见这里的说明。

头条值点与头条小店

今日头条电商布局相信是看中了电商的无线潜力,事实上早在2014年7月头条就开始涉足于电商导购,只不过当时以消息流形式,还不是那么鲜为人知。现在再次踏足电商,凭借头条系希望能快速开辟自己的电商领域。很多人就对于值点和头条小店好奇了,这两个到底有什么区别呢。

1、今日头条值点与头条小店主打方向

今日头条值点是兼容资讯和电商,通过用户粘合度延长时间,实现资讯和数据购买的打通。这里的算法也是千人千面,做到私人定制,想要的商品会呈现在客户眼前。它主打是一款性价比、实惠、偏中低端层次,主要推荐9.9包邮、低至3折等活动。值点APP主要分两类,值得买和值得看,供客户自由选择。

头条小店定位于自媒体作者提供电商变现工具,帮助自媒体作者拓宽内容变现渠道,提升流量价值。头条小店可以选择企业或个人身份入驻,而且开通后店铺首页会出现在今日头条、西瓜视频、抖音、火山个人主页,这样更方便客户知晓。

2、今日头条值点与头条小店怎么入驻

今日头条值点目前只要是邀约制的,没有说需要符合什么条件可以申请入驻,必须是官方的邀请才能入驻。如果没收到值得APP入驻邀请的,耐心等候,同时还能看看头条小店怎么入驻。

头条小店个人或企业身份入驻都需要提供资质、缴纳保证金、通过审核,想了解具体入驻流程往下看:

头条小店

头条小店入驻入口有两个,一个是头条号后台的功能实验室-头条小店,还有一个是官方链接进入申请;无论你是从哪个入口进入,记住一定要将店铺和头条绑定在一起。

头条号投放广告

头条号发文时,不能随意插入链接,会提示必须是头条站内链接才可以插入,因此无法直接在发文时插入广告链接。

头条广告是什么:

头条广告是头条号作者将广告位委托给头条号平台代为运营的一种广告形式。 由头条号平台对用户和广告内容进行智能匹配,实现精准推广,广告收益完全属于创作者。

头条广告适用范围:

个人、群媒体、新闻媒体、企业类型的头条号。

如何设置投放头条广告:

自动同步的文章投放头条广告,请在「我的收益 - 收益设置」页面进行设置,此处设置只对自动同步内容生效;

手动发表的文章投放头条广告,请在发表文章时选择「投放头条广告」,手动发布的内容的广告投放类型以发布时编辑器上的选择为准。

详情请参照后台公告栏:http://www.toutiao.com/i6360082733166756354/

头条广告展示位置:

头条广告会展示在今日头条APP的文章下方,图集类文章的头条广告展示在图集末尾,视频不显示头条广告。为了平衡用户体验,文章并非每次刷新都有广告展示。PC端不展示头条广告。

头条广告收益如何产生:

1.投放了头条广告的内容才会有收益,每日的收益会展示在「我的收益」栏目中;

2.帐号分值与收益挂钩,不良行为引发的扣分,可能影响收益。详情请参考《关于帐号分值与帐号收益联动的公告》:https://www.toutiao.com/i6498912461758923277/

自营广告

投放自营广告需要满足头条号的千粉权益

samba 拷贝远程目录

主要参考了两个地方

https://superuser.com/questions/856617/how-do-i-recursively-download-a-directory-using-smbclient

http://technotize.blogspot.com/2011/12/copy-folder-with-ubuntu-smb-client.html


cd path_to_your_destination_directory  // 打开需要拷贝到的目标目录
smbclient remote_address  // 链接远程地址
cd dirctory_for_copy // 打开需要拷贝的目录
recurse
prompt OFF
mget *

tuo-fair-core参数调整器数据结构说明

1.基本数据结构

{
   [key]: {
      type: String, // 类型
      value: Any,  // 当前的值
      defaultValue: Any, // 默认值
      label: String, // 展示在界面上的参数名称
      options: Object, // 其他属性
   }
}

2. 具体参数调整器的options说明

2.1 数字输入类

{
  type: 'adjustorNumber',
  value: Number,
  defaultValue: Number,
  label: String,
  options: {
      precision: Number, // 小数点精度,表示保留几位小数
      step: Number, // 点击梯度变化按钮时的增减梯度,是正数
      hideStep: Boolean, // 是否隐藏梯度变化按钮,默认是false
      min: Number, // 最小值
      max: Number // 最大值
  }
}

2.2 图形选择枚举对象类

这类参数是指用一张图片来示意此参数值达成的效果,然后用一个对象来作为这个参数的实际值。此类参数主要用在需要用图片才能表达参数值的效果的情况。例如,用来调整材质的参数,这时候就需要提供一张图片来表示当前参数值能达成的渲染效果。此类参数的数据结构如下:

{
  type: 'imageEnumObject',
  value: Number,
  defaultValue: Number,
  label: String,
  options: {
      images: [<url_to_images>, ...]
      objects: [Any,...]
  }
}

2.3 图片输入类

{
   type: 'imageInput',
   value:  String, // 图片的 url
   defaultValue: String, // 图片的 url
   label: String,
   options: {
     width: Number,
     height: Number,
     aspect: Number, //optional
     texture: {
       wrapT: oneOf(['RepeatWrapping', 'MirroredRepeatWrapping', 'ClampToEdgeWrapping' ]), //default: 'ClampToEdgeWrapping',
       wrapS: oneOf(['RepeatWrapping', 'MirroredRepeatWrapping', 'ClampToEdgeWrapping' ]), //default: 'ClampToEdgeWrapping'
     }
   }
 }

图片输入类参数options中的aspect如果存在的,则表示输入的图片需要先进行一步变形。这里的aspect值是指uv值应用到3维对象上后,3维空间上u的长度比上v的长度的比值。例如,下面杯子所示:

如果杯子外壁上的uv展开值是铺满的,那么这里的aspect就应该满足如下的情况:

aspect = 外壁的周长 / 外壁的高度

2.4 一般选择类

{
  type: 'enum',
  value: ,
  defaultValue: ,
  label: String,
  options: {
     mutiple: Boolean, // 是否多选
     options: ArrayOf(String) | ArrayOf({lable: String, value: String}), // 若是String数组,则每个元素都必须唯一;若是Object数组则每个元素的value必须唯一
  }
}

2.5 人像选择类

{
   type: 'faceEnum',
   value:  String || null, // face3d的id
   defaultValue: null,
   label: String
 }

tuo-ui数据结构说明

以下是基本数据结构说明,具体实现时可能会根据实际需要增加一些属性。

1.字符输入类

{

value: String, // 默认初始值为‘’

onChange: (value) => {},

}

2.数字输入类

{

value: Number | undefined, // 默认初始值为undefined

onChange: (value) => {},

precision: Number, // 小数点精度,表示保留几位小数

step: Number, // 点击梯度变化按钮时的增减梯度,是正数

hideStep: Boolean, // 是否隐藏梯度变化按钮,默认是false

}

3.选项(Option)

{

value: String, // 必须唯一

title: String,

…...

}

或者

Option: String // 每个选项必须唯一

4.一般选择类

{

value: String,

onChange: (value, option: Option) => {}, // 所选值发生变化时调用

onSelect: (option: Option) => {}, // 进行选择操作时,调用(值不一定变化)

}

4.弹窗式选择类

{

visible: Boolean, // 弹窗是否可见

value: Any,

onClose: () => {}, // 点击关闭时调用

onOk: (value) => {}, // 点击确定时调用

onCancel: () => {} // 点击取消时调用

}

5.其他

5.1 adjustorNumber

{

value: Number,

onChange: (value) => {},

name: String,

min: Number,

max: Number

step: Number,

type: EnumOf(['continuous', 'discrete']),

couple: Boolean

}

在bat脚本中执行start nginx

在windows系统中,启动nginx的命令是:

cd c:\nginx-1.19.2
start nginx

但是在bat脚本文件中这样写出现了问题,提示找不到ngnix.exe文件。可以这样:

set root=c:\nginx-1.19.2
cd /D %root%
start nginx

具体参考: https://stackoverflow.com/questions/5138507/how-to-change-current-working-directory-using-a-batch-file

小程序的开发过程

1.申请小程序

2. 使用云函数开发小程序

1)获取openid

// 初始化云函数
cloud.init({
  // API 调用都保持和云函数当前所在环境一致
  env: cloud.DYNAMIC_CURRENT_ENV
})
cloud.getWXContext() // 获取context, 里面包含了OPENID等信息

2)小程序支付

小程序后台要先完成商户号关联和微信认证,然后需要在IDE中设置好商户号

3)统一下单
官方文档: https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-sdk-api/open/pay/CloudPay.unifiedOrder.html

cloud.cloudPay.unifiedOrder(orderInfo) // order参数是一个object

这里有几点需要注意:
a) 参数orderInfo.functionName,是微信支付完成后微信平台需要调用的函数名,是云函数,需要开发,必须返回{errcode: 0, errmsg: 'SUCCESS'},否则微信平台会反复调用它,它需要拥有处理重复消息的能力。另外使用云函数开发,不会有签名字符串返回,无法做签名校验。
b) orderInfo. subMchId 是关联的商户号,不一定是子商户号
c) orderInfo.spbillCreateIp 是服务器的公网IP地址

3. 云函数的返回问题

云函数默认是1秒返回,可以调整。当使用了setTimeout之类的函数,setTimeout内的函数在运行完成之前,如果先return了结果前端可以收到返回值,但是由于云函数还在运行,若超时,云函数还是会抛出一个超时错误