nginx解析中文域名
最近给客户做一个网站,客户提供的域名是中文的,再设置nginx后发现代理没有起作用.
查了不少资料后发现浏览器是将地方语言(中文)转成punycode编码,然后交给DNS解析的.
那么需要做的就是吧中文域名通过punycode转码,然后放到nginx的server_name后面.
个人找到的一个中文编码网站http://tools.jb51.net/punycode/index.php
记录一下,以便后期查看
最近给客户做一个网站,客户提供的域名是中文的,再设置nginx后发现代理没有起作用.
查了不少资料后发现浏览器是将地方语言(中文)转成punycode编码,然后交给DNS解析的.
那么需要做的就是吧中文域名通过punycode转码,然后放到nginx的server_name后面.
个人找到的一个中文编码网站http://tools.jb51.net/punycode/index.php
记录一下,以便后期查看
因为需要做一个付款在winform应用程序上扫码付款,所以采用native扫码的模式一来实现.
进入商户平台-->产品中心-->开发配置 扫码支付回调链接
我设置的是 https://域名/pay/notify
首先 npm 引入tenpay 框架
npm i tenpay --save
全局创建一个tenpay api对象
// wxpay.js
const Tenpay = require('tenpay')
const config = require('../config/config.js')
/**
* tenpayConfig: {
appid: '公众号ID',
mchid: '微信商户号',
partnerKey: '微信支付安全密钥',
notify_url: 'https://域名/pay/complete', // 支付后回调的接口
spbill_create_ip: '服务器ip地址'
}
*/
let api = null
module.exports = {
getApi () {
if(!api) api = new Tenpay(config.tenpayConfig)
return api
}
}
根据商品ID生成url链接
api.getNativeUrl({
product_id: product.id
})
将商品链接转成二维码
node二维码生成开源框架:node-qrcode
npm install --save qrcode // npm 安装.
const QRCode = require('qrcode')
...
const qr = await QRCode.toDataURL(order.url) // 转成base64
this.header('Content-Type', 'image/png; charset=UTF-8') // 设置头部
this.body = base64ToSteam(qr) // 输出图片流
// 将base64图片转流方法.
function base64ToSteam (data) {
const base64 = data.replace(/^data:image\/\w+;base64,/, '')
const dataBuffer = Buffer.from(base64, 'base64')
const bufferStream = new stream.PassThrough()
bufferStream.end(dataBuffer)
return bufferStream
}
生成商品二维码后,只要有用户用微信扫码,微信会自动调你之前在商户后台设置的回调链接
tenpay框架已经将几个回调的参数校验解析已中间件的形式开放出来,这里我们只需要将他集成到thinkjs的中间件管理里,因为有多个地方用到了中间件,集中封装一下:
const wxpay = require('./wxpay') // 代码参考最上面,就是拿到tenpay的实例对象.
// 默认options
const defaultOptions = {
type: 'nativePay' // 扫码的回调中间件传入nativePay
}
module.exports = (options = {}) => {
options = Object.assign({}, defaultOptions, options);
let api = wxpay.getApi() // 拿到实例对象
let pay = api.middleware(options.type) // 创建回调函数
return pay
}
然后在thinkjs的middleware.js 中间件管理中的后面插入:
// middleware.js
const pay = require('../utils/paycallback')
....
{
handle: 'payload', // thinkjs 自己的参数转换中间件,类似于bodyParser的功能.
options: {
...
}
},
// 扫码回调
{
handle: pay,
options: {
type: 'nativePay'
},
match: '/pay/notify' // 这里根据自己的接口匹配设置,代表中间件只在这个接口起作用.
}
然后开发 /pay/notify 接口:
中间件会帮你在ctx对象下绑定两个方法:
replyNative : 扫描成功,传入微信的预订单编号
reply : 失败,传入失败原因.
try {
let res = this.ctx.request
let info = res.weixin // 中间件会将微信的参数解析到request下的weixin对象中.
let product_id = info.product_id // 商品id,就是你生成url链接时候,传入的商品id
let openid = info.openid // 用户的openid 在你商户下对应微信唯一ID
// 下面是业务代码
// 获取商品信息.
let product = await this.model('product_list').where({ id: product_id }).find()
if (think.isEmpty(product)) {
return this.ctx.reply('未找到商品')
}
// 自己数据库生成订单号.
....
// 调用tenpay的unifiedOrder方法统一下单,生成预订单编号.
let result = await api.unifiedOrder({
out_trade_no: orderId, // 订单编号
body: product.name, // 商品名称
total_fee: product.amount * 100, // 我们数据库是元为单位,微信要求分为单位提交
openid: openid,
trade_type: 'NATIVE'
})
....
return this.ctx.replyNative(result.prepay_id) // 成功后将统一下单生成的prepay_id 通过replyNative方法返回给微信服务器
} catch (error) {
this.ctx.reply(error.message || '服务器错误')
}
然后将代码发布到服务器上后,你测试用微信扫码后,会发现服务器会返回报错,原因是tenpay要求开发人员将微信的xml内容解析后直接已字符串的形式放在body下,而thinkjs的payload会把xml内容解析后,将xml变成对象的形式,放在 body.xml 下.所以我们还要设置一步让payload不要解析xml,直接把流转成文字放在body下就可以了(这是我看了tenpay的源码后才发现的...)
{
handle: 'payload',
options: {
....
extendTypes: {
text: ['text/xml', 'application/xml'] // xml以text形式解析.
}
}
},
tenpay框架的config里如果设置了notify_url地址,微信在用户支付后会回调这个接口
首先一样,让tenpay框架的中间件去处理微信解析和校验的功能
// middleware.js
....
一样要放在payload后面
// 用户支付完成通知.
{
handle: pay,
options: {
type: 'pay'
},
match: '/pay/complete' // 你的回调链接 同上.
},
....
然后开发支付回调/pay/complete接口:
try {
let info = this.ctx.request.weixin // 拿到中间件解析内容.
const orderModel = this.model('order')
if (info.return_code === 'SUCCESS') {
let orderId = info.out_trade_no // 订单号
let total_fee = parseInt(info.total_fee) / 100 // 金额
if (info.result_code === 'SUCCESS') { // 支付成功.
// 交易成功.
let order = await orderModel.where({ id: orderId }).find()
if (think.isEmpty(order)) throw new Error('未找到订单')
// 自己数据库订单处理
....
} else { // 支付失败
....
}
}
this.ctx.reply() // 回复消息(参数为空回复成功, 传值则为错误消息)
} catch (error) {
this.ctx.reply(error.message || '服务器错误')
}
到第4步已经走完了,但是总有些订单有可能因为网络/数据库原因,complete接口没有接收到或者保存失败之类的.这时候要有一个主动向服务器请求订单状态的接口,这里简单写一下提供参考:
let code = this.query('code')
let result = await api.orderQuery({
out_trade_no: code
})
// return this.success(result)
if (result.return_code === 'SUCCESS') {
if (result.result_code === 'SUCCESS') {
if (result.trade_state === 'SUCCESS') {
// 付款成功
let amount = parseInt(result.total_fee) / 100
let complete_time = result.time_end.replace(/(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/, '$1-$2-$3 $4:$5:$6')
....
// 成功回调.
} else {
// 付款失败
return this.success({
status: 1,
message: result.trade_state_desc,
info: result
})
}
} else {
return this.fail(result.err_code_des)
}
} else {
return this.fail(result.return_msg)
}
之前在一个SDK包里看到对方用3d的注释文字,使得在codeglance之类的插件中也能醒目的看到某一段代码的注释,感觉非常秀.
这使得2000多行代码的文件还能有一点可读性...
后来终于在找到了一个能够生成类似文字的网站,在这里记录一下:
http://patorjk.com/software/taag/#p=display&f=Big%20Money-se&t=Public
之前使用postman都只会设置静态的环境变量 如设置请求的域名. 这样切换就可以很方便的切换正式库和测试库.
最近由于需要做接口测试,必须先调用login接口后记录token值,然后再依次调用后面的所有的接口需要把token动态的写入.去查了postman的相关资料,终于发现在postman的测试(Tests)标签栏里是可以做接口返回数据校验已经设置环境变量当前值的.
以下是我写在login接口中的Tests脚本
pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
pm.test('success', function () {
var jsonData = pm.response.json();
pm.environment.set("token", jsonData.result.token);
pm.expect(jsonData.code).to.eql(200); // 返回的json code值为200
})
其他的接口里可以不设置token,单纯检测状态值返回以及json code返回
如果需要并发测试,可以参考 github开源框架
newman通过导出postman配置文件,用node进行并发测试.
最近有一个需求,希望能在全景图的贴图上直接选择位置放置物体,最后反应在全景图的相应位置点.在这里记录一下开发代码:
let path = this.publicPath + 'texture/uv_grid_opengl.jpg'
let texture = new THREE.TextureLoader().load(path)
let material = new THREE.MeshBasicMaterial({
map: texture,
side: THREE.DoubleSide // 也可以是单面
})
let geometry = new THREE.SphereBufferGeometry(510, 40, 40) // 半径 ,宽高分割数.可以随意
geometry.scale(-1, 1, 1) // 让贴图在内部贴,而不是外部.
this.$mesh = new THREE.Mesh(geometry, material)
参考代码:https://threejsfundamentals.org/threejs/lessons/threejs-align-html-elements-to-3d.html
// x,y 的0点位置从左上角来算的,反应在图片上的长宽比值.
// 因为geometry的x坐标返了,所以真也要相反处理
let lat = (e.y - 0.5) * 180
let lon = (1 - e.x) * 360
const lonFudge = -Math.PI * 0.5 // Math.PI
const latFudge = Math.PI
// these helpers will make it easy to position the boxes
// We can rotate the lon helper on its Y axis to the longitude
const lonHelper = new THREE.Object3D()
// We rotate the latHelper on its X axis to the latitude
const latHelper = new THREE.Object3D()
lonHelper.add(latHelper)
// The position helper moves the object to the edge of the sphere
const positionHelper = new THREE.Object3D()
positionHelper.position.z = 500
latHelper.add(positionHelper)
// adjust the helpers to point to the latitude and longitude
lonHelper.rotation.y = THREE.MathUtils.degToRad(lon) + lonFudge
latHelper.rotation.x = THREE.MathUtils.degToRad(lat) + latFudge
// get the position of the lat/lon
positionHelper.updateWorldMatrix(true, false)
const position = new THREE.Vector3()
positionHelper.getWorldPosition(position)
// 最终x,y点反应在球形位置上.
let pos = [position.x, position.y, position.z]