CoinPayments.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <?php
  2. namespace App\Payments;
  3. class CoinPayments {
  4. public function __construct($config) {
  5. $this->config = $config;
  6. }
  7. public function form()
  8. {
  9. return [
  10. 'coinpayments_merchant_id' => [
  11. 'label' => 'Merchant ID',
  12. 'description' => '商户 ID,填写您在 Account Settings 中得到的 ID',
  13. 'type' => 'input',
  14. ],
  15. 'coinpayments_ipn_secret' => [
  16. 'label' => 'IPN Secret',
  17. 'description' => '通知密钥,填写您在 Merchant Settings 中自行设置的值',
  18. 'type' => 'input',
  19. ],
  20. 'coinpayments_currency' => [
  21. 'label' => '货币代码',
  22. 'description' => '填写您的货币代码(大写),建议与 Merchant Settings 中的值相同',
  23. 'type' => 'input',
  24. ]
  25. ];
  26. }
  27. public function pay($order) {
  28. // IPN notifications are slow, when the transaction is successful, we should return to the user center to avoid user confusion
  29. $parseUrl = parse_url($order['return_url']);
  30. $port = isset($parseUrl['port']) ? ":{$parseUrl['port']}" : '';
  31. $successUrl = "{$parseUrl['scheme']}://{$parseUrl['host']}{$port}";
  32. $params = [
  33. 'cmd' => '_pay_simple',
  34. 'reset' => 1,
  35. 'merchant' => $this->config['coinpayments_merchant_id'],
  36. 'item_name' => $order['trade_no'],
  37. 'item_number' => $order['trade_no'],
  38. 'want_shipping' => 0,
  39. 'currency' => $this->config['coinpayments_currency'],
  40. 'amountf' => sprintf('%.2f', $order['total_amount'] / 100),
  41. 'success_url' => $successUrl,
  42. 'cancel_url' => $order['return_url'],
  43. 'ipn_url' => $order['notify_url']
  44. ];
  45. $params_string = http_build_query($params);
  46. return [
  47. 'type' => 1, // Redirect to url
  48. 'data' => 'https://www.coinpayments.net/index.php?' . $params_string,
  49. 'custom_result' => 'IPN OK'
  50. ];
  51. }
  52. public function notify($params) {
  53. if (!isset($params['merchant']) || $params['merchant'] != trim($this->config['coinpayments_merchant_id'])) {
  54. abort(500, 'No or incorrect Merchant ID passed');
  55. }
  56. $headers = getallheaders();
  57. ksort($params);
  58. reset($params);
  59. $request = stripslashes(http_build_query($params));
  60. $headerName = 'Hmac';
  61. $signHeader = isset($headers[$headerName]) ? $headers[$headerName] : '';
  62. $hmac = hash_hmac("sha512", $request, trim($this->config['coinpayments_ipn_secret']));
  63. // if (!hash_equals($hmac, $signHeader)) {
  64. // if ($hmac != $_SERVER['HTTP_HMAC']) { <-- Use this if you are running a version of PHP below 5.6.0 without the hash_equals function
  65. // $this->dieSendMessage(400, 'HMAC signature does not match');
  66. // }
  67. if ($hmac != $signHeader) {
  68. abort(400, 'HMAC signature does not match');
  69. }
  70. // HMAC Signature verified at this point, load some variables.
  71. $status = $params['status'];
  72. if ($status >= 100 || $status == 2) {
  73. // payment is complete or queued for nightly payout, success
  74. return [
  75. 'trade_no' => $params['item_number'],
  76. 'callback_no' => $params['txn_id']
  77. ];
  78. } else if ($status < 0) {
  79. //payment error, this is usually final but payments will sometimes be reopened if there was no exchange rate conversion or with seller consent
  80. abort(500, 'Payment Timed Out or Error');
  81. } else {
  82. //payment is pending, you can optionally add a note to the order page
  83. die('IPN OK: pending');
  84. }
  85. }
  86. }