How to properly add headers, paypal tutorial? - javascript

Im doing the paypal tutorial server side integration.
With PHP.
I'm having a problem.
I want to test funding failures,the last part
https://developer.paypal.com/docs/business/checkout/server-side-api-calls/handle-funding-failures/
I think I add the mock header in the right place but is doing nothing it keeps saying Transaction completed .
Whats the proper way to put it?
Paypal says:
In the call to Capture payment for order, include the PayPal-Mock-Response header with the mock_application_codes value set to INSTRUMENT_DECLINED. Sample code: -H "PayPal-Mock-Response: {"mock_application_codes" : "INSTRUMENT_DECLINED"}"
<script>
// Render the PayPal button into #paypal-button-container
paypal.Buttons({
// Call your server to set up the transaction
createOrder: function() {
return fetch('examplecreateorder.php', {
method: 'post',
headers: {
'content-type': 'application/json'
}
}).then(function(res) {
return res.json();
}).then(function(data) {
return data.id;
});
},
// Call your server to finalize the transaction
onApprove: function(data) {
return fetch('examplecaptureorder.php', {
method: 'post',
headers: {
'content-type': 'application/json',
'PayPal-Mock-Response': {
'mock_application_codes': 'INSTRUMENT_DECLINED'
}
},
body: JSON.stringify({
orderID: data.orderID
})
}
).then(function(res) {
return res.json().catch(error => console.error('Error:', error));
}).then(function(orderData) {
// Three cases to handle:
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
// (2) Other non-recoverable errors -> Show a failure message
// (3) Successful transaction -> Show confirmation or thank you
// This example reads a v2/checkout/orders capture response, propagated from the server
// You could use a different API or structure for your 'orderData'
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail && errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart(); // Recoverable state, per:
// https://developer.paypal.com/docs/checkout/integration-features/funding-failure/
}
if (errorDetail) {
var msg = 'Sorry, your transaction could not be processed.';
if (errorDetail.description) msg += '\n\n' + errorDetail.description;
if (orderData.debug_id) msg += ' (' + orderData.debug_id + ')';
return alert(msg); // Show a failure message
}
// Show a success message
alert('Transaction completed by + orderData.payer.name.given_name);
})
}
}).render('#paypal-button-container');
</script>

In the headers, the value for PayPal-Mock-Response should just be a string and not an object:
...
headers: {
'content-type': 'application/json',
'PayPal-Mock-Response': '{"mock_application_codes" : "INSTRUMENT_DECLINED" }'
},
...
Note the difference between what was being specified in OPs code as an object literal:
'PayPal-Mock-Response': {
'mock_application_codes': 'INSTRUMENT_DECLINED'
}
And the working code treating the value of PayPal-Mock-Response as a string:
'PayPal-Mock-Response': '{"mock_application_codes" : "INSTRUMENT_DECLINED" }'

Related

How to approve order from response links of create order api using paypal's javascript sdk?

I am trying to implement paypal advanced credit and debit cards payments using javascript sdk on client side. I am using the following example as reference https://developer.paypal.com/docs/business/checkout/advanced-card-payments/.
I have created the order, got links as response, how to approve the order using the approve url link as the user is using credit card details for payment without paypal login before performing order capture.
I know that it is not best approach for this implementation. firstly i want to try out this example as given in paypal docs.i will implement it in server side later to avoid security vulnerabilities.
<html>
<head>
<meta charset="utf-8"/>
<!-- Optimal rendering on mobile devices. -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Optimal Internet Explorer compatibility -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- Sample CSS styles for demo purposes. You can override these styles to match your web page's branding. -->
<link rel="stylesheet" type="text/css" href="https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css"/>
</head>
<body>
<!-- JavaScript SDK -->
<script src="https://www.paypal.com/sdk/js?components=buttons,hosted-fields&client-id=abc"
data-client-token="xyz">
<div align="center"> or </div>
<!-- Advanced credit and debit card payments form -->
<div class="card_container">
<form id="card-form">
<label for="card-number">Card Number</label><div id="card-number" class="card_field"></div>
<div>
<label for="expiration-date">Expiration Date</label>
<div id="expiration-date" class="card_field"></div>
</div>
<div>
<label for="cvv">CVV</label><div id="cvv" class="card_field"></div>
</div>
<label for="card-holder-name">Name on Card</label>
<input type="text" id="card-holder-name" name="card-holder-name" autocomplete="off" placeholder="card holder name"/>
<button value="submit" id="submit" class="btn">Pay</button>
</form>
</div>
<!-- Implementation -->
<script>
let orderId;
// Displays PayPal buttons
paypal.Buttons({
style: {
layout: 'horizontal'
},
createOrder: function(data, actions) {
return actions.order.create({
purchase_units: [{
amount: {
value: "1.00"
}
}]
});
},
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
console.log(details)
window.location.href = '/success.html';
});
}
}).render("#paypal-button-container");
// If this returns false or the card fields aren't visible, see Step #1.
if (paypal.HostedFields.isEligible()) {
// Renders card fields
paypal.HostedFields.render({
// Call your server to set up the transaction
createOrder: function () {
return fetch('https://api-m.sandbox.paypal.com/v2/checkout/orders', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer wert'
}
}).then(function(res) {
return res.json();
}).then(function(orderData) {
console.log(orderData)
orderId = orderData.id;
fetch('https://api-m.sandbox.paypal.com/v2/checkout/orders/' + orderId + '/capture/', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer AGeU7jOKBXFPa0Fe_e9Xv3g',
'PayPal-Request-Id': '7b92603e-77ed-4896-8e78-5dea2050476a'
},
"application_context": {
"return_url": "https://google.com"
}
}).then(function(res) {
console.log(res)
return res.json();
})
// return orderId;
});
},
onApprove: function(data) {
console.log(data)
return fetch('/my-server/capture-paypal-transaction', {
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: data.orderID
})
}).then(function(res) {
return res.json();
}).then(function(details) {
alert('Transaction funds captured from ' + details.payer_given_name);
})
},
styles: {
'.valid': {
'color': 'green'
},
'.invalid': {
'color': 'red'
}
},
fields: {
number: {
selector: "#card-number",
placeholder: "4111 1111 1111 1111"
},
cvv: {
selector: "#cvv",
placeholder: "123"
},
expirationDate: {
selector: "#expiration-date",
placeholder: "MM/YY"
}
}
}).then(function (cardFields) {
document.querySelector("#card-form").addEventListener('submit', (event) => {
event.preventDefault();
cardFields.submit({
// Cardholder's first and last name
cardholderName: document.getElementById('card-holder-name').value,
// Billing Address
// billingAddress: {
// // Street address, line 1
// streetAddress: document.getElementById('card-billing-address-street').value,
// // Street address, line 2 (Ex: Unit, Apartment, etc.)
// extendedAddress: document.getElementById('card-billing-address-unit').value,
// // State
// region: document.getElementById('card-billing-address-state').value,
// // City
// locality: document.getElementById('card-billing-address-city').value,
// // Postal Code
// postalCode: document.getElementById('card-billing-address-zip').value,
// // Country Code
// countryCodeAlpha2: document.getElementById('card-billing-address-country').value
// }
}).then(function (data) {
console.log(orderId)
console.log(data);
fetch('https://api-m.sandbox.paypal.com/v2/checkout/orders/' + orderId + '/capture/', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer AjOKBXFPa0Fe_e9Xv3g'
},
"application_context": {
"return_url": "https://google.com"
}
}).then(function(res) {
console.log(res)
return res.json();
}).then(function (orderData) {
console.log(orderData)
// Three cases to handle:
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
// (2) Other non-recoverable errors -> Show a failure message
// (3) Successful transaction -> Show confirmation or thank you
// This example reads a v2/checkout/orders capture response, propagated from the server
// You could use a different API or structure for your 'orderData'
var errorDetail = Array.isArray(orderData.details) && orderData.details[0];
if (errorDetail && errorDetail.issue === 'INSTRUMENT_DECLINED') {
return actions.restart(); // Recoverable state, per:
// https://developer.paypal.com/docs/checkout/integration-features/funding-failure/
}
if (errorDetail) {
var msg = 'Sorry, your transaction could not be processed.';
if (errorDetail.description) msg += '\n\n' + errorDetail.description;
if (orderData.debug_id) msg += ' (' + orderData.debug_id + ')';
return alert(msg); // Show a failure message
}
// Show a success message or redirect
alert('Transaction completed!');
})
}).catch(function (err) {
alert('Payment could not be captured! ' + JSON.stringify(err))
});
});
});
} else {
// Hides card fields if the merchant isn't eligible
document.querySelector("#card-form").style = 'display: none';
}
</script>
</body>
</html>
after executing above snippet, getting this as response
{name: "UNPROCESSABLE_ENTITY", details: [{issue: "ORDER_NOT_APPROVED",…}],…}
debug_id: "a63fbc3806995"
details: [{issue: "ORDER_NOT_APPROVED",…}]
0: {issue: "ORDER_NOT_APPROVED",…}
links: [{href: "https://developer.paypal.com/docs/api/orders/v2/#error-ORDER_NOT_APPROVED",…}]
0: {href: "https://developer.paypal.com/docs/api/orders/v2/#error-ORDER_NOT_APPROVED",…}
message: "The requested action could not be performed, semantically incorrect, or failed business validation."
name: "UNPROCESSABLE_ENTITY
how to approve the order using the approve url link as the user is using credit card details for payment without paypal login before performing order capture.
The approval URL link is not used in conjunction with the JavaScript SDK.
When using the hosted fields, the approval step is card fields submission, which triggers cardFields.submit({.
The use of hosted fields requires a server-side integration for capturing the approved (submitted) payment.

how to capture javascript request payload in php

I am sending a request payload from a javascript function like such
onApprove: function(data, actions) {
return actions.order.capture().then(function(details) {
fetch('https://www.eg.com/tq.php', {
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
orderID: id // i get the id here.
})
});
return window.location.href = "https://www.https://www.eg.com/tq.php";
});
}
}).render('#paypal-button-container');
In my PHP file I want to retrieve that id. I did :
$data = $_POST['orderID'];
AND
$data = json_decode($data);
echo $data->orderID;
AND
even tried changing the url to x-www-form-urlencoded. Still I do not get the value. When I check on the payload I do see the orderID, I also see a 200 OK. Can someone show me what i'm doing wrong? I did research stackoverflow and still can't get this to work. Please help.
fetch function will send GET request if you don't pass method: POST in config explicitly.
That's why you're not getting orderID from $_POST in server-side.
Insert method: "POST" in config like this.
fetch("https://www.eg.com/tq.php", {
method: "POST",
headers: {
"content-type": "application/json"
},
body: JSON.stringify({
orderID: id // i get the id here.
})
});

Trying to create multisig account for NEM on local machine but getting error

Hello Everyone I am trying to make plugin from Buildfire to be bale to create NEM account and to change it into multisig account using local network (ei localhost)
Here are the code snippets for the required things I would like to ask weather there is an issue in making of JSON missing bits in the json or any other errors I need to look up, I have tried to look up error and it's solution but met with no results. The error I get is :
"error: "Internal Server Error" message: "expected value for property
transaction, but none was found" status: 500"
let done = $.ajax({
url: "http://127.0.0.1:7890/account/generate"
}).done(function (data) {
/// check you have data to report on
///if (data && data.list && data.list.length) {
/// fill in the UI with the new data
var report = data;
PubKey = report.publicKey;
PKey = report.privateKey;
$('#address').text("Created Account");
$('#balance').text(report.address);
$('#summary').text(report.privateKey);
$('#vested').text(report.publicKey)
///}
});
var date = new Date();
var TS = date.getTime();
var xyz = {
xyz: JSON.stringify({
"transaction":
{
"timeStamp": TS, ///needs to be changed to current timestamp from creating of account
"fee": 20, ///have to check
"type": 4097,
"deadline": TS + 30000, ///need to be changed
"version": -1744830462, /// main(real) network 1744830465,
"signer": PubKey,
"modifications": [
{
"modificationType": 1,
"cosignatoryAccount": PbKey
}
],
"minCosignatories" : {
"relativeChange": 1
}
},
"privateKey": PKey
})
};
fetch("http://127.0.0.1:7890/transaction/prepare-announce",{
method : 'POST',
headers : {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body : JSON.stringify(xyz)
}).then(function (response) {
return response.json();
})
.then(function (result) {
alert(result);
}).catch (function (error) {
console.log('Request failed', error);
});
did you try normal transaction?
It looks you don't sign your transaction.
and DON'T FETCH YOUR PRIVATE KEY ON NETWORK.

Fetch(): Request body malformed

I want to make a fetch request to an API that accepts different types of body requests: twitter handle, facebook link, phone number, etc. The structure of the body is:
body: {
"typeOfHandle": "input"
}
Since there are different types of handles, I test the input type and assign it to the body accordingly, as seen below:
// handle is the input
let atSign = /^[#]/,
handleIsTwitter = atSign.test(handle.value),
handleType;
handleIsTwitter ? handleType = `"` + "twitter" + `"` : console.log("not twitter");
let abc = `"` + handle.value + `"`;
let bodyOfFetch = `{${handleType}: ${abc}}`;
console.log("body: " + bodyOfFetch);
fetch("xxx", {
method: "POST",
headers: {
Authorization: "xxx"
},
body: JSON.stringify(bodyOfFetch)
})
.then(function(res) {
return res.json();
})
.then(function(json) {
console.log(json);
});
However, this method returns a body malformed error. When I do the request statically (i.e. replace the variables with static text, e.g. "twitter": "#alex") it works. I double-triple-quadruple checked the syntax, I don't think that is the problem. Can it be an issue on the API's side?
In your example bodyOfFetch is a string ({"twitter": "#alex"}). Either you can send it directly, this is:
fetch("xxx", {
method: "POST",
headers: {
Authorization: "xxx"
},
body: bodyOfFetch
})
Or you can send a stringify object:
fetch("xxx", {
method: "POST",
headers: {
Authorization: "xxx"
},
body: JSON.stringify({[handleType]: abc})
})
But sending JSON.stringify(bodyOfFetch) will stringify a json string, this will add surrounding " and escape existing quotation marks: "{\\"twitter\\": \\"#alex\\"}"
Hope this helps.

CORS error when trying to post message

I have an AngularJS Application I am trying to post a message through. I am successfully able to log the user in, get the access token, and I have ensured I have my domain in the JavaScript Origins within Yammer.
Whenever I try to post a message, however, I get the following error:
The strange thing is when it does the preflight it seems OK but as the error states I can't figure out why it isn't coming back in the CORS header as I have it registered within the Yammer Client area.
Here is the code for posting:
$scope.YammerPost = function (Yammer) {
var _token = Yammer.access_token.token;
var config = {
headers: {
'Authorization': 'Bearer ' + _token
}
};
$http.post('https://api.yammer.com/api/v1/messages.json', { body: 'blah blah', group_id: XXXXXXX }, config);
}
I call that scope variable in the view via a button click.
Here is the logic I use to sign the user in:
function checkYammerLogin() {
$scope.Yammer = {};
yam.getLoginStatus(
function (response) {
if (response.authResponse) {
$scope.Yammer = response;
console.dir(response); //print user information to the console
}
else {
yam.platform.login(function (response) {
if (response.authResponse) {
$scope.Yammer = response;
console.dir(response);
}
});
}
}
);
}
I ended up finding the issue.
For some odd reason, every time I would try to use an $http post it would include an Auth token from AD (app using Azure AD for authentication).
I ended up using jQuery inside of my Angular scope function on the button click and it works as I can control the headers for the request.
$.ajax({
url: 'https://api.yammer.com/api/v1/messages.json',
type: 'post',
data: {
body: 'this is a test from jQuery using AngularJS',
group_id: <group_id>
},
headers: {
'Authorization': _token
},
dataType: 'json',
success: function (data) {
console.info(data);
}
});
Fixed the issue and I can now post.
If anyone sees any issues with this practice please let me know, still a little new to angular

Categories

Resources