PayPlusLogic.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <?php
  2. namespace App\Http\logic\api;
  3. use App\dao\Pay\AccountPayInfo;
  4. use App\dao\Pay\PayController;
  5. use App\Http\helper\CreateOrder;
  6. use App\Http\helper\NumConfig;
  7. use App\Jobs\Order;
  8. use App\Notification\TelegramBot;
  9. use App\Services\CreateLog;
  10. use App\Services\OrderServices;
  11. use App\Services\PayPlus;
  12. use App\Util;
  13. use Illuminate\Support\Facades\DB;
  14. class PayPlusLogic extends BaseApiLogic
  15. {
  16. protected $service;
  17. public function __construct(PayPlus $service = null)
  18. {
  19. $this->service = $service ?: new PayPlus();
  20. }
  21. public function pay_order(
  22. $userId,
  23. $payAmount,
  24. $userPhone,
  25. $userEmail,
  26. $userName,
  27. $GiftsID,
  28. $buyIP,
  29. $AdId,
  30. $eventType,
  31. $payMethod = ''
  32. ) {
  33. $dao = new AccountPayInfo();
  34. list($userPhone, $userName, $userEmail) = $dao->payInfo($userId);
  35. $payVerify = new PayController();
  36. $payAmount = $payVerify->verify($userId, $GiftsID, $payAmount);
  37. if ($payAmount === false || $payAmount < 0) {
  38. $this->error = $payVerify->getError() ?: 'Payment error_4';
  39. return false;
  40. }
  41. $orderSn = CreateOrder::order_sn($userId);
  42. $amount = (int) round($payAmount * NumConfig::NUM_VALUE);
  43. $logic = new OrderLogic();
  44. if (
  45. !$logic->orderCreate(
  46. $orderSn,
  47. $amount,
  48. 'PayPlus',
  49. $userId,
  50. $payMethod,
  51. $GiftsID,
  52. $AdId,
  53. $eventType
  54. )
  55. ) {
  56. $this->error = $logic->getError();
  57. return false;
  58. }
  59. $payload = $this->buildPaymentPayload([
  60. 'order_sn' => $orderSn,
  61. 'amount' => $payAmount,
  62. 'user_id' => $userId,
  63. 'user_email' => $userEmail,
  64. 'user_phone' => $userPhone,
  65. 'user_name' => $userName,
  66. 'buy_ip' => $buyIP,
  67. 'pay_method' => $payMethod,
  68. ]);
  69. CreateLog::pay_request(
  70. $userPhone,
  71. json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
  72. $orderSn,
  73. $userEmail,
  74. $userId,
  75. $userName
  76. );
  77. Util::WriteLog('PayPlus', 'PayPlus payment request: ' . json_encode($payload));
  78. try {
  79. $result = $this->service->postPayin($payload);
  80. Util::WriteLog('PayPlus', 'PayPlus payment response: ' . json_encode($result));
  81. if ($result['code'] !== 200) {
  82. TelegramBot::getDefault()->sendProgramNotify(
  83. 'PayPlus payment failed',
  84. 'Response: ' . json_encode($result),
  85. null
  86. );
  87. }
  88. return $result;
  89. } catch (\Exception $exception) {
  90. Util::WriteLog('PayPlus_error', $exception->getMessage());
  91. $this->error = 'Payment processing error';
  92. return false;
  93. }
  94. }
  95. public function buildPaymentPayload(array $input)
  96. {
  97. $config = $this->service->getConfig();
  98. $payMethod = (int) ($input['pay_method'] ?: 1);
  99. $methodMap = $config['payment_methods'] ?? [
  100. 1 => 8,
  101. 2 => 2,
  102. 4 => 1,
  103. 8 => 5,
  104. ];
  105. $nameParts = preg_split('/\s+/', trim((string) ($input['user_name'] ?? '')), 2);
  106. return [
  107. 'order_type' => 'RECHARGE',
  108. 'platform_order_id' => (string) $input['order_sn'],
  109. 'currency' => strtoupper($config['currency'] ?? 'USD'),
  110. 'amount' => number_format((float) $input['amount'], 2, '.', ''),
  111. 'payment_method' => $methodMap[$payMethod] ?? 8,
  112. 'return_url' => $config['return'] ?? '',
  113. 'cancel_url' => $config['cancel'] ?? ($config['return'] ?? ''),
  114. 'connection_info' => [
  115. 'ip' => $input['buy_ip'] ?: '0.0.0.0',
  116. 'country' => $config['country'] ?? 'US',
  117. 'state' => $config['state'] ?? 'NA',
  118. 'zip_code' => $config['zip'] ?? '00000',
  119. 'media_source' => $config['media_source'] ?? 'organic',
  120. 'language' => $config['language'] ?? 'en-US',
  121. ],
  122. 'account_info' => [
  123. 'merchant_user_id' => (string) $input['user_id'],
  124. 'create_time' => time()*1000,
  125. 'role' => 'PRIVATE',
  126. 'email' => $this->emailOrDefault($input['user_email'] ?? '', $input['user_id']),
  127. 'phone' => preg_replace('/\D+/', '', (string) ($input['user_phone'] ?? '')) ?: '0000000000',
  128. 'area_code' => $config['area_code'] ?? '1',
  129. 'first_name' => 'user',
  130. 'last_name' => 'user',
  131. 'vip_level' => 0,
  132. ],
  133. ];
  134. }
  135. public function notify(array $post)
  136. {
  137. $orderSn = $post['data']['platform_order_id'] ?? '';
  138. if ($orderSn === '') {
  139. return 'success';
  140. }
  141. $order = DB::connection('write')
  142. ->table('agent.dbo.order')
  143. ->where('order_sn', $orderSn)
  144. ->first();
  145. if (!$order || !empty($order->pay_at) || !empty($order->finished_at)) {
  146. return 'success';
  147. }
  148. $data = $post['data'] ?? [];
  149. $body = [
  150. 'payment_sn' => $data['order_id'] ?? '',
  151. 'updated_at' => date('Y-m-d H:i:s'),
  152. ];
  153. if ($this->isSuccessfulPayment($post)) {
  154. $payAmount = round((float) ($data['amount'] ?? 0), 2);
  155. $body['pay_status'] = 1;
  156. $body['pay_at'] = date('Y-m-d H:i:s');
  157. $body['finished_at'] = date('Y-m-d H:i:s');
  158. $body['amount'] = (int) round($payAmount * NumConfig::NUM_VALUE);
  159. $service = new OrderServices();
  160. list($give, $favorablePrice, $recharge, $czReason, $cjReason) = $service->getPayInfo(
  161. $order->GiftsID ?: '',
  162. $order->user_id ?: '',
  163. $payAmount
  164. );
  165. list($score) = $service->addRecord(
  166. $order->user_id,
  167. $payAmount,
  168. $favorablePrice,
  169. $orderSn,
  170. $order->GiftsID,
  171. $recharge,
  172. $czReason,
  173. $give,
  174. $cjReason,
  175. $order->AdId ?: '',
  176. $order->eventType ?: '',
  177. 0
  178. );
  179. Order::dispatch([
  180. $order->user_id,
  181. $payAmount,
  182. $score,
  183. $favorablePrice,
  184. $order->GiftsID,
  185. $orderSn,
  186. ]);
  187. } elseif ($this->isFailedPayment($post)) {
  188. $body['pay_status'] = 2;
  189. } else {
  190. return 'success';
  191. }
  192. DB::connection('write')
  193. ->table('agent.dbo.order')
  194. ->where('order_sn', $orderSn)
  195. ->update($body);
  196. return 'success';
  197. }
  198. public function isSuccessfulPayment(array $post)
  199. {
  200. return ($post['event'] ?? '') === 'PAYMENT.CAPTURE.COMPLETED'
  201. && ($post['event_detail_name'] ?? '') === 'payment_captured'
  202. && (int) ($post['data']['order_status'] ?? 0) === 3;
  203. }
  204. public function isFailedPayment(array $post)
  205. {
  206. $event = $post['event'] ?? '';
  207. $detail = $post['event_detail_name'] ?? '';
  208. $status = (int) ($post['data']['order_status'] ?? 0);
  209. return ($event === 'PAYMENT.CAPTURE.COMPLETED' && in_array($status, [4, 10, 11], true))
  210. || $event === 'PAYMENT.ORDER.TIMEOUT'
  211. || in_array($detail, ['payment_declined', 'payment_timeout'], true);
  212. }
  213. protected function resolvePaymentUrl(array $result)
  214. {
  215. $data = $result['data'] ?? $result;
  216. foreach (['cashierUrl', 'cashier_url', 'payment_url', 'paymentUrl', 'redirect_url', 'url'] as $key) {
  217. if (!empty($data[$key])) {
  218. return $data[$key];
  219. }
  220. }
  221. return '';
  222. }
  223. protected function emailOrDefault($email, $userId)
  224. {
  225. return filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : 'unknown' . $userId . '@example.com';
  226. }
  227. protected function stringOrDefault($value, $default)
  228. {
  229. $value = trim((string) $value);
  230. return $value === '' ? $default : $value;
  231. }
  232. }