feat(trade): WeChat confirm-receive component + admin status log columns

Open weappOrderConfirm in mini-user so users confirm in-app instead of
service notice; verify via get_order before completing. Show operator/remark
on admin order status timeline.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-29 16:48:44 +08:00
parent 05dffbfa15
commit 1a0afb6d39
14 changed files with 505 additions and 32 deletions
@@ -10,6 +10,7 @@ import type {
WechatWxaCodeUnlimitedInput,
WechatUploadShippingInfoInput,
WechatUploadShippingInfoResult,
WechatOrderShippingQueryResult,
WechatDeliveryCompany,
} from './wechat.interface';
import { logWechatAuth, type WechatActorRef } from './wechat-log.util';
@@ -375,6 +376,55 @@ export class WechatApiProvider implements IWechatProvider {
};
}
async getOrderShippingInfo(input: {
transactionId?: string;
mchId?: string;
outTradeNo?: string;
}): Promise<WechatOrderShippingQueryResult> {
const callOnce = async (accessToken: string) => {
const body: Record<string, string> = {};
if (input.transactionId) {
body.transaction_id = input.transactionId;
} else {
if (!input.mchId || !input.outTradeNo) {
throw new BadRequestException('请提供 transaction_id 或 mchid+out_trade_no');
}
body.merchant_id = input.mchId;
body.merchant_trade_no = input.outTradeNo;
}
const apiUrl = `https://api.weixin.qq.com/wxa/sec/order/get_order?access_token=${accessToken}`;
return this.fetchJson<{
errcode?: number;
errmsg?: string;
order?: {
transaction_id?: string;
merchant_trade_no?: string;
order_state?: number;
shipping?: { finish_shipping?: boolean };
};
}>(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
};
let accessToken = await this.getMiniAccessToken();
let data = await callOnce(accessToken);
if (TOKEN_INVALID_ERRCODES.has(data.errcode ?? -1)) {
accessToken = await this.getMiniAccessToken(true);
data = await callOnce(accessToken);
}
return {
errcode: data.errcode ?? 0,
errmsg: data.errmsg ?? 'ok',
orderState: data.order?.order_state,
transactionId: data.order?.transaction_id,
merchantTradeNo: data.order?.merchant_trade_no,
finishShipping: data.order?.shipping?.finish_shipping,
};
}
async getDeliveryList(): Promise<WechatDeliveryCompany[]> {
const accessToken = await this.getMiniAccessToken();
const apiUrl = `https://api.weixin.qq.com/cgi-bin/express/delivery/open_msg/get_delivery_list?access_token=${accessToken}`;