PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Core/InfinitasPayments/Lib/Providers/PayPal/PayPalExpress.php

http://github.com/infinitas/infinitas
PHP | 371 lines | 285 code | 28 blank | 58 comment | 29 complexity | f8f971dd37dc6b79f7ceb70f41fa5927 MD5 | raw file
  1. <?php
  2. App::uses('PayPalSocket', 'InfinitasPayments.Lib/Providers/PayPal');
  3. class PayPalExpress extends PayPalSocket {
  4. /**
  5. * Prepare the order by sending the details to PayPal
  6. *
  7. * @param string $state the state of the call before / after
  8. * @param array $data
  9. *
  10. * @return array
  11. */
  12. protected function _paymentPrepare($state, array $request, array $response = array()) {
  13. if ($state == 'before') {
  14. $allowNotes = !empty($request['notes']) ? false : true;
  15. if (array_key_exists('allow_notes', $request) && $request['allow_notes'] == false) {
  16. $allowNotes = false;
  17. }
  18. $return = array_merge($this->_requestDefaults(), array(
  19. 'METHOD' => 'SetExpressCheckout',
  20. 'RETURNURL' => $request['return_url'],
  21. 'CANCELURL' => $request['cancel_url'],
  22. 'REQCONFIRMSHIPPING' => (int)(!empty($request['confirmed_shipping']) ? $request['confirmed_shipping'] : false),
  23. 'NOSHIPPING' => 2,
  24. 'ALLOWNOTE' => $allowNotes,
  25. 'CHANNELTYPE' => 'Merchant',
  26. 'BRANDNAME' => Configure::read('Website.name'),
  27. ));
  28. foreach($request['orders'] as $k => $order) {
  29. $return = array_merge($return, array_filter(Hash::flatten(array(
  30. 'PAYMENTREQUEST' => array(
  31. $k => array(
  32. 'PAYMENTACTION' => 'Sale',
  33. 'SELLERPAYPALACCOUNTID' => $this->getConfig(null, 'e'),
  34. 'CURRENCYCODE' => $order['currency_code'],
  35. 'AMT' => (float)$order['total'],
  36. 'ITEMAMT' => $order['subtotal'],
  37. 'CUSTOM' => $order['custom'],
  38. 'SHIPPINGAMT' => $order['shipping'],
  39. 'HANDLINGAMT' => $order['handling'],
  40. 'INSURANCEAMT' => $order['insurance'],
  41. 'SHIPDISCAMT' => null,
  42. 'TAXAMT' => $order['tax'],
  43. 'INSURANCEOPTIONOFFERED' => '0',
  44. 'INVNUM' => $order['invoice_number'],
  45. 'NOTIFYURL' => $order['notify_url']
  46. )
  47. )
  48. ), '_')));
  49. $this->_pageStyle($order, $return, $k);
  50. $this->_items((array)$order['items'], $return, $k);
  51. $this->_user($order, $return, $k);
  52. }
  53. return $return;
  54. }
  55. return array(
  56. 'token' => $response['TOKEN'],
  57. 'timestamp' => $response['TIMESTAMP'],
  58. 'correlation' => $response['CORRELATIONID'],
  59. 'redirect' => String::insert($this->getConfig(null, 'site'), array(
  60. 'token' => $response['TOKEN']
  61. )),
  62. 'raw' => array(
  63. 'request' => json_encode($request),
  64. 'response' => json_encode($response)
  65. )
  66. );
  67. }
  68. /**
  69. * Get the paid status of an order
  70. *
  71. * @param string $status
  72. *
  73. * @return array
  74. */
  75. protected function _paidStatus($status) {
  76. switch ($status) {
  77. case 'PaymentActionFailed':
  78. return self::$ERROR;
  79. case 'PaymentActionCompleted':
  80. case 'PaymentCompleted':
  81. return self::$PAID;
  82. default:
  83. return self::$PENDING;
  84. }
  85. }
  86. /**
  87. * Get the details of a payment transaction
  88. *
  89. * before:
  90. * Build up the details of the request to get the details of an order
  91. *
  92. * after:
  93. * parse the return order details
  94. *
  95. * @param string $state before or after
  96. * @param array $data
  97. * @param array $response
  98. *
  99. * @return array
  100. */
  101. protected function _paymentStatus($state, array $request, array $response = array()) {
  102. if ($state == 'before') {
  103. return array_merge($this->_requestDefaults(), array(
  104. 'METHOD' => 'GetExpressCheckoutDetails',
  105. 'TOKEN' => $request['token'],
  106. ));
  107. }
  108. $response = Hash::expand($response, '_');
  109. $return = array(
  110. 'ack' => $response['ACK'],
  111. 'token' => $response['TOKEN'],
  112. 'checkout_status' => $response['CHECKOUTSTATUS'],
  113. 'paid_status' => $this->_paidStatus($response['CHECKOUTSTATUS']),
  114. 'timestamp' => $response['TIMESTAMP'],
  115. 'correlation' => $response['CORRELATIONID'],
  116. 'customer_id' => $response['PAYERID'],
  117. 'customer_status' => $response['PAYERSTATUS'],
  118. 'currency_code' => $response['CURRENCYCODE'],
  119. 'shipping' => $response['SHIPPINGAMT'],
  120. 'handling' => $response['HANDLINGAMT'],
  121. 'insurance' => $response['INSURANCEAMT'],
  122. 'shipping_discount' => $response['SHIPDISCAMT'],
  123. 'tax' => $response['TAXAMT'],
  124. 'total' => $response['AMT'],
  125. 'notify_url' => $response['NOTIFYURL'],
  126. 'user' => array(
  127. 'full_name' => $response['SHIPTONAME'],
  128. 'first_name' => $response['FIRSTNAME'],
  129. 'last_name' => $response['LASTNAME'],
  130. 'country_code' => $response['COUNTRYCODE'],
  131. ),
  132. 'arrdess' => array(
  133. 'street' => $response['SHIPTOSTREET'],
  134. 'city' => $response['SHIPTOCITY'],
  135. 'state' => $response['SHIPTOSTATE'],
  136. 'post_code' => $response['SHIPTOZIP'],
  137. 'country_code' => $response['SHIPTOCOUNTRYCODE'],
  138. 'country' => $response['SHIPTOCOUNTRYNAME'],
  139. 'status' => $response['ADDRESSSTATUS'],
  140. ),
  141. 'orders' => array(),
  142. 'raw' => array(
  143. 'request' => serialize($request),
  144. 'response' => serialize($response)
  145. )
  146. );
  147. foreach ($response['PAYMENTREQUEST'] as $paymentRequest) {
  148. $subTotal = !empty($paymentRequest['ITEMAMT']) ? $paymentRequest['ITEMAMT'] : null;
  149. if (!$subTotal) {
  150. $subTotal = $paymentRequest['AMT'] - array_sum(array(
  151. $paymentRequest['SHIPPINGAMT'],
  152. $paymentRequest['HANDLINGAMT'],
  153. $paymentRequest['TAXAMT']
  154. ));
  155. }
  156. $return['orders'][] = array(
  157. 'currency_code' => $paymentRequest['CURRENCYCODE'],
  158. 'total' => $paymentRequest['AMT'],
  159. 'sub_total' => $subTotal,
  160. 'shipping' => $paymentRequest['SHIPPINGAMT'],
  161. 'handling' => $paymentRequest['HANDLINGAMT'],
  162. 'tax' => $paymentRequest['TAXAMT'],
  163. 'notify_url' => $paymentRequest['NOTIFYURL'],
  164. 'insurance' => $paymentRequest['INSURANCEAMT'],
  165. 'shipping_discount_amount' => $paymentRequest['SHIPDISCAMT'],
  166. 'insurance_option_offered' => $paymentRequest['INSURANCEOPTIONOFFERED'],
  167. 'transaction_id' => $paymentRequest['TRANSACTIONID'],
  168. 'custom' => $paymentRequest['CUSTOM'],
  169. 'arrdess' => array(
  170. 'full_name' => $paymentRequest['SHIPTONAME'],
  171. 'street' => $paymentRequest['SHIPTOSTREET'],
  172. 'city' => $paymentRequest['SHIPTOCITY'],
  173. 'state' => $paymentRequest['SHIPTOSTATE'],
  174. 'post_code' => $paymentRequest['SHIPTOZIP'],
  175. 'country_code' => $paymentRequest['SHIPTOCOUNTRYCODE'],
  176. 'country' => $paymentRequest['SHIPTOCOUNTRYNAME'],
  177. 'status' => $paymentRequest['ADDRESSSTATUS'],
  178. )
  179. );
  180. }
  181. return $return;
  182. }
  183. /**
  184. * Finalise the transaction
  185. *
  186. * @param string $state
  187. * @param array $request
  188. * @param array $response
  189. *
  190. * @return array
  191. */
  192. protected function _paymentFinalise($state, array $request, array $response = array()) {
  193. if ($state == 'before') {
  194. return array_merge($this->_requestDefaults(), array(
  195. 'METHOD' => 'DoExpressCheckoutPayment',
  196. 'TOKEN' => $request['token'],
  197. 'PAYERID' => $request['customer_id'],
  198. 'PAYMENTACTION' => 'Sale',
  199. 'CURRENCYCODE' => $request['currency_code'],
  200. 'AMT'=> $request['total']
  201. ));
  202. }
  203. $response = Hash::expand($response, '_');
  204. $return = array(
  205. 'status' => $response['ACK'],
  206. 'token' => $response['TOKEN'],
  207. 'timestamp' => $response['TIMESTAMP'],
  208. 'correlation' => $response['CORRELATIONID'],
  209. 'transaction_id' => $response['TRANSACTIONID'],
  210. 'transaction_type' => $response['TRANSACTIONTYPE'],
  211. 'transaction_status' => $response['PAYMENTSTATUS'],
  212. 'transaction_fee' => $response['FEEAMT'],
  213. 'payment_type' => $response['PAYMENTTYPE'],
  214. 'order_time' => $response['ORDERTIME'],
  215. 'total' => $response['AMT'],
  216. 'tax' => $response['TAXAMT'],
  217. 'currency_code' => $response['CURRENCYCODE'],
  218. 'pending_reason' => $response['PENDINGREASON'],
  219. 'reason_code' => $response['REASONCODE'],
  220. 'protection_eligibility' => $response['PROTECTIONELIGIBILITY'],
  221. 'insurance_option_selected' => strtolower($response['INSURANCEOPTIONSELECTED']) == 'true' ? true : false,
  222. 'shipping_option_default' => strtolower($response['SHIPPINGOPTIONISDEFAULT']) == 'true' ? true : false,
  223. 'orders' => array(),
  224. 'raw' => array(
  225. 'request' => serialize($request),
  226. 'response' => serialize($response),
  227. )
  228. );
  229. foreach ($response['PAYMENTINFO'] as $paymentInfo) {
  230. $return['orders'][] = array(
  231. 'transaction_id' => $paymentInfo['TRANSACTIONID'],
  232. 'transaction_type' => $paymentInfo['TRANSACTIONTYPE'],
  233. 'transaction_status' => $paymentInfo['PAYMENTSTATUS'],
  234. 'transaction_fee' => $paymentInfo['FEEAMT'],
  235. 'payment_type' => $paymentInfo['PAYMENTTYPE'],
  236. 'order_time' => $paymentInfo['ORDERTIME'],
  237. 'total' => $paymentInfo['AMT'],
  238. 'tax' => $paymentInfo['TAXAMT'],
  239. 'currency_code' => $paymentInfo['CURRENCYCODE'],
  240. 'pending_reason' => $paymentInfo['PENDINGREASON'],
  241. 'reason_code' => $paymentInfo['REASONCODE'],
  242. 'protection_eligibility' => $paymentInfo['PROTECTIONELIGIBILITY'],
  243. 'error_code' => $paymentInfo['ERRORCODE'],
  244. 'status' => $paymentInfo['ACK']
  245. );
  246. }
  247. return $return;
  248. }
  249. /**
  250. * Parse the users details
  251. *
  252. * uptp 10 orders can be placed at once,
  253. *
  254. * @param array $request the raw data
  255. * @param array $return the data to be returned
  256. * @param integer $orderNumber the order number
  257. *
  258. * @return void
  259. */
  260. protected function _user(array $request, array &$return, $orderNumber = 0) {
  261. $return = array_merge(array_filter(array(
  262. 'EMAIL' => $request['user']['email']
  263. )), $return);
  264. $return = array_merge($return, array_filter(Hash::flatten(array(
  265. 'PAYMENTREQUEST' => array(
  266. $orderNumber => array(
  267. 'SHIPTONAME' => $request['user']['full_name'],
  268. 'SHIPTOSTREET' => $request['address']['address_1'],
  269. 'SHIPTOSTREET2' => $request['address']['address_2'],
  270. 'SHIPTOCITY' => $request['address']['city'],
  271. 'SHIPTOSTATE' => $request['address']['state'],
  272. 'SHIPTOZIP' => $request['address']['post_code'],
  273. 'SHIPTOCOUNTRYCODE' => $request['address']['country_code'],
  274. 'SHIPTOPHONENUM' => $request['user']['phone']
  275. )
  276. )
  277. ), '_')));
  278. }
  279. /**
  280. * Configure the page styles from the config
  281. *
  282. * @param array $request
  283. * @param array $return
  284. *
  285. * @return void
  286. */
  287. protected function _pageStyle(array $request, &$return) {
  288. $styles = array_merge(array(
  289. 'page_style' => 'Copify',
  290. 'header' => array(
  291. 'image' => null,
  292. 'border' => null,
  293. 'background' => null
  294. ),
  295. 'page' => array(
  296. 'background' => null
  297. )
  298. ), (array)Configure::read('InfinitasPayments.PayPal.styles'));
  299. $return = array_merge(array_filter(array(
  300. 'PAGESTYLE' => $styles['page_style'],
  301. 'HDRIMG' => $styles['header']['image'],
  302. 'HDRBORDERCOLOR' => $styles['header']['border'],
  303. 'HDRBACKCOLOR' => $styles['header']['background'],
  304. 'PAYFLOWCOLOR' => $styles['page']['background'],
  305. )), $return);
  306. }
  307. protected function _items(array $items, &$return, $orderNumber = 0) {
  308. foreach ($items as $k => $item) {
  309. $return['L_PAYMENTREQUEST_' . $orderNumber . '_NAME' . $k] = $item['name'];
  310. $return['L_PAYMENTREQUEST_' . $orderNumber . '_AMT' . $k] = (float)$item['selling'];
  311. $return['L_PAYMENTREQUEST_' . $orderNumber . '_QTY' . $k] = $item['quantity'];
  312. if (array_key_exists('description', $item) && $item['description']) {
  313. $return['L_PAYMENTREQUEST_' . $orderNumber . '_DESC' . $k] = $item['description'];
  314. }
  315. if (array_key_exists('tax', $item) && $item['tax']) {
  316. $return['L_PAYMENTREQUEST_' . $orderNumber . '_TAXAMT' . $k] = $item['tax'];
  317. }
  318. if (array_key_exists('url', $item) && $item['url']) {
  319. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMURL' . $k] = $item['url'];
  320. }
  321. if (array_key_exists('weight', $item) && $item['weight']) {
  322. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMWEIGHTVALUE' . $k] = $item['weight'];
  323. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMWEIGHTUNIT' . $k] = 'g';
  324. }
  325. if (array_key_exists('length', $item) && $item['length']) {
  326. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMLENGTHVALUE' . $k] = $item['length'];
  327. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMLENGTHUNIT' . $k] = 'mm';
  328. }
  329. if (array_key_exists('width', $item) && $item['width']) {
  330. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMWIDTHVALUE' . $k] = $item['width'];
  331. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMWIDTHUNIT' . $k] = 'mm';
  332. }
  333. if (array_key_exists('height', $item) && $item['height']) {
  334. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMHEIGHTVALUE' . $k] = $item['height'];
  335. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMHEIGHTUNIT' . $k] = 'mm';
  336. }
  337. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMCATEGORY' . $k] = 'Physical';
  338. if (array_key_exists('digital', $item) && $item['digital']) {
  339. $return['L_PAYMENTREQUEST_' . $orderNumber . '_ITEMCATEGORY' . $k] = 'Digital';
  340. }
  341. }
  342. }
  343. }