Skip to content

Instantly share code, notes, and snippets.

@wpmudev-sls
Created August 6, 2018 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wpmudev-sls/db55a831e25e66198707e851d33f3a12 to your computer and use it in GitHub Desktop.
Save wpmudev-sls/db55a831e25e66198707e851d33f3a12 to your computer and use it in GitHub Desktop.
Affiliate - custom integration with PayPerView plugin
<?php
/**
* Plugin Name: Affiliate - custom integration with PayPerView plugin
* Plugin URI: https://premium.wpmudev.org/
* Description: Affiliate - custom integration with PayPerView plugin
* Author: Ariful Islam @ WPMUDEV
* Author URI: https://premium.wpmudev.org/profile/itsarifulislam
* License: GPLv2 or later
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Affiliate_PayPerView_Integration {
/**
* This is the area-key which is passed to affiliates to recognize data
* created by this integration.
*/
const AREA_KEY = 'paid:payperview';
/**
* This is affiliate commission filed for options and metadata
* created by this integration.
*/
const AFF_COMMISSION_FIELD = 'aff_commission';
/**
* This is affiliate reward type filed for options and metadata
* created by this integration.
*/
const AFF_REWARD_TYPE = 'aff_reward_type';
/**
* Create and setup the Membership2 integration.
*
* @since 1.0.0
*/
public static function setup() {
static $Inst = null;
if ( null === $Inst ) {
$Inst = new Affiliate_PayPerView_Integration();
}
}
/**
* Protected constructor is run once only.
*
* @since 1.0.0
*/
protected function __construct() {
// Init metaboxes for affiliate settings
add_action( 'add_meta_boxes', array( $this, 'init_affiliate_metaboxes' ) );
// Save affiliate settings metabox
add_action( 'save_post', array( $this, 'save_affiliate_metaboxes' ), 1 );
// Create global setting page for affiliate
add_action( 'admin_menu', array( $this, 'process_admin_menu' ), 99);
// Send Paypal to IPN function
add_action( 'wp_ajax_ppw_paypal_ipn', array( $this, 'process_paypal_ipn' ) );
// Send Paypal to IPN function
add_action( 'wp_ajax_nopriv_ppw_paypal_ipn', array( $this, 'process_paypal_ipn' ) );
// Paypal single payment
add_action( 'ppw_paypal_single_payment_done', array( $this, 'process_ppw_paypal_single_payment' ), 20, 6 );
}
function process_ppw_paypal_single_payment( $user_id, $post_id, $amount, $currency, $timestamp, $order_id ) {
$this->process_commission( $amount, $currency, $post_id, $user_id, $order_id );
}
function process_admin_menu() {
add_submenu_page( 'pay-per-view', __( 'Affiliate Settings', 'ppw' ), __( 'Affiliate Settings', 'ppw' ), 'manage_options', "ppw_aff_integration", array( $this, 'ppw_aff_integration' ) );
add_action( 'admin_init', array( $this, 'register_ppw_aff_settings' ) );
}
function register_ppw_aff_settings() {
register_setting( 'ppw_aff_integration', self::AFF_COMMISSION_FIELD );
register_setting( 'ppw_aff_integration', self::AFF_REWARD_TYPE );
}
function ppw_aff_integration() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.' ) );
}
$aff_commission = esc_attr( get_option(self::AFF_COMMISSION_FIELD) );
$aff_reward_type = esc_attr( get_option(self::AFF_REWARD_TYPE) );
if ( ! $aff_reward_type ) {
$aff_reward_type = 'abs';
}
?>
<div class="wrap">
<h2><?php _e( 'Affiliate Settings', 'ppw' ); ?></h2>
<div id="poststuff" class="metabox-holder ppw-settings">
<form method="post" action="options.php">
<?php settings_fields( 'ppw_aff_integration' ); ?>
<?php do_settings_sections( 'ppw_aff_integration' ); ?>
<div class="postbox" id="ppw_global_postbox">
<h3 class='hndle'><span><?php _e( 'Affiliate Settings', 'ppw' ) ?></span></h3>
<div class="inside">
<span class="description"><?php _e( 'This could be overridden from the post or page', 'ppw' ) ?></span>
<table class="form-table">
<tr valign="top">
<th scope="row"><?php _e( 'Affiliate Commission', 'ppw' ) ?></th>
<td colspan="2">
<input type="text" style="width:50px" name="aff_commission" value="<?php echo $aff_commission; ?>"/>
</td>
</tr>
<tr valign="top">
<th scope="row"><?php _e( 'Affiliate Commission Type', 'ppw' ) ?></th>
<td colspan="2">
<select id="aff_reward_type" name="aff_reward_type">
<option value="per" <?php if ( $aff_reward_type == 'per' ) { echo "selected='selected'"; } ?> ><?php _e( 'Percentage', 'ppw' ); ?></option>
<option value="abs" <?php if ( $aff_reward_type == 'abs' ) { echo "selected='selected'"; } ?> ><?php _e( 'USD', 'ppw' ); ?></option>
</select>
</td>
</tr>
</table>
</div>
</div>
<?php submit_button(); ?>
</form>
</div>
</div>
<?php
}
function init_affiliate_metaboxes() {
$ppw_name = __( 'Affiliate Settings', 'ppw' ); // For translation compatibility
add_meta_box( 'ppw_affiliate_metabox', $ppw_name, array( $this, 'ppw_affiliate_metabox' ), 'post', 'side', 'high' );
add_meta_box( 'ppw_affiliate_metabox', $ppw_name, array( $this, 'ppw_affiliate_metabox' ), 'page', 'side', 'high' );
// New in V1.2: Custom post type support
$args = array(
'public' => true,
'_builtin' => false
);
$post_types = get_post_types( $args );
if ( is_array( $post_types ) ) {
foreach ( $post_types as $post_type ) {
add_meta_box( 'ppw_affiliate_metabox', $ppw_name, array( $this, 'ppw_affiliate_metabox' ), $post_type, 'side', 'high' );
}
}
}
function ppw_affiliate_metabox() {
global $post;
global $ppw;
$aff_commission = get_post_meta( $post->ID, self::AFF_COMMISSION_FIELD, true );
$aff_reward_type = get_post_meta( $post->ID, self::AFF_REWARD_TYPE, true );
wp_nonce_field( 'ppw_aff_integration_metabox', 'ppw_aff_integration_metabox_nonce' );
?>
<div class="aff_commission_area">
<label for="aff_commission"><?php
_e( 'Affiliate Commission', 'ppw' ); ?>
</label>
<div class="ppw_info"><?php
echo $ppw->tips->add_tip( __( 'Changes here will override the Global "Affiliate Commission" for this post', 'ppw' ) ); ?>
</div>
<input type="number" min="0" step="1" name="aff_commission" id="aff_commission" value="<?php echo $aff_commission; ?>"/>
</div>
<div class="ppw_clear ppw_border"></div>
<div class="aff_commission_area">
<label for="aff_reward_type"><?php
_e( 'Affiliate Commission Type', 'ppw' ); ?>
</label>
<div class="ppw_info"><?php
echo $ppw->tips->add_tip( __( 'Changes here will override the Global "Affiliate Commission Type" for this post', 'ppw' ) ); ?>
</div>
<select id="aff_reward_type" name="aff_reward_type">
<option <?php if ( $aff_reward_type != 'per' || $aff_reward_type != 'abs' ) { echo "selected='selected'"; } ?> ><?php _e( 'Inherit from global', 'ppw' ); ?></option>
<option value="per" <?php if ( $aff_reward_type == 'per' ) { echo "selected='selected'"; } ?> ><?php _e( 'Percentage', 'ppw' ); ?></option>
<option value="abs" <?php if ( $aff_reward_type == 'abs' ) { echo "selected='selected'"; } ?> ><?php _e( 'USD', 'ppw' ); ?></option>
</select>
</div>
<div class="ppw_clear"></div>
<style type="text/css">
#ppw_metabox_ddd label {
margin-bottom: 8px;
display: inline-block;
vertical-align: middle;
}
#ppw_metabox_ddd select,
#ppw_metabox_ddd input {
width: 100%;
}
#ppw_metabox_ddd .ppw_info {
padding-top: 0px;
margin-bottom: 8px;
display: inline-block;
vertical-align: middle;
}
</style>
<?php
}
function save_affiliate_metaboxes( $post_id ) {
if ( ! wp_verify_nonce( @$_POST['ppw_aff_integration_metabox_nonce'], 'ppw_aff_integration_metabox' ) ) {
return $post_id;
}
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check permissions
if ( 'page' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} elseif ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
// Auth ok
if ( isset( $_POST[self::AFF_COMMISSION_FIELD] ) ) {
if ( $_POST[self::AFF_COMMISSION_FIELD] != '' ) {
update_post_meta( $post_id, self::AFF_COMMISSION_FIELD, $_POST[self::AFF_COMMISSION_FIELD] );
} else {
delete_post_meta( $post_id, self::AFF_COMMISSION_FIELD );
}
}
if ( isset( $_POST[self::AFF_REWARD_TYPE] ) ) {
if ( $_POST[self::AFF_REWARD_TYPE] != '' ) {
update_post_meta( $post_id, self::AFF_REWARD_TYPE, $_POST[self::AFF_REWARD_TYPE] );
} else {
delete_post_meta( $post_id, self::AFF_REWARD_TYPE );
}
}
}
public function process_paypal_ipn() {
if ( ! isset( $_POST['payment_status'] ) || empty( $_POST['payment_status'] ) ) return;
if ( $_POST['payment_status'] != 'Completed' || $_POST['payment_status'] != 'Processed' ) return;
$this->pay_commission( $_POST );
}
public function pay_commission( $data ) {
if ( empty( $data ) ) {
return false;
}
$amount = $data['mc_gross'];
$txn_id = $data['txn_id'];
$currency = $data['mc_currency'];
list( $post_id, $user_id ) = explode( ':', $data['custom'] );
$this->process_commission( $amount, $currency, $post_id, $user_id, $txn_id );
}
public function process_commission( $amount, $currency, $post_id, $user_id, $txn_id ) {
global $affiliate; // Used for communication with Affiliates plugin.
global $blog_id, $site_id; // Used for logging.
$pay_once = defined( 'AFFILIATE_PAYONCE' ) && 'yes' == AFFILIATE_PAYONCE;
$user_id_referrer = null;
if ( $user_id ) {
$user_id_referrer = get_user_meta( $user_id, 'affiliate_referred_by', true );
if ( empty( $user_id_referrer ) ) {
// We do not know who referred the user, don't pay a commission.
return;
}
$affiliate_paid = get_user_meta( $user_id, 'affiliate_paid', true );
if ( $pay_once && 'yes' == $affiliate_paid ) {
// The referrer already got a one-time commission, don't pay again.
return;
}
} else {
if ( isset( $_COOKIE[ 'affiliate_' . COOKIEHASH ] ) ) {
global $wpdb;
$hash = addslashes( $_COOKIE[ 'affiliate_' . COOKIEHASH ] );
$user_id_referrer = $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = 'affiliate_hash' AND meta_value = %s", $hash ) );
}
}
if ( ! $user_id_referrer ) return;
$complete_records = $affiliate->get_complete_records(
$user_id_referrer,
date( 'Ym' ),
array( self::AREA_KEY ),
$user_id
);
if ( is_array( $complete_records ) ) {
// Make sure that this payment was not commissioned before.
foreach ( $complete_records as $record ) {
$meta = maybe_unserialize( $record->meta );
if ( $meta['txn_id'] == $txn_id ) {
// It seems this payment was already commissioned.
return;
}
}
}
// Okay, the referrer is entitiled to the commission!
/*
* Reward is the money that the user receives.
* It is stored in cents/milli-percent.
* I.e. '100' $ -> 1.00 $ and '100' % -> 1.00 %
*/
$reward = $this->get_value( $post_id );
$type = $this->get_type( $post_id );
switch ( $type ) {
case 'per':
$reward = $amount * $reward / 100;
break;
case 'abs':
default:
// Reward already has correct value.
break;
}
$reward = round( $reward, 2, PHP_ROUND_HALF_DOWN );
$meta = array(
'blog_id' => $blog_id,
'site_id' => $site_id,
'current_user_id' => get_current_user_id(),
'REMOTE_URL' => $_SERVER['HTTP_REFERER'],
'txn_id' => $txn_id,
'post_id' => $post_id
);
$affiliate_process_payment = apply_filters( 'affiliate_process_payment', true, $user_id_referrer, $reward, $user_id, $meta );
if ( ! $affiliate_process_payment ) return;
do_action(
'affiliate_purchase',
$user_id_referrer,
$reward,
self::AREA_KEY,
$user_id,
__( 'PayPerView', 'affiliate' ),
$meta
);
if ( $pay_once && $user_id ) {
update_user_meta( $user_id, 'affiliate_paid', 'yes' );
}
}
//
// INTERNAL HELPER FUNCTIONS.
//
protected function get_value( $post_id ) {
$reward = get_post_meta( $post_id, self::AFF_COMMISSION_FIELD, true );
if ( empty( $reward ) ) {
$reward = esc_attr( get_option(self::AFF_COMMISSION_FIELD) );
}
$reward = max( 0, intval( $reward ) );
return $reward;
}
protected function get_type( $post_id ) {
$available_types = array( 'per', 'abs' );
$type = get_post_meta( $post_id, self::AFF_REWARD_TYPE, true );
if ( empty($type) || ! in_array( $type, $available_types ) ) {
$type = esc_attr( get_option(self::AFF_REWARD_TYPE) );
}
if ( empty($type) || ! in_array( $type, $available_types ) ) {
$type = 'abs';
}
return $type;
}
};
// Initialize the integration
Affiliate_PayPerView_Integration::setup();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment