diff --git a/app/Http/Controllers/Pay/CoinbaseController.php b/app/Http/Controllers/Pay/CoinbaseController.php new file mode 100644 index 00000000..d5fb91ba --- /dev/null +++ b/app/Http/Controllers/Pay/CoinbaseController.php @@ -0,0 +1,144 @@ +loadGateWay($orderSN, $payway); + //构造要请求的参数数组,无需改动 + switch ($payway) { + case 'coinbase': + default: + try { + $createOrderUrl="https://api.commerce.coinbase.com/charges"; + $price_amount = sprintf('%.2f', (float)$this->order->actual_price);// 只取小数点后两位 + $fees = (double)$this->payGateway->merchant_id;//手续费费率 比如 0.05 + if($fees>0.00) + { + $price_amount =(double)$price_amount * (1.00+$fees);// 价格 * (1 + 0.05) + } + + + $redirect_url = url('detail-order-sn', ['orderSN' => $this->order->order_sn]); //同步地址 + $cancel_url = url('detail-order-sn', ['orderSN' => $this->order->order_sn]); //同步地址 + $config = [ + 'name'=>$this->order->title, + 'description'=>$this->order->title.'需付款'.$price_amount.'元', + 'pricing_type' => 'fixed_price', + 'local_price' => [ + 'amount' => $price_amount, + 'currency' => 'CNY' + ], + 'metadata' => [ + 'customer_id' => $this->order->order_sn, + 'customer_name' => $this->order->title + ], + 'redirect_url' =>$redirect_url, + 'cancel_url'=> $cancel_url + ]; + $header = array(); + $header[] = 'Content-Type:application/json'; + $header[] = 'X-CC-Api-Key:'.$this->payGateway->merchant_key; //APP key + $header[] = 'X-CC-Version: 2018-03-22'; + + $ch = curl_init(); //使用curl请求 + curl_setopt($ch, CURLOPT_URL, $createOrderUrl); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($config)); + $coinbase_json = curl_exec($ch); + curl_close($ch); + + $coinbase_date=json_decode($coinbase_json,true); + if(is_array($coinbase_date)) + { + $payment_url = $coinbase_date['data']['hosted_url']; + } + else + { + return 'fail|Coinbase支付接口请求失败'; + } + return redirect()->away($payment_url); + } catch (\Exception $e) { + throw new RuleValidationException(__('dujiaoka.prompt.abnormal_payment_channel') . $e->getMessage()); + } + break; + } + } catch (RuleValidationException $exception) { + return $this->err($exception->getMessage()); + } + } + + public function notifyUrl(Request $request) + { + $payload = file_get_contents( 'php://input' ); + $sig = $_SERVER['HTTP_X_CC_WEBHOOK_SIGNATURE']; + $data = json_decode( $payload, true ); + $event_data = $data['event']['data']; + $order = $this->orderService->detailOrderSN($event_data['metadata']['customer_id']);// + if (!$order) { + return 'fail'; + } + $payGateway = $this->payService->detail($order->pay_id); + if (!$payGateway) { + return 'fail'; + } + $secret = $payGateway->merchant_pem;//共享密钥 + $sig2 = hash_hmac( 'sha256', $payload, $secret ); + $result_str=array("confirmed","resolved");//返回的结果字符串数组 + if (!empty( $payload ) && ($sig === $sig2)) + { + + foreach ($event_data['payments'] as $payment) { + //if ((strtolower($payment['status']) === 'confirmed')||(strtolower($payment['status']) === 'resolved')) { + if(in_array(strtolower($payment['status']),$result_str){ + $return_pay_amount = $payment['value']['local']['amount']; + $return_currency=$payment['value']['local']['currency']; + $return_status=strtolower($payment['status']); + } + } + if($return_currency !== 'CNY') + { + return 'error|Notify: Wrong currency:'.$return_currency; + } + + $bccomp = bccomp($order->actual_price, $return_pay_amount, 2); //如果订单金额 大于 实际支付金额 返回1,抛出异常 + if ($bccomp == 1) { + throw new \Exception(__('Coinbase付款金额不足')); + } + $return_merchant_order_id = $event_data['metadata']['customer_id'];//卡网订单号 + $tradeid = $event_data['code'];//Coinbase订单号 + //if($return_status === 'confirmed'||$return_status === 'resolved') + if(in_array(strtolower($payment['status']),$result_str) + { + $this->orderProcessService->completedOrder($return_merchant_order_id, $order->actual_price, $tradeid);// 卡网订单号,订单金额(不能传入支付金额,否则抛出订单金额不一致异常),收款平台订单号 + return "{\"status\": 200}"; + } + else + { + //不合法的数据 + return 'fail'; + //返回失败 继续补单 + } + + } + else + { + //不合法的数据 + return 'fail|wrong sig'; + //返回失败 继续补单 + } + + } + + +} \ No newline at end of file diff --git a/database/sql/install.sql b/database/sql/install.sql index 82f6a06a..0dae6e35 100644 --- a/database/sql/install.sql +++ b/database/sql/install.sql @@ -476,6 +476,7 @@ INSERT INTO `pays` VALUES (17, 'PayPal', 'paypal', 1, 1, '商户号', NULL, '密 INSERT INTO `pays` VALUES (19, 'V 免签支付宝', 'vzfb', 1, 1, 'V 免签通讯密钥', NULL, 'V 免签地址 例如 https://vpay.qq.com/ 结尾必须有/', 'pay/vpay', 1, '2020-05-01 13:15:56', '2020-05-01 13:18:29', NULL); INSERT INTO `pays` VALUES (20, 'V 免签微信', 'vwx', 1, 1, 'V 免签通讯密钥', NULL, 'V 免签地址 例如 https://vpay.qq.com/ 结尾必须有/', 'pay/vpay', 1, '2020-05-01 13:17:28', '2020-05-01 13:18:38', NULL); INSERT INTO `pays` VALUES (21, 'Stripe[微信支付宝]', 'stripe', 1, 1, 'pk开头的可发布密钥', NULL, 'sk开头的密钥', 'pay/stripe', 1, '2020-10-29 13:15:56', '2020-10-29 13:18:29', NULL); +INSERT INTO `pays` VALUES (22, 'Coinbase[加密货币]', 'coinbase', 1, 3, '费率', 'API密钥', '共享密钥', 'pay/coinbase', 0, '2021-08-15 13:15:56', '2021-10-12 13:15:56', NULL); -- ---------------------------- COMMIT; diff --git a/public/assets/luna/main.js b/public/assets/luna/main.js index 83fb484e..966e5ff9 100644 --- a/public/assets/luna/main.js +++ b/public/assets/luna/main.js @@ -8,6 +8,7 @@ let qqSvg = ''; let otherSvg = ''; let paypal = ''; + let coinbaseSvg = ''; let paySvgArr = { zfbf2f : alipaySvg, @@ -24,6 +25,7 @@ qqpay : qqSvg, paypal : paypal, mgcoin : otherSvg, + coinbase : coinbaseSvg, vzfb : alipaySvg, vwx : weChatSvg, }; diff --git a/routes/common/pay.php b/routes/common/pay.php index 43c66252..a0e198b3 100644 --- a/routes/common/pay.php +++ b/routes/common/pay.php @@ -45,4 +45,7 @@ Route::get('stripe/return_url','StripeController@returnUrl'); Route::get('stripe/check','StripeController@check'); Route::get('stripe/charge','StripeController@charge'); + // Coinbase + Route::get('coinbase/{payway}/{orderSN}', 'CoinbaseController@gateway'); + Route::post('coinbase/notify_url', 'CoinbaseController@notifyUrl'); });