代币优化
This commit is contained in:
@@ -11,6 +11,7 @@ return [
|
||||
'Files' => '附件',
|
||||
'Desc' => '需求详情',
|
||||
'Contact' => '联系方式',
|
||||
'Pay_platform' => '发布终端',
|
||||
'Budget_amount' => '预算(元)',
|
||||
'Limit_time' => '工期(天)',
|
||||
'Weigh' => '排序',
|
||||
|
||||
@@ -8,6 +8,7 @@ use app\common\service\ContractService;
|
||||
use app\common\service\DemandBiddingService;
|
||||
use app\common\service\DemandService;
|
||||
use app\common\service\OrderShipService;
|
||||
use app\common\service\VirtualPayService;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\Lang;
|
||||
use think\Validate;
|
||||
@@ -273,6 +274,9 @@ class Demand extends Api
|
||||
try {
|
||||
$demandId = $this->request->param('demandId', 0);
|
||||
$info = ContractService::getWinBiddingContract($demandId);
|
||||
$demand = DemandService::getOne(['id' => $demandId]);
|
||||
$platform = $demand ? VirtualPayService::normalizePayPlatform($demand->pay_platform) : '';
|
||||
$info->pay_platform = $platform !== '' ? $platform : 'android';
|
||||
if (empty($info->data_json['customData']) && ($firstContract = ContractService::getFirstContract($demandId))) {
|
||||
$data_json = $info->data_json;
|
||||
$data_json['customData'] = $firstContract->data_json['customData'] ?? [];
|
||||
|
||||
@@ -151,6 +151,8 @@ class DemandService
|
||||
'files' => $data['files'] ?? [],
|
||||
'budget_amount' => $data['budget_amount'] ?? 0,
|
||||
'limit_time' => $data['limit_time'] ?? 0,
|
||||
// 客户发布需求时的手机系统,报价预估按这个终端。真正付款可能换设备,以支付记录为准
|
||||
'pay_platform' => VirtualPayService::normalizePayPlatform($data['pay_platform'] ?? '') ?: 'android',
|
||||
'publish_status' => CommonService::ONGOING,
|
||||
'status' => self::STATUS_NO
|
||||
];
|
||||
|
||||
@@ -481,8 +481,9 @@ class VirtualPayService
|
||||
}
|
||||
|
||||
/**
|
||||
* 代币数量,保留两位小数。1元=1代币时,0.01元对应 0.01 个代币
|
||||
* @param float|string $amountYuan
|
||||
* @return int
|
||||
* @return float
|
||||
* @throws \Exception
|
||||
*/
|
||||
private static function coinQuantity($amountYuan)
|
||||
@@ -495,11 +496,9 @@ class VirtualPayService
|
||||
if ($coinPerYuan < 1) {
|
||||
$coinPerYuan = 1;
|
||||
}
|
||||
if (($fen * $coinPerYuan) % 100 !== 0) {
|
||||
throw new \Exception('订单金额须为整数元才能按1元=1代币支付');
|
||||
}
|
||||
$quantity = bcdiv(bcmul((string)$fen, (string)$coinPerYuan, 0), '100', 2);
|
||||
|
||||
return intdiv($fen * $coinPerYuan, 100);
|
||||
return (float)$quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@ return [
|
||||
'transfer_authorization_notify_url' => Env::get('app.url') . '/api/account/transferAuthorizationNotify',
|
||||
],
|
||||
// 小程序虚拟支付(类目不支持普通微信支付时使用)
|
||||
// 代币比例须与 MP「虚拟支付-代币配置」一致:1元=1代币。buyQuantity 只能是整数,订单金额须为整数元
|
||||
// 代币比例须与 MP「虚拟支付-代币配置」一致:1元=1代币。数量保留两位小数,0.01元=0.01代币
|
||||
'virtual_pay' => [
|
||||
'offer_id' => Env::get('wechat.vp_offer_id', ''),
|
||||
'app_key' => Env::get('wechat.vp_app_key', ''), // 现网 AppKey,env=0
|
||||
|
||||
@@ -60,6 +60,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
|
||||
class: 'autocontent',
|
||||
formatter: Table.api.formatter.content
|
||||
},
|
||||
{field: 'pay_platform', title: __('Pay_platform'), searchList: {"android":"安卓","ios":"苹果"}, formatter: Table.api.formatter.normal},
|
||||
{field: 'budget_amount', title: __('Budget_amount'), operate: 'BETWEEN'},
|
||||
{field: 'limit_time', title: __('Limit_time'), operate: false},
|
||||
{field: 'weigh', title: __('Weigh'), operate: false},
|
||||
|
||||
@@ -9,8 +9,10 @@ Page({
|
||||
*/
|
||||
data: {
|
||||
demandId: 0,
|
||||
androidAccount: 0,
|
||||
iosAccount: 0,
|
||||
actualAccount: 0,
|
||||
payPlatform: 'android', // 客户发布需求时的手机系统
|
||||
platformName: '安卓',
|
||||
payFeePercent: 1,
|
||||
commissionRatio: 0.1, // 平台服务费比例,来自 common/getMiniConfig
|
||||
commissionPercent: 10,
|
||||
androidPayFeeRate: 0.01,
|
||||
@@ -73,12 +75,17 @@ Page({
|
||||
},
|
||||
|
||||
incomePreview(amount, rates) {
|
||||
const commissionRatio = rates ? rates.commissionRatio : this.data.commissionRatio;
|
||||
const androidPayFeeRate = rates ? rates.androidPayFeeRate : this.data.androidPayFeeRate;
|
||||
const iosPayFeeRate = rates ? rates.iosPayFeeRate : this.data.iosPayFeeRate;
|
||||
const commissionRatio = rates && rates.commissionRatio !== undefined ? rates.commissionRatio : this.data.commissionRatio;
|
||||
const androidPayFeeRate = rates && rates.androidPayFeeRate !== undefined ? rates.androidPayFeeRate : this.data.androidPayFeeRate;
|
||||
const iosPayFeeRate = rates && rates.iosPayFeeRate !== undefined ? rates.iosPayFeeRate : this.data.iosPayFeeRate;
|
||||
const rawPlatform = rates && rates.payPlatform !== undefined ? rates.payPlatform : this.data.payPlatform;
|
||||
const payPlatform = rawPlatform === 'ios' ? 'ios' : 'android';
|
||||
const payFeeRate = payPlatform === 'ios' ? iosPayFeeRate : androidPayFeeRate;
|
||||
return {
|
||||
androidAccount: calcActualAccount(amount, commissionRatio, androidPayFeeRate),
|
||||
iosAccount: calcActualAccount(amount, commissionRatio, iosPayFeeRate),
|
||||
actualAccount: calcActualAccount(amount, commissionRatio, payFeeRate),
|
||||
payPlatform,
|
||||
payFeePercent: toPercent(payFeeRate),
|
||||
platformName: payPlatform === 'ios' ? 'iOS' : '安卓',
|
||||
};
|
||||
},
|
||||
// 拉取平台服务费和支付费率,并重算预计到手金额
|
||||
@@ -91,7 +98,10 @@ Page({
|
||||
iosPayFeeRate: rates.iosPayFeeRate,
|
||||
androidFeePercent: toPercent(rates.androidPayFeeRate),
|
||||
iosFeePercent: toPercent(rates.iosPayFeeRate),
|
||||
...this.incomePreview(this.data.formData?.totalCost, rates),
|
||||
...this.incomePreview(this.data.formData?.totalCost, {
|
||||
...rates,
|
||||
payPlatform: this.data.payPlatform,
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
@@ -549,7 +559,7 @@ Page({
|
||||
'formData.taskContent': resData.task_content,
|
||||
'formData.needDays': resData.need_days,
|
||||
'formData.totalCost': resData.total_amount,
|
||||
...this.incomePreview(resData.total_amount),
|
||||
...this.incomePreview(resData.total_amount, { payPlatform: resData.pay_platform }),
|
||||
});
|
||||
|
||||
// 客户签约时,附件展示开发者签约时上传的附件,仅可预览,不可删除和上传
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
/>
|
||||
</view>
|
||||
|
||||
<t-input label="总费用" placeholder="请输入总费用" suffix="元" align="right" type="number" tips="{{source == 'dev' ? '预计到手 安卓' + androidAccount + '元 / iOS' + iosAccount + '元,已扣平台服务费' + commissionPercent + '%和支付费率' + androidFeePercent + '%/' + iosFeePercent + '%' : '总费用 = 首付款50% + 尾款50%'}}" disabled="{{source != 'dev'}}" value="{{formData.totalCost}}" bind:change="onTotalCostChange" />
|
||||
<t-input label="总费用" placeholder="请输入总费用" suffix="元" align="right" type="number" tips="{{source == 'dev' ? '预计到手金额 ' + actualAccount + '元,已扣平台服务费' + commissionPercent + '%和' + platformName + '支付费率' + payFeePercent + '%' : '总费用 = 首付款50% + 尾款50%'}}" disabled="{{source != 'dev'}}" value="{{formData.totalCost}}" bind:change="onTotalCostChange" />
|
||||
<t-input label="开发工期" placeholder="请输入开发工期" suffix="天" align="right" type="number" disabled="{{source != 'dev'}}" value="{{formData.needDays}}" bind:change="onDevelopmentPeriodChange" />
|
||||
</view>
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ Page({
|
||||
quotedPrice: '',
|
||||
needDays: '',
|
||||
remark: '',
|
||||
androidAccount: 0,
|
||||
iosAccount: 0,
|
||||
actualAccount: 0,
|
||||
payPlatform: 'android', // 客户发布需求时的手机系统
|
||||
platformName: '安卓',
|
||||
payFeePercent: 1,
|
||||
commissionRatio: 0.1, // 平台服务费比例,来自 common/getMiniConfig
|
||||
commissionPercent: 10,
|
||||
androidPayFeeRate: 0.01,
|
||||
@@ -41,7 +43,7 @@ Page({
|
||||
const demandInfo = res.data;
|
||||
this.setData({
|
||||
demandInfo,
|
||||
...this.incomePreview(this.getQuoteAmount(demandInfo))
|
||||
...this.incomePreview(this.getQuoteAmount(demandInfo), { payPlatform: demandInfo.pay_platform })
|
||||
}, () => resolve()); // setData 回调:页面已重新渲染
|
||||
},
|
||||
() => {
|
||||
@@ -55,14 +57,19 @@ Page({
|
||||
getQuoteAmount(demandInfo) {
|
||||
return demandInfo?.myBidding?.quoted_price || demandInfo?.demand_contracts?.total_amount || this.data.quotedPrice || 0;
|
||||
},
|
||||
// 按当前报价计算安卓、iOS 两种预计到手
|
||||
// 按客户发布需求时的手机系统计算预计到手
|
||||
incomePreview(amount, rates) {
|
||||
const commissionRatio = rates ? rates.commissionRatio : this.data.commissionRatio;
|
||||
const androidPayFeeRate = rates ? rates.androidPayFeeRate : this.data.androidPayFeeRate;
|
||||
const iosPayFeeRate = rates ? rates.iosPayFeeRate : this.data.iosPayFeeRate;
|
||||
const commissionRatio = rates && rates.commissionRatio !== undefined ? rates.commissionRatio : this.data.commissionRatio;
|
||||
const androidPayFeeRate = rates && rates.androidPayFeeRate !== undefined ? rates.androidPayFeeRate : this.data.androidPayFeeRate;
|
||||
const iosPayFeeRate = rates && rates.iosPayFeeRate !== undefined ? rates.iosPayFeeRate : this.data.iosPayFeeRate;
|
||||
const rawPlatform = rates && rates.payPlatform !== undefined ? rates.payPlatform : this.data.payPlatform;
|
||||
const payPlatform = rawPlatform === 'ios' ? 'ios' : 'android';
|
||||
const payFeeRate = payPlatform === 'ios' ? iosPayFeeRate : androidPayFeeRate;
|
||||
return {
|
||||
androidAccount: calcActualAccount(amount, commissionRatio, androidPayFeeRate),
|
||||
iosAccount: calcActualAccount(amount, commissionRatio, iosPayFeeRate),
|
||||
actualAccount: calcActualAccount(amount, commissionRatio, payFeeRate),
|
||||
payPlatform,
|
||||
payFeePercent: toPercent(payFeeRate),
|
||||
platformName: payPlatform === 'ios' ? 'iOS' : '安卓',
|
||||
};
|
||||
},
|
||||
// 拉取平台服务费和支付费率,并重算预计到手金额
|
||||
@@ -75,7 +82,10 @@ Page({
|
||||
iosPayFeeRate: rates.iosPayFeeRate,
|
||||
androidFeePercent: toPercent(rates.androidPayFeeRate),
|
||||
iosFeePercent: toPercent(rates.iosPayFeeRate),
|
||||
...this.incomePreview(this.getQuoteAmount(this.data.demandInfo), rates),
|
||||
...this.incomePreview(this.getQuoteAmount(this.data.demandInfo), {
|
||||
...rates,
|
||||
payPlatform: (this.data.demandInfo && this.data.demandInfo.pay_platform) || this.data.payPlatform,
|
||||
}),
|
||||
});
|
||||
},
|
||||
// 取文件扩展名对应的 openDocument 类型(默认 pdf)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</t-collapse-panel>
|
||||
<t-collapse-panel header="{{opType=='quote' ? '我的报价' : '开发人员报价'}}" value="{{3}}" expandIcon>
|
||||
<view>
|
||||
<t-input style="--td-input-border-color: rgb(238, 116, 2);" placeholder="填写报价金额" suffix="元" align="right" type="number" value="{{opType=='quote' ? demandInfo.myBidding.quoted_price || demandInfo.demand_contracts.total_amount ||quotedPrice : demandInfo.winBidding.quoted_price}}" disabled="{{opType=='quote' && (!demandInfo.myBidding && !demandInfo.demand_contracts) ? false : true}}" tips="{{opType=='quote' && androidAccount > 0 ? '预计到手 安卓' + androidAccount + '元 / iOS' + iosAccount + '元,已扣平台服务费' + commissionPercent + '%和支付费率' + androidFeePercent + '%/' + iosFeePercent + '%' : ''}}" data-field="quotedPrice" bindchange="onInputChange">
|
||||
<t-input style="--td-input-border-color: rgb(238, 116, 2);" placeholder="填写报价金额" suffix="元" align="right" type="number" value="{{opType=='quote' ? demandInfo.myBidding.quoted_price || demandInfo.demand_contracts.total_amount ||quotedPrice : demandInfo.winBidding.quoted_price}}" disabled="{{opType=='quote' && (!demandInfo.myBidding && !demandInfo.demand_contracts) ? false : true}}" tips="{{opType=='quote' && actualAccount > 0 ? '预计到手金额 ' + actualAccount + '元,已扣平台服务费' + commissionPercent + '%和' + platformName + '支付费率' + payFeePercent + '%' : ''}}" data-field="quotedPrice" bindchange="onInputChange">
|
||||
<view slot="label" class="custom-label">报价</view>
|
||||
</t-input>
|
||||
<t-input placeholder="填写预计工期" suffix="天" align="right" disabled="{{opType=='quote' && (!demandInfo.myBidding && !demandInfo.demand_contracts) ? false : true}}" type="number" value="{{opType=='quote' ? demandInfo.myBidding.need_days || demandInfo.demand_contracts.need_days || needDays : demandInfo.winBidding.need_days}}" data-field="needDays" bindchange="onInputChange">
|
||||
|
||||
@@ -4,6 +4,17 @@ import { fetchConfig } from '../../../services/home/home';
|
||||
// 联系方式:仅允许英文、数字、下划线、中划线(不含中文与特殊字符)
|
||||
const CONTACT_REG = /^[A-Za-z0-9_-]+$/;
|
||||
|
||||
// 客户发布需求时的手机系统。iOS 单独记,其余按安卓
|
||||
function currentPayPlatform() {
|
||||
let platform = '';
|
||||
try {
|
||||
platform = String((wx.getSystemInfoSync() || {}).platform || '').toLowerCase();
|
||||
} catch (err) {
|
||||
platform = '';
|
||||
}
|
||||
return platform === 'ios' ? 'ios' : 'android';
|
||||
}
|
||||
|
||||
Page({
|
||||
|
||||
/**
|
||||
@@ -170,6 +181,7 @@ Page({
|
||||
budget_amount: budgetAmount,
|
||||
limit_time: limitTime,
|
||||
contact: contact,
|
||||
pay_platform: currentPayPlatform(),
|
||||
}, 'POST').then(res => {
|
||||
if (res.code === 1) {
|
||||
wx.requestSubscribeMessage({
|
||||
|
||||
Reference in New Issue
Block a user