Commit aab1cccd authored by wanjilong's avatar wanjilong

add: post

parent a963c378
......@@ -15,5 +15,10 @@ class PayException extends BaseException
3 => '该订单已经支付,请刷新确认',
4 => '费率计算错误,费率分母为0',
5 => '支付回调失败,请核对订单',
6 => '回调参数错误,请管理员关注',
7 => '制定订单回调类型错误,请管理员关注',
8 => '退款中订单不允许核销,请管理员关注',
9 => '未支付订单不允许核销,请管理员关注',
10 => '仅允许核销商家自己的订单,请管理员关注',
];
}
......@@ -101,7 +101,7 @@ class Logger {
];
//$_SERVER['HTTP_X_FORWARDED_FOR']
$string = json_encode($log) . "\n";
$string = json_encode($log, JSON_UNESCAPED_UNICODE) . "\n";
if($fd = @fopen($file, 'a')) {
fputs($fd, $string);
fclose($fd);
......
......@@ -28,7 +28,7 @@ class Sdk {
Logger::info('api request', ['url'=>$url, 'params'=>$params]);
$data = (new TimeOut())->runPost($url, $params, $headers);
Logger::info('api request', ['ret'=>$data]);
Logger::info('api response', ['ret'=>$data]);
return $data;
}
......
......@@ -25,6 +25,7 @@ if (!function_exists('config')) {
$key = $file.'.'. (empty($appid) ? $env : $env.'-'.$appid);
$key = $param ==='' ? $key : $key.".".$param;
return \Yaconf::get($key);
}
......
<?php
namespace App\Models\demo\mongo;
use Api\PhpUtils\Mongo\MongoBase;
class Test extends MongoBase
{
protected function getConfigIndex()
{
return "demo";
}
protected function getDatabaseName()
{
return "demo";
}
protected function getCollectionName()
{
return "user";
}
protected function getWhere($params)
{
return $params;
}
protected function getQueryOptions($fields = [], $sort = [], $limit = [])
{
$options = [
'maxTimeMS' => 800,
'limit' => 100
];
if (is_array($fields) && !empty($fields)) {
$options['projection'] = $fields;
}
if (is_array($sort) && !empty($sort)) {
$options['sort'] = $sort;
}
if (is_array($limit)) {
if (isset($limit['start'])) {
$options['skip'] = intval($limit['start']);
}
if (isset($limit['count'])) {
$options['limit'] = intval($limit['count']);
}
}
return $options;
}
}
<?php
namespace App\Models\demo\mongo;
use Api\PhpUtils\Mongo\Base;
class User extends Base
{
protected static $instance;
protected static $db_config_index = 'metro';
protected function getCollectionName()
{
return 'user';
}
protected function getWhere($params)
{
$where = [];
if (isset($params['name']) && !empty($params['name'])) {
$where['name'] = $params['name'];
}
return $where;
}
protected function getQueryOptions()
{
$options = [
'projection' => [
'mobile' => 1
],
'maxTimeMS' => 800,
'limit' => 5,
'sort' => ['mobile' => -1]
];
return $options;
}
}
<?php
namespace App\Models\demo\mysql;
use Api\PhpUtils\Mysql\MysqlBase2;
class TestMysql extends MysqlBase2
{
const TABLE_NAME = 'test';
const CONFIG_INDEX = 'merchant';
const LIFE_ACCOUNT_TYPE_PERSIONAL = 1; // 个人
const LIFE_ACCOUNT_TYPE_ENTERPRISE = 2; // 企业
const LIFE_ACCOUNT_STATUS_ON = 1; // 上线
const LIFE_ACCOUNT_STATUS_OFF = 2; // 下线
const LIFE_ACCOUNT_STATUS_UPGRADE = 3; // 升级中
const LIFE_ACCOUNT_AUTH_STATUS_NO = 1; // 未认证生活号
const LIFE_ACCOUNT_AUTH_STATUS_YES = 2; // 已认证生活号
const ENTERPRISE_AUTH_STATUS_ING = 1; // 升级审核中
const ENTERPRISE_AUTH_STATUS_FAIL = 2; // 升级失败
public static function getRecord($where, $colums = [])
{
if (empty($colums)) {
$colums = '*';
}
return self::get($colums, $where);
}
public static function getRecordMaster($where, $colums = [])
{
if (empty($colums)) {
$colums = '*';
}
return self::selectMaster($colums, $where);
}
public static function insertRecord($colums)
{
return self::insert($colums);
}
public static function updateRecord($colums, $where)
{
return self::update($colums, $where);
}
public static function save($data, $where = [])
{
if (empty($where)) {
return self::insert($data);
}
return self::update($data, $where);
}
public static function deleteRecord($where)
{
return self::delete($where);
}
public static function getAccountList($data, $colums = [])
{
$colums = " * ";
$where = " 1=1 ";
if (!empty($data['life_account_name'])) {
$where .= " and (`life_account_name` LIKE '%{$data['life_account_name']}%') ";
}
if (!empty($data['life_account_type'])) {
$where .= " and life_account_type = '{$data['life_account_type']}'";
}
if (!empty($data['ORDER'])) {
$where .= " ORDER BY `create_time` DESC ";
}
if (!empty($data['LIMIT'])) {
$where .= " LIMIT {$data['LIMIT'][1]} OFFSET {$data['LIMIT'][0]} ";
}
return $data = self::query("SELECT {$colums} FROM `life_account` WHERE $where ")->fetchAll();
}
public static function getAccountCount($data, $colums = [])
{
$colums = " * ";
$where = " 1=1 ";
if (!empty($data['life_account_name'])) {
$where .= " and (`life_account_name` LIKE '%{$data['life_account_name']}%') ";
}
if (!empty($data['life_account_type'])) {
$where .= " and life_account_type = '{$data['life_account_type']}'";
}
$data = self::query("SELECT COUNT(*) as count FROM `life_account` WHERE $where ")->fetch();
return !empty($data['count']) ? $data['count'] : 0;
}
public static function getRecords($where, $colums = [])
{
if (empty($colums)) {
$colums = '*';
}
return self::select($colums, $where);
}
public static function getCount($where)
{
return self::count($where);
}
public static function duplicate($data, $duplicate)
{
return self::insertDuplicate($data, $duplicate);
}
public static function forupdate($columns, $where)
{
return self::selectForUpdate($columns, $where);
}
}
<?php
namespace App\Models\demo\mysql;
use Api\PhpUtils\Mysql\Base;
class User extends Base
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'user';
}
protected function getPKey()
{
return 'id';
}
protected function getWhere($params)
{
$where = [];
if (isset($params['ids']) && !empty($params['ids'])) {
$where['id'] = $params['ids'];
}
if (isset($params['name']) && !empty($params['name'])) {
$where['name'] = $params['name'];
}
if (isset($params['id[>]']) && !empty($params['id[>]'])) {
$where['id[>]'] = $params['id[>]'];
}
return $where;
}
}
......@@ -2,24 +2,13 @@
namespace App\Models\order\mysql;
use Api\PhpUtils\Mysql\MysqlBase;
use App\Exception\custom\PayException;
use Helpers\Logger;
class PayOrder extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order';
}
protected function getPKey()
{
return 'pay_order_id';
}
const TABLE_NAME = 'pay_order';
const CONFIG_INDEX = 'pay';
/**
* @param $order_id
......@@ -28,30 +17,14 @@ class PayOrder extends MysqlBase
*/
public static function get_valid_order($order_id, $pay_order) {
$link = self::getConnection('write');
$order = [];
$link->action(function($link, $order_id, $pay_order) use (&$order) {
$_date = date('Y-h-m H:i:s');
$sql = "select * from " . self::getTableName() . " where order_id = :order_id and expire_time >:date limit 1 for update";
$order = $link->query(
$sql, [
":order_id" => $order_id,
":date" => $_date
]
)->fetch();
self::beginTransaction();
$_date = date('Y-m-d H:i:s');
$order = self::getMaster('*', ['order_id'=>$order_id, 'expire_time[>]'=>$_date]);
if(empty($order)) {
$link->insert(self::getTableName(), $pay_order);
$order = $link->query(
$sql, [
":order_id" => $order_id,
":date" => $_date
]
)->fetch();
self::insert($pay_order, ['rowCount'=>true]);
$order = $pay_order;
}
});
self::commit();
return $order;
}
}
......@@ -5,19 +5,6 @@ use Api\PhpUtils\Mysql\MysqlBase;
class PayOrderClearing extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order_clearing';
}
protected function getPKey()
{
return 'pay_order_clearing_id';
}
const TABLE_NAME = 'pay_order_clearing';
const CONFIG_INDEX = 'pay';
}
......@@ -5,19 +5,6 @@ use Api\PhpUtils\Mysql\MysqlBase;
class PayOrderClearingItem extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order_clearing_item';
}
protected function getPKey()
{
return 'pay_order_clearing_item_id';
}
const TABLE_NAME = 'pay_order_clearing_item';
const CONFIG_INDEX = 'pay';
}
......@@ -5,19 +5,6 @@ use Api\PhpUtils\Mysql\MysqlBase;
class PayOrderItem extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'pay_order_item';
}
protected function getPKey()
{
return 'pay_order_item_id';
}
const TABLE_NAME = 'pay_order_item';
const CONFIG_INDEX = 'pay';
}
......@@ -5,19 +5,6 @@ use Api\PhpUtils\Mysql\MysqlBase;
class RefundOrder extends MysqlBase
{
protected static $write;
protected static $read;
protected static $db_config_index = 'metro';
protected function getTableName()
{
return 'refund_order';
}
protected function getPKey()
{
return 'refund_order_id';
}
const TABLE_NAME = 'refund_order';
const CONFIG_INDEX = 'pay';
}
......@@ -13,19 +13,23 @@ class CallbackController extends Base
*/
public function payAction()
{
try{
// try{
$raw_data = file_get_contents('php://input');
$paySrv = new PayService();
$ret = $paySrv->call_back($raw_data);
//todo ping++ 回调数据验签
$this->success(['result'=>$ret]);
$data = json_decode($raw_data, true);
$ret = $paySrv->call_back($data);
$this->success(['result'=>$ret]);
/*
}catch (Exception $e) {
http_response_code(500);
$this->failed('500');
}
}*/
}
public function refundAction() {
......
......@@ -13,17 +13,28 @@ class OrderService
* @param $userId
* 调用内部服务获取用户订单、子单、分润信息
*/
public static function getOrderData($order_id, $user_id) {
public static function getFullOrderData($order_id, $user_id) {
$url = config('interface', 'order.order.pay_order');
if (!$url) {
throw new CodeSpecialException("failed");
throw new CodeSpecialException("failed" . __METHOD__ );
}
$params = ['user_id'=>$user_id, 'order_id'=>$order_id];
return Sdk::call($url, $params);
}
public static function getOrderInfo($order_id, $user_id) {
//pay_order_info
$url = config('interface', 'order.order.pay_order_info');
if (!$url) {
throw new CodeSpecialException("failed" . __METHOD__ );
}
$params = ['order_id'=>$order_id, 'user_id'=>$user_id];
return Sdk::call($url, $params);
}
/**
* @param $order_item_id
* @param $user_id
......@@ -35,7 +46,7 @@ class OrderService
//merchant.account.get_role_list
$url = config('interface', 'order.order.pay_order_item');
if (!$url) {
throw new CodeSpecialException("failed");
throw new CodeSpecialException("failed" . __METHOD__ );
}
$params = ['user_id'=>$user_id, 'order_item_id'=>$order_item_id];
......
......@@ -9,12 +9,14 @@ use App\Models\order\mysql\PayOrder;
use App\Models\order\mysql\PayOrderItem;
use App\Models\order\mysql\PayOrderClearing;
use App\Models\order\mysql\PayOrderClearingItem;
use App\Models\order\mysql\RefundOrder;
use App\Services\Order\OrderService;
use App\Services\pingxx\PingxxService;
use App\Services\wallet\WalletService;
use Helpers\Strategy;
use Helpers\Logger;
use Helpers\Sdk;
use App\Exception\custom\PayException;
......@@ -24,77 +26,86 @@ class PayService
private $order_info = [];
// 子订单信息
private $order_items = [];
// 分销信息
private $order_distribution = [];
private $pay_order = [];
private $pay_order_items = [];
private $clear_list = [];
private $clear_items_list = [];
private $wallet_list = [];
public function do_pay($order_id, $user_id) {
public function do_pay($order_id, $user_id)
{
// 获取订单信息 + 子单信息 + 分润信息
$data = OrderService::getOrderData($order_id, $user_id);
if(empty($data['order'])) {
$data = OrderService::getOrderInfo($order_id, $user_id);
if (empty($data['result'])) {
throw new PayException(['cus' => 1]);
}
$order = $data['order'];
$order = $data['result'];
// 判断是否存在有效订单
//$order['user_id'] = 'uid5d34843d013d8';
$expire_time = time() + 30 * 60;
$pay_order_id = $this->gen_pay_order_id($order_id);
$pay_order_id = $this->gen_pay_order_id($user_id);
$pay_order = [
'pay_order_id'=>$pay_order_id,
'user_id'=>$order['user_id'],
'life_account_id'=>$order['life_account_id'],
'shop_id'=>$order['shop_id'],
'order_id'=>$order['order_id'],
'pay_order_status'=>Dictionary::O_PAY_STATUS_UNPAY,
'pay_amount'=>$order['payment'],
'third_order_id'=>'',
'expire_time'=>$expire_time,
'is_distribution'=>$order['is_distribution'] ?? 0,
'source_name'=>1,
'service_name'=>1,
'extra'=> json_encode([]),
'pay_order_id' => $pay_order_id,
'user_id' => $order['user_id'],
'life_account_id' => $order['life_account_id'],
'shop_id' => $order['shop_id'],
'order_id' => $order['order_id'],
'pay_order_status' => Dictionary::O_PAY_STATUS_UNPAY,
'pay_amount' => $order['payment'],
'third_order_id' => '',
'expire_time' => date('Y-m-d H:i:s', $expire_time),
'source_name' => 1,
'service_name' => 1,
'extra' => json_encode([]),
];
//获取或创建支付订单
$order = PayOrder::get_valid_order($order_id, $pay_order);
if(empty($order)) {
if (empty($order)) {
throw new PayException(['cus' => 0]);
}
if($order['pay_order_status'] == Dictionary::O_PAY_STATUS_PAYED) {
if ($order['pay_order_status'] == Dictionary::O_PAY_STATUS_PAYED) {
throw new PayException(['cus' => 3]);
}
$order['user_id'] = 'uid5d349de743119';
// 支持幂等,存在有效订单需要可以重复支付
$ret = PingxxService::createOrder($pay_order);
if($ret["status"] == 'paid') {
$ret = PingxxService::getInstance()->createOrder($order);
if (!empty($ret['error'])) {
throw new \ErrorException($ret['error']['message'], '2001');
}
if ($ret["status"] == 'paid') {
$edit = [
'pay_order_status'=>Dictionary::O_PAY_STATUS_PAYED,
'third_order_id'=>$ret['id'],
'pay_order_status' => Dictionary::O_PAY_STATUS_PAYED,
'third_order_id' => $ret['id'],
//'pay_channel'=>$ret['charge_essentials']['channel'],
];
PayOrder::update($edit, ['pay_order_id'=>$order['pay_order_id']]);
PayOrder::update($edit, ['pay_order_id' => $order['pay_order_id']]);
} elseif($ret["status"] == 'created') {
} elseif ($ret["status"] == 'created') {
$edit = [
'pay_order_status'=>Dictionary::O_PAY_STATUS_WAIT,
'third_order_id'=>$ret['id'],
'pay_order_status' => Dictionary::O_PAY_STATUS_WAIT,
'third_order_id' => $ret['id'],
];
PayOrder::update($edit, ['pay_order_id'=>$order['pay_order_id']]);
PayOrder::update($edit, ['pay_order_id' => $order['pay_order_id']]);
} elseif($ret["status"] == 'canceled') {
} elseif ($ret["status"] == 'canceled') {
$edit = [
'expire_time'=>date('Y-m-d H:i:s'),
'expire_time' => date('Y-m-d H:i:s'),
];
PayOrder::update($edit, ['pay_order_id'=>$order['pay_order_id']]);
PayOrder::update($edit, ['pay_order_id' => $order['pay_order_id']]);
}else{}
} else {
}
return $ret;
}
......@@ -103,39 +114,92 @@ class PayService
* @throws PayException
* 回调订单支付
*/
public function call_back($data) {
public function call_back($data)
{
if ($data['type'] != 'order.succeeded') {
throw new PayException(['cus' => 7]);
}
if(empty($data['data']['object'])) {
if (empty($data['data']['object'])) {
Logger::error('回调参数错误:', $data);
throw new PayException(['cus' => 5]);
throw new PayException(['cus' => 6]);
}
$object = $data['data']['object'];
$ping_data = PingxxService::getOrder($object['id']);
/*
$ping_data = PingxxService::getInstance()->getOrder($object['id']);
if($ping_data['status'] != 'paid') {
throw new PayException(['cus' => 5]);
} //actual_amount 金额核对
*/
// 修改状态,锁定业务
$pay_order_id = $ping_data['merchant_order_no'];
$pay_order_id = $object['merchant_order_no'];
$this->lock_pay_order($pay_order_id);
//获取订单 + 子单 + 分销信息
$ret = OrderService::getOrderData($this->pay_order['order_id'], $this->pay_order['user_id']);
if(empty($ret['order'])) {
$ret = OrderService::getFullOrderData($this->pay_order['order_id'], $this->pay_order['user_id']);
if (empty($ret['result']['order_info'])) {
throw new PayException(['cus' => 1]);
}
// 生成支付清分单
$this->make_order_clearing($ret);
$this->make_order_clearing($ret['result']);
}
public function write_off($order_item_id, $life_account_id)
{
try{
PayOrderItem::beginTransaction();
$refund = RefundOrder::getMaster('*', ['order_item_id'=>$order_item_id]);
if(!empty($refund)) {
throw new PayException(['cus'=>8]);
}
$this->make_order_clear();
$item = PayOrderItem::getMaster('*', ['order_item_id' => $order_item_id, 'notify_account_status' => 0]);
if(empty($item)) {
throw new PayException(['cus'=>9]);
}
$pay_order = PayOrder::getMaster('*', ['pay_order_id'=>$item['pay_order_id']]);
if(empty($pay_order) || $pay_order['life_account_id'] != $life_account_id) {
throw new PayException(['cus'=>10]);
}
public function write_off() {
//锁定状态
PayOrderItem::update([
'notify_account_status' => 1,
], ['order_item_id' => $order_item_id, 'notify_account_status' => 0]);
PayOrderItem::commit();
}catch (\Exception $e) {
PayOrderItem::rollback();
throw $e;
}
$clearing_items = PayOrderClearingItem::select('*',
['order_item_id' => $item['order_item_id']]
);
$wallet_list = [];
foreach ($clearing_items as $row) {
$wallet_list[] = [
'account_id' => $row['account_id'],
'pay_amount' => $row['pay_amount'],
'pay_type' => $row['pay_type'],
'trade_id' => $row['pay_order_clearing_item_id'],
];
}
if ($wallet_list) {
$ret = WalletService::send($wallet_list);
if($ret) {
PayOrderItem::update([
'notify_account_status' => 2,
'notify_account_success_time' => date('Y-m-d H:i:s')
], ['pay_order_id' => $this->pay_order['order_id'], 'notify_account_status' => 1]);
}
}
}
/**
......@@ -143,154 +207,99 @@ class PayService
* @throws PayException
* 锁定支付状 态
*/
private function lock_pay_order($pay_order_id) {
try{
private function lock_pay_order($pay_order_id)
{
try {
PayOrder::beginTransaction();
$pay_order = PayOrder::getMaster('*', ['pay_order_id'=>$pay_order_id]);
if(empty($pay_order)) {
$pay_order = PayOrder::getMaster('*', ['pay_order_id' => $pay_order_id]);
if (empty($pay_order)) {
throw new PayException(['cus' => 0]);
}
$this->pay_order = $pay_order;
/*
// 如果已经支付,返回成功保持幂等。
if($pay_order['pay_order_status'] == Dictionary::O_PAY_STATUS_PAYED) {
throw new RefundException(['cus' => 0]);
throw new PayException(['cus' => 0]);
}
*/
$edit = [
'pay_order_status'=>Dictionary::O_PAY_STATUS_PAYED,
'pingxx_callback_success_time'=>date('Y-m-d H:i:s'),
'pay_order_status' => Dictionary::O_PAY_STATUS_PAYED,
'pingxx_callback_success_time' => date('Y-m-d H:i:s'),
];
PayOrder::update($edit, ['pay_order_id'=>$pay_order_id]);
PayOrder::update($edit, ['pay_order_id' => $pay_order_id]);
PayOrder::commit();
}catch (Exception $e) {
} catch (Exception $e) {
PayOrder::rollback();
Logger::error($e->getMessage(), $edit);
throw $e;
}
}
/**
* @param $pay_order_id
* 处理清分
*/
private function make_order_clear() {
$this->wallet_list = [];
$data = OrderService::getOrderData($this->pay_order['order_id'], $this->pay_order['user_id']);
//平台收入、团长、商户
foreach ($data['order_item'] as $item) {
if($item['marketing_type'] == 1) {
$this->make_order_item_clear($item);
}
}
if($this->wallet_list) {
$ret = WalletService::send($this->send_wallet());
PayOrderItem::update([
'notify_account_status'=>2,
'notify_account_success_time'=>date('Y-m-d H:i:s')
], ['pay_order_id'=>$this->pay_order['order_id'], 'notify_account_status'=>1]);
}
}
/**
* @param $order_item
* 结算单个子单
*/
private function make_order_item_clear($order_item) {
if(empty($this->pay_order)) {
throw new PayException(['cus' => 0]);
}
PayOrderItem::update([
'notify_account_status'=>1,
], ['order_item_id'=>$order_item['order_item_id'], 'notify_account_status'=>0]);
$clearing_items = PayOrderClearingItem::select('*',
['order_item_id'=>$order_item['order_item_id'], 'pay_order_id'=>$this->pay_order['pay_order_id']]
);
foreach ($clearing_items as $row) {
$this->wallet_list[] = [
'account_id'=>$row['account_id'],
'pay_amount'=>$row['pay_amount'],
'pay_type'=>$row['pay_type'],
'trade_id'=>$row['pay_order_clearing_item_id'],
];
}
}
/**
* @param $order_id
* @param $user_id
* @throws PayException
* 判断是否有效订单,如果存在则调用三方判断订单状态
*/
private function exist_valid($order_id, $order) {
}
/**
* @param $data
* 构造订单流水
*/
private function make_order_clearing($data) {
$this->order_info = $data['order'];
$this->order_items = $data['order_items'];
$this->order_distribution = $data['order_distribution'];
private function make_order_clearing($data)
{
$this->order_info = $data['order_info'];
$this->order_items = $data['order_item_list'];
$this->clear_list = [];
$this->clear_items_list = [];
$this->pay_order_items = [];
$this->wallet_list = [];
foreach ($this->order_items as $r) {
$this->pay_order_items[] = [
'pay_order_item_id' => $this->gen_pay_order_item_id(),
'pay_order_id' => $this->order_info['pay_order_id'],
'order_id' => $this->order_info['order_id'],
'pay_order_id' => $this->pay_order['pay_order_id'],
'order_id' => $this->pay_order['order_id'],
'order_item_id' => $r['order_item_id'],
'user_id' => $this->order_info['user_id'],
'user_id' => $this->pay_order['user_id'],
];
}
$wx_tip = $this->make_tip_clearing(); //微信手续费
/*
$subsidy_tip = $this->make_platform_subsidy_clearing(); //系统补贴
$merchant_tip = $this->make_merchant_subsidy_clearing(); //商家补贴
*/
$distribution_tip = $this->make_distribution_clearing(); //团长收益
$platform_tip = $this->make_platform_clearing(); //平台收益
$merchant_cash = $this->order_info['payment'] + $subsidy_tip + $merchant_tip - $wx_tip - $distribution_tip - $platform_tip;
$merchant_cash = $this->order_info['payment'] - $wx_tip - $distribution_tip - $platform_tip;
$this->make_merchant_clearing($merchant_cash); //商户收益
try{
try {
PayOrderClearing::beginTransaction();
$i_cnt = PayOrderClearing::insert($this->pay_order_items, ['rowCount'=>true]);
$c_cnt = PayOrderItem::insert($this->clear_list, ['rowCount'=>true]);
$ci_cnt = PayOrderClearingItem::insert($this->clear_items_list, ['rowCount'=>true]);
$c_cnt = PayOrderItem::insert($this->pay_order_items, ['rowCount' => true]);
$i_cnt = PayOrderClearing::insert($this->clear_list, ['rowCount' => true]);
$ci_cnt = PayOrderClearingItem::insert($this->clear_items_list, ['rowCount' => true]);
if($i_cnt * $c_cnt * $ci_cnt == 0) {
throw new PayException(['cus'=>0]);
if ($i_cnt * $c_cnt * $ci_cnt == 0) {
throw new PayException(['cus' => 0]);
}
PayOrderClearing::commit();
}catch (\Exception $e) {
} catch (\Exception $e) {
Logger::error($e->getMessage(), []);
PayOrderClearing::rollback();
throw new PayException(['cut'=>5]);
throw new PayException(['cut' => 5]);
}
if ($this->wallet_list) {
$ret = WalletService::send($this->wallet_list);
PayOrderItem::update([
'notify_account_status' => 2,
'notify_account_success_time' => date('Y-m-d H:i:s')
], ['pay_order_id' => $this->pay_order['order_id'], 'notify_account_status' => 1]);
}
}
......@@ -299,15 +308,16 @@ class PayService
* @return false|float
* 获取微信手续费
*/
private function make_tip_clearing() {
private function make_tip_clearing()
{
$total_tip = round(0.006 * $this->order_info['payment']);
$account = [
'account_id'=>'100020003001',
'amount'=>$total_tip,
'title'=>'微信手续费',
'account_id' => '100020003001',
'amount' => $total_tip,
'title' => '微信手续费',
];
if(empty($total_tip)) {
if (empty($total_tip)) {
return 0;
}
......@@ -324,12 +334,13 @@ class PayService
/**
* 计算平台运营补贴
*/
private function make_platform_subsidy_clearing() {
private function make_platform_subsidy_clearing()
{
return 0; //本期不做平台补贴
$account = $this->get_marketing_subsidy();
$total_tip = $account['amount'];
if(empty($total_tip)) {
if (empty($total_tip)) {
return 0;
}
......@@ -345,11 +356,12 @@ class PayService
/**
* 计算商户运营补贴
*/
private function make_merchant_subsidy_clearing() {
private function make_merchant_subsidy_clearing()
{
return 0; // 本期不做商户补贴
$account = $this->get_marketing_subsidy();
$total_tip = $account['amount'];
if(empty($total_tip)) {
if (empty($total_tip)) {
return 0;
}
......@@ -367,16 +379,17 @@ class PayService
* @return false|float
* 计算平台收入
*/
private function make_platform_clearing() {
private function make_platform_clearing()
{
$account = [
'account_id'=>'100020003201',
'amount'=>0,
'rate'=>60,
'title'=>'平台收益',
'account_id' => '100020003201',
'amount' => 0,
'rate' => 60,
'title' => '平台收益',
];
$total_tip = $account['amount'] = round($this->order_info['total_price'] * $account['rate'] / 10000);
if(empty($total_tip)) {
if (empty($total_tip)) {
return 0;
}
......@@ -391,53 +404,65 @@ class PayService
/**
* @return mixed
* 计算分销信息
* 计算分销信息, 分销没有总帐,仅有单条四舍五入的计算
*/
private function make_distribution_clearing() {
if($this->order_info['is_distribution'] == 0) {
return 0;
}
private function make_distribution_clearing()
{
/**
'distributor_user_id'=>122234,
'distributor_commission_value'=>60,
'parent_user_id'=>122234 . rand(111, 999),
'parent_commission_value'=>60,
* 'distributor_user_id'=>122234,
* 'distributor_commission_value'=>60,
* 'parent_user_id'=>122234 . rand(111, 999),
* 'parent_commission_value'=>60,
*/
$list = [
[
'user_id'=>$this->order_distribution['distributor_user_id'],
'commission_value'=>$this->order_distribution['distributor_commission_value'],
'commission_type'=>$this->order_distribution['distributor_commission_type'],
],
[
'user_id'=>$this->order_distribution['parent_user_id'],
'commission_value'=>$this->order_distribution['parent_commission_value'],
'commission_type'=>$this->order_distribution['parent_commission_type'],
],
];
$total_tip = 0;
foreach ($this->order_items as $r) {
if($r['marketing_type'] != 1) {
continue;
}
foreach ($list as $account) {
$users[0] = [
'user_id'=>$r['distributor_user_id'],
'value'=>$r['distributor_commission_value'],
'amount'=>0
];
$users[1] = [
'user_id'=>$r['parent_user_id'],
'value'=>$r['parent_commission_value'],
'amount'=>0
];
if($r['commission_mode'] == 1) {
$users[0]['amount'] = round($users[0]['value'] * $this->order_info['total_price'] / 10000);
$users[1]['amount'] = round($users[1]['value'] * $this->order_info['total_price'] / 10000);
if($account['commission_type'] == 1) {//rate
$account['amount'] = round($account['commission_value'] * $this->order_info['total_price'] / 10000);
} else { //定值
$account['amount'] = $account['commission_value'];
} elseif($r['commission_mode'] == 2) {
$users[0]['amount'] = $users[0]['value'];
$users[1]['amount'] = $users[1]['value'];
}
$account['account_id'] = $account['account_id'];
$account['account_type'] = Dictionary::ACCOUNT_TYPE_M;
$account['pay_type'] = Dictionary::PAY_TYPE_OUT;
$account['pay_sub_type'] = Dictionary::PAY_SUB_TYPE_M_OUT;
$account['need_recorded'] = Dictionary::NO;
foreach ($users as $u) {
if (empty($r['user_id']) || $u['amount'] == 0) {
continue;
}
$this->do_clearing_data($account, $account['amount'], false);
$this->clear_items_list[] = [
'pay_order_clearing_item_id' => $this->gen_pay_order_clearing_item_id(),
'pay_order_clearing_id' => '',
'pay_order_id' => $this->pay_order['pay_order_id'],
'order_id' => $this->pay_order['order_id'],
'order_item_id' => $r['order_item_id'],
'account_id' => $u['user_id'],
'account_type' => Dictionary::ACCOUNT_TYPE_C,
'pay_amount' => $u['amount'],
'pay_type' => Dictionary::PAY_TYPE_IN,
'pay_sub_type' => Dictionary::PAY_SUB_TYPE_C_IN,
'need_recorded' => Dictionary::YES,
];
$total_tip += $account['amount'];
$total_tip += $u['amount'];
}
}
return $total_tip;
......@@ -448,27 +473,26 @@ class PayService
* @return mixed
* 计算商户清分信息
*/
private function make_merchant_clearing($merchant_cash) {
$user_id = $this->get_life_account($this->order_info['life_account_id']);
private function make_merchant_clearing($merchant_cash)
{
$ret = $this->get_life_account($this->order_info['life_account_id']);
$account = [
'account_id'=>$user_id,
'amount'=>$merchant_cash,
'title'=>'商家订单收益',
'account_id' => $ret['result']['life_account_admin_id'],
'amount' => $merchant_cash,
'title' => '商家订单收益',
];
$account['account_type'] = Dictionary::ACCOUNT_TYPE_M;
$account['pay_type'] = Dictionary::PAY_TYPE_IN;
$account['pay_sub_type'] = Dictionary::PAY_SUB_TYPE_M_IN;
$account['need_recorded'] = Dictionary::NO;
$account['need_recorded'] = Dictionary::YES;
$this->do_clearing_data($account, $merchant_cash, false);
return $merchant_cash;
}
private function do_clearing_data($account, $total_tip, $is_wx = false) {
private function do_clearing_data($account, $total_tip, $is_wx = false)
{
$total_amount = $this->order_info['payment']; //订单支付总价格
$cleared_amount = 0; //已经结算记录
$cleared_tip = 0; //已经结算记录
......@@ -477,7 +501,7 @@ class PayService
$this->clear_list[] = [
'pay_order_clearing_id' => $pay_order_clearing_id,
'pay_order_id' => $this->pay_order['pay_order_id'],
'order_id' => $this->order_info['order_id'],
'order_id' => $this->pay_order['order_id'],
'account_id' => $account['account_id'],
'account_type' => $account['account_type'],
'pay_amount' => $account['amount'],
......@@ -486,19 +510,19 @@ class PayService
'need_recorded' => $account['need_recorded'],
];
if($is_wx) { //微信不计算手续费拆弹
if ($is_wx) { //微信不计算手续费拆弹
return true;
}
foreach ($this->order_items as $r) {
$current_tip = Strategy::getTip($r['payment'], $total_amount, $cleared_amount, $total_tip, $cleared_tip);
$this->clear_items_list[] = [
'pay_order_clearing_item_id' => $this->gen_pay_order_clearing_item_id(),
'pay_order_clearing_id' => $pay_order_clearing_id,
'pay_order_id' => $this->order_info['pay_order_id'],
'order_id' => $this->order_info['order_id'],
'pay_order_id' => $this->pay_order['pay_order_id'],
'order_id' => $this->pay_order['order_id'],
'order_item_id' => $r['order_item_id'],
'account_id' => $account['account_id'],
'account_type' => $account['account_type'],
'pay_amount' => $current_tip,
......@@ -507,6 +531,17 @@ class PayService
'need_recorded' => $account['need_recorded'],
];
// 收集直接到账信息
if($r['marketing_type'] == 1 && $current_tip > 0) {
$this->wallet_list[] = [
'account_id' => $account['account_id'],
'account_type' => $account['account_type'],
'pay_amount' => $current_tip,
'pay_type' => $account['pay_type'],
'pay_sub_type' => $account['pay_sub_type'],
];
}
$cleared_amount += $r['payment'];
$cleared_tip += $current_tip;
}
......@@ -519,11 +554,12 @@ class PayService
* @return string[]
* 获取支付订单的营销补贴,返回补贴出款账号,补贴金额,补贴原因
*/
private function get_marketing_subsidy() {
private function get_marketing_subsidy()
{
return [
'account_id'=>'100020003001',
'amount'=>1000,
'title'=>'营销专号支付补贴',
'account_id' => '100020003001',
'amount' => 1000,
'title' => '营销专号支付补贴',
];
}
......@@ -532,51 +568,61 @@ class PayService
* @return string[]
* 获取订单优惠券补贴,一般来自订单,需要这里完善出款账号 + 原因
*/
private function get_coupon_subsidy($order) {
private function get_coupon_subsidy($order)
{
return [
'account_id'=>'100020002001',
'amount'=>'0',
'title'=>'营销专号支付补贴',
'account_id' => '100020002001',
'amount' => '0',
'title' => '营销专号支付补贴',
];
}
private function gen_pay_order_id($user_id) {
private function gen_pay_order_id($user_id)
{
$number = substr($user_id, -2);
return $this->get_idgen_id($number, 1);
$ids = $this->get_idgen_id($number, 1);
return array_pop($ids);
}
private function gen_pay_order_item_id($user_id) {
$number = substr($user_id, -2);
return $this->get_idgen_id($number, 1);
private function gen_pay_order_item_id()
{
$number = substr($this->order_info['user_id'], -2);
$ids = $this->get_idgen_id($number, 1);
return array_pop($ids);
}
private function gen_pay_order_clearing_id() {
private function gen_pay_order_clearing_id()
{
$number = substr($this->order_info['user_id'], -2);
return $this->get_idgen_id($number, 1);
$ids = $this->get_idgen_id($number, 1);
return array_pop($ids);
}
private function gen_pay_order_clearing_item_id() {
private function gen_pay_order_clearing_item_id()
{
$number = substr($this->order_info['user_id'], -2);
return $this->get_idgen_id($number, 1);
$ids = $this->get_idgen_id($number, 1);
return array_pop($ids);
}
private function get_idgen_id($number, $count=1){
$res = Idgen::get(appConfig('idgen.partner'),appConfig('idgen.key'), [], [[
private function get_idgen_id($number, $count = 1)
{
$res = Idgen::get(appConfig('idgen.partner'), appConfig('idgen.key'), [], [[
"type" => "55c768",
'number'=>$number,
"count"=> $count]]);
'number' => $number,
"count" => $count]]);
$id = $res['id_datetime']['55c768'] ?? [];
return $id;
}
private function get_life_account($life_account_id) {
private function get_life_account($life_account_id)
{
$url = config('interface', 'merchant.lifeaccount.get_life_account_by_id');
if (!$url) {
throw new CodeSpecialException("failed");
throw new CodeSpecialException("failed" . __METHOD__);
}
$params = ['life_account_id'=>$life_account_id];
$params = ['life_account_id' => $life_account_id];
return Sdk::call($url, $params);
}
......@@ -584,7 +630,8 @@ class PayService
* @param $data
* 构造订单支付订单信息
*/
private function make_new_pay($data) {
private function make_new_pay($data)
{
$this->make_new_pay_order($data['order']);
}
}
\ No newline at end of file
......@@ -4,13 +4,33 @@
namespace App\Services\pingxx;
use Pingpp\Order;
use Pingpp\Pingpp;
use Pingpp\OrderRefund;
use Helpers\Logger;
use Api\PhpUtils\Common\IP;
class PingxxService
{
private static $instance = null;
private function __construct()
{
Pingpp::setApiKey('sk_test_ibbTe5jLGCi5rzfH4OqPW9KC'); // 设置 API Key
Pingpp::setPrivateKeyPath(ROOT_PATH . '/conf/your_rsa_private_key.pem'); // 设置私钥
Pingpp::setAppId('app_1Gqj58ynP0mHeX1q'); // 设置 App ID
}
private function __clone() {}
public static function getInstance() {
if(empty(self::$instance)) {
self::$instance = new self;
}
return self::$instance;
}
/**
* @param $order_item_id
......@@ -18,7 +38,7 @@ class PingxxService
* @throws RefundException
* 发起退款请求
*/
public static function sendRefund($refundData, $chargeId) {
public function sendRefund($refundData, $chargeId) {
try {
Logger::info('退款订单发起', ['chargeId'=>$chargeId, 'refundData'=>$refundData]);
......@@ -36,7 +56,6 @@ class PingxxService
'goods_sku_id'=>$refundData['goods_sku_id'] ?? ''
],
'refund_mode' => 'to_source', //退款模式。原路退回:to_source,退至余额:to_balance。默认为原路返回。
'royalty_users' => $royalty_users,
]
);
......@@ -89,7 +108,7 @@ class PingxxService
* @return mixed
* 退款信息查询
*/
public static function getRefund($orderId, $refundId) {
public function getRefund($orderId, $refundId) {
try {
Logger::info('退款查询发起', ['orderId'=>$orderId, 'refundId'=>$refundId]);
$ret = OrderRefund::retrieve($orderId, $refundId);
......@@ -112,27 +131,22 @@ class PingxxService
* @return mixed
* 创建订单
*/
public static function createOrder($order) {
public function createOrder($order) {
try {
Logger::info('创建订单发起', $order);
$royalty_users = [];
$ret = Order::create(
[
"amount" => $order['pay_amount'],
"app" => APP_ID,
"app" => Pingpp::getAppId(),
"merchant_order_no" => $order['pay_order_id'],
"subject" => "用户购买",
"currency" => "cny",
"body" => "购买商品",
"uid" => $order['user_id'],
"client_ip" => "192.168.0.101",
'receipt_app' => APP_ID, // 收款方应用
'service_app' => APP_ID, // 服务方应用
'royalty_users' => $royalty_users,
//'balance_settlement' => [ // 可选参数,余额结算信息。
// 'user' => 'user_001',
// 'user_fee' => 1
//]
"client_ip" => IP::ip(),
'receipt_app' => Pingpp::getAppId(), // 收款方应用
'service_app' => Pingpp::getAppId(), // 服务方应用
]
);
......@@ -155,7 +169,7 @@ class PingxxService
* @param $orderId
* 订单查询
*/
public static function getOrder($orderId) {
public function getOrder($orderId) {
try {
Logger::info('查询订单发起', ['orderId'=>$orderId]);
......@@ -181,7 +195,7 @@ class PingxxService
* @return int
* 校验回调是否合法
*/
public static function verifySignature($raw, $headers) {
public function verifySignature($raw, $headers) {
$signature = isset($headers['X-Pingplusplus-Signature']) ? $headers['X-Pingplusplus-Signature'] : null;
......
......@@ -58,7 +58,7 @@ class RefundService
],
];
try{
$ret = PingxxService::sendRefund($refund);
$ret = PingxxService::getInstance()->sendRefund($refund);
if(!empty($ret["data"])) {
$edit = ['request_pingxx_success_time'=>date('Y-m-d H:i:s')];
} else {
......@@ -86,7 +86,7 @@ class RefundService
// 获取退款回调信息,确认订单ID
$charge = $object['charges']['data'][0];
$ping_refund = PingxxService::getRefund($charge['id'], $object['id']);
$ping_refund = PingxxService::getInstance()->getRefund($charge['id'], $object['id']);
if($ping_refund['status'] != 'succeeded') {
throw new RefundException(['cus' => 6]);
}
......
......@@ -18,6 +18,7 @@ class WalletService
*/
public static function send($params) {
return true;
$url = config('interface', 'wallet.wallet.recharge');
if (!$url) {
throw new CodeSpecialException("failed");
......
[common]
application.debug = TRUE
application.dispatcher.throwException = 0
application.dispatcher.catchException = 0
application.directory = APP_PATH
application.bootstrap = APP_PATH "/Bootstrap.php"
application.library = APP_PATH"/library"
application.library.namespace = ""
application.modules="Index,Test,Pay,Refund"
application.modules="Index,Pay"
appid = "pay"
......
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0d0QxZFYeHXGeWWneib
4Q0jUFjj4ro7bMnIJ8DjZ4w2NtLJi8p1mcFMbrIS5g95U5FUBCfAZXFb2QIaJfft
BByCQRbon7Jb97XoTP6kfk65tLz8Q9Cank1Ah/qivPIY0aNwvq8stedq9rcuJ6OQ
ncbfQ1217/Za50vKotYa+MEcFo9Y65biEmzq7BZeNYzuU4dGrPaCi917cfwNa8ey
ZSpoIOBe8e5JGOtZKCfgsgfecbXxdh6jq8Qn6mmrJILapEdxlj4xfzBzAuM3snqt
5XnDzzFWlI5Z+4lhyZr7eFVmnQSqn1HWt4VPzz/EWvxP8Rkvy89XuRXBAiO3/7Ur
8wIDAQAB
-----END PUBLIC KEY-----
\ No newline at end of file
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAx2MktxcKBEqdYRi2IgYcupPQIN5cxgiBL5udCCBJBNBbXPaq
uOE1qspfhB1KUzHXATnCONiSzubLcBTnwi2tz0ErRCeJZSERRCpbKx4eu6b1neUT
Wkga7xpZxWONEvkmZo5Nlhf4fXRPUYnO/bdGCNGpQ/HSJfWLtzmhCqO1aJwVhcDm
DMYz4bTkZavhFBdVyXf/8n7UKylk03eymlKJ1swQpeFcxaKfzsk1mJU7mc93mCWj
aR+VWkNbw4AQHDyHgbzH+zYARzCluiy5hXdixGEP+iO4ZBk48rEs1hKTvGz1k+jh
LCdkdpBRjq0pK/htjA3Ce8pF2AJs+fgN6ZUumQIDAQABAoIBAFa4MEfRpXGoYjrQ
3KZ/sg8UKvmgvQkEuetS60GViSym0pXkUuyGRyk5S8HSW3lDvBe0X10KFRAYIXNm
JEa4R1hVJ9REveVWNIRJR83BE+zZ+QnrkDc8FTrZYyIO4lTWOHVyfxxA4Lrv02/L
WFPRWoyLY+tBSf1ohpPyZLCT81rDglT1Z4svX020y8tXvnQqQiOjl4q7Zu4b26HU
TQ463ntMEhM5u7y9MFcxGRaOpF/gARlMGqDu6T8h/oYMiOSLoXOuTR7B80yaX/Mj
RZfUBoZMb5thX9qBLQ7dYnTkwaxwerYPrYvQrW9vtsswZ5NeIbEmCZyorUe8DOmQ
hT1+HmECgYEA/iQERHhZKHXnP0gvhl/uEOGOvLjD5H1D6zClzOHMmOcIF5OuEQb0
VcSMV+8emN7SCp/b/LVgKa27Mla9eXm+EXABRFcI7qGYsYXfbCD7EYX3TaJSp/30
jyLBy+MsHCTEiLeylSh7kHqgTR8tKND8UIzXo9aM7JqwFqleeXGyh7MCgYEAyNiU
EUzyBAv9sui3ZgVYRiVvTilk2HVTY6u61/mMOLsTrX3eYQaqb4GRJJShJO9mmsxX
RHBEZQJvUqqF9PapOsyv8HKuF5+UP6svHnJo7sn9gCvV/h1HTHqzFcYSvUaXnrym
D/0Tthf8CDeuGp5UFWMoFZF14HTr1oQROGAASoMCgYA0bZmzxmAeSLR8CZhEUGX8
dYvMwxEmgfERA+gwbCSZJpA0zPKL8LNXPkT1nw7g2pbaOkBX0dMUxhJoQBy2grcD
QegBATOGhy/I76U32VXyN4DdMy96GJnrLXBtb2AaLjudOMhOnRtgouuO/W+DjBmB
RIz377sC1KafBjHHO/1ooQKBgDQqfJrZv2ppquVTKH9pF/pwMq68daL7JkOXERqT
iGYbwQqozJ+q2Y3Iu2gi6o/rVl0SggAWoM0TitKP0+dCQcYx7+imAK3GFv1KexyP
Xs3WzO8Dc7ti42fr3qPjJG7g7PSfzwoME5iSNjX0MFZdlT1Q2dJwS4uXEsJO3yIj
XS/9AoGBALRApgtUA7Odw4tjCLGvxXuLFnyRkg6hFqoXAP2j8H9bJDOlSSVwQTFd
ahbcIDtQJS57vXUGK2uspbFKLm1WCFzPVyuxDIW6oue/kO+YxxU3NA58zk8oaORq
eA3YvHc7ZmRjVnVkxnXjKofrL6jF5A+lXSXnXchrv2ZYI+1pOsIV
-----END RSA PRIVATE KEY-----
\ No newline at end of file
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2MktxcKBEqdYRi2IgYc
upPQIN5cxgiBL5udCCBJBNBbXPaquOE1qspfhB1KUzHXATnCONiSzubLcBTnwi2t
z0ErRCeJZSERRCpbKx4eu6b1neUTWkga7xpZxWONEvkmZo5Nlhf4fXRPUYnO/bdG
CNGpQ/HSJfWLtzmhCqO1aJwVhcDmDMYz4bTkZavhFBdVyXf/8n7UKylk03eymlKJ
1swQpeFcxaKfzsk1mJU7mc93mCWjaR+VWkNbw4AQHDyHgbzH+zYARzCluiy5hXdi
xGEP+iO4ZBk48rEs1hKTvGz1k+jhLCdkdpBRjq0pK/htjA3Ce8pF2AJs+fgN6ZUu
mQIDAQAB
-----END PUBLIC KEY-----
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment