Env::get("paystation.client_id"), 'gateway_id' => "PAYSTATION",//GATEWAY_ID, "merchant_session" => $sn, "merchant_reference"=>$sn, "amount" =>100, "return_url"=>"https://www.tmrjournals.com/", "response_url"=>"http://api.tmrjournals.com/public/index.php/api/Order/completePaystation" ]; $data = json_encode($data_array); $purchase = postPayStationQuery('v1/hosted/purchases', $accessToken, $data); $paystation_res = object_to_array(json_decode($purchase)); return jsonSuccess($paystation_res); } public function completePaystation(){ Log::log("payStation:act ".date("Y-m-d H:i:s")); $data = $this->request->post(); if(!isset($data['transaction_id'])|| !$data['result']['success']){ return jsonError("Paystation responds with no results or result fail"); } $tid = $data['transaction_id']; Log::log("payStation:".$tid); $paystation_info = $this->paystation_obj->where("transaction_id",$tid)->find(); if (!$paystation_info){ return jsonSuccess([]); } $order_info = $this->order_obj->where("ps_id",$paystation_info['ps_id'])->find(); $this->article_obj->where("article_id",$order_info['article_id'])->update(['is_buy'=>1]); $this->order_obj->where("order_id",$order_info['order_id'])->update(['state'=>1]); return jsonSuccess([]); } public function PaystationLookup(){ $data = $this->request->post(); $rule = new Validate([ "article_id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $article_info = $this->article_obj->where("article_id",$data['article_id'])->find(); $order_info = $this->order_obj->where("article_id",$article_info['article_id'])->whereIn("state",[0,1])->find(); if($order_info==null){ return jsonError("no order"); } sleep(2); $paystation_info = $this->paystation_obj->where("ps_id",$order_info['ps_id'])->find(); $response = paystationLookup($paystation_info["merchant_session"]); $res = xml_to_array($response); if(isset($res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage'])&&$res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage']=="Transaction successful"&&$res['PaystationQuickLookup']['LookupResponse']['PaystationErrorCode']==0){ $this->article_obj->where("article_id",$order_info['article_id'])->update(['is_buy'=>1]); $this->order_obj->where("order_id",$order_info['order_id'])->update(['state'=>1]); return jsonSuccess(["result"=>"success","paystation"=>$paystation_info]); }else{ return jsonSuccess(['result'=>"fail","msg"=> $res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage'] ?? "no message"]); } } public function testPays(){ $data = $this->request->post(); $rule = new Validate([ "ms"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $url = "https://payments.paystation.co.nz/lookup/"; $time = time(); $params = [ "pi" => "616562", "ms" => $data['ms'], "pstn_HMACTimestamp" => $time ]; $secret_key = Env::get("paystation.hmac");// 使用提供的HMAC认证密钥 // function calculate_hmac($key, $message) { // return hash_hmac('sha256', $message, $key); // } $query_string = http_build_query($params); $hmac_signature = hash_hmac('sha256', $time."paystation".$query_string,$secret_key); $params["pstn_HMAC"] = $hmac_signature; $url_with_params = $url . '?' . http_build_query($params); // echo $url_with_params; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url_with_params); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($ch); if(curl_errno($ch)) { echo 'Error:' . curl_error($ch); } curl_close($ch); return jsonSuccess(xml_to_array($response)); } public function getPreOrderDetail(){ $data = $this->request->post(); $rule = new Validate([ "article_id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $order_info = $this->order_obj->where("article_id",$data['article_id'])->whereIn("state",[0,1])->find(); if(!$order_info){ return jsonError("order not find"); } if($order_info['pay_type']==2){ $paystation = $this->paystation_obj->where("ps_id",$order_info['ps_id'])->find(); if($order_info['state']==0){ $res = xml_to_array(paystationLookup($paystation['merchant_session'])); if(isset($res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage'])&&$res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage']=='Transaction successful'){ $this->article_obj->where("article_id",$order_info['article_id'])->update(['is_buy'=>1]); $this->order_obj->where("order_id",$order_info['order_id'])->update(['state'=>1]); } } $order_info['paystation'] = $paystation; $re['detail'] = $order_info; return jsonSuccess($re); }else{ return jsonError("Payment type error"); } } /**提交改价申请 * @return void */ public function applyPrice(){ $data = $this->request->post(); $rule = new Validate([ "article_id"=>"require", "fee"=>"require", "remark"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } // 查询文章、期刊和编辑者信息 $article_info = $this->article_obj->where("article_id",$data['article_id'])->find(); $journal_info = $this->journal_obj->where("journal_id",$article_info['journal_id'])->find(); $editor_info = $this->user_obj->where("user_id",$journal_info['editor_id'])->find(); // 验证编辑者权限 if($journal_info['editor_id']!=$editor_info['user_id']){ return jsonError("You are not the editor of this journal"); } $check = Db::name("article_price_apply")->where("article_id",$data['article_id'])->where("state",0)->find(); if($check){ return jsonError("There is an unfinished price change application for this article"); } $insert['article_id'] = $data['article_id']; $insert['old_fee'] = $article_info['fee']; $insert['fee'] = $data['fee']; $insert['remark'] = $data['remark']; $insert['ctime'] = time(); Db::name("article_price_apply")->insert($insert); //发送邮件 $tt = '您有新的价格审批!link'; sendEmail("18812616272@qq.com", "tmr-文章价格申请", "tmr-文章价格申请", $tt, $journal_info['email'], $journal_info['epassword']); return jsonSuccess(); } public function getApplyList(){ $data = $this->request->post(); $data['pageIndex'] = isset($data['pageIndex'])?$data['pageIndex']:0; $data['pageSize'] = isset($data['pageSize'])?$data['pageSize']:10; $start_page = ($data['pageIndex']-1)*$data['pageSize']; $list = Db::name("article_price_apply")->where("state", $data['state'] ?? 0)->limit($start_page,$data['pageSize'])->select(); foreach ($list as $k=>$v){ $list[$k]['article_info'] = $this->article_obj->field("article_id,journal_id,accept_sn,title")->where("article_id",$v['article_id'])->find(); $list[$k]['journal_info'] = $this->journal_obj->field("journal_id,title")->where("journal_id",$list[$k]['article_info']['journal_id'])->find(); $list[$k]['history'] = Db::name("article_price_apply")->where("article_id",$list[$k]['article_info']['article_id'])->select(); } $re['list'] = $list; $re['total'] = Db::name("article_price_apply")->where("state", $data['state'] ?? 0)->count(); return jsonSuccess($re); } public function getApplyCount(){ $res = Db::name("article_price_apply")->field("state,count(*) as count")->group("state")->select(); return jsonSuccess($res); } public function acceptPriceApply(){ $data = $this->request->post(); $rule = new Validate([ "id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $apply_info = Db::name("article_price_apply")->where("id",$data['id'])->find(); $article_update['fee']=$apply_info['fee']; $article_update['fee_remark']=$apply_info['remark']; if(intval($apply_info['fee'])==0) { $article_update['is_buy']=1; } $this->article_obj->where("article_id",$apply_info['article_id'])->update($article_update); Db::name("article_price_apply")->where("id",$data['id'])->update(['state'=>1]); $order_info = $this->order_obj->where("article_id",$apply_info['article_id'])->whereIn("state",[0,1])->find(); if($order_info){ if(intval($apply_info['fee'])==0){ $this->order_obj->where("order_id",$order_info['order_id'])->update(['state'=>2]); }else{ $update1['order_fee']=$apply_info['fee']; $this->order_obj->where("order_id",$order_info['order_id'])->update($update1); } } return jsonSuccess(); } public function getArticlePriceApplyList(){ $data = $this->request->post(); $rule = new Validate([ "article_id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $list = Db::name("article_price_apply")->where("article_id",$data['article_id'])->select(); return jsonSuccess($list); } public function rejectPriceApply(){ $data = $this->request->post(); $rule = new Validate([ "id"=>"require", "remark"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } // $apply_info = Db::name("article_price_apply")->where("id",$data['id'])->find(); Db::name("article_price_apply")->where("id",$data['id'])->update(['state'=>2,"remark"=>trim($data['remark'])]); return jsonSuccess(); } /** * 修改文章价格 * * 该函数用于编辑者修改指定文章的费用信息,包括费用金额和费用备注。 * 同时会同步更新相关的订单信息(如果存在未完成的订单)。 * * @return \think\response\Json 返回JSON格式的结果,成功时返回成功状态,失败时返回错误信息 */ public function changePrice(){ // 获取POST请求数据 $data = $this->request->post(); // 验证必要字段 $rule = new Validate([ "editor_id"=>"require", "article_id"=>"require", "fee"=>"require", "fee_remark"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } // 查询文章、期刊和编辑者信息 $article_info = $this->article_obj->where("article_id",$data['article_id'])->find(); $journal_info = $this->journal_obj->where("journal_id",$article_info['journal_id'])->find(); $editor_info = $this->user_obj->where("user_id",$data['editor_id'])->find(); // 验证编辑者权限 if($journal_info['editor_id']!=$editor_info['user_id']){ return jsonError("You are not the editor of this journal"); } // 更新文章费用信息 $article_update['fee']=$data['fee']; $article_update['fee_remark']=$data['fee_remark']; if(intval($data['fee'])==0) { $article_update['is_buy']=1; } $this->article_obj->where("article_id",$data['article_id'])->update($article_update); // 如果存在未完成的订单,则同步更新订单费用 $order_info = $this->order_obj->where("article_id",$data['article_id'])->whereIn("state",[0,1])->find(); if($order_info){ if(intval($data['fee'])==0){ $this->order_obj->where("order_id",$order_info['order_id'])->update(['state'=>2]); }else{ $update1['order_fee']=$data['fee']; $this->order_obj->where("order_id",$order_info['order_id'])->update($update1); } } return jsonSuccess(); } /** * @throws DataNotFoundException * @throws ModelNotFoundException * @throws DbException * @throws PDOException * @throws Exception * @throws \Exception */ public function creatArticleOrder(){ $data = $this->request->post(); $rule = new Validate([ "article_id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $frag = []; $article_info = $this->article_obj->where("article_id",$data['article_id'])->find(); if($article_info['is_buy']==1){ return jsonError("paid"); } // $journal_info = $this->journal_obj->where("journal_id",$article_info['journal_id'])->find(); $check = $this->order_obj->where("user_id",$article_info['user_id'])->where("article_id",$data['article_id'])->whereIn("state",[0,1])->find(); if($check){ $re['paypal'] = null; $paystation_res = $this->creatPaystation($article_info['article_id']); $ps_insert['transaction_id'] = $paystation_res['transaction_id']; $ps_insert['session_id'] = $paystation_res['session_id']; $ps_insert['paystation_id'] = $paystation_res['paystation_id']; $ps_insert['currency'] = $paystation_res['currency']; $ps_insert['amount'] = $paystation_res['amount']; $ps_insert['merchant_session'] = $paystation_res['merchant_session']; $ps_insert['request_time'] = $paystation_res['request_time']; $ps_insert['payment_url'] = $paystation_res['payment_url']; $ps_insert['data'] = json_encode($paystation_res); $ps_id = $this->paystation_obj->insertGetId($ps_insert); $this->order_obj->where("order_id",$check['order_id'])->update(['ps_id'=>$ps_id,"paystation_url"=>$paystation_res['payment_url']]); $re['paystation'] = $this->paystation_obj->where("ps_id",$ps_id)->find(); $re['detail'] =$this->order_obj->where("order_id",$check['order_id'])->find(); return jsonSuccess($re); } $ca_sn = 'TMR'.date('Ymd') . strtoupper(bin2hex(random_bytes(8))); $insert1['order_sn'] = $ca_sn; $insert1['user_id'] = $article_info['user_id']; $insert1['pay_type'] = 2; $insert1["article_id"] = $data['article_id']; $insert1["currency"] = "USD"; $insert1['order_fee'] = $article_info['fee']; $insert1['real_fee'] = $article_info['fee']; $accessToken = createPayStationToken(); $data_array = [ 'paystation_id' => Env::get("paystation.client_id"), 'gateway_id' => "PAYSTATION",//GATEWAY_ID, "merchant_session" => $ca_sn, "merchant_reference"=>$ca_sn, "amount" =>(int)(prin($article_info['fee'])*100),//(int)((((int)$journal_info['fee'])*726/416)*100), // "amount" =>100, // "currency"=>"USD",//目前paystation仅支持nzd "return_url"=>"https://submission.tmrjournals.com/success?id=".$article_info['article_id'], "response_url"=>"http://api.tmrjournals.com/public/index.php/api/Order/completePaystation" ]; $data = json_encode($data_array); $purchase = postPayStationQuery('v1/hosted/purchases', $accessToken, $data); $paystation_res = object_to_array(json_decode($purchase)); // return jsonSuccess($paystation_res); $ps_insert['transaction_id'] = $paystation_res['transaction_id']; $ps_insert['session_id'] = $paystation_res['session_id']; $ps_insert['paystation_id'] = $paystation_res['paystation_id']; $ps_insert['currency'] = $paystation_res['currency']; $ps_insert['amount'] = $paystation_res['amount']; $ps_insert['merchant_session'] = $paystation_res['merchant_session']; $ps_insert['request_time'] = $paystation_res['request_time']; $ps_insert['payment_url'] = $paystation_res['payment_url']; $ps_insert['data'] = json_encode($paystation_res); $ps_id = $this->paystation_obj->insertGetId($ps_insert); $insert1['ps_id'] = $ps_id; $insert1['paystation_url'] = $paystation_res['payment_url']; $insert1['ctime'] = time(); $id = $this->order_obj->insertGetId($insert1); $frag['paystation'] = $paystation_res; $frag["paypal"] = null; $frag['detail'] = $this->order_obj->where("order_id",$id)->find(); return jsonSuccess($frag); } private function creatPaystation($article_id){ $article_info = $this->article_obj->where("article_id",$article_id)->find(); $ca_sn = 'TMR'.date('Ymd') . strtoupper(bin2hex(random_bytes(8))); $accessToken = createPayStationToken(); $data_array = [ 'paystation_id' => Env::get("paystation.client_id"), 'gateway_id' => "PAYSTATION",//GATEWAY_ID, "merchant_session" => $ca_sn, "merchant_reference"=>$ca_sn, "amount" =>(int)(prin($article_info['fee'])*100), "return_url"=>"https://submission.tmrjournals.com/success?id=".$article_info['article_id'], "response_url"=>"http://api.tmrjournals.com/public/index.php/api/Order/completePaystation" ]; $data = json_encode($data_array); $purchase = postPayStationQuery('v1/hosted/purchases', $accessToken, $data); $paystation_res = object_to_array(json_decode($purchase)); return $paystation_res; } public function getUserOrder(){ $data = $this->request->post(); $rule = new Validate([ "user_id"=>"require", "state"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $list = $this->order_obj->where("user_id",$data['user_id'])->where("state",$data['state'])->select(); foreach ($list as $k=>$v){ $article = $this->article_obj->where("article_id",$v['article_id'])->find(); $list[$k]['article_detail'] = $article; $list[$k]['journal_detail'] = $this->journal_obj->where("journal_id",$article['journal_id'])->find(); } $re['list'] = $list; return jsonSuccess($re); } private function handleResponse($response) { $jsonResponse = json_decode($response->getBody(), true); return [ "jsonResponse" => $jsonResponse, "httpStatusCode" => $response->getStatusCode(), ]; } public function preOrderDetail(){ $data = $this->request->post(); $rule = new Validate([ "article_id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $article_info = $this->article_obj->where("article_id",$data['article_id'])->find(); $journal_info = $this->journal_obj->where("journal_id",$article_info['journal_id'])->find(); $user_info = $this->user_obj->where("user_id",$article_info['user_id'])->find(); $order_info = $this->order_obj->where("article_id",$article_info['article_id'])->find(); if($order_info&$order_info['state']==0&&$order_info['ps_id']>0){ $paystation = $this->paystation_obj->where("ps_id",$order_info['ps_id'])->find(); $res = xml_to_array(paystationLookup($paystation['merchant_session'])); if(isset($res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage'])&&$res['PaystationQuickLookup']['LookupResponse']['PaystationErrorMessage']=="Transaction successful"&&$res['PaystationQuickLookup']['LookupResponse']['PaystationErrorCode']==0){ $this->article_obj->where("article_id",$order_info['article_id'])->update(['is_buy'=>1]); $this->order_obj->where("order_id",$order_info['order_id'])->update(['state'=>1]); $article_info = $this->article_obj->where("article_id",$data['article_id'])->find(); } } $re['article_detail'] = $article_info; $re['journal_detail'] = $journal_info; $re['user_detail'] = $user_info; return jsonSuccess($re); } private function createPaypalOrder($fee) { $client = $this->createClient(); $orderBody = [ "body" => OrderRequestBuilder::init("CAPTURE", [ PurchaseUnitRequestBuilder::init( AmountWithBreakdownBuilder::init("USD", $fee)->build() )->build(), ]) ->paymentSource( PaymentSourceBuilder::init()->paypal( PaypalWalletBuilder::init()->experienceContext( PaypalWalletExperienceContextBuilder::init()->returnUrl("https://www.baidu.com")->build() )->build() )->build() ) ->build(), ]; $apiResponse = $client->getOrdersController()->ordersCreate($orderBody); return $this->handleResponse($apiResponse); } public function completeOrder(){ $data = $this->request->post(); $rule = new Validate([ "order_id"=>"require" ]); if(!$rule->check($data)){ return jsonError($rule->getError()); } $order_info = $this->order_obj->where("order_id",$data['order_id'])->find(); $this->captureOrder($order_info['paypal_order_id']); $this->article_obj->where("article_id",$order_info['article_id'])->update(['is_buy'=>1]); $this->order_obj->where("order_id",$data['order_id'])->update(['state'=>1]); return jsonSuccess([]); } private function getOrderStatus($orderId){ $client = $this->createClient(); return $client->getOrdersController()->ordersGet(["id"=>$orderId]); } private function createClient(){ return PaypalServerSdkClientBuilder::init() ->clientCredentialsAuthCredentials( ClientCredentialsAuthCredentialsBuilder::init( $this->PAYPAL_CLIENT_ID, $this->PAYPAL_CLIENT_SECRET ) ) ->environment(Environment::SANDBOX) ->build(); } private function captureOrder($orderID) { $client = $this->createClient(); $captureBody = [ "id" => $orderID, ]; $apiResponse = $client->getOrdersController()->ordersCapture($captureBody); return $this->handleResponse($apiResponse); } }