egg-wechat-pay
Version:
Wechat pay plugin for egg.
203 lines (173 loc) • 3.52 kB
JavaScript
const {Payment} = require('wechat-pay')
const delegates = require('delegates')
const moment = require('moment')
const {defaults, BASIC_TYPES} = require('skema')
const {shape} = defaults({
types: BASIC_TYPES.STRICT
})
const MockData = shape({
nonce_str: {
default (self) {
return self._payment._generateNonceStr()
}
},
sign_type: {
optional: true,
validate (v) {
return v === 'MD5' || v === 'HMAC-SHA256'
}
},
result_code: {
default: 'SUCCESS'
},
appid: {
set (self) {
return self._config.appId
}
},
mch_id: {
set (self) {
return self._config.mchId
}
},
openid: {
default: 'wxd930ea5d5a258f4f'
},
trade_type: {
default: 'JSAPI'
},
bank_type: {
default: 'CMC'
},
total_fee: Number,
cash_fee: Number,
settlement_total_fee: {
optional: true,
type: Number
},
fee_type: {
default: 'CNY',
type: String
},
transaction_id: String,
out_trade_no: String,
attach: {
optional: true,
type: String
},
time_end: {
default () {
return new Date
},
set (v) {
const date = v instanceof Date
? date
: new Date(date)
return moment(date).format('YYYYMMDDHHmmss')
}
}
})
class WechatPayBase {
constructor ({
bodyPrefix,
config
}) {
this._bodyPrefix = bodyPrefix
this._config = config
}
requestPayment ({
body,
spbill_create_ip,
ip,
...others
}) {
return this._payment.getBrandWCPayRequestParams({
body: this._handleBody(body),
spbill_create_ip: ip || spbill_create_ip,
...others
})
}
parse (xml) {
return this._payment.validate(xml)
}
stringify (obj) {
return this._payment.buildXml(obj)
}
fail (ctx, return_msg) {
ctx.body = this.stringify({
return_code: 'FAIL',
return_msg
})
}
success (ctx) {
ctx.body = this.stringify({
return_code: 'SUCCESS'
})
}
mock (data) {
const mocked = MockData.from(data, [this])
mocked.sign = this._payment._getSign(mocked)
return this.stringify(mocked)
}
_handleBody (body) {
const prefix = this._bodyPrefix
if (!prefix) {
return body
}
if (body.indexOf(prefix) === 0) {
return body
}
return `${prefix}-${body}`
}
}
delegates(WechatPayBase.prototype, '_payment')
.method('refund')
.method('refundQuery')
.method('closeOrder')
.method('orderQuery')
.method('sendRedPacket')
.method('redPacketQuery')
.method('transfers')
.method('downloadBill')
class WechatPayNew extends WechatPayBase {
constructor (payment, options) {
super(options)
this._payment = payment
}
}
module.exports = class WechatPayManager extends WechatPayBase {
constructor ({
secret, partnerKey,
appId,
merchantId, mchId,
notifyUrl,
pfx,
bodyPrefix
}) {
const config = {
partnerKey: secret || partnerKey,
mchId: merchantId || mchId,
notifyUrl,
pfx,
appId
}
super({bodyPrefix, config})
this._apps = Object.create(null)
this._payment = this._newApp(appId)
}
_newApp (appId) {
const app = this._apps[appId]
if (app) {
return app
}
const config = Object.assign({}, this._config, {appId})
return this._apps[appId] = new Payment(config)
}
// Creates a new instance
newApp (appId) {
if (appId === this._appId) {
return this
}
return new WechatPayNew(this._newApp(appId), this._config)
}
}