I can't work out why I'm getting this error from Stripe on submission of my form:
An unexpected error has occurred submitting your credit card to our secure credit card processor. This may be due to network connectivity issues, so you should try again (you won't be charged twice). If this problem persists, please let us know!
However the transaction is processed successfully.
My code deviates from the example forms only because I'm validating the code using Parsely and want to generate the token only if the rest of the form is valid:
if $(".error-block").length > 0 && $(".error-block").html() != ''
$.scrollTo($(".error-block"))
Stripe.setPublishableKey($('#stripe_key').val())
stripeResponseHandler = (status, response) ->
if response.error
$(".error-block").text(response.error.message)
$('#join-button').attr("disabled", false).removeClass('disable').html('Join')
else
$form = $('#user_new')
token = response['id']
$('#user_stripe_token').val(token)
$('#user_card_number').val('')
$('#user_card_cvc').val('')
$('#user_card_expiry_month').val('')
$('#user_card_expiry_year').val('')
$form.get(0).submit()
$('#user_new').submit ->
valid = $(#).parsley().isValid()
if valid != false
$('#join-button').attr("disabled", true).addClass('disable').html('Please wait...')
Stripe.card.createToken({
number: $('#user_card_number').val(),
cvc: $('#user_card_cvc').val(),
exp_month: $('#user_card_expiry_month').val(),
exp_year: $('#user_card_expiry_year').val()
name: $('#user_first_name').val() + " " + $('#user_last_name').val()
}, stripeResponseHandler)
return false
return false
Any ideas where I'm going wrong?
Related
I was thinking about integration in the background without any website other than the payment page as part of a desktop application in c++.
Would it be possible to following the following scenario:
1. Generate the invoice / sale and via REST API obtain some sort of unique ID for the transaction to come.
2. Redirect to Paypal web site to a ad-hoc payment page, using the unique ID.
3. In the background, check every few minutes, via REST API, if the payment was made.
We finally found a way, which is why I publish this answer along with some code (a POC) we have developed. This is a POC for a built-in payment processing engine which allows you to accept payments from any credit card holder (regardless of being a PayPal customer) and pay for unlocking a software product or for specific features.
To process payments you need to apply as a PayPal developer and obtain your own PayPal credentials. You will then receive 2 sets of credentials. One for tests ("sandbox") and the other for real life.
First you can use the Sandbox to test the API
Void InitPayPal(BOOL Sandbox, LPTSTR User, LPTSTR password, LPTSTR signature, LPTSTR successUrl, LPTSTR failedURL)
Sandbox – indicates whether you are testing your integration using PayPal's Sandbox account, or going live.
User – your PayPal user name
Password – your PayPal password
Signature – you PayPal signature
successUrl – a url leading to a web page which you wish to be shown after successful payment.
failedURL – a url leading to a web page which you wish to be shown after failed / cancalled payment.
This function is straight forward:
void InitPayPal(BOOL Sandbox, LPTSTR User, LPTSTR password, LPTSTR signature, LPTSTR successUrl, LPTSTR failedURL, LPWSTR ProductName)
{
m_sandbox = Sandbox;
m_user = User;
m_password = password;
m_signature = signature;
m_SuccessURL = successUrl;
m_FailureURL = failedURL;
m_ProductName = ProductName;
CUR_CHAR = L"$";
SYSTEMTIME st;
GetSystemTime(&st);
g_tPayStart = CTime(st);
InitilizedPaypal = TRUE;
}
Initiating a payment
When you wish to initiate a payment from your program, you call the following function which I wrote which generally build a string (ExpChkoutStr) and use the following PayPal API call:
// Send string to PayPal server
WinHttpClient WinClient1(ExpChkoutStr.GetBuffer());
WinClient1.SetRequireValidSslCertificates(false);
WinClient1.SendHttpRequest(L"GET");
httpResponseContent1 = WinClient1.GetResponseContent();
CString strTransactionRet = UrlDecode(httpResponseContent1.c_str());
The WinHTTP class was developed by Cheng Shi.
The Express Checkout String (ExpChkoutStr) is generated by another function which uses the member variables' values and the transaction details into a single string:
CString result;
result = (m_sandbox) ? PAYPAL_SANDBOX_HTTPS : PAYPAL_REAL_HTTPS;
result += Q_USER;
result += m_user;
result += AND_PASSWORD;
result += m_password;
result += AND_SIGNATURE;
result += m_signature;
result += AND_PAYMENTAMOUNT;
result += strAmount;
result += L"&METHOD=SetExpressCheckout";
result += AND_RETURN_URL;
result += m_SuccessURL;
result += AND_CANCEL_URL;
result += m_FailureURL;
result += AND_VERSION;
result += L"&NOSHIPPING=1";
result += L"&ADDROVERRIDE=0&BRANDNAME=Secured Globe, Inc.";
result += L"&PAYMENTREQUEST_0_DESC=";
result += L"Item name: " + strUnits + L"(" + UnitName + L") ";
result += L"Price: " + strAmount;
result += L"&NOTETOBUYER=Here you can add a note to the buyer";
The result from the PayPal server is a "token" used to figure out a one-time web page (LinkToOpen ) that must be opened in order for the end user to confirm the purchase:
// Extract token from response
CString sToken = ExtractElement(strTransactionRet, L"TOKEN");
if (sToken == L"")
{
wprintf(L"Internal error: (Paypal): no token was generated (%s)", strTransactionRet);
MessageBox(NULL, L"Internal payment processing error", L"", MB_OK);
return FALSE;
}
CString LinkToOpen = (m_sandbox) ? SANDBOX_PAYPAL_CHECKOUT : REAL_PAYPAL_CHECKOUT;
LinkToOpen += L"&token=";
LinkToOpen += sToken;
We then programatically open this one-time web page using the default web browser:
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
CString command_line;
command_line.Format(L"cmd.exe /c start \"link\" \"%s\" ", LinkToOpen);
// LinkToOpen
if (!CreateProcess(NULL, // No module name (use command line)
command_line.GetBuffer(),
NULL, // Process handle not inheritable
NULL, // Thread handle not inhberitable
FALSE, // Set handle inheritance to FALSE
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
wprintf(L"CreateProcess failed (%d).\n", GetLastError());
// At this stage you would want to mark this transaction as "failed"
return FALSE;
}
Then the rest is to maintain a small database of all pending transactions and follow up each of them until it is either succeed, failed, cancelled or if a timeout has passed.
To extract elements from the PayPal server response, we wrote this small function:
CString ExtractElement(CString EntireString, CString ElementName)
{
CString result = L"";
CString WhatToFind = ElementName + L"=";
int foundToken = EntireString.Find(WhatToFind);
if (foundToken > -1)
{
int EndToken = EntireString.Find(L"&", foundToken);
if (EndToken != -1)
{
result = EntireString.Mid(foundToken + ElementName.GetLength()+1, EndToken - foundToken - ElementName.GetLength()-1);
}
}
return result;
}
I am using the email verification feature that Parse offers and would like my users to be able to resend the email verification if it fails to send or they cannot see it. Last I saw, Parse does not offer an intrinsic way to do this (stupid) and people have been half-hazzerdly writing code to change the email and then change it back to trigger a re-send. Has there been any updates to this or is changing the email from the original and back still the only way? Thanks
You should only need to update the email to its existing value. This should trigger another email verification to be sent. I haven't been able to test the code, but this should be how you do it for the various platforms.
// Swift
PFUser.currentUser().email = PFUser.currentUser().email
PFUser.currentUser().saveInBackground()
// Java
ParseUser.getCurrentUser().setEmail(ParseUser.getCurrentUser().getEmail());
ParseUser.getCurrentUser().saveInBackground();
// JavaScript
Parse.User.current().set("email", Parse.User.current().get("email"));
Parse.User.current().save();
You have to set the email address to a fake one save and then set it back to the original and then parse will trigger the verification process. Just setting it to what it was will not trigger the process.
iOS
if let email = PFUser.currentUser()?.email {
PFUser.currentUser()?.email = email+".verify"
PFUser.currentUser()?.saveInBackgroundWithBlock({ (success, error) -> Void in
if success {
PFUser.currentUser()?.email = email
PFUser.currentUser()?.saveEventually()
}
})
}
Poking around the source code for Parse server, there doesn't seem to be any public api to manually resend verification emails. However I was able to find 2 undocumented ways to access the functionality.
The first would be to use the internal UserController on the server (for instance from a Cloud function) like this:
import { AppCache } from 'parse-server/lib/cache'
Cloud.define('resendVerificationEmail', async request => {
const userController = AppCache.get(process.env.APP_ID).userController
await userController.resendVerificationEmail(
request.user.get('username')
)
return true
})
The other is to take advantage of an endpoint that is used for the verification webpage:
curl -X "POST" "http://localhost:5000/api/apps/press-play-development/resend_verification_email" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{ "username": "7757429624" }'
Both are prone to break if you update Parse and internals get changed, but should be more reliable than changing the users email and then changing it back.
We were setting emails to an empty string, but found that there was a race condition where 2 users would hit it at the same time and 1 would fail because Parse considered it to be a duplicate of the other blank email. In other cases, the user's network connection would fail between the 2 requests and they would be stuck without an email.
Now, with Parse 3.4.1 that I'm testing, you can do (for Javascript):
Parse.User.requestEmailVerification(Parse.User.current().get("email"));
BUT NOTE that it will throw error if user is already verified.
Reference:
http://parseplatform.org/Parse-SDK-JS/api/3.4.1/Parse.User.html#.requestEmailVerification
To resend the verification email, as stated above, you have to modify then reset the user email address. To perform this operation in secure and efficient way, you can use the following cloud code function:
Parse.Cloud.define("resendVerificationEmail", async function(request, response) {
var originalEmail = request.params.email;
const User = Parse.Object.extend("User");
const query = new Parse.Query(User);
query.equalTo("email", originalEmail);
var userObject = await query.first({useMasterKey: true});
if(userObject !=null)
{
userObject.set("email", "tmp_email_prefix_"+originalEmail);
await userObject.save(null, {useMasterKey: true}).catch(error => {response.error(error);});
userObject.set("email", originalEmail);
await userObject.save(null, {useMasterKey: true}).catch(error => {response.error(error);});
response.success("Verification email is well resent to the user email");
}
});
After that, you just need to call the cloud code function from your client code. From Android client, you can use the following code (Kotlin):
fun resendVerificationEmail(email:String){
val progress = ProgressDialog(this)
progress.setMessage("Loading ...")
progress.show()
val params: HashMap<String, String> = HashMap<String,String>()
params.put("email", email)
ParseCloud.callFunctionInBackground("resendVerificationEmail", params,
FunctionCallback<Any> { response, exc ->
progress.dismiss()
if (exc == null) {
// The function executed, but still has to check the response
Toast.makeText(baseContext, "Verification email is well sent", Toast.LENGTH_SHORT)
.show()
} else {
// Something went wrong
Log.d(TAG, "$TAG: ---- exeception: "+exc.message)
Toast.makeText(
baseContext,
"Error encountered when resending verification email:"+exc.message,
Toast.LENGTH_LONG
).show()
}
})
}
I trying the new Paypal REST API and want integrate it in sandbox mode into a simple site just to see is it possible to implement one of the following payment flows:
Flow1
1) user fills the payment form, including credit card information
2) user clicks Buy
3) browser stores credit card information in paypal vault via REST API for credit cards (card id used later).
4) browser creates payment for the purchase via REST API call.
5) browser calls app server to ensure that purchase is going on.
5) browser redirects user to url provided by paypal.
6) when user consent/approval received at paypal website, and site redirected back to welcome page,
7) under the hood the IPN callback receives the conformation of payment and marks purchase as paid
8) user obtains access to the service app provides
Flow 2
1) user fills the payment form, including credit card information
2) user clicks Buy
4) browser creates payment for the purchase via REST API call.
5) browser calls app server to ensure that purchase is going on.
5) browser redirects user to url provided by paypal.
6) when user consent/approval received at paypal website, and site redirected back to welcome page,
7) under the hood the IPN callback receives the conformation of payment and marks purchase as paid and uses a bit more pf purchase details like credit card type and last 4 digits to add this info to my purchase object.
8) user obtains the access to services the application provides
8) user obtains access to the service app provides
Reasons to implement all this in such way
Mostly I going this path because i don't want deal with all this PCI compliance, and hones;ty i don't care where customers of my app live, which exactly card numbers they used, or when the card expire, since i don't want use automated subscription like payment, i want use different model:
user gets some pats of service for free, but to use rest of service, user buys time intervals of improved access (e. g. X months or 1 year).
This is what i trying to implement without storing credit cards information or storing as less as possible (paypal credit card id is enough i guess).
Question
Can i implement all this with Paypal REST API?
What i trying to do:
PaypalAdapter.prototype.sendCreditCardPayment = function (amount, description, creditCard, success, failure) {
var ccNumberResult = this.impl.validator.validateCardNumber(creditCard.number);
if (!ccNumberResult.success) {
return this.impl.$q.reject(ccNumberResult);
}
var cardInfo = {
number: ccNumberResult.number,
type: ccNumberResult.type,
expire_month: creditCard.expireMonth,
expire_year: String(creditCard.expireYear),
cvv2: creditCard.securityCode,
first_name: creditCard.firstName,
last_name: creditCard.lastName
};
var self = this;
var defer = self.impl.$q.defer();
this.impl.storeCardAPI(cardInfo,
function cardTokenCreated(cardTokenReply) {
var paymentSettings = {
intent: self.PaymentIntents.Sale,
redirect_urls: {
return_url: self.urls.returnUrl,
cancel_url: self.urls.cancelUrl
},
payer: {
payment_method: self.PayMethods.CreditCard,
funding_instruments: [
{
credit_card_token: {
credit_card_id: cardTokenReply.id
}
}
]
},
transactions: [
{
amount: {
total: String(amount.toFixed(2)),
currency: self.currencyCode
},
description: description
}
]
};
self.impl.createPaymentAPI(paymentSettings, function paymentCreated(payment) {
defer.resolve(payment);
}, function failedToCreatePayment(pcErr) {
defer.reject(pcErr);
});
},
function failedToStoreCard(ctErr) {
defer.reject(ctErr);
});
return defer.promise.then(success, failure);
};
To keep context more clean, here some more pieces of code:
var defaultHeaders = {
Authorization: 'Bearer ' + securityContext.tokens.paypal.access_token,
Accept: 'application/json'
};
var createPaymentResource = $resource(securityContext.configuration.paypal.endPoint + 'payments/payment', {}, {
sendPayment : {
method:'POST',
headers: defaultHeaders
}
});
var saveCreditCardResource = $resource(securityContext.configuration.paypal.endPoint + "vault/credit-cards", {}, {
storeCreditCard: {
method: 'POST',
headers: defaultHeaders
}
});
function storeCardFunc(cardInfo, success, failure) {
return saveCreditCardResource.storeCreditCard(null, cardInfo, success, failure);
}
function createPaymentFunc(paymentInformation, success, failure) {
return createPaymentResource.sendPayment(null, paymentInformation, success, failure);
}
var adapter = new PaypalAdapter($q, securityContext, creditCardValidator, storeCardFunc, createPaymentFunc);
return adapter;
Current "Results"
What i getting:
1) I can store credit card into vault via REST API.
2) i getting error 500 on try to create payment whether i use plain credit card properties to fill credit card funding instrument or try to use credit card token instead.
What i'm doing wrong?
Update
My mistake is a sort of logical with a lack of knowledge.
1) The direct credit cards payments (weather user approves them manually (with intent 'order' and payment_method = 'credit_card'), or not ('sale' intent and payment method 'credit_card') are not available for my country (Republic of Georgia). This is a single reason for the error i see.
Discovered this via Paypal account pages at developer.paypal.com website... It is a frustrating thing. Especially with all this too cryptic "internal server error". I t would be VERY helpful if Paypal would provide at least an informative message "Requested feature not available for your account" with info link to that page with available/enabled features.
Also documentation s a bit broken - some fields like first_name or last_name of payer object of order/payment request are NOT expected by the /payments/payment endpoint...
For certain account transactionSearch API call is giving an internal error.
Its happening only for certain date range.
According to this post
Paypal Sandbox API Internal Error
the issue is resolved. So raised a new question.
Here is the response
ITEMS = Array (#5a4a881)
[0] = Object (#786e251)
AMT = "21.35"
CURRENCYCODE = "USD"
EMAIL = "xxx"
ERRORCODE = "10001"
FEEAMT = "-0.71"
LONGMESSAGE = "Internal Error"
NAME = "xxx"
NETAMT = "20.64"
SEVERITYCODE = "Error"
SHORTMESSAGE = "Transaction failed due to internal error"
STATUS = "Completed"
TIMESTAMP = "2013-10-02T19:12:30Z"
TIMEZONE = "GMT"
TRANSACTIONID = "xxx"
TYPE = "Payment"
Any ideas why this is happening?
That error could be a lot of different things. It could simply be a problem with the API servers, but if that's the case it shouldn't continue to happen for a long period of time. It could be an issue with your API request. If you want to post a sample of that I'll see if I can find any issue with it. It could also be that your range is too long or something like that. Again, post a sample of your request and I'll see if I can reproduce the issue.
Sorry If there is a post like this question, I checked but I couldn’t find any..
I’m using tank_auth_social for Facebook login.
https://github.com/sicsol/Tank-Auth-Social
Also someone mentioned this problem on issues but no reply..
https://github.com/sicsol/Tank-Auth-Social/issues/2
After user giving access from Facebook at first login it throws exception like this.
Fatal error: Uncaught OAuthException: An active access token must be used to query information about the current user. thrown in /home/hayvanse/public_html/application/libraries/facebook/base_facebook.php on line 1058
Yeah so we couldn’t have write token it means that yeah? But when I click to login and it works.
The first one only gives exception due to one problem and its not about Facebook token I think.
I’m really newbie on Facebook connect stuff, I updated Facebook and base_facebook library but didn’t work.
I hope had this problem and could help me. This is based function on this line so I wonder if I just skip exception,I'm really confused and looked for it all night :(
protected function throwAPIException($result) {
$e = new FacebookApiException($result);
switch ($e->getType()) {
// OAuth 2.0 Draft 00 style
case 'OAuthException':
// OAuth 2.0 Draft 10 style
case 'invalid_token':
// REST server errors are just Exceptions
case 'Exception':
$message = $e->getMessage();
if ((strpos($message, 'Error validating access token') !== false) ||
(strpos($message, 'Invalid OAuth access token') !== false)) {
$this->setAccessToken(null);
$this->user = 0;
$this->clearAllPersistentData();
}
}
throw $e;
}
Please update base_book with this function , check the link please. Main problem was getuser was returnin 0. You have to update code like blow on base_Facebook file.(latest sdk)
protected function getCode() {
$server_info = array_merge($_GET, $_POST, $_COOKIE);
if (isset($server_info['code'])) {
if ($this->state !== null &&
isset($server_info['state']) &&
$this->state === $server_info['state']) {
// CSRF state has done its job, so clear it
$this->state = null;
$this->clearPersistentData('state');
return $server_info['code'];
} else {
self::errorLog('CSRF state token does not match one provided.');
return false;
}
}
return false;
}
When using CodeIgniter + Facebook PHP SDK: getUser() always returns 0