reels
This commit is contained in:
@@ -17,6 +17,7 @@ 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 { needsUsernameAndPassword } = require('../../../utils/authSteps')
|
||||
|
||||
const OFFER_COMMISSION_RATE = 0.5
|
||||
|
||||
@@ -108,8 +109,8 @@ const initiatePaymentWeb = async (req, res) => {
|
||||
message: 'شما قبلاً از درخواست رایگان امروز استفاده کردهاید.'
|
||||
})
|
||||
}
|
||||
user.daily_free_request -= 1
|
||||
await user.save()
|
||||
// updateOne + $inc بهجای user.save() — رجوع کنید به توضیح مشابه در initiateOfferPaymentWeb
|
||||
await UserModel.updateOne({ _id: userId }, { $inc: { daily_free_request: -1 } })
|
||||
const project = await ProjectModel.findById(projectId)
|
||||
if (!project) {
|
||||
return res.status(404).json({ error: true, message: 'پروژه یافت نشد' })
|
||||
@@ -573,7 +574,8 @@ const initiateAdvertisingPaymentWeb = async (req, res) => {
|
||||
if (item.name === 'free' && item.price === 0) {
|
||||
if (canUseFreeBillboard(user)) {
|
||||
await consumeFreeBillboard(user)
|
||||
await user.save()
|
||||
// updateOne + $inc بهجای user.save() — رجوع کنید به توضیح مشابه در initiateOfferPaymentWeb
|
||||
await UserModel.updateOne({ _id: userId }, { $inc: { free_billboard_count: 1 } })
|
||||
const project = await AdvertisingModel.findById(advertisingId)
|
||||
if (!project) {
|
||||
res.status(404).send('Advertising not found')
|
||||
@@ -727,7 +729,8 @@ const republishAdvertisingPaymentWeb = async (req, res) => {
|
||||
if (item.name === 'free' && item.price === 0) {
|
||||
if (canUseFreeBillboard(user)) {
|
||||
await consumeFreeBillboard(user)
|
||||
await user.save()
|
||||
// updateOne + $inc بهجای user.save() — رجوع کنید به توضیح مشابه در initiateOfferPaymentWeb
|
||||
await UserModel.updateOne({ _id: userId }, { $inc: { free_billboard_count: 1 } })
|
||||
const project = await AdvertisingModel.findById(advertisingId)
|
||||
if (!project) {
|
||||
res.status(404).send('Advertising not found')
|
||||
@@ -874,7 +877,13 @@ const initiateOfferPaymentWeb = async (req, res) => {
|
||||
const receiver = await UserModel.findById(receiverId)
|
||||
if (!user || !receiver) { return res.status(404).json({ error: 'User not found' }) }
|
||||
|
||||
const price = await getOfferPriceFromDatabase(offerType) // تومان
|
||||
if (needsUsernameAndPassword(user)) {
|
||||
return res.status(403).json({
|
||||
error: true,
|
||||
type: 'needs_username_password',
|
||||
message: 'برای ثبت درخواست همکاری باید نامکاربری و رمز عبور خود را تکمیل کنید'
|
||||
})
|
||||
}
|
||||
|
||||
// 🎁 free offer
|
||||
if (offerType === 'free' && user.monthly_free_offer > 0) {
|
||||
@@ -884,8 +893,10 @@ const initiateOfferPaymentWeb = async (req, res) => {
|
||||
transaction_id: null
|
||||
})
|
||||
|
||||
user.monthly_free_offer -= 1
|
||||
await user.save()
|
||||
// updateOne + $inc بهجای user.save() — save() کل سند رو ریولیدیت میکنه و برای
|
||||
// کاربرهایی که مقدار قدیمی/نامعتبر توی فیلدهای دیگه (مثلاً income_range) دارن
|
||||
// با ValidationError شکست میخوره، حتی وقتی فقط monthly_free_offer تغییر کرده
|
||||
await UserModel.updateOne({ _id: userId }, { $inc: { monthly_free_offer: -1 } })
|
||||
|
||||
return res.json({
|
||||
type: 'free',
|
||||
@@ -908,6 +919,11 @@ const initiateOfferPaymentWeb = async (req, res) => {
|
||||
})
|
||||
}
|
||||
|
||||
// نوعِ «رایگان» قیمتی توی OfferTypeModel نداره (اصلاً پرایسدار نیست، سهمیهمحوره) —
|
||||
// پس این لوکاپ فقط باید برای نوعهای واقعاً پولی اجرا بشه، بعد از هر دو حالتِ بالا؛
|
||||
// قبلاً بیقید-و-شرط بالای تابع اجرا میشد و برای «رایگان» با خطای «not found» throw میکرد
|
||||
const price = await getOfferPriceFromDatabase(offerType) // تومان
|
||||
|
||||
const { walletAmount, gatewayAmount, fullyCovered } = await resolveWalletSplit(userId, price, useWallet)
|
||||
|
||||
// کاملاً از کیف پول پوشش داده شد — اصلاً نیازی به درگاه نیست
|
||||
|
||||
@@ -14,7 +14,7 @@ function toRial (tomanAmount) {
|
||||
|
||||
const initiateOrderPayment = async (req, res) => {
|
||||
try {
|
||||
const { orderId, useWallet } = req.body
|
||||
const { orderId, useWallet, platform } = req.body
|
||||
if (!orderId) {
|
||||
return res.status(422).json({ error: true, message: 'سفارش مشخص نشده است' })
|
||||
}
|
||||
@@ -71,13 +71,14 @@ const initiateOrderPayment = 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: MERCHANT_ID,
|
||||
amount: toRial(gatewayAmount),
|
||||
description: `پرداخت سفارش شماره ${order._id}`,
|
||||
callback_url: `${callbackBase}/payment/shop-order/callback?orderId=${order._id}`
|
||||
callback_url: `${callbackBase}/payment/shop-order/callback?orderId=${order._id}${platformSuffix}`
|
||||
},
|
||||
{ headers: { 'Content-Type': 'application/json' } }
|
||||
)
|
||||
@@ -101,9 +102,18 @@ const initiateOrderPayment = async (req, res) => {
|
||||
}
|
||||
|
||||
const handleOrderPaymentCallback = async (req, res) => {
|
||||
const { orderId, Authority, Status } = req.query
|
||||
const failRedirect = `${process.env.APP_SITE}/shops/payment/failed?orderId=${orderId || ''}`
|
||||
const successRedirect = (id) => `${process.env.APP_SITE}/shops/payment/success?orderId=${id}`
|
||||
const { orderId, Authority, Status, platform } = req.query
|
||||
// اندروید: نتیجه با دیپلینکِ اپ (modstagram://) برگردونده میشه، نه یه صفحهی وب —
|
||||
// عینِ همهی مسیرهای پرداختِ دیگه (آفر/بیلبورد/پروژه). قبلاً این مسیر فقط به وب
|
||||
// ریدایرکت میکرد، یعنی اپ هیچوقت نمیفهمید پرداخت واقعاً موفق شده یا نه
|
||||
const isAndroid = platform === 'android'
|
||||
const failRedirect = isAndroid
|
||||
? `modstagram://FailedPay?type=shop&orderId=${orderId || ''}`
|
||||
: `${process.env.APP_SITE}/shops/payment/failed?orderId=${orderId || ''}`
|
||||
const successRedirect = (id) =>
|
||||
isAndroid
|
||||
? `modstagram://SuccessPay?type=shop&orderId=${id}`
|
||||
: `${process.env.APP_SITE}/shops/payment/success?orderId=${id}`
|
||||
|
||||
const io = req.app.get('io')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user