463 lines
19 KiB
PHP
463 lines
19 KiB
PHP
<?php
|
||
namespace app\api\controller;
|
||
|
||
use app\api\controller\Base;
|
||
use PaypalServerSdkLib\Authentication\ClientCredentialsAuthCredentialsBuilder;
|
||
use PaypalServerSdkLib\Environment;
|
||
use PaypalServerSdkLib\Models\Builders\AmountWithBreakdownBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\ExperienceContextBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\OrderApplicationContextBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\OrderRequestBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\PaymentSourceBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\PaypalWalletBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\PaypalWalletExperienceContextBuilder;
|
||
use PaypalServerSdkLib\Models\Builders\PurchaseUnitRequestBuilder;
|
||
use PaypalServerSdkLib\Models\PaymentSource;
|
||
use PaypalServerSdkLib\PaypalServerSdkClientBuilder;
|
||
use think\Db;
|
||
use think\db\exception\DataNotFoundException;
|
||
use think\Env;
|
||
use think\db\exception\ModelNotFoundException;
|
||
use think\Exception;
|
||
use think\Request;
|
||
use think\exception\DbException;
|
||
use think\exception\PDOException;
|
||
use think\Queue;
|
||
use think\Validate;
|
||
use think\log;
|
||
|
||
class Order extends base{
|
||
protected $PAYPAL_CLIENT_ID="ATqBigrhcNdqR8J83aDjTOoJHsAVz0U45JRY4H0stcEcv0mQrMDHQmyrydQInYd1w4lJ1ee3Wsblm2WP";
|
||
protected $PAYPAL_CLIENT_SECRET="EJL5CtykvRiMZ1apKrX4zDX03d01CuxgrUi6-D7K45NgNQAGGY0Kj0Du9tL04Zc3aDBgxgZ4JLErSQp3";
|
||
|
||
public function __construct(\think\Request $request = null)
|
||
{
|
||
parent::__construct($request);
|
||
}
|
||
|
||
public function paystationTest(){
|
||
$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" => $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']['Authentication']['auth_Status'])&&$res['PaystationQuickLookup']['LookupResponse']['Authentication']['auth_Status']=="Y"){
|
||
$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"]);
|
||
}
|
||
}
|
||
|
||
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);
|
||
} else {
|
||
echo "Response: " . $response;
|
||
}
|
||
curl_close($ch);
|
||
|
||
return jsonSuccess($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 \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();
|
||
$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);
|
||
}
|
||
|
||
|
||
|
||
} |