├── README.md ├── payment_form.php └── PaymentPaypal.module /README.md: -------------------------------------------------------------------------------- 1 | # PaymentPaypal 2 | PayPal payment method for ProcessWire 3 | 4 | ## Requirements 5 | Requires PaymentModule -module 6 | 7 | ## Example 8 | 9 | ```PHP 10 | 11 | // Load the module and setup payment 12 | $payment = $modules->get("PaymentPaypal"); 13 | $payment->setCurrency("EUR"); 14 | $payment->setId(123456789); 15 | 16 | $customer = Array(); 17 | $customer['givenName'] = "Antti"; 18 | $customer['familyName'] = "Peisa"; 19 | $customer['streetAddress'] = "Some Street"; 20 | $customer['locality'] = "Some City"; 21 | $customer['postalCode'] = "12345"; 22 | $customer['email'] = "antti.peisa@gmail.com"; 23 | $payment->setCustomerData($customer); 24 | 25 | $title = "Cool product"; 26 | $quantity = 2; 27 | $amount = 1000; // Amount in payment modules always in cents 28 | $payment->addProduct($title, $amount, $quantity); 29 | 30 | // In this example we are going to do all in same page 31 | $url = $page->httpUrl; 32 | $payment->setProcessUrl($url . "?step=process"); 33 | $payment->setFailureUrl($url . "?step=fail"); 34 | $payment->setCancelUrl($url . "?step=cancel"); 35 | 36 | switch ($input->get->step) { 37 | case 'process': 38 | if ($payment->processPayment()) { 39 | echo "Thanks, payment successful!"; 40 | } else { 41 | echo "Are you kidding me?"; 42 | } 43 | break; 44 | 45 | case 'fail': 46 | echo "Something went wrong"; 47 | break; 48 | 49 | case 'cancel': 50 | echo "I think you cancelled?"; 51 | break; 52 | 53 | default: 54 | echo $payment->render(); 55 | break; 56 | } 57 | ``` 58 | 59 | ## License 60 | GPL 2.0 61 | -------------------------------------------------------------------------------- /payment_form.php: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | amount / 100; 34 | $amount = str_replace(",", ".", $amount); 35 | echo ''; 36 | echo ''; 37 | echo ''; 38 | echo ''; 39 | } 40 | ?> 41 | 42 | " class="button" type="submit"> 43 | 44 |
45 | 46 | -------------------------------------------------------------------------------- /PaymentPaypal.module: -------------------------------------------------------------------------------- 1 | 'PaymentPaypal', 22 | 'version' => 001, 23 | 'summary' => 'PaymentPaypal - using standard payment API and PDT for verification', 24 | 'singular' => false, 25 | 'autoload' => false, 26 | 'requires' => 'PaymentModule' 27 | ); 28 | } 29 | 30 | public function init() { 31 | $this->currency = $this->defaultCurrency; 32 | } 33 | 34 | public function getTitle() { 35 | return $this->_("PayPal"); 36 | } 37 | 38 | public function getFailureReason() { 39 | return $this->session->paypalError; 40 | } 41 | 42 | public function processPayment() { 43 | 44 | $tx = $this->input->get->tx; 45 | $postParams = array( 46 | 'cmd' => '_notify-synch', 47 | 'tx' => $tx, 48 | 'at' => $this->identityToken 49 | ); 50 | 51 | $endpoint = $this->endpoint . 'cgi-bin/webscr'; 52 | 53 | if ($this->curl) { 54 | $ch = curl_init(); 55 | curl_setopt($ch,CURLOPT_URL, $endpoint); 56 | curl_setopt($ch,CURLOPT_POST, count($postParams)); 57 | curl_setopt($ch,CURLOPT_POSTFIELDS, http_build_query($postParams)); 58 | curl_setopt($ch,CURLOPT_RETURNTRANSFER, TRUE); 59 | curl_setopt($ch,CURLOPT_HEADER, FALSE); 60 | curl_setopt($ch,CURLOPT_SSLVERSION, 6); 61 | $response = curl_exec($ch); 62 | } else { 63 | $http = new WireHttp(); 64 | $response = $http->post($endpoint, $postParams); 65 | } 66 | 67 | if (! $response) { 68 | throw new WireException("Couldn't get access into "); 69 | 70 | } 71 | 72 | // Response should start with SUCCESS, otherwise something fishy going on (or more likely PayPal changing something...) 73 | if( ! strpos($response, 'SUCCESS') === 0) { 74 | // TODO: We could do much better error handling here 75 | if (strpos($response, "4020")) $this->session->paypalError = "PayPal error 4020. Most probably wrong or missing Identity Token"; 76 | else $this->session->paypalError = $response; 77 | return false; 78 | } 79 | 80 | // Clean the messy response into an array 81 | $data = substr($response, 7); 82 | $data = urldecode($data); 83 | preg_match_all('/^([^=\s]++)=(.*+)/m', $data, $m, PREG_PATTERN_ORDER); 84 | $data = array_combine($m[1], $m[2]); 85 | 86 | // Verify payment to have same id and amount that we except 87 | $amount = $data['mc_gross'] * 100; 88 | if ($this->getTotalAmount() == $amount && $this->id == $data['invoice']) { 89 | return true; 90 | } 91 | 92 | return false; 93 | } 94 | 95 | public function render() { 96 | 97 | if ($this->getTotalAmount() <= 0) throw new WireException("Products are not set"); 98 | if ($this->processUrl == '') throw new WireException("processUrl is not set"); 99 | 100 | $formTemplate = new TemplateFile(__DIR__ . DIRECTORY_SEPARATOR . "payment_form.php"); 101 | $formTemplate->set("invoice", $this->id); 102 | $formTemplate->set("endpoint", $this->endpoint); 103 | $formTemplate->set("customer", $this->customer); 104 | $formTemplate->set("products", $this->products); 105 | $formTemplate->set("business", $this->business); 106 | $formTemplate->set("currency", $this->currency); 107 | $formTemplate->set("location", $this->location); 108 | $formTemplate->set("returnUrl", $this->processUrl); 109 | $formTemplate->set("returntxt", $this->returntxt); 110 | $formTemplate->set("cancelUrl", $this->cancelUrl); 111 | 112 | return $formTemplate->render(); 113 | } 114 | 115 | public static function getModuleConfigInputfields(array $data) { 116 | $inputfields = new InputfieldWrapper(); 117 | 118 | $field = wire('modules')->get('InputfieldText'); 119 | $field->name = 'currency'; 120 | $field->label = __("Default currency"); 121 | $field->notes = __("Use this currency by default (always possible to overwrite when using this module from API)"); 122 | if(isset($data['currency'])) $field->value = $data['currency']; 123 | $inputfields->add($field); 124 | 125 | $field = wire('modules')->get('InputfieldText'); 126 | $field->name = 'returntxt'; 127 | $field->label = __("Return to store text at PayPal"); 128 | $field->notes = __("Text that is shown on back to store buttons at PayPal."); 129 | if(isset($data['returntxt'])) $field->value = $data['returntxt']; 130 | $inputfields->add($field); 131 | 132 | $field = wire('modules')->get('InputfieldText'); 133 | $field->name = 'location'; 134 | $field->label = __("Location"); 135 | $field->notes = __("Location code, ie. GB"); 136 | if(isset($data['location'])) $field->value = $data['location']; 137 | $inputfields->add($field); 138 | 139 | $field = wire('modules')->get('InputfieldText'); 140 | $field->name = 'endpoint'; 141 | $field->label = __("API Endpoint"); 142 | $field->notes = __("Either https://www.paypal.com/ or https://www.sandbox.paypal.com/ depending if testing or not"); 143 | if(isset($data['endpoint'])) $field->value = $data['endpoint']; 144 | $inputfields->add($field); 145 | 146 | 147 | $field = wire('modules')->get('InputfieldText'); 148 | $field->name = 'identityToken'; 149 | $field->label = __("Identity Token"); 150 | $field->notes = __("Payment Data Transfer Identity Token (can be found from paypal.com => LOGIN => Profile => My selling preferences => Website preferences"); 151 | if(isset($data['identityToken'])) $field->value = $data['identityToken']; 152 | $inputfields->add($field); 153 | 154 | $field = wire('modules')->get('InputfieldEmail'); 155 | $field->name = 'business'; 156 | $field->label = __("PayPal email"); 157 | if(isset($data['business'])) $field->value = $data['business']; 158 | $inputfields->add($field); 159 | 160 | $field = wire('modules')->get("InputfieldMarkup"); 161 | $field->label = __("Additional information"); 162 | $field->value = "Make sure you have Auto Return and Payment Data Transfer set to ON from PayPal website preferences"; 163 | $inputfields->add($field); 164 | 165 | $field = wire('modules')->get("InputfieldCheckbox"); 166 | $field->name = 'curl'; 167 | $field->label = __("Use cURL for payment validation"); 168 | $field->description = __("If your successfull payment's doesn't validate, you might want to try this cURL based verification instead of the standard (WireHttp)"); 169 | $field->value = 1; 170 | $field->attr('checked', empty($data['curl']) ? '' : 'checked'); 171 | $inputfields->add($field); 172 | 173 | return $inputfields; 174 | } 175 | } 176 | --------------------------------------------------------------------------------