Use NVP/SOAP Api from PayPal

This commit is contained in:
2017-05-24 23:36:49 +02:00
parent 0aa9ac202b
commit 938159a55c
33 changed files with 2385 additions and 634 deletions

View File

@ -2,7 +2,6 @@ using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc;
using Microsoft.Extensions.OptionsModel;
using Microsoft.Extensions.Localization;
using PayPal.Api;
namespace Yavsc.ApiControllers
@ -20,8 +19,10 @@ namespace Yavsc.ApiControllers
using Helpers;
using Microsoft.Data.Entity;
using Models.Payment;
using Models.Relationship;
using Newtonsoft.Json;
using PayPal.PayPalAPIInterfaceService.Model;
using Yavsc.Models.Haircut.Views;
using Microsoft.AspNet.Http;
[Route("api/haircut")]
public class HairCutController : Controller
@ -67,79 +68,185 @@ namespace Yavsc.ApiControllers
{
var uid = User.GetUserId();
var now = DateTime.Now;
var result = _context.HairCutQueries.Where(
var result = _context.HairCutQueries
.Include(q => q.Prestation)
.Include(q => q.Client)
.Include(q => q.PerformerProfile)
.Include(q => q.Location)
.Where(
q => q.ClientId == uid
&& q.EventDate > now
&& ( q.EventDate > now || q.EventDate == null )
&& q.Status == QueryStatus.Inserted
);
).Select(q => new HaircutQueryClientInfo(q));
return Ok(result);
}
// GET: api/HairCutQueriesApi/5
[HttpGet("{id}", Name = "GetHairCutQuery")]
public async Task<IActionResult> GetHairCutQuery([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
HairCutQuery hairCutQuery = await _context.HairCutQueries.SingleAsync(m => m.Id == id);
if (hairCutQuery == null)
{
return HttpNotFound();
}
return Ok(hairCutQuery);
}
// PUT: api/HairCutQueriesApi/5
[HttpPut("{id}")]
public async Task<IActionResult> PutHairCutQuery([FromRoute] long id, [FromBody] HairCutQuery hairCutQuery)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
if (id != hairCutQuery.Id)
{
return HttpBadRequest();
}
_context.Entry(hairCutQuery).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!HairCutQueryExists(id))
{
return HttpNotFound();
}
else
{
throw;
}
}
return new HttpStatusCodeResult(StatusCodes.Status204NoContent);
}
[HttpPost]
public IActionResult PostQuery(HairCutQuery query)
public async Task<IActionResult> PostQuery(HairCutQuery hairCutQuery)
{
var uid = User.GetUserId();
if (!ModelState.IsValid)
{
return new BadRequestObjectResult(ModelState);
}
_context.HairCutQueries.Add(query);
_context.Update(uid);
return Ok();
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
_context.HairCutQueries.Add(hairCutQuery);
try
{
await _context.SaveChangesAsync(uid);
}
catch (DbUpdateException)
{
if (HairCutQueryExists(hairCutQuery.Id))
{
return new HttpStatusCodeResult(StatusCodes.Status409Conflict);
}
else
{
throw;
}
}
return CreatedAtRoute("GetHairCutQuery", new { id = hairCutQuery.Id }, hairCutQuery);
}
[HttpPost("createpayment/{id}")]
public async Task<IActionResult> CreatePayment(long id)
{
APIContext apiContext = null;
HairCutQuery query = await _context.HairCutQueries.Include(q => q.Client).
Include(q => q.Client.PostalAddress).Include(q => q.Prestation).Include(q=>q.Regularisation)
.SingleAsync(q => q.Id == id);
if (query.PaymentId!=null)
return new BadRequestObjectResult(new { error = "An existing payment process already exists" });
query.SelectedProfile = _context.BrusherProfile.Single(p => p.UserId == query.PerformerId);
SetExpressCheckoutResponseType payment = null;
try {
apiContext = PayPalHelpers.CreateAPIContext();
payment = Request.CreatePayment("HairCutCommand", query, "sale", _logger);
}
catch (PayPal.IdentityException ex) {
_logger.LogError(ex.Response);
catch (Exception ex) {
_logger.LogError(ex.Message);
return new HttpStatusCodeResult(500);
}
if (apiContext==null) {
if (payment==null) {
_logger.LogError("Error doing SetExpressCheckout, aborting.");
_logger.LogError(JsonConvert.SerializeObject(Startup.PayPalSettings));
throw new Exception("No PayPal Api context");
return new HttpStatusCodeResult(500);
}
var payment = Request.CreatePayment("HairCutCommand",apiContext, query, "sale", _logger);
switch (payment.state)
switch (payment.Ack)
{
case "created":
case "approved":
case AckCodeType.SUCCESS:
case AckCodeType.SUCCESSWITHWARNING:
{
var dbinfo = new PaypalPayment
var dbinfo = new PayPalPayment
{
ExecutorId = User.GetUserId(),
PaypalPayerId = payment.payer.payer_info?.payer_id,
PaypalPaymentId = payment.id,
State = payment.state
PaypalPayerId = payment.Token,
CreationToken = null,
State = "inserted"
};
var links = payment.links.Select
(
l=> new Link {
HRef = l.href,
Rel = l.rel,
Method = l.method
});
_context.PaypalPayments.Add(dbinfo);
query.PaymentId = payment.id;
await _context.SaveChangesAsync(User.GetUserId());
}
break;
case "failed":
default:
_logger.LogError(JsonConvert.SerializeObject(payment));
return new BadRequestObjectResult(payment);
default: throw new NotImplementedException();
}
return Json(payment);
return Json(new { token = payment.Token });
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteHairCutQuery([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
HairCutQuery hairCutQuery = await _context.HairCutQueries.SingleAsync(m => m.Id == id);
if (hairCutQuery == null)
{
return HttpNotFound();
}
_context.HairCutQueries.Remove(hairCutQuery);
await _context.SaveChangesAsync();
return Ok(hairCutQuery);
}
private bool HairCutQueryExists(long id)
{
return _context.HairCutQueries.Count(e => e.Id == id) > 0;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
base.Dispose(disposing);
}
}
}

View File

@ -1,173 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using Yavsc.Models;
using Yavsc.Models.Haircut;
using Yavsc.Models.Haircut.Views;
namespace Yavsc.Controllers
{
[Produces("application/json")]
[Route("api/haircutquery")]
public class HairCutQueriesApiController : Controller
{
private ApplicationDbContext _context;
public HairCutQueriesApiController(ApplicationDbContext context)
{
_context = context;
}
// GET: api/HairCutQueriesApi
// Get the active queries for current
// user, as a client
[HttpGet]
public async Task<IActionResult> GetHairCutQueries()
{
IEnumerable<HaircutQueryClientInfo> info = null;
await Task.Run(
() =>
{
var bi = DateTime.Now.AddDays(-15);
var uid = User.GetUserId();
var dat = _context.HairCutQueries
.Include(q => q.Prestation)
.Include(q => q.Client)
.Include(q => q.PerformerProfile)
.Include(q => q.Location)
.Where(q => q.ClientId == uid
&& (q.EventDate == null || q.EventDate > bi))
;
info = dat.ToArray().Select(q => new HaircutQueryClientInfo(q));
});
return Ok(info);
}
// GET: api/HairCutQueriesApi/5
[HttpGet("{id}", Name = "GetHairCutQuery")]
public async Task<IActionResult> GetHairCutQuery([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
HairCutQuery hairCutQuery = await _context.HairCutQueries.SingleAsync(m => m.Id == id);
if (hairCutQuery == null)
{
return HttpNotFound();
}
return Ok(hairCutQuery);
}
// PUT: api/HairCutQueriesApi/5
[HttpPut("{id}")]
public async Task<IActionResult> PutHairCutQuery([FromRoute] long id, [FromBody] HairCutQuery hairCutQuery)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
if (id != hairCutQuery.Id)
{
return HttpBadRequest();
}
_context.Entry(hairCutQuery).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!HairCutQueryExists(id))
{
return HttpNotFound();
}
else
{
throw;
}
}
return new HttpStatusCodeResult(StatusCodes.Status204NoContent);
}
// POST: api/HairCutQueriesApi
[HttpPost]
public async Task<IActionResult> PostHairCutQuery([FromBody] HairCutQuery hairCutQuery)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
_context.HairCutQueries.Add(hairCutQuery);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateException)
{
if (HairCutQueryExists(hairCutQuery.Id))
{
return new HttpStatusCodeResult(StatusCodes.Status409Conflict);
}
else
{
throw;
}
}
return CreatedAtRoute("GetHairCutQuery", new { id = hairCutQuery.Id }, hairCutQuery);
}
// DELETE: api/HairCutQueriesApi/5
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteHairCutQuery([FromRoute] long id)
{
if (!ModelState.IsValid)
{
return HttpBadRequest(ModelState);
}
HairCutQuery hairCutQuery = await _context.HairCutQueries.SingleAsync(m => m.Id == id);
if (hairCutQuery == null)
{
return HttpNotFound();
}
_context.HairCutQueries.Remove(hairCutQuery);
await _context.SaveChangesAsync();
return Ok(hairCutQuery);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_context.Dispose();
}
base.Dispose(disposing);
}
private bool HairCutQueryExists(long id)
{
return _context.HairCutQueries.Count(e => e.Id == id) > 0;
}
}
}

View File

@ -1,14 +1,10 @@
using System.Threading.Tasks;
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Mvc;
using Microsoft.Data.Entity;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.OptionsModel;
using PayPal.Api;
using Newtonsoft.Json;
using Yavsc.Helpers;
using Yavsc.Models;
using Yavsc.Models.Billing;
using Yavsc.ViewModels.PayPal;
namespace Yavsc.ApiControllers
{
@ -16,57 +12,23 @@ namespace Yavsc.ApiControllers
public class PaymentApiController : Controller
{
private ApplicationDbContext dbContext;
PayPalSettings paymentSettings;
private SiteSettings siteSettings;
private readonly ILogger _logger;
public PaymentApiController(
ApplicationDbContext dbContext,
IOptions<PayPalSettings> paypalSettingsReceiver,
IOptions<SiteSettings> siteSettingsReceiver,
ILoggerFactory loggerFactory)
{
this.dbContext = dbContext;
paymentSettings = paypalSettingsReceiver.Value;
siteSettings = siteSettingsReceiver.Value;
_logger = loggerFactory.CreateLogger<PaymentApiController>();
}
public async Task<IActionResult> Info(string paymentId)
public async Task<IActionResult> Info(string paymentId, string token)
{
var result = new PaymentInfo {
DbContent = await dbContext.PaypalPayments.SingleAsync(
p=>p.PaypalPaymentId==paymentId)
};
await Task.Run( () => {
var apiContext = PayPalHelpers.CreateAPIContext();
result.FromPaypal = Payment.Get(apiContext,paymentId);
});
return Ok(result);
}
[HttpPost("execute")]
public async Task<IActionResult> Execute(string paymentId, string payerId)
{
Payment result=null;
await Task.Run( () => {
var apiContext = PayPalHelpers.CreateAPIContext();
var payment = Payment.Get(apiContext,paymentId);
var execution = new PaymentExecution();
execution.payer_id = payerId;
execution.transactions = payment.transactions;
result = payment.Execute(apiContext,execution);
});
return Ok(result);
}
[HttpPost("create"),AllowAnonymous]
public IActionResult Create()
{
var apiContext = PayPalHelpers.CreateAPIContext();
Payment result= Request.CreatePayment("Command",apiContext,new Estimate());
return Ok(Payment.Create(apiContext,result));
var details = await dbContext.GetCheckoutInfo(token);
_logger.LogInformation(JsonConvert.SerializeObject(details));
return Ok(details);
}
}

View File

@ -24,7 +24,6 @@ namespace Yavsc.Controllers
using System.Globalization;
using Microsoft.AspNet.Mvc.Rendering;
using System.Collections.Generic;
using PayPal.Api;
public class HairCutCommandController : CommandController
{
@ -62,12 +61,27 @@ namespace Yavsc.Controllers
{
return HttpNotFound();
}
ViewBag.CreatePaymentUrl = Request.ToAbsolute("api/haircut/createpayment/"+id);
ViewBag.ExecutePaymentUrl = Request.ToAbsolute("api/payment/execute");
ViewBag.Urls=Request.GetPaymentUrls("HairCutCommand",id.ToString());
SetViewBagPaymentUrls(id);
return View (command);
}
public async Task<IActionResult> Confirmation([FromRoute] long id, string token, string PayerID)
{
HairCutQuery command = await GetQuery(id);
if (command == null)
{
return HttpNotFound();
}
SetViewBagPaymentUrls(id);
var paymentinfo = await _context.ConfirmPayment( User.GetUserId(), PayerID, token );
return View (paymentinfo);
}
private void SetViewBagPaymentUrls(long id)
{
ViewBag.CreatePaymentUrl = Request.ToAbsolute("api/haircut/createpayment/"+id);
ViewBag.ExecutePaymentUrl = Request.ToAbsolute("api/payment/execute");
ViewBag.Urls=Request.GetPaymentUrls("HairCutCommand",id.ToString());
}
public async Task<IActionResult> ClientCancelConfirm(long id)
{
var query = await GetQuery(id);if (query == null)
@ -97,7 +111,7 @@ namespace Yavsc.Controllers
.ToListAsync());
}
public async Task<IActionResult> Details(long id, string paymentId, string token, string PayerID)
public async Task<IActionResult> Details(long id)
{
HairCutQuery command = await _context.HairCutQueries
@ -106,40 +120,16 @@ namespace Yavsc.Controllers
.Include(x => x.Prestation)
.Include(x => x.PerformerProfile.Performer)
.Include(x => x.Regularisation)
.SingleAsync(m => m.Id == id);
.SingleOrDefaultAsync(m => m.Id == id);
if (command == null)
{
return HttpNotFound();
}
ViewBag.CreatePaymentUrl = Request.ToAbsolute("api/haircut/createpayment/"+id);
ViewBag.ExecutePaymentUrl = Request.ToAbsolute("api/payment/execute");
ViewBag.Urls=Request.GetPaymentUrls("HairCutCommand",id.ToString());
SetViewBagPaymentUrls(id);
return View(command);
}
public async Task<IActionResult> Execute(long id, string paymentId, string token, string PayerID)
{
HairCutQuery command = await _context.HairCutQueries
.Include(x => x.Location)
.Include(x => x.PerformerProfile)
.Include(x => x.Prestation)
.Include(x => x.PerformerProfile.Performer)
.Include(x => x.Regularisation)
.SingleAsync(m => m.Id == id);
if (command == null)
{
return HttpNotFound();
}
var context = PayPalHelpers.CreateAPIContext();
var payment = Payment.Get(context,paymentId);
var execution = new PaymentExecution{ transactions = payment.transactions,
payer_id = PayerID };
var result = payment.Execute(context,execution);
return View(command);
}
/// <summary>
/// Crée une requête en coiffure à domicile
///
@ -244,9 +234,6 @@ namespace Yavsc.Controllers
var items = model.GetBillItems();
var addition = items.Addition();
ViewBag.Addition = addition.ToString("C",CultureInfo.CurrentUICulture);
ViewBag.CreatePaymentUrl = Request.ToAbsolute("api/haircut/createpayment/"+model.Id);
ViewBag.ExecutePaymentUrl = Request.ToAbsolute("api/payment/execute");
ViewBag.Urls=Request.GetPaymentUrls("HairCutCommand",model.Id.ToString());
return View("CommandConfirmation",model);
}
@ -256,6 +243,7 @@ namespace Yavsc.Controllers
return View("HairCut",model);
}
public async Task<ActionResult> HairCut(string performerId, string activityCode)
{
HairPrestation pPrestation=null;

View File

@ -23,7 +23,6 @@ using Yavsc.Models.Identity;
namespace Yavsc.Controllers
{
using Models.Relationship;
using PayPal.Api;
using Yavsc.Models.Bank;
[Authorize]
@ -716,13 +715,18 @@ namespace Yavsc.Controllers
ViewBag.GoogleSettings = _googleSettings;
return View(model);
}
public IActionResult PaymentInfo(string id)
public IActionResult PaymentInfo (string id)
{
var context = PayPalHelpers.CreateAPIContext();
var payment = Payment.Get(context,id);
return View (payment);
ViewData["id"] = id;
var info = PayPalHelpers.GetCheckoutInfo(_dbContext,id);
return View(info);
}
public IActionResult PaymentError (string id, string error)
{
ViewData["error"] = error;
ViewData["id"] = id;
return View();
}
}
}

View File

@ -1,188 +1,249 @@
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using PayPal.Api;
using PayPal.Exception;
using Yavsc.Models.Billing;
using Microsoft.AspNet.Http;
using System.Threading.Tasks;
using System.Net.Http;
using System;
using System.Text;
using Newtonsoft.Json;
using PayPal.PayPalAPIInterfaceService.Model;
using PayPal.PayPalAPIInterfaceService;
using Yavsc.ViewModels.PayPal;
using Yavsc.Models;
using Microsoft.Data.Entity;
using System.Linq;
using Yavsc.Models.Payment;
namespace Yavsc.Helpers
{
public static class PayPalHelpers
{
private static OAuthTokenCredential payPaylCredential=null;
public static OAuthTokenCredential PayPaylCredential
{
get
{
if (payPaylCredential==null)
{
Dictionary<string,string> config = new Dictionary<string,string>();
// config.Add("mode",Startup.PayPalSettings.Mode);
// config.Add("clientId",Startup.PayPalSettings.ClientId);
// config.Add("clientSecret",Startup.PayPalSettings.Secret);
// config.Add("user",Startup.PayPalSettings.APIUserId);
// https://api-3t.paypal.com/nvp
config.Add("USER",Startup.PayPalSettings.APIUserId);
config.Add("SIGNATURE",Startup.PayPalSettings.APISignature);
config.Add("PWD",Startup.PayPalSettings.APIPassword);
payPaylCredential = new OAuthTokenCredential(config);
private static Dictionary<string,string> payPalProperties = null;
public static Dictionary<string,string> GetPayPalProperties() {
if (payPalProperties==null) {
payPalProperties = new Dictionary<string,string>();
// Don't do:
// payPalProperties.Add("mode", Startup.PayPalSettings.Mode);
// Instead, set the endpoint parameter.
if (Startup.PayPalSettings.Mode == "production") {
// use nvp end point: https://api-3t.paypal.com/nvp
payPalProperties.Add("endpoint", "https://api-3t.paypal.com/nvp");
} else {
payPalProperties.Add("endpoint", "https://api-3t.sandbox.paypal.com/nvp");
}
payPalProperties.Add("clientId", Startup.PayPalSettings.ClientId);
payPalProperties.Add("clientSecret", Startup.PayPalSettings.ClientSecret);
int numClient = 0;
if (Startup.PayPalSettings.Accounts!=null)
foreach (var account in Startup.PayPalSettings.Accounts) {
numClient++;
payPalProperties.Add ($"account{numClient}.apiUsername",account.ApiUsername);
payPalProperties.Add ($"account{numClient}.apiPassword",account.ApiPassword);
payPalProperties.Add ($"account{numClient}.apiSignature",account.Signature);
}
return payPaylCredential;
}
return payPalProperties;
}
public static APIContext CreateAPIContext()
public class PayPalOAuth2Token
{
var accessToken = PayPaylCredential.GetAccessToken();
var apiContext = new APIContext(accessToken);
return apiContext;
}
public string scope;
public string nonce;
public string access_token;
public string token_type;
public class PaymentUrls {
public string Details { get; set; }
public string Cancel { get; set; }
public string app_id;
public string expires_in;
public string CGV { get; set; }
}
public static PaymentUrls GetPaymentUrls(this HttpRequest request, string controllerName, string id )
private static PayPalOAuth2Token token = null;
private static PayPalAPIInterfaceServiceService payPalService = null;
public static PayPalAPIInterfaceServiceService PayPalService {
get {
if (payPalService==null)
payPalService = new PayPal.PayPalAPIInterfaceService.PayPalAPIInterfaceServiceService(GetPayPalProperties());
return payPalService;
}}
[Obsolete("use the PayPalService property")]
internal static async Task<string> GetAccessToken()
{
var result =new PaymentUrls {
Details = request.ToAbsolute($"{controllerName}/Details/{id}") ,
Cancel = request.ToAbsolute($"{controllerName}/ClientCancel/{id}"),
CGV = request.ToAbsolute($"{controllerName}/CGV")
};
if (token == null)
{
token = new PayPalOAuth2Token();
using (HttpClient client = new HttpClient())
{
var uriString = Startup.PayPalSettings.Mode == "production" ?
"https://api.paypal.com/v1/oauth2/token" : "https://api.sandbox.paypal.com/v1/oauth2/token";
client.DefaultRequestHeaders.Add("Accept", "application/json");
client.DefaultRequestHeaders.Add("Accept-Language", "en_US");
string oAuthCredentials = Convert.ToBase64String(Encoding.Default.GetBytes(Startup.PayPalSettings.ClientId + ":" + Startup.PayPalSettings.ClientSecret));
var h_request = new HttpRequestMessage(HttpMethod.Post, uriString);
h_request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", oAuthCredentials);
var keyValues = new List<KeyValuePair<string, string>>();
keyValues.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
h_request.Content = new FormUrlEncodedContent(keyValues);
using (var response = await client.SendAsync(h_request))
{
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
token = JsonConvert.DeserializeObject<PayPalOAuth2Token>(content);
}
else
{
throw new PayPalException($"{response.StatusCode}");
}
}
}
}
return token?.access_token ?? null;
//return PayPalCredential.GetAccessToken();
}
public class PaymentUrls
{
public string ReturnUrl { get; set; }
public string CancelUrl { get; set; }
public string CGVUrl { get; set; }
}
public static PaymentUrls GetPaymentUrls(this HttpRequest request, string controllerName, string id)
{
var result = new PaymentUrls
{
ReturnUrl = request.ToAbsolute($"{controllerName}/Confirmation/{id}"),
CancelUrl = request.ToAbsolute($"{controllerName}/ClientCancel/{id}"),
CGVUrl = request.ToAbsolute($"{controllerName}/CGV")
};
return result;
}
public static Payment CreatePayment(this HttpRequest request, string controllerName, APIContext apiContext, NominativeServiceCommand query, string intent = "sale", ILogger logger=null)
private static string MerchantUserId { get {
return Startup.PayPalSettings.Accounts[0].ApiUsername;
}}
public static SetExpressCheckoutResponseType CreatePayment(this HttpRequest request, string controllerName, NominativeServiceCommand query, string intent = "sale", ILogger logger = null)
{
var items = query.GetBillItems();
var total = items.Addition().ToString("F2");
var queryType = query.GetType().Name;
var transaction = new Transaction
{
description = query.Description,
invoice_number = query.Id.ToString(),
custom = query.GetType().Name + "/"+ query.Id.ToString()
var coreq = new SetExpressCheckoutReq {};
var urls = request.GetPaymentUrls(controllerName, query.Id.ToString());
coreq.SetExpressCheckoutRequest = new SetExpressCheckoutRequestType{
DetailLevel = new List<DetailLevelCodeType?> { DetailLevelCodeType.RETURNALL },
SetExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType
{
PaymentDetails = items.Select(i => new PaymentDetailsType{
OrderTotal = new BasicAmountType {
currencyID = CurrencyCodeType.EUR,
value = (i.Count * i.UnitaryCost).ToString("F2")
},
OrderDescription = i.Description
}).ToList(),
InvoiceID = queryType + "/" + query.Id.ToString(),
OrderDescription = query.Description, CancelURL = urls.CancelUrl, ReturnURL = urls.ReturnUrl
}
};
var urls = request.GetPaymentUrls(controllerName, query.Id.ToString() );
transaction.order_url = urls.Details;
var response = PayPalService.SetExpressCheckout( coreq, MerchantUserId );
// transaction.item_list.shipping_address.city
// country_code default_address id
// line1 line2 preferred_address recipient_name state status type
/* transaction.item_list = new ItemList();
if (query.Client.PostalAddress!=null) {
var address = query.Client.PostalAddress?.Address;
if (address!=null) {
var parts = new Stack<string> ( address.Split(',') );
var country = parts.Pop().Trim();
var city = parts.Pop().Trim().Split(' ');
var line1 = parts.First().Trim();
var line2 = string.Join(" - ",parts.Skip(1));
transaction.item_list.shipping_address = new ShippingAddress {
line1 = line1,
line2 = line2,
city = city[1],
postal_code = city[0],
country_code = country == "France" ? "fr" : country
};
}
}
transaction.item_list.shipping_phone_number = query.Client.PhoneNumber;
var items = query.GetBillItems();
transaction.item_list.items = items.Select(i => new Item {
name = i.Name,
description = i.Description,
quantity = i.Count.ToString(),
price = i.UnitaryCost.ToString("F2"),
currency = "EUR",
sku = "sku"
// postback_data=
// supplementary_data=
}).ToList();
*/ var total = query.GetBillItems().Addition().ToString("F2");
transaction.amount = new Amount {
currency = "EUR",
total = total
};
var payment = new Payment
{
intent = intent, // "sale", "order", "authorize"
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction> { transaction },
redirect_urls = new RedirectUrls
{
return_url = urls.Details,
cancel_url = urls.Cancel
}
};
Payment result = null;
try {
result = Payment.Create(apiContext,payment);
}
catch (PaymentsException ex) {
logger.LogError (ex.Message);
}
return result;
/* transaction.item_list = new ItemList();
if (query.Client.PostalAddress!=null) {
var address = query.Client.PostalAddress?.Address;
if (address!=null) {
var parts = new Stack<string> ( address.Split(',') );
var country = parts.Pop().Trim();
var city = parts.Pop().Trim().Split(' ');
var line1 = parts.First().Trim();
var line2 = string.Join(" - ",parts.Skip(1));
transaction.item_list.shipping_address = new ShippingAddress {
line1 = line1,
line2 = line2,
city = city[1],
postal_code = city[0],
country_code = country == "France" ? "fr" : country
};
}
}
transaction.item_list.shipping_phone_number = query.Client.PhoneNumber;
var items = query.GetBillItems();
transaction.item_list.items = items.Select(i => new Item {
name = i.Name,
description = i.Description,
quantity = i.Count.ToString(),
price = i.UnitaryCost.ToString("F2"),
currency = "EUR",
sku = "sku"
// postback_data=
// supplementary_data=
}).ToList();
*/
return response;
}
public static Payment CreatePayment(this HttpRequest request, string controllerName, APIContext apiContext, Estimate estimation)
public static async Task<PaymentInfo> GetCheckoutInfo(
this ApplicationDbContext context,
string token)
{
var urls = request.GetPaymentUrls( controllerName, estimation.Id.ToString() );
var payment = Payment.Create(apiContext,
new Payment
{
intent = "order", // "sale", "order", "authorize"
payer = new Payer
{
payment_method = "paypal"
},
transactions = new List<Transaction>
{
new Transaction
{
description = "Transaction description.",
invoice_number = estimation.Id.ToString(),
amount = new Amount
{
currency = "EUR",
total = "0.11",
details = new Details
{
tax = "0.01",
shipping = "0.02",
subtotal = "0.08"
}
},
item_list = new ItemList
{
items = new List<Item>
{
new Item
{
name = "nah",
currency = "EUR",
price = "0.02",
quantity = "4",
sku = "sku"
}
}
}
return await CreatePaymentViewModel(context,token,GetExpressCheckoutDetails(token));
}
private static GetExpressCheckoutDetailsResponseType GetExpressCheckoutDetails(string token)
{
GetExpressCheckoutDetailsReq req = new GetExpressCheckoutDetailsReq{
GetExpressCheckoutDetailsRequest = new GetExpressCheckoutDetailsRequestType {
Token = token
}
};
return PayPalService.GetExpressCheckoutDetails(req,Startup.PayPalSettings.Accounts[0].ApiUsername);
}
public static async Task<PaymentInfo> ConfirmPayment(
this ApplicationDbContext context,
string userId,
string payerId,
string token)
{
var details = GetExpressCheckoutDetails(token);
var payment = new PayPalPayment{
ExecutorId = userId,
PaypalPayerId = payerId,
CreationToken = token
};
context.PayPalPayments.Add(payment);
await context.SaveChangesAsync(userId);
// GetCheckoutInfo(,token);
return new PaymentInfo { DbContent = payment, DetailsFromPayPal = details };
}
public static async Task<PaymentInfo> CreatePaymentViewModel (
this ApplicationDbContext context,
string token, GetExpressCheckoutDetailsResponseType fromPayPal)
{
return new PaymentInfo {
DbContent = await context.PayPalPayments.SingleOrDefaultAsync(
p=>p.CreationToken==token),
DetailsFromPayPal = fromPayPal
};
}
},
redirect_urls = new RedirectUrls
{
return_url = urls.Details,
cancel_url = urls.Cancel
}
});
return payment;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
using Microsoft.Data.Entity.Migrations;
namespace Yavsc.Migrations
{
public partial class paypalToDeprecated : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameTable( name: "PaypalPayment", newName: "PayPalPayment");
migrationBuilder.RenameColumn ( name:"PaypalPaymentId", table: "PayPalPayment", newName:"CreationToken" );
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn ( newName :"PaypalPaymentId", table: "PayPalPayment", name:"CreationToken" );
migrationBuilder.RenameTable( newName: "PaypalPayment", name: "PayPalPayment");
}
}
}

View File

@ -1,6 +1,8 @@
using System;
using Microsoft.Data.Entity;
using Microsoft.Data.Entity.Infrastructure;
using Microsoft.Data.Entity.Metadata;
using Microsoft.Data.Entity.Migrations;
using Yavsc.Models;
namespace Yavsc.Migrations
@ -596,6 +598,8 @@ namespace Yavsc.Migrations
b.Property<long?>("LocationId");
b.Property<string>("PaymentId");
b.Property<string>("PerformerId")
.IsRequired();
@ -863,9 +867,9 @@ namespace Yavsc.Migrations
b.HasKey("UserId");
});
modelBuilder.Entity("Yavsc.Models.Payment.PaypalPayment", b =>
modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b =>
{
b.Property<string>("PaypalPaymentId");
b.Property<string>("CreationToken");
b.Property<DateTime>("DateCreated");
@ -884,7 +888,7 @@ namespace Yavsc.Migrations
b.Property<string>("UserModified");
b.HasKey("PaypalPaymentId");
b.HasKey("CreationToken");
});
modelBuilder.Entity("Yavsc.Models.Relationship.Circle", b =>
@ -927,7 +931,7 @@ namespace Yavsc.Migrations
b.Property<string>("Method");
b.Property<string>("PaypalPaymentPaypalPaymentId");
b.Property<string>("PayPalPaymentCreationToken");
b.Property<string>("Rel");
@ -1117,6 +1121,8 @@ namespace Yavsc.Migrations
b.Property<long?>("LocationTypeId");
b.Property<string>("PaymentId");
b.Property<string>("PerformerId")
.IsRequired();
@ -1282,7 +1288,7 @@ namespace Yavsc.Migrations
.WithMany()
.HasForeignKey("LocationId");
b.HasOne("Yavsc.Models.Payment.PaypalPayment")
b.HasOne("Yavsc.Models.Payment.PayPalPayment")
.WithMany()
.HasForeignKey("PaymentId");
@ -1313,6 +1319,10 @@ namespace Yavsc.Migrations
.WithMany()
.HasForeignKey("LocationId");
b.HasOne("Yavsc.Models.Payment.PayPalPayment")
.WithMany()
.HasForeignKey("PaymentId");
b.HasOne("Yavsc.Models.Workflow.PerformerProfile")
.WithMany()
.HasForeignKey("PerformerId");
@ -1401,7 +1411,7 @@ namespace Yavsc.Migrations
.HasForeignKey("UserId");
});
modelBuilder.Entity("Yavsc.Models.Payment.PaypalPayment", b =>
modelBuilder.Entity("Yavsc.Models.Payment.PayPalPayment", b =>
{
b.HasOne("Yavsc.Models.ApplicationUser")
.WithMany()
@ -1435,9 +1445,9 @@ namespace Yavsc.Migrations
modelBuilder.Entity("Yavsc.Models.Relationship.Link", b =>
{
b.HasOne("Yavsc.Models.Payment.PaypalPayment")
b.HasOne("Yavsc.Models.Payment.PayPalPayment")
.WithMany()
.HasForeignKey("PaypalPaymentPaypalPaymentId");
.HasForeignKey("PayPalPaymentCreationToken");
});
modelBuilder.Entity("Yavsc.Models.Relationship.PostTag", b =>
@ -1505,6 +1515,10 @@ namespace Yavsc.Migrations
.WithMany()
.HasForeignKey("LocationTypeId");
b.HasOne("Yavsc.Models.Payment.PayPalPayment")
.WithMany()
.HasForeignKey("PaymentId");
b.HasOne("Yavsc.Models.Workflow.PerformerProfile")
.WithMany()
.HasForeignKey("PerformerId");

View File

@ -309,7 +309,7 @@ namespace Yavsc.Models
public DbSet<BankIdentity> BankIdentity { get; set; }
public DbSet<PaypalPayment> PaypalPayments { get; set; }
public DbSet<PayPalPayment> PayPalPayments { get; set; }
public DbSet<Link> Links { get; set; }
}

View File

@ -79,6 +79,6 @@ namespace Yavsc.Models.Billing
public string PaymentId { get; set; }
[ForeignKey("PaymentId"), Display(Name = "Acquittement de la facture")]
public virtual PaypalPayment Regularisation { get; set; }
public virtual PayPalPayment Regularisation { get; set; }
}
}

View File

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Yavsc.Models.Billing;
using Yavsc.Models.Payment;
using Yavsc.Models.Relationship;
using YavscLib.Billing;
@ -56,10 +55,7 @@ namespace Yavsc.Models.Haircut
[DisplayFormat(ConvertEmptyStringToNull = true, NullDisplayText = "[pas d'informations complémentaires]")]
public string AdditionalInfo { get; set; }
public string PaymentId { get; set; }
[ForeignKey("PaymentId"), Display(Name = "Acquittement de la facture")]
public virtual PaypalPayment Regularisation { get; set; }
public override List<IBillItem> GetBillItems()
{

View File

@ -7,10 +7,10 @@ namespace Yavsc.Models.Payment {
using YavscLib;
using Relationship;
public class PaypalPayment : IBaseTrackedEntity
public class PayPalPayment : IBaseTrackedEntity
{
[Required,Key]
public string PaypalPaymentId { get; set; }
public string CreationToken { get; set; }
[Required]
public string ExecutorId { get; set; }

View File

@ -0,0 +1,7 @@
namespace Yavsc.Services
{
public interface IBankInterface
{
}
}

View File

@ -1,14 +1,30 @@
namespace Yavsc
{
/// <summary>
/// PayPal NV/SOAP API Credentials
/// </summary>
public class PayPalSettings {
/// <summary>
/// supported values: <c>sandbox</c> or <c>production</c>
/// </summary>
/// <returns></returns>
public string Mode { get; set; }
public string Secret { get; set; }
/// <summary>
///
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// For sandbox only?
/// </summary>
/// <returns></returns>
public string ClientSecret { get; set; }
public string ApplicationId { get; set; }
public class ClassicPayPalAccountApiCredential {
public string Signature { get; set; }
public string ApiUsername { get; set; }
public string ApiPassword { get; set; }
// NV/SOAP Api - Signature
public string UserId { get; set; }
public string Password { get; set; }
public string Signature { get; set; }
}
public ClassicPayPalAccountApiCredential[] Accounts { get; set; }
}
}

View File

@ -25,8 +25,11 @@ using Microsoft.Net.Http.Headers;
namespace Yavsc
{
using System.Net;
using Formatters;
using Models;
using Newtonsoft.Json;
using PayPal.Manager;
using Services;
using ViewModels.Auth.Handlers;
public partial class Startup
@ -320,6 +323,12 @@ namespace Yavsc
else throw ex;
}
}
// before fixing the security protocol, let beleive our lib it's done with it.
var cxmgr = ConnectionManager.Instance;
// then, fix it.
ServicePointManager.SecurityProtocol = (SecurityProtocolType) 0xC00;
logger.LogInformation($"ServicePointManager.SecurityProtocol: {ServicePointManager.SecurityProtocol}");
app.UseIISPlatformHandler(options =>
{
@ -341,6 +350,8 @@ namespace Yavsc
template: "{controller=Home}/{action=Index}/{id?}");
});
logger.LogInformation(JsonConvert.SerializeObject(Startup.PayPalSettings));
}
// Entry point for the application.

View File

@ -0,0 +1,18 @@
using Microsoft.AspNet.Mvc;
using Yavsc.Helpers;
using Yavsc.Models.Billing;
namespace Yavsc.ViewComponents
{
public class PayPalButtonViewComponent : ViewComponent
{
public IViewComponentResult Invoke(NominativeServiceCommand command, string apiControllerName , string controllerName)
{
ViewBag.CreatePaymentUrl = Request.ToAbsolute($"api/{apiControllerName}/createpayment/"+command.Id);
ViewBag.ExecutePaymentUrl = Request.ToAbsolute("api/payment/execute");
ViewBag.Urls=Request.GetPaymentUrls(controllerName,command.Id.ToString());
return View ( command);
}
}
}

View File

@ -1,11 +1,14 @@
using PayPal.Api;
using PayPal.PayPalAPIInterfaceService.Model;
using Yavsc.Models.Payment;
namespace Yavsc.ViewModels.PayPal
{
public class PaymentInfo
{
public PaypalPayment DbContent { get; set; }
public Payment FromPaypal { get; set; }
public PayPalPayment DbContent { get; set; }
public virtual GetExpressCheckoutDetailsResponseType DetailsFromPayPal { get; set; }
}
}

View File

@ -1,4 +1,7 @@
@model HairCutQuery
@section header {
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
}
@{
ViewData["Title"] = @SR["Annuler votre commande"];

View File

@ -2,6 +2,10 @@
@{
ViewData["Title"] = SR["Command confirmation"]+" "+ViewBag.Activity.Name;
}
@section header {
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
}
<h2>@ViewData["Title"]</h2>
<div class="form-horizontal">
<h4>@SR["Your book query"]</h4>
@ -84,10 +88,9 @@
</environment>
<dt>@Html.DisplayNameFor(m=>m.Regularisation)</dt>
<dd>@Html.DisplayFor(m=>m.Regularisation,new {
PaymentUrl = "/api/haircut/createpayment/"+Model.Id.ToString(),
SuccessUrl = "/HairCutCommand/Details/"+Model.Id.ToString() })</dd>
<dt>@Html.DisplayNameFor(m=>m.Regularisation)</dt>
<dd> @Component.Invoke("PayPalButton", Model, "haircut", "HairCutCommand" )
</dd>
</dl>
</div>

View File

@ -1,4 +1,7 @@
@model HairCutQuery
@section header {
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
}
@{
ViewData["Title"] = @SR["Le detail de votre commande de prestation en coiffure à domicile"];

View File

@ -233,7 +233,7 @@
<a asp-action="CGV" class="btn btn-link">Conditions générales de vente</a> liées à cette commande de service.</label>
</div>
<input asp-for="ClientId" type="hidden" />
<img src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/pp-acceptance-medium.png" alt="PayPal Acceptance">
<input type="submit" class="btn btn-success btn-submit" value="@SR["Validez ce choix, et prendre rendez-vous"] avec @Model.PerformerProfile.Performer.UserName"/>
<environment names="Development">

View File

@ -0,0 +1,8 @@
<dl>
<dt> Le paiment @ViewData["id"] a échoué
</dt>
<dd> @ViewData["error"]
</dd>
</dl>

View File

@ -1,20 +0,0 @@
@using PayPal.Api
@model Payment
<dl>
<dt> État du paiment
</dt>
<dd> @SR[Model.state] @Model.failure_reason
</dd>
<dt>
</dt>
<dd>@Model.payment_instruction
</dd>
</dl>
@if (Model.state=="created") {
<a href="@Model.GetApprovalUrl()">Autoriser le paiement</a>
}
@{ var refundUrl = Model.GetHateoasLink("refund"); }
@if (refundUrl!=null) {
<a href="@refundUrl">Rembourser ce paiement</a>
}

View File

@ -0,0 +1,43 @@
@model NominativeServiceCommand
@inject IOptions<PayPalSettings> PayPalSettings
@Model.PaymentId
@if (Model!=null && Model.PaymentId!=null) {
@if (Model.Regularisation.Executor.Id == User.GetUserId()) {
<text>
Votre paiment
</text>
} else {
<text>
Le paiment de @Html.DisplayFor(m=>m.Regularisation.Executor.UserName)
</text>
}
<text> :
</text><a asp-controller="Manage" asp-action="PaymentInfo" asp-route-id="@Model.Regularisation.PaypalPaymentId">@Model.Regularisation.PaypalPaymentId</a>
} else {
<div id="paypalzone"></div>
<script>
var CREATE_PAYMENT_URL = '@ViewBag.CreatePaymentUrl';
var EXECUTE_PAYMENT_URL = '@ViewBag.ExecutePaymentUrl';
var PAYPAL_ENV = '@PayPalSettings.Value.Mode';
var APP_ID = '@PayPalSettings.Value.ApplicationId';
paypal.checkout.setup(APP_ID, {
environment: PAYPAL_ENV,
container: '#paypalzone',
click: function () {
paypal.checkout.initXO();
var action = $.post(CREATE_PAYMENT_URL)
.done(function (data) {
paypal.checkout.startFlow(data.token)
})
.fail(function () {
paypal.checkout.closeFlow()
})
}
});
</script>
}

View File

@ -21,7 +21,8 @@
<dd>@Html.DisplayFor(m=>m.AdditionalInfo)
</dd>
<dt>@Html.DisplayNameFor(m=>m.Regularisation)</dt>
<dd>@Html.DisplayFor(m=>m.Regularisation)
<dd>
@Component.Invoke("PayPalButton", Model, "haircut", "HairCutCommand" )
</dd>
</dl>

View File

@ -1,55 +0,0 @@
@model PaypalPayment
@inject IOptions<PayPalSettings> PayPalSettings
@if (Model!=null && Model.PaypalPaymentId!=null) {
@if (Model.Executor.Id == User.GetUserId()) {
<text>
Votre paiment
</text>
} else {
<text>
Le paiment de @Html.DisplayFor(m=>m.Executor.UserName)
</text>
}
<text> :
</text><a asp-controller="Manage" asp-action="PaymentInfo" asp-route-id="@Model.PaypalPaymentId">@Model.PaypalPaymentId</a>
} else {
<div id="paypal-button"></div>
<script src="https://www.paypalobjects.com/api/checkout.js"></script>
<script>
var CREATE_PAYMENT_URL = '@ViewBag.CreatePaymentUrl';
var EXECUTE_PAYMENT_URL = '@ViewBag.ExecutePaymentUrl';
var PAYPAL_ENV = '@PayPalSettings.Value.Mode';
paypal.Button.render({
env: PAYPAL_ENV, // 'production', Optional: specify 'sandbox' environment
commit: true,
payment: function(resolve, reject) {
return paypal.request.post(CREATE_PAYMENT_URL)
.then(function(data) { resolve(data.id); })
.catch(function(err) { reject(err); });
},
onAuthorize: function(data) {
// Note: you can display a confirmation page before executing
return paypal.request.post(EXECUTE_PAYMENT_URL,
{ paymentID: data.paymentID, payerID: data.payerID })
.then(function(data) {
document.location = '@ViewBag.Urls.Details';
/* Go to a success page */ })
.catch(function(err) {
document.location = '/Manage/PaymentInfo/'+data.paymentID;
/* Go to an error page */ });
}
}, '#paypal-button');
</script>
}

View File

@ -2,31 +2,31 @@
"use strict";
var gulp = require("gulp"),
rimraf = require("rimraf"),
// concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify"),
shell = require("gulp-shell"),
rename = require('gulp-rename');
rimraf = require("rimraf"),
// concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify"),
shell = require("gulp-shell"),
rename = require('gulp-rename');
var webroot = "./wwwroot/";
var paths = {
bower: "./bower_components/",
js: webroot + "js/**/*.js",
minJs: webroot + "js/**/*.min.js",
css: webroot + "css/**/*.css",
minCss: webroot + "css/**/*.min.css",
concatJsDest: webroot + "js/site.min.js",
concatCssDest: webroot + "css/site.min.css"
bower: "./bower_components/",
js: webroot + "js/**/*.js",
minJs: webroot + "js/**/*.min.js",
css: webroot + "css/**/*.css",
minCss: webroot + "css/**/*.min.css",
concatJsDest: webroot + "js/site.min.js",
concatCssDest: webroot + "css/site.min.css"
};
gulp.task("clean:js", function (cb) {
rimraf(paths.concatJsDest, cb);
gulp.task("clean:js", function(cb) {
rimraf(paths.concatJsDest, cb);
});
gulp.task("clean:css", function (cb) {
rimraf(paths.concatCssDest, cb);
gulp.task("clean:css", function(cb) {
rimraf(paths.concatCssDest, cb);
});
gulp.task("clean", ["clean:js", "clean:css"]);
@ -34,21 +34,20 @@ gulp.task("clean", ["clean:js", "clean:css"]);
gulp.task('watch', shell.task(['ASPNET_ENV=Development dnx-watch web --configuration=Debug']));
gulp.task('watchlua', shell.task(['ASPNET_ENV=Lua dnx-watch luatest --configuration=Debug']));
gulp.task('watchlua', shell.task(['ASPNET_ENV=lua dnx-watch luatest --configuration=Debug']));
gulp.task('watchpre', shell.task(['ASPNET_ENV=yavscpre dnx-watch web --configuration=Debug']));
gulp.task("min:css", function () {
gulp.task("min:css", function() {
gulp.src([paths.css, "!" + paths.minCss, '!site.css'])
.pipe(cssmin())
.pipe(rename({suffix: '.min'}))
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('wwwroot/css'));
});
gulp.task("min:js", function () {
return gulp.src([paths.js, "!" + paths.minJs, '!site.js'])
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
gulp.task("min:js", function() {
return gulp.src([paths.js, "!" + paths.minJs, '!site.js'])
.pipe(uglify())
.pipe(rename({ suffix: '.min' }))
.pipe(gulp.dest('wwwroot/js'));
});
@ -60,5 +59,4 @@ gulp.task('buildrelease', shell.task(['dnu build --configuration=Release']));
gulp.task('publish', shell.task(['dnu publish --configuration=Release']));
gulp.task('postpublish', shell.task(['contrib/rsync-to-pre.sh']));
gulp.task("default", ["watch"]);
gulp.task("default", ["watch"]);

View File

@ -107,7 +107,6 @@
"Microsoft.AspNet.DataProtection": "1.0.0-rc1-final",
"Microsoft.AspNet.DataProtection.SystemWeb": "1.0.0-rc1-final",
"Microsoft.AspNet.Authentication.JwtBearer": "1.0.0-rc1-final",
"PayPalCoreSDK": "1.7.1",
"Microsoft.AspNet.Authentication.OAuth": "1.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Json": "6.0.0-rc1-final",
"Microsoft.AspNet.OWin": "1.0.0-rc1-final",
@ -119,7 +118,7 @@
"Extensions.AspNet.Authentication.Instagram": "1.0.0-t150809211713",
"Microsoft.AspNet.Http.Extensions": "1.0.0-rc1-final",
"Microsoft.DiaSymReader.Native": "1.5.0",
"PayPal": "1.8.0"
"MyPayPalMerchantSDK": "1.0.0"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel --server.urls http://*:5000",

View File

@ -2514,6 +2514,18 @@
"lib/net451/MimeKit.dll": {}
}
},
"MyPayPalMerchantSDK/1.0.0": {
"type": "package",
"dependencies": {
"PayPalCoreSDK": "1.7.1"
},
"compile": {
"lib/net451/PayPalMerchantSDK.dll": {}
},
"runtime": {
"lib/net451/PayPalMerchantSDK.dll": {}
}
},
"Newtonsoft.Json/10.0.2": {
"type": "package",
"compile": {
@ -2547,18 +2559,6 @@
"lib/net40/Owin.dll": {}
}
},
"PayPal/1.8.0": {
"type": "package",
"dependencies": {
"Newtonsoft.Json": "7.0.1"
},
"compile": {
"lib/net451/PayPal.dll": {}
},
"runtime": {
"lib/net451/PayPal.dll": {}
}
},
"PayPalCoreSDK/1.7.1": {
"type": "package",
"dependencies": {
@ -5383,6 +5383,18 @@
"lib/net451/MimeKit.dll": {}
}
},
"MyPayPalMerchantSDK/1.0.0": {
"type": "package",
"dependencies": {
"PayPalCoreSDK": "1.7.1"
},
"compile": {
"lib/net451/PayPalMerchantSDK.dll": {}
},
"runtime": {
"lib/net451/PayPalMerchantSDK.dll": {}
}
},
"Newtonsoft.Json/10.0.2": {
"type": "package",
"compile": {
@ -5416,18 +5428,6 @@
"lib/net40/Owin.dll": {}
}
},
"PayPal/1.8.0": {
"type": "package",
"dependencies": {
"Newtonsoft.Json": "7.0.1"
},
"compile": {
"lib/net451/PayPal.dll": {}
},
"runtime": {
"lib/net451/PayPal.dll": {}
}
},
"PayPalCoreSDK/1.7.1": {
"type": "package",
"dependencies": {
@ -8252,6 +8252,18 @@
"lib/net451/MimeKit.dll": {}
}
},
"MyPayPalMerchantSDK/1.0.0": {
"type": "package",
"dependencies": {
"PayPalCoreSDK": "1.7.1"
},
"compile": {
"lib/net451/PayPalMerchantSDK.dll": {}
},
"runtime": {
"lib/net451/PayPalMerchantSDK.dll": {}
}
},
"Newtonsoft.Json/10.0.2": {
"type": "package",
"compile": {
@ -8285,18 +8297,6 @@
"lib/net40/Owin.dll": {}
}
},
"PayPal/1.8.0": {
"type": "package",
"dependencies": {
"Newtonsoft.Json": "7.0.1"
},
"compile": {
"lib/net451/PayPal.dll": {}
},
"runtime": {
"lib/net451/PayPal.dll": {}
}
},
"PayPalCoreSDK/1.7.1": {
"type": "package",
"dependencies": {
@ -10632,6 +10632,16 @@
"MimeKit.nuspec"
]
},
"MyPayPalMerchantSDK/1.0.0": {
"type": "package",
"sha512": "T/4NVweMlULqGurtG0EuXE2WebtMiD4M0QPpJxx/AAHS33eJiXjWb/CZRcEvJKE9REgWctK7RALuMQqzPt9DEg==",
"files": [
"lib/net451/PayPalMerchantSDK.dll",
"MyPayPalMerchantSDK.1.0.0.nupkg",
"MyPayPalMerchantSDK.1.0.0.nupkg.sha512",
"MyPayPalMerchantSDK.nuspec"
]
},
"Newtonsoft.Json/10.0.2": {
"type": "package",
"sha512": "iwElSU2IXmwGvytJsezyDML2ZWDkG2JzTYzlU/BNlmzMdlmRvbnwITsGGY74gwVEpDli1UdOLkMT7/3jxWvXzA==",
@ -10689,21 +10699,6 @@
"Owin.nuspec"
]
},
"PayPal/1.8.0": {
"type": "package",
"sha512": "r59EIEePqy0yLRbGgJ1Ul86rXGtogC/8ofn9qTdKozN/CsTsotxGZMCzzDIFgnZRAm3zO6xz8tZGAWmKxDFX/Q==",
"files": [
"lib/net40/PayPal.dll",
"lib/net40/PayPal.xml",
"lib/net45/PayPal.dll",
"lib/net45/PayPal.xml",
"lib/net451/PayPal.dll",
"lib/net451/PayPal.xml",
"PayPal.1.8.0.nupkg",
"PayPal.1.8.0.nupkg.sha512",
"PayPal.nuspec"
]
},
"PayPalCoreSDK/1.7.1": {
"type": "package",
"sha512": "hGOLo3X2vgOpOWJI91+vlBgr/Dchk3xZAF0bdIpKiAwjlRKMjzSC4zuT1eGwmQ8uVL1IaGBZwNGklyRHDniYlQ==",
@ -11623,7 +11618,6 @@
"Microsoft.AspNet.DataProtection >= 1.0.0-rc1-final",
"Microsoft.AspNet.DataProtection.SystemWeb >= 1.0.0-rc1-final",
"Microsoft.AspNet.Authentication.JwtBearer >= 1.0.0-rc1-final",
"PayPalCoreSDK >= 1.7.1",
"Microsoft.AspNet.Authentication.OAuth >= 1.0.0-rc1-final",
"Microsoft.AspNet.Mvc.Formatters.Json >= 6.0.0-rc1-final",
"Microsoft.AspNet.OWin >= 1.0.0-rc1-final",
@ -11632,7 +11626,7 @@
"Extensions.AspNet.Authentication.Instagram >= 1.0.0-t150809211713",
"Microsoft.AspNet.Http.Extensions >= 1.0.0-rc1-final",
"Microsoft.DiaSymReader.Native >= 1.5.0",
"PayPal >= 1.8.0"
"MyPayPalMerchantSDK >= 1.0.0"
],
"DNX,Version=v4.5.1": [
"fx/System.Drawing >= 4.0.0",

View File

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="210mm"
height="297mm"
id="svg2"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="meche-cheveux.svg">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective3240" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5454241"
inkscape:cx="-145.39699"
inkscape:cy="570.82595"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1670"
inkscape:window-height="771"
inkscape:window-x="105"
inkscape:window-y="240"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<path
style="fill:#ac9393;stroke:#000000;stroke-width:1.33444129999999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 313.07765,585.55788 c 69.3417,-92.10668 -205.277,-404.02027 -78.52163,-399.82392 126.75538,4.19636 181.08502,340.81426 78.52163,399.82392 z"
id="path2985"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
<path
style="fill:#483737;stroke:#000000;stroke-width:1.33444129999999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 130.28057,582.08153 C 233.20136,530.12747 124.80014,128.93588 236.63638,188.74548 348.47263,248.5551 248.36507,574.50264 130.28057,582.08153 z"
id="path2985-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
<path
style="fill:#6c5353;stroke:#000000;stroke-width:1.3344413px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 247.97601,534.96113 c 75.96164,-86.72798 -174.84487,-418.09124 -48.74663,-404.535 126.09823,13.55625 155.39208,353.26965 48.74663,404.535 z"
id="path2985-3-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
<path
style="fill:#ac9393;stroke:#ffffff;stroke-width:1.00382698px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 301.72304,326.2129 C 345.70788,240.72782 56.68077,198.78469 166.36779,139.55137 276.05481,80.318076 379.88582,243.19485 301.72304,326.2129 z"
id="path2985-3-7-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
<path
style="fill:#483737;stroke:#ffffff;stroke-width:1.3344413px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 180.69589,531.81366 C 266.33952,454.6315 56.287482,96.045874 179.91288,124.35296 c 123.62543,28.30715 112.72218,369.10686 0.78301,407.4607 z"
id="path2985-3-7"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
<path
style="fill:#6c5353;stroke:#ffffff;stroke-width:0.53339744px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M 107.06331,222.38985 C 74.793607,186.12917 238.88465,138.19113 170.64146,120.75367 102.39828,103.31623 55.191539,190.61605 107.06331,222.38985 z"
id="path2985-3-7-5-3"
inkscape:connector-curvature="0"
sodipodi:nodetypes="czc" />
<path
style="fill:#ffaaaa;stroke:#000000;stroke-width:0.4433642px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 470.54061,448.07463 c -0.81906,-20.22961 -0.34929,-85.5725 -0.28738,-88.80549 0.22028,-11.50539 14.28826,-23.38239 18.96815,-28.16485 6.69381,-6.84051 10.63367,-24.1413 10.63367,-24.1413 0,0 7.66108,1.59484 15.99558,0.32228 -0.57479,10.79807 10.56992,19.98425 15.69374,26.00513 4.085,4.80019 17.72735,17.93302 17.72842,24.6608 l 0.0144,90.98561 c 0.002,7.64377 -79.07713,5.85978 -78.74662,-0.86218 z"
id="path3238"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssccsssc" />
<path
style="fill:#806600;stroke:#000000;stroke-width:0.24125907px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 399.7668,385.77497 c 0,0 21.53755,19.2682 25.90887,18.54582 4.37133,-0.72237 48.06813,-50.91255 46.42734,-54.66976 -1.64079,-3.75722 -26.6823,-22.503 -26.6823,-22.503 0,0 21.12978,19.04623 18.25285,21.75963 -2.87694,2.7134 -25.38156,-12.1564 -25.38156,-12.1564 0,0 19.76193,17.40327 17.29569,20.28334 -2.16694,2.53055 -23.92968,-11.8921 -23.92968,-11.8921 0,0 21.10376,16.50059 18.04829,20.4778 -2.8429,3.70055 -24.74241,-11.95019 -24.74241,-11.95019 0,0 19.83028,16.13067 17.50778,19.33061 -1.66812,2.29833 -23.32596,-11.57609 -23.32596,-11.57609 0,0 20.11175,16.71856 18.33828,19.0103 -1.7735,2.29174 -22.79144,-13.01186 -22.79144,-13.01186 0,0 20.60175,16.25034 18.71649,18.87566 -1.65355,2.30266 -23.51521,-12.9419 -23.51521,-12.9419 0,0 18.80224,16.34655 17.04569,18.53661 -1.84308,2.29794 -22.67837,-11.88866 -22.67837,-11.88866 0,0 20.19488,14.82119 17.5525,17.89665 -2.64238,3.07545 -22.04685,-12.12646 -22.04685,-12.12646 z"
id="path3236"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csscscscscsczcscsczc" />
<g
id="g3225"
transform="matrix(0.32321071,-0.27398935,0.27398935,0.32321071,62.443723,389.20207)">
<path
sodipodi:nodetypes="zzsssczz"
inkscape:connector-curvature="0"
id="path3107-1"
d="m 611.08052,628.77068 c -11.35007,22.10407 -56.01094,59.25314 -83.44352,62.76065 -27.43258,3.50751 -41.51006,-12.1071 -39.78047,-34.59172 1.72958,-22.48462 15.56627,-39.78048 34.59172,-39.78048 19.02544,0 62.2175,0.80819 75.92567,-31.26515 l 96.41541,-225.58545 c 0.43194,16.48111 -1.23715,42.56061 -9.44327,62.75307 -8.20613,20.19246 -62.91548,183.60502 -74.26554,205.70908 z"
style="fill:#c8beb7;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<path
transform="matrix(-1.4565539,0,0,1.3670916,1456.7998,-410.12805)"
d="m 656.90489,779.51813 c 0,9.35069 -6.84445,16.93093 -15.28752,16.93093 -8.44307,0 -15.28752,-7.58024 -15.28752,-16.93093 0,-9.3507 6.84445,-16.93094 15.28752,-16.93094 8.44307,0 15.28752,7.58024 15.28752,16.93094 z"
sodipodi:ry="16.930933"
sodipodi:rx="15.287524"
sodipodi:cy="779.51813"
sodipodi:cx="641.61737"
id="path3111-2"
style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="arc" />
<g
transform="matrix(0.75214983,0.65899214,-0.65899214,0.75214983,652.97101,-319.95333)"
id="g3203"
style="fill:#c8beb7">
<path
style="fill:#c8beb7;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 554.77368,756.10744 c 11.35007,22.10407 56.01094,59.25314 83.44352,62.76065 27.43258,3.50751 41.51006,-12.1071 39.78047,-34.59172 -1.72958,-22.48462 -15.56627,-39.78048 -34.59172,-39.78048 -19.02544,0 -62.2175,0.80819 -75.92567,-31.26515 L 471.06487,487.64529 c -0.43194,16.48111 1.23715,42.56061 9.44327,62.75307 8.20613,20.19246 62.91548,183.60502 74.26554,205.70908 z"
id="path3107-1-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="zzsssczz" />
<path
sodipodi:type="arc"
style="fill:#ffffff;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
id="path3111-2-3"
sodipodi:cx="641.61737"
sodipodi:cy="779.51813"
sodipodi:rx="15.287524"
sodipodi:ry="16.930933"
d="m 656.90489,779.51813 c 0,9.35069 -6.84445,16.93093 -15.28752,16.93093 -8.44307,0 -15.28752,-7.58024 -15.28752,-16.93093 0,-9.3507 6.84445,-16.93094 15.28752,-16.93094 8.44307,0 15.28752,7.58024 15.28752,16.93094 z"
transform="matrix(1.4565539,0,0,1.3670916,-290.94556,-282.79129)" />
</g>
<path
transform="translate(351.33384,-132.23635)"
d="m 248.43053,750.76202 c 0,4.05032 -3.28343,7.33375 -7.33374,7.33375 -4.05032,0 -7.33375,-3.28343 -7.33375,-7.33375 0,-4.05031 3.28343,-7.33374 7.33375,-7.33374 4.05031,0 7.33374,3.28343 7.33374,7.33374 z"
sodipodi:ry="7.3337426"
sodipodi:rx="7.3337426"
sodipodi:cy="750.76202"
sodipodi:cx="241.09679"
id="path3219"
style="fill:#808080;fill-opacity:1;stroke:#666666;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="arc" />
<path
inkscape:connector-curvature="0"
id="path3223"
d="m 588.90551,616.11187 6.48217,4.86163"
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -0,0 +1,33 @@
+(function($, paypal, PAYPAL_ENV, CREATE_PAYMENT_URL, EXECUTE_PAYMENT_URL) {
$(document).ready(function() {
paypal.Button.render({
env: PAYPAL_ENV, // 'production', Optional: specify 'sandbox' environment
commit: true,
payment: function(resolve, reject) {
return paypal.request.post(CREATE_PAYMENT_URL)
.then(function(data) { resolve(data.id); })
.catch(function(err) { reject(err); });
},
onAuthorize: function(data) {
// Note: you can display a confirmation page before executing
return paypal.request.post(EXECUTE_PAYMENT_URL, { paymentID: data.paymentID, payerID: data.payerID })
.then(function(data) {
document.location = '@ViewBag.Urls.Details';
/* Go to a success page */
})
.catch(function(err) {
document.location = '/Manage/PaymentInfo/' + data.paymentID + '/?error=' + err;
/* Go to an error page */
});
}
}, '#paypal-button');
})
})(jQuery);

1
Yavsc/wwwroot/js/paypalbutton.min.js vendored Normal file
View File

@ -0,0 +1 @@
+function(n,t,e,o,u){n(document).ready(function(){t.Button.render({env:e,commit:!0,payment:function(n,e){return t.request.post(o).then(function(t){n(t.id)})["catch"](function(n){e(n)})},onAuthorize:function(n){return t.request.post(u,{paymentID:n.paymentID,payerID:n.payerID}).then(function(n){document.location="@ViewBag.Urls.Details"})["catch"](function(t){document.location="/Manage/PaymentInfo/"+n.paymentID+"/?error="+t})}},"#paypal-button")})}(jQuery);