Browse Source

CCB支付下单

ccb_pay2
yangrz 3 years ago
parent
commit
cbdfdcdef3
  1. 61
      app/Model/v3/CcbPayment.php
  2. 186
      app/Service/v3/CcbPaymentService.php
  3. 32
      test/Cases/CCBTest.php

61
app/Model/v3/CcbPayment.php

@ -1,35 +1,36 @@
<?php
declare (strict_types=1);
namespace App\Model\v3;
use Hyperf\DbConnection\Model\Model;
/**
* @property int $id
* @property int $order_main_id
* @property string $main_ordr_no
* @property string $pymd_cd
* @property string $clrg_dt
* @property string $sub_appid
* @property string $sub_openid
* @property string $py_ordr_tpcd
* @property float $ordr_tamt
* @property float $txn_tamt
* @property string $orderlist
* @property string $py_trn_no
* @property string $prim_ordr_no
* @property string $ordr_gen_tm
* @property string $cshdk_url
* @property string $rtn_par_data
* @property string $ordr_stcd
* @property string $rtn_orderlist
* @property string $pay_time
* @property string $pay_type
* @property string $pay_channel
* @property string $debit_credit_type
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property int $id
* @property int $order_main_id
* @property string $main_ordr_no
* @property string $pymd_cd
* @property string $clrg_dt
* @property string $sub_appid
* @property string $sub_openid
* @property string $py_ordr_tpcd
* @property float $ordr_tamt
* @property float $txn_tamt
* @property string $orderlist
* @property string $py_trn_no
* @property string $prim_ordr_no
* @property string $ordr_gen_tm
* @property string $cshdk_url
* @property string $rtn_par_data
* @property string $ordr_stcd
* @property string $rtn_orderlist
* @property string $pay_time
* @property string $pay_type
* @property string $pay_channel
* @property string $debit_credit_type
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
*/
class CcbPayment extends Model
{
@ -50,5 +51,15 @@ class CcbPayment extends Model
*
* @var array
*/
protected $casts = ['id' => 'integer', 'order_main_id' => 'integer', 'ordr_tamt' => 'float', 'txn_tamt' => 'float', 'created_at' => 'datetime', 'updated_at' => 'datetime'];
protected $casts = [
'id' => 'integer',
'order_main_id' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
public function orderMain()
{
return $this->belongsTo(OrderMain::class, 'order_main_id', 'global_order_id');
}
}

186
app/Service/v3/CcbPaymentService.php

@ -2,13 +2,17 @@
namespace App\Service\v3;
use App\Commons\Log;
use App\Constants\v3\ErrorCode;
use App\Constants\v3\LogLabel;
use App\Constants\v3\OrderState;
use App\Exception\BusinessException;
use App\Exception\ErrorCodeException;
use App\Model\v3\CcbPayment;
use App\Model\v3\OrderMain;
use App\Model\v3\Store;
use App\Model\v3\User;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Guzzle\ClientFactory;
use Hyperf\Logger\LoggerFactory;
@ -38,6 +42,18 @@ class CcbPaymentService
*/
private $mktId;
/**
* 我方商家编号
* @var string
*/
private $merchantId;
/**
* 支付方式
* @var string
*/
private $pymdCd;
/**
* 我方私钥
* @var resource
@ -72,6 +88,12 @@ class CcbPaymentService
*/
private $logger;
/**
* @Inject
* @var Log
*/
protected $log;
public function __construct(ClientFactory $clientFactory, LoggerFactory $loggerFactory)
{
$this->clientFactory = $clientFactory;
@ -79,6 +101,8 @@ class CcbPaymentService
$this->isDebug = config('ccb.debug');
$this->mktId = config('ccb.mkt_id');
$this->merchantId = config('ccb.merchant_id');
$this->pymdCd = config('ccb.pymd_cd');
$selfPrivateKey = config('ccb.self_private_key');
$selfPrivateKey = "-----BEGIN RSA PRIVATE KEY-----\n".chunk_split($selfPrivateKey, 64, "\n")."-----END RSA PRIVATE KEY-----\n";
@ -269,18 +293,22 @@ class CcbPaymentService
return date('YmdHis').mt_rand(10000, 99999).mt_rand(10000, 99999);
}
private function genMainOrderNo()
{
return time().mt_rand(10000, 99999).mt_rand(10000, 99999);
}
/**
* 3.1 生成支付订单接口
* @param string $Main_Ordr_No 主订单编号
* @param string $Ordr_Tamt 订单总金额
* @param string $Txn_Tamt 交易总金额(实付)
* @param string $Pymd_Cd 支付方式:03为H5,05为小程序
* @param string $Sub_Appid 当前调起支付的小程序appid
* @param string $Sub_Openid 用户在小程序下的openid
* @param string|null $Sub_Appid 当前调起支付的小程序appid
* @param string|null $Sub_Openid 用户在小程序下的openid
* @param array $Orderlist 子订单列表
* @return array
*/
public function gatherPlaceorder(string $Main_Ordr_No, string $Ordr_Tamt, string $Txn_Tamt, string $Pymd_Cd, string $Sub_Appid, string $Sub_Openid, array $Orderlist)
public function gatherPlaceorder(string $Main_Ordr_No, string $Ordr_Tamt, string $Txn_Tamt, ?string $Sub_Appid, ?string $Sub_Openid, array $Orderlist)
{
$uri = '/online/direct/gatherPlaceorder';
@ -291,19 +319,22 @@ class CcbPaymentService
'Ittparty_Jrnl_No' => $this->genSerialNumber(),
'Mkt_Id' => $this->mktId,
'Main_Ordr_No' => $Main_Ordr_No,
'Pymd_Cd' => $Pymd_Cd,
'Pymd_Cd' => $this->pymdCd,
'Py_Ordr_Tpcd' => '04',
'Py_Rslt_Ntc_Sn' => '1',
'Ccy' => '156',
'Ordr_Tamt' => $Ordr_Tamt,
'Txn_Tamt' => $Txn_Tamt,
'Sub_Appid' => $Sub_Appid,
'Sub_Openid' => $Sub_Openid,
'Order_Time_Out' => '1800',
'Orderlist' => $Orderlist,
'Vno' => '4',
];
if ($this->pymdCd == '05') {
$params['Sub_Appid'] = $Sub_Appid;
$params['Sub_Openid'] = $Sub_Openid;
}
return $this->apiRequest($uri, $params);
}
@ -313,11 +344,12 @@ class CcbPaymentService
* @param string $Cmdty_Ordr_No 子订单编号
* @param string $Ordr_Amt 订单金额
* @param string $Txnamt 实付金额
* @param string $Cmdty_Dsc 商品描述
* @return string[]
*/
public function subOrderListItem(string $Mkt_Mrch_Id, string $Cmdty_Ordr_No, string $Ordr_Amt, string $Txnamt)
public function subOrderListItem(string $Mkt_Mrch_Id, string $Cmdty_Ordr_No, string $Ordr_Amt, string $Txnamt, string $Cmdty_Dsc)
{
return compact('Mkt_Mrch_Id', 'Cmdty_Ordr_No', 'Ordr_Amt', 'Txnamt');
return compact('Mkt_Mrch_Id', 'Cmdty_Ordr_No', 'Ordr_Amt', 'Txnamt', 'Cmdty_Dsc');
}
/**
@ -457,4 +489,140 @@ class CcbPaymentService
return $this->apiRequest($uri, $params);
}
/**
* 创建支付订单
* @param $globalOrderId
* @param $userId
* @return array
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function createCcbPayment($globalOrderId, $userId)
{
try {
// 待支付的,未超时(15min,900sec)的订单
$orderMain = OrderMain::query()
->where(['state' => OrderState::UNPAID, 'global_order_id' => $globalOrderId, 'user_id' => $userId])
->where('created_at', '>=', (time() - 900))
->first();
if (empty($orderMain)) {
throw new ErrorCodeException(ErrorCode::ORDER_NOT_AVAILABLE, '[支付订单号]'.$globalOrderId);
}
$user = User::select('openid')->find($userId);
$model = new CcbPayment();
$model->order_main_id = $orderMain->global_order_id;
$model->main_ordr_no = $this->genMainOrderNo();
$model->pymd_cd = $this->pymdCd;
if ($this->pymdCd == '05') {
$model->sub_appid = config('wechat.applet.app_id');
$model->sub_openid = $user->openid;
}
$model->py_ordr_tpcd = '04';
$model->ordr_tamt = $orderMain->money;
$model->txn_tamt = $orderMain->money;
$subOrderList = [];
// 运费判断
if (bccomp($orderMain->delivery_money, '0', 2) == 1) {
$subOrderList[] = $this->subOrderListItem(
$this->merchantId,
$model->main_ordr_no.'D',
$orderMain->delivery_money,
$orderMain->delivery_money,
'配送费'
);
}
// 我方分润比例%
$selfProfitRatio = config('ccb.self_profit_ratio');
if (bccomp($selfProfitRatio, '0', 3) == 0) {
throw new BusinessException(500, '未配置分润比例,请联系管理员');
}
foreach ($orderMain->orders as $order) {
if (empty($order->store->ccb_merchant_id)) {
throw new BusinessException(500, '店铺'.$order->store_id.'未配置商户编号,请联系管理员');
}
foreach ($order->orderGoods as $orderGoods) {
$goodsMoney = bcmul($orderGoods->price, (string)$orderGoods->number, 2);
$selfProfitMoney = bcmul($goodsMoney, $selfProfitRatio, 2);
$merchantProfitMoney = bcsub($goodsMoney, $selfProfitMoney, 2);
// 平台抽佣后最小金额不能为0
if (bccomp($merchantProfitMoney, '0', 2) == 0) {
$selfProfitMoney = '0.00';
$merchantProfitMoney = $goodsMoney;
}
$subOrderList[] = $this->subOrderListItem(
$order->store->ccb_merchant_id,
$model->main_ordr_no.'G'.$orderGoods->id.'N01',
$merchantProfitMoney,
$merchantProfitMoney,
$orderGoods->name.'(分佣到账)'
);
if (bccomp($selfProfitMoney, '0', 2) == 1) {
$subOrderList[] = $this->subOrderListItem(
$this->merchantId,
$model->main_ordr_no.'G'.$orderGoods->id.'N02',
$selfProfitMoney,
$selfProfitMoney,
$orderGoods->name.'(平台抽佣)'
);
}
}
}
$model->orderlist = json_encode($subOrderList);
$model->save();
$result = $this->gatherPlaceorder(
$model->main_ordr_no,
$model->ordr_tamt,
$model->txn_tamt,
$model->sub_appid,
$model->sub_openid,
$subOrderList
);
$model->py_trn_no = $result['Py_Trn_No'];
$model->prim_ordr_no = $result['Prim_Ordr_No'];
$model->ordr_gen_tm = $result['Ittparty_Tms'];
if (isset($result['Cshdk_Url'])) {
$model->cshdk_url = $result['Cshdk_Url'];
}
if ($this->pymdCd == '05') {
$model->rtn_par_data = json_encode($result['Rtn_Par_Data']);
}
$model->ordr_stcd = $result['Ordr_Stcd'];
$model->rtn_orderlist = json_encode($result['Orderlist']);
$model->save();
if ($this->pymdCd == '05') {
// 返回支付参数给前端
$parameters = [
'appId' => $result['Rtn_Par_Data']['appId'],
'timeStamp' => $result['Rtn_Par_Data']['timeStamp'],
'nonceStr' => $result['Rtn_Par_Data']['nonceStr'],
'package' => $result['Rtn_Par_Data']['package'],
'signType' => $result['Rtn_Par_Data']['signType'],
'paySign' => $result['Rtn_Par_Data']['paySign'],
];
} else {
$parameters = [
'Cshdk_Url' => $model->cshdk_url,
];
}
$parameters['order_main_id'] = $orderMain->global_order_id;
return $parameters;
} catch (\Exception $e) {
$this->log->event(LogLabel::ORDER_PAYMENT_LOG, ['payment_do_exception_msg' => $e->getMessage()]);
throw new ErrorCodeException(ErrorCode::PAYMENT_FAIL, '[稍后重试]');
}
}
}

32
test/Cases/CCBTest.php

@ -73,21 +73,27 @@ class CCBTest extends HttpTestCase
// var_export($result);
// }
public function testQuery()
{
$ccb = ApplicationContext::getContainer()->get(CcbPaymentService::class);
$result = $ccb->gatherEnquireOrder('m2020060915410278990');
var_export($result);
}
// public function testQuery()
// {
// $ccb = ApplicationContext::getContainer()->get(CcbPaymentService::class);
//
// $result = $ccb->gatherEnquireOrder('m2020060915410278990');
//
// var_export($result);
// }
//
// public function testOrderInfQuery()
// {
// $ccb = ApplicationContext::getContainer()->get(CcbPaymentService::class);
//
// $result = $ccb->orderInfQuery('m2020060915410278990', '10500000780012708212236595958H');
//
// var_export($result);
// }
public function testOrderInfQuery()
public function testCreateCcbPayment()
{
$ccb = ApplicationContext::getContainer()->get(CcbPaymentService::class);
$result = $ccb->orderInfQuery('m2020060915410278990', '10500000780012708212236595958H');
var_export($result);
$ccb->createCcbPayment('415142026151948289', 193155);
}
}
Loading…
Cancel
Save