Cryptomus.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace App\Utils\Payments;
  3. use App\Utils\Library\PaymentHelper;
  4. use App\Utils\Library\Templates\Gateway;
  5. use Http;
  6. use Illuminate\Http\JsonResponse;
  7. use Illuminate\Http\Request;
  8. use Log;
  9. use Response;
  10. class Cryptomus implements Gateway
  11. {
  12. private const API_URL = 'https://api.cryptomus.com/';
  13. public static array $methodDetails = [
  14. 'key' => 'cryptomus',
  15. 'settings' => ['cryptomus_merchant_uuid', 'cryptomus_key'],
  16. ];
  17. private string $apiKey;
  18. private string $mid;
  19. public function __construct()
  20. {
  21. $this->mid = sysConfig('cryptomus_merchant_uuid');
  22. $this->apiKey = sysConfig('cryptomus_api_key');
  23. }
  24. public function purchase(Request $request): JsonResponse
  25. {
  26. $payment = PaymentHelper::createPayment(auth()->id(), $request->input('id'), $request->input('amount'));
  27. $result = $this->createOrder([
  28. 'amount' => $payment->amount,
  29. 'currency' => sysConfig('standard_currency'),
  30. 'order_id' => $payment->trade_no,
  31. 'lifetime' => 900,
  32. // 'network' => '',
  33. 'is_payment_multiple' => false,
  34. 'url_return' => route('shop.index'),
  35. 'url_success' => route('invoice.index'),
  36. 'url_callback' => route('payment.notify', ['method' => 'cryptomus']),
  37. ]);
  38. if (isset($result['state'], $result['result']['url']) && $result['state'] === 0) {
  39. $payment->update(['url' => $result['result']['url']]);
  40. return Response::json(['status' => 'success', 'url' => $result['result']['url'], 'message' => trans('user.payment.order_creation.success')]);
  41. }
  42. $payment->failed();
  43. if (isset($result['message'])) {
  44. Log::alert('【Cryptomus】创建订单错误:'.$result['message']);
  45. return Response::json(['status' => 'fail', 'message' => trans('user.payment.order_creation.failed')]);
  46. }
  47. if (! isset($result['result']['url'])) {
  48. Log::alert('【Cryptomus】创建订单错误:未获取到支付链接'.var_export($result, true));
  49. }
  50. return Response::json(['status' => 'fail', 'message' => trans('user.payment.order_creation.failed')]);
  51. }
  52. private function createOrder(array $params): array
  53. {
  54. $response = Http::withHeaders(['merchant' => $this->mid, 'sign' => $this->sign($params)])->asJson()->post(self::API_URL.'v1/payment', $params);
  55. if ($response->ok()) {
  56. return $response->json();
  57. }
  58. Log::alert('【Cryptomus】创建订单失败:'.var_export($response->json(), true));
  59. return ['status' => 'fail', 'message' => '获取失败!请检查配置信息'];
  60. }
  61. private function sign(array|string $data): string
  62. {
  63. if (isset($params['sign'])) {
  64. unset($params['sign']);
  65. }
  66. return md5(base64_encode(json_encode($data, JSON_UNESCAPED_UNICODE)).$this->apiKey);
  67. }
  68. public function notify(Request $request): void
  69. {
  70. if (! $this->verify($request->post())) {
  71. exit(400);
  72. }
  73. if ($request->has(['is_final', 'status', 'order_id']) && in_array($request->input('status'), ['paid', 'paid_over'], true) && PaymentHelper::paymentReceived($request->input(['order_id']))) {
  74. exit(200);
  75. }
  76. Log::error('【Cryptomus】交易失败:'.var_export($request->all(), true));
  77. exit(500);
  78. }
  79. private function verify(array $params): bool
  80. {
  81. return hash_equals($params['sign'], $this->sign($params));
  82. }
  83. }