Process PayPal PDT/IPN messages and link them to simple account modifications.
Implement these interfaces:
interface IAccountManager {
public function getId($data);
public function isCreated($id);
public function isActive($id);
public function create($id, $data);
public function setActive($id, $active, $data);
}
interface ITransactionLogger {
public function logTransaction($id, $data);
}
interface INotifier {
public function notify($msg);
}
Then dependency inject the implementations into PTAP
, along with a closure function that depicts what accounts actions you want to take based on PDT/IPN variables (checkout this gist for a opinionated but more encompassing closure):
$ptap = new PTAP(new DummyAccount(), new DummyLogger(), new DummyNotifier(), function($data){
if($data['txn_type'] == "web_accept") {
return array(Action::create, Category::payment);
} else if($data['txn_type'] == "new_case"){
return array(Action::deactivate, Category::dispute);
}
});
$ptap->process($_POST);
A very simple demostration of an implmentation that will create accounts when a new subscriber is created. Deactivate accounts if a payment is missed or a dispute is created, and re-activate accounts if a new payment comes in. The $repo
variable is meant to represent a repository abstraction (such a database).
include("PATP.php");
class DummyAccount implements IAccountManager {
private $repo = array();
public function getId($data){
return $data['payer_email'];
}
public function isCreated($id){
return isset($this->repo[$id]);
}
public function isActive($id){
return $this->repo[$id]["active"];
}
public function create($id, $data){
$this->repo[$id] = array(
"name" => $data["first_name"],
"password" => "foobar",
"email" => $data["payer_email"],
"active" => true
);
$this->email($id, "Hey {$this->repo[$id]["name"]}, your password is {$this->repo[$id]["password"]}");
}
public function setActive($id, $active, $data){
$this->repo[$id]["active"] = $active;
}
private function email($id, $msg){
$email = $this->repo[$id]["email"];
print "[EMAIL] sent mail to $email -> $msg<br>\n";
}
}
class DummyLogger implements ITransactionLogger {
public function logTransaction($id, $data){
print "[LOG] $id: " . var_export($data, true) . "<br>\n";
}
}
class DummyNotifier implements INotifier {
public function notify($message){
print "[NOTIFY] $message <br>\n";
}
}
$ptap = new PTAP(new DummyAccount(), new DummyLogger(), new DummyNotifier(), function($data){
switch($data["txn_type"]){
//=========== SUBSCRIPTIONS
case "subscr_signup": //Subscription started
return array(Action::create, Category::subscription);
case "subscr_payment": //Subscription payment received
return array(Action::activate, Category::subscription);
case "subscr_cancel": //Subscription canceled
case "subscr_eot": //Subscription expired
case "subscr_failed": //Subscription payment failed
return array(Action::deactivate, Category::subscription);
case "subscr_modify": //Subscription modified
return array(Action::nop, Category::subscription);
//=========== DISPUTES
case "adjustment": //A dispute has been resolved and closed
return array(Action::nop, Category::dispute);
case "new_case": //A new dispute was filed
return array(Action::deactivate, Category::dispute);
default:
throw new Exception("Unexpected transaction type $type");
}
});
And then mocking a PayPal POST request to see it in action:
$PaypalData_Payment= array(
"txn_type" => "subscr_payment",
"subscr_id" => "I-W3V7E2U39WJM",
"first_name" => "Joe Bob",
"payer_email" => "[email protected]"
);
$PaypalData_NewSubscriber = array(
"txn_type" => "subscr_signup",
"subscr_id" => "I-W3V7E2U39WJM",
"first_name" => "Joe Bob",
"payer_email" => "[email protected]"
);
$PaypalData_ReactivateSubscriber = array(
"txn_type" => "subscr_modify",
"subscr_id" => "I-W3V7E2U39WJM",
"payer_email" => "[email protected]"
);
$PaypalData_Dispute = array(
"txn_type" => "new_case",
"case_id" => "CASE444",
"payer_email" => "[email protected]"
);
$PaypalData_CancelSubscriber = array(
"txn_type" => "subscr_cancel",
"subscr_id" => "I-W3V7E2U39WJM",
"payer_email" => "[email protected]"
);
$ptap->process($PaypalData_CancelSubscriber); // Notify
$ptap->process($PaypalData_NewSubscriber); // Make account
$ptap->process($PaypalData_CancelSubscriber); // Deactivate account
$ptap->process($PaypalData_ReactivateSubscriber); // Do nothing
$ptap->process($PaypalData_Payment); // Reactivate account
$ptap->process($PaypalData_Dispute); // Deactivate account
$ptap->process($PaypalData_CancelSubscriber); // Notify
Yields the following output:
[LOG] I-W3V7E2U39WJM: array ( 'txn_type' => 'subscr_cancel', 'subscr_id' => 'I-W3V7E2U39WJM', 'payer_email' => '[email protected]', )
[NOTIFY] Attempted to set account ID [email protected] activeness to false, but the account wasnt created
[LOG] I-W3V7E2U39WJM: array ( 'txn_type' => 'subscr_signup', 'subscr_id' => 'I-W3V7E2U39WJM', 'first_name' => 'Joe Bob', 'payer_email' => '[email protected]', )
[EMAIL] sent mail to [email protected] -> Hey Joe Bob, your password is foobar
[LOG] I-W3V7E2U39WJM: array ( 'txn_type' => 'subscr_cancel', 'subscr_id' => 'I-W3V7E2U39WJM', 'payer_email' => '[email protected]', )
[LOG] I-W3V7E2U39WJM: array ( 'txn_type' => 'subscr_modify', 'subscr_id' => 'I-W3V7E2U39WJM', 'payer_email' => '[email protected]', )
[LOG] I-W3V7E2U39WJM: array ( 'txn_type' => 'subscr_payment', 'subscr_id' => 'I-W3V7E2U39WJM', 'first_name' => 'Joe Bob', 'payer_email' => '[email protected]', )
[LOG] CASE444: array ( 'txn_type' => 'new_case', 'case_id' => 'CASE444', 'payer_email' => '[email protected]', )
[LOG] I-W3V7E2U39WJM: array ( 'txn_type' => 'subscr_cancel', 'subscr_id' => 'I-W3V7E2U39WJM', 'payer_email' => '[email protected]', )
[NOTIFY] Attempted to set account ID [email protected] activeness to false, but it already was.