Skip to content

Instantly share code, notes, and snippets.

@lewayotte
Created March 24, 2015 15:29
Show Gist options
  • Save lewayotte/0d277e443fc8ec896497 to your computer and use it in GitHub Desktop.
Save lewayotte/0d277e443fc8ec896497 to your computer and use it in GitHub Desktop.
PayPal Payments - WordCamp ATL 2015
<?php
if ( !defined( 'PAYPAL_PAYMENT_LIVE_URL' ) )
define( 'PAYPAL_PAYMENT_LIVE_URL', 'https://www.paypal.com/cgi-bin/webscr' );
if ( !defined( 'PAYPAL_PAYMENT_SANDBOX_URL' ) )
define( 'PAYPAL_PAYMENT_SANDBOX_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr' );
/* Insecure */
function insecure_paypal_payment_url() {
$paypal_email = 'you@domain.tld';
$transaction_return_page = get_permalink( 1 ); //Whatever page ID you're using for your transaction return page
$transaction_cancel_page = get_permalink( 1 ); //Whatever page ID you're using for your transaction cancel page
$customer_email = '';
$description = '';
$custom_value = ''; //good to use a unique key per customer to track them throughout the payment process
$nonce = wp_create_nonce( 'pps-nonce' );
$query = array(
'cmd' => '_xclick',
'amount' => number_format( cart_total(), 2, '.', '' ), //Whatever method you use to determine the value of the cart
'quantity' => '1',
'business' => $paypal_email,
'item_name' => $description,
'return' => add_query_arg( array( 'transaction-method' => 'paypal-standard', 'paypal-standard-nonce' => $nonce ), $transaction_return_page ),
'currency_code' => 'USD',
'notify_url' => get_site_url() . '/?paypal-standard-ipn=1',
'no_note' => '1',
'no_shipping' => '1',
'shipping' => '0',
'email' => $customer_email, //your customer's email address, if you have it
'rm' => '2',
'cancel_return' => add_query_arg( array( 'transaction-method' => 'paypal-standard' ), $transaction_cancel_page ),
'custom' => $custom_value,
);
$paypal_payment_url = PAYPAL_PAYMENT_URL . '?' . http_build_query( $query );
return $paypal_payment_url;
/*
* Outputs:
* https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&amount=50.00&quantity=1&business=you@domain.tld&item_name=&return=http://domain.tld/?transaction-method=paypal-standard&paypal-standard-nonce=baa09c68e1&currency_code=USD&notify_url=http://domain.tld/?paypal-standard-ipn=1&no_note=1&no_shipping=1&shipping=0&email=&rm=2&cancel_return=https://domain.tld/?transaction-method=paypal-standard&custom=
*/
}
/* Secure */
if ( !defined( 'PAYPAL_PAYMENT_URL' ) )
define( 'PAYPAL_PAYMENT_URL', 'https://www.paypal.com/cgi-bin/webscr' );
if ( !defined( 'PAYPAL_NVP_API_URL' ) )
define( 'PAYPAL_NVP_API_URL', 'https://api-3t.paypal.com/nvp' );
function secure_paypal_payment_url() {
$paypal_email = 'you@domain.tld';
$paypal_api_username = 'api_username.domain.tld';
$paypal_api_password = 'PASSWORD';
$paypal_api_signature = 'SiGnAtUrE';
$transaction_return_page = get_permalink( 1 ); //Whatever page ID you're using for your transaction return page
$transaction_cancel_page = get_permalink( 1 ); //Whatever page ID you're using for your transaction cancel page
$customer_email = '';
$description = '';
$custom_value = ''; //good to use a unique key per customer to track them throughout the payment process
if ( ! empty( $paypal_email )
&& ! empty( $paypal_api_username )
&& ! empty( $paypal_api_password )
&& ! empty( $paypal_api_signature ) ) {
$button_request = array(
'USER' => trim( $paypal_api_username ),
'PWD' => trim( $paypal_api_password ),
'SIGNATURE' => trim( $paypal_api_signature ),
'VERSION' => '96.0', //The PayPal API version
'METHOD' => 'BMCreateButton',
'BUTTONCODE' => 'ENCRYPTED',
'BUTTONIMAGE' => 'REG',
'BUYNOWTEXT' => 'PAYNOW',
'BUTTONTYPE' => 'BUYNOW',
);
$nonce = wp_create_nonce( 'ppss-nonce' );
$L_BUTTONVARS[] = 'amount=' . number_format( cart_total(), 2, '.', '' );
$L_BUTTONVARS[] = 'quantity=1';
$L_BUTTONVARS[] = 'business=' . $paypal_email;
$L_BUTTONVARS[] = 'item_name=' . $description;
$L_BUTTONVARS[] = 'return=' . add_query_arg( array( 'transaction-method' => 'paypal-secure-standard', 'paypal-standard-secure-nonce' => $nonce ), $transaction_return_page );
$L_BUTTONVARS[] = 'currency_code=USD';
$L_BUTTONVARS[] = 'notify_url=' . get_site_url() . '/?paypal-standard-secure-ipn=1';
$L_BUTTONVARS[] = 'no_note=1';
$L_BUTTONVARS[] = 'no_shipping=1';
$L_BUTTONVARS[] = 'shipping=0';
$L_BUTTONVARS[] = 'email=' . $customer_email;
$L_BUTTONVARS[] = 'rm=2'; //Return Method - https://developer.paypal.com/webapps/developer/docs/classic/button-manager/integration-guide/ButtonManagerHTMLVariables/
$L_BUTTONVARS[] = 'cancel_return=' . add_query_arg( array( 'transaction-method' => 'paypal-standard-secure' ), $transaction_cancel_page );
$L_BUTTONVARS[] = 'custom=' . $custom_value;
$count = 0;
foreach( $L_BUTTONVARS as $L_BUTTONVAR ) {
$button_request['L_BUTTONVAR' . $count] = $L_BUTTONVAR;
$count++;
}
$response = wp_remote_post( PAYPAL_NVP_API_URL, array( 'body' => $button_request ) );
if ( !is_wp_error( $response ) ) {
parse_str( wp_remote_retrieve_body( $response ), $response_array );
if ( !empty( $response_array['ACK'] ) && 'Success' === $response_array['ACK'] ) {
if ( !empty( $response_array['WEBSITECODE'] ) ) {
$payment_form = str_replace( array( "\r\n", "\r", "\n" ), '', stripslashes( $response_array['WEBSITECODE'] ) );
if ( preg_match( '/-----BEGIN PKCS7-----.*-----END PKCS7-----/i', $payment_form, $matches ) ) {
$query = array(
'cmd' => '_s-xclick',
'encrypted' => $matches[0],
);
return PAYPAL_PAYMENT_LIVE_URL . '?' . http_build_query( $query );
}
}
}
} else {
return $response->get_error_messages();
}
}
return false;
/*
* Outputs:
* https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&encrypted=-----BEGIN+PKCS7-----MIIImQYJKoZIhvcNAQcEoIIIijCCCIYCAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYCvCIUnOf4UQo1VntxT%2FVo2i9U2fx6P3oBio%2F3SD4Rvj%2BtR7gDJb3Uab%2BcsaSfExYvrXNzvwjaSNomqFGELnPVjHG7Daur2JdxGyNzulDytYLhvYSaIIOdAaKBlpQHm2wRCBt12jJtSJ7asafOqEO%2BbWWjn0QietV93iJWZyw0%2F0TELMAkGBSsOAwIaBQAwggIVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECC3fZXrkomQTgIIB8A91Db3nOjzyfe5yfI9RxUBCkQLZ7CwBEi7swviC3bFFbshIUTAyNDSvdxW3vUNdM4DsVK9olM9e%2ByQgUgTY596vmfZGqFc8HjDgshOv1ZVwdbH9t7IPUavTIDRzDW2gnpmeIy1PrpD0aIctZUlqhRevOqKl8qd9IX1jUo%2FHiCoPbVta2JIVqJy%2BFnP3bdmWL%2F%2BbLlWAV0q1kxxCyi5ruLgBndg5HXhA0RQw3wziMwhMyZHzfu7mlKIYmCRX8iyYmbXmuiBc%2BNA19nk8vxtzYRt5TB2W2dpisQnOELkAzQzNGGVmkhjowtjRRkwGW3pprxRUnYdgn%2BAqnhLEelrOkzpqRreDsYKQ4IGonFLIFHVlBqWYDijPvhxqLCyJY2LOJtK%2FWtbdJDdYc2uAZ07fjFuO%2F1OzNlQwYKJj4l8AKLBBO1bvQu5Oz7rpM5HcWIC1xeOF1SkuqCDOASzhhZuSl7R7FaIL53%2FVjepU7VmQnjkuhLqL0b0UuqTtHdC2SEe2OM0qbrhVZkTfkPeqfc1u3lVeOa4Jfeex0kVcctsgMetQvBn20Ffprw4QN6VOlo%2FWHnQU1b2H1JwkWix45eVeokkOE6KPfHlMYq90lBdw9KX9zpMLNp%2BmibTvfkFeC%2BeHhaSsEK5GFDgJueEHavFy%2BnCgggOHMIIDgzCCAuygAwIBAgIBADANBgkqhkiG9w0BAQUFADCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20wHhcNMDQwMjEzMTAxMzE1WhcNMzUwMjEzMTAxMzE1WjCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMFHTt38RMxLXJyO2SmS%2BNdl72T7oKJ4u4uw%2B6awntALWh03PewmIJuzbALScsTS4sZoS1fKciBGoh11gIfHzylvkdNe%2FhJl66%2FRGqrj5rFb08sAABNTzDTiqqNpJeBsYs%2Fc2aiGozptX2RlnBktH%2BSUNpAajW724Nv2Wvhif6sFAgMBAAGjge4wgeswHQYDVR0OBBYEFJaffLvGbxe9WT9S1wob7BDWZJRrMIG7BgNVHSMEgbMwgbCAFJaffLvGbxe9WT9S1wob7BDWZJRroYGUpIGRMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbYIBADAMBgNVHRMEBTADAQH%2FMA0GCSqGSIb3DQEBBQUAA4GBAIFfOlaagFrl71%2Bjq6OKidbWFSE%2BQ4FqROvdgIONth%2B8kSK%2F%2FY%2F4ihuE4Ymvzn5ceE3S%2FiBSQQMjyvb%2Bs2TWbQYDwcp129OPIbD9epdr4tJOUNiSojw7BHwYRiPh58S1xGlFgHFXwrEBb3dgNbMUa%2Bu4qectsMAXpVHnD9wIyfmHMYIBmjCCAZYCAQEwgZQwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tAgEAMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0xNTAzMjQxNDEzMzlaMCMGCSqGSIb3DQEJBDEWBBQ9O%2FMbhUbWlfaOaKjnRn%2BjNIRy6jANBgkqhkiG9w0BAQEFAASBgGE0Ed9bDtQihbfXVvvhutonQ2H0nKyYn2oAE%2FVqX89SiHwmBCZ%2FAZNn6hAm8F9ejCMfYD59hT2BCKzaYFNpdQdOaSZfbct4P0tH4FqRt7g4nLRidr9dsZFDONq8%2B%2FtliBeGBuo0jms7upEFnFV378v1SoReQHmo4AB41ssKvdwI-----END+PKCS7-----
*/
}
function cart_total() {
return '50.00';
}
<?php
if ( !defined( 'PAYPAL_PAYMENT_LIVE_URL' ) )
define( 'PAYPAL_PAYMENT_LIVE_URL', 'https://www.paypal.com/cgi-bin/webscr' );
if ( !defined( 'PAYPAL_PAYMENT_SANDBOX_URL' ) )
define( 'PAYPAL_PAYMENT_SANDBOX_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr' );
function process_paypal_standard_return_transaction() {
if ( !empty( $_REQUEST['transaction-method'] ) && 'paypal-standard' === $_REQUEST['transaction-method'] ) {
if ( !empty( $_REQUEST['paypal-standard-nonce'] ) && wp_verify_nonce( $_REQUEST['paypal-standard-nonce'], 'pps-nonce' ) ) {
if ( !empty( $_REQUEST['tx'] ) ) //if PDT is enabled
$transaction_id = $_REQUEST['tx'];
else if ( !empty( $_REQUEST['txn_id'] ) ) //if PDT is not enabled
$transaction_id = $_REQUEST['txn_id'];
else
$transaction_id = NULL;
// This is that 'custom' value we set in the Payment URL
if ( !empty( $_REQUEST['cm'] ) )
$transient_transaction_id = $_REQUEST['cm'];
else if ( !empty( $_REQUEST['custom'] ) )
$transient_transaction_id = $_REQUEST['custom'];
else
$transient_transaction_id = NULL;
if ( !empty( $_REQUEST['amt'] ) ) //if PDT is enabled
$transaction_amount = $_REQUEST['amt'];
else if ( !empty( $_REQUEST['mc_gross'] ) ) //if PDT is not enabled
$transaction_amount = $_REQUEST['mc_gross'];
else
$transaction_amount = NULL;
if ( !empty( $_REQUEST['st'] ) ) //if PDT is enabled
$transaction_status = $_REQUEST['st'];
else if ( !empty( $_REQUEST['payment_status'] ) ) //if PDT is not enabled
$transaction_status = $_REQUEST['payment_status'];
else
$transaction_status = NULL;
if ( !empty( $transaction_id ) && !empty( $transient_transaction_id ) && NULL !== $transaction_amount && !empty( $transaction_status ) ) {
try {
$cart_total = cart_total(); //Get the original cart total somehow
if ( number_format( $transaction_amount, '2', '', '' ) != number_format( $cart_total, '2', '', '' ) ) {
throw new Exception( __( 'Error: Amount charged is not the same as the cart total!', 'it-l10n-ithemes-exchange' ) );
}
return $transaction_id;
}
catch ( Exception $e ) {
echo $e->getMessage();
}
}
}
}
return false;
}
if ( !defined( 'PAYPAL_NVP_API_LIVE_URL' ) )
define( 'PAYPAL_NVP_API_LIVE_URL', 'https://api-3t.paypal.com/nvp' );
if ( !defined( 'PAYPAL_NVP_API_SANDBOX_URL' ) )
define( 'PAYPAL_NVP_API_SANDBOX_URL', 'https://api-3t.sandbox.paypal.com/nvp' );
function process_paypal_standard_secure_return_transaction() {
if ( !empty( $_REQUEST['transaction-method'] ) && 'paypal-standard-secure' === $_REQUEST['transaction-method'] ) {
if ( !empty( $_REQUEST['paypal-standard-secure-nonce'] ) && wp_verify_nonce( $_REQUEST['paypal-standard-secure-nonce'], 'ppss-nonce' ) ) {
if ( !empty( $_REQUEST['tx'] ) ) //if PDT is enabled
$transaction_id = $_REQUEST['tx'];
else if ( !empty( $_REQUEST['txn_id'] ) ) //if PDT is not enabled
$transaction_id = $_REQUEST['txn_id'];
else
$transaction_id = NULL;
if ( !empty( $_REQUEST['cm'] ) )
$transient_transaction_id = $_REQUEST['cm'];
else if ( !empty( $_REQUEST['custom'] ) )
$transient_transaction_id = $_REQUEST['custom'];
else
$transient_transaction_id = NULL;
if ( !empty( $_REQUEST['amt'] ) ) //if PDT is enabled
$transaction_amount = $_REQUEST['amt'];
else if ( !empty( $_REQUEST['mc_gross'] ) ) //if PDT is not enabled
$transaction_amount = $_REQUEST['mc_gross'];
else
$transaction_amount = NULL;
if ( !empty( $_REQUEST['st'] ) ) //if PDT is enabled
$transaction_status = $_REQUEST['st'];
else if ( !empty( $_REQUEST['payment_status'] ) ) //if PDT is not enabled
$transaction_status = $_REQUEST['payment_status'];
else
$transaction_status = NULL;
if ( !empty( $transaction_id ) && !empty( $transient_transaction_id ) && !empty( $transaction_amount ) && !empty( $transaction_status ) ) {
try {
$paypal_api_username = 'api_username.domain.tld';
$paypal_api_password = 'PASSWORD';
$paypal_api_signature = 'SiGnAtUrE';
$request = array(
'USER' => trim( $paypal_api_username ),
'PWD' => trim( $paypal_api_password ),
'SIGNATURE' => trim( $paypal_api_signature ),
'VERSION' => '96.0', //The PayPal API version
'METHOD' => 'GetTransactionDetails',
'TRANSACTIONID' => $transaction_id,
);
$response = wp_remote_post( PAYPAL_NVP_API_LIVE_URL, array( 'body' => $request ) );
if ( !is_wp_error( $response ) ) {
$array = array();
parse_str( wp_remote_retrieve_body( $response ), $response_array );
$transaction_status = $response_array['PAYMENTSTATUS'];
if ( $transaction_id != $response_array['TRANSACTIONID'] ) {
throw new Exception( __( 'Error: Transaction IDs do not match! %s, %s', 'it-l10n-ithemes-exchange' ) );
}
$cart_total = cart_total(); //Get the original cart total somehow
if ( number_format( $response_array['AMT'], '2', '', '' ) != number_format( $cart_total, '2', '', '' ) ) {
throw new Exception( sprintf( __( 'Error: Amount charged is not the same as the cart total! %s | %s', 'it-l10n-ithemes-exchange' ), $response_array['AMT'], $transaction_object->total ) );
}
return $transaction_id;
} else {
throw new Exception( $response->get_error_message() );
}
}
catch ( Exception $e ) {
echo $e->getMessage();
}
}
}
}
return false;
}
function cart_total() {
return '50.00';
}
<?php
// https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNTesting/
// https://developer.paypal.com/webapps/developer/applications/ipn_simulator
if ( !defined( 'PAYPAL_PAYMENT_LIVE_URL' ) )
define( 'PAYPAL_PAYMENT_LIVE_URL', 'https://www.paypal.com/cgi-bin/webscr' );
if ( !defined( 'PAYPAL_PAYMENT_SANDBOX_URL' ) )
define( 'PAYPAL_PAYMENT_SANDBOX_URL', 'https://www.sandbox.paypal.com/cgi-bin/webscr' );
function paypal_standard_process_webhook() {
$payload['cmd'] = '_notify-validate';
foreach( $_POST as $key => $value ) {
$payload[$key] = stripslashes( $value );
}
$paypal_api_url = !empty( $_REQUEST['test_ipn'] ) ? PAYPAL_PAYMENT_SANDBOX_URL : PAYPAL_PAYMENT_LIVE_URL;
$response = wp_remote_post( $paypal_api_url, array( 'body' => $payload ) );
$body = wp_remote_retrieve_body( $response );
if ( 'VERIFIED' === $body ) {
// We can use $_REQUEST['custom'] to find the customer who had this transaction
if ( !empty( $_REQUEST['paypal-standard-ipn'] ) || !empty( $_REQUEST['paypal-standard-secure-ipn'] ) ) {
if ( !empty( $_REQUEST['txn_type'] ) ) {
switch( $_REQUEST['txn_type'] ) {
case 'web_accept':
switch( strtolower( $_REQUEST['payment_status'] ) ) {
case 'completed' :
//Record the transaction for the customer...
break;
case 'reversed' :
//Record the transaction reversal for the customer...
break;
}
break;
}
} else {
//These IPNs don't have txn_types, why PayPal!? WHY!?
if ( !empty( $_REQUEST['reason_code'] ) ) {
switch( $_REQUEST['reason_code'] ) {
case 'refund' :
//Record the transaction refund for the customer...
break;
}
}
}
}
} else {
error_log( sprintf( 'Invalid IPN sent from PayPal: %s', maybe_serialize( $payload ) ) );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment