diff --git a/app/Http/Controllers/Gateway/BitpayX.php b/app/Http/Controllers/Gateway/BitpayX.php index b737ea41..46a9e0bf 100644 --- a/app/Http/Controllers/Gateway/BitpayX.php +++ b/app/Http/Controllers/Gateway/BitpayX.php @@ -3,7 +3,6 @@ namespace App\Http\Controllers\Gateway; use Auth; -use Http; use Illuminate\Http\JsonResponse; use Log; use Response; @@ -13,69 +12,91 @@ class BitpayX extends AbstractPayment public function purchase($request): JsonResponse { $payment = $this->creatNewPayment(Auth::id(), $request->input('id'), $request->input('amount')); - $data = [ - 'merchant_order_id' => $payment->trade_no, - 'price_amount' => $payment->amount, - 'price_currency' => 'CNY', - 'title' => '支付单号:'.$payment->trade_no, - 'description' => sysConfig('subject_name') ?: sysConfig('website_name'), - 'callback_url' => route('payment.notify', ['method' => 'bitpayx']), - 'success_url' => route('invoice'), - 'cancel_url' => route('invoice'), - 'token' => $this->sign($payment->trade_no), + 'merchant_order_id' => $payment->trade_no, + 'price_amount' => (float) $payment->amount, + 'price_currency' => 'CNY', + 'title' => '支付单号:'.$payment->trade_no, + 'description' => sysConfig('subject_name') ?: sysConfig('website_name'), + 'callback_url' => route('payment.notify', ['method' => 'bitpayx']), + 'success_url' => route('invoice'), + 'cancel_url' => route('invoice'), + 'token' => $this->sign($this->prepareSignId($payment->trade_no)), ]; + if ($request->input('type') == 1) { + $data['pay_currency'] = 'ALIPAY'; + } elseif ($request->input('type') == 3) { + $data['pay_currency'] = 'WECHAT'; + } $result = $this->sendRequest($data); - if ($result['status'] === 200 || $result['status'] === 201) { $result['payment_url'] .= '&lang=zh'; $payment->update(['url' => $result['payment_url']]); return Response::json(['status' => 'success', 'url' => $result['payment_url'], 'message' => '创建订单成功!']); } - Log::warning('创建订单错误:'.var_export($result, true)); return Response::json(['status' => 'fail', 'message' => '创建订单失败!'.$result['error']]); } - private function sign($tradeNo): string + private function prepareSignId($tradeNo): string { $data = [ 'merchant_order_id' => $tradeNo, - 'secret' => sysConfig('bitpay_secret'), - 'type' => 'FIAT', + 'secret' => sysConfig('bitpay_secret'), + 'type' => 'FIAT', ]; + ksort($data); - return $this->aliStyleSign($data, sysConfig('bitpay_secret')); + return http_build_query($data); + } + + private function sign($data) + { + return strtolower(md5(md5($data).sysConfig('bitpay_secret'))); } private function sendRequest($data, $type = 'createOrder') { - $client = Http::baseUrl('https://api.mugglepay.com/v1/') - ->timeout(15) - ->withHeaders([ - 'token' => sysConfig('bitpay_secret'), - 'content-type' => 'application/json', - ]); - - if ($type === 'query') { - $response = $client->get('orders/merchant_order_id/status?id='.$data['merchant_order_id']); - } else {// Create Order - $response = $client->post('orders', ['body' => json_encode($data)]); - } - if ($response->failed()) { - Log::error('BitPayX请求支付错误:'.var_export($response, true)); + $bitpayGatewayUri = 'https://api.mugglepay.com/v1/'; + $headers = ['content-type: application/json', 'token: '.sysConfig('bitpay_secret')]; + $curl = curl_init(); + if ($type === 'createOrder') { + $bitpayGatewayUri .= 'orders'; + curl_setopt($curl, CURLOPT_URL, $bitpayGatewayUri); + curl_setopt($curl, CURLOPT_POST, 1); + $data_string = json_encode($data); + curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string); + } elseif ($type === 'query') { + $bitpayGatewayUri .= 'orders/merchant_order_id/status?id='.$data['merchant_order_id']; + curl_setopt($curl, CURLOPT_URL, $bitpayGatewayUri); + curl_setopt($curl, CURLOPT_HTTPGET, 1); } + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + $result = curl_exec($curl); + curl_close($curl); - return $response->json(); + return json_decode($result, true); + } + + private function verify_bit($data, $signature) + { + $mySign = $this->sign($data); + + return $mySign === $signature; } //Todo: Postman虚拟测试通过,需要真实数据参考验证 public function notify($request): void { $tradeNo = $request->input(['merchant_order_id']); - if ($request->input(['status']) === 'PAID' && hash_equals($this->sign($tradeNo), $request->input(['token']))) { + // 准备待签名数据 + $str_to_sign = $this->prepareSignId($tradeNo); + if ($request->input(['status']) === 'PAID' && $this->verify_bit($str_to_sign, $request->input(['token']))) { if ($this->paymentReceived($tradeNo)) { exit(json_encode(['status' => 200])); } diff --git a/resources/views/admin/config/system.blade.php b/resources/views/admin/config/system.blade.php index 19dc3964..cd46a488 100644 --- a/resources/views/admin/config/system.blade.php +++ b/resources/views/admin/config/system.blade.php @@ -217,10 +217,10 @@
+ :list="['关闭' => '', 'F2F' => 'f2fpay', '码支付' => 'codepay', '易支付' => 'epay', '海狸支付' => 'paybeaver', '平头哥支付' => 'theadpay', '麻瓜宝' => 'bitpayx']"/> + :list="['关闭' => '', '码支付' => 'codepay', 'PayJS' => 'payjs', '易支付' => 'epay', '海狸支付' => 'paybeaver', '麻瓜宝' => 'bitpayx']"/>