Troubles with Paypal Adaptive Payments API - paypal

I'm having trouble with the Chained Payments API, still in development.
Speaking for the sandbox: I've read that, for some reason, the PayKey (the unique identifier Paypal creates for the transaction), is not passed back to the transaction. And certainly, in my testing, I get most the data back (like the buyer's email address, name, address information) but I do not get the paykey back.
This field is not just blank, it's not present at all. I'm doing the most basic loop over the form scope and writing the results to a file (obviously I won't be doing something this rudimentary in production, this was just to understand what data I was getting).
So I thought I'd pass my own unique identifier, store that in the database, and then pass that through the custom variable. This, (the custom field) oddly, comes back blank every time.
Finally I thought I'd just pass it as part of the url of the IpnNotificationUrl like receipt.cfm?myKey=SOMEVERYRANDOMLYGENERATEDKEYHERE but when I pass IpnNotificationUrl, the specified url is not pinged, whether or not I have a separate IPN Notification URL setup in my sandbox account. The URL specified in the account is properly pinged each time.
Both files are identical except that they write to differently named text files. I'm not getting an error off either file.
<cfoutput><cfsavecontent variable="buildfile">--- Break ---
<cfloop list="#structkeylist(form)#" index="i">
#i#: #form[i]#
</cfloop>
</cfsavecontent></cfoutput>
<cffile file="#expandpath(".")#\dump_new.txt" action="write" output="#buildfile#" />
I need to be able to create a key and pass through Paypal or Paypal needs to pass back.
For what it's worth, this is my invocation from Paypal's SDK on GitHub
<cfinvoke component="svc.adaptivepayments" method="payRequest" returnvariable="response">
<cfinvokeargument name="returnURL" value="#request.serverURL#/success.cfm">
<cfinvokeargument name="cancelURL" value="#request.serverURL#/cancel.cfm">
<cfinvokeargument name="ipnNotificationUrl" value="http://myurl/taction/pp_rect2.cfm">
<cfinvokeargument name="senderEmail" value="">
<cfinvokeargument name="custom" value="test data">
<cfinvokeargument name="receiverAmount" value="#ArrayToList(pp_amounts)#">
<cfinvokeargument name="receiverEmail" value="#ArrayToList(pp_emails)#">
<cfinvokeargument name="receiverPrimary" value="true,false,false,false,false,false">
<cfinvokeargument name="feesPayer" value="PRIMARYRECEIVER">
<cfinvokeargument name="receiverPaymentType" value="DIGITALGOODS,DIGITALGOODS,DIGITALGOODS,DIGITALGOODS,DIGITALGOODS,DIGITALGOODS">
<cfinvokeargument name="actionType" value="PAY">
<cfinvokeargument name="currencyCode" value="USD">
</cfinvoke>
Edit: For clarification, Paykey comes back from this service, it's how I generate the link to send the user to paypal. Paykey simply doesn't get passed to my IPN, though other transaction data does. I removed certain information. And I've double checked, none of this information is the paykey or is available at time of paykey creation (so there's no unique identifier on both ends)
--- Break ---
payer_email: redacted
charset: windows-1252
item_name:
payment_gross: 10.00
payer_id: A62WKW8N3YDYU
transaction_subject:
item_number:
payment_status: Completed
payment_fee: 0.55
notify_version: 3.8
verify_sign: A.CSYz4u5IILQm5wM0J0JbJiIcEuAHODNEgw.2k7ZMYT31eXFO6G0R1o
mc_currency: USD
quantity: 0
residence_country: US
tax: 0.00
first_name: John
receiver_email: redacted
last_name: Blow
mc_fee: 0.55
ipn_track_id: dd4151b653ead
payer_status: verified
custom:
fieldnames: payer_email,charset,item_name,payment_gross,payer_id,transaction_subject,
item_number,payment_status,payment_fee,notify_version,verify_sign,
mc_currency,quantity,residence_country,tax,first_name,receiver_email,
last_name,mc_fee,ipn_track_id,payer_status,custom,mc_gross,test_ipn,
business,txn_id,receiver_id,txn_type,payment_type,payment_date,protection_eligibility
mc_gross: 10.00
test_ipn: 1
business: redacted
txn_id: 71N09598H1922352W
receiver_id: VBETUFDEQL5BC
txn_type: web_accept
payment_type: instant
payment_date: 12:53:10 Nov 04, 2014 PST
protection_eligibility: Ineligible

I think you're getting lost in the fact that Adaptive Payments transactions actually have separate IPN's for the app and for the receiver. In cases where you're acting as both, you would get 2 separate IPN's.
What you've included here is the receiver/transaction specific IPN. That would not include a PayKey, but instead, a transaction ID, like you're getting. You'll notice there is no PayKey parameter at all (as opposed to it being included, but blank, like you originally stated.)
If you want to process app specific data, including the PayKey, you'll need do that from within the app specific IPN, which is what I linked you to for my sample. You'll notice the parameters it includes are much different than what you're getting here.
In my sample, I was indeed both the app owner and the receiver of the transaction, so I got 2 IPN's at the same time, but of course my IPN script is configured to handle them accordingly.
So again, I had an app specific IPN, which includes app specific data including the PayKey. Then I also got a separate transaction specific IPN, which includes data like you're showing here, but does not include a PayKey.
You need to make sure you're handling both correctly. The IPNNotificationURL parameter in your Pay request would trigger the app specific IPN, where-as the IPN config in the receiver account would trigger the transaction specific IPN.
I see that you are including a value for IPNNotificationURL in your request, but the data you're getting is not that. You need to check your web server logs because it seems like that one must be failing for some reason, but then the other is hitting and succeeding.

Related

DoExpressCheckout 10004 - no additional error messages

We have an issue with our PayPal Express Checkout integration. We see an error coming back from DoExpressCheckout with code 10004 saying "Transaction refused because of an invalid argument. See additional error messages for details." But the response contains no additional error messages.
This occurs randomly with our integration. It started approximately one month ago and has happened 70 times vs 1430 successful transactions.
It appears to be random. Not tied to any specific amounts, browser type, time of transaction etc. One user could have several failures then try again with the same token and have it go through. Some users have come back 10 minutes later or change browser and it works. Most give up.
I'd appreciate any suggestions, is there a way to retrieve any more debug for this error?
SetExpressCheckout
USER=XXX
PWD=XXX
SIGNATURE=XXX
VERSION=112
METHOD=SetExpressCheckout
ALLOWNOTE=0
ADDROVERRIDE=1
PAYMENTREQUEST_0_SHIPTONAME=Mr X
PAYMENTREQUEST_0_SHIPTOSTREET=Test St
PAYMENTREQUEST_0_SHIPTOSTREET2=
PAYMENTREQUEST_0_SHIPTOCITY=City
PAYMENTREQUEST_0_SHIPTOSTATE=State
PAYMENTREQUEST_0_SHIPTOZIP=5000
PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=AU
PAYMENTREQUEST_0_SHIPTOPHONENUM=8888888888
RETURNURL=URLA
CANCELURL=URLB
PAYMENTREQUEST_0_PAYMENTACTION=Authorization
PAYMENTREQUEST_0_CURRENCYCODE=AUD
PAYMENTREQUEST_0_AMT=20.9
L_PAYMENTREQUEST_0_NAME0=DOOM PATROL VOL 6 #3
L_PAYMENTREQUEST_0_AMT0=7.95
L_PAYMENTREQUEST_0_NUMBER0=SEP160206
L_PAYMENTREQUEST_0_QTY0=1
L_PAYMENTREQUEST_0_CURRENCYCODE0=AUD
L_PAYMENTREQUEST_0_NAME1=MOTHER PANIC #1
L_PAYMENTREQUEST_0_AMT1=7.95
L_PAYMENTREQUEST_0_NUMBER1=SEP160201
L_PAYMENTREQUEST_0_QTY1=1
L_PAYMENTREQUEST_0_CURRENCYCODE1=AUD
L_PAYMENTREQUEST_0_NAME2=Regular Post (cannot be tracked)
L_PAYMENTREQUEST_0_AMT2=5
L_PAYMENTREQUEST_0_NUMBER2=Freight
L_PAYMENTREQUEST_0_QTY2=1
L_PAYMENTREQUEST_0_CURRENCYCODE2=AUD
GetExpressCheckout
USER=XXX
PWD=XXX
SIGNATURE=XXX
VERSION=2.3
TOKEN=EC-5DX46556HG972093T
METHOD=GetExpressCheckoutDetails
DoExpressCheckout
USER=XXX
PWD=XXX
SIGNATURE=XXX
VERSION=2.3
PAYMENTACTION=Authorization
PAYERID=XXX
TOKEN=EC-5DX46556HG972093T
AMT=20.9
CURRENCYCODE=AUD
METHOD=DoExpressCheckoutPayment
PayPal returns:
TOKEN=EC-5DX46556HG972093T
TIMESTAMP=2016-11-23T10:53:35Z
CORRELATIONID=XXX
ACK=Failure
VERSION=2.3
BUILD=000000
L_ERRORCODE0=10004
L_SHORTMESSAGE0=Internal Error
L_LONGMESSAGE0=Transaction refused because of an invalid argument. See additional error messages for details.
L_SEVERITYCODE0=Error
Error was on PayPals side. If you have the same issue just log a support ticket and magic will happen.

Mailgun API: Batch Sending vs. Individual Calls

Background
We're building an application that will process & send emails via Mailgun. These are sometimes one-off messages, initiated by a transaction. Some emails, though, will be sent to 30k+ at once.
Eg, a newsletter to all members.
Considerations
Mailgun offers a Batch Sending option with their API. Using "Recipient Variables", you can include dynamic values that are paired with a particular user.
This Batch Sending functionality is limited, however. You cannot send more than 1,000 recipients per request, which means we have to iterate through a recipient list (on our database) for each set of 1,000. Mailgun provides an example of how this might work, using Python (scroll about 2/3 down).
Question
Are there any advantages to batch sending (ie, sending an email to a group of recipients through a single API call, using recipient variables) as opposed to making our own loop, variable substitutions and individual API calls?
I assume this is more taxing on our server, as it would be processing each message itself, instead of just offloading all that data to Mailgun's server for heavy-lifting on their end. But I also like the flexibility & simplicity of handling that on our end and sending a "fully-rendered" message to Mailgun, one at a time, without having to iterate 1k at a time.
Any thoughts on best practices, or considerations we should take into account?
Stumbled onto this today, and felt it provided a pretty good summary/answer for my original question. I wanted to post this as an answer, in case anybody else has this question and hasn't found this Mailgun post. Straight from the horse's mouth, too. The nutshell version:
For PHP, at least, the SDK has a Mailgun class, with a BatchMessage() method. This actually handles the counting of recipients for you, so you can just queue up as many email addresses as you want (ie, more than 1k) and Mailgun will fire off to the API endpoint as needed. Pretty slick!
Here's their original wording, plus a link to the page.
Sending a message with Mailgun PHP SDK + Batch Message:
Batch Message
In addition to Message Builder, we have Batch Message. This class
allows you to build a message and submit a template message in
batches, up to 1,000 recipients per post. The benefit of using this
class is that the recipients tally is monitored and will automatically
submit the message to the endpoint when you've added the 1,000th
recipient. This means you can build your message and begin iterating
through your database. Forget about sending the message, the SDK will
keep track of posting to the API when necessary.
// First, instantiate the SDK with your API credentials and define your domain.
$mgClient = new Mailgun("key-example");
$domain = "example.com";
// Next, instantiate a Message Builder object from the SDK, pass in your sending domain.
$batchMsg = $mgClient->BatchMessage($domain);
// Define the from address.
$batchMsg->setFromAddress("dwight#example.com",
array("first"=>"Dwight", "last" => "Schrute"));
// Define the subject.
$batchMsg->setSubject("Help!");
// Define the body of the message.
$batchMsg->setTextBody("The printer is on fire!");
// Next, let's add a few recipients to the batch job.
$batchMsg->addToRecipient("pam#example.com",
array("first" => "pam", "last" => "Beesly"));
$batchMsg->addToRecipient("jim#example.com",
array("first" => "Jim", "last" => "Halpert"));
$batchMsg->addToRecipient("andy#example.com",
array("first" => "Andy", "last" => "Bernard"));
// ...etc...etc...
// After 1,000 recipeints,
// Batch Message will automatically post your message to the messages endpoint.
// Call finalize() to send any remaining recipients still in the buffer.
$batchMsg->finalize();
The answer of #cdwyer and #nikoshr is very helpful, but bit legacy. Used methods in the example are deprecated. Here is current usage of lib:
$batchMessage = $this->mailgun->messages()->getBatchMessage('mydomain.com');
$batchMessage->setFromAddress('user#domain.com');
$batchMessage->setReplyToAddress('user2#domain.com');
$batchMessage->setSubject('Contact form | Company');
$batchMessage->setHtmlBody('<html>...</html>');
foreach ($recipients as $recipient) {
$batchMessage->addToRecipient($recipient);
}
$batchMessage->finalize();
More info at documentation.

How to get the ItemId of save-to-sent copy when sending mail via EWS

The EWS documentation says that to send a message and save a copy to the Sent Items folder, you should use the CreateItem operation with a MessageDisposition value of SendAndSaveCopy.
<m:CreateItem MessageDisposition="SendAndSaveCopy">
<m:SavedItemFolderId>
<t:DistinguishedFolderId Id="sentitems" />
</m:SavedItemFolderId>
<m:Items>
<t:Message>
<t:Subject>Company Soccer Team</t:Subject>
<t:Body BodyType="HTML">Are you interested in joining?</t:Body>
<t:ToRecipients>
<t:Mailbox>
<t:EmailAddress>sadie#contoso.com </t:EmailAddress>
</t:Mailbox>
</t:ToRecipients>
</t:Message>
</m:Items>
</m:CreateItem>
On success, "the server responds to the CreateItem request with a CreateItemResponse message that includes a ResponseCode value of NoError, which indicates that the email was created successfully, and the ItemId of the newly created message."
Using EWS against Office 365, this works almost successfully. The message is sent, the copy is saved to Sent Items... but the ItemId of the saved copy is not returned in the response:
<m:CreateItemResponse>
<m:ResponseMessages>
<m:CreateItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items />
</m:CreateItemResponseMessage>
</m:ResponseMessages>
</m:CreateItemResponse>
Is there a way to direct the EWS server to actually return the ItemId of the saved copy? Alternatively, what's the preferred mechanism for locating the saved copy once the send completes?
Evidently the documentation is either wrong or inapplicable. This MSDN blog post matches my experience: no ItemId is returned from a SendAndSaveCopy CreateItem request. It suggests the following:
Simply stamp your e-mail message with a custom extended property when you create the message, and then use that extended property to find the message in the Sent Items folder after it has been sent.
A commenter suggests that rather than using an expensive FindItems-with-SearchFilter call to locate the custom-property-stamped saved copy, you should instead do the following:
1. Set your extended prop.
2. Do a FindItem with NO restriction against the sent items folder, SORTED by creation date descending with a indexed page view of about 5. Include your extended prop in the PropertySet.
3. Iterate across the results looking for your extended prop.

How to get the latest email using CFIMAP

I am using the below code block in CF9 to get all the mail data,
<cfimap
action="GETHEADERONLY"
name="LOCAL.checkEmail"
secure="true"
folder="Inbox"
server="#ImportAquireMailServer#"
username="#ImportAquireUsername#"
password="#ImportAquirePassword#" />
This query object provides the information about all the mails present in inbox. While doing so it takes a lot of time and also times out frequently.
Is there any way to get the latest mail only, so that it will not provide the information about all the mails and will also not run into time out situation?
Please help.
you may need to update the read messages to "read" like:
<cfimap action="MarkRead" connection = "Conn" messagenumber="#getHeaders.messagenumber#">
after the message id done with work.
so you can query the latest messages as:
<cfquery dbtype="query" name="getMails">
select * from getHeaders
where seen=<cfqueryparam value="no" cfsqltype="cf_sql_varchar">
</cfquery>also you can filter with received date
you can refer http://shemy-coldfusion.blogspot.in/2013/03/coldfusion-code-to-get-multiple-mail.html

Paypal IPN returns verified on sandbox, but invalid on live

So I have been using paypal, and sandbox mode everything works fine. Yet when I move over to live paypal with real money, IPN returns INVALID.
I am using a version of the script here ( https://cms.paypal.com/cms_content/US/en_US/files/developer/IPN_PHP_41.txt ) modified to my needs, only bits that are different are the db interactions etc
I have found this issue here ( http://www.hebtech.co.uk/blog/paypal-ipn-invalid-on-live-server-but-valid-on-test-server-fixed/ ) which seems to be the problem I am having, and basically says its to do with a carriage return in the optional second line of the address (which on test accounts in sandbox, isnt filled out). But the solution in the main post and another in the comments dont work, as below
$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i','${1}%0D%0A${3}',$value);
OR
$value = preg_replace('/(.*?)(%0D%0A|%0A)(.*)/i','${1}%0D%0A${3}',$value);
Any ideas? Driving me mad. Its not stopping the payment, but it just means on the site, changing the status to paid has to be done manually
You can try this one:
$value = preg_replace('/%0D%0A|%0A/i','%0D%0A',$value);
I have also problem with character ; in custom field. Look in all fields you send to PayPall. Also check in all field any character which is not A-Z or 0-9.
Last thing you can try is set charset in your language encoding options: https://www.paypal.com/cgi-bin/webscr?cmd=_profile-language-encoding