Skip to content

Commit a8be8ce

Browse files
committed
PayPal Plus: Rest API has different endpoints for different intents
1 parent ca6ea80 commit a8be8ce

3 files changed

Lines changed: 103 additions & 105 deletions

File tree

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
using System;
2-
using System.Web;
3-
using SmartStore.Core.Domain.Payments;
42
using SmartStore.Core.Plugins;
53
using SmartStore.PayPal.Controllers;
6-
using SmartStore.PayPal.Services;
74
using SmartStore.PayPal.Settings;
85
using SmartStore.Services.Payments;
96

@@ -14,24 +11,11 @@ namespace SmartStore.PayPal
1411
[DisplayOrder(1)]
1512
public partial class PayPalPlusProvider : PayPalRestApiProviderBase<PayPalPlusPaymentSettings>
1613
{
17-
private readonly HttpContextBase _httpContext;
18-
19-
public PayPalPlusProvider(
20-
HttpContextBase httpContext)
21-
{
22-
_httpContext = httpContext;
23-
}
24-
2514
public static string SystemName
2615
{
2716
get { return "Payments.PayPalPlus"; }
2817
}
2918

30-
public static string CheckoutCompletedKey
31-
{
32-
get { return SystemName + "CheckoutCompleted"; }
33-
}
34-
3519
public override PaymentMethodType PaymentMethodType
3620
{
3721
get
@@ -44,89 +28,5 @@ public override Type GetControllerType()
4428
{
4529
return typeof(PayPalPlusController);
4630
}
47-
48-
public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest)
49-
{
50-
var result = new ProcessPaymentResult
51-
{
52-
NewPaymentStatus = PaymentStatus.Pending
53-
};
54-
55-
_httpContext.Session.SafeRemove(CheckoutCompletedKey);
56-
57-
var settings = Services.Settings.LoadSetting<PayPalPlusPaymentSettings>(processPaymentRequest.StoreId);
58-
var session = _httpContext.GetPayPalSessionData();
59-
60-
processPaymentRequest.OrderGuid = session.OrderGuid;
61-
62-
var apiResult = PayPalService.ExecutePayment(settings, session);
63-
64-
if (apiResult.Success && apiResult.Json != null)
65-
{
66-
var state = (string)apiResult.Json.state;
67-
68-
if (!state.IsCaseInsensitiveEqual("failed"))
69-
{
70-
result.AuthorizationTransactionCode = apiResult.Id; // payment id, actually not required anymore
71-
72-
var sale = apiResult.Json.transactions[0].related_resources[0].sale;
73-
74-
if (sale != null)
75-
{
76-
state = (string)sale.state;
77-
78-
result.AuthorizationTransactionResult = state;
79-
result.AuthorizationTransactionId = (string)sale.id;
80-
81-
result.NewPaymentStatus = PaymentStatus.Authorized;
82-
83-
if (state.IsCaseInsensitiveEqual("completed") || state.IsCaseInsensitiveEqual("processed"))
84-
{
85-
result.CaptureTransactionResult = state;
86-
result.CaptureTransactionId = (string)sale.id;
87-
88-
result.NewPaymentStatus = PaymentStatus.Paid;
89-
}
90-
else if (state.IsCaseInsensitiveEqual("pending"))
91-
{
92-
var reasonCode = (string)sale.reason_code;
93-
if (reasonCode.IsCaseInsensitiveEqual("ECHECK"))
94-
{
95-
result.NewPaymentStatus = PaymentStatus.Pending;
96-
}
97-
}
98-
99-
session.PaymentInstruction = PayPalService.ParsePaymentInstruction(apiResult.Json.payment_instruction) as PayPalPaymentInstruction;
100-
}
101-
}
102-
else
103-
{
104-
var failureReason = (string)apiResult.Json.failure_reason;
105-
106-
result.Errors.Add(T("Plugins.SmartStore.PayPal.PaymentExecuteFailed").Text.Grow(failureReason, " "));
107-
}
108-
}
109-
else
110-
{
111-
result.Errors.Add(apiResult.ErrorMessage);
112-
}
113-
114-
return result;
115-
}
116-
117-
public override void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
118-
{
119-
if (postProcessPaymentRequest.Order.PaymentStatus == PaymentStatus.Paid)
120-
return;
121-
122-
var instruction = PayPalService.CreatePaymentInstruction(_httpContext.GetPayPalSessionData().PaymentInstruction);
123-
124-
if (instruction.HasValue())
125-
{
126-
_httpContext.Session[CheckoutCompletedKey] = instruction;
127-
128-
OrderService.AddOrderNote(postProcessPaymentRequest.Order, instruction, true);
129-
}
130-
}
13131
}
13232
}

src/Plugins/SmartStore.PayPal/Providers/PayPalRestApiProviderBase.cs

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Web;
34
using System.Web.Routing;
45
using SmartStore.Core.Configuration;
56
using SmartStore.Core.Domain.Orders;
@@ -22,6 +23,7 @@ protected PayPalRestApiProviderBase()
2223
}
2324

2425
public ILogger Logger { get; set; }
26+
public HttpContextBase HttpContext { get; set; }
2527
public ICommonServices Services { get; set; }
2628
public IOrderService OrderService { get; set; }
2729
public IOrderTotalCalculationService OrderTotalCalculationService { get; set; }
@@ -32,6 +34,11 @@ protected string GetControllerName()
3234
return GetControllerType().Name.EmptyNull().Replace("Controller", "");
3335
}
3436

37+
public static string CheckoutCompletedKey
38+
{
39+
get { return "PayPalCheckoutCompleted"; }
40+
}
41+
3542
public override bool SupportCapture
3643
{
3744
get { return true; }
@@ -67,7 +74,93 @@ public override decimal GetAdditionalHandlingFee(IList<OrganizedShoppingCartItem
6774
return result;
6875
}
6976

70-
public override CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest)
77+
public override ProcessPaymentResult ProcessPayment(ProcessPaymentRequest processPaymentRequest)
78+
{
79+
var result = new ProcessPaymentResult
80+
{
81+
NewPaymentStatus = PaymentStatus.Pending
82+
};
83+
84+
HttpContext.Session.SafeRemove(CheckoutCompletedKey);
85+
86+
var settings = Services.Settings.LoadSetting<TSetting>(processPaymentRequest.StoreId);
87+
var session = HttpContext.GetPayPalSessionData();
88+
89+
processPaymentRequest.OrderGuid = session.OrderGuid;
90+
91+
var apiResult = PayPalService.ExecutePayment(settings, session);
92+
93+
if (apiResult.Success && apiResult.Json != null)
94+
{
95+
var state = (string)apiResult.Json.state;
96+
97+
if (!state.IsCaseInsensitiveEqual("failed"))
98+
{
99+
// intent: "sale" for immediate payment, "authorize" for pre-authorized payments and "order" for an order.
100+
// info required cause API has different endpoints for different intents.
101+
result.AuthorizationTransactionCode = (string)apiResult.Json.intent;
102+
103+
var sale = apiResult.Json.transactions[0].related_resources[0].sale;
104+
105+
if (sale != null)
106+
{
107+
state = (string)sale.state;
108+
109+
result.AuthorizationTransactionResult = state;
110+
result.AuthorizationTransactionId = (string)sale.id;
111+
112+
result.NewPaymentStatus = PaymentStatus.Authorized;
113+
114+
if (state.IsCaseInsensitiveEqual("completed") || state.IsCaseInsensitiveEqual("processed"))
115+
{
116+
result.CaptureTransactionResult = state;
117+
result.CaptureTransactionId = (string)sale.id;
118+
119+
result.NewPaymentStatus = PaymentStatus.Paid;
120+
}
121+
else if (state.IsCaseInsensitiveEqual("pending"))
122+
{
123+
var reasonCode = (string)sale.reason_code;
124+
if (reasonCode.IsCaseInsensitiveEqual("ECHECK"))
125+
{
126+
result.NewPaymentStatus = PaymentStatus.Pending;
127+
}
128+
}
129+
130+
session.PaymentInstruction = PayPalService.ParsePaymentInstruction(apiResult.Json.payment_instruction) as PayPalPaymentInstruction;
131+
}
132+
}
133+
else
134+
{
135+
var failureReason = (string)apiResult.Json.failure_reason;
136+
137+
result.Errors.Add(T("Plugins.SmartStore.PayPal.PaymentExecuteFailed").Text.Grow(failureReason, " "));
138+
}
139+
}
140+
else
141+
{
142+
result.Errors.Add(apiResult.ErrorMessage);
143+
}
144+
145+
return result;
146+
}
147+
148+
public override void PostProcessPayment(PostProcessPaymentRequest postProcessPaymentRequest)
149+
{
150+
if (postProcessPaymentRequest.Order.PaymentStatus == PaymentStatus.Paid)
151+
return;
152+
153+
var instruction = PayPalService.CreatePaymentInstruction(HttpContext.GetPayPalSessionData().PaymentInstruction);
154+
155+
if (instruction.HasValue())
156+
{
157+
HttpContext.Session[CheckoutCompletedKey] = instruction;
158+
159+
OrderService.AddOrderNote(postProcessPaymentRequest.Order, instruction, true);
160+
}
161+
}
162+
163+
public override CapturePaymentResult Capture(CapturePaymentRequest capturePaymentRequest)
71164
{
72165
var result = new CapturePaymentResult
73166
{

src/Plugins/SmartStore.PayPal/Services/PayPalService.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -719,9 +719,15 @@ public PayPalResponse ExecutePayment(PayPalApiSettingsBase settings, PayPalSessi
719719
public PayPalResponse Refund(PayPalApiSettingsBase settings, PayPalSessionData session, RefundPaymentRequest request)
720720
{
721721
var data = new Dictionary<string, object>();
722-
var saleId = request.Order.CaptureTransactionId;
722+
var isSale = request.Order.AuthorizationTransactionCode.IsCaseInsensitiveEqual("sale");
723723

724-
if (request.IsPartialRefund)
724+
var path = "/v1/payments/{0}/{1}/refund".FormatInvariant(isSale ? "sale" : "capture", request.Order.CaptureTransactionId);
725+
726+
if (isSale && !request.IsPartialRefund)
727+
{
728+
// no body required
729+
}
730+
else
725731
{
726732
var store = _services.StoreService.GetStoreById(request.Order.StoreId);
727733

@@ -732,8 +738,7 @@ public PayPalResponse Refund(PayPalApiSettingsBase settings, PayPalSessionData s
732738
data.Add("amount", amount);
733739
}
734740

735-
var result = CallApi("POST", "/v1/payments/sale/{0}/refund".FormatInvariant(saleId), session.AccessToken, settings,
736-
data.Any() ? JsonConvert.SerializeObject(data) : null);
741+
var result = CallApi("POST", path, session.AccessToken, settings, data.Any() ? JsonConvert.SerializeObject(data) : null);
737742

738743
if (result.Success && result.Json != null)
739744
{

0 commit comments

Comments
 (0)