326 lines
11 KiB
JavaScript
326 lines
11 KiB
JavaScript
import assert from "assert";
|
||
import WechatSDK from 'oak-external-sdk/lib/WechatSDK';
|
||
import dayjs from "dayjs";
|
||
/**
|
||
* 微信物流支持的下单服务类型,参见:
|
||
* https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express-old/expressinfo.html
|
||
*/
|
||
const ShipServiceCodeDict = {
|
||
'sf-sftk': 2,
|
||
'sf-sfbk': 3,
|
||
'sf-sfjr': 1,
|
||
'dbl-tkzj': 2,
|
||
'dbl-djkd360': 1,
|
||
'yto-bzkd': 0,
|
||
'yto-yzd': 1,
|
||
'zto-bzkd': 0,
|
||
'sto-bzkd': 1,
|
||
};
|
||
export default class WechatMpShipDebug {
|
||
wechatMpShipId;
|
||
wechatMpShip;
|
||
// 这个外部可能也需要调用
|
||
getReceiverInfo;
|
||
getExtraData;
|
||
constructor(wechatMpShipId, getReceiverInfo, getExtraData) {
|
||
this.wechatMpShipId = wechatMpShipId;
|
||
this.getReceiverInfo = getReceiverInfo;
|
||
this.getExtraData = getExtraData;
|
||
}
|
||
async getWechatMpShip(context) {
|
||
if (this.wechatMpShip) {
|
||
return this.wechatMpShip;
|
||
}
|
||
const [wechatMpShip] = await context.select('wechatMpShip', {
|
||
data: {
|
||
id: 1,
|
||
applicationId: 1,
|
||
application: {
|
||
id: 1,
|
||
type: 1,
|
||
config: 1,
|
||
}
|
||
},
|
||
filter: {
|
||
id: this.wechatMpShipId,
|
||
}
|
||
}, { dontCollect: true });
|
||
this.wechatMpShip = wechatMpShip;
|
||
return this.wechatMpShip;
|
||
}
|
||
async available(shipServiceId, orderIds, context) {
|
||
if (!ShipServiceCodeDict.hasOwnProperty(shipServiceId)) {
|
||
return false;
|
||
}
|
||
const wechatMpShip = await this.getWechatMpShip(context);
|
||
const { openId, appWxId } = await this.getReceiverInfo(orderIds, wechatMpShip.applicationId, context);
|
||
if (!openId && !appWxId) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
async getInstance(context) {
|
||
const wechatMpShip = await this.getWechatMpShip(context);
|
||
const { config } = wechatMpShip.application;
|
||
assert(config.type === 'wechatMp');
|
||
const { appId, appSecret } = config;
|
||
const instance = WechatSDK.getInstance(appId, 'wechatMp', appSecret);
|
||
return instance;
|
||
}
|
||
async prepareOrder(shipId, context) {
|
||
const [ship] = await context.select('ship', {
|
||
data: {
|
||
id: 1,
|
||
entity: 1,
|
||
entityId: 1,
|
||
from: {
|
||
id: 1,
|
||
detail: 1,
|
||
name: 1,
|
||
phone: 1,
|
||
area: {
|
||
id: 1,
|
||
name: 1,
|
||
parent: {
|
||
id: 1,
|
||
name: 1,
|
||
parent: {
|
||
id: 1,
|
||
name: 1,
|
||
},
|
||
},
|
||
},
|
||
},
|
||
to: {
|
||
id: 1,
|
||
detail: 1,
|
||
name: 1,
|
||
phone: 1,
|
||
area: {
|
||
id: 1,
|
||
name: 1,
|
||
parent: {
|
||
id: 1,
|
||
name: 1,
|
||
parent: {
|
||
id: 1,
|
||
name: 1,
|
||
},
|
||
},
|
||
},
|
||
},
|
||
wechatMpShip: {
|
||
id: 1,
|
||
application: {
|
||
id: 1,
|
||
config: 1,
|
||
},
|
||
},
|
||
shipOrder$ship: {
|
||
$entity: 'shipOrder',
|
||
data: {
|
||
id: 1,
|
||
orderId: 1,
|
||
},
|
||
},
|
||
shipService: {
|
||
id: 1,
|
||
name: 1,
|
||
shipCompany: {
|
||
id: 1,
|
||
abbr: 1,
|
||
},
|
||
},
|
||
},
|
||
filter: {
|
||
id: shipId,
|
||
}
|
||
}, { dontCollect: true });
|
||
assert(ship);
|
||
const { entity, entityId, shipOrder$ship, wechatMpShip, from, to, shipService } = ship;
|
||
assert(entity === 'wechatMpShip' && entityId === this.wechatMpShipId);
|
||
const orderIds = shipOrder$ship.map(ele => ele.orderId);
|
||
const { openId, appWxId } = await this.getReceiverInfo(orderIds, wechatMpShip.applicationId, context);
|
||
assert(openId || appWxId);
|
||
const extraData = await this.getExtraData(shipId, context);
|
||
const data = Object.assign({
|
||
order_id: ship.id,
|
||
openid: openId,
|
||
wx_appid: appWxId,
|
||
add_source: openId ? 0 : 2,
|
||
delivery_id: shipService.shipCompanyId,
|
||
service: {
|
||
service_type: ShipServiceCodeDict[shipService.id],
|
||
service_name: shipService.name,
|
||
},
|
||
sender: {
|
||
name: from.name,
|
||
mobile: from.phone,
|
||
// country: from!.area!.parent!.parent!.name!, //国家
|
||
province: from.area.parent.parent.name, //省份
|
||
city: from.area.parent.name, //市
|
||
area: from.area.name, // 区
|
||
address: from.detail, //详细地址
|
||
},
|
||
receiver: {
|
||
name: to.name,
|
||
mobile: to.phone,
|
||
province: to.area.parent.parent.name,
|
||
city: to.area.parent.name,
|
||
area: to.area.name,
|
||
address: to.detail,
|
||
},
|
||
expect_time: 0,
|
||
}, extraData);
|
||
return data;
|
||
}
|
||
async prepareCancelOrder(shipId, context) {
|
||
const [ship] = await context.select('ship', {
|
||
data: {
|
||
id: 1,
|
||
extraShipId: 1,
|
||
shipService: {
|
||
shipCompanyId: 1,
|
||
},
|
||
shipOrder$ship: {
|
||
$entity: 'shipOrder',
|
||
data: {
|
||
orderId: 1,
|
||
},
|
||
},
|
||
wechatMpShip: {
|
||
applicationId: 1,
|
||
},
|
||
},
|
||
filter: {
|
||
id: shipId,
|
||
}
|
||
}, { dontCollect: true });
|
||
assert(ship);
|
||
const { extraShipId, shipService, shipOrder$ship: shipOrders, wechatMpShip } = ship;
|
||
const orderIds = shipOrders.map(ele => ele.orderId);
|
||
const { openId } = await this.getReceiverInfo(orderIds, wechatMpShip.applicationId, context);
|
||
return {
|
||
openid: openId,
|
||
delivery_id: shipService.shipCompanyId,
|
||
waybill_id: extraShipId,
|
||
order_id: shipId,
|
||
};
|
||
}
|
||
async prepareGetPath(shipId, context) {
|
||
const [ship] = await context.select('ship', {
|
||
data: {
|
||
id: 1,
|
||
extraShipId: 1,
|
||
shipService: {
|
||
shipCompanyId: 1,
|
||
},
|
||
shipOrder$ship: {
|
||
$entity: 'shipOrder',
|
||
data: {
|
||
orderId: 1,
|
||
},
|
||
},
|
||
wechatMpShip: {
|
||
applicationId: 1,
|
||
},
|
||
},
|
||
filter: {
|
||
id: shipId,
|
||
}
|
||
}, { dontCollect: true });
|
||
assert(ship);
|
||
const { extraShipId, shipService, shipOrder$ship: shipOrders, wechatMpShip } = ship;
|
||
const orderIds = shipOrders.map(ele => ele.orderId);
|
||
const { openId } = await this.getReceiverInfo(orderIds, wechatMpShip.applicationId, context);
|
||
return {
|
||
openid: openId,
|
||
delivery_id: shipService.shipCompanyId,
|
||
waybill_id: extraShipId,
|
||
};
|
||
}
|
||
async prepareGetOrder(shipId, context) {
|
||
const [ship] = await context.select('ship', {
|
||
data: {
|
||
id: 1,
|
||
extraShipId: 1,
|
||
shipService: {
|
||
shipCompanyId: 1,
|
||
},
|
||
shipOrder$ship: {
|
||
$entity: 'shipOrder',
|
||
data: {
|
||
orderId: 1,
|
||
},
|
||
},
|
||
wechatMpShip: {
|
||
applicationId: 1,
|
||
},
|
||
},
|
||
filter: {
|
||
id: shipId,
|
||
}
|
||
}, { dontCollect: true });
|
||
assert(ship);
|
||
const { extraShipId, shipService, shipOrder$ship: shipOrders, wechatMpShip } = ship;
|
||
const orderIds = shipOrders.map(ele => ele.orderId);
|
||
const { openId } = await this.getReceiverInfo(orderIds, wechatMpShip.applicationId, context);
|
||
return {
|
||
order_id: shipId,
|
||
openid: openId,
|
||
delivery_id: shipService.shipCompanyId,
|
||
waybill_id: extraShipId,
|
||
};
|
||
}
|
||
async eOrder(shipId, context) {
|
||
const data = await this.prepareOrder(shipId, context);
|
||
console.log('mock eOrder to wechatMpShip, data:', data);
|
||
return 'mockExtraShipId';
|
||
}
|
||
async cancelOrder(shipId, context) {
|
||
const data = await this.prepareCancelOrder(shipId, context);
|
||
console.log('mock cancelOrder to wechatMpShip, data:', data);
|
||
}
|
||
async syncState(shipId, context) {
|
||
const data = await this.prepareGetPath(shipId, context);
|
||
console.log('mock syncState to wechatMpShip, data:', data);
|
||
const r = Math.random();
|
||
const now = Date.now();
|
||
if (r < 0.3) {
|
||
return { state: 'shipping', time: now };
|
||
}
|
||
else if (r > 0.95) {
|
||
return { state: 'unknow', time: now };
|
||
}
|
||
return { state: 'received', time: now };
|
||
}
|
||
async syncPaths(shipId, context) {
|
||
const data = await this.prepareGetPath(shipId, context);
|
||
console.log('mock syncPaths to wechatMpShip, data:', data);
|
||
const time = dayjs().subtract(1, 'h').valueOf();
|
||
return [{
|
||
time,
|
||
action: "快递员已成功取件"
|
||
},
|
||
{
|
||
time,
|
||
action: "快件已到达xxx集散中心,准备发往xxx"
|
||
},
|
||
{
|
||
time,
|
||
action: "快递员已出发,联系电话xxxxxx"
|
||
}];
|
||
}
|
||
async getPrintInfo(shipId, context) {
|
||
const data = await this.prepareGetOrder(shipId, context);
|
||
console.log('mock getPrintInfo to wechatMpShip, data:', data);
|
||
const mockData = 'PGh0bWw+PGhlYWQ+PC9oZWFkPjxib2R5PjxoMT5tb2NrIOmdouWNlTwvaDE+PC9ib2R5PjwvaHRtbD4=';
|
||
const mockHtml = Buffer.from(mockData, 'base64').toString();
|
||
return {
|
||
type: 'html',
|
||
data: mockHtml
|
||
};
|
||
}
|
||
}
|
||
;
|