205 lines
5.4 KiB
JavaScript
205 lines
5.4 KiB
JavaScript
import { getPayClazz } from './payClazz';
|
||
import assert from 'assert';
|
||
import { generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||
export const fullPayProjection = {
|
||
id: 1,
|
||
applicationId: 1,
|
||
price: 1,
|
||
meta: 1,
|
||
iState: 1,
|
||
depositId: 1,
|
||
deposit: {
|
||
id: 1,
|
||
price: 1,
|
||
iState: 1,
|
||
accountId: 1,
|
||
},
|
||
entity: 1,
|
||
entityId: 1,
|
||
paid: 1,
|
||
refunded: 1,
|
||
timeoutAt: 1,
|
||
forbidRefundAt: 1,
|
||
orderId: 1,
|
||
order: {
|
||
id: 1,
|
||
title: 1,
|
||
desc: 1,
|
||
},
|
||
};
|
||
export async function payNotify(context, body, payId, headers) {
|
||
const [pay] = await context.select('pay', {
|
||
data: {
|
||
id: 1,
|
||
price: 1,
|
||
iState: 1,
|
||
entity: 1,
|
||
entityId: 1,
|
||
meta: 1,
|
||
applicationId: 1,
|
||
},
|
||
filter: {
|
||
id: payId,
|
||
}
|
||
}, { blockTrigger: true });
|
||
if (!pay) {
|
||
console.error('接受到无效的payId', payId);
|
||
return;
|
||
}
|
||
const { applicationId, entity, entityId, price } = pay;
|
||
const payClazz = await getPayClazz(entity, entityId, context);
|
||
const { payId: payId2, iState, extra } = await payClazz.decodePayNotification({
|
||
headers,
|
||
}, body);
|
||
assert(payId2 === payId);
|
||
if (iState !== pay.iState) {
|
||
let action = 'close';
|
||
const updateData = {};
|
||
switch (iState) {
|
||
case 'closed': {
|
||
// action = 'close';
|
||
break;
|
||
}
|
||
case 'paid': {
|
||
action = 'succeedPaying';
|
||
updateData.paid = price;
|
||
if (extra) {
|
||
Object.assign(updateData, extra);
|
||
}
|
||
break;
|
||
}
|
||
default: {
|
||
assert(false);
|
||
}
|
||
}
|
||
await context.operate('pay', {
|
||
id: await generateNewIdAsync(),
|
||
action,
|
||
data: updateData,
|
||
filter: {
|
||
id: payId,
|
||
}
|
||
}, {});
|
||
}
|
||
return;
|
||
}
|
||
export async function refundNotify(context, body, refundId, headers) {
|
||
const [refund] = await context.select('refund', {
|
||
data: {
|
||
id: 1,
|
||
price: 1,
|
||
iState: 1,
|
||
pay: {
|
||
entity: 1,
|
||
entityId: 1,
|
||
}
|
||
},
|
||
filter: {
|
||
id: refundId,
|
||
}
|
||
}, {});
|
||
if (!refund) {
|
||
console.error('接受到无效的refundId', refundId);
|
||
return;
|
||
}
|
||
const { entity, entityId } = refund.pay;
|
||
const payClazz = await getPayClazz(entity, entityId, context);
|
||
const { refundId: refundId2, extra, iState, } = await payClazz.decodeRefundNotification({ headers }, body);
|
||
assert(refundId2 === refundId);
|
||
if (iState !== refund.iState) {
|
||
let action = 'succeed';
|
||
const updateData = {};
|
||
switch (iState) {
|
||
case 'successful': {
|
||
// action = 'close';
|
||
break;
|
||
}
|
||
case 'failed': {
|
||
action = 'fail';
|
||
break;
|
||
}
|
||
default: {
|
||
assert(false);
|
||
}
|
||
}
|
||
if (extra) {
|
||
Object.assign(updateData, extra);
|
||
}
|
||
await context.operate('refund', {
|
||
id: await generateNewIdAsync(),
|
||
action,
|
||
data: updateData,
|
||
filter: {
|
||
id: refundId,
|
||
}
|
||
}, {});
|
||
}
|
||
}
|
||
/**
|
||
* 刷新paying状态的pay的真实支付状态
|
||
* @param pay
|
||
* @param context
|
||
* @returns
|
||
*/
|
||
export async function refreshPayState(pay, context) {
|
||
let pay2 = pay;
|
||
if (!pay2.entity || !pay2.entityId || !pay2.timeoutAt || !pay2.price || !pay2.iState) {
|
||
const pays = await context.select('pay', {
|
||
data: {
|
||
id: 1,
|
||
entity: 1,
|
||
entityId: 1,
|
||
price: 1,
|
||
iState: 1,
|
||
},
|
||
filter: {
|
||
id: pay.id,
|
||
}
|
||
}, {
|
||
blockTrigger: true,
|
||
forUpdate: true,
|
||
});
|
||
pay2 = pays[0];
|
||
}
|
||
const { entity, entityId, timeoutAt, price } = pay2;
|
||
const clazz = await getPayClazz(entity, entityId, context);
|
||
const [iState, updateData] = await clazz.getState(pay);
|
||
if (iState !== pay.iState) {
|
||
let action = 'close';
|
||
switch (iState) {
|
||
case 'closed': {
|
||
// action = 'close';
|
||
break;
|
||
}
|
||
case 'paid': {
|
||
action = 'succeedPaying';
|
||
updateData.paid = price;
|
||
break;
|
||
}
|
||
default: {
|
||
assert(false);
|
||
}
|
||
}
|
||
return await context.operate('pay', {
|
||
id: await generateNewIdAsync(),
|
||
action,
|
||
data: updateData,
|
||
filter: {
|
||
id: pay.id,
|
||
}
|
||
}, {});
|
||
}
|
||
else if (iState === 'paying' && timeoutAt < Date.now()) {
|
||
// 尝试关闭订单
|
||
// 理论上用户可能在上一个getState和这个close之间支付完成,此时关闭失败,下一个Watcher到来时就能处理成功了
|
||
return await context.operate('pay', {
|
||
id: await generateNewIdAsync(),
|
||
action: 'close',
|
||
data: updateData,
|
||
filter: {
|
||
id: pay.id,
|
||
}
|
||
}, {});
|
||
}
|
||
}
|