general_pay_trans_flowchart
2016-03-20 22:34:34 0 举报
general_pay_trans_flowchart是一个流程图,用于描述一般支付交易的处理过程。该流程图通常包括以下步骤:首先,用户发起支付请求,例如通过在线购物或银行转账。然后,支付系统接收到请求并验证用户的账户信息和支付金额。接下来,支付系统会与相关银行的支付网关进行通信,以完成交易的授权和结算。一旦交易成功,支付系统会更新用户的账户余额,并向用户发送支付成功的确认信息。最后,商家收到支付通知,并根据需要提供相应的商品或服务。整个流程旨在确保支付的安全性和准确性,同时为用户提供便捷的支付体验。
作者其他创作
大纲/内容
N
如果client_source不是手机端
fee_type fee_settlement_type has_pay_mode 必须同时存在或者同时不存在
遍历传入的up_merchants对于每一个item,遍历solution去寻找,找不到报错找到了,如果是up2即最上层商户,从对应的solution item记录最上级商户fee_plus_amount钱包收取手续费即最上级商户的fee_amount找到了,如果是up1中间级商户,从对应的solution item记录中间商户的fee_amout将每个uid放入merchant_user
先将有钱自己记账到买家才能进行下面的记账
交易的结算要在手续费结算之前否则可能商户账号上没钱扣手续费(info.settlement_type info.fee_settlement_type)
根据入参info.trans_id从数据库加载交易单t_trans放入info
交易单是否关联收款单?即是否传入收款单号
Y
if (info.PAYMENT_MODE_DIRECT != info.payment_mode)
如果传入,用传入值改变库中值:channel_idsettlement_typefee_amountfee_account.user_id
能出现实时结算但是后收的情况 这种情况在业务上不合理也不存在需要控制一下
if (!is_reentry)if (info.TRANS_STATE_CREATED != info.state)如果不是ral重试,则校验交易单状态如果不是created,则抛异常退出
支付之前的校验 也包括是否是可重入的判断bool is_reentry = false;
if (is_reentry) {如果是ral重试
如果有2级商户,则最上级商户fee_plus_amount等于中间商户的fee_amout如果只有1级商户,则最上级商户fee_plus_amount应该为0
更新trans_query要根据trans_mode区分
是否有营销支付方案has_mkt_solution
if (input_buyer_fee_amount 0)
如果是异步分钱,则资金流向卖家4账号上面通过介绍方式决定了流向1或3账号if (trans_info::SHARE_PROFIT_TYPE_DELAY == info.share_profit_type()) {info.seller.sub_account_type = info.seller.SUB_ACCOUNT_TYPE_SHARE;
internal_check_trans_freeze_stateif (info.TRANS_STATE_FREEZED_MASK & info.state) 交易已冻结就直接报错了
对于委托分账,create_trans的时候创建的分账信息需要在pay_trans的时候更新,更新之后再分账这里,share_profit_solution是create时的分账方案,billing_solution_info是pay接口新传进来的share_profit_solution = billing_solution_info;
如果买家付款金额为0,则不验证支付密码,否则需要验证支付密码根据client_source验证密码
share_profit_check
交易是否已经支付? if (is_trans_payed(info))
填充返回信息,打印notice日志pay_trans_output_info trans_ub_log_pushnotice(info);
recv._recvable_id_initialized 如果提供了收款单,就要检查收款单是否已支付并且包含这个交易的信息并且对金额也要做检查,支付成功之后需要修改相应已支付金额,所以需要锁表
if (info.PAYMENT_MODE_DIRECT == info.payment_mode) {直付交易必须在付款之后才能进行分润if (info.TRANS_STATE_PAID != info.state) {
如果强制分润,但是交易不是直付交易或者不含分润方案则报错if (trans_info::NEED_SHARE_PROFIT_MUST == need_share_profit)
info.state = info.TRANS_STATE_PAID;
库中payment_mode必须与模板中payment_mode一致
校验交易单各个属性,是否支持分钱valid_trans_state_for_share_profit
有钱逻辑一坨
遍历solution_user都要在merchant_user里面
读取入参info.trans_idrecv_recvable_idcash_amountneed_share_profitinfo.client_source_flaginfo.mkt_solution_idac_solutioninfo.is_profit_flaginfo.is_recv_confirm_flaginfo.is_refund_fee_amount_flaginfo.fee_amount_payer_flaginput_channel_idinput_fee_amountinput_fee_user_idinput_settlement_typeinput_buyer_fee_amountinput_buyer_fee_user_idbilling_solution_infocredit_recv._credit_recv_id设置_recvable_id_initializedhas_buyer_fee_amounthas_billing_solution_info_credit_recv_id_initializedhas_input_channel_idhas_input_fee_amounthas_mkt_solution_idhas_mkt_solutionread_client_source_flag_okhas_special_code
商户分账金额不能大于商户所得金额
如果传入了分账方案has_billing_solution_info
pay_trans_output_info如果是ral重入那么给前端返回相应的信息
有营销方案且交易单为初始状态has_mkt_solution && info.TRANS_STATE_CREATED == info.state
if (will_share_profit) {要做真正支付动作了,判断是否当即分润,则开始做分润动作这里的will_share_profit标识:1)传入must或者传入auto且多出且为支付2)且分钱类型为realtime
收款单可用金额是否满足本次支付如果是完全充值支付,则要求收款单可用金额一定要大于等于本次支付金额如果是部分充值支付时,会使用余额+充值金额,不好检测,目前请求充值时限定纯网关交易不能使用部分充值支付if (recv_info.RECVABLE_TYPE_FULL_DEPOSIT_PAY == recv_info.recv_type) {if (recv_info.available_amount (info.cash_amount + info.buyer_fee_amount)) {
merchant_user和solution_user的size必须相等且都不大于2
目前只有实时结算才支持分润if (info.SETTLEMENT_TYPE_REALTIME != info.settlement_type)
是否当即分钱will_share_profit
决定要不要立即当场分润、分账条件:传入must,或者传入auto且创建了多出方案且是支付交易will_share_profit = (trans_info::NEED_SHARE_PROFIT_MUST == need_share_profit) ||((info.PARALLEL_TYPE_MULTIPLE_OUT_MASK & info.parallel_type) &&(trans_info::NEED_SHARE_PROFIT_AUTO == need_share_profit)&& (info.PAYMENT_MODE_DIRECT == info.payment_mode));
if (!is_trans_payed(info)) {交易单还没支付
has_special_code是否传入超级密码?
share_profit记账 share_profit_trans_do_accounting
从入参读取组合支付方式pay_mode_var设置has_pay_mode
是否需要执行分润操作pay接口明确传入must,或者传入auto并有多出方案,则要执行分润 bool will_share_profit = (trans_info::NEED_SHARE_PROFIT_MUST == need_share_profit) ||((info.PARALLEL_TYPE_MULTIPLE_OUT_MASK & info.parallel_type) && (trans_info::NEED_SHARE_PROFIT_AUTO == need_share_profit));
0 != info.fee_amount
if (!will_share_profit || trans_info::SHARE_PROFIT_TYPE_REALTIME != info.share_profit_type())如果传入了分账信息,则比如must分钱且必须实时
if (has_billing_solution_info)如果本次传入了分账方案
((info.PAYMENT_MODE_RESERVABLE == info.payment_mode)&& (info.PARALLEL_TYPE_MULTIPLE_IN_MASK & info.parallel_type)) {预付交易不支持多进并行支付类型
判断关闭余额限制相关逻辑涉及到load buyer的account表
分润总金额不能大于分润前支付给卖家的金额if (share_profit_solution().get_total_amount() (info.get_total_cash_amount() - info.fee_amount))
手续费不能大于交易总现金金额收益账户不能跟卖家相同收益账户必须是C账户,这是财务要求的收益账户必须存在设置info.fee_account.sub_account_type
在pay_trans接口区分是否含有pay_mode信息info.pay_mode_flag = trans_info::PAY_MODE_FLAG_INCLUDE;
校验超级密码
如果交易单的状态恰好为paid且redis中有redis_key重入键值
if ((recv_info.RECVABLE_TYPE_FULL_DEPOSIT_PAY != recv_info.recv_type)&& (recv_info.RECVABLE_TYPE_PARTIAL_DEPOSIT_PAY != recv_info.recv_type)) {收款单类型必须不能是纯充值
if (cash_amount != info.cash_amount)
has_buyer_fee_amount如果传入了买家手续费
只需要关心传入的recv_id和交易里存的是否一致if (!info.pay_recvable_id.initialized()) { if (info.pay_recvable_id != recv_info.recvable_id)
info.buyer_fee_account.user_id = input_buyer_fee_user_id;info.buyer_fee_account.sub_account_type = info.buyer_fee_account.SUB_ACCOUNT_TYPE_DEFAULT;info.buyer_fee_account.currency = info.buyer.currency;收益账户不能跟卖家相同收益账户不能跟买家相同收益账户必须是C账户收益账户必须存在
check_trans_solution_account
当前用户必须是买家,因为这是从买家账户里出钱if (info.buyer.user_id != current.user_id)
is_reentry = false;
分润方案中不能有重复的商户号(统一放在这个函数中判断)check_duplicate_share_profit_account(share_profit_solution().get_solution_items());
inner_check_trans_solution_account遍历solution里面所有solution_item,取出user_id案中的账户不能是卖家或者买家案中的账户必须存在且状态正常方案中的账户必须存在
if (is_deposit_pay) {如果交易单关联收款单,即充值支付
将merchant_trans里存的share-profit_type赋予trans,如果没存,默认使用realtime,实时分钱info.share_profit_type = trans_info::SHARE_PROFIT_TYPE_REALTIME;if (trans_info::SHARE_PROFIT_TYPE_NONE != merchant_trans.share_profit_type()) {info.share_profit_type = merchant_trans.share_profit_type;
校验payment_mode 现在只支持中介、直付、预付交易
只做支付的记账do_pay_accounting_and_insert_log
更新t_trans更新状态、pay_type、结算信息、卖方买方手续费、收款单id、营销相关金额、confirm/end/share_profit的时间
pay_and_share_profit_trans
交易入参与库中交易单数据一致优惠信息必须与交易一致优惠支付方案必须与交易一致优惠方案钱数与优惠券钱数必须一致
internal_check_trans_freeze_state(info);校验交易单是否冻结?
if (!(info.PARALLEL_TYPE_MULTIPLE_OUT_MASK & info.parallel_type)) 一定要存在分润方案
credit_recv._credit_recv_id_initialized
if (recv._recvable_id_initialized)如果交易关联收款单
bool is_deposit_pay = recv_info.recvable_id.initialized();bool is_credit_deposit_pay = info.pay_credit_recv_id.initialized(); trans_info::pay_type_t pay_type(is_deposit_pay | is_credit_deposit_pay ? trans_info::TRANS_PAY_TYPE_DEPOSIT_PAY : trans_info::TRANS_PAY_TYPE_BALANCE_PAY);
做支付和分钱的记账do_pay_and_share_profile_accounting_and_insert_log
如果要分润/分账if (will_share_profit)
分润标记必须为未分润if (info.SHARE_PROFIT_FLAG_UNDO != info.share_profit_flag)
检验完支付信息,校验是否是可重入如果出现交易单状态是已支付状态,那么可能出现重入,如果在redis中找到这个主键说明是重入,如果不是那么就是调用错误,错误码在前面抛出,不影响之前的逻辑is_reentry = true;
更新有钱收款单信息
声明本地变量trans_info infotrans_info merchant_transtrans_solution_t pay_trans_solutiontrans_solution_t share_profit_solutiontrans_solution_t billing_solution_inforecvable_info recvCreditRecvableInfo credit_recvmkt_solution_t ac_solutionup_merchant_info merchant_info
开启事务
如果需要立即当场分润,根据分润方式,确定资金流注意,分润方式的来源要么是默认实时要么是从merchant_trans中加载的,即创建时存入的if (will_share_profit) {
has_billing_solution_info如果传入了分账方案
if (!(info.PARALLEL_TYPE_MULTIPLE_OUT_MASK & info.parallel_type))
pay记账 pay_trans_do_accounting
info.buyer_fee_flag = trans_info::BUYER_FEE_FLAG_INCLUDE;info.buyer_fee_amount = input_buyer_fee_amount;
pay_trans接口中这些信息只是为了向支付方式结算信息表中插入记录 并不用于记账info.mkt_solution_flag = trans_info::MKT_SOLUTION_FLAG_INCLUDE;info.mkt_solution_amount = ac_solution().get_total_amount();info._mkt_total_no_settlement_amount = ac_solution().get_total_no_settlement_amount();
if ((recv.RECVABLE_TYPE_FULL_DEPOSIT_PAY != recv.recv_type) && (recv.RECVABLE_TYPE_PARTIAL_DEPOSIT_PAY != recv.recv_type))
recv.RECVABLE_STATE_PAID != recv.state
!recv.account.same_account(info.buyer)收款单账户必须与买家相同
if (has_billing_solution_info)如果传入了分账信息
check_merchants_in_entrust_solution
如果不是实时分钱,则设置标识if (trans_info::SHARE_PROFIT_TYPE_REALTIME != info.share_profit_type()) {will_share_profit = false;
从入参获取fee_settlement_type手续费结算类型,异步还是实时如果没传,默认使用交易的结算类型设置has_fee_settlement_type
获取service_code有没有收款单,计算入参不一样
如果有支付方案,则加载支付方案has_pay_trans_solution = info.PARALLEL_TYPE_MULTIPLE_IN_MASK & info.parallel_type;
如果有2级商户,则钱包收取的手续费=最上级商户的fee_amount如果只有1级商户,则钱包收取的手续费=中间商户的fee_amout
如果传入了支付信息has_pay_mode
从入参获取fee_type收取手续费类型1坐扣2后收不传默认坐扣设置has_fee_type
根据settlement_type决定info.seller.sub_account_type实时用1,异步用3
if ((info.PAYMENT_MODE_MEDIATE == info.payment_mode)|| (info.PAYMENT_MODE_RESERVABLE == info.payment_mode)) {中介或预付交易必须在确认收货之后才能进行分润if (info.TRANS_STATE_CONFIRMED != info.state) {
0 条评论
下一页