full app
This commit is contained in:
@@ -14,6 +14,7 @@ const {
|
||||
consumeFreeCreation,
|
||||
freeCreationLimitResponse
|
||||
} = require('../../../utils/freeCreationLimit')
|
||||
const { canUseFreeBillboard, consumeFreeBillboard } = require('../../../utils/billboardFreeLimit')
|
||||
const {
|
||||
PROJECT_ACCEPT_RATE,
|
||||
PROJECT_COMPLETION_COMMISSION_RATE,
|
||||
@@ -646,24 +647,20 @@ const initiateAdvertisingPayment = async (req, res) => {
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (item.name === 'free' && item.price === 0) {
|
||||
if (user.daily_free_request > 0 && canUseFreeCreation(user)) {
|
||||
const consumed = await consumeFreeCreation(user)
|
||||
if (!consumed.ok) {
|
||||
return res.status(403).json(freeCreationLimitResponse())
|
||||
}
|
||||
user.daily_free_request -= 1
|
||||
if (canUseFreeBillboard(user)) {
|
||||
await consumeFreeBillboard(user)
|
||||
await user.save()
|
||||
const project = await ProjectModel.findById(advertisingId)
|
||||
const project = await AdvertisingModel.findById(advertisingId)
|
||||
if (!project) {
|
||||
res.status(404).send('Project not found')
|
||||
res.status(404).send('Advertising not found')
|
||||
return
|
||||
}
|
||||
project.payment_status = 'done' // Set project status to 'done'
|
||||
project.status = await resolveApprovalStatus(userId, 'temp_accept') // Set project status to 'done'
|
||||
await project.save()
|
||||
res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
res.status(200).json({ message: 'بیلبورد رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
} else {
|
||||
res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کردهاید.' })
|
||||
res.status(403).json({ message: 'سقف ۲۰۰ بیلبورد رایگان شما به پایان رسیده است.' })
|
||||
}
|
||||
} else {
|
||||
const response = await axios.post(
|
||||
@@ -802,24 +799,20 @@ const republishAdvertisingPayment = async (req, res) => {
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (item.name === 'free' && item.price === 0) {
|
||||
if (user.daily_free_request > 0 && canUseFreeCreation(user)) {
|
||||
const consumed = await consumeFreeCreation(user)
|
||||
if (!consumed.ok) {
|
||||
return res.status(403).json(freeCreationLimitResponse())
|
||||
}
|
||||
user.daily_free_request -= 1
|
||||
if (canUseFreeBillboard(user)) {
|
||||
await consumeFreeBillboard(user)
|
||||
await user.save()
|
||||
const project = await ProjectModel.findById(advertisingId)
|
||||
const project = await AdvertisingModel.findById(advertisingId)
|
||||
if (!project) {
|
||||
res.status(404).send('Project not found')
|
||||
res.status(404).send('Advertising not found')
|
||||
return
|
||||
}
|
||||
project.payment_status = 'done' // Set project status to 'done'
|
||||
project.status = await resolveApprovalStatus(userId, 'temp_accept') // Set project status to 'done'
|
||||
await project.save()
|
||||
res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
res.status(200).json({ message: 'بیلبورد رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
} else {
|
||||
res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کردهاید.' })
|
||||
res.status(403).json({ message: 'سقف ۲۰۰ بیلبورد رایگان شما به پایان رسیده است.' })
|
||||
}
|
||||
} else {
|
||||
const response = await axios.post(
|
||||
|
||||
@@ -9,14 +9,16 @@ const NotificationModel = require('../../../models/NotificationModel')
|
||||
const UserModel = require('../../../models/UserModel')
|
||||
const AdvertisingTypeModel = require('../../../models/AdvertisingTypeModel')
|
||||
const AdvertisingModel = require('../../../models/AdvertisingModel')
|
||||
const { canUseFreeBillboard, consumeFreeBillboard } = require('../../../utils/billboardFreeLimit')
|
||||
const OfferTypeModel = require('../../../models/OfferTypeModel')
|
||||
const OfferModel = require('../../../models/OfferModel')
|
||||
const { default: axios } = require('axios')
|
||||
const WalletTransactionModel = require('../../../models/WalletTransactionModel')
|
||||
const { PROJECT_ACCEPT_RATE, PROJECT_COMPLETION_COMMISSION_RATE, creditProjectShare } = require('../../../utils/projectCommission')
|
||||
const { isVerifiedBadge } = require('../../../utils/verifyBadge')
|
||||
const { resolveWalletSplit, debitWalletForPurchase } = require('../../../utils/walletSplit')
|
||||
|
||||
const OFFER_COMMISSION_RATE = 0.3
|
||||
const OFFER_COMMISSION_RATE = 0.5
|
||||
|
||||
const apiKey =
|
||||
process.env.ZARINPAL_MERCHANT_ID ||
|
||||
@@ -285,6 +287,7 @@ const paymentRequestAcceptWeb = async (req, res) => {
|
||||
}
|
||||
|
||||
const requestId = req.body.requestId
|
||||
const platform = req.body.platform
|
||||
const request = await RequestModel.findById(requestId)
|
||||
if (!request) {
|
||||
return res.status(404).json({ error: 'Request not found' })
|
||||
@@ -300,13 +303,14 @@ const paymentRequestAcceptWeb = async (req, res) => {
|
||||
return res.status(500).json({ error: true, message: 'آدرس بازگشت پرداخت تنظیم نشده است' })
|
||||
}
|
||||
|
||||
const platformSuffix = platform ? `&platform=${encodeURIComponent(platform)}` : ''
|
||||
const response = await axios.post(
|
||||
'https://api.zarinpal.com/pg/v4/payment/request.json',
|
||||
{
|
||||
merchant_id: apiKey,
|
||||
amount: toRial(acceptAmount),
|
||||
description: `پرداخت پذیرش همکاری برای پروژه ${project.title || projectId}`,
|
||||
callback_url: `${callbackBase}/projects/payment-request-step-one-callback/web?projectId=${projectId}&requestId=${requestId}&userId=${userId}`
|
||||
callback_url: `${callbackBase}/projects/payment-request-step-one-callback/web?projectId=${projectId}&requestId=${requestId}&userId=${userId}${platformSuffix}`
|
||||
},
|
||||
{ headers: { 'Content-Type': 'application/json' }, timeout: 20000 }
|
||||
)
|
||||
@@ -328,8 +332,14 @@ const paymentRequestAcceptWeb = async (req, res) => {
|
||||
}
|
||||
|
||||
const paymentRequestAcceptWebCallback = async (req, res) => {
|
||||
const { Authority, Status, projectId, requestId, userId } = req.query
|
||||
const failRedirect = `${process.env.APP_SITE}/projects/payment/failed?projectId=${projectId || ''}`
|
||||
const { Authority, Status, projectId, requestId, userId, platform } = req.query
|
||||
const isAndroid = platform === 'android'
|
||||
const failRedirect = isAndroid
|
||||
? `modstagram://FailedPay?type=steps&projectId=${projectId || ''}`
|
||||
: `${process.env.APP_SITE}/projects/payment/failed?projectId=${projectId || ''}`
|
||||
const successRedirect = isAndroid
|
||||
? `modstagram://SuccessPay?type=steps&projectId=${projectId || ''}&requestId=${requestId || ''}`
|
||||
: `${process.env.APP_SITE}/projects/payment/success?projectId=${projectId}&type=accept`
|
||||
|
||||
try {
|
||||
if (Status !== 'OK') return res.redirect(failRedirect)
|
||||
@@ -339,7 +349,7 @@ const paymentRequestAcceptWebCallback = async (req, res) => {
|
||||
if (!request || !project) return res.redirect(failRedirect)
|
||||
|
||||
if (project.status === 'ongoing') {
|
||||
return res.redirect(`${process.env.APP_SITE}/projects/payment/success?projectId=${projectId}&type=accept`)
|
||||
return res.redirect(successRedirect)
|
||||
}
|
||||
|
||||
const acceptAmount = Math.round(Number(request.price) * PROJECT_ACCEPT_RATE)
|
||||
@@ -402,7 +412,11 @@ const paymentRequestAcceptWebCallback = async (req, res) => {
|
||||
})
|
||||
await notification.save()
|
||||
|
||||
return res.redirect(`${process.env.APP_SITE}/projects/payment/success?projectId=${projectId}&type=accept`)
|
||||
return res.redirect(
|
||||
isAndroid
|
||||
? `modstagram://SuccessPay?type=steps&projectId=${projectId}&requestId=${requestId}&price=${acceptAmount}`
|
||||
: successRedirect
|
||||
)
|
||||
} catch (error) {
|
||||
console.error('paymentRequestAcceptWebCallback error:', error?.response?.data || error?.message || error)
|
||||
return res.redirect(failRedirect)
|
||||
@@ -557,8 +571,8 @@ const initiateAdvertisingPaymentWeb = async (req, res) => {
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (item.name === 'free' && item.price === 0) {
|
||||
if (user.daily_free_request > 0) {
|
||||
user.daily_free_request -= 1
|
||||
if (canUseFreeBillboard(user)) {
|
||||
await consumeFreeBillboard(user)
|
||||
await user.save()
|
||||
const project = await AdvertisingModel.findById(advertisingId)
|
||||
if (!project) {
|
||||
@@ -570,7 +584,7 @@ const initiateAdvertisingPaymentWeb = async (req, res) => {
|
||||
await project.save()
|
||||
res.status(200).json({ message: 'بیلبورد رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
} else {
|
||||
res.status(403).json({ message: 'شما قبلاً از بیلبورد رایگان این ماه استفاده کردهاید.' })
|
||||
res.status(403).json({ message: 'سقف ۲۰۰ بیلبورد رایگان شما به پایان رسیده است.' })
|
||||
}
|
||||
} else {
|
||||
const response = await axios.post(
|
||||
@@ -711,20 +725,20 @@ const republishAdvertisingPaymentWeb = async (req, res) => {
|
||||
const user = await UserModel.findById(userId)
|
||||
|
||||
if (item.name === 'free' && item.price === 0) {
|
||||
if (user.daily_free_request > 0) {
|
||||
user.daily_free_request -= 1
|
||||
if (canUseFreeBillboard(user)) {
|
||||
await consumeFreeBillboard(user)
|
||||
await user.save()
|
||||
const project = await AdvertisingModel.findById(advertisingId)
|
||||
if (!project) {
|
||||
res.status(404).send('Project not found')
|
||||
res.status(404).send('Advertising not found')
|
||||
return
|
||||
}
|
||||
project.payment_status = 'done' // Set project status to 'done'
|
||||
project.status = await resolveApprovalStatus(userId, 'temp_accept') // Set project status to 'done'
|
||||
await project.save()
|
||||
res.status(200).json({ message: 'پروژه رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
res.status(200).json({ message: 'بیلبورد رایگان با موفقیت ایجاد شد', advertisingId, type: 'free' })
|
||||
} else {
|
||||
res.status(403).json({ message: 'شما قبلاً از درخواست رایگان امروز استفاده کردهاید.' })
|
||||
res.status(403).json({ message: 'سقف ۲۰۰ بیلبورد رایگان شما به پایان رسیده است.' })
|
||||
}
|
||||
} else {
|
||||
const response = await axios.post(
|
||||
@@ -853,14 +867,14 @@ const initiateOfferPaymentWeb = async (req, res) => {
|
||||
const decoded = jwt.verify(token, process.env.APP_SECRET)
|
||||
const userId = decoded.id
|
||||
|
||||
const { receiverId, offerType, platform } = req.body
|
||||
const { receiverId, offerType, platform, useWallet } = req.body
|
||||
if (!receiverId || !offerType) { return res.status(400).json({ error: 'Invalid data' }) }
|
||||
|
||||
const user = await UserModel.findById(userId)
|
||||
const receiver = await UserModel.findById(receiverId)
|
||||
if (!user || !receiver) { return res.status(404).json({ error: 'User not found' }) }
|
||||
|
||||
const price = await getOfferPriceFromDatabase(offerType) // ✅ ریال
|
||||
const price = await getOfferPriceFromDatabase(offerType) // تومان
|
||||
|
||||
// 🎁 free offer
|
||||
if (offerType === 'free' && user.monthly_free_offer > 0) {
|
||||
@@ -894,9 +908,39 @@ const initiateOfferPaymentWeb = async (req, res) => {
|
||||
})
|
||||
}
|
||||
|
||||
const amount = Number(price) * 10 // ✅ ریال – بدون ×10
|
||||
const { walletAmount, gatewayAmount, fullyCovered } = await resolveWalletSplit(userId, price, useWallet)
|
||||
|
||||
// کاملاً از کیف پول پوشش داده شد — اصلاً نیازی به درگاه نیست
|
||||
if (fullyCovered) {
|
||||
const payment = await PaymentModel.create({
|
||||
amount: price,
|
||||
status: 'successful',
|
||||
authority: null,
|
||||
user_id: userId,
|
||||
type: 'offer'
|
||||
})
|
||||
|
||||
const receiverShare = Math.round(price * OFFER_COMMISSION_RATE)
|
||||
const offer = await OfferModel.create({
|
||||
sender: userId,
|
||||
receiver: receiverId,
|
||||
transaction_id: payment._id,
|
||||
pendingCommissionAmount: receiverShare,
|
||||
walletAmountUsed: walletAmount
|
||||
})
|
||||
|
||||
await debitWalletForPurchase(userId, walletAmount, {
|
||||
referenceType: 'offer',
|
||||
referenceId: offer._id,
|
||||
description: 'پرداخت آفر از کیف پول'
|
||||
})
|
||||
|
||||
return res.json({ paidFromWallet: true, offerId: offer._id })
|
||||
}
|
||||
|
||||
const amount = toRial(gatewayAmount)
|
||||
const platformSuffix = platform ? `&platform=${encodeURIComponent(platform)}` : ''
|
||||
const callbackUrl = `https://api.modstagram.com/api/v1/offers/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}${platformSuffix}`
|
||||
const callbackUrl = `https://api.modstagram.com/api/v1/offers/payment-web?receiverId=${receiverId}&offerType=${offerType}&userId=${userId}&walletAmount=${walletAmount}${platformSuffix}`
|
||||
|
||||
const zarinpalRes = await axios.post(
|
||||
'https://api.zarinpal.com/pg/v4/payment/request.json',
|
||||
@@ -942,16 +986,21 @@ const handleOfferPaymentCallback = async (req, res) => {
|
||||
const isAndroid = req.query.platform === 'android'
|
||||
|
||||
try {
|
||||
const { Authority, Status, receiverId, offerType, userId } = req.query
|
||||
const { Authority, Status, receiverId, offerType, userId, walletAmount } = req.query
|
||||
const receiverUserForFail = receiverId ? await UserModel.findById(receiverId).select('user_name') : null
|
||||
const failUsername = receiverUserForFail?.user_name || ''
|
||||
const failParams = `receiverId=${receiverId || ''}&offerType=${offerType || ''}&username=${encodeURIComponent(failUsername)}`
|
||||
|
||||
if (Status !== 'OK') {
|
||||
return isAndroid
|
||||
? res.redirect('modstagram://FailedPay?type=offer')
|
||||
: res.redirect(`${process.env.APP_SITE}/offer/payment/failed`)
|
||||
? res.redirect(`modstagram://FailedPay?type=offer&${failParams}`)
|
||||
: res.redirect(`${process.env.APP_SITE}/offer/payment/failed?userId=${receiverId || ''}&offerType=${offerType || ''}`)
|
||||
}
|
||||
|
||||
const price = await getOfferPriceFromDatabase(offerType) // ریال
|
||||
const amount = Number(price) * 10
|
||||
const offerPriceToman = await getOfferPriceFromDatabase(offerType) // تومان
|
||||
const usedWalletAmount = Number(walletAmount) || 0
|
||||
const gatewayAmountToman = offerPriceToman - usedWalletAmount
|
||||
const amount = toRial(gatewayAmountToman)
|
||||
|
||||
const verify = await axios.post(
|
||||
'https://api.zarinpal.com/pg/v4/payment/verify.json',
|
||||
@@ -967,7 +1016,7 @@ const handleOfferPaymentCallback = async (req, res) => {
|
||||
console.log('🔔payment:', data.code)
|
||||
if (data.code === 100) {
|
||||
const payment = await PaymentModel.create({
|
||||
amount: (amount / 10),
|
||||
amount: gatewayAmountToman,
|
||||
status: 'successful',
|
||||
authority: Authority,
|
||||
ref_id: data.ref_id,
|
||||
@@ -977,7 +1026,6 @@ const handleOfferPaymentCallback = async (req, res) => {
|
||||
|
||||
console.log('🔔payment:', payment)
|
||||
|
||||
const offerPriceToman = amount / 10
|
||||
const receiverShare = Math.round(offerPriceToman * OFFER_COMMISSION_RATE)
|
||||
|
||||
// سهم گیرنده فقط با پاسخگویی ظرف ۱۲ ساعت به اولین پیام دایرکت واریز میشود
|
||||
@@ -986,7 +1034,16 @@ const handleOfferPaymentCallback = async (req, res) => {
|
||||
sender: userId,
|
||||
receiver: receiverId,
|
||||
transaction_id: payment._id,
|
||||
pendingCommissionAmount: receiverShare
|
||||
pendingCommissionAmount: receiverShare,
|
||||
walletAmountUsed: usedWalletAmount
|
||||
})
|
||||
|
||||
// درگاه فقط بخشِ باقیمونده رو تایید کرد؛ حالا که پرداخت قطعاً موفق شد، سهمِ کیف
|
||||
// پول هم واقعاً کسر میشه (نگاه کن به utils/walletSplit.js)
|
||||
await debitWalletForPurchase(userId, usedWalletAmount, {
|
||||
referenceType: 'offer',
|
||||
referenceId: offer._id,
|
||||
description: 'پرداخت آفر از کیف پول'
|
||||
})
|
||||
|
||||
// صفحه/دیپلینکِ موفقیت برای دکمهی «ارسال پیام» به شناسه (و نامکاربریِ) گیرنده
|
||||
@@ -1005,13 +1062,14 @@ const handleOfferPaymentCallback = async (req, res) => {
|
||||
}
|
||||
|
||||
return isAndroid
|
||||
? res.redirect('modstagram://FailedPay?type=offer')
|
||||
: res.redirect(`${process.env.APP_SITE}/offer/payment/failed`)
|
||||
? res.redirect(`modstagram://FailedPay?type=offer&${failParams}`)
|
||||
: res.redirect(`${process.env.APP_SITE}/offer/payment/failed?userId=${receiverId || ''}&offerType=${offerType || ''}`)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
const { receiverId, offerType } = req.query
|
||||
return isAndroid
|
||||
? res.redirect('modstagram://FailedPay?type=offer')
|
||||
: res.redirect(`${process.env.APP_SITE}/offer/payment/failed`)
|
||||
? res.redirect(`modstagram://FailedPay?type=offer&receiverId=${receiverId || ''}&offerType=${offerType || ''}`)
|
||||
: res.redirect(`${process.env.APP_SITE}/offer/payment/failed?userId=${receiverId || ''}&offerType=${offerType || ''}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ const OrderModel = require('../../../models/OrderModel')
|
||||
const PaymentModel = require('../../../models/PaymentModel')
|
||||
const ShopModel = require('../../../models/ShopModel')
|
||||
const { notifyUser } = require('../../../utils/notifyUser')
|
||||
const { resolveWalletSplit, debitWalletForPurchase } = require('../../../utils/walletSplit')
|
||||
|
||||
const MERCHANT_ID = process.env.ZARINPAL_MERCHANT_ID || process.env.MERCHENT_CODE
|
||||
|
||||
@@ -13,7 +14,7 @@ function toRial (tomanAmount) {
|
||||
|
||||
const initiateOrderPayment = async (req, res) => {
|
||||
try {
|
||||
const { orderId } = req.body
|
||||
const { orderId, useWallet } = req.body
|
||||
if (!orderId) {
|
||||
return res.status(422).json({ error: true, message: 'سفارش مشخص نشده است' })
|
||||
}
|
||||
@@ -29,6 +30,42 @@ const initiateOrderPayment = async (req, res) => {
|
||||
return res.status(400).json({ error: true, message: 'این سفارش قابل پرداخت نیست' })
|
||||
}
|
||||
|
||||
const { walletAmount, gatewayAmount, fullyCovered } = await resolveWalletSplit(
|
||||
req.user._id,
|
||||
order.total_amount,
|
||||
useWallet
|
||||
)
|
||||
|
||||
// کاملاً از کیف پول پوشش داده شد — اصلاً نیازی به درگاه نیست
|
||||
if (fullyCovered) {
|
||||
await debitWalletForPurchase(req.user._id, walletAmount, {
|
||||
referenceType: 'order',
|
||||
referenceId: order._id,
|
||||
description: `پرداخت سفارش شماره ${order._id} از کیف پول`
|
||||
})
|
||||
order.walletAmountUsed = walletAmount
|
||||
order.status = 'processing'
|
||||
await order.save()
|
||||
await PaymentModel.create({
|
||||
amount: order.total_amount,
|
||||
status: 'successful',
|
||||
authority: null,
|
||||
user_id: order.buyer,
|
||||
order_id: order._id,
|
||||
type: 'shop_order'
|
||||
})
|
||||
const shop = await ShopModel.findById(order.shop)
|
||||
if (shop) {
|
||||
await notifyUser(req.app.get('io'), shop.owner, {
|
||||
project_post_id: order._id,
|
||||
type: 'shop_order',
|
||||
title: 'سفارش جدید',
|
||||
description: `یک سفارش جدید برای فروشگاه ${shop.name} ثبت و پرداخت شد.`
|
||||
})
|
||||
}
|
||||
return res.json({ paidFromWallet: true })
|
||||
}
|
||||
|
||||
const callbackBase = process.env.APP_SITE_CallBack || process.env.APP_URL
|
||||
if (!callbackBase) {
|
||||
return res.status(500).json({ error: true, message: 'آدرس بازگشت پرداخت تنظیم نشده است' })
|
||||
@@ -38,7 +75,7 @@ const initiateOrderPayment = async (req, res) => {
|
||||
'https://api.zarinpal.com/pg/v4/payment/request.json',
|
||||
{
|
||||
merchant_id: MERCHANT_ID,
|
||||
amount: toRial(order.total_amount),
|
||||
amount: toRial(gatewayAmount),
|
||||
description: `پرداخت سفارش شماره ${order._id}`,
|
||||
callback_url: `${callbackBase}/payment/shop-order/callback?orderId=${order._id}`
|
||||
},
|
||||
@@ -48,6 +85,9 @@ const initiateOrderPayment = async (req, res) => {
|
||||
const result = response.data?.data
|
||||
if (result?.code === 100 && result?.authority) {
|
||||
order.paymentAuthority = result.authority
|
||||
// فقط «قصدِ» استفاده از این مقدار کیف پول رو یادداشت میکنه — کسرِ واقعی توی
|
||||
// کالبکِ موفقیت انجام میشه (نگاه کن به بالای فایل: utils/walletSplit.js)
|
||||
order.walletAmountUsed = walletAmount
|
||||
await order.save()
|
||||
return res.json({ authority: result.authority })
|
||||
}
|
||||
@@ -77,8 +117,15 @@ const handleOrderPaymentCallback = async (req, res) => {
|
||||
return res.redirect(failRedirect)
|
||||
}
|
||||
|
||||
// این مقدار توی initiateOrderPayment فقط «یادداشت» شده بود (نگاه کن به utils/
|
||||
// walletSplit.js) — کیف پول تا همین لحظه دستنخورده مونده، پس اگه پرداختِ درگاه
|
||||
// ناموفق/رهاشده باشه، چیزی برای برگردوندن وجود نداره
|
||||
const walletAmount = order.walletAmountUsed || 0
|
||||
const gatewayAmount = order.total_amount - walletAmount
|
||||
|
||||
if (Status !== 'OK') {
|
||||
order.status = 'failed'
|
||||
order.walletAmountUsed = 0
|
||||
await order.save()
|
||||
await PaymentModel.create({
|
||||
amount: order.total_amount,
|
||||
@@ -102,15 +149,23 @@ const handleOrderPaymentCallback = async (req, res) => {
|
||||
{
|
||||
merchant_id: MERCHANT_ID,
|
||||
authority: Authority,
|
||||
amount: toRial(order.total_amount)
|
||||
amount: toRial(gatewayAmount)
|
||||
},
|
||||
{ headers: { 'Content-Type': 'application/json' } }
|
||||
)
|
||||
|
||||
const data = verify.data?.data
|
||||
if (data?.code === 100 || data?.code === 101) {
|
||||
// درگاه فقط بخشِ باقیمونده رو تایید کرد؛ حالا که پرداخت قطعاً موفق شد، سهمِ
|
||||
// کیف پول هم واقعاً کسر میشه
|
||||
await debitWalletForPurchase(order.buyer, walletAmount, {
|
||||
referenceType: 'order',
|
||||
referenceId: order._id,
|
||||
description: `پرداخت سفارش شماره ${order._id} از کیف پول`
|
||||
})
|
||||
|
||||
await PaymentModel.create({
|
||||
amount: order.total_amount,
|
||||
amount: gatewayAmount,
|
||||
status: 'successful',
|
||||
authority: Authority,
|
||||
user_id: order.buyer,
|
||||
@@ -135,6 +190,7 @@ const handleOrderPaymentCallback = async (req, res) => {
|
||||
}
|
||||
|
||||
order.status = 'failed'
|
||||
order.walletAmountUsed = 0
|
||||
await order.save()
|
||||
await PaymentModel.create({
|
||||
amount: order.total_amount,
|
||||
|
||||
Reference in New Issue
Block a user