Payment.php 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php
  2. namespace app\controller;
  3. use app\BaseController;
  4. use think\facade\Db;
  5. use phpu\facade\ThinkCaptcha;
  6. use Ramsey\Uuid\Uuid;
  7. use think\captcha\facade\Captcha;
  8. /**
  9. * 支付类(彩虹易支付)
  10. */
  11. class Payment extends BaseController
  12. {
  13. protected $noNeedLogin = ['payOrder','payCallback'];
  14. public $baseUrl = 'https://pay.v8jisu.cn';
  15. public $merchantId = '28399';
  16. public $key = '0QknLivpRQB50Bq76r06PiR464SrTrvQ';
  17. // 生成 MD5 签名
  18. private function makeMd5Sign($data)
  19. {
  20. $md5_key = $this->key; // 商户密钥
  21. ksort($data); // 按照 ASCII 码排序
  22. $str = '';
  23. foreach ($data as $k => $v) {
  24. if ($v !== "" && $k != 'sign' && $k != 'sign_type') {
  25. // 排除空值、sign 和 sign_type
  26. $str .= "{$k}={$v}&";
  27. }
  28. }
  29. $str = rtrim($str, "&"); // 去掉最后一个 &
  30. $str .= $md5_key; // 按文档要求,直接拼接 KEY
  31. return md5($str); // 小写
  32. }
  33. //请求
  34. private function HttpRequest($url, $postData)
  35. {
  36. // 将数组编码为 x-www-form-urlencoded 格式的查询字符串
  37. $postData1 = http_build_query($postData);
  38. // 初始化 cURL 会话
  39. $ch = curl_init($url);
  40. // 设置 cURL 选项
  41. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 将响应作为字符串返回
  42. curl_setopt($ch, CURLOPT_POST, true); // 使用 POST 方法
  43. curl_setopt($ch, CURLOPT_POSTFIELDS, $postData1); // 设置 POST 数据
  44. curl_setopt($ch, CURLOPT_HTTPHEADER, array(
  45. 'Content-Type: application/x-www-form-urlencoded' // 设置 Content-Type 头
  46. ));
  47. // 执行请求并获取响应
  48. $response = curl_exec($ch);
  49. // 关闭 cURL 会话
  50. curl_close($ch);
  51. // 检查请求是否成功
  52. if ($response === false) {
  53. return "cURL Error: " . curl_error($ch);
  54. } else {
  55. // 处理响应
  56. return $response;
  57. }
  58. }
  59. /**
  60. * 发起支付
  61. */
  62. public function payOrder()
  63. {
  64. $goodsName = $this->request->post('goodsName'); // 商品名称
  65. $goodsPrice = $this->request->post('goodsPrice'); // 商品金额
  66. $type = $this->request->post('type'); // 支付方式
  67. $user_id = $this->getUser()->user_id; // 用户ID
  68. if(!$user_id) {
  69. $this->fail(500, '用户未登录');
  70. }
  71. $data['pid'] = $this->merchantId;
  72. // $data['method'] = 'web'; // 接口类型
  73. // $datap['device'] = 'pc'; // 设备类型
  74. $data['type'] = $type; // 支付方式
  75. $data['out_trade_no'] = date("YmdHis") . rand(100, 999); // 订单号
  76. $data['notify_url'] = 'https://api.danjiwanjia.com/payment/payCallback'; // 服务器异步通知地址
  77. $data['return_url'] = 'https://www.danjiwanjia.com/#/userCenter'; // 页面跳转通知地址
  78. $data['name'] = $goodsName; // 商品名称
  79. $data['money'] = $goodsPrice; // 商品金额
  80. $data['clientip'] = $this->request->ip(); // 用户ip地址
  81. $data['timestamp'] = time(); // 当前时间戳
  82. $data['sign_type'] = 'MD5'; // 当前时间戳
  83. $data['sign'] = $this->makeMd5Sign($data); // 签名生成
  84. // 插入数据库
  85. Db::name('tb_user_order')->insert([
  86. 'user_id' => $user_id,
  87. 'order_no' => $data['out_trade_no'],
  88. 'balance' => $goodsPrice,
  89. 'state' => 0,
  90. 'create_at' => time(),
  91. ]);
  92. $url = $this->baseUrl . '/mapi.php';
  93. $result = $this->HttpRequest($url, $data);
  94. // header('Content-Type: application/json');
  95. // echo $result;
  96. // exit();
  97. if($result['code'] == 1) {
  98. $this->success('success', $result['payurl']);
  99. } else {
  100. $this->fail(500, $result['msg']);
  101. }
  102. }
  103. /**
  104. * 支付回调
  105. */
  106. public function payCallback()
  107. {
  108. $data = $this->request->param();
  109. if(!$data) {
  110. exit('success');
  111. }
  112. $order_sn = $data['out_trade_no'];
  113. $amount = $data['money'];
  114. $order = Db::name('tb_user_order')->where('order_no', $order_sn)->find();
  115. if (!$order) {
  116. exit('订单不存在');
  117. }
  118. if ($order['state'] == 1) {
  119. // 订单已支付 不走后面的逻辑但是要返回success
  120. exit('success');
  121. }
  122. // 订单校验通过 更新订单状态
  123. Db::name('tb_user_order')
  124. ->where('order_no', $order_sn)
  125. ->update([
  126. 'state' => 1,
  127. 'pay_at' => time(),
  128. ]);
  129. exit('success');
  130. }
  131. }