This bugtracker is archived (announcement). New tickets are created on github.com. See all framework issues, cms issues, and search the module listings for more specific bugtrackers.

Ticket #1760: PayPalPayment.php

File PayPalPayment.php, 10.8 KB (added by nicolaas, 6 years ago)
Line 
1<?php
2
3
4
5/**
6 * @package ecommerce
7 */
8 
9/**
10 * Sub-class of Payment that supports PayPal Website Payment Standard
11 * (https://www.paypal.com/IntegrationCenter/ic_standard_home.html) as its payment processor
12 Configure using
13  PayPalPayment::setMyVariable(value);
14 in www.mysite.com/ecommerce/_config.php file
15
16 Must configure:
17 $setPayPalRealAccount;
18 $setPayPalTestAccount;
19 $setPayPalUseTestAccount;
20 
21 May configure
22 $setPayPalImageLocation;
23 $setPayPalContinueNextButton;
24 $setPayPalPurchaseName;
25 $setPayPalCppHeaderImage;
26 $setPayPalCppHeaderBackcolor;
27 $setPayPalCppHeaderBordercolor;
28 $setPayPalCppPayflowColor;
29 $setPayPalCs;
30 
31 REQUIREMENTS:
32  need to add: "PayPalInstructions" field to CheckoutPage.php
33  static $db = array(
34   "PayPalInstructions" => "HTMLText"
35  );
36 
37  have a paypalPaymentPage.ss template or replace some code below (search for renderwith)
38  on the paypalPaymentPage you can use $PayPalInstructions (see above)
39**/
40 
41
42class PayPalPayment extends Payment {
43 
44 protected static $payPalRealAccount; static function setPayPalRealAccount($payPalRealAccount) { self::$payPalRealAccount = $payPalRealAccount; }
45 protected static $payPalTestAccount; static function setPayPalTestAccount($payPalTestAccount) { self::$payPalTestAccount = $payPalTestAccount; }
46 protected static $payPalUseTestAccount; static function setPayPalUseTestAccount($payPalUseTestAccount) { self::$payPalUseTestAccount = $payPalUseTestAccount; }
47 protected static $payPalImageLocation; static function setPayPalImageLocation($payPalImageLocation) { self::$payPalImageLocation = $payPalImageLocation; }
48 protected static $payPalContinueNextButton; static function setPayPalContinueNextButton($payPalContinueNextButton) { self::$payPalContinueNextButton = $payPalContinueNextButton; }
49 protected static $payPalPurchaseName; static function setPayPalPurchaseName($payPalPurchaseName) { self::$payPalPurchaseName = $payPalPurchaseName; }
50 protected static $payPalCppHeaderImage; static function setPayPalCppHeaderImage($payPalCppHeaderImage) { self::$payPalCppHeaderImage = $payPalCppHeaderImage; }
51 protected static $payPalCppHeaderBackcolor; static function setPayPalCppHeaderBackcolor($payPalCppHeaderBackcolor) { self::$payPalCppHeaderBackcolor = $payPalCppHeaderBackcolor; }
52 protected static $payPalCppHeaderBordercolor; static function setPayPalCppHeaderBordercolor($payPalCppHeaderBordercolor) { self::$payPalCppHeaderBordercolor = $payPalCppHeaderBordercolor; }
53 protected static $payPalCppPayflowColor; static function setPayPalCppPayflowColor($payPalCppPayflowColor) { self::$payPalCppPayflowColor = $payPalCppPayflowColor; }
54 protected static $payPalCs; static function setPayPalCs($payPalCs) { self::$payPalCs = $payPalCs; }
55 
56 
57 // extra fields to be added to the checkout form
58 // at present we do not do anything with this selection
59 // however, on the paypal select payment type the user is pushed toward paypal while they can also pay with credit card
60 // in the future, it is envisaged that their choice will be forwarded to paypal so that they can skip this section
61 function getPaymentFormFields() {
62  $field = new OptionsetField("PayPalPaymentMethod", "preferred payment method", array("VISA" => "VISA", "MASTERCARD" => "MASTERCARD", "AMEX" => "AMEX", "PAYPAL ACCOUNT" => "PAYPAL ACCOUNT"), "" );
63  $field->addExtraClass("optionSet");
64  $fieldSet = new FieldSet(
65   $field
66  );
67  return $fieldSet;
68 }
69 
70 function getPaymentFormRequirements() {
71  null;
72 }
73 
74 function getPaymentFormRequiredFields() {
75  return array();
76 }
77 
78 function processPayment($data, $form) {
79  $tmpPage = new Page();
80  $tmpPage->Title = "Make payment at Paypal";
81  /*
82  echo $this->StartPayPalForm();
83  return array('Processing' => true, 'ReturnValue' => $form);
84  */
85  $CheckoutPageObject = DataObject::get_one("CheckoutPage", "");
86  $message = $CheckoutPageObject->PayPalInstructions;   
87  $tmpPage->PayPalInstructions = $message;
88  $tmpPage->Content = $this->buildPayPalSubmission();
89  $tmpPage->URLSegment = "paypalpayment";
90  $controller = new Page_Controller($tmpPage);
91  //$controller->pushCurrent();/* does not work! */
92  $form = $controller->renderWith("paypalPaymentPage");
93  Requirements::clear(); /* does not work! */
94  return array('Processing' => true, 'ReturnValue' => $form);
95 }
96 
97 function buildPayPalSubmission() {
98  $member = $this->Member();
99  $o = DataObject::get_by_id("Order", $this->OrderID);
100  if(self::$payPalUseTestAccount) {
101   $accountEmail = self::$payPalTestAccount;
102   $URL = "https://www.sandbox.paypal.com/cgi-bin/webscr";
103  }
104  else {
105   $accountEmail = self::$payPalRealAccount;
106   $URL = "https://www.paypal.com/cgi-bin/webscr";
107  }
108
109  $returnUrl = Director::absoluteBaseURL(). 'PayPalPayment_Handler/?flush=1';
110  $cancelUrl = Director::absoluteBaseURL().  CheckoutPage::find_link() . "ConfirmPayPal/$order->ID";
111  $notifyUrl = $returnUrl;
112 
113  $info = array(
114   //<!-- PayPal Configuration -->
115   "business" => $accountEmail,
116    //rather than uploading the cart, the decision was made to just upload the total cost of the purchase   
117   "cmd" => "_xclick", //The button that the person clicked was a Buy Now button
118   "return" => $returnUrl,
119   "cancel_return" => $cancelUrl,
120   "notify_url" => $notifyUrl,
121   "rm" => 0, // 0 = GET with all variables, 1 GET without transaction variables, 2 = POST with transaction variables
122   "currency_code" => Order::site_currency(),
123   "bn" => "Silverstripe", //name of cart I think ....
124   
125   //<!-- Payment Page Information -->
126   "no_shipping" => 1,//  silverstripe collects this 0: (default) buyer is prompted to include a shipping address. 1: buyer is not asked for a shipping address? 2: buyer must provide a shipping address
127   "noShipping" => 1,//  check!
128   "no_note" => 1, //buyer does not have to leave a note
129   "cn" => "",//Label above the note field.
130   
131   //payment page look and paypal customisation
132   "image_url" => self::$payPalImageLocation,
133   "cbt" => self::$payPalContinueNextButton,
134   "lc" => "NZ", //language of login page on Paypal
135   "cpp_header_image" => self::$payPalCppHeaderImage, //Sets the image at the top left of the payment page. The image’s maximum size is 750 pixels wide by 90 pixels high. PayPal recommends that you provide an image that is stored only on a secure (https) server.
136   "cpp_headerback_color" => self::$payPalCppHeaderBackcolor,
137   "cpp_headerborder_color" => self::$payPalCppHeaderBordercolor,
138   "cpp_payflow_color" => self::$payPalCppPayflowColor,
139   "cs" => self::$payPalCs, //background color - this can be set using your paypal account
140   "page_style" => "primary", //you can set different styles or choose paypal
141   
142   //<!-- Product Information -->
143   "item_name" => self::$payPalPurchaseName,
144   "amount" => $this->Amount,
145   "quantity" => 1,
146   "item_number" => $this->OrderID,
147   "undefined_quantity" => 0,
148  /* set options - colours - etc...
149   "on0" => $paypal[on0],
150   "os0" => $paypal[os0], 
151   "on1" => $paypal[on1],
152   "os1" => $paypal[os1],
153  */
154   //<!-- Shipping and Misc Information -->
155   "shipping" => $this->Shipping,
156   "shipping2" => 0,
157   "handling" => 0,
158   "tax" => $this->AddedTax,
159   "custom" => $this->OrderID,//add anything extra here
160   "invoice" => "", //
161   
162   //<!-- Customer Information -->
163   "address_override" => 1,
164   "first_name" => $member->FirstName,
165   "last_name" => $member->Surname,
166   "address1" => $member->Address,
167   "address2" =>  $member->AddressLine2,
168   "city" =>  $member->City,
169   "country" => $member->Country,
170   "state" => $member->State,
171   "zip" => $member->Postcode,
172   //it is hard to change the SS phone number (basically one number / string) to the PayPal one (broken down into parts)
173   "night_phone_a" => "", // country code or area code
174   "night_phone_b" => "", //phone without country code or next three digits
175   "night_phone_c" => "", // last four digits
176  );
177 
178  foreach($info as $k => $v) {
179   $fields .= "<input type=\"hidden\" name=\"" . Convert::raw2att($k) . "\" value=\"" . Convert::raw2att($v) . "\" />\n";
180  }
181  return <<<HTML
182   <form id="PaymentForm" method="post" action="$URL">
183    <p>
184     $fields
185    </p>
186    <p class="Actions" id="Submit">
187     <input type="submit" value="Start Payment Process" />
188    </p>
189   </form>
190HTML;
191 }
192}
193
194/**
195 * Handler for responses from the PayPal site
196 */
197class PayPalPayment_Handler extends Controller {
198
199 function init() {
200  parent::init();
201  ManifestBuilder::compileManifest();
202  $this->paid(); 
203 }
204 function paid(){
205  $order = DataObject::get_by_id("Order", $_REQUEST["item_number"]);
206  if($_REQUEST['payment_status']=='Completed' && $order->Status == "Unpaid"){
207   $payment = Object::create("Payment");
208   $payment->Amount = $_REQUEST["payment_gross"];
209   $payment->OrderID = $_REQUEST["item_number"];
210   $payment->Status = 'Success';
211   $payment->Currency = $_REQUEST["mc_currency"];
212   $payment->TxnRef = 'PayPal technical details: '.
213    $_REQUEST["txn_id"]." | ".$_REQUEST["verify_sign"]." | ".$_REQUEST["payer_id"]." | ".
214    $_REQUEST["receiver_id"]." | ".$_REQUEST["payer_email"]." | ".$_REQUEST["mc_gross"]." | ".
215    $_REQUEST["item_number"];
216   $paymentID = $payment->write();
217   Session::set('Order.OrderID', $order->ID);
218   Session::set('Order.PurchaseComplete',true);
219   $order->Status = 'paid';
220   $order->sendReceipt();
221   $order->isComplete();
222   $order->write();   
223   Director::redirect(CheckoutPage::find_link() . "OrderSuccessful/$order->ID");
224  }
225  elseif($_REQUEST['payment_status']=='Completed' && $order->Status == "Paid") {
226   Director::redirect(CheckoutPage::find_link() . "OrderSuccessful/$order->ID");
227  }
228  elseif($_REQUEST['payment_status']=='Pending'){
229   /* CHECK THIS */
230   Director::redirect(CheckoutPage::find_link() . "ConfirmPayPal/$order->ID");
231  }
232  else{
233   Director::redirect(CheckoutPage::find_link() . "ConfirmPayPal/$order->ID");
234  }
235 }
236 
237 function PayPalInstructions() {
238  return DataObject::get_one('CheckoutPage')->PayPalInstructions;
239 }
240}
241
242
243
244/* what comes back from Paypal as get variables (see https://www.paypal.com/IntegrationCenter/ic_ipn-pdt-variable-reference.html)
245 txn_type=web_accept
246 payment_date=19%3A09%3A25+Apr+15%2C+2008+PDT
247 last_name=Tester
248 residence_country=US
249 item_name=templates
250 payment_gross=70.00
251 mc_currency=USD
252 business=abc%40def.ghi (email of business owner)
253 payment_type=instant
254 payer_status=verified
255 verify_sign=AFhW6IfTc.P96fDJUr48Gahf6BlHAhxUUkTH59p-rGnYUe2n5es5ZeLn
256 test_ipn=1
257 payer_email=testpayer%40abc.def.ghi (person paying)
258 tax=0.00
259 txn_id=40863971JS8149811
260 first_name=Chester
261 receiver_email=aaa%40bbb.com
262 quantity=1
263 payer_id=QW5PPSM3TFGPA
264 receiver_id=LZZDEWP3XWLUG
265 item_number=39
266 payment_status=Completed
267 mc_fee=3.03
268 payment_fee=3.03
269 shipping=0.00
270 mc_gross=70.00
271 custom=39
272*/