How to run postmapping in a RestController in Springboot - javascript

I am very new to Springboot and do not fully understand how postmapping works. Currently, I have to implement Stripe payment system. From what I gathered, Stripe provides a custom payment flow but it is using Spark framework. I was able to create a Springboot Postmapping in place of the Spark Post. I have tried different methods I see online with no success. What would be the best method to do the following.
My PostMapping Code
#PostMapping("/create-payment-intent")
public String StripeTest(HttpServletRequest request, HttpServletResponse response) throws StripeException {
System.out.println("Stripe Controller Begins");
Gson gson = new Gson();
response.setContentType("application/json");
Stripe.apiKey = "sk_test_key";
try {
StringBuilder buffer = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
String dataBody = buffer.toString();
CreatePayment postBody = gson.fromJson(dataBody,
CreatePayment.class);
PaymentIntentCreateParams createParams = new PaymentIntentCreateParams.Builder()
.setCurrency("USD")
.setAmount(new Long(calculateOrderAmount(postBody.getItems())))
.build();
// Create a PaymentIntent with the order amount and currency
PaymentIntent intent = PaymentIntent.create(createParams);
// Send publishable key and PaymentIntent details to client
return gson.toJson(new Server.CreatePaymentResponse(intent.getClientSecret()));
} catch (JsonSyntaxException e) {
e.printStackTrace();
return "";
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
I need to get the post to run then fetch the data using my javascript:
// Fetches a payment intent and captures the client secret
async function initialize() {
const response = await fetch("/create-payment-intent", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ items }),
});
const { clientSecret } = await response.json();
const appearance = {
theme: 'stripe',
};
elements = stripe.elements({ appearance, clientSecret });
const paymentElementOptions = {
layout: "tabs",
};
const paymentElement = elements.create("payment", paymentElementOptions);
paymentElement.mount("#payment-element");
}
Which will then be injected into the payment-id in the html below:
<form id="payment-form" action='/create-payment-intent' method='POST'>
<div id="payment-element">
<!--Stripe.js injects the Payment Element-->
</div>
<button id="submit">
<div class="spinner hidden" id="spinner"></div>
<span id="button-text">Pay now</span>
</button>
<div id="payment-message" class="hidden"></div>
</form>
I have tried $.Ajax from an example I read with no luck.

Related

Put method is not working 403 forbidden response

When I send a put request to a user in my spring boot backend, I got a 403 forbidden response. But when I send the same request through postman it gets updates. Can anyone help me to correct my code? I'll put all the relevant code segments below. (front - angular-cli 12, back - spring boot)
front end requesting method
updateUser(userId: string, profilePic: string, shortDes: string, username: string, email: string, phoneNumber: string): Observable<any> {
const body: FormData = new FormData();
body.append('id', userId);
body.append('username', username);
body.append('email', email);
body.append('shortDes', shortDes);
body.append('profilePic', profilePic);
body.append('phoneNum', phoneNumber);
console.log(userId,username,)
return this.http.put<HttpResponse<any>>(environment.baseUrl + `/api/v1/users/` + userId, body,{
observe: 'response'
});
}
backend receiving method
#PutMapping(
value = "/{id}",
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.MULTIPART_FORM_DATA_VALUE
)
#ResponseStatus(HttpStatus.OK)
#ResponseBody
public ResponseEntity<?> updateUser( #ModelAttribute UserBody body, #PathVariable("id") int id){
if (body.getId() != id) {
return new ResponseEntity<>("Mismatch userId !!", HttpStatus.BAD_REQUEST);
} else if (true) {
// TODO: 5/26/2022 handle the multi part file size from this stage before save it
}
try {
String filePath = null;
if (body.getProfilePic() != null) {
filePath = fileService.saveUserProfilePicture(body.getProfilePic());
UserDTO user = bo.getUser(id);
fileService.deleteFile(user.getProfilePicture());
}
UserDTO dto = new UserDTO();
dto.setId(body.getId());
dto.setUsername(body.getUsername());
dto.setEmail(body.getEmail());
dto.setShortDescription(body.getShortDes());
dto.setProfilePicture(filePath);
dto.setContactNum(body.getPhoneNum());
bo.updateUserNormalDetails(dto);
return new ResponseEntity<>(dto, HttpStatus.CREATED);
} catch (NoSuchElementException e) {
return new ResponseEntity<>("No user is found !!", HttpStatus.NOT_FOUND);
} catch (Exception e) {
return new ResponseEntity<>("Something went wrong !!", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
postman request
The error I get from the spring-boot backend when I send a put request from the front-end
2022-07-04 10:44:40.619 WARN 3068 --- [nio-8080-exec-7] o.springframework.validation.DataBinder : Skipping URI variable 'id' because request contains bind value with same name.
HTTP request via browser

Axios get Request not receiving data

I am trying to download the content of my s3 bucket, and when I hit the API endpoint the data shows in my Intellij console, but in my postman and browser console I simply get an empty object.
Is there a certain why I am supposed to receive this in an Axios request?
Axios -
downloadLocations() {
axios.get("http://localhost:8080/api/v1/targetLocation/downloadSearchData")
.then((res) => {
console.log(res.data)
// We will need to retrieve the data into a downloadable blob
// const content = new Blob([JSON.stringify(???)],{ type: 'text/plain;charset=utf-8' })
// const fileName = `test.txt`
// saveAs(content, fileName)
}, (error) => {
console.log(error);
});
}
Service -
public ByteArrayOutputStream downloadSearchData() throws IOException {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
AmazonS3 s3client = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(awsRegion)
.build();
var s3Object = s3client.getObject("downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json");
var out = new ByteArrayOutputStream();
try (var in = s3Object.getObjectContent()) {
in.transferTo(out);
}
System.out.println(out);
return out;
}
Controller -
#GetMapping(value = "downloadSearchData")
public ByteArrayOutputStream downloadSearchData() throws IOException {
return targetLocationService.downloadSearchData();
}
Ok, I found the answer. I changed the Service and Controller return value to String and it now works perfectly
public String downloadSearchData() throws IOException {
BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
AmazonS3 s3client = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withRegion(Regions.GovCloud)
.build();
var s3Object = s3client.getObject("downloadable-cases", "7863784198_2021-08-16T13_30_06.690Z.json");
var out = new ByteArrayOutputStream();
try (var in = s3Object.getObjectContent()) {
in.transferTo(out);
}
return out.toString();
}

JWT token stored in localstorage lost after window.location.href call

I am using Javascript Fetch API to invoke Dot net web API.
Using Visual Studio code for HTML/Javascript & Visual Studio 2019 for Dot Net Web API.
I am trying to implement login functionality using Dot net C# Web API, that will return JWT token in the response and use the token later to invoke separate Web API/Service (e.g. EmployeeInfo ).
Login page :
It displays user id and password fields and the button "Login"
Once user clicks on login button, the function fnlogin is invoked
function fnlogin() {
const uname = document.getElementById('uname').value;
const pwd = document.getElementById('pwd').value;
const logindata = {
username: uname,
password: pwd
}
const loginurl = 'http://localhost:13402/api/Auth/Login';
authenticate(loginurl, logindata);
}
async function authenticate(loginurl, logindata) {
console.log(logindata)
const response = await fetch(loginurl , {
method: "POST",
mode: "cors",
body: JSON.stringify(logindata),
headers: { "Content-type" : "application/json, charset=UTF-8"}
});
const rdata = await response.json();
console.log(rdata);
if (!rdata.success) {
document.getElementById("loginMessage").innerHTML = rdata.message;
return;
}
const inMemoryToken = rdata.data
localStorage.setItem('user', JSON.stringify(rdata));
window.location.href = "http://localhost:5500/Employeeinfo1.html";
}
The Web API returns JWT token properly.
The code in controller is as follows :
[HttpPost("Login")]
public async Task<ActionResult<ServiceResponse<string>>> Login(UserLoginDto request)
{
var response = await _authRepo.Login(
request.Username, request.Password
);
if (!response.Success)
{
return BadRequest(response);
}
return Ok(response);
}
``
The code in AuthRepository class is as follows :
public class AuthRepository : IAuthRepository
{
private readonly AppDbContext _context;
private readonly IConfiguration _configuration;
public AuthRepository(AppDbContext context, IConfiguration configuration)
{
_configuration = configuration;
_context = context;
}
public async Task<ServiceResponse<string>> Login(string username, string password)
{
var response = new ServiceResponse<string>();
var user = await _context.Users.FirstOrDefaultAsync(x => x.Username.ToLower().Equals(username.ToLower()));
if (user == null)
{
response.Success = false;
response.Message = "User not found.";
}
else if (!VerifyPasswordHash(password, user.PasswordHash, user.PasswordSalt))
{
response.Success = false;
response.Message = "Wrong password.";
}
else
{
response.Data = CreateToken(user);
}
return response;
}
public async Task<ServiceResponse<User>> Register(User user, string password)
{
ServiceResponse<User> response = new ServiceResponse<User>();
if (await UserExists(user.Username))
{
response.Success = false;
response.Message = "User already exists.";
return response;
}
CreatePasswordHash(password, out byte[] passwordHash, out byte[] passwordSalt);
user.PasswordHash = passwordHash;
user.PasswordSalt = passwordSalt;
_context.Users.Add(user);
await _context.SaveChangesAsync();
response.Data = user;
return response;
}
public async Task<bool> UserExists(string username)
{
if (await _context.Users.AnyAsync(x => x.Username.ToLower().Equals(username.ToLower())))
{
return true;
}
return false;
}
private void CreatePasswordHash(string password, out byte[] passwordHash, out byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512())
{
passwordSalt = hmac.Key;
passwordHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
}
}
private bool VerifyPasswordHash(string password, byte[] passwordHash, byte[] passwordSalt)
{
using (var hmac = new System.Security.Cryptography.HMACSHA512(passwordSalt))
{
var computedHash = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(password));
for (int i = 0; i < computedHash.Length; i++)
{
if (computedHash[i] != passwordHash[i])
{
return false;
}
}
return true;
}
}
private string CreateToken(User user)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username)
};
var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_configuration.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokendDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = System.DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokendDescriptor);
return tokenHandler.WriteToken(token);
}
4. Once the JWT token is returned , it is stored in LocalStorage. I verified in Chrome Dev Tools
But after the next screen is displayed, when I check in Chrome dev tools, the object/token is no longer present in the Local Storage.
Is this because of window.location.href will remove all local data in localStorage in the browser ?
I want to be able to use the token to pass to remaining html screens and web api
You are storing an item in the local storage of http://127.0.0.1:5500 and trying to read it from http://localhost:5500.
From Window.localStorage in MDN Web Docs:
The localStorage read-only property of the window interface allows you to access a Storage object for the Document's origin;
And about Origin:
Web content's origin is defined by the scheme (protocol), host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match.
As you see, for the browser the origins are different because the host does not match: 127.0.0.1 is not the same string as localhost.
Use either localhost or 127.0.0.1 everywhere, but do not use both.

how to integrate asp.net mvc 5 with latest Paypal checkout .net sdk v2?

I tried to use Paypal Checkout SDK V2 in my Asp.Net MVC 5 project with .Net Framework 4.7.2 the but this seems to be something missing or wrong from my side.
I am just trying to integrate Paypal Checkout sdk and want to create an order so that my payment 'll be proceed by some paypal user and I only want to show one Pay Now button.
The SDK link is here:
https://github.com/paypal/Checkout-NET-SDK
and followed these links
https://developer.paypal.com/docs/checkout/reference/server-integration/get-transaction/#on-the-client
https://developer.paypal.com/demo/checkout/#/pattern/server
This is my code for trying it
C# Code
public class CheckoutController : Controller
{
public ActionResult Index()
{
ViewBag.ClientId = PayPalClient.ClientId;
ViewBag.CurrencyCode = "GBP"; // Get from a data store
ViewBag.CurrencySign = "£"; // Get from a data store
return View();
}
//[Route("api/paypal/checkout/order/create")]
public async static Task<HttpResponse> createOrder()
{
HttpResponse response;
// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
var order = new OrderRequest()
{
CheckoutPaymentIntent = "CAPTURE",
PurchaseUnits = new List<PurchaseUnitRequest>()
{
new PurchaseUnitRequest()
{
AmountWithBreakdown = new AmountWithBreakdown()
{
CurrencyCode = "USD",
Value = "100.00"
}
}
},
ApplicationContext = new ApplicationContext()
{
ReturnUrl = "https://www.example.com",
CancelUrl = "https://www.example.com"
}
};
// Call API with your client and get a response for your call
var request = new OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(order);
response = await PayPalClient.Client().Execute(request);
var statusCode = response.StatusCode;
Order result = response.Result<Order>();
Console.WriteLine("Status: {0}", result.Status);
Console.WriteLine("Order Id: {0}", result.Id);
Console.WriteLine("Intent: {0}", result.CheckoutPaymentIntent);
Console.WriteLine("Links:");
foreach (LinkDescription link in result.Links)
{
Console.WriteLine("\t{0}: {1}\tCall Type: {2}", link.Rel, link.Href, link.Method);
}
return response;
}
public async static Task<HttpResponse> captureOrder()
{
// Construct a request object and set desired parameters
// Replace ORDER-ID with the approved order id from create order
var request = new OrdersCaptureRequest("APPROVED-ORDER-ID");
request.RequestBody(new OrderActionRequest());
HttpResponse response = await PayPalClient.Client().Execute(request);
var statusCode = response.StatusCode;
Order result = response.Result<Order>();
Console.WriteLine("Status: {0}", result.Status);
Console.WriteLine("Capture Id: {0}", result.Id);
return response;
}
/// <summary>
/// This action is called when the user clicks on the PayPal button.
/// </summary>
/// <returns></returns>
//[Route("api/paypal/checkout/order/create")]
public async Task<SmartButtonHttpResponse> Create()
{
var request = new PayPalCheckoutSdk.Orders.OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(OrderBuilder.Build());
// Call PayPal to set up a transaction
var response = await PayPalClient.Client().Execute(request);
// Create a response, with an order id.
var result = response.Result<PayPalCheckoutSdk.Orders.Order>();
var payPalHttpResponse = new SmartButtonHttpResponse(response)
{
orderID = result.Id
};
return payPalHttpResponse;
}
/// <summary>
/// This action is called once the PayPal transaction is approved
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/approved/{orderId}")]
public ActionResult Approved(string orderId)
{
return Json("Sucess", JsonRequestBehavior.AllowGet);
}
/// <summary>
/// This action is called once the PayPal transaction is complete
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/complete/{orderId}")]
public ActionResult Complete(string orderId)
{
// 1. Update the database.
// 2. Complete the order process. Create and send invoices etc.
// 3. Complete the shipping process.
return Json("Completed", JsonRequestBehavior.AllowGet);
}
/// <summary>
/// This action is called once the PayPal transaction is complete
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/cancel/{orderId}")]
public ActionResult Cancel(string orderId)
{
// 1. Remove the orderId from the database.
return Json("Cancel", JsonRequestBehavior.AllowGet);
}
/// <summary>
/// This action is called once the PayPal transaction is complete
/// </summary>
/// <param name="orderId"></param>
/// <returns></returns>
//[Route("api/paypal/checkout/order/error/{orderId}/{error}")]
public ActionResult Error(string orderId,
string error)
{
// Log the error.
// Notify the user.
string temp = System.Web.HttpUtility.UrlDecode(error);
return Json(temp, JsonRequestBehavior.AllowGet);
}
}
public static class OrderBuilder
{
/// <summary>
/// Use classes from the PayPalCheckoutSdk to build an OrderRequest
/// </summary>
/// <returns></returns>
public static OrderRequest Build()
{
// Construct a request object and set desired parameters
// Here, OrdersCreateRequest() creates a POST request to /v2/checkout/orders
OrderRequest order = new OrderRequest()
{
CheckoutPaymentIntent = "CAPTURE",
PurchaseUnits = new List<PurchaseUnitRequest>()
{
new PurchaseUnitRequest()
{
AmountWithBreakdown = new AmountWithBreakdown()
{
CurrencyCode = "USD",
Value = "100.00"
}
}
},
ApplicationContext = new ApplicationContext()
{
ReturnUrl = "https://www.example.com",
CancelUrl = "https://www.example.com"
}
};
// Call API with your client and get a response for your call
var request = new OrdersCreateRequest();
request.Prefer("return=representation");
request.RequestBody(order);
return order;
}
}
public class PayPalClient
{
public static string ClientId = " your client id";
public static string Secrets = "your client secret";
public static string SandboxClientId { get; set; } =
"<alert>{SandboxClientId}</alert>";
public static string SandboxClientSecret { get; set; } =
"<alert>{SandboxClientSecret}</alert>";
public static string LiveClientId { get; set; } =
"<alert>{PayPal LIVE Client Id}</alert>";
public static string LiveClientSecret { get; set; } =
"<alert>{PayPal LIVE Client Secret}</alert>";
public static PayPalEnvironment Environment()
{
//return new SandboxEnvironment("<alert>SandboxClientId</alert>",
// "<alert>SandboxClientSecret</alert>");
return new SandboxEnvironment(ClientId, Secrets);
}
public static PayPalCheckoutSdk.Core.PayPalHttpClient Client()
{
return new PayPalHttpClient(Environment());
}
public static PayPalCheckoutSdk.Core.PayPalHttpClient Client(string refreshToken)
{
return new PayPalHttpClient(Environment(), refreshToken);
}
public static String ObjectToJSONString(Object serializableObject)
{
MemoryStream memoryStream = new MemoryStream();
var writer = JsonReaderWriterFactory.CreateJsonWriter(memoryStream,
Encoding.UTF8,
true,
true,
" ");
var ser = new DataContractJsonSerializer(serializableObject.GetType(),
new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
});
ser.WriteObject(writer,
serializableObject);
memoryStream.Position = 0;
StreamReader sr = new StreamReader(memoryStream);
return sr.ReadToEnd();
}
}
public class SmartButtonHttpResponse
{
readonly PayPalCheckoutSdk.Orders.Order _result;
public SmartButtonHttpResponse(PayPalHttp.HttpResponse httpResponse)
{
Headers = httpResponse.Headers;
StatusCode = httpResponse.StatusCode;
_result = httpResponse.Result<PayPalCheckoutSdk.Orders.Order>();
}
public HttpHeaders Headers { get; }
public HttpStatusCode StatusCode { get; }
public PayPalCheckoutSdk.Orders.Order Result()
{
return _result;
}
public string orderID { get; set; }
}
View html is
<!-- Set up a container element for the PayPal smart button -->
<div id="paypal-button-container"></div>
#section scripts
{
<script src="https://www.paypal.com/sdk/js?client-id=#ViewBag.ClientId"></script>
<script type="text/javascript">
var orderId;
function httpGet(url) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
return xmlHttp.responseText;
}
paypal.Buttons({
// Set up the transaction
enableStandardCardFields: true,
createOrder: function (data, actions) {
orderId = data.orderID;
console.log("Start");
console.log(data);
console.log(actions);
console.log("End");
return fetch(
'/PaypalPayments/create/', {
method: 'post'
}).then(function (res) {
return res.json();
}).then(function (data) {
return data.orderID;
});
},
// Finalise the transaction
onApprove: function (data, actions) {
return fetch('/PaypalPayments/approved/' + data.orderID, {
method: 'post'
}).then(function (res) {
return actions.order.capture();
}).then(function (details) {
// (Preferred) Notify the server that the transaction id complete
// and have an option to display an order completed screen.
window.location.replace('/PaypalPayments/complete/' +
data.orderID + '/#ViewBag.CurrencyCode');
// OR
// Notify the server that the transaction id complete
//httpGet('/api/paypal/checkout/order/complete/' + data.orderID);
// Show a success message to the buyer
alert('Transaction completed by ' + details.payer.name.given_name + '!');
});
},
// Buyer cancelled the payment
onCancel: function (data, actions) {
httpGet('/PaypalPayments/cancel/' + data.orderID);
},
// An error occurred during the transaction
onError: function (err) {
debugger;
fetch(
'/PaypalPayments/error/', {
method: 'post',
headers: { 'Content-type': 'application/json' },
body: JSON.stringify({ orderId: orderId, error: encodeURIComponent(err)})
}).then(function (res) {
return res.json();
}).then(function (data) {
return data.orderID;
});
}
}).render('#paypal-button-container');
</script>
}
The error which I 'll have to receive is given below:
My create post request is successful by returning 200 status.
After this request, the control instantly goes to Error function and throwing this error.
Error: Unexpected token P in JSON at position 0"
The complete error detail is mentioned below
SyntaxError: Unexpected token P in JSON at position 0
Error: Unexpected token P in JSON at position 0
at Qt.error (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:60544)
at Object.<anonymous> (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68311)
at JSON.parse (<anonymous>)
at o (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68170)
at dr (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68323)
at u.on (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:72994)
at br (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:73131)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79250
at Function.n.try (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:14118)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79047
Error: Unexpected token P in JSON at position 0
at Qt.error (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:60544)
at Array.<anonymous> (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68311)
at JSON.parse (<anonymous>)
at o (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68170)
at dr (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:68323)
at u.on (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:72994)
at br (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:73131)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79250
at Function.n.try (https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:14118)
at https://www.paypal.com/sdk/js?client-id=ATiT9hZAk22xK68Sg9cE3qg24jH1GP9eTm6XW2O47fPl3cligEblR35E1f24OnLg8XOmD7Y_tcnHDhPZ:2:79047
Can anybody guide me properly? I tried different articles but I am still getting these errors.
When you fetch /PaypalPayments/create/ from your server , what do you get back?
Obviously you aren't getting back valid JSON, but your code is trying to parse it as JSON.
Change your server code to only give back valid JSON. The code actually seems okay, so perhaps there is something wrong with the /PayPalPayments/create/ route that is hardcoded in the client-side code.
It would also be wise to change your client-side code to follow the best sample available, which is at https://developer.paypal.com/demo/checkout/#/pattern/server and demonstrates how to properly handle errors for the capture
(Just noticed the code in your example uses actions.order.capture() combined with this server-side integration, which is rather awful -- seems the server-side captureOrder task never even gets called, which is rather the whole point of using server-side APIs in the first place, if you don't capture from the server you get none of the benefits)

How to write an JavaScript client for connecting an OAuth 2.0 Secure Spring WebSocket API?

I need to create a Websocket Server using spring which was easily completed by using the below code
#Configuration
#EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new SocketHandler(), "/poll");
registry.addHandler(new SocketPushHandler(), "/push");
}
}
Where SocketHandler and SocketPushHandler are the handler classes for the websocket endpoints.
Till this very thing is good able to run the server and connect to the endpoint using normal socket = new WebSocket(websocketUrl) javascript code.
Now we need to have OAuth 2.0 Security implemented on the API endpoints which is done easily by importing some Spring security dependencies.\
Now the hard part is writing the client to connect the secure endpoint by passing the Oauth Authorization beaer <token> as part of header.
From documents came to know that we can't send headers to Web-socket endpoints.
So according to the information form this Is it possible to secure WebSocket APIs with OAuth 2.0? link I created a API gateway /open-ws Request type GET to which the client would connect and send the authorization headers and this endpoint internally on server-side will open an WebSocket Client connection passing the the headers as javax.websocket.WebSocketContainer supports websocket client with custom headers.
So now my javascript first makes an GET ajax call to the Gateway endpoint and on success makes an new websocket request.
Below is the Spring API mimicking as gateway
#RequestMapping(value = "/open-ws", method = RequestMethod.GET)
public void getOperatorTokenDefinition(#RequestHeader(value = HttpHeaders.AUTHORIZATION) String bearerToken,
#RequestHeader(value = "websocketURL") String websocketURL,
HttpServletRequest acquireTokenServletRequest, HttpServletResponse response) {
webSocketClient.connecttoserver(websocketURL, acquireTokenServletRequest.getRemoteHost(), bearerToken, response);
// ResponseEntity<String> responseEntity = new ResponseEntity<>("connected", HttpStatus.OK);
}
}
Below is my Spring side client.
#Component
public class WebSocketClient {
private Session client;
public void connecttoserver(String websocketURL,String host,String bearerAccessToken, HttpServletResponse response) {
final AtomicReference<String> message = new AtomicReference<>();
Endpoint endpoint = new Endpoint() {
#Override
public void onOpen(Session session, EndpointConfig config) {
System.out.println("WSS OPEN!!!!!");
try (OutputStream output = response.getOutputStream()) {
output.write(session.getId());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
ClientEndpointConfig.Configurator configurator = new ClientEndpointConfig.Configurator() {
#Override
public void beforeRequest(Map<String, List<String>> headers) {
List<String> connection = new ArrayList<>(1);
connection.add("Upgrade");
List<String> origin = new ArrayList<>(1);
origin.add(originURL);
List<String> upgradeWebsocket = new ArrayList<>(1);
upgradeWebsocket.add("WebSocket");
List<String> host = new ArrayList<>(1);
host.add(websocketURL);
List<String> contenttype = new ArrayList<>(1);
contenttype.add("application/json");
List<String> authorization = new ArrayList<>(1);
authorization.add("Bearer " + bearerAccessToken);
List<String> tenantId = new ArrayList<>(1);
tenantId.add(tenantID);
List<String> key = new ArrayList<>(1);
key.add("HcFOxrSD89ya65X2qMF9lQ==");
List<String> version = new ArrayList<>(1);
version.add("13");
headers.put("Connection", connection);
headers.put("Upgrade", upgradeWebsocket);
headers.put("Host", host);
headers.put("Origin", origin);
// headers.put("Content-Type", contenttype);
headers.put("Authorization", authorization);
headers.put("Sec-WebSocket-Key", key);
headers.put("Sec-WebSocket-Version", version);
}
};
ClientEndpointConfig clientConfig = ClientEndpointConfig.Builder.create().configurator(configurator).build();
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
try {
// if (!this.client.isOpen())
this.client = container.connectToServer(endpoint, clientConfig, URI.create(websocketURL));
client.addMessageHandler(new MessageHandler.Whole<String>() {
#Override
public void onMessage(String response) {
// TODO Auto-generated method stub
message.set(response);
// System.out.println("response>>>>>>>>>>>>>>>>>>> "+response.toString());// this dosent work
}
});
System.out.println("Response--------------------------------->" + message.get());
// client.close();
} catch (DeploymentException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Below is the JQuery code
$(document).ready(function(){
$("#Websocketconnect").click(function(){
$.ajax({
type: 'GET',
url: hostUrl.value,
headers: {
"Authorization":websocketToken.value,
"websocketURL":websocketUrl.value,
"Content-type":"text/plain"
},
success: function(result){
$("#readystatus").value = result;
webSocketCycleEvent(websocketUrl.value);
}});
});
});
function webSocketCycleEvent(websocketUrl){
socket = new WebSocket(websocketUrl);
socket.onerror = function(error) {
console.log('WebSocket Error: ' + error);
};
// Show a connected message when the WebSocket is opened.
socket.onopen = function(event) {
socketStatus.innerHTML = 'Connected to: ' + websocketUrl;
socketStatus.className = 'open';
};
socket.onmessage = function(event) {
var message = event.data;
messagesList.innerHTML += '<li class="received"><span>Received:</span>' +
message + '</li>';
};
socket.onclose = function(event) {
socketStatus.innerHTML = 'Disconnected from WebSocket.';
socketStatus.className = 'closed';
};
}
form.onsubmit = function(e) {
e.preventDefault();
// Retrieve the message from the textarea.
var message = messageField.value;
socket.send(message);
messagesList.innerHTML += '<li class="sent"><span>Sent:</span>' + message +
'</li>';
// Clear out the message field.
messageField.value = '';
return false;
};
I am not to connect to the websocket and send the socket.id as the server-side gives an
javax.websocket.DeploymentException: The HTTP response from the server [400] did not permit the HTTP upgrade to WebSocket
at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:343)
at com.example.simplewebsocketserver.WebSocketClient.connecttoserver(WebSocketClient.java:101)
at com.example.simplewebsocketserver.WebSocketController.getOperatorTokenDefinition(WebSocketController.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
So the Question arises is this the proper way of connecting the Oauth 2.0 Websocket, if yes how to deal with the above error, if no how to send headers to the authorization endpoint.
Note: No using Stomp because we are not yet confirmed whether the actual client i.e UI will allow/have stomp JS.

Categories