Comments (25)
(اگر در خواندن متن مشکل چپ چین راست چین، دارید لطفا داخل برنامه ای مثل ورد کپی کنید)
۱. مقدار Already Verified در اینام VerifyResultStatus به معنای این هست که اگر شما بنا به دلایلی بیش از یکبار، درخواست تأیید رو به بانک ارسال کنید، این مقدار به شما بازگشت داده خواهد شد.
علت آینه که درخواستی که قبلاً تأیید شده، اگر بار دیگه آنجام بشه، نباید Success رو برگردونه. چون فروشنده ممکن هست بیش از یکبار عملیات خرید رو برای مشتری انجام بده. برای مثال ممکنه کاربر صفحه رو رفرش کنه و این عملیات دو مرتبه تکرار بشه.
۲. در مورد ذخیره در دیتابیس، قرار هست نسخه جدیدی آماده بشه که بسیار کاملتر از نسخه فعلی هست.
۳. TransactionID فقط در صورتی ذخیره میشه که پرداخت موفقیت آمیز بوده باشه. درواقع به پرداختی که انجام نگرفته، هیچ TransactionID هم اختصاص داده نمیشه از جانب بانک.
from parbad.
خب متوجه نشدم، الان من چطوری بعد از بازگشت به سایت متوجه بشم که کاربر پرداخت رو کنسل کرده یا پرداختش موفقیت آمیز بوده؟ ضمنا من جای دیگه غیر از در اکشن متدی که قراره بوده کاربر رو به بانک منتقل کنه، عملیات تأیید رو انجام ندادم. (اون البته بررسی وضعیت تایید "درخواست" هست). این دو اکشن متد من هست:
کلیک کنید
ممنون میشم اگر نگاهی بندازید و بفرمایید اگر جایی عملیات اشتباهی رو انجام دادم.
در مورد ذخیره در دیتابیس، می تونید حدودا بهم بگید نسخه ای که میفرمایید کی ریلیز میشه؟ و اینکه تا اون موقع باید چه کار کرد در خصوص اون وضعیت های پرداخت؟
from parbad.
الان بخش بررسی وضعیت تأیید درخواست در اولین اکشن متد رو هم حذف کردم اما باز مشکل پابرجاست و مقدار AlreadyVerified بازگردونده میشه.
from parbad.
زمانیکه که کاربر از درگاه بانک به سایت شما برمیگرده، فقط ۲ حالت بیشتر وجود نداره
۱. پرداخت شد Success
۲. پرداخت نشد Failed
در مورد اکشن متدی که گفتید، فکر میکنم منظورم رو اشتباه متوجه شدید. منظورم این هست که اگر برای مثال کاربر صفحه رو رفرش کنه، در نتیجه اکشن متد شما دوبار صدا زده میشه. در نتیجه برای بار دوم، به جای اینکه دوباره عملیات موفق اعلام بشه، عملیات تکراری اعلام میشه.
AlreadyVerified
درواقع این مورد توسط خود سیستم بانکی طراحی شده و ما چیزی رو اختراع نکردیم. زمانیکه شما به درگاه بانکی بیش از یکبار درخواست تأیید بفرستید، بانک به شما اعلام میکنه که عملیات قبلاً تأیید شده.
در مورد دیتابیس، من سعی میکنم در همین نسخه فعلی که نسخه بتا هست این مورد رو اصلاح کنم.
فکر میکنم بین یک تا حداکثر سه روز زمان ببره.
اجازه بدید کد شما رو نگاه کنم.
from parbad.
from parbad.
from parbad.
شما با درگاه تست ParbadVirtualGateway هم تست کردید؟
from parbad.
from parbad.
from parbad.
from parbad.
from parbad.
من الان یکبار دیگه سیستم رو تست کردم و هیچ مشکلی وجود نداره.
آیا شما خودتون دارید در دیتابیس ذخیره میکنید و یا اینکه از SQLServer خود این کتابخونه دارید استفاده میکنید؟
from parbad.
from parbad.
اگر ممکنه کد مربوط به ذخیره سازی رو همینجا در گیت هاب قرار بدید تا ببینم
from parbad.
کد ذخیره سازی:
namespace Abarbazar.Models.DomainModels
{
public class ParbadStorage : Storage
{
private readonly AbarbazarDatabaseContext dbContext;
public ParbadStorage() => dbContext = new AbarbazarDatabaseContext();
protected override void Insert(PaymentData paymentData)
{
dbContext.Payments.Add(new Payment
{
UserId = (HttpContext.Current.User as AbarbazarPrincipal).UserId,
PaymentId = paymentData.Id,
OrderNumber = paymentData.OrderNumber,
Amount = paymentData.Amount,
CreatedOn = paymentData.CreatedOn,
ReferenceId = paymentData.ReferenceId,
TransactionId = paymentData.TransactionId,
AdditionalData = paymentData.AdditionalData,
GatewayId = paymentData.Gateway == Parbad.Providers.Gateway.ParbadVirtualGateway ? PaymentGateway.ParbadVirtualId : PaymentGateway.PasargadId,
StatusId = paymentData.Status == PaymentDataStatus.Verified ? PaymentStatus.VerifiedId : paymentData.Status == PaymentDataStatus.Failed ? PaymentStatus.FailedId : paymentData.Status == PaymentDataStatus.Refunded ? PaymentStatus.RefundedId : PaymentStatus.RequestedId,
});
dbContext.SaveChanges();
}
protected override Task InsertAsync(PaymentData paymentData)
{
dbContext.Payments.Add(new Payment
{
UserId = (HttpContext.Current.User as AbarbazarPrincipal).UserId,
PaymentId = paymentData.Id,
OrderNumber = paymentData.OrderNumber,
Amount = paymentData.Amount,
CreatedOn = paymentData.CreatedOn,
ReferenceId = paymentData.ReferenceId,
TransactionId = paymentData.TransactionId,
AdditionalData = paymentData.AdditionalData,
GatewayId = paymentData.Gateway == Parbad.Providers.Gateway.ParbadVirtualGateway ? PaymentGateway.ParbadVirtualId : PaymentGateway.PasargadId,
StatusId = paymentData.Status == PaymentDataStatus.Verified ? PaymentStatus.VerifiedId : paymentData.Status == PaymentDataStatus.Failed ? PaymentStatus.FailedId : paymentData.Status == PaymentDataStatus.Refunded ? PaymentStatus.RefundedId : PaymentStatus.RequestedId,
});
return dbContext.SaveChangesAsync();
}
protected override PaymentData SelectById(Guid id)
{
return dbContext.Payments.Where(p => p.PaymentId == id).Select(p => new PaymentData
{
Id = p.PaymentId,
OrderNumber = p.OrderNumber,
Amount = (long)p.Amount,
CreatedOn = p.CreatedOn,
ReferenceId = p.ReferenceId,
TransactionId = p.TransactionId,
AdditionalData = p.AdditionalData,
Gateway = p.GatewayId == PaymentGateway.ParbadVirtualId ? Parbad.Providers.Gateway.ParbadVirtualGateway : Parbad.Providers.Gateway.Pasargad,
Status = p.StatusId == PaymentStatus.VerifiedId ? PaymentDataStatus.Verified : p.StatusId == PaymentStatus.FailedId ? PaymentDataStatus.Failed : p.StatusId == PaymentStatus.RefundedId ? PaymentDataStatus.Refunded : PaymentDataStatus.Requested,
}).SingleOrDefault();
}
protected override Task<PaymentData> SelectByIdAsync(Guid id)
{
return dbContext.Payments.Where(p => p.PaymentId == id).Select(p => new PaymentData
{
Id = p.PaymentId,
OrderNumber = p.OrderNumber,
Amount = (long)p.Amount,
CreatedOn = p.CreatedOn,
ReferenceId = p.ReferenceId,
TransactionId = p.TransactionId,
AdditionalData = p.AdditionalData,
Gateway = p.GatewayId == PaymentGateway.ParbadVirtualId ? Parbad.Providers.Gateway.ParbadVirtualGateway : Parbad.Providers.Gateway.Pasargad,
Status = p.StatusId == PaymentStatus.VerifiedId ? PaymentDataStatus.Verified : p.StatusId == PaymentStatus.FailedId ? PaymentDataStatus.Failed : p.StatusId == PaymentStatus.RefundedId ? PaymentDataStatus.Refunded : PaymentDataStatus.Requested,
}).SingleOrDefaultAsync();
}
protected override PaymentData SelectByOrderNumber(long orderNumber)
{
return dbContext.Payments.Where(p => p.OrderNumber == orderNumber).Select(p => new PaymentData
{
Id = p.PaymentId,
OrderNumber = p.OrderNumber,
Amount = (long)p.Amount,
CreatedOn = p.CreatedOn,
ReferenceId = p.ReferenceId,
TransactionId = p.TransactionId,
AdditionalData = p.AdditionalData,
Gateway = p.GatewayId == PaymentGateway.ParbadVirtualId ? Parbad.Providers.Gateway.ParbadVirtualGateway : Parbad.Providers.Gateway.Pasargad,
Status = p.StatusId == PaymentStatus.VerifiedId ? PaymentDataStatus.Verified : p.StatusId == PaymentStatus.FailedId ? PaymentDataStatus.Failed : p.StatusId == PaymentStatus.RefundedId ? PaymentDataStatus.Refunded : PaymentDataStatus.Requested,
}).SingleOrDefault();
}
protected override Task<PaymentData> SelectByOrderNumberAsync(long orderNumber)
{
return dbContext.Payments.Where(p => p.OrderNumber == orderNumber).Select(p => new PaymentData
{
Id = p.PaymentId,
OrderNumber = p.OrderNumber,
Amount = (long)p.Amount,
CreatedOn = p.CreatedOn,
ReferenceId = p.ReferenceId,
TransactionId = p.TransactionId,
AdditionalData = p.AdditionalData,
Gateway = p.GatewayId == PaymentGateway.ParbadVirtualId ? Parbad.Providers.Gateway.ParbadVirtualGateway : Parbad.Providers.Gateway.Pasargad,
Status = p.StatusId == PaymentStatus.VerifiedId ? PaymentDataStatus.Verified : p.StatusId == PaymentStatus.FailedId ? PaymentDataStatus.Failed : p.StatusId == PaymentStatus.RefundedId ? PaymentDataStatus.Refunded : PaymentDataStatus.Requested,
}).SingleOrDefaultAsync();
}
protected override void Update(PaymentData paymentData)
{
Payment payment = dbContext.Payments.SingleOrDefault(p => p.PaymentId == paymentData.Id);
payment.OrderNumber = payment.OrderNumber;
payment.Amount = payment.Amount;
payment.ReferenceId = payment.ReferenceId;
payment.TransactionId = payment.TransactionId;
payment.AdditionalData = payment.AdditionalData;
payment.StatusId = paymentData.Status == PaymentDataStatus.Verified ? PaymentStatus.VerifiedId : paymentData.Status == PaymentDataStatus.Failed ? PaymentStatus.FailedId : paymentData.Status == PaymentDataStatus.Refunded ? PaymentStatus.RefundedId : PaymentStatus.RequestedId;
payment.AdditionalData = paymentData.AdditionalData;
dbContext.SaveChanges();
}
protected override Task UpdateAsync(PaymentData paymentData)
{
Payment payment = dbContext.Payments.SingleOrDefault(p => p.PaymentId == paymentData.Id);
payment.OrderNumber = payment.OrderNumber;
payment.Amount = payment.Amount;
payment.ReferenceId = payment.ReferenceId;
payment.TransactionId = payment.TransactionId;
payment.AdditionalData = payment.AdditionalData;
payment.StatusId = paymentData.Status == PaymentDataStatus.Verified ? PaymentStatus.VerifiedId : paymentData.Status == PaymentDataStatus.Failed ? PaymentStatus.FailedId : paymentData.Status == PaymentDataStatus.Refunded ? PaymentStatus.RefundedId : PaymentStatus.RequestedId;
payment.AdditionalData = paymentData.AdditionalData;
return dbContext.SaveChangesAsync();
}
}
}
from parbad.
این کد اکشن متد ها رو هم ممنون میشم اگر یه بررسی کوچیک بفرمایید:
`
[AbarbazarMVCAuthorize(Roles = "ShopOwner")]
[Route("Shop/Plan")]
[Route("Shop/Plan/{shopPlanTermId:int}")]
public ActionResult ShopPlan(int? shopPlanTermId, string couponCode)
{
if (shopPlanTermId.HasValue)
{
int shopId = (User as AbarbazarPrincipal).ShopId;
ShopPlanService service = new ShopPlanService();
if (service.IsPurchaseValid(shopId, shopPlanTermId.Value, couponCode))
{
decimal finalPrice = service.GetShopPlanPurchaseFinalPrice(shopPlanTermId.Value, couponCode);
if (finalPrice > 0)
{
var invoice = new Invoice(service.GenerateUniqueOrderNumber(),
(long)finalPrice,
Request.Url.GetLeftPart(System.UriPartial.Authority) + $"/Panel/Shop/Plan/{shopPlanTermId}/Verify{(!string.IsNullOrEmpty(couponCode) ? "?couponCode=" + couponCode : string.Empty)}");
var reqResult = Parbad.Payment.Request(Parbad.Providers.Gateway.ParbadVirtualGateway, invoice);
if (reqResult.Status == RequestResultStatus.Success)
return reqResult.ToActionResult();
else
ViewBag.PurchaseErrorMessage = Presentation.Resources.Messages.ExceptionWasThrown;
}
else
{
bool purchaseResult = service.CompleteShopPlanPurchase(shopId, new CreateOrUpgradeShopPlan
{
ShopPlanTermId = shopPlanTermId.Value,
CouponCode = couponCode
});
if (purchaseResult)
return Redirect("/Panel/Shop/Plan");
}
}
ViewBag.PurchaseErrorMessage = Presentation.Resources.Messages.ShopPlanPurchaseIsNotValid;
}
return View(new ShopService().GetShopPlanInfo());
}
[AbarbazarMVCAuthorize(Roles = "ShopOwner")]
[Route("Shop/Plan/{shopPlanTermId:int}/Verify")]
public ActionResult ShopPlanPurchaseFinalize(int shopPlanTermId, string couponCode, string paymentID)
{
ShopPlanService service = new ShopPlanService();
long orderNumber = 0;
int shopId = (User as AbarbazarPrincipal).ShopId;
var paymentResult = Parbad.Payment.Verify(HttpContext, invoice =>
{
orderNumber = invoice.OrderNumber;
if (!service.IsPurchaseValid(shopId, shopPlanTermId, couponCode))
invoice.Cancel();
});
if (paymentResult.Status == VerifyResultStatus.Success/* || paymentResult.Status == VerifyResultStatus.AlreadyVerified*/)
{
bool purchaseResult = service.CompleteShopPlanPurchase(shopId, new CreateOrUpgradeShopPlan
{
ShopPlanTermId = shopPlanTermId,
PaymentGuid = paymentID,
CouponCode = couponCode
});
if (!purchaseResult)
{
Parbad.Payment.Refund(new RefundInvoice(orderNumber));
ViewBag.PurchaseErrorMessage = Presentation.Resources.Messages.ShopPlanPurchaseIsNotValid;
}
}
return RedirectToAction("ShopPlan");
}`
from parbad.
from parbad.
from parbad.
این مواردی که میگم رو لطفا دقیق انجام بدید و اطلاع بدید.
ابتدا سفارش رو انجام بدید و برید به درگاه تست ParbadVirtualGateway
قبل از اینکه کلید پرداخت رو بزنید، برید به پایگاه داده که اطلاعات رو ثبت کردید ببینید مقدار فیلد Status چی هست
from parbad.
این مواردی که میگم رو لطفا دقیق انجام بدید و اطلاع بدید.
ابتدا سفارش رو انجام بدید و برید به درگاه تست ParbadVirtualGateway
قبل از اینکه کلید پرداخت رو بزنید، برید به پایگاه داده که اطلاعات رو ثبت کردید ببینید مقدار فیلد Status چی هست
در واقع منظورم به رکوردی که ثبت شده هست. با توجه به شماره سفارشی که تولید کردید
from parbad.
این مواردی که میگم رو لطفا دقیق انجام بدید و اطلاع بدید.
ابتدا سفارش رو انجام بدید و برید به درگاه تست ParbadVirtualGateway
قبل از اینکه کلید پرداخت رو بزنید، برید به پایگاه داده که اطلاعات رو ثبت کردید ببینید مقدار فیلد Status چی هستدر واقع منظورم به رکوردی که ثبت شده هست. با توجه به شماره سفارشی که تولید کردید
from parbad.
بله.
به همین خاطر میخواستم کد ذخیره سازیتون رو ببینم.
در ذخیره سازی شما دارید وضعیت رو اشتباه ذخیره میکنید.
در نتیجه زمانیکه کاربر از بانک برمیگرده و درخواست باید تایید بشه، وضعیت اون درخواست از همون ابتدا اشتباه ذخیره شده توسط شما.
علته اینکه کد کنسل کردن پرداخت در دیلیگت پارامتر دوم هم هیچوقت کال نمیشه همین هست. چون اصلا هیچ پردازشی بابت اون پرداخت انجام نمیشه که بخواد کنسل بشه.
from parbad.
بله الان متوجه شدم اشتباه از من بوده. عذر خواهی می کنم.
بازهم خیلی ازتون متشکرم که وقتتون در اختیار من قرار دادید. لطف کردید. واقعا پشتیبانیتون خیلی خوب بود. امیدوارم موفق باشید.
from parbad.
bool purchaseResult = service.CompleteShopPlanPurchase(shopId, new CreateOrUpgradeShopPlan { ShopPlanTermId = shopPlanTermId, PaymentGuid = paymentID, CouponCode = couponCode }); if (!purchaseResult) { Parbad.Payment.Refund(new RefundInvoice(orderNumber)); ViewBag.PurchaseErrorMessage = Presentation.Resources.Messages.ShopPlanPurchaseIsNotValid; }
بهتره که هر گونه چک کردن سفارش با پایگاه داده و سیستم خودتون رو به جای اینکه بعد از تایید سفارش انجام بدید که بخواید Refund کنید، در قسمت پارامتر دوم دیلیگت صدا کنید و بررسی کنید.
به اینصورت دیگه نیازی نیست که یک درخواست تأیید بشه و از حساب کاربر کم بشه، و بعدش بلافاصله Refund بشه. در واقع اگر شرایط رو درون پارامتر دوم چک کنید، اصلا نیازی به نوشتن دستور Refund هم نیست.
from parbad.
موفق باشید
from parbad.
Related Issues (20)
- خطای در دسترسی به درگاه بانک پاسارگاد HOT 2
- SameSiteMode.Strict عدم بازگشت در صورت فعال سازی HOT 1
- کانفیگ چندین ترمینال HOT 3
- امکان تسهیم در پرداخت در بانک ملی HOT 3
- خطا در زرین پال HOT 2
- خطا در MyVirtualGateway HOT 1
- خطا هنگام ثبت دستی در دیتابیس HOT 3
- قابلیت تسهیم در زرین پال HOT 1
- چرا کنسل کردن در زمان Verify اهمیت دارد ؟ HOT 5
- توکن بانک پاسارگاد HOT 1
- ارسال کد داینامیک
- دریافت درگاه پرداخت HOT 7
- خطا در دریافت invoice با استفاده از Tracking Number HOT 2
- Saman Gateway files not the same in nuget.org and Github source code
- خطای 400 در بازگشت از درگاه بانک سامان به اپلیکیشن
- تغییر ساعت از UTC به ساعت ایران HOT 2
- ستل شدن تراکنش بعد از درخواست ریفاند
- اشکال در پکیج زرین پال با تغییر تنظیمات پیشفرض Newtonsoft.Json
- درگاه پرداخت snapp pay
- پیام خطا "درخواست تاریخ گذشته است" درگاه کیش
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from parbad.