Merge branch 'dev' of gitea.51mars.com:Oak-Team/oak-pay-business into dev
This commit is contained in:
commit
849c4179e4
|
|
@ -2,6 +2,7 @@
|
||||||
* 抽象组件在业务层根据EntityDict的重新声明
|
* 抽象组件在业务层根据EntityDict的重新声明
|
||||||
* by Xc 20230807
|
* by Xc 20230807
|
||||||
*/
|
*/
|
||||||
|
import React from 'react';
|
||||||
import { EntityDict } from '../oak-app-domain';
|
import { EntityDict } from '../oak-app-domain';
|
||||||
import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, ListButtonProps, OakAbsAttrUpsertDef } from 'oak-frontend-base';
|
import { ReactComponentProps, ColumnProps, RowWithActions, OakExtraActionProps, OakAbsAttrDef, onActionFnDef, ListButtonProps, OakAbsAttrUpsertDef } from 'oak-frontend-base';
|
||||||
declare const FilterPanel: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
|
declare const FilterPanel: <T extends keyof EntityDict>(props: ReactComponentProps<EntityDict, T, false, {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
* 抽象组件在业务层根据EntityDict的重新声明
|
* 抽象组件在业务层根据EntityDict的重新声明
|
||||||
* by Xc 20230807
|
* by Xc 20230807
|
||||||
*/
|
*/
|
||||||
// @ts-nocheck
|
|
||||||
import AbsFilterPanel from 'oak-frontend-base/es/components/filterPanel';
|
import AbsFilterPanel from 'oak-frontend-base/es/components/filterPanel';
|
||||||
import AbsList from 'oak-frontend-base/es/components/list';
|
import AbsList from 'oak-frontend-base/es/components/list';
|
||||||
import AbsListPro from 'oak-frontend-base/es/components/listPro';
|
import AbsListPro from 'oak-frontend-base/es/components/listPro';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { String, Text, Price } from 'oak-domain/lib/types/DataType';
|
import { String, Text, Price, Datetime } from 'oak-domain/lib/types/DataType';
|
||||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||||
import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
|
import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
|
||||||
import { Schema as User } from './User';
|
import { Schema as User } from './User';
|
||||||
|
|
@ -14,6 +14,7 @@ export interface Schema extends EntityShape {
|
||||||
price: Price;
|
price: Price;
|
||||||
creator: User;
|
creator: User;
|
||||||
reason?: Text;
|
reason?: Text;
|
||||||
|
successAt?: Datetime;
|
||||||
opers: AccountOper[];
|
opers: AccountOper[];
|
||||||
}
|
}
|
||||||
export type IAction = 'succeed' | 'fail';
|
export type IAction = 'succeed' | 'fail';
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@ export const entityDesc = {
|
||||||
iState: '状态',
|
iState: '状态',
|
||||||
creator: '创建者',
|
creator: '创建者',
|
||||||
reason: '原因',
|
reason: '原因',
|
||||||
opers: '相关账户操作'
|
opers: '相关账户操作',
|
||||||
|
successAt: '退款成功时间'
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
succeed: '退款成功',
|
succeed: '退款成功',
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, MakeFil
|
||||||
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
||||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult, EntityShape } from "oak-domain/lib/types/Entity";
|
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult, EntityShape } from "oak-domain/lib/types/Entity";
|
||||||
import { Action, ParticularAction, IState } from "./Action";
|
import { Action, ParticularAction, IState } from "./Action";
|
||||||
import { Price, String, Text } from "oak-domain/lib/types/DataType";
|
import { Price, String, Text, Datetime } from "oak-domain/lib/types/DataType";
|
||||||
import * as Withdraw from "../Withdraw/Schema";
|
import * as Withdraw from "../Withdraw/Schema";
|
||||||
import * as Pay from "../Pay/Schema";
|
import * as Pay from "../Pay/Schema";
|
||||||
import * as User from "../User/Schema";
|
import * as User from "../User/Schema";
|
||||||
|
|
@ -18,6 +18,7 @@ export type OpSchema = EntityShape & {
|
||||||
price: Price;
|
price: Price;
|
||||||
creatorId: ForeignKey<"user">;
|
creatorId: ForeignKey<"user">;
|
||||||
reason?: Text | null;
|
reason?: Text | null;
|
||||||
|
successAt?: Datetime | null;
|
||||||
iState?: IState | null;
|
iState?: IState | null;
|
||||||
};
|
};
|
||||||
export type OpAttr = keyof OpSchema;
|
export type OpAttr = keyof OpSchema;
|
||||||
|
|
@ -30,6 +31,7 @@ export type Schema = EntityShape & {
|
||||||
price: Price;
|
price: Price;
|
||||||
creatorId: ForeignKey<"user">;
|
creatorId: ForeignKey<"user">;
|
||||||
reason?: Text | null;
|
reason?: Text | null;
|
||||||
|
successAt?: Datetime | null;
|
||||||
iState?: IState | null;
|
iState?: IState | null;
|
||||||
withdraw?: Withdraw.Schema | null;
|
withdraw?: Withdraw.Schema | null;
|
||||||
pay: Pay.Schema;
|
pay: Pay.Schema;
|
||||||
|
|
@ -57,6 +59,7 @@ type AttrFilter = {
|
||||||
creatorId: Q_StringValue;
|
creatorId: Q_StringValue;
|
||||||
creator: User.Filter;
|
creator: User.Filter;
|
||||||
reason: Q_StringValue;
|
reason: Q_StringValue;
|
||||||
|
successAt: Q_DateValue;
|
||||||
iState: Q_EnumValue<IState>;
|
iState: Q_EnumValue<IState>;
|
||||||
sysAccountOper$refund: SysAccountOper.Filter & SubQueryPredicateMetadata;
|
sysAccountOper$refund: SysAccountOper.Filter & SubQueryPredicateMetadata;
|
||||||
accountOper$entity: AccountOper.Filter & SubQueryPredicateMetadata;
|
accountOper$entity: AccountOper.Filter & SubQueryPredicateMetadata;
|
||||||
|
|
@ -80,6 +83,7 @@ export type Projection = {
|
||||||
creatorId?: number;
|
creatorId?: number;
|
||||||
creator?: User.Projection;
|
creator?: User.Projection;
|
||||||
reason?: number;
|
reason?: number;
|
||||||
|
successAt?: number;
|
||||||
iState?: number;
|
iState?: number;
|
||||||
sysAccountOper$refund?: SysAccountOper.Selection & {
|
sysAccountOper$refund?: SysAccountOper.Selection & {
|
||||||
$entity: "sysAccountOper";
|
$entity: "sysAccountOper";
|
||||||
|
|
@ -134,6 +138,8 @@ export type SortAttr = {
|
||||||
creator: User.SortAttr;
|
creator: User.SortAttr;
|
||||||
} | {
|
} | {
|
||||||
reason: number;
|
reason: number;
|
||||||
|
} | {
|
||||||
|
successAt: number;
|
||||||
} | {
|
} | {
|
||||||
iState: number;
|
iState: number;
|
||||||
} | {
|
} | {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ export const desc = {
|
||||||
reason: {
|
reason: {
|
||||||
type: "text"
|
type: "text"
|
||||||
},
|
},
|
||||||
|
successAt: {
|
||||||
|
type: "datetime"
|
||||||
|
},
|
||||||
iState: {
|
iState: {
|
||||||
type: "enum",
|
type: "enum",
|
||||||
enumeration: ["refunding", "successful", "failed"]
|
enumeration: ["refunding", "successful", "failed"]
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{ "name": "帐户", "attr": { "pay": "关联支付", "price": "价格", "loss": "损耗", "withdraw": "关联提现", "meta": "metadata", "externalId": "外部退款流水号", "iState": "状态", "creator": "创建者", "reason": "原因", "opers": "相关账户操作" }, "action": { "succeed": "退款成功", "fail": "退款失败" }, "v": { "iState": { "refunding": "退款中", "successful": "退款成功", "failed": "退款失败" } } }
|
{ "name": "帐户", "attr": { "pay": "关联支付", "price": "价格", "loss": "损耗", "withdraw": "关联提现", "meta": "metadata", "externalId": "外部退款流水号", "iState": "状态", "creator": "创建者", "reason": "原因", "opers": "相关账户操作", "successAt": "退款成功时间" }, "action": { "succeed": "退款成功", "fail": "退款失败" }, "v": { "iState": { "refunding": "退款中", "successful": "退款成功", "failed": "退款失败" } } }
|
||||||
|
|
|
||||||
|
|
@ -322,7 +322,7 @@ const triggers = [
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const data = await payClazz.refund(refund);
|
const data = await payClazz.refund(refund, context);
|
||||||
if (data) {
|
if (data) {
|
||||||
assert(data.externalId);
|
assert(data.externalId);
|
||||||
const closeFn = context.openRootMode();
|
const closeFn = context.openRootMode();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ import { BRC } from '../types/RuntimeCxt';
|
||||||
* @param context
|
* @param context
|
||||||
* @param refunds
|
* @param refunds
|
||||||
*/
|
*/
|
||||||
export declare function updateWithdrawState(context: BRC, id: string): Promise<0 | 1>;
|
export declare function updateWithdrawState(context: BRC, id: string): Promise<1 | 0>;
|
||||||
declare const triggers: Trigger<EntityDict, 'withdraw', BRC>[];
|
declare const triggers: Trigger<EntityDict, 'withdraw', BRC>[];
|
||||||
export default triggers;
|
export default triggers;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { OakException, OpRecord } from 'oak-domain/lib/types';
|
import { OakException, OpRecord } from 'oak-domain/lib/types';
|
||||||
import { EntityDict } from '../oak-app-domain/index';
|
import { EntityDict } from '../oak-app-domain/index';
|
||||||
export declare class ExternalPrePayException<ED extends EntityDict> extends OakException<ED> {
|
export declare class ExternalPayUtilException<ED extends EntityDict> extends OakException<ED> {
|
||||||
reason: any;
|
reason: any;
|
||||||
constructor(reason: any, message?: string);
|
constructor(reason: any, message?: string);
|
||||||
getSerialData(): {
|
getSerialData(): {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { OakException } from 'oak-domain/lib/types';
|
import { OakException } from 'oak-domain/lib/types';
|
||||||
import makeDepedentException from './DependentExceptions';
|
import makeDepedentException from './DependentExceptions';
|
||||||
export class ExternalPrePayException extends OakException {
|
export class ExternalPayUtilException extends OakException {
|
||||||
reason;
|
reason;
|
||||||
constructor(reason, message) {
|
constructor(reason, message) {
|
||||||
super(message || '调用外部支付预下单接口失败');
|
super(message || '调用外部支付渠道接口失败');
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
getSerialData() {
|
getSerialData() {
|
||||||
|
|
@ -28,7 +28,7 @@ export function makeException(msg) {
|
||||||
const { name, message } = data;
|
const { name, message } = data;
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'ExternalPrePayException': {
|
case 'ExternalPrePayException': {
|
||||||
exception = new ExternalPrePayException(data.reason, message);
|
exception = new ExternalPayUtilException(data.reason, message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'RefundExceedMax': {
|
case 'RefundExceedMax': {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { EntityDict } from '../oak-app-domain';
|
import { EntityDict } from '../oak-app-domain';
|
||||||
import { BRC } from '../types/RuntimeCxt';
|
import { BRC } from '../types/RuntimeCxt';
|
||||||
type IState = EntityDict['pay']['OpSchema']['iState'];
|
type IState = EntityDict['pay']['OpSchema']['iState'];
|
||||||
|
type RefundIState = EntityDict['refund']['OpSchema']['iState'];
|
||||||
export default interface PayClazz {
|
export default interface PayClazz {
|
||||||
getAccountEntity(): [string, string];
|
getAccountEntity(): [string, string];
|
||||||
getAccountAmount(context: BRC): Promise<number>;
|
getAccountAmount(context: BRC): Promise<number>;
|
||||||
|
|
@ -16,8 +17,13 @@ export default interface PayClazz {
|
||||||
extra?: EntityDict['pay']['Update']['data'];
|
extra?: EntityDict['pay']['Update']['data'];
|
||||||
price?: number;
|
price?: number;
|
||||||
}>;
|
}>;
|
||||||
refund(refund: EntityDict['refund']['OpSchema']): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
closeRefund(refund: EntityDict['refund']['OpSchema']): Promise<void>;
|
refundId: string;
|
||||||
|
iState: RefundIState;
|
||||||
|
extra?: EntityDict['refund']['Update']['data'];
|
||||||
|
price?: number;
|
||||||
|
}>;
|
||||||
|
refund(refund: EntityDict['refund']['Schema'], context: BRC): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
getRefundState(refund: EntityDict['refund']['OpSchema']): Promise<[EntityDict['refund']['OpSchema']['iState'], EntityDict['refund']['Update']['data'] | undefined]>;
|
getRefundState(refund: EntityDict['refund']['OpSchema']): Promise<[EntityDict['refund']['OpSchema']['iState'], EntityDict['refund']['Update']['data'] | undefined]>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,18 @@ export default class Account implements PayClazz {
|
||||||
calcPayTax(): [number, string, string];
|
calcPayTax(): [number, string, string];
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
refund(refund: EntityDict['refund']['Schema']): Promise<undefined>;
|
refund(refund: EntityDict['refund']['Schema']): Promise<undefined>;
|
||||||
closeRefund(refund: EntityDict['refund']['Schema']): Promise<void>;
|
|
||||||
getRefundState(refund: EntityDict['refund']['Schema']): Promise<[EntityDict['refund']['Schema']['iState'], undefined]>;
|
getRefundState(refund: EntityDict['refund']['Schema']): Promise<[EntityDict['refund']['Schema']['iState'], undefined]>;
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
payId: string;
|
payId: string;
|
||||||
iState: string | null | undefined;
|
iState: string | null | undefined;
|
||||||
extra?: EntityDict['pay']['Update']['data'] | undefined;
|
extra?: EntityDict['pay']['Update']['data'] | undefined;
|
||||||
}>;
|
}>;
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: EntityDict['refund']['Update']['data'] | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
prepay(pay: EntityDict['pay']['Schema'], data: EntityDict['pay']['Update']['data'], context: BRC): Promise<void>;
|
prepay(pay: EntityDict['pay']['Schema'], data: EntityDict['pay']['Update']['data'], context: BRC): Promise<void>;
|
||||||
getState(pay: EntityDict['pay']['Schema']): Promise<[string, EntityDict['pay']['Update']['data']]>;
|
getState(pay: EntityDict['pay']['Schema']): Promise<[string, EntityDict['pay']['Update']['data']]>;
|
||||||
close(pay: EntityDict['pay']['Schema']): Promise<void>;
|
close(pay: EntityDict['pay']['Schema']): Promise<void>;
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,15 @@ export default class Account {
|
||||||
async refund(refund) {
|
async refund(refund) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async closeRefund(refund) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund) {
|
async getRefundState(refund) {
|
||||||
return ['refuding', undefined];
|
return ['refuding', undefined];
|
||||||
}
|
}
|
||||||
decodePayNotification(params, body) {
|
decodePayNotification(params, body) {
|
||||||
throw new Error("account类型的pay不需调用此接口");
|
throw new Error("account类型的pay不需调用此接口");
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params, body) {
|
||||||
|
throw new Error("account类型的pay不需调用此接口");
|
||||||
|
}
|
||||||
async prepay(pay, data, context) {
|
async prepay(pay, data, context) {
|
||||||
const { entity, entityId, price } = pay;
|
const { entity, entityId, price } = pay;
|
||||||
assert(entity === 'account' && entityId);
|
assert(entity === 'account' && entityId);
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,18 @@ export default class Offline implements PayClazz {
|
||||||
calcPayTax(price: number): [number, string, string];
|
calcPayTax(price: number): [number, string, string];
|
||||||
getRefundableAt(successTime: number): number;
|
getRefundableAt(successTime: number): number;
|
||||||
refund(refund: RefundOpSchema): Promise<UpdateOperationData | undefined>;
|
refund(refund: RefundOpSchema): Promise<UpdateOperationData | undefined>;
|
||||||
closeRefund(refund: RefundOpSchema): Promise<void>;
|
|
||||||
getRefundState(refund: RefundOpSchema): Promise<[PayOpSchema['iState'], PayUpdateData | undefined]>;
|
getRefundState(refund: RefundOpSchema): Promise<[PayOpSchema['iState'], PayUpdateData | undefined]>;
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
payId: string;
|
payId: string;
|
||||||
iState: string | null | undefined;
|
iState: string | null | undefined;
|
||||||
extra?: PayUpdateData | undefined;
|
extra?: PayUpdateData | undefined;
|
||||||
}>;
|
}>;
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: EntityDict['refund']['Update']['data'] | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
prepay(pay: PayOpSchema, data: PayUpdateData, context: BRC): Promise<void>;
|
prepay(pay: PayOpSchema, data: PayUpdateData, context: BRC): Promise<void>;
|
||||||
getState(pay: PayOpSchema): Promise<[string, PayUpdateData]>;
|
getState(pay: PayOpSchema): Promise<[string, PayUpdateData]>;
|
||||||
close(pay: PayOpSchema): Promise<void>;
|
close(pay: PayOpSchema): Promise<void>;
|
||||||
|
|
|
||||||
|
|
@ -49,10 +49,6 @@ export default class Offline {
|
||||||
// 啥也不做
|
// 啥也不做
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async closeRefund(refund) {
|
|
||||||
// 啥也不做
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund) {
|
async getRefundState(refund) {
|
||||||
const { iState } = refund;
|
const { iState } = refund;
|
||||||
assert(iState === 'refunding');
|
assert(iState === 'refunding');
|
||||||
|
|
@ -61,6 +57,9 @@ export default class Offline {
|
||||||
decodePayNotification(params, body) {
|
decodePayNotification(params, body) {
|
||||||
throw new Error("offline类型的pay不需调用此接口");
|
throw new Error("offline类型的pay不需调用此接口");
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params, body) {
|
||||||
|
throw new Error("offline类型的pay不需调用此接口");
|
||||||
|
}
|
||||||
async prepay(pay, data, context) {
|
async prepay(pay, data, context) {
|
||||||
data.phantom3 = Math.ceil(Math.random() * 1000000);
|
data.phantom3 = Math.ceil(Math.random() * 1000000);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import PayClazz from "../../../types/PayClazz";
|
||||||
import { BRC } from "../../../types/RuntimeCxt";
|
import { BRC } from "../../../types/RuntimeCxt";
|
||||||
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
||||||
import { EntityDict } from "../../../oak-app-domain";
|
import { EntityDict } from "../../../oak-app-domain";
|
||||||
import { OpSchema as OpRefund, UpdateOperationData as RefundUpdateData } from "../../../oak-app-domain/Refund/Schema";
|
import { OpSchema as OpRefund, UpdateOperationData as RefundUpdateData, Schema as Refund } from "../../../oak-app-domain/Refund/Schema";
|
||||||
import { Schema as WpProduct } from '../../../oak-app-domain/WpProduct/Schema';
|
import { Schema as WpProduct } from '../../../oak-app-domain/WpProduct/Schema';
|
||||||
import WechatPayDebug from './WechatPay.debug';
|
import WechatPayDebug from './WechatPay.debug';
|
||||||
export default class WechatPay extends WechatPayDebug implements PayClazz {
|
export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
|
|
@ -19,10 +19,9 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
static MIN_REFUND_DAYS_GAP: number;
|
static MIN_REFUND_DAYS_GAP: number;
|
||||||
static DEFAULT_REFUND_DAYS_GAP: number;
|
static DEFAULT_REFUND_DAYS_GAP: number;
|
||||||
constructor(wpProduct: WpProduct, appId: string);
|
constructor(wpProduct: WpProduct, appId: string);
|
||||||
refund(refund: OpRefund): Promise<RefundUpdateData | undefined>;
|
refund(refund: Refund, context: BRC): Promise<RefundUpdateData | undefined>;
|
||||||
closeRefund(refund: OpRefund): Promise<void>;
|
getRefundState(refund: OpRefund): Promise<[string | null | undefined, RefundUpdateData | undefined]>;
|
||||||
getRefundState(refund: OpRefund): Promise<[string | null | undefined, PayUpdateData | undefined]>;
|
private analyzeResult;
|
||||||
private analyzePrepayResult;
|
|
||||||
private caclRefundDeadline;
|
private caclRefundDeadline;
|
||||||
prepay(pay: Pay, data: PayUpdateData, context: BRC): Promise<void>;
|
prepay(pay: Pay, data: PayUpdateData, context: BRC): Promise<void>;
|
||||||
getState(pay: OpPay): Promise<[EntityDict['pay']['OpSchema']['iState'], PayUpdateData]>;
|
getState(pay: OpPay): Promise<[EntityDict['pay']['OpSchema']['iState'], PayUpdateData]>;
|
||||||
|
|
@ -32,5 +31,11 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
iState: EntityDict['pay']['OpSchema']['iState'];
|
iState: EntityDict['pay']['OpSchema']['iState'];
|
||||||
extra?: PayUpdateData;
|
extra?: PayUpdateData;
|
||||||
}>;
|
}>;
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: RefundUpdateData | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,18 @@ export declare function registerGetPayStateResult(payState: NonNullable<EntityDi
|
||||||
export default class WechatPay implements PayClazz {
|
export default class WechatPay implements PayClazz {
|
||||||
wpProduct: WpProduct;
|
wpProduct: WpProduct;
|
||||||
constructor(wpProduct: WpProduct);
|
constructor(wpProduct: WpProduct);
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: RefundUpdateData | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
getAccountEntity(): [string, string];
|
getAccountEntity(): [string, string];
|
||||||
getAccountAmount(context: BRC): Promise<number>;
|
getAccountAmount(context: BRC): Promise<number>;
|
||||||
calcTransferTax(price: number): [number, string, string];
|
calcTransferTax(price: number): [number, string, string];
|
||||||
calcRefundTax(price: number): [number, string, string];
|
calcRefundTax(price: number): [number, string, string];
|
||||||
calcPayTax(price: number): [number, string, string];
|
calcPayTax(price: number): [number, string, string];
|
||||||
refund(refund: Refund): Promise<RefundUpdateData | undefined>;
|
refund(refund: Refund, context: BRC): Promise<RefundUpdateData | undefined>;
|
||||||
closeRefund(refund: Refund): Promise<void>;
|
|
||||||
getRefundState(refund: Refund): Promise<[string | null | undefined, PayUpdateData | undefined]>;
|
getRefundState(refund: Refund): Promise<[string | null | undefined, PayUpdateData | undefined]>;
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
payId: string;
|
payId: string;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ export default class WechatPay {
|
||||||
constructor(wpProduct) {
|
constructor(wpProduct) {
|
||||||
this.wpProduct = wpProduct;
|
this.wpProduct = wpProduct;
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params, body) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
getAccountEntity() {
|
getAccountEntity() {
|
||||||
return ['wpAccount', this.wpProduct.wpAccountId];
|
return ['wpAccount', this.wpProduct.wpAccountId];
|
||||||
}
|
}
|
||||||
|
|
@ -49,14 +52,11 @@ export default class WechatPay {
|
||||||
assert(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
assert(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
||||||
return [Math.round(price * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId];
|
return [Math.round(price * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId];
|
||||||
}
|
}
|
||||||
async refund(refund) {
|
async refund(refund, context) {
|
||||||
return {
|
return {
|
||||||
externalId: Math.random().toString(),
|
externalId: Math.random().toString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async closeRefund(refund) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund) {
|
async getRefundState(refund) {
|
||||||
const r = Math.random();
|
const r = Math.random();
|
||||||
if (r < 0.5) {
|
if (r < 0.5) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import fs from 'fs';
|
||||||
import dayJs from 'dayjs';
|
import dayJs from 'dayjs';
|
||||||
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
||||||
import { compressTo32, decompressFrom32 } from 'oak-domain/lib/utils/uuid';
|
import { compressTo32, decompressFrom32 } from 'oak-domain/lib/utils/uuid';
|
||||||
import { ExternalPrePayException } from "../../../types/Exception";
|
import { ExternalPayUtilException } from "../../../types/Exception";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import { omit } from "oak-domain/lib/utils/lodash";
|
import { omit } from "oak-domain/lib/utils/lodash";
|
||||||
import WechatPayDebug from './WechatPay.debug';
|
import WechatPayDebug from './WechatPay.debug';
|
||||||
|
|
@ -14,6 +14,12 @@ const TRADE_STATE_MATRIX = {
|
||||||
'PAYERROR': 'closed',
|
'PAYERROR': 'closed',
|
||||||
'REVOKED': 'closed',
|
'REVOKED': 'closed',
|
||||||
};
|
};
|
||||||
|
const REFUND_STATE_MATRIX = {
|
||||||
|
'SUCCESS': "successful",
|
||||||
|
'CLOSED': "failed",
|
||||||
|
"ABNORMAL": "refunding",
|
||||||
|
"PROCESSING": 'refunding',
|
||||||
|
};
|
||||||
export default class WechatPay extends WechatPayDebug {
|
export default class WechatPay extends WechatPayDebug {
|
||||||
wechatPay;
|
wechatPay;
|
||||||
refundGapDays;
|
refundGapDays;
|
||||||
|
|
@ -45,20 +51,45 @@ export default class WechatPay extends WechatPayDebug {
|
||||||
cert_public_content: fs.readFileSync(this.publicKeyFilePath),
|
cert_public_content: fs.readFileSync(this.publicKeyFilePath),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
refund(refund) {
|
async refund(refund, context) {
|
||||||
throw new Error("Method not implemented.");
|
const { id, price, pay } = refund;
|
||||||
|
const serverUrl = context.composeAccessPath();
|
||||||
|
const endpoint = this.refundNotifyUrl;
|
||||||
|
const refundNotifyUrl = `${serverUrl}/endpoint/${endpoint}/${pay.id}`;
|
||||||
|
const result = await this.wechatPay.createRefund({
|
||||||
|
out_trade_no: compressTo32(pay.id),
|
||||||
|
out_refund_no: compressTo32(id),
|
||||||
|
notify_url: refundNotifyUrl,
|
||||||
|
amount: {
|
||||||
|
refund: price,
|
||||||
|
total: pay.price,
|
||||||
|
currency: 'CNY',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { refund_id } = this.analyzeResult(result);
|
||||||
|
return {
|
||||||
|
externalId: refund_id,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
closeRefund(refund) {
|
async getRefundState(refund) {
|
||||||
throw new Error("Method not implemented.");
|
const result = await this.wechatPay.queryRefundByOutRefundNo(compressTo32(refund.id));
|
||||||
|
const { status, success_time } = this.analyzeResult(result);
|
||||||
|
/**
|
||||||
|
* 【退款状态】 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
|
||||||
|
可选取值:
|
||||||
|
SUCCESS: 退款成功
|
||||||
|
CLOSED: 退款关闭
|
||||||
|
PROCESSING: 退款处理中
|
||||||
|
ABNORMAL: 退款异常
|
||||||
|
*/
|
||||||
|
const iState = REFUND_STATE_MATRIX[status];
|
||||||
|
return [iState, success_time ? { successAt: dayJs(success_time).millisecond() } : undefined];
|
||||||
}
|
}
|
||||||
getRefundState(refund) {
|
analyzeResult(result) {
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
analyzePrepayResult(result) {
|
|
||||||
const { success, data, } = result;
|
const { success, data, } = result;
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error(JSON.stringify(result));
|
console.error(JSON.stringify(result));
|
||||||
throw new ExternalPrePayException(result);
|
throw new ExternalPayUtilException(result);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +119,7 @@ export default class WechatPay extends WechatPayDebug {
|
||||||
total: pay.price,
|
total: pay.price,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { code_url } = this.analyzePrepayResult(result);
|
const { code_url } = this.analyzeResult(result);
|
||||||
data.externalId = code_url;
|
data.externalId = code_url;
|
||||||
data.meta = {
|
data.meta = {
|
||||||
codeUrl: code_url,
|
codeUrl: code_url,
|
||||||
|
|
@ -119,7 +150,7 @@ export default class WechatPay extends WechatPayDebug {
|
||||||
openid: wechatUser.openId,
|
openid: wechatUser.openId,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const prepayMeta = this.analyzePrepayResult(result);
|
const prepayMeta = this.analyzeResult(result);
|
||||||
const prepayId = prepayMeta.package.slice(11); // `prepay_id=${prepay_id}`
|
const prepayId = prepayMeta.package.slice(11); // `prepay_id=${prepay_id}`
|
||||||
data.externalId = prepayId;
|
data.externalId = prepayId;
|
||||||
data.meta = {
|
data.meta = {
|
||||||
|
|
@ -152,7 +183,7 @@ export default class WechatPay extends WechatPayDebug {
|
||||||
* USERPAYING:用户支付中(仅付款码支付会返回)
|
* USERPAYING:用户支付中(仅付款码支付会返回)
|
||||||
* PAYERROR:支付失败(仅付款码支付会返回)
|
* PAYERROR:支付失败(仅付款码支付会返回)
|
||||||
*/
|
*/
|
||||||
const { trade_state: tradeState, success_time } = this.analyzePrepayResult(result);
|
const { trade_state: tradeState, success_time } = this.analyzeResult(result);
|
||||||
const iState = TRADE_STATE_MATRIX[tradeState];
|
const iState = TRADE_STATE_MATRIX[tradeState];
|
||||||
assert(iState);
|
assert(iState);
|
||||||
const updateData = {
|
const updateData = {
|
||||||
|
|
@ -168,7 +199,7 @@ export default class WechatPay extends WechatPayDebug {
|
||||||
async close(pay) {
|
async close(pay) {
|
||||||
const outTradeNo = compressTo32(pay.id);
|
const outTradeNo = compressTo32(pay.id);
|
||||||
const result = await this.wechatPay.closeOrder(outTradeNo);
|
const result = await this.wechatPay.closeOrder(outTradeNo);
|
||||||
this.analyzePrepayResult(result);
|
this.analyzeResult(result);
|
||||||
}
|
}
|
||||||
async decodePayNotification(params, body) {
|
async decodePayNotification(params, body) {
|
||||||
const { resource } = body;
|
const { resource } = body;
|
||||||
|
|
@ -285,6 +316,59 @@ export default class WechatPay extends WechatPayDebug {
|
||||||
extra,
|
extra,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
async decodeRefundNotification(params, body) {
|
||||||
|
const { resource } = body;
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.log('decodeRefundNotification-resource', JSON.stringify(resource));
|
||||||
|
}
|
||||||
|
const { ciphertext, nonce, associated_data } = resource;
|
||||||
|
const result2 = this.wechatPay.decryptAesGcm({
|
||||||
|
ciphertext,
|
||||||
|
nonce,
|
||||||
|
apiV3Key: this.apiV3Key,
|
||||||
|
associatedData: associated_data,
|
||||||
|
});
|
||||||
|
const result = JSON.parse(result2);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.log('decodeRefundNotification-decrypt', JSON.stringify(result));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 对resource对象进行解密后,得到的资源对象示例
|
||||||
|
* https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html
|
||||||
|
* {
|
||||||
|
"mchid": "1900000100",
|
||||||
|
"transaction_id": "1008450740201411110005820873",
|
||||||
|
"out_trade_no": "20150806125346",
|
||||||
|
"refund_id": "50200207182018070300011301001",
|
||||||
|
"out_refund_no": "7752501201407033233368018",
|
||||||
|
"refund_status": "SUCCESS",
|
||||||
|
"success_time": "2018-06-08T10:34:56+08:00",
|
||||||
|
"user_received_account": "招商银行信用卡0403",
|
||||||
|
"amount" : {
|
||||||
|
"total": 999,
|
||||||
|
"refund": 999,
|
||||||
|
"payer_total": 999,
|
||||||
|
"payer_refund": 999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const { out_refund_no, mchid, refund_status, success_time, } = result;
|
||||||
|
const refundId = decompressFrom32(out_refund_no);
|
||||||
|
assert(mchid === this.mchId);
|
||||||
|
const iState = REFUND_STATE_MATRIX[refund_status];
|
||||||
|
assert(iState);
|
||||||
|
const extra = {
|
||||||
|
meta: omit(result, ['mchid',]),
|
||||||
|
};
|
||||||
|
if (iState === 'successful') {
|
||||||
|
extra.successAt = success_time;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
refundId,
|
||||||
|
iState,
|
||||||
|
extra,
|
||||||
|
};
|
||||||
|
}
|
||||||
getRefundableAt(successAt) {
|
getRefundableAt(successAt) {
|
||||||
return this.caclRefundDeadline(successAt);
|
return this.caclRefundDeadline(successAt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import WechatPay from './WechatPay';
|
import WechatPay from './WechatPay';
|
||||||
import WechatPayDebug from './WechatPay.debug';
|
import WechatPayDebug from './WechatPay.debug';
|
||||||
declare const _default: typeof WechatPayDebug | typeof WechatPay;
|
declare const _default: typeof WechatPay | typeof WechatPayDebug;
|
||||||
export default _default;
|
export default _default;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ export declare function getWithdrawCreateData(params: {
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
creator?: import("../oak-app-domain/User/Schema").UpdateOperation | undefined;
|
creator?: import("../oak-app-domain/User/Schema").UpdateOperation | undefined;
|
||||||
} & {
|
} & {
|
||||||
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
|
|
@ -26,8 +26,8 @@ export declare function getWithdrawCreateData(params: {
|
||||||
creator?: undefined;
|
creator?: undefined;
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
} & {
|
} & {
|
||||||
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
|
|
@ -40,8 +40,8 @@ export declare function getWithdrawCreateData(params: {
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
creator?: import("../oak-app-domain/User/Schema").UpdateOperation | undefined;
|
creator?: import("../oak-app-domain/User/Schema").UpdateOperation | undefined;
|
||||||
} & {
|
} & {
|
||||||
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
|
|
@ -54,8 +54,8 @@ export declare function getWithdrawCreateData(params: {
|
||||||
creator?: undefined;
|
creator?: undefined;
|
||||||
creatorId: string;
|
creatorId: string;
|
||||||
} & {
|
} & {
|
||||||
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
refund$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/Refund/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/Refund/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/Refund/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdraw" | "withdrawId">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdraw" | "withdrawId">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdraw" | "withdrawId">>)[] | undefined;
|
withdrawTransfer$withdraw?: import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">[]> | (import("oak-domain/lib/types").Operation<string, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").UpdateOperationData, "withdrawId" | "withdraw">, Omit<import("../oak-app-domain/WithdrawTransfer/Schema").Filter, "withdrawId" | "withdraw">> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/WithdrawTransfer/Schema").CreateOperationData, "withdrawId" | "withdraw">>)[] | undefined;
|
||||||
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
modiEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/ModiEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
operEntity$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/OperEntity/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
accountOper$entity?: import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">[]> | import("oak-domain/lib/types").Operation<"create", Omit<import("../oak-app-domain/AccountOper/Schema").CreateOperationData, "entity" | "entityId">>[] | undefined;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export declare class BackendRuntimeContext<ED extends EntityDict & BaseEntityDic
|
||||||
type?: number | undefined;
|
type?: number | undefined;
|
||||||
systemId?: number | undefined;
|
systemId?: number | undefined;
|
||||||
system?: import("../oak-app-domain/System/Schema").Projection | undefined;
|
system?: import("../oak-app-domain/System/Schema").Projection | undefined;
|
||||||
config?: number | import("oak-domain/lib/types").JsonProjection<import("../oak-app-domain/Application/Schema").WechatMpConfig | import("../oak-app-domain/Application/Schema").WebConfig | import("../oak-app-domain/Application/Schema").WechatPublicConfig | import("../oak-app-domain/Application/Schema").NativeConfig> | undefined;
|
config?: number | import("oak-domain/lib/types").JsonProjection<import("../oak-app-domain/Application/Schema").WebConfig | import("../oak-app-domain/Application/Schema").WechatMpConfig | import("../oak-app-domain/Application/Schema").WechatPublicConfig | import("../oak-app-domain/Application/Schema").NativeConfig> | undefined;
|
||||||
style?: number | import("oak-domain/lib/types").JsonProjection<import("oak-general-business/lib/types/Style").Style> | undefined;
|
style?: number | import("oak-domain/lib/types").JsonProjection<import("oak-general-business/lib/types/Style").Style> | undefined;
|
||||||
domainId?: number | undefined;
|
domainId?: number | undefined;
|
||||||
domain?: import("../oak-app-domain/Domain/Schema").Projection | undefined;
|
domain?: import("../oak-app-domain/Domain/Schema").Projection | undefined;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { String, Text, Price } from 'oak-domain/lib/types/DataType';
|
import { String, Text, Price, Datetime } from 'oak-domain/lib/types/DataType';
|
||||||
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
import { EntityShape } from 'oak-domain/lib/types/Entity';
|
||||||
import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
|
import { EntityDesc, ActionDef } from 'oak-domain/lib/types';
|
||||||
import { Schema as User } from './User';
|
import { Schema as User } from './User';
|
||||||
|
|
@ -14,6 +14,7 @@ export interface Schema extends EntityShape {
|
||||||
price: Price;
|
price: Price;
|
||||||
creator: User;
|
creator: User;
|
||||||
reason?: Text;
|
reason?: Text;
|
||||||
|
successAt?: Datetime;
|
||||||
opers: AccountOper[];
|
opers: AccountOper[];
|
||||||
}
|
}
|
||||||
export type IAction = 'succeed' | 'fail';
|
export type IAction = 'succeed' | 'fail';
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ exports.entityDesc = {
|
||||||
iState: '状态',
|
iState: '状态',
|
||||||
creator: '创建者',
|
creator: '创建者',
|
||||||
reason: '原因',
|
reason: '原因',
|
||||||
opers: '相关账户操作'
|
opers: '相关账户操作',
|
||||||
|
successAt: '退款成功时间'
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
succeed: '退款成功',
|
succeed: '退款成功',
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { Q_DateValue, Q_NumberValue, Q_StringValue, Q_EnumValue, NodeId, MakeFil
|
||||||
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
import { OneOf } from "oak-domain/lib/types/Polyfill";
|
||||||
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult, EntityShape } from "oak-domain/lib/types/Entity";
|
import { FormCreateData, FormUpdateData, DeduceAggregation, Operation as OakOperation, Selection as OakSelection, MakeAction as OakMakeAction, AggregationResult, EntityShape } from "oak-domain/lib/types/Entity";
|
||||||
import { Action, ParticularAction, IState } from "./Action";
|
import { Action, ParticularAction, IState } from "./Action";
|
||||||
import { Price, String, Text } from "oak-domain/lib/types/DataType";
|
import { Price, String, Text, Datetime } from "oak-domain/lib/types/DataType";
|
||||||
import * as Withdraw from "../Withdraw/Schema";
|
import * as Withdraw from "../Withdraw/Schema";
|
||||||
import * as Pay from "../Pay/Schema";
|
import * as Pay from "../Pay/Schema";
|
||||||
import * as User from "../User/Schema";
|
import * as User from "../User/Schema";
|
||||||
|
|
@ -18,6 +18,7 @@ export type OpSchema = EntityShape & {
|
||||||
price: Price;
|
price: Price;
|
||||||
creatorId: ForeignKey<"user">;
|
creatorId: ForeignKey<"user">;
|
||||||
reason?: Text | null;
|
reason?: Text | null;
|
||||||
|
successAt?: Datetime | null;
|
||||||
iState?: IState | null;
|
iState?: IState | null;
|
||||||
};
|
};
|
||||||
export type OpAttr = keyof OpSchema;
|
export type OpAttr = keyof OpSchema;
|
||||||
|
|
@ -30,6 +31,7 @@ export type Schema = EntityShape & {
|
||||||
price: Price;
|
price: Price;
|
||||||
creatorId: ForeignKey<"user">;
|
creatorId: ForeignKey<"user">;
|
||||||
reason?: Text | null;
|
reason?: Text | null;
|
||||||
|
successAt?: Datetime | null;
|
||||||
iState?: IState | null;
|
iState?: IState | null;
|
||||||
withdraw?: Withdraw.Schema | null;
|
withdraw?: Withdraw.Schema | null;
|
||||||
pay: Pay.Schema;
|
pay: Pay.Schema;
|
||||||
|
|
@ -57,6 +59,7 @@ type AttrFilter = {
|
||||||
creatorId: Q_StringValue;
|
creatorId: Q_StringValue;
|
||||||
creator: User.Filter;
|
creator: User.Filter;
|
||||||
reason: Q_StringValue;
|
reason: Q_StringValue;
|
||||||
|
successAt: Q_DateValue;
|
||||||
iState: Q_EnumValue<IState>;
|
iState: Q_EnumValue<IState>;
|
||||||
sysAccountOper$refund: SysAccountOper.Filter & SubQueryPredicateMetadata;
|
sysAccountOper$refund: SysAccountOper.Filter & SubQueryPredicateMetadata;
|
||||||
accountOper$entity: AccountOper.Filter & SubQueryPredicateMetadata;
|
accountOper$entity: AccountOper.Filter & SubQueryPredicateMetadata;
|
||||||
|
|
@ -80,6 +83,7 @@ export type Projection = {
|
||||||
creatorId?: number;
|
creatorId?: number;
|
||||||
creator?: User.Projection;
|
creator?: User.Projection;
|
||||||
reason?: number;
|
reason?: number;
|
||||||
|
successAt?: number;
|
||||||
iState?: number;
|
iState?: number;
|
||||||
sysAccountOper$refund?: SysAccountOper.Selection & {
|
sysAccountOper$refund?: SysAccountOper.Selection & {
|
||||||
$entity: "sysAccountOper";
|
$entity: "sysAccountOper";
|
||||||
|
|
@ -134,6 +138,8 @@ export type SortAttr = {
|
||||||
creator: User.SortAttr;
|
creator: User.SortAttr;
|
||||||
} | {
|
} | {
|
||||||
reason: number;
|
reason: number;
|
||||||
|
} | {
|
||||||
|
successAt: number;
|
||||||
} | {
|
} | {
|
||||||
iState: number;
|
iState: number;
|
||||||
} | {
|
} | {
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,9 @@ exports.desc = {
|
||||||
reason: {
|
reason: {
|
||||||
type: "text"
|
type: "text"
|
||||||
},
|
},
|
||||||
|
successAt: {
|
||||||
|
type: "datetime"
|
||||||
|
},
|
||||||
iState: {
|
iState: {
|
||||||
type: "enum",
|
type: "enum",
|
||||||
enumeration: ["refunding", "successful", "failed"]
|
enumeration: ["refunding", "successful", "failed"]
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{ "name": "帐户", "attr": { "pay": "关联支付", "price": "价格", "loss": "损耗", "withdraw": "关联提现", "meta": "metadata", "externalId": "外部退款流水号", "iState": "状态", "creator": "创建者", "reason": "原因", "opers": "相关账户操作" }, "action": { "succeed": "退款成功", "fail": "退款失败" }, "v": { "iState": { "refunding": "退款中", "successful": "退款成功", "failed": "退款失败" } } }
|
{ "name": "帐户", "attr": { "pay": "关联支付", "price": "价格", "loss": "损耗", "withdraw": "关联提现", "meta": "metadata", "externalId": "外部退款流水号", "iState": "状态", "creator": "创建者", "reason": "原因", "opers": "相关账户操作", "successAt": "退款成功时间" }, "action": { "succeed": "退款成功", "fail": "退款失败" }, "v": { "iState": { "refunding": "退款中", "successful": "退款成功", "failed": "退款失败" } } }
|
||||||
|
|
|
||||||
|
|
@ -325,7 +325,7 @@ const triggers = [
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const data = await payClazz.refund(refund);
|
const data = await payClazz.refund(refund, context);
|
||||||
if (data) {
|
if (data) {
|
||||||
(0, assert_1.default)(data.externalId);
|
(0, assert_1.default)(data.externalId);
|
||||||
const closeFn = context.openRootMode();
|
const closeFn = context.openRootMode();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { OakException, OpRecord } from 'oak-domain/lib/types';
|
import { OakException, OpRecord } from 'oak-domain/lib/types';
|
||||||
import { EntityDict } from '../oak-app-domain/index';
|
import { EntityDict } from '../oak-app-domain/index';
|
||||||
export declare class ExternalPrePayException<ED extends EntityDict> extends OakException<ED> {
|
export declare class ExternalPayUtilException<ED extends EntityDict> extends OakException<ED> {
|
||||||
reason: any;
|
reason: any;
|
||||||
constructor(reason: any, message?: string);
|
constructor(reason: any, message?: string);
|
||||||
getSerialData(): {
|
getSerialData(): {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
exports.makeException = exports.RefundExceedMax = exports.ExternalPrePayException = void 0;
|
exports.makeException = exports.RefundExceedMax = exports.ExternalPayUtilException = void 0;
|
||||||
const tslib_1 = require("tslib");
|
const tslib_1 = require("tslib");
|
||||||
const types_1 = require("oak-domain/lib/types");
|
const types_1 = require("oak-domain/lib/types");
|
||||||
const DependentExceptions_1 = tslib_1.__importDefault(require("./DependentExceptions"));
|
const DependentExceptions_1 = tslib_1.__importDefault(require("./DependentExceptions"));
|
||||||
class ExternalPrePayException extends types_1.OakException {
|
class ExternalPayUtilException extends types_1.OakException {
|
||||||
reason;
|
reason;
|
||||||
constructor(reason, message) {
|
constructor(reason, message) {
|
||||||
super(message || '调用外部支付预下单接口失败');
|
super(message || '调用外部支付渠道接口失败');
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
getSerialData() {
|
getSerialData() {
|
||||||
|
|
@ -18,7 +18,7 @@ class ExternalPrePayException extends types_1.OakException {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.ExternalPrePayException = ExternalPrePayException;
|
exports.ExternalPayUtilException = ExternalPayUtilException;
|
||||||
class RefundExceedMax extends types_1.OakException {
|
class RefundExceedMax extends types_1.OakException {
|
||||||
constructor(message) {
|
constructor(message) {
|
||||||
super(message || '可退款的总额不足');
|
super(message || '可退款的总额不足');
|
||||||
|
|
@ -34,7 +34,7 @@ function makeException(msg) {
|
||||||
const { name, message } = data;
|
const { name, message } = data;
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'ExternalPrePayException': {
|
case 'ExternalPrePayException': {
|
||||||
exception = new ExternalPrePayException(data.reason, message);
|
exception = new ExternalPayUtilException(data.reason, message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'RefundExceedMax': {
|
case 'RefundExceedMax': {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { EntityDict } from '../oak-app-domain';
|
import { EntityDict } from '../oak-app-domain';
|
||||||
import { BRC } from '../types/RuntimeCxt';
|
import { BRC } from '../types/RuntimeCxt';
|
||||||
type IState = EntityDict['pay']['OpSchema']['iState'];
|
type IState = EntityDict['pay']['OpSchema']['iState'];
|
||||||
|
type RefundIState = EntityDict['refund']['OpSchema']['iState'];
|
||||||
export default interface PayClazz {
|
export default interface PayClazz {
|
||||||
getAccountEntity(): [string, string];
|
getAccountEntity(): [string, string];
|
||||||
getAccountAmount(context: BRC): Promise<number>;
|
getAccountAmount(context: BRC): Promise<number>;
|
||||||
|
|
@ -16,8 +17,13 @@ export default interface PayClazz {
|
||||||
extra?: EntityDict['pay']['Update']['data'];
|
extra?: EntityDict['pay']['Update']['data'];
|
||||||
price?: number;
|
price?: number;
|
||||||
}>;
|
}>;
|
||||||
refund(refund: EntityDict['refund']['OpSchema']): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
closeRefund(refund: EntityDict['refund']['OpSchema']): Promise<void>;
|
refundId: string;
|
||||||
|
iState: RefundIState;
|
||||||
|
extra?: EntityDict['refund']['Update']['data'];
|
||||||
|
price?: number;
|
||||||
|
}>;
|
||||||
|
refund(refund: EntityDict['refund']['Schema'], context: BRC): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
getRefundState(refund: EntityDict['refund']['OpSchema']): Promise<[EntityDict['refund']['OpSchema']['iState'], EntityDict['refund']['Update']['data'] | undefined]>;
|
getRefundState(refund: EntityDict['refund']['OpSchema']): Promise<[EntityDict['refund']['OpSchema']['iState'], EntityDict['refund']['Update']['data'] | undefined]>;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ export declare const mergedProjection: {
|
||||||
type?: number | undefined;
|
type?: number | undefined;
|
||||||
systemId?: number | undefined;
|
systemId?: number | undefined;
|
||||||
system?: import("../oak-app-domain/System/Schema").Projection | undefined;
|
system?: import("../oak-app-domain/System/Schema").Projection | undefined;
|
||||||
config?: number | import("oak-domain/lib/types").JsonProjection<import("../oak-app-domain/Application/Schema").WechatMpConfig | import("../oak-app-domain/Application/Schema").WebConfig | import("../oak-app-domain/Application/Schema").WechatPublicConfig | import("../oak-app-domain/Application/Schema").NativeConfig> | undefined;
|
config?: number | import("oak-domain/lib/types").JsonProjection<import("../oak-app-domain/Application/Schema").WebConfig | import("../oak-app-domain/Application/Schema").WechatMpConfig | import("../oak-app-domain/Application/Schema").WechatPublicConfig | import("../oak-app-domain/Application/Schema").NativeConfig> | undefined;
|
||||||
style?: number | import("oak-domain/lib/types").JsonProjection<import("oak-general-business/lib/types/Style").Style> | undefined;
|
style?: number | import("oak-domain/lib/types").JsonProjection<import("oak-general-business/lib/types/Style").Style> | undefined;
|
||||||
domainId?: number | undefined;
|
domainId?: number | undefined;
|
||||||
domain?: import("../oak-app-domain/Domain/Schema").Projection | undefined;
|
domain?: import("../oak-app-domain/Domain/Schema").Projection | undefined;
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,18 @@ export default class Account implements PayClazz {
|
||||||
calcPayTax(): [number, string, string];
|
calcPayTax(): [number, string, string];
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
refund(refund: EntityDict['refund']['Schema']): Promise<undefined>;
|
refund(refund: EntityDict['refund']['Schema']): Promise<undefined>;
|
||||||
closeRefund(refund: EntityDict['refund']['Schema']): Promise<void>;
|
|
||||||
getRefundState(refund: EntityDict['refund']['Schema']): Promise<[EntityDict['refund']['Schema']['iState'], undefined]>;
|
getRefundState(refund: EntityDict['refund']['Schema']): Promise<[EntityDict['refund']['Schema']['iState'], undefined]>;
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
payId: string;
|
payId: string;
|
||||||
iState: string | null | undefined;
|
iState: string | null | undefined;
|
||||||
extra?: EntityDict['pay']['Update']['data'] | undefined;
|
extra?: EntityDict['pay']['Update']['data'] | undefined;
|
||||||
}>;
|
}>;
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: EntityDict['refund']['Update']['data'] | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
prepay(pay: EntityDict['pay']['Schema'], data: EntityDict['pay']['Update']['data'], context: BRC): Promise<void>;
|
prepay(pay: EntityDict['pay']['Schema'], data: EntityDict['pay']['Update']['data'], context: BRC): Promise<void>;
|
||||||
getState(pay: EntityDict['pay']['Schema']): Promise<[string, EntityDict['pay']['Update']['data']]>;
|
getState(pay: EntityDict['pay']['Schema']): Promise<[string, EntityDict['pay']['Update']['data']]>;
|
||||||
close(pay: EntityDict['pay']['Schema']): Promise<void>;
|
close(pay: EntityDict['pay']['Schema']): Promise<void>;
|
||||||
|
|
|
||||||
|
|
@ -26,15 +26,15 @@ class Account {
|
||||||
async refund(refund) {
|
async refund(refund) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async closeRefund(refund) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund) {
|
async getRefundState(refund) {
|
||||||
return ['refuding', undefined];
|
return ['refuding', undefined];
|
||||||
}
|
}
|
||||||
decodePayNotification(params, body) {
|
decodePayNotification(params, body) {
|
||||||
throw new Error("account类型的pay不需调用此接口");
|
throw new Error("account类型的pay不需调用此接口");
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params, body) {
|
||||||
|
throw new Error("account类型的pay不需调用此接口");
|
||||||
|
}
|
||||||
async prepay(pay, data, context) {
|
async prepay(pay, data, context) {
|
||||||
const { entity, entityId, price } = pay;
|
const { entity, entityId, price } = pay;
|
||||||
(0, assert_1.default)(entity === 'account' && entityId);
|
(0, assert_1.default)(entity === 'account' && entityId);
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,18 @@ export default class Offline implements PayClazz {
|
||||||
calcPayTax(price: number): [number, string, string];
|
calcPayTax(price: number): [number, string, string];
|
||||||
getRefundableAt(successTime: number): number;
|
getRefundableAt(successTime: number): number;
|
||||||
refund(refund: RefundOpSchema): Promise<UpdateOperationData | undefined>;
|
refund(refund: RefundOpSchema): Promise<UpdateOperationData | undefined>;
|
||||||
closeRefund(refund: RefundOpSchema): Promise<void>;
|
|
||||||
getRefundState(refund: RefundOpSchema): Promise<[PayOpSchema['iState'], PayUpdateData | undefined]>;
|
getRefundState(refund: RefundOpSchema): Promise<[PayOpSchema['iState'], PayUpdateData | undefined]>;
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
payId: string;
|
payId: string;
|
||||||
iState: string | null | undefined;
|
iState: string | null | undefined;
|
||||||
extra?: PayUpdateData | undefined;
|
extra?: PayUpdateData | undefined;
|
||||||
}>;
|
}>;
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: EntityDict['refund']['Update']['data'] | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
prepay(pay: PayOpSchema, data: PayUpdateData, context: BRC): Promise<void>;
|
prepay(pay: PayOpSchema, data: PayUpdateData, context: BRC): Promise<void>;
|
||||||
getState(pay: PayOpSchema): Promise<[string, PayUpdateData]>;
|
getState(pay: PayOpSchema): Promise<[string, PayUpdateData]>;
|
||||||
close(pay: PayOpSchema): Promise<void>;
|
close(pay: PayOpSchema): Promise<void>;
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,6 @@ class Offline {
|
||||||
// 啥也不做
|
// 啥也不做
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async closeRefund(refund) {
|
|
||||||
// 啥也不做
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund) {
|
async getRefundState(refund) {
|
||||||
const { iState } = refund;
|
const { iState } = refund;
|
||||||
(0, assert_1.default)(iState === 'refunding');
|
(0, assert_1.default)(iState === 'refunding');
|
||||||
|
|
@ -64,6 +60,9 @@ class Offline {
|
||||||
decodePayNotification(params, body) {
|
decodePayNotification(params, body) {
|
||||||
throw new Error("offline类型的pay不需调用此接口");
|
throw new Error("offline类型的pay不需调用此接口");
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params, body) {
|
||||||
|
throw new Error("offline类型的pay不需调用此接口");
|
||||||
|
}
|
||||||
async prepay(pay, data, context) {
|
async prepay(pay, data, context) {
|
||||||
data.phantom3 = Math.ceil(Math.random() * 1000000);
|
data.phantom3 = Math.ceil(Math.random() * 1000000);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import PayClazz from "../../../types/PayClazz";
|
||||||
import { BRC } from "../../../types/RuntimeCxt";
|
import { BRC } from "../../../types/RuntimeCxt";
|
||||||
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
||||||
import { EntityDict } from "../../../oak-app-domain";
|
import { EntityDict } from "../../../oak-app-domain";
|
||||||
import { OpSchema as OpRefund, UpdateOperationData as RefundUpdateData } from "../../../oak-app-domain/Refund/Schema";
|
import { OpSchema as OpRefund, UpdateOperationData as RefundUpdateData, Schema as Refund } from "../../../oak-app-domain/Refund/Schema";
|
||||||
import { Schema as WpProduct } from '../../../oak-app-domain/WpProduct/Schema';
|
import { Schema as WpProduct } from '../../../oak-app-domain/WpProduct/Schema';
|
||||||
import WechatPayDebug from './WechatPay.debug';
|
import WechatPayDebug from './WechatPay.debug';
|
||||||
export default class WechatPay extends WechatPayDebug implements PayClazz {
|
export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
|
|
@ -19,10 +19,9 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
static MIN_REFUND_DAYS_GAP: number;
|
static MIN_REFUND_DAYS_GAP: number;
|
||||||
static DEFAULT_REFUND_DAYS_GAP: number;
|
static DEFAULT_REFUND_DAYS_GAP: number;
|
||||||
constructor(wpProduct: WpProduct, appId: string);
|
constructor(wpProduct: WpProduct, appId: string);
|
||||||
refund(refund: OpRefund): Promise<RefundUpdateData | undefined>;
|
refund(refund: Refund, context: BRC): Promise<RefundUpdateData | undefined>;
|
||||||
closeRefund(refund: OpRefund): Promise<void>;
|
getRefundState(refund: OpRefund): Promise<[string | null | undefined, RefundUpdateData | undefined]>;
|
||||||
getRefundState(refund: OpRefund): Promise<[string | null | undefined, PayUpdateData | undefined]>;
|
private analyzeResult;
|
||||||
private analyzePrepayResult;
|
|
||||||
private caclRefundDeadline;
|
private caclRefundDeadline;
|
||||||
prepay(pay: Pay, data: PayUpdateData, context: BRC): Promise<void>;
|
prepay(pay: Pay, data: PayUpdateData, context: BRC): Promise<void>;
|
||||||
getState(pay: OpPay): Promise<[EntityDict['pay']['OpSchema']['iState'], PayUpdateData]>;
|
getState(pay: OpPay): Promise<[EntityDict['pay']['OpSchema']['iState'], PayUpdateData]>;
|
||||||
|
|
@ -32,5 +31,11 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
iState: EntityDict['pay']['OpSchema']['iState'];
|
iState: EntityDict['pay']['OpSchema']['iState'];
|
||||||
extra?: PayUpdateData;
|
extra?: PayUpdateData;
|
||||||
}>;
|
}>;
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: RefundUpdateData | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,18 @@ export declare function registerGetPayStateResult(payState: NonNullable<EntityDi
|
||||||
export default class WechatPay implements PayClazz {
|
export default class WechatPay implements PayClazz {
|
||||||
wpProduct: WpProduct;
|
wpProduct: WpProduct;
|
||||||
constructor(wpProduct: WpProduct);
|
constructor(wpProduct: WpProduct);
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
refundId: string;
|
||||||
|
iState: string | null | undefined;
|
||||||
|
extra?: RefundUpdateData | undefined;
|
||||||
|
price?: number | undefined;
|
||||||
|
}>;
|
||||||
getAccountEntity(): [string, string];
|
getAccountEntity(): [string, string];
|
||||||
getAccountAmount(context: BRC): Promise<number>;
|
getAccountAmount(context: BRC): Promise<number>;
|
||||||
calcTransferTax(price: number): [number, string, string];
|
calcTransferTax(price: number): [number, string, string];
|
||||||
calcRefundTax(price: number): [number, string, string];
|
calcRefundTax(price: number): [number, string, string];
|
||||||
calcPayTax(price: number): [number, string, string];
|
calcPayTax(price: number): [number, string, string];
|
||||||
refund(refund: Refund): Promise<RefundUpdateData | undefined>;
|
refund(refund: Refund, context: BRC): Promise<RefundUpdateData | undefined>;
|
||||||
closeRefund(refund: Refund): Promise<void>;
|
|
||||||
getRefundState(refund: Refund): Promise<[string | null | undefined, PayUpdateData | undefined]>;
|
getRefundState(refund: Refund): Promise<[string | null | undefined, PayUpdateData | undefined]>;
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
payId: string;
|
payId: string;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ class WechatPay {
|
||||||
constructor(wpProduct) {
|
constructor(wpProduct) {
|
||||||
this.wpProduct = wpProduct;
|
this.wpProduct = wpProduct;
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params, body) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
getAccountEntity() {
|
getAccountEntity() {
|
||||||
return ['wpAccount', this.wpProduct.wpAccountId];
|
return ['wpAccount', this.wpProduct.wpAccountId];
|
||||||
}
|
}
|
||||||
|
|
@ -54,14 +57,11 @@ class WechatPay {
|
||||||
(0, assert_1.default)(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
(0, assert_1.default)(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
||||||
return [Math.round(price * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId];
|
return [Math.round(price * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId];
|
||||||
}
|
}
|
||||||
async refund(refund) {
|
async refund(refund, context) {
|
||||||
return {
|
return {
|
||||||
externalId: Math.random().toString(),
|
externalId: Math.random().toString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async closeRefund(refund) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund) {
|
async getRefundState(refund) {
|
||||||
const r = Math.random();
|
const r = Math.random();
|
||||||
if (r < 0.5) {
|
if (r < 0.5) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,12 @@ const TRADE_STATE_MATRIX = {
|
||||||
'PAYERROR': 'closed',
|
'PAYERROR': 'closed',
|
||||||
'REVOKED': 'closed',
|
'REVOKED': 'closed',
|
||||||
};
|
};
|
||||||
|
const REFUND_STATE_MATRIX = {
|
||||||
|
'SUCCESS': "successful",
|
||||||
|
'CLOSED': "failed",
|
||||||
|
"ABNORMAL": "refunding",
|
||||||
|
"PROCESSING": 'refunding',
|
||||||
|
};
|
||||||
class WechatPay extends WechatPay_debug_1.default {
|
class WechatPay extends WechatPay_debug_1.default {
|
||||||
wechatPay;
|
wechatPay;
|
||||||
refundGapDays;
|
refundGapDays;
|
||||||
|
|
@ -48,20 +54,45 @@ class WechatPay extends WechatPay_debug_1.default {
|
||||||
cert_public_content: fs_1.default.readFileSync(this.publicKeyFilePath),
|
cert_public_content: fs_1.default.readFileSync(this.publicKeyFilePath),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
refund(refund) {
|
async refund(refund, context) {
|
||||||
throw new Error("Method not implemented.");
|
const { id, price, pay } = refund;
|
||||||
|
const serverUrl = context.composeAccessPath();
|
||||||
|
const endpoint = this.refundNotifyUrl;
|
||||||
|
const refundNotifyUrl = `${serverUrl}/endpoint/${endpoint}/${pay.id}`;
|
||||||
|
const result = await this.wechatPay.createRefund({
|
||||||
|
out_trade_no: (0, uuid_1.compressTo32)(pay.id),
|
||||||
|
out_refund_no: (0, uuid_1.compressTo32)(id),
|
||||||
|
notify_url: refundNotifyUrl,
|
||||||
|
amount: {
|
||||||
|
refund: price,
|
||||||
|
total: pay.price,
|
||||||
|
currency: 'CNY',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { refund_id } = this.analyzeResult(result);
|
||||||
|
return {
|
||||||
|
externalId: refund_id,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
closeRefund(refund) {
|
async getRefundState(refund) {
|
||||||
throw new Error("Method not implemented.");
|
const result = await this.wechatPay.queryRefundByOutRefundNo((0, uuid_1.compressTo32)(refund.id));
|
||||||
|
const { status, success_time } = this.analyzeResult(result);
|
||||||
|
/**
|
||||||
|
* 【退款状态】 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
|
||||||
|
可选取值:
|
||||||
|
SUCCESS: 退款成功
|
||||||
|
CLOSED: 退款关闭
|
||||||
|
PROCESSING: 退款处理中
|
||||||
|
ABNORMAL: 退款异常
|
||||||
|
*/
|
||||||
|
const iState = REFUND_STATE_MATRIX[status];
|
||||||
|
return [iState, success_time ? { successAt: (0, dayjs_1.default)(success_time).millisecond() } : undefined];
|
||||||
}
|
}
|
||||||
getRefundState(refund) {
|
analyzeResult(result) {
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
analyzePrepayResult(result) {
|
|
||||||
const { success, data, } = result;
|
const { success, data, } = result;
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error(JSON.stringify(result));
|
console.error(JSON.stringify(result));
|
||||||
throw new Exception_1.ExternalPrePayException(result);
|
throw new Exception_1.ExternalPayUtilException(result);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +122,7 @@ class WechatPay extends WechatPay_debug_1.default {
|
||||||
total: pay.price,
|
total: pay.price,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { code_url } = this.analyzePrepayResult(result);
|
const { code_url } = this.analyzeResult(result);
|
||||||
data.externalId = code_url;
|
data.externalId = code_url;
|
||||||
data.meta = {
|
data.meta = {
|
||||||
codeUrl: code_url,
|
codeUrl: code_url,
|
||||||
|
|
@ -122,7 +153,7 @@ class WechatPay extends WechatPay_debug_1.default {
|
||||||
openid: wechatUser.openId,
|
openid: wechatUser.openId,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const prepayMeta = this.analyzePrepayResult(result);
|
const prepayMeta = this.analyzeResult(result);
|
||||||
const prepayId = prepayMeta.package.slice(11); // `prepay_id=${prepay_id}`
|
const prepayId = prepayMeta.package.slice(11); // `prepay_id=${prepay_id}`
|
||||||
data.externalId = prepayId;
|
data.externalId = prepayId;
|
||||||
data.meta = {
|
data.meta = {
|
||||||
|
|
@ -155,7 +186,7 @@ class WechatPay extends WechatPay_debug_1.default {
|
||||||
* USERPAYING:用户支付中(仅付款码支付会返回)
|
* USERPAYING:用户支付中(仅付款码支付会返回)
|
||||||
* PAYERROR:支付失败(仅付款码支付会返回)
|
* PAYERROR:支付失败(仅付款码支付会返回)
|
||||||
*/
|
*/
|
||||||
const { trade_state: tradeState, success_time } = this.analyzePrepayResult(result);
|
const { trade_state: tradeState, success_time } = this.analyzeResult(result);
|
||||||
const iState = TRADE_STATE_MATRIX[tradeState];
|
const iState = TRADE_STATE_MATRIX[tradeState];
|
||||||
(0, assert_1.default)(iState);
|
(0, assert_1.default)(iState);
|
||||||
const updateData = {
|
const updateData = {
|
||||||
|
|
@ -171,7 +202,7 @@ class WechatPay extends WechatPay_debug_1.default {
|
||||||
async close(pay) {
|
async close(pay) {
|
||||||
const outTradeNo = (0, uuid_1.compressTo32)(pay.id);
|
const outTradeNo = (0, uuid_1.compressTo32)(pay.id);
|
||||||
const result = await this.wechatPay.closeOrder(outTradeNo);
|
const result = await this.wechatPay.closeOrder(outTradeNo);
|
||||||
this.analyzePrepayResult(result);
|
this.analyzeResult(result);
|
||||||
}
|
}
|
||||||
async decodePayNotification(params, body) {
|
async decodePayNotification(params, body) {
|
||||||
const { resource } = body;
|
const { resource } = body;
|
||||||
|
|
@ -288,6 +319,59 @@ class WechatPay extends WechatPay_debug_1.default {
|
||||||
extra,
|
extra,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
async decodeRefundNotification(params, body) {
|
||||||
|
const { resource } = body;
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.log('decodeRefundNotification-resource', JSON.stringify(resource));
|
||||||
|
}
|
||||||
|
const { ciphertext, nonce, associated_data } = resource;
|
||||||
|
const result2 = this.wechatPay.decryptAesGcm({
|
||||||
|
ciphertext,
|
||||||
|
nonce,
|
||||||
|
apiV3Key: this.apiV3Key,
|
||||||
|
associatedData: associated_data,
|
||||||
|
});
|
||||||
|
const result = JSON.parse(result2);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.log('decodeRefundNotification-decrypt', JSON.stringify(result));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 对resource对象进行解密后,得到的资源对象示例
|
||||||
|
* https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html
|
||||||
|
* {
|
||||||
|
"mchid": "1900000100",
|
||||||
|
"transaction_id": "1008450740201411110005820873",
|
||||||
|
"out_trade_no": "20150806125346",
|
||||||
|
"refund_id": "50200207182018070300011301001",
|
||||||
|
"out_refund_no": "7752501201407033233368018",
|
||||||
|
"refund_status": "SUCCESS",
|
||||||
|
"success_time": "2018-06-08T10:34:56+08:00",
|
||||||
|
"user_received_account": "招商银行信用卡0403",
|
||||||
|
"amount" : {
|
||||||
|
"total": 999,
|
||||||
|
"refund": 999,
|
||||||
|
"payer_total": 999,
|
||||||
|
"payer_refund": 999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const { out_refund_no, mchid, refund_status, success_time, } = result;
|
||||||
|
const refundId = (0, uuid_1.decompressFrom32)(out_refund_no);
|
||||||
|
(0, assert_1.default)(mchid === this.mchId);
|
||||||
|
const iState = REFUND_STATE_MATRIX[refund_status];
|
||||||
|
(0, assert_1.default)(iState);
|
||||||
|
const extra = {
|
||||||
|
meta: (0, lodash_1.omit)(result, ['mchid',]),
|
||||||
|
};
|
||||||
|
if (iState === 'successful') {
|
||||||
|
extra.successAt = success_time;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
refundId,
|
||||||
|
iState,
|
||||||
|
extra,
|
||||||
|
};
|
||||||
|
}
|
||||||
getRefundableAt(successAt) {
|
getRefundableAt(successAt) {
|
||||||
return this.caclRefundDeadline(successAt);
|
return this.caclRefundDeadline(successAt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
* 抽象组件在业务层根据EntityDict的重新声明
|
* 抽象组件在业务层根据EntityDict的重新声明
|
||||||
* by Xc 20230807
|
* by Xc 20230807
|
||||||
*/
|
*/
|
||||||
// @ts-nocheck
|
|
||||||
|
|
||||||
|
// @ts-nocheck
|
||||||
|
import React from 'react';
|
||||||
import { EntityDict } from '../oak-app-domain';
|
import { EntityDict } from '../oak-app-domain';
|
||||||
|
|
||||||
import { TableProps, PaginationProps } from 'antd';
|
import { TableProps, PaginationProps } from 'antd';
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export interface Schema extends EntityShape {
|
||||||
price: Price;
|
price: Price;
|
||||||
creator: User;
|
creator: User;
|
||||||
reason?: Text;
|
reason?: Text;
|
||||||
|
successAt?: Datetime;
|
||||||
opers: AccountOper[];
|
opers: AccountOper[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -53,7 +54,8 @@ export const entityDesc: EntityDesc<Schema, Action, '', {
|
||||||
iState: '状态',
|
iState: '状态',
|
||||||
creator: '创建者',
|
creator: '创建者',
|
||||||
reason: '原因',
|
reason: '原因',
|
||||||
opers: '相关账户操作'
|
opers: '相关账户操作',
|
||||||
|
successAt: '退款成功时间'
|
||||||
},
|
},
|
||||||
action: {
|
action: {
|
||||||
succeed: '退款成功',
|
succeed: '退款成功',
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,7 @@ const triggers: Trigger<EntityDict, 'refund', BRC>[] = [
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const data = await payClazz.refund(refund as EntityDict['refund']['Schema']);
|
const data = await payClazz.refund(refund as EntityDict['refund']['Schema'], context);
|
||||||
if (data) {
|
if (data) {
|
||||||
assert(data.externalId);
|
assert(data.externalId);
|
||||||
const closeFn = context.openRootMode();
|
const closeFn = context.openRootMode();
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import { OakException, OakUserException, OpRecord } from 'oak-domain/lib/types';
|
||||||
import { EntityDict } from '@oak-app-domain';
|
import { EntityDict } from '@oak-app-domain';
|
||||||
import makeDepedentException from './DependentExceptions';
|
import makeDepedentException from './DependentExceptions';
|
||||||
|
|
||||||
export class ExternalPrePayException<ED extends EntityDict> extends OakException<ED> {
|
export class ExternalPayUtilException<ED extends EntityDict> extends OakException<ED> {
|
||||||
reason: any;
|
reason: any;
|
||||||
constructor(reason: any, message?: string) {
|
constructor(reason: any, message?: string) {
|
||||||
super(message || '调用外部支付预下单接口失败');
|
super(message || '调用外部支付渠道接口失败');
|
||||||
this.reason = reason;
|
this.reason = reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ export function makeException<ED extends EntityDict>(msg: string | object) {
|
||||||
const { name, message } = data;
|
const { name, message } = data;
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'ExternalPrePayException': {
|
case 'ExternalPrePayException': {
|
||||||
exception = new ExternalPrePayException<ED>(data.reason, message);
|
exception = new ExternalPayUtilException<ED>(data.reason, message);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'RefundExceedMax': {
|
case 'RefundExceedMax': {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { EntityDict } from '../oak-app-domain';
|
import { EntityDict } from '../oak-app-domain';
|
||||||
import { BRC } from '../types/RuntimeCxt';
|
import { BRC } from '../types/RuntimeCxt';
|
||||||
type IState = EntityDict['pay']['OpSchema']['iState'];
|
type IState = EntityDict['pay']['OpSchema']['iState'];
|
||||||
|
type RefundIState = EntityDict['refund']['OpSchema']['iState'];
|
||||||
|
|
||||||
export default interface PayClazz {
|
export default interface PayClazz {
|
||||||
getAccountEntity(): [string, string];
|
getAccountEntity(): [string, string];
|
||||||
|
|
@ -26,10 +27,15 @@ export default interface PayClazz {
|
||||||
price?: number;
|
price?: number;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
// refund相关的待定
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
refund(refund: EntityDict['refund']['OpSchema']): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
refundId: string,
|
||||||
|
iState: RefundIState,
|
||||||
|
extra?: EntityDict['refund']['Update']['data'],
|
||||||
|
price?: number;
|
||||||
|
}>
|
||||||
|
|
||||||
closeRefund(refund: EntityDict['refund']['OpSchema']): Promise<void>;
|
// refund相关的待定
|
||||||
|
refund(refund: EntityDict['refund']['Schema'], context: BRC): Promise<EntityDict['refund']['Update']['data'] | undefined>;
|
||||||
|
|
||||||
getRefundableAt(successAt: number): number;
|
getRefundableAt(successAt: number): number;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,6 @@ export default class Account implements PayClazz {
|
||||||
async refund(refund: EntityDict['refund']['Schema']): Promise<undefined> {
|
async refund(refund: EntityDict['refund']['Schema']): Promise<undefined> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async closeRefund(refund: EntityDict['refund']['Schema']): Promise<void> {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund: EntityDict['refund']['Schema']): Promise<[EntityDict['refund']['Schema']['iState'], undefined]> {
|
async getRefundState(refund: EntityDict['refund']['Schema']): Promise<[EntityDict['refund']['Schema']['iState'], undefined]> {
|
||||||
return ['refuding', undefined];
|
return ['refuding', undefined];
|
||||||
}
|
}
|
||||||
|
|
@ -41,6 +38,10 @@ export default class Account implements PayClazz {
|
||||||
throw new Error("account类型的pay不需调用此接口");
|
throw new Error("account类型的pay不需调用此接口");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{ refundId: string; iState: string | null | undefined; extra?: EntityDict['refund']['Update']['data'] | undefined; price?: number | undefined; }> {
|
||||||
|
throw new Error("account类型的pay不需调用此接口");
|
||||||
|
}
|
||||||
|
|
||||||
async prepay(pay: EntityDict['pay']['Schema'], data: EntityDict['pay']['Update']['data'], context: BRC) {
|
async prepay(pay: EntityDict['pay']['Schema'], data: EntityDict['pay']['Update']['data'], context: BRC) {
|
||||||
const { entity, entityId, price } = pay;
|
const { entity, entityId, price } = pay;
|
||||||
assert(entity === 'account' && entityId);
|
assert(entity === 'account' && entityId);
|
||||||
|
|
|
||||||
|
|
@ -60,10 +60,6 @@ export default class Offline implements PayClazz {
|
||||||
// 啥也不做
|
// 啥也不做
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
async closeRefund(refund: RefundOpSchema): Promise<void> {
|
|
||||||
// 啥也不做
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund: RefundOpSchema): Promise<[PayOpSchema['iState'], PayUpdateData | undefined]> {
|
async getRefundState(refund: RefundOpSchema): Promise<[PayOpSchema['iState'], PayUpdateData | undefined]> {
|
||||||
const { iState } = refund;
|
const { iState } = refund;
|
||||||
assert(iState === 'refunding');
|
assert(iState === 'refunding');
|
||||||
|
|
@ -72,6 +68,9 @@ export default class Offline implements PayClazz {
|
||||||
decodePayNotification(params: Record<string, any>, body: any): Promise<{ payId: string; iState: string | null | undefined; extra?: PayUpdateData | undefined; }> {
|
decodePayNotification(params: Record<string, any>, body: any): Promise<{ payId: string; iState: string | null | undefined; extra?: PayUpdateData | undefined; }> {
|
||||||
throw new Error("offline类型的pay不需调用此接口");
|
throw new Error("offline类型的pay不需调用此接口");
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{ refundId: string; iState: string | null | undefined; extra?: EntityDict['refund']['Update']['data'] | undefined; price?: number | undefined; }> {
|
||||||
|
throw new Error("offline类型的pay不需调用此接口");
|
||||||
|
}
|
||||||
async prepay(pay: PayOpSchema, data: PayUpdateData, context: BRC): Promise<void> {
|
async prepay(pay: PayOpSchema, data: PayUpdateData, context: BRC): Promise<void> {
|
||||||
data.phantom3 = Math.ceil(Math.random() * 1000000);
|
data.phantom3 = Math.ceil(Math.random() * 1000000);
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ export default class WechatPay implements PayClazz {
|
||||||
constructor(wpProduct: WpProduct) {
|
constructor(wpProduct: WpProduct) {
|
||||||
this.wpProduct = wpProduct;
|
this.wpProduct = wpProduct;
|
||||||
}
|
}
|
||||||
|
decodeRefundNotification(params: Record<string, any>, body: any): Promise<{ refundId: string; iState: string | null | undefined; extra?: RefundUpdateData | undefined; price?: number | undefined; }> {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
getAccountEntity(): [string, string] {
|
getAccountEntity(): [string, string] {
|
||||||
return ['wpAccount', this.wpProduct.wpAccountId];
|
return ['wpAccount', this.wpProduct.wpAccountId];
|
||||||
}
|
}
|
||||||
|
|
@ -61,14 +64,11 @@ export default class WechatPay implements PayClazz {
|
||||||
assert(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
assert(typeof taxLossRatio === 'number', '微信渠道的手续费率未配置');
|
||||||
return [Math.round(price * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId!];
|
return [Math.round(price * taxLossRatio / 100), 'wpAccount', wpProduct.wpAccountId!];
|
||||||
}
|
}
|
||||||
async refund(refund: Refund): Promise<RefundUpdateData | undefined> {
|
async refund(refund: Refund, context: BRC): Promise<RefundUpdateData | undefined> {
|
||||||
return {
|
return {
|
||||||
externalId: Math.random().toString(),
|
externalId: Math.random().toString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async closeRefund(refund: Refund): Promise<void> {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async getRefundState(refund: Refund): Promise<[string | null | undefined, PayUpdateData | undefined]> {
|
async getRefundState(refund: Refund): Promise<[string | null | undefined, PayUpdateData | undefined]> {
|
||||||
const r = Math.random();
|
const r = Math.random();
|
||||||
if (r < 0.5) {
|
if (r < 0.5) {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import { OpSchema as OpPay, Schema as Pay, UpdateOperationData as PayUpdateData } from "../../../oak-app-domain/Pay/Schema";
|
import { OpSchema as OpPay, Schema as Pay, UpdateOperationData as PayUpdateData } from "../../../oak-app-domain/Pay/Schema";
|
||||||
import PayClazz from "../../../types/PayClazz";
|
import PayClazz from "../../../types/PayClazz";
|
||||||
import fs from 'fs';
|
import fs, { stat } from 'fs';
|
||||||
import dayJs from 'dayjs';
|
import dayJs from 'dayjs';
|
||||||
|
|
||||||
import { BRC } from "../../../types/RuntimeCxt";
|
import { BRC } from "../../../types/RuntimeCxt";
|
||||||
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
import { WechatPay as WechatPaySDK } from 'wechat-pay-nodejs';
|
||||||
import { compressTo32, decompressFrom32 } from 'oak-domain/lib/utils/uuid';
|
import { compressTo32, decompressFrom32 } from 'oak-domain/lib/utils/uuid';
|
||||||
import { ExternalPrePayException } from "../../../types/Exception";
|
import { ExternalPayUtilException } from "../../../types/Exception";
|
||||||
import { ApiResult, QueryOrderResult } from "wechat-pay-nodejs/typings";
|
import { ApiResult, QueryOrderResult } from "wechat-pay-nodejs/typings";
|
||||||
import assert from "assert";
|
import assert from "assert";
|
||||||
import { EntityDict } from "../../../oak-app-domain";
|
import { EntityDict } from "../../../oak-app-domain";
|
||||||
|
|
@ -24,6 +24,13 @@ const TRADE_STATE_MATRIX: Record<string, EntityDict['pay']['OpSchema']['iState']
|
||||||
'REVOKED': 'closed',
|
'REVOKED': 'closed',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const REFUND_STATE_MATRIX: Record<string, EntityDict['refund']['OpSchema']['iState']> = {
|
||||||
|
'SUCCESS': "successful",
|
||||||
|
'CLOSED': "failed",
|
||||||
|
"ABNORMAL": "refunding",
|
||||||
|
"PROCESSING": 'refunding',
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
export default class WechatPay extends WechatPayDebug implements PayClazz {
|
export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
wechatPay: WechatPaySDK;
|
wechatPay: WechatPaySDK;
|
||||||
|
|
@ -61,24 +68,51 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
refund(refund: OpRefund): Promise<RefundUpdateData | undefined> {
|
async refund(refund: Refund, context: BRC): Promise<RefundUpdateData | undefined> {
|
||||||
throw new Error("Method not implemented.");
|
const { id, price, pay } = refund;
|
||||||
|
const serverUrl = context.composeAccessPath();
|
||||||
|
const endpoint = this.refundNotifyUrl;
|
||||||
|
const refundNotifyUrl = `${serverUrl}/endpoint/${endpoint}/${pay.id}`;
|
||||||
|
const result = await this.wechatPay.createRefund({
|
||||||
|
out_trade_no: compressTo32(pay.id),
|
||||||
|
out_refund_no: compressTo32(id),
|
||||||
|
notify_url: refundNotifyUrl,
|
||||||
|
amount: {
|
||||||
|
refund: price!,
|
||||||
|
total: pay.price!,
|
||||||
|
currency: 'CNY',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { refund_id } = this.analyzeResult(result);
|
||||||
|
return {
|
||||||
|
externalId: refund_id,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
closeRefund(refund: OpRefund): Promise<void> {
|
async getRefundState(refund: OpRefund): Promise<[string | null | undefined, RefundUpdateData | undefined]> {
|
||||||
throw new Error("Method not implemented.");
|
const result = await this.wechatPay.queryRefundByOutRefundNo(compressTo32(refund.id!));
|
||||||
}
|
|
||||||
getRefundState(refund: OpRefund): Promise<[string | null | undefined, PayUpdateData | undefined]> {
|
const { status, success_time } = this.analyzeResult(result);
|
||||||
throw new Error("Method not implemented.");
|
/**
|
||||||
|
* 【退款状态】 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台(pay.weixin.qq.com)-交易中心,手动处理此笔退款。
|
||||||
|
可选取值:
|
||||||
|
SUCCESS: 退款成功
|
||||||
|
CLOSED: 退款关闭
|
||||||
|
PROCESSING: 退款处理中
|
||||||
|
ABNORMAL: 退款异常
|
||||||
|
*/
|
||||||
|
const iState = REFUND_STATE_MATRIX[status];
|
||||||
|
|
||||||
|
return [iState, success_time ? { successAt: dayJs(success_time).millisecond() } : undefined];
|
||||||
}
|
}
|
||||||
|
|
||||||
private analyzePrepayResult<R extends any>(result: ApiResult<R>) {
|
private analyzeResult<R extends any>(result: ApiResult<R>) {
|
||||||
const {
|
const {
|
||||||
success,
|
success,
|
||||||
data,
|
data,
|
||||||
} = result;
|
} = result;
|
||||||
if (!success) {
|
if (!success) {
|
||||||
console.error(JSON.stringify(result));
|
console.error(JSON.stringify(result));
|
||||||
throw new ExternalPrePayException(result);
|
throw new ExternalPayUtilException(result);
|
||||||
}
|
}
|
||||||
return data!;
|
return data!;
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +144,7 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
total: pay.price,
|
total: pay.price,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { code_url } = this.analyzePrepayResult(result);
|
const { code_url } = this.analyzeResult(result);
|
||||||
data.externalId = code_url;
|
data.externalId = code_url;
|
||||||
data.meta = {
|
data.meta = {
|
||||||
codeUrl: code_url,
|
codeUrl: code_url,
|
||||||
|
|
@ -141,7 +175,7 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
openid: wechatUser.openId!,
|
openid: wechatUser.openId!,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const prepayMeta = this.analyzePrepayResult(result);
|
const prepayMeta = this.analyzeResult(result);
|
||||||
const prepayId = prepayMeta.package.slice(11); // `prepay_id=${prepay_id}`
|
const prepayId = prepayMeta.package.slice(11); // `prepay_id=${prepay_id}`
|
||||||
data.externalId = prepayId;
|
data.externalId = prepayId;
|
||||||
data.meta = {
|
data.meta = {
|
||||||
|
|
@ -176,7 +210,7 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
* USERPAYING:用户支付中(仅付款码支付会返回)
|
* USERPAYING:用户支付中(仅付款码支付会返回)
|
||||||
* PAYERROR:支付失败(仅付款码支付会返回)
|
* PAYERROR:支付失败(仅付款码支付会返回)
|
||||||
*/
|
*/
|
||||||
const { trade_state: tradeState, success_time } = this.analyzePrepayResult(result) as QueryOrderResult & {
|
const { trade_state: tradeState, success_time } = this.analyzeResult(result) as QueryOrderResult & {
|
||||||
trade_state: string;
|
trade_state: string;
|
||||||
};
|
};
|
||||||
const iState: EntityDict['pay']['OpSchema']['iState'] = TRADE_STATE_MATRIX[tradeState];
|
const iState: EntityDict['pay']['OpSchema']['iState'] = TRADE_STATE_MATRIX[tradeState];
|
||||||
|
|
@ -195,7 +229,7 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
async close(pay: OpPay): Promise<void> {
|
async close(pay: OpPay): Promise<void> {
|
||||||
const outTradeNo = compressTo32(pay.id);
|
const outTradeNo = compressTo32(pay.id);
|
||||||
const result = await this.wechatPay.closeOrder(outTradeNo);
|
const result = await this.wechatPay.closeOrder(outTradeNo);
|
||||||
this.analyzePrepayResult(result);
|
this.analyzeResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
async decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
async decodePayNotification(params: Record<string, any>, body: any): Promise<{
|
||||||
|
|
@ -338,6 +372,82 @@ export default class WechatPay extends WechatPayDebug implements PayClazz {
|
||||||
extra,
|
extra,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async decodeRefundNotification(params: Record<string, any>, body: any): Promise<{ refundId: string; iState: string | null | undefined; extra?: RefundUpdateData | undefined; price?: number | undefined; }> {
|
||||||
|
const {
|
||||||
|
resource
|
||||||
|
} = body as {
|
||||||
|
resource: {
|
||||||
|
algorithm: string;
|
||||||
|
ciphertext: string;
|
||||||
|
associated_data: string;
|
||||||
|
original_type: string;
|
||||||
|
nonce: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.log('decodeRefundNotification-resource', JSON.stringify(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { ciphertext, nonce, associated_data } = resource;
|
||||||
|
const result2 = this.wechatPay.decryptAesGcm({
|
||||||
|
ciphertext,
|
||||||
|
nonce,
|
||||||
|
apiV3Key: this.apiV3Key,
|
||||||
|
associatedData: associated_data,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = JSON.parse(result2);
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
console.log('decodeRefundNotification-decrypt', JSON.stringify(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对resource对象进行解密后,得到的资源对象示例
|
||||||
|
* https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/refund-result-notice.html
|
||||||
|
* {
|
||||||
|
"mchid": "1900000100",
|
||||||
|
"transaction_id": "1008450740201411110005820873",
|
||||||
|
"out_trade_no": "20150806125346",
|
||||||
|
"refund_id": "50200207182018070300011301001",
|
||||||
|
"out_refund_no": "7752501201407033233368018",
|
||||||
|
"refund_status": "SUCCESS",
|
||||||
|
"success_time": "2018-06-08T10:34:56+08:00",
|
||||||
|
"user_received_account": "招商银行信用卡0403",
|
||||||
|
"amount" : {
|
||||||
|
"total": 999,
|
||||||
|
"refund": 999,
|
||||||
|
"payer_total": 999,
|
||||||
|
"payer_refund": 999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const {
|
||||||
|
out_refund_no,
|
||||||
|
mchid,
|
||||||
|
refund_status,
|
||||||
|
success_time,
|
||||||
|
} = result;
|
||||||
|
|
||||||
|
const refundId = decompressFrom32(out_refund_no);
|
||||||
|
assert(mchid === this.mchId);
|
||||||
|
const iState = REFUND_STATE_MATRIX[refund_status];
|
||||||
|
assert(iState);
|
||||||
|
|
||||||
|
const extra: RefundUpdateData = {
|
||||||
|
meta: omit(result, ['mchid', ]),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (iState === 'successful') {
|
||||||
|
extra.successAt = success_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
refundId,
|
||||||
|
iState,
|
||||||
|
extra,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
getRefundableAt(successAt: number): number {
|
getRefundableAt(successAt: number): number {
|
||||||
return this.caclRefundDeadline(successAt);
|
return this.caclRefundDeadline(successAt);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue