修改 用户属性表中userId从number到string
| | |
| | | "remark": "自动确认收货时间,从支付成功起算,单位:天" |
| | | }, |
| | | { |
| | | "keyName": "carbonratio", |
| | | "name": "碳积分兑换比例", |
| | | "data": "100", |
| | | "dataType": 0, |
| | | "remark": "商城碳积分支付:所需积分 = 订单金额 * carbonratio,默认 100" |
| | | }, |
| | | { |
| | | "keyName": "userAgreement", |
| | | "name": "用户协议", |
| | | "data": "<h3 style=\"text-align: center;\"><strong>用户协议</strong></h3><p><br></p><p>xxxxxx</p>", |
| | |
| | | export class MarketCouponUserEntity extends BaseEntity { |
| | | @Index() |
| | | @Column({ comment: '用户ID' }) |
| | | userId: number; |
| | | userId: string; |
| | | |
| | | @Index() |
| | | @Column({ comment: '优惠券ID' }) |
| | |
| | | * @param couponId |
| | | * @param userId |
| | | */ |
| | | async receive(couponId: number, userId: number) { |
| | | async receive(couponId: number, userId: string) { |
| | | // 检查优惠券 |
| | | await this.check(couponId); |
| | | // 检查用户是否已领取 |
| | |
| | | * @param userId |
| | | * @param order |
| | | */ |
| | | async checkAndUse(couponId: number, userId: number, order: OrderInfoEntity) { |
| | | async checkAndUse(couponId: number, userId: string, order: OrderInfoEntity) { |
| | | // 判断优惠券 |
| | | const couponInfo = await this.check(couponId); |
| | | // 判断用户 |
| | |
| | | * @param idcouponId |
| | | * @param userId |
| | | */ |
| | | async save(couponId: number, userId: number) { |
| | | async save(couponId: number, userId: string) { |
| | | const couponUser = new MarketCouponUserEntity(); |
| | | couponUser.userId = userId; |
| | | couponUser.couponId = couponId; |
| | |
| | | * @param couponId |
| | | * @param userId |
| | | */ |
| | | async check(couponId: number, userId: number) { |
| | | async check(couponId: number, userId: string) { |
| | | const info = await this.marketCouponUserEntity.findOneBy({ |
| | | couponId: Equal(couponId), |
| | | userId: Equal(userId), |
| | |
| | | * @param couponId |
| | | * @param userId |
| | | */ |
| | | async checkExist(couponId: number, userId: number) { |
| | | async checkExist(couponId: number, userId: string) { |
| | | const info = await this.marketCouponUserEntity.findOneBy({ |
| | | couponId: Equal(couponId), |
| | | userId: Equal(userId), |
| | |
| | | * @param couponId |
| | | * @param userId |
| | | */ |
| | | async use(couponId: number, userId: number) { |
| | | async use(couponId: number, userId: string) { |
| | | await this.marketCouponUserEntity.update( |
| | | { couponId: Equal(couponId), userId: Equal(userId) }, |
| | | { status: 1, useTime: new Date() } |
| | |
| | | entity: OrderInfoEntity, |
| | | service: OrderInfoService, |
| | | pageQueryOp: { |
| | | fieldEq: ['status'], |
| | | fieldEq: ['status','userId'], |
| | | where: ctx => { |
| | | return [ |
| | | // 过滤用户ID |
| | |
| | | remark: string; |
| | | title: string; |
| | | couponId: number; |
| | | payType?: number; |
| | | } |
| | | ) { |
| | | return this.ok( |
| | |
| | | await this.orderPayService.wxAppPay(orderId, this.ctx.user.id) |
| | | ); |
| | | } |
| | | |
| | | @Post('/carbonPay', { summary: '碳积分支付' }) |
| | | async carbonPay(@Body('orderId') orderId) { |
| | | return this.ok( |
| | | await this.orderPayService.carbonPay(orderId, this.ctx.user.id) |
| | | ); |
| | | } |
| | | } |
| | |
| | | export class OrderInfoEntity extends BaseEntity { |
| | | @Index() |
| | | @Column({ comment: '用户ID' }) |
| | | userId: number; |
| | | userId: string; |
| | | |
| | | @Column({ comment: '标题', nullable: true }) |
| | | title: string; |
| | | |
| | | @Column({ comment: '支付方式 0-待支付 1-微信 2-支付宝', default: 0 }) |
| | | @Column({ comment: '支付方式 0-待支付 1-微信 2-支付宝 3-碳积分', default: 0 }) |
| | | payType: number; |
| | | |
| | | @Column({ comment: '支付时间', type: 'datetime', nullable: true }) |
| | |
| | | * @param data |
| | | */ |
| | | async create(data: { |
| | | userId: number; |
| | | userId: string; |
| | | goodsList: OrderGoodsEntity[]; |
| | | addressId: number; |
| | | remark: string; |
| | | title: string; |
| | | couponId?: number; |
| | | payType?: number; |
| | | }) { |
| | | const address = await this.userAddressService.info(data.addressId); |
| | | const payType = Number(data.payType) || 0; |
| | | const order = { |
| | | userId: data.userId, |
| | | address, |
| | | remark: data.remark, |
| | | title: data.title, |
| | | goodsList: data.goodsList, |
| | | payType, |
| | | } as OrderInfoEntity; |
| | | // 检查库存 |
| | | await this.checkStock(data.goodsList); |
| | |
| | | // 生成订单号 |
| | | const orderNum = await this.generateOrderNum(order.id); |
| | | |
| | | // 更新订单 |
| | | await this.orderInfoEntity.update(order.id, { |
| | | orderNum, |
| | | payType, |
| | | }); |
| | | |
| | | // 保存订单商品 |
| | |
| | | * 物流信息 |
| | | * @param orderId |
| | | */ |
| | | async logistics(orderId: number, userId?: number) { |
| | | async logistics(orderId: number, userId?: string) { |
| | | const order: OrderInfoEntity = await this.info(orderId); |
| | | if (userId && order.userId != userId) { |
| | | throw new CoolCommException('非法操作'); |
| | |
| | | import { Init, Inject, Provide } from '@midwayjs/core'; |
| | | import { BaseService, CoolCommException } from '@cool-midway/core'; |
| | | import { BaseService, CoolCommException, CoolTransaction } from '@cool-midway/core'; |
| | | import { PluginService } from '../../plugin/service/info'; |
| | | import { OrderInfoService } from './info'; |
| | | import { UserWxService } from '../../user/service/wx'; |
| | | import BigNumber from 'bignumber.js'; |
| | | import { OrderInfoEntity } from '../entity/info'; |
| | | import { InjectEntityModel } from '@midwayjs/typeorm'; |
| | | import { Repository } from 'typeorm'; |
| | | import { QueryRunner, Repository } from 'typeorm'; |
| | | import { Action, OrderQueue } from '../queue/order'; |
| | | import { BaseSysParamService } from '../../base/service/sys/param'; |
| | | import { UserInfoEntity } from '../../user/entity/info'; |
| | | import { RecycleTransactionEntity } from '../../shop/entity/transaction'; |
| | | |
| | | /** |
| | | * 支付 |
| | |
| | | export class OrderPayService extends BaseService { |
| | | @InjectEntityModel(OrderInfoEntity) |
| | | orderInfoEntity: Repository<OrderInfoEntity>; |
| | | |
| | | @InjectEntityModel(UserInfoEntity) |
| | | userInfoEntity: Repository<UserInfoEntity>; |
| | | |
| | | @InjectEntityModel(RecycleTransactionEntity) |
| | | recycleTransactionEntity: Repository<RecycleTransactionEntity>; |
| | | |
| | | @Inject() |
| | | pluginService: PluginService; |
| | |
| | | /** |
| | | * 支付成功 |
| | | * @param orderNum 订单号 |
| | | * @param payType 支付方式 0-待支付 1-微信 2-支付宝 |
| | | * @param payType 支付方式 0-待支付 1-微信 2-支付宝 3-碳积分 |
| | | */ |
| | | async paySuccess(orderNum: string, payType: number) { |
| | | const order = await this.orderInfoService.getByOrderNum(orderNum); |
| | |
| | | await this.orderInfoEntity.update(order.id, { |
| | | payType, |
| | | status: 1, |
| | | payTime: order.payTime, |
| | | payTime: new Date(), |
| | | }); |
| | | // 发送自动确认收货队列 |
| | | const orderConfirm = await this.baseSysParamService.dataByKey( |
| | |
| | | * @param userId |
| | | * @param orderId |
| | | */ |
| | | async wxMiniPay(orderId: number, userId: number) { |
| | | async wxMiniPay(orderId: number, userId: string) { |
| | | await this.orderInfoEntity.update(orderId, { wxType: 0 }); |
| | | return await this.wxJSAPI(orderId, userId, 0); |
| | | } |
| | |
| | | * @param userId |
| | | * @param orderId |
| | | */ |
| | | async wxMpPay(orderId: number, userId: number) { |
| | | async wxMpPay(orderId: number, userId: string) { |
| | | await this.orderInfoEntity.update(orderId, { wxType: 1 }); |
| | | return await this.wxJSAPI(orderId, userId, 1); |
| | | } |
| | |
| | | * @param userId |
| | | * @returns |
| | | */ |
| | | async wxAppPay(orderId: number, userId: number) { |
| | | async wxAppPay(orderId: number, userId: string) { |
| | | const appid = await this.getAppidByType(2); |
| | | |
| | | const { config, instance } = await this.wxPayInstance(appid); |
| | |
| | | * @param userId |
| | | * @returns |
| | | */ |
| | | async getOrder(orderId: number, userId: number) { |
| | | async getOrder(orderId: number, userId: string) { |
| | | const order: OrderInfoEntity = await this.orderInfoService.info(orderId); |
| | | if (!order || order.status != 0 || order.userId != userId) { |
| | | throw new CoolCommException('订单不存在或不是可以支付的状态'); |
| | |
| | | * @param type 0-小程序 1-公众号 2-App |
| | | * @returns |
| | | */ |
| | | async wxJSAPI(orderId: number, userId: number, type = 0) { |
| | | async wxJSAPI(orderId: number, userId: string, type = 0) { |
| | | const order = await this.getOrder(orderId, userId); |
| | | const openid = await this.userWxService.getOpenid(userId, type); |
| | | |
| | |
| | | } |
| | | throw new CoolCommException(result.message); |
| | | } |
| | | |
| | | /** |
| | | * 读取碳积分兑换比例,默认 100 |
| | | */ |
| | | async getCarbonRatio() { |
| | | try { |
| | | const value = await this.baseSysParamService.dataByKey('carbonratio'); |
| | | const ratio = Number(value); |
| | | if (ratio > 0) { |
| | | return ratio; |
| | | } |
| | | } catch (e) {} |
| | | return 100; |
| | | } |
| | | |
| | | /** |
| | | * 碳积分支付:不调用外部渠道 |
| | | * 扣减积分 = 订单实付金额 * carbonratio |
| | | */ |
| | | @CoolTransaction() |
| | | async carbonPay(orderId: number, userId: string, queryRunner?: QueryRunner) { |
| | | if (!queryRunner) { |
| | | throw new CoolCommException('事务启动失败'); |
| | | } |
| | | |
| | | const manager = queryRunner.manager; |
| | | const order = await manager.findOne(OrderInfoEntity, { |
| | | where: { id: orderId }, |
| | | }); |
| | | if (!order || order.status != 0 || order.userId != userId) { |
| | | throw new CoolCommException('订单不存在或不是可以支付的状态'); |
| | | } |
| | | |
| | | const user = await manager.findOne(UserInfoEntity, { |
| | | where: { unionid: userId }, |
| | | }); |
| | | if (!user) { |
| | | throw new CoolCommException('用户不存在'); |
| | | } |
| | | |
| | | const ratio = await this.getCarbonRatio(); |
| | | const payAmount = new BigNumber(order.price).minus(order.discountPrice || 0); |
| | | const carbonCost = payAmount.multipliedBy(ratio).toNumber(); |
| | | |
| | | if (Number(user.carbonBalance || 0) < carbonCost) { |
| | | throw new CoolCommException('碳积分不足'); |
| | | } |
| | | |
| | | const dec = await manager |
| | | .createQueryBuilder() |
| | | .update(UserInfoEntity) |
| | | .set({ carbonBalance: () => `carbonBalance - ${carbonCost}` }) |
| | | .where('id = :id AND carbonBalance >= :cost', { |
| | | id: userId, |
| | | cost: carbonCost, |
| | | }) |
| | | .execute(); |
| | | if (!dec.affected) { |
| | | throw new CoolCommException('碳积分不足'); |
| | | } |
| | | |
| | | await manager.update(OrderInfoEntity, order.id, { |
| | | payType: 3, |
| | | status: 1, |
| | | payTime: new Date(), |
| | | }); |
| | | |
| | | await manager.save(RecycleTransactionEntity, { |
| | | userId: user.unionid || String(userId), |
| | | departmentId: user.departmentId, |
| | | type: '支出', |
| | | amount: carbonCost, |
| | | sourceType: '商城', |
| | | remark: `商城订单 ${order.orderNum} 碳积分支付`, |
| | | orderId: order.orderNum, |
| | | }); |
| | | |
| | | const orderConfirm = await this.baseSysParamService.dataByKey('orderConfirm'); |
| | | this.orderQueue.add( |
| | | { orderId: order.id, action: Action.CONFIRM }, |
| | | { |
| | | delay: orderConfirm * 60 * 60 * 1000, |
| | | } |
| | | ); |
| | | |
| | | return true; |
| | | } |
| | | } |
| | |
| | | }; |
| | | await this.userInfoEntity.insert(user); |
| | | } |
| | | return this.token({ id: user.id }); |
| | | return this.token({ id: user.unionid }); |
| | | } |
| | | |
| | | /** |
| | |
| | | const find: any = { openid: wxUserInfo.openid }; |
| | | let wxInfo: any = await this.userWxEntity.findOneBy(find); |
| | | if (wxInfo) { |
| | | wxUserInfo.id = wxInfo.id; |
| | | wxUserInfo.id = wxInfo.unionid; |
| | | } |
| | | return this.userWxEntity.save({ |
| | | ...wxUserInfo, |
| | |
| | | }; |
| | | await this.userInfoEntity.insert(userInfo); |
| | | } |
| | | return this.token({ id: userInfo.id }); |
| | | return this.token({ id: userInfo.unionid }); |
| | | } |
| | | |
| | | /** |
| | |
| | | const userInfo = await this.userInfoEntity.findOneBy({ |
| | | id: info['id'], |
| | | }); |
| | | return this.token({ id: userInfo.id }); |
| | | return this.token({ id: userInfo?.unionid }); |
| | | } catch (e) { |
| | | throw new CoolCommException( |
| | | '刷新token失败,请检查refreshToken是否正确或过期' |
| | |
| | | |
| | | if (user && user.password == md5(password)) { |
| | | return this.token({ |
| | | id: user.id, |
| | | id: user.unionid, |
| | | }); |
| | | } else { |
| | | throw new CoolCommException('账号或密码错误'); |
| | |
| | | */ |
| | | async generateToken(info, isRefresh = false) { |
| | | const { expire, refreshExpire, secret } = this.jwtConfig; |
| | | const user = await this.userInfoEntity.findOneBy({ id: Equal(info.id) }); |
| | | const user = await this.userInfoEntity.findOneBy({ unionid: Equal(info.unionid) }); |
| | | const tokenInfo = { |
| | | isRefresh, |
| | | ...info, |
| | |
| | | */ |
| | | async generateSorterToken(info, isRefresh = false) { |
| | | const { expire, refreshExpire, secret } = this.jwtConfig; |
| | | const user = await this.basicdataSorterEntity.findOneBy({ businessId: Equal(info.id) }); |
| | | const user = await this.basicdataSorterEntity.findOneBy({ businessId: Equal(info.unionid) }); |
| | | const tokenInfo = { |
| | | isRefresh, |
| | | ...info, |
| | |
| | | * @param userId |
| | | * @param type 0-小程序 1-公众号 2-App |
| | | */ |
| | | async getOpenid(userId: number, type = 0) { |
| | | async getOpenid(userId: string, type = 0) { |
| | | const user = await this.userInfoEntity.findOneBy({ |
| | | id: Equal(userId), |
| | | unionid: Equal(userId), |
| | | status: 1, |
| | | }); |
| | | if (!user) { |