rabin 11 months ago
parent
commit
7044ac25ea

+ 37 - 4
database/account.php

@@ -130,7 +130,7 @@ return array
 			'desc' 		=> 'appid',
 			'match' 	=> 'is_string',
 			'update'	=> 'text',
-			'show'	=> 'type=wechat,cmbc,alipay,yspay',
+			'show'	=> 'type=wechat,cmbc,alipay,yspay,yspaym',
 		),
 
 		'appsecret'		=> array
@@ -141,7 +141,7 @@ return array
 			'desc' 		=> 'appsecret',
 			'match' 	=> 'is_string',
 			'update'	=> 'text',
-			'show'	=> 'type=wechat,cmbc,yspay',
+			'show'	=> 'type=wechat,cmbc,yspay,yspaym',
 		),
 
 		'account'		=> array
@@ -227,7 +227,7 @@ return array
 		'file_cert'		=> array
 		(
 			'type' 		=> 'varchar-150',
-			'name' 		=> '证书cert文件-微信支付需要退款时使用',
+			'name' 		=> '证书cert文件',
 			'default' 	=> '',
 			'desc' 		=> '证书cert文件',
 			'match' 	=> 'option',
@@ -239,7 +239,7 @@ return array
 		'file_key'		=> array
 		(
 			'type' 		=> 'varchar-150',
-			'name' 		=> '证书key文件-微信支付需要退款时使用',
+			'name' 		=> '证书key文件',
 			'default' 	=> '',
 			'desc' 		=> '证书key文件',
 			'match' 	=> 'option',
@@ -258,6 +258,33 @@ return array
 			'update'	=> 'text',
 		),
 
+		'pay/yspay' => array
+		(
+			'name' 		=> '银商扩展设置',
+			'default' 	=> '',
+			'desc' 		=> '银商扩展设置',
+			'match' 	=> 'option',
+			# 同步更新另外一个表的内容,另外一个表的字段=>本表的字段
+			'sync'		=> array('account_id' => 'id'),
+			'update'	=> array(1),
+			'option'	=> array('默认配置'),
+			# 1纵向展示 2横向展示
+			'update_type' => 1,
+			'show'		=> 'type=yspay',
+		),
+
+		'pay/yspay_project'      => array
+        (
+            'name'      => '关联项目',
+            'default'   => '',
+            'desc'      => '关联项目',
+            'match'     => 'option',
+            'sync'      => array('account_id' => 'id'),
+            'update_type' => 2,
+            'update'    => array(1),
+            'show'		=> 'type=yspay',
+        ),
+
 		'state'		=> array
 		(
 			'type' 		=> 'tinyint-1',
@@ -287,6 +314,12 @@ return array
         (
             '渠道管理' => array('list', 'channel&project=pay&oper_parent=account&oper_project=pay'),
         ),
+        'list_button' => array
+        (
+        	'list' => array('商户列表', '"yspay_merchant&search_option_account_id={id}&oper_table=account"', '"{type}" == "yspay"'),
+
+			//'list1' => array('资管', '"yspay_sign&search_option_account_id={id}&oper_table=account"', '"{type}" == "yspay"'),
+        ),
 	),
 
 	# 默认值

+ 188 - 0
database/yspay.php

@@ -0,0 +1,188 @@
+<?php
+
+$type = array
+(
+	1 => '无资金管理功能',
+	2 => '有资金管理功能',
+);
+
+return array
+(
+	# 表名
+	'name' => 'yspay',
+	# 显示给用户看的名称
+	'lang' => '银商扩展配置',
+	'order' => 10,
+	'menu' => false,
+	# 数据结构
+	'struct' => array
+	(
+	
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'account_id'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '所属账户',
+			'default' 	=> '1',
+			'desc' 		=> '所属账户',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'hidden',
+		),
+
+		'type'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '资金管理类型',
+			'default' 	=> '1',
+			'desc' 		=> '支付类型',
+			'match' 	=> 'is_string',
+			'update'	=> 'radio',
+			'option'	=> $type,
+			'control'	=> 'type',
+		),
+
+		'per'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '平台分账百分比-如输入10,就是从总支付金额中分账10%',
+			'default' 	=> '10',
+			'desc' 		=> '平台分账百分比',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'text',
+			'show'		=> 'type=2',
+		),
+
+		'mid'		=> array
+		(
+			'type' 		=> 'varchar-200',
+			'name' 		=> '平台分账商户号',
+			'default' 	=> '',
+			'desc' 		=> '平台分账商户号',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'show'		=> 'type=2',
+		),
+
+		'card'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '平台分账卡号',
+			'default' 	=> '',
+			'desc' 		=> '平台分账卡号',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'show'		=> 'type=2',
+		),
+
+		'private_file'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '资金管理私钥文件',
+			'default' 	=> '',
+			'desc' 		=> '资金管理私钥文件',
+			'match' 	=> 'is_string',
+			'update'	=> 'upload',
+			'key'		=> '4',
+			'show'		=> 'type=2',
+		),
+
+		'private_file_password'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '资金管理私钥文件密码',
+			'default' 	=> '',
+			'desc' 		=> '资金管理私钥文件密码',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'show'		=> 'type=2',
+		),
+
+		'public_file'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '资金管理公钥文件',
+			'default' 	=> '',
+			'desc' 		=> '资金管理公钥文件',
+			'match' 	=> 'is_string',
+			'update'	=> 'upload',
+			'key'		=> '4',
+			'show'		=> 'type=2',
+		),
+
+		'sys_id'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '提现系统编号',
+			'default' 	=> '',
+			'desc' 		=> '提现系统编号',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+		),
+
+		'private_key'		=> array
+		(
+			'type' 		=> 'varchar-2000',
+			'name' 		=> '提现私钥',
+			'default' 	=> '',
+			'desc' 		=> '提现私钥',
+			'match' 	=> 'is_string',
+			'update'	=> 'textarea',
+		),
+
+		'private_key_pkcs1'		=> array
+		(
+			'type' 		=> 'varchar-2000',
+			'name' 		=> '提现PKCS1私钥',
+			'default' 	=> '',
+			'desc' 		=> '提现PKCS1私钥',
+			'match' 	=> 'is_string',
+			'update'	=> 'textarea',
+		),
+
+		'public_key'		=> array
+		(
+			'type' 		=> 'varchar-2000',
+			'name' 		=> '提现公钥',
+			'default' 	=> '',
+			'desc' 		=> '提现公钥',
+			'match' 	=> 'is_string',
+			'update'	=> 'textarea',
+		),
+
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '申请时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+			'search'	=> 'date',
+			'list'		=> 'date("Y-m-d H:i:s", {cdate})',
+		),
+	),
+
+	'manage' => array
+	(
+		
+	),
+);

+ 168 - 0
database/yspay_cash.php

@@ -0,0 +1,168 @@
+<?php
+
+$status = array
+(
+	1 => '未确认',
+    2 => '待入账',
+	3 => '已入账',
+	4 => '不入账',
+);
+
+return array
+(
+    # 表名
+    'name' => 'yspay_cash',
+    # 显示给用户看的名称
+    'lang' => '银联资金记录表',
+    'menu' => false,
+    # 数据结构
+    'struct' => array
+    (
+    
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            'update'    => 'hidden',
+            //'list'        => true,
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'order_num'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '流水号',
+            'default'   => '',
+            'desc'      => '流水号',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'list'		=> true,
+        ),
+
+        'source_order_num'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '关联订单号',
+            'default'   => '',
+            'desc'      => '关联订单号',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'list'		=> true,
+        ),
+
+        'cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '总金额',
+            'default'   => '0',
+            'desc'      => '总金额',
+            'match'     => 'option',
+            'list'      => 'round({cash}/100, 2)',
+        ),
+
+        'hf_cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户划付金额',
+            'default'   => '0',
+            'desc'      => '划付金额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            'list'		=> 'round({hf_cash}/100, 2)',
+        ),
+
+        'fz_cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '平台分账金额',
+            'default'   => '0',
+            'desc'      => '分账金额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            'list'		=> 'round({fz_cash}/100, 2)',
+        ),
+
+        'rdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '入账时间',
+            'default'   => '',
+            'match'     => 'is_numeric',
+            'desc'      => '',
+            'search'    => 'date',
+            'list'      => '"{rdate}" ? date("Y-m-d H:i", \'{rdate}\') : "-"',
+            'list_order' => 100,
+        ),
+
+        'status'        => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '状态',
+            'match'     => 'is_numeric',
+            'option'    => $status,
+            'search'    => 'select',
+            'list'      => true,
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '创建时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            //'insert'    => true,
+            //'search'    => 'date',
+            'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+
+    'manage' => array
+    (
+        'edit' => false,
+        'insert' => false,
+        'delete' => false,
+    ),
+
+    'request' => array
+    (
+        'getTotal' => array
+        (
+            'option' => array
+            (
+                'merchant_id' => 'yes',
+                'status' => 'yes',
+                'state' => 1,
+            ),
+            'type' => 'one',
+            'col' => 'sum(cash) as cash,sum(tx_cash) as tx_cash,sum(fz_cash) as fz_cash',
+        ),
+    ),
+);

+ 199 - 0
database/yspay_cash_log.php

@@ -0,0 +1,199 @@
+<?php
+$status = array
+(
+    1 => array('name' => '申请中', 'style' => 'font-weight:bold;color:blue'),
+    2 => array('name' => '受理成功', 'style' => 'font-weight:bold;color:green'),
+    3 => array('name' => '受理失败', 'style' => 'font-weight:bold;color:#CD3700'),
+);
+
+$type = array
+(
+	1 => '划付',
+	2 => '分账',
+);
+
+$auto = array
+(
+	1 => '自动',
+	2 => '手动',
+);
+return array
+(
+    # 表名
+    'name' => 'yspay_cash_log',
+    # 显示给用户看的名称
+    'lang' => '银联资金日志列表',
+    'order' => -200,
+    'menu' => false,
+    # 数据结构
+    'struct' => array
+    (
+    
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            'update'    => 'hidden',
+            //'list'        => true,
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'mid'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '分账商户号',
+            'default'   => '',
+            'desc'      => '分账商户号',
+            'match'     => 'option',
+            'update'    => 'text',
+            'searchs'    => 'fulltext',
+            'list'		=> true,
+        ),
+
+        'order_num'      => array
+        (
+            'type'      => 'varchar-100',
+            'name'      => '订单号',
+            'default'   => '',
+            'desc'      => '订单号',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'list'		=> true,
+        ),
+
+        'type'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '类型',
+            'default'   => '',
+            'desc'      => '类型',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+            'option'    => $type,
+        ),
+
+        'cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现金额',
+            'default'   => '0',
+            'desc'      => '提现金额',
+            'match'     => 'option',
+            'update'    => 'text',
+            'list'      => 'round({cash}/100, 2)',
+        ),
+
+        'tdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现时间',
+            'default'   => '',
+            'match'     => 'is_numeric',
+            'desc'      => '',
+            'search'    => 'date',
+            'list'      => '"{tdate}" ? date("Y-m-d H:i", \'{tdate}\') : "-"',
+            'order'		=> 'desc',
+        ),
+
+        'auto'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '是否自动提现',
+            'default'   => '1',
+            'desc'      => '是否自动提现',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+        ),
+
+        'status'        => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '提现状态',
+            'default'   => '1',
+            'desc'      => '提现状态',
+            'match'     => 'is_numeric',
+            'option'    => $status,
+            'search'    => 'select',
+            'list'      => true,
+        ),
+
+        'error'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '提现错误信息',
+            'default'   => '',
+            'desc'      => '提现错误信息',
+            'match'     => 'is_string',
+            'update'    => 'text',
+        ),
+
+        'desc'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '备注',
+            'default'   => '-',
+            'desc'      => '备注',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+            'list'      => true,
+        ),
+
+        'response'        => array
+        (
+            'type'      => 'text-255',
+            'name'      => '回调响应数据',
+            'default'   => '',
+            'desc'      => '回调响应数据',
+            'match'     => 'is_string',
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '创建时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            //'insert'    => true,
+            //'search'    => 'date',
+            //'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+
+    'manage' => array
+    (
+        'edit' => false,
+        'insert' => false,
+        'delete' => false,
+    ),
+
+    'request' => array
+    (
+        
+    ),
+);

+ 264 - 0
database/yspay_merchant.php

@@ -0,0 +1,264 @@
+<?php
+$status = array
+(
+    1 => '已签约',
+    2 => '未签约',
+);
+$project = function()
+{
+	return Dever::db('pay/yspay_project')->state();
+};
+
+return array
+(
+    # 表名
+    'name' => 'yspay_merchant',
+    # 显示给用户看的名称
+    'lang' => '银联商户列表',
+    # 后台菜单排序
+    'order' => -100,
+    'check' => 'mid',
+    'menu' => false,
+    # 数据结构
+    'struct' => array
+    (
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            //'list'      => true,
+            'order'     => 'desc',
+        ),
+
+        'account_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '账户id',
+            'default'   => '',
+            'desc'      => '账户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_account_id'),
+        ),
+
+        'name'      => array
+        (
+            'type'      => 'varchar-300',
+            'name'      => '商户名称',
+            'default'   => '',
+            'desc'      => '商户名称',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'project_id'       => array
+        (
+            'type'      => 'varchar-500',
+            'name'      => '所属项目',
+            'default'   => '',
+            'desc'      => '所属项目',
+            'match'     => 'option',
+            'search'    => 'select',
+            'update'    => 'radio',
+            'control_url'	=> 'pay/yspay/merchant.selectRelate',
+            'option'    => $project,
+            'list'      => true,
+        ),
+
+        'relate_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '关联数据',
+            'default'   => '1',
+            'desc'      => '关联数据',
+            'match'     => 'option',
+            'update'    => 'select',
+        ),
+
+        'mid'      => array
+        (
+            'type'      => 'varchar-200',
+            'name'      => '商户号',
+            'default'   => '',
+            'desc'      => '商户号',
+            'match'     => 'option',
+            'update'    => 'text',
+            'list'		=> true,
+        ),
+
+        'per'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '平台分账百分比-如输入10,就是从总支付金额中分账10%,未输入则直接使用默认分账百分比',
+			'default' 	=> '',
+			'desc' 		=> '平台分账百分比',
+			'match' 	=> 'option',
+			'update'	=> 'text',
+		),
+
+        'cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '资金总额',
+            'default'   => '0',
+            'desc'      => '资金总额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            'list_name' => '资金总额 / 划付总额 / 分账总额',
+            'list'      => 'Dever::number({cash}/100, 2) . " / " . Dever::number({hf_cash}/100, 2) . " / " . Dever::number({fz_cash}/100, 2)',
+        ),
+
+        'hf_cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '划付总额-划付就是提现到商户自己账户的意思',
+            'default'   => '0',
+            'desc'      => '划付总额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            //'list'		=> 'round({hf_cash}/100, 2)',
+        ),
+
+        'fz_cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '分账总额',
+            'default'   => '0',
+            'desc'      => '分账总额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            //'list'		=> 'round({fz_cash}/100, 2)',
+        ),
+
+        'yue'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '账户余额',
+            'default'   => '0',
+            'desc'      => '账户余额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            'list_name' => '账户余额 / 提现总额',
+            'list'		=> 'Dever::number({yue}/100, 2) . " / " . Dever::number({tx_cash}/100, 2)',
+        ),
+
+        'tx_cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现总额',
+            'default'   => '0',
+            'desc'      => '划付总额',
+            'match'     => 'option',
+            //'update'    => 'text',
+            //'list'		=> 'round({tx_cash}/100, 2)',
+        ),
+
+        'pay/yspay_sign-one#step'=> array
+	    (
+	        'name'      => '当前状态',
+	        'default'   => '',
+	        'desc'      => '当前状态',
+	        'match'     => 'option',
+	        # 读取另外表的关联方式
+	        'sync'      => array('merchant_id' => 'id'),
+	    ),
+
+        'status'      => array
+        (
+            'type'      => 'tinyint-11',
+            'name'      => '状态',
+            'default'   => '2',
+            'desc'      => '状态',
+            'match'     => 'option',
+            'option'    => $status,
+            'update'    => 'radio',
+            'search'    => 'select',
+            //'list'      => true,
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+            'list_name' => '签约进度',
+            'list'      => 'Dever::load("pay/yspay/sign.getLog", {id}, {status})',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '录入时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            'insert'    => true,
+            'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+	'manage' => array
+    (
+    	'insert' => false,
+        'edit' => false,
+
+        # 自定义快捷新增和编辑
+        'button' => array
+        (
+            '新增' => array('fast'),
+        ),
+
+        'list_button' => array
+        (
+        	'edit' => array('编辑'),
+
+        	'add' => array('签约', '"yspay_sign&search_option_merchant_id={id}&where_id={id}&oper_table=account&oper_save_table=yspay_merchant"', '{status} == 2'),
+
+        	'oper' => array('提交资料', 'pay/yspay/sign.handle?sign_id={id}', '{pay/yspay_sign-one#step} == -1 && {status} == 2'),
+            'fast' => array('打款确认', '"yspay_sign&where_id={id}&col=cash"', '{pay/yspay_sign-one#step} == 2 && {status} == 2'),
+            'copy' => array('合同链接', 'pay/yspay/sign.getAgreement?sign_id={id}', '{pay/yspay_sign-one#step} == 4 && {status} == 2'),
+
+        	'list' => array('资金流水', '"yspay_cash&search_option_merchant_id={id}&oper_table=yspay_merchant&top_table=account"', '{status} == 1'),
+
+        	'list2' => array('提现管理', '"yspay_tixian&search_option_merchant_id={id}&oper_table=yspay_merchant&top_table=account"', '{status} == 1'),
+
+        	'list1' => array('签约日志', '"yspay_sign_log&search_option_merchant_id={id}&oper_table=yspay_merchant&top_table=account"'),
+        ),
+    ),
+
+    'request' => array
+    (
+       'tx_inc' => array
+		(
+			'type' => 'update',
+			'where' => array
+			(
+				'id' => 'yes',
+			),
+			'set' => array
+			(
+				'tx_cash' => array('yes', '+='),
+			),
+		),
+
+		'dec' => array
+		(
+			'type' => 'update',
+			'where' => array
+			(
+				'id' => 'yes',
+			),
+			'set' => array
+			(
+				'yue' => array('yes', '-='),
+			),
+		),
+    )
+);

+ 81 - 0
database/yspay_project.php

@@ -0,0 +1,81 @@
+<?php
+
+return array
+(
+	# 表名
+	'name' => 'yspay_project',
+	# 显示给用户看的名称
+	'lang' => '银商关联项目',
+	'order' => 10,
+	'menu' => false,
+	# 数据结构
+	'struct' => array
+	(
+	
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'account_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '账户id',
+            'default'   => '',
+            'desc'      => '账户id',
+            'match'     => 'option',
+        ),
+
+		'name'		=> array
+		(
+			'type' 		=> 'varchar-50',
+			'name' 		=> '项目名',
+			'default' 	=> '',
+			'desc' 		=> '项目名',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+		),
+
+		'table'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '表名',
+			'default' 	=> '',
+			'desc' 		=> '表名',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+		),
+
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '申请时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+			'search'	=> 'date',
+			'list'		=> 'date("Y-m-d H:i:s", {cdate})',
+		),
+	),
+
+	'manage' => array
+	(
+		
+	),
+);

+ 534 - 0
database/yspay_sign.php

@@ -0,0 +1,534 @@
+<?php
+$acct_type = array
+(
+    -1 => '个人账户',
+    1 => '公司账户',
+);
+$mer_type = array
+(
+    2 => '个人工商户',
+    1 => '企业商户',
+    3 => '小微商户',
+);
+$desc = '';
+$col = Dever::input('col');
+if (!$col) {
+    $tab = array('门店信息', '法人信息', '企业信息', '银行信息');
+} else {
+    $tab = '';
+}
+
+$step = array
+(
+    -1 => '待提交资料',
+    1 => '入网:资料提交',//3.2
+    2 => '入网:对公账户打款',//3.7
+    3 => '入网:对公账户验证',//3.6
+
+    4 => '入网:前台签约中',//3.3
+    5 => '入网:签约审核中',//3.4
+    6 => '入网:签约成功',//3.4
+
+    11 => '变更:资料提交',//3.9
+    14 => '变更:前台签约中',//3.10
+    15 => '变更:签约审核中',//3.11
+    16 => '变更:签约成功',//3.11
+);
+
+return array
+(
+    # 表名
+    'name' => 'yspay_sign',
+    # 显示给用户看的名称
+    'lang' => '银联签约',
+    # 后台菜单排序
+    'order' => -100,
+    'menu' => false,
+    'step' => $step,
+    'end' => array
+    (
+        'update' => 'pay/yspay/sign.update',
+    ),
+    # 数据结构
+    'struct' => array
+    (
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            //'list'      => true,
+            'order'     => 'desc',
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'ums_reg_id'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '自助签约平台唯一标识',
+            'default'   => '',
+            'desc'      => '自助签约平台唯一标识',
+            'match'     => 'option',
+            // 'update'    => 'text',
+        ),
+
+        'url'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '签约前台页面地址',
+            'default'   => '',
+            'desc'      => '签约前台页面地址',
+            'match'     => 'option',
+            // 'update'    => 'text',
+        ),
+
+        'cash'      => array
+        (
+            'type'      => 'varchar-30',
+            'name'      => '打款金额',
+            'default'   => '',
+            'desc'      => '打款金额',
+            'match'     => 'option',
+            'update'    => $col ? 'text' : false,
+        ),
+
+        'area'       => array
+        (
+            'type'      => 'varchar-500',
+            'name'      => '城市区域',
+            'default'   => '',
+            'desc'      => '城市区域',
+            'match'     => 'option',
+            //'search'    => 'linkage',
+            'update'    => 'linkage',
+            'option'    => Dever::url('api.get?level_total=3', 'area'),
+            //'list'      => 'Dever::load("area/api.string", "{area}")',
+        ),
+
+        'address'       => array
+        (
+            'type'      => 'varchar-1000',
+            'name'      => '详细地址',
+            'default'   => '',
+            'desc'      => '详细地址',
+            'match'     => 'option',
+            'update'    => 'text',
+            //'list'        => true,
+        ),
+
+        'mccCode'      => array
+        (
+            'type'      => 'varchar-200',
+            'name'      => '行业类别编码',
+            'default'   => '5499',
+            'desc'      => '行业类别编码',
+            'match'     => 'option',
+            //'update'    => 'text',
+            'tab'       => 0,
+        ),
+
+        'tax'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '税务登记证',
+            'default'   => '',
+            'desc'      => '税务登记证',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 0,
+        ),
+
+        'door'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '门头照片',
+            'default'   => '',
+            'desc'      => '门头照片',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 0,
+        ),
+
+        'house_pic'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '室内照片',
+            'default'   => '',
+            'desc'      => '室内照片',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 0,
+        ),
+
+        'screen_pic'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '商户网站/APP截图',
+            'default'   => '',
+            'desc'      => '商户网站/APP截图',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 0,
+        ),
+
+        'name'      => array
+        (
+            'type'      => 'varchar-32',
+            'name'      => '法人姓名',
+            'default'   => '',
+            'desc'      => '请输入法人姓名',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+            'list_order' => -9,
+            'tab'       => 1,
+        ),
+
+        'mobile'      => array
+        (
+            'type'      => 'bigint-11',
+            'name'      => '法人电话',
+            'default'   => '',
+            'desc'      => '请输入法人电话',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+            'list_order' => -8,
+            'tab'       => 1,
+        ),
+
+        'legalmanHomeAddr'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '法人家庭地址',
+            'default'   => '',
+            'desc'      => '法人家庭地址',
+            'match'     => 'option',
+            'update'    => 'text',
+            'tab'       => 1,
+        ),
+
+        'idcard'      => array
+        (
+            'type'      => 'varchar-32',
+            'name'      => '法人身份证号码',
+            'default'   => '',
+            'desc'      => '身份证号码',
+            'match'     => Dever::rule('idcard'),
+            'update'    => 'text',
+            'tab'       => 1,
+        ),
+
+        'card_deadline'      => array
+        (
+            'type'      => 'varchar-32',
+            'name'      => '法人身份证截止日期',
+            'default'   => '',
+            'desc'      => '身份证截止日期',
+            'match'     => 'option',
+            'default'   => '0',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'update'    => 'day',
+            //'search'    => 'date',
+            'callback'  => 'maketime',
+            'tab'       => 1,
+        ),
+
+        'idcard_front'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '法人身份证正面',
+            'default'   => '',
+            'desc'      => '身份证正面',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 1,
+        ),
+
+        'idcard_back'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '法人身份证背面',
+            'default'   => '',
+            'desc'      => '法人身份证背面',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 1,
+        ),
+
+        'hand_idcard'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '法人手持身份证自拍照',
+            'default'   => '',
+            'desc'      => '法人手持身份证自拍照',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 1,
+        ),
+
+        'reg_mer_type'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '企业类型',
+            'default'   => '2',
+            'desc'      => '企业类型',
+            'match'     => 'option',
+            'update'    => 'radio',
+            'option'    => $mer_type,
+            'search'    => 'select',
+            'list'      => true,
+            'tab'       => 2,
+        ),
+
+        'company_name'      => array
+        (
+            'type'      => 'varchar-200',
+            'name'      => '企业名称',
+            'default'   => '',
+            'desc'      => '企业名称',
+            'match'     => 'option',
+            'update'    => 'text',
+            'tab'       => 2,
+        ),
+
+        'license'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '企业营业执照',
+            'default'   => '',
+            'desc'      => '营业执照',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 2,
+        ),
+
+        'license_number'      => array
+        (
+            'type'      => 'varchar-200',
+            'name'      => '企业营业执照号码',
+            'default'   => '',
+            'desc'      => '营业执照号码',
+            'match'     => 'option',
+            'update'    => 'text',
+            'tab'       => 2,
+        ),
+
+        'bank_acct_type'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '开户行账户类型',
+            'default'   => '-1',
+            'desc'      => '账户类型',
+            'match'     => 'option',
+            'update'    => 'radio',
+            'option'    => $acct_type,
+            'tab'       => 3,
+        ),
+
+        'back_no'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '开户行行号',
+            'default'   => '',
+            'desc'      => '开户行行号',
+            'match'     => 'option',
+            // 'update'    => 'text',
+            'tab'       => 3,
+        ),
+
+        'shop_addr_ext'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '开户行地址',
+            'default'   => '',
+            'desc'      => '开户行地址',
+            'match'     => 'option',
+            // 'update'    => 'text',
+            'tab'       => 3,
+        ),
+
+        'bank_acct_no'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '开户行账号',
+            'default'   => '',
+            'desc'      => '开户行账号',
+            'match'     => 'option',
+            'update'    => 'text',
+            'tab'       => 3,
+        ),
+
+        'bank_area'       => array
+        (
+            'type'      => 'varchar-500',
+            'name'      => '开户所在地',
+            'default'   => '',
+            'desc'      => '开户所在地',
+            'match'     => 'option',
+            //'search'    => 'linkage',
+            'update'    => 'linkage',
+            'option'    => Dever::url('api.get?level_total=2', 'area'),
+            //'list'      => 'Dever::load("area/api.string", "{area}")',
+            'tab'       => 3,
+        ),
+
+        'bank_acct_noname'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '开户行名称-银行名称和支行名称用/隔开,如:招商/天通苑',
+            'default'   => '',
+            'desc'      => '开户行名称',
+            'match'     => 'option',
+            'update'    => 'text',
+            'tab'       => 3,
+        ),
+
+        'bank_fount'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '银行卡正面照',
+            'default'   => '',
+            'desc'      => '银行卡正面照',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 3,
+        ),
+
+        'bank_back'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '银行卡反面照',
+            'default'   => '',
+            'desc'      => '银行卡反面照',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 3,
+        ),
+
+        'open'     => array
+        (
+            'type'      => 'varchar-150',
+            'name'      => '开户许可证',
+            'default'   => '',
+            'desc'      => '开户许可证',
+            'match'     => 'option',
+            'update'    => 'image',
+            'key'       => '8',
+            'place'     => '660*660',
+            'tab'       => 3,
+        ),
+
+        'step'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '状态',
+            'default'   => '-1',
+            'desc'      => '当前步骤',
+            'match'     => 'option',
+            'option'    => $step,
+            // 'update'    => 'text',
+            'search'    => 'select',
+            'list'      => true,
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+            'list_name' => '最新进度',
+            'list'      => 'Dever::load("shop/lib/sign.getLog", {id})',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '录入时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            'insert'    => true,
+            //'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+	'manage' => array
+    (
+        'edit' => false,
+        'delete' => false,
+        # 图片上传后调用的接口
+        'upload' => 'pay/yspay/sign.upload?sign=1',
+        # 更新页面顶部描述
+        'desc' => $desc,
+        # 更新页面tab切换
+        'tab' => $tab,
+        //'list' => 'update',
+        'list_button' => array
+        (
+            'update' => array('编辑', '', '{step} == -1'),
+            'delete' => array('删除', '', '{step} == -1'),
+            'oper' => array('提交资料', 'pay/yspay/sign.handle?sign_id={id}', '{step} == -1'),
+            'fast' => array('打款确认', '"yspay_sign&where_id={id}&col=cash"', '{step} == 2'),
+            'copy' => array('复制链接', 'pay/yspay/sign.getAgreement?sign_id={id}', '{step} == 4'),
+            //'oper' => array('重新生成合同', 'pay/yspay/sign.getAgreement?sign_id={id}', '{step} == 4'),
+            'list' => array('查看日志', '"yspay_sign_log&search_option_sign_id={id}&oper_table=yspay_sign"'),
+            //'fast1' => array('绑定门店', '"sign&where_id={id}&col=create_shop,shop_id"', '({step} == 6)'),
+        )
+    ),
+
+    'request' => array
+    (
+        'getData' => array
+        (
+            # 匹配的正则或函数 选填项
+            'option' => array
+            (
+                'step' => array('yes', 'in'),
+                'state' => 1,
+            ),
+            'type' => 'all',
+            'order' => array('id' => 'asc'),
+            'col' => '*',
+        ),
+    )
+);

+ 136 - 0
database/yspay_sign_log.php

@@ -0,0 +1,136 @@
+<?php
+
+$step = Dever::db('pay/yspay_sign')->config['step'];
+$step[100] = '绑定门店';
+
+return array
+(
+    # 表名
+    'name' => 'yspay_sign_log',
+    # 显示给用户看的名称
+    'lang' => '自主签约日志',
+    # 后台菜单排序
+    'order' => 99,
+    'step' => $step,
+    'menu' => false,
+    # 数据结构
+    'struct' => array
+    (
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            //'list'      => true,
+            'order'     => 'desc',
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'step'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '当前进度',
+            'default'   => '',
+            'desc'      => '当前进度',
+            'match'     => 'option',
+            'update'    => 'text',
+            'option'    => $step,
+            'list'      => true,
+        ),
+
+        'desc'     => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '日志描述',
+            'default'   => '',
+            'desc'      => '日志描述',
+            'match'     => 'option',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'request_seq'     => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '请求流水号',
+            'default'   => '',
+            'desc'      => '请求流水号',
+            'match'     => 'option',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'request'     => array
+        (
+            'type'      => 'text-255',
+            'name'      => '请求数据',
+            'default'   => '',
+            'desc'      => '请求数据',
+            'match'     => 'option',
+            'update'    => 'text',
+        ),
+
+        'response'     => array
+        (
+            'type'      => 'text-255',
+            'name'      => '响应数据',
+            'default'   => '',
+            'desc'      => '响应数据',
+            'match'     => 'option',
+            'update'    => 'text',
+        ),
+
+        'admin_id'       => array
+        (
+            'type'      => 'int-11',
+            'name'      => '管理员id',
+            'default'   => '0',
+            'desc'      => '管理员id',
+            'match'     => 'is_numeric',
+            'update'    => 'hidden',
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '请求时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            //'insert'    => true,
+            'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+	'manage' => array
+    (
+        'insert' => false,
+        'edit' => false,
+        'delete' => false,
+    ),
+);

+ 121 - 0
database/yspay_sign_pic.php

@@ -0,0 +1,121 @@
+<?php
+$acct_type = array
+(
+    -1 => '个人账户',
+    1 => '公司账户',
+);
+$mer_type = array
+(
+    1 => '企业商户',
+    2 => '个人工商户',
+    3 => '小微商户',
+);
+return array
+(
+    # 表名
+    'name' => 'yspay_sign_pic',
+    # 显示给用户看的名称
+    'lang' => '自主签约图片',
+    # 后台菜单排序
+    'order' => 99,
+    'menu' => false,
+    # 数据结构
+    'struct' => array
+    (
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            //'list'      => true,
+            'order'     => 'desc',
+        ),
+
+        'key'      => array
+        (
+            'type'      => 'varchar-32',
+            'name'      => '图片key',
+            'default'   => '',
+            'desc'      => '图片key',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'url'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '图片url',
+            'default'   => '',
+            'desc'      => '图片url',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'document_name'      => array
+        (
+            'type'      => 'varchar-32',
+            'name'      => '图片名称',
+            'default'   => '',
+            'desc'      => '请输入姓名',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'document_type'      => array
+        (
+            'type'      => 'varchar-32',
+            'name'      => '图片类型',
+            'default'   => '',
+            'desc'      => '请输入姓名',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'      => true,
+        ),
+
+        'path'      => array
+        (
+            'type'      => 'text-300',
+            'name'      => '图片内容',
+            'default'   => '',
+            'desc'      => '请输入姓名',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'search'    => 'text',
+            'list'      => true,
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '录入时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            'insert'    => true,
+            //'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+	'manage' => array
+    (
+        // 'list' => 'update',
+    ),
+);

+ 186 - 0
database/yspay_tixian.php

@@ -0,0 +1,186 @@
+<?php
+$status = array
+(
+    4 => array('name' => '提现完成', 'style' => 'font-weight:bold;color:green'),
+    5 => array('name' => '提现失败', 'style' => 'font-weight:bold;color:#CD3700'),
+);
+
+$merchant_id = Dever::input('search_option_merchant_id');
+$button = array();
+$info = '';
+$tixian = Dever::input('tixian', 1);
+if ($shop) {
+    # 申请提现和查看提现日志
+    $account = Dever::db('pay/yspay_merchant')->find($merchant_id);
+    if ($account) {
+        $info = $shop['name'] . ',当前余额:' . round($account['yue']/100, 2) . '元,总提现金额:' . round($account['tx_cash']/100, 2) . '元';
+    }
+    
+
+    if ($tixian == 1) {
+        $button['手动申请提现'] = array('fast', 1,'yspay_tixian_apply&search_option_merchant_id=' . $merchant_id);
+        $button['提现申请记录'] = array('location', 'l=project/database/list&project=pay&table=yspay_tixian_log&search_option_state=1&search_option_merchant_id='.$merchant_id.'&oper_table=yspay_tixian');
+    }
+}
+
+return array
+(
+    # 表名
+    'name' => 'yspay_tixian',
+    # 显示给用户看的名称
+    'lang' => '银联提现列表',
+    'order' => -200,
+    'info' => $info,
+    # 数据结构
+    'struct' => array
+    (
+    
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            'update'    => 'hidden',
+            //'list'        => true,
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'mid'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '分账商户号',
+            'default'   => '',
+            'desc'      => '分账商户号',
+            'match'     => 'option',
+            'update'    => 'text',
+            'search'    => 'fulltext',
+            'list'		=> true,
+        ),
+
+        'order_num'      => array
+        (
+            'type'      => 'varchar-100',
+            'name'      => '订单号',
+            'default'   => '',
+            'desc'      => '订单号',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'list'		=> true,
+        ),
+
+        'type'      => array
+        (
+            'type'      => 'varchar-10',
+            'name'      => '类型',
+            'default'   => '',
+            'desc'      => '类型',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+        ),
+
+        'cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现金额',
+            'default'   => '0',
+            'desc'      => '提现金额',
+            'match'     => 'option',
+            'update'    => 'text',
+            'list'      => 'round({cash}/100, 2)',
+        ),
+
+        'cardNo'      => array
+        (
+            'type'      => 'varchar-100',
+            'name'      => '到账银行卡号',
+            'default'   => '',
+            'desc'      => '到账银行卡号',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            //'list'		=> true,
+        ),
+
+        'tdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现到账时间',
+            'default'   => '',
+            'match'     => 'is_numeric',
+            'desc'      => '',
+            'search'    => 'date',
+            'list'      => '"{tdate}" ? date("Y-m-d H:i", \'{tdate}\') : "-"',
+            'order'		=> 'desc',
+        ),
+
+        'status'        => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '提现状态',
+            'default'   => '1',
+            'desc'      => '提现状态',
+            'match'     => 'is_numeric',
+            'option'    => $status,
+            'search'    => 'select',
+            'list'      => true,
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '创建时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            //'insert'    => true,
+            //'search'    => 'date',
+            //'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+
+    'manage' => array
+    (
+        'edit' => false,
+        'insert' => false,
+        'delete' => false,
+        'button' => $button,
+    ),
+
+    'request' => array
+    (
+        'getTotal' => array
+        (
+            'option' => array
+            (
+                'merchant_id' => 'yes',
+                'status' => 'yes',
+                'state' => 1,
+            ),
+            'type' => 'one',
+            'col' => 'sum(cash) as cash',
+        ),
+    ),
+);

+ 113 - 0
database/yspay_tixian_apply.php

@@ -0,0 +1,113 @@
+<?php
+
+return array
+(
+    # 表名
+    'name' => 'yspay_tixian_apply',
+    # 显示给用户看的名称
+    'lang' => '申请提现',
+    'order' => -200,
+    'menu' => false,
+    'start' => array
+    (
+        'insert' => 'pay/yspay/tixian.insert',
+    ),
+    'end' => array
+    (
+    	'insert' => 'pay/yspay/tixian.update', 
+    	'update' => 'pay/yspay/tixian.update',
+    ),
+    # 数据结构
+    'struct' => array
+    (
+    
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            'update'    => 'hidden',
+            //'list'        => true,
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现金额',
+            'default'   => '0',
+            'desc'      => '提现金额',
+            'match'     => 'option',
+            'update'    => 'text',
+            'list'      => 'round({cash}/100, 2)',
+        ),
+
+        'desc'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '备注',
+            'default'   => '',
+            'desc'      => '备注',
+            'match'     => 'is_numeric',
+            'update'    => 'textarea',
+            'list'      => true,
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '创建时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            //'insert'    => true,
+            //'search'    => 'date',
+            //'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+
+    'manage' => array
+    (
+        'edit' => false,
+        'insert' => false,
+        'delete' => false,
+    ),
+
+    'request' => array
+    (
+        'getAll' => array
+        (
+            'option' => array
+            (
+                'merchant_id' => 'yes',
+                'state' => 1,
+            ),
+            'type' => 'all',
+            'col' => '*|merchant_id',
+        ),
+    ),
+);

+ 191 - 0
database/yspay_tixian_log.php

@@ -0,0 +1,191 @@
+<?php
+$status = array
+(
+    1 => array('name' => '提现申请中', 'style' => 'font-weight:bold;color:blue'),
+    2 => array('name' => '受理成功', 'style' => 'font-weight:bold;color:green'),
+    //3 => array('name' => '受理失败', 'style' => 'font-weight:bold;color:#CD3700'),
+);
+
+$mtype = array
+(
+	1 => '自动提现',
+	2 => '手动提现',
+);
+return array
+(
+    # 表名
+    'name' => 'yspay_tixian_log',
+    # 显示给用户看的名称
+    'lang' => '银联提现日志列表',
+    'order' => -200,
+    'menu' => false,
+    # 数据结构
+    'struct' => array
+    (
+    
+        'id'        => array
+        (
+            'type'      => 'int-11',
+            'name'      => 'ID',
+            'default'   => '',
+            'desc'      => '',
+            'match'     => 'is_numeric',
+            'search'    => 'order',
+            'update'    => 'hidden',
+            //'list'        => true,
+        ),
+
+        'merchant_id'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '商户id',
+            'default'   => '',
+            'desc'      => '商户id',
+            'match'     => 'option',
+            'update'    => 'hidden',
+            'value'     => Dever::input('search_option_merchant_id'),
+            'list_name' => '商户名称',
+            'list'      => 'Dever::load("pay/yspay_merchant-one#name", "{merchant_id}")',
+        ),
+
+        'mid'      => array
+        (
+            'type'      => 'varchar-50',
+            'name'      => '分账商户号',
+            'default'   => '',
+            'desc'      => '分账商户号',
+            'match'     => 'option',
+            'update'    => 'text',
+            'searchs'    => 'fulltext',
+            'list'		=> true,
+        ),
+
+        'order_num'      => array
+        (
+            'type'      => 'varchar-100',
+            'name'      => '订单号',
+            'default'   => '',
+            'desc'      => '订单号',
+            'match'     => 'is_string',
+            'update'    => 'text',
+            'list'		=> true,
+        ),
+
+        'type'      => array
+        (
+            'type'      => 'varchar-10',
+            'name'      => '类型',
+            'default'   => '',
+            'desc'      => '类型',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+        ),
+
+        'cash'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现金额',
+            'default'   => '0',
+            'desc'      => '提现金额',
+            'match'     => 'option',
+            'update'    => 'text',
+            'list'      => 'round({cash}/100, 2)',
+        ),
+
+        'tdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现时间',
+            'default'   => '',
+            'match'     => 'is_numeric',
+            'desc'      => '',
+            'search'    => 'date',
+            'list'      => '"{tdate}" ? date("Y-m-d H:i", \'{tdate}\') : "-"',
+            'order'		=> 'desc',
+        ),
+
+        'mtype'      => array
+        (
+            'type'      => 'int-11',
+            'name'      => '提现类型',
+            'default'   => '1',
+            'desc'      => '提现类型',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+        ),
+
+        'status'        => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '提现状态',
+            'default'   => '1',
+            'desc'      => '提现状态',
+            'match'     => 'is_numeric',
+            'option'    => $status,
+            'search'    => 'select',
+            'list'      => true,
+        ),
+
+        'desc'      => array
+        (
+            'type'      => 'varchar-800',
+            'name'      => '备注',
+            'default'   => '-',
+            'desc'      => '备注',
+            'match'     => 'is_numeric',
+            'update'    => 'text',
+            'list'      => true,
+        ),
+
+        'response'        => array
+        (
+            'type'      => 'text-255',
+            'name'      => '回调响应数据',
+            'default'   => '',
+            'desc'      => '回调响应数据',
+            'match'     => 'is_string',
+        ),
+
+        'state'     => array
+        (
+            'type'      => 'tinyint-1',
+            'name'      => '状态',
+            'default'   => '1',
+            'desc'      => '请选择状态',
+            'match'     => 'is_numeric',
+        ),
+        
+        'cdate'     => array
+        (
+            'type'      => 'int-11',
+            'name'      => '创建时间',
+            'match'     => array('is_numeric', time()),
+            'desc'      => '',
+            # 只有insert时才生效
+            //'insert'    => true,
+            //'search'    => 'date',
+            //'list'      => 'date("Y-m-d H:i:s", {cdate})',
+        ),
+    ),
+
+    'manage' => array
+    (
+        'edit' => false,
+        'insert' => false,
+        'delete' => false,
+    ),
+
+    'request' => array
+    (
+        'getAll' => array
+        (
+            'option' => array
+            (
+                'merchant_id' => 'yes',
+                'state' => 1,
+            ),
+            'type' => 'all',
+            'col' => '*|merchant_id',
+        ),
+    ),
+);

+ 64 - 29
lib/Yspay.php

@@ -1,6 +1,7 @@
 <?php namespace Pay\Lib;
 use Dever;
 
+#银联商务正常交易
 class Yspay extends Core
 {
 	public function __construct($config)
@@ -160,22 +161,41 @@ class Yspay extends Core
 		$request['tradeType'] = $trade_type;
 
 		if ($other) {
-			$request['originalAmount'] = round($other['oprice'] * 100, 2);
-			$request['divisionFlag'] = true;
-			# 平台分账金额
-			$other['per'] = $other['per'] && $other['per'] >= 0 ? $other['per'] : 0;
-			$other['per'] = $other['per']/100;
-			$request['platformAmount'] = round($request['totalAmount'] * $other['per'], 2);
+			if (!isset($other[0])) {
+				$other = array($other);
+			}
+			$request['originalAmount'] = $request['totalAmount'];
+			$request['platformAmount'] = $request['totalAmount'];
 			$request['subOrders'] = array();
-			$request['subOrders']['mid'] = $other['mid'];
-			if (isset($this->config['prefix']) && $this->config['prefix']) {
-				$request['subOrders']['merOrderId'] = $this->config['prefix'] . $other['order_id'];
-			} else {
-				$request['subOrders']['merOrderId'] = $other['order_id'];
+			foreach ($other as $k => $v) {
+				$subOrders = array();
+				if (isset($v['amount']) && $v['amount']) {
+					$subOrders['totalAmount'] = $v['amount'];
+					$request['platformAmount'] = round($request['platformAmount'] - $subOrders['totalAmount'], 2);
+				} elseif (isset($v['per']) && $v['per']) {
+					# 此处为兼容历史业务代码
+					$v['per'] = $v['per'] && $v['per'] >= 0 ? $v['per'] : 0;
+					$v['per'] = $v['per']/100;
+					$request['platformAmount'] = round($request['totalAmount'] * $v['per'], 2);
+					$subOrders['totalAmount'] = round($request['totalAmount'] - $request['platformAmount'], 2);
+					break;
+				} else {
+					continue;
+				}
+				$subOrders['mid'] = $v['mid'];
+				if (isset($this->config['prefix']) && $this->config['prefix']) {
+					$subOrders['merOrderId'] = $this->config['prefix'] . $v['order_id'];
+				} else {
+					$subOrders['merOrderId'] = $v['order_id'];
+				}
+				$request['subOrders'][] = $subOrders;
+
+				# 记录划付
+				Dever::load('pay/yspay/cash')->add($order_id, $request, $subOrders);
+			}
+			if ($request['subOrders']) {
+				$request['divisionFlag'] = true;
 			}
-			
-			$request['subOrders']['totalAmount'] = round($request['totalAmount'] - $request['platformAmount'], 2);
-			$request['subOrders'] = array($request['subOrders']);
 		}
 		if (!$openid) {
 			# 测试的openid
@@ -253,25 +273,40 @@ class Yspay extends Core
 		
 		if (isset($order['param']['other']) && $order['param']['other']) {
 			$other = $order['param']['other'];
-			$other['per'] = $other['per'] && $other['per'] >= 0 ? $other['per'] : 0;
-			$other['per'] = $other['per']/100;
-			$request['platformAmount'] = round($request['refundAmount'] * $other['per'], 2);
+			if (!isset($other[0])) {
+				$other = array($other);
+			}
+			$request['platformAmount'] = $request['refundAmount'];
 			$request['subOrders'] = array();
-			$request['subOrders']['mid'] = $other['mid'];
-			if (isset($this->config['prefix']) && $this->config['prefix']) {
-				$request['subOrders']['merOrderId'] = $this->config['prefix'] . $other['order_id'];
-				if ($refund_order_id) {
-					$request['subOrders']['refundOrderId'] = $this->config['prefix'] . $refund_order_id;
+			foreach ($other as $k => $v) {
+				$subOrders = array();
+				if (isset($v['amount']) && $v['amount']) {
+					$subOrders['totalAmount'] = $v['amount'];
+					$request['platformAmount'] = round($request['platformAmount'] - $subOrders['totalAmount'], 2);
+				} elseif (isset($v['per']) && $v['per']) {
+					$v['per'] = $v['per'] && $v['per'] >= 0 ? $v['per'] : 0;
+					$v['per'] = $v['per']/100;
+					$request['platformAmount'] = round($request['refundAmount'] * $v['per'], 2);
+					$subOrders['totalAmount'] = round($request['totalAmount'] - $request['platformAmount'], 2);
+				} else {
+					continue;
 				}
-			} else {
-				$request['subOrders']['merOrderId'] = $other['order_id'];
-				if ($refund_order_id) {
-					$request['subOrders']['refundOrderId'] = $refund_order_id;
+				
+				$subOrders['mid'] = $other['mid'];
+				if (isset($this->config['prefix']) && $this->config['prefix']) {
+					$subOrders['merOrderId'] = $this->config['prefix'] . $v['order_id'];
+					if ($refund_order_id) {
+						$subOrders['refundOrderId'] = $this->config['prefix'] . $refund_order_id;
+					}
+				} else {
+					$subOrders['merOrderId'] = $v['order_id'];
+					if ($refund_order_id) {
+						$subOrders['refundOrderId'] = $refund_order_id;
+					}
 				}
+
+				$request['subOrders'][] = $subOrders;
 			}
-			
-			$request['subOrders']['totalAmount'] = round($request['refundAmount'] - $request['platformAmount'], 2);
-			$request['subOrders'] = array($request['subOrders']);
 		}
 
 		$account = Dever::db('pay/account')->find($order['account_id']);

+ 331 - 0
yspay/Account.php

@@ -0,0 +1,331 @@
+<?php namespace Pay\Yspay;
+use Dever;
+/**
+ * 银联商务代付
+ * Class Chinaums
+ */
+class Account
+{
+	//测试地址
+	protected $test_host = 'https://mobl-test.chinaums.com/';
+
+	//正式地址
+	protected $host = 'https://managefree.chinaums.com/';
+
+    //系统编号(sysId)
+    protected $sys_id = '10119';
+
+    //商户号
+    protected $mch_id = '89810007372106N';
+
+    //外部平台私钥
+    protected $private_key = 'MIIEowIBAAKCAQEApzpOtvWGclmdw+/aEzAxwyTgUwnC9qjQEhL+qfMWDBIbFR8N4q6GQ8fRKZ9Zyvm0voFhgpH44Y6sh2U7rF9HQOuw2puywvU8kk5JAUxpxykbH7QqW/ijH1gBG3Ck/Ip/5I4co+q9K/CjQRmId5nSJ8ffnaiAOogNZycrP+AgEEU8vL1eNtnagVxT3EC1LEh0wBwecT9Tkyi0tMD0sMeIUl9POrnh7YADJtUzGf+TTNrqK6DhoT9mE3Plw0pqxKSk4/tHNx1ZIXf4I/UeYSEAreXHWVfLQ/if1C9HRYhEGB57mmqn0JdmsSRD7DX7eU7Oja+RqtWfQ/KH+2fnjq9uSwIDAQABAoIBABACUvrM8nwL/EB/u77OhFUMOLV6X8HBU3oHe33Fmby6FwGkoW2sC4p9nJaBfNUjppv+Qtl/I/Zj9DxaAqZz0Jx0c8/Zy/lCBPR0riSDrjS0yLX2R3/ag7NCd4iq9gB/OdMlj7RZipakSNy4lwnsHeRVDCFJukzgLXhMlaVdzXQBJTdERP3G8A9vwxuvbOE3q3kHCTWepVYd3KdEQ5rDPrYh/HwfVB2tWSne7Z/NurutW5qLA6aiJGcDoF7H41Fit8zw1QDnwJNvsUeR/POFFD0zog7+ZpMX3OiJwFKBZfTNvzJtH3mkqnN62JJwpJNqTTMWdfSziFlQNJ6GrCqhaxECgYEA1STJz0GAC7tho/l6O13BYlnyjS15bSCrr23XXUY3Sa7s6JiNFAUkIFq57XzEEdZhqOmgQlJQmGKJmmRVSshnSH7HohRdjisnjAbK1O0qABe3tP3IIuKCrPY+q1zb+PpYkFMiWUr3+1JYKU8o5tQCWQhRLVPN8Gbl6K0ffr3sJzcCgYEAyNoS4oWNeKnAJyK7rkDq7iMkf4eDMEUl1VPunZOTsZDkycf3bIKJJK+KW/HNpCt5M+DdhgZPtbuvpPVZFsscbM/q2q4vIBxp2riS94o+Aoijc8U5FzkhE+a5+qTJpykMBOVXaHENVvZzeh9TysoRROiI3c4IibKsP2NdwxnRU40CgYACozjoGqxl+MSljdHIaEmbWPeabaSiCBR30Eko+1R10fdWjYS5abLfv5+rY67ddaSxvWphR7l9mUKQqYswqLg2enMn+06JEtmjbvYVmnW5mJGKaNWQMPNjBo0R+80xEJAGATFcn4PgFU3H/RXJfXgl9+dhQzc6MVvI/FN2cw04EwKBgQCp3uaB9vpDxy3g65tYMUeAyPAhe/cUaCcrWaVCWIJdd3JIxnsYpv5erKiUQtnts2b63X/9znCz/1z6YxdKE9aioOa8tPzeZ6mPdvO1sJHpiq7TR0aVwZecQVOiDKUQX8LukRlwF810c1QPQVeY93XLle/LyGmoLBlKMzwlujw0MQKBgDZT/egpnQM3x4TR9ERrk0o5GOLHNFiNkSfkzzZ3D2nRGT+6GRlmb40LtPzBy5+vAgLqBlfEEfToaMGZ+Vrl2CePBBoR/j/q8nlziqZ3H5b8plqHSbX85zONT6tF+YZ2nRMxpI2gQtecRzoozm+ilELCNSd6V7pAzpl14KRU2V5l';
+
+    //外部平台PKCS1私钥(银联商务提供的PKCS8格式需转为PKCS1格式)
+    protected $private_key_pkcs1 = 'MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnOk629YZyWZ3D79oTMDHDJOBTCcL2qNASEv6p8xYMEhsVHw3iroZDx9Epn1nK+bS+gWGCkfjhjqyHZTusX0dA67Dam7LC9TySTkkBTGnHKRsftCpb+KMfWAEbcKT8in/kjhyj6r0r8KNBGYh3mdInx9+dqIA6iA1nJys/4CAQRTy8vV422dqBXFPcQLUsSHTAHB5xP1OTKLS0wPSwx4hSX086ueHtgAMm1TMZ/5NM2uoroOGhP2YTc+XDSmrEpKTj+0c3HVkhd/gj9R5hIQCt5cdZV8tD+J/UL0dFiEQYHnuaaqfQl2axJEPsNft5Ts6Nr5Gq1Z9D8of7Z+eOr25LAgMBAAECggEAEAJS+szyfAv8QH+7vs6EVQw4tXpfwcFTegd7fcWZvLoXAaShbawLin2cloF81SOmm/5C2X8j9mP0PFoCpnPQnHRzz9nL+UIE9HSuJIOuNLTItfZHf9qDs0J3iKr2AH850yWPtFmKlqRI3LiXCewd5FUMIUm6TOAteEyVpV3NdAElN0RE/cbwD2/DG69s4TereQcJNZ6lVh3cp0RDmsM+tiH8fB9UHa1ZKd7tn826u61bmosDpqIkZwOgXsfjUWK3zPDVAOfAk2+xR5H884UUPTOiDv5mkxfc6InAUoFl9M2/Mm0feaSqc3rYknCkk2pNMxZ19LOIWVA0noasKqFrEQKBgQDVJMnPQYALu2Gj+Xo7XcFiWfKNLXltIKuvbdddRjdJruzomI0UBSQgWrntfMQR1mGo6aBCUlCYYomaZFVKyGdIfseiFF2OKyeMBsrU7SoAF7e0/cgi4oKs9j6rXNv4+liQUyJZSvf7UlgpTyjm1AJZCFEtU83wZuXorR9+vewnNwKBgQDI2hLihY14qcAnIruuQOruIyR/h4MwRSXVU+6dk5OxkOTJx/dsgokkr4pb8c2kK3kz4N2GBk+1u6+k9VkWyxxsz+rari8gHGnauJL3ij4CiKNzxTkXOSET5rn6pMmnKQwE5VdocQ1W9nN6H1PKyhFE6IjdzgiJsqw/Y13DGdFTjQKBgAKjOOgarGX4xKWN0choSZtY95ptpKIIFHfQSSj7VHXR91aNhLlpst+/n6tjrt11pLG9amFHuX2ZQpCpizCouDZ6cyf7TokS2aNu9hWadbmYkYpo1ZAw82MGjRH7zTEQkAYBMVyfg+AVTcf9Fcl9eCX352FDNzoxW8j8U3ZzDTgTAoGBAKne5oH2+kPHLeDrm1gxR4DI8CF79xRoJytZpUJYgl13ckjGexim/l6sqJRC2e2zZvrdf/3OcLP/XPpjF0oT1qKg5ry0/N5nqY9287WwkemKrtNHRpXBl5xBU6IMpRBfwu6RGXAXzXRzVA9BV5j3dcuV78vIaagsGUozPCW6PDQxAoGANlP96CmdAzfHhNH0RGuTSjkY4sc0WI2RJ+TPNncPadEZP7oZGWZvjQu0/MHLn68CAuoGV8QR9OhowZn5WuXYJ48EGhH+P+ryeXOKpncflvymWodJtfznM41Pq0X5hnadEzGkjaBC15xHOijOb6KUQsI1J3pXukDOmXXgpFTZXmU=';
+
+    //银商系统公钥
+    protected $public_key = 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhTzN8wxdXYr+/+t8iX0mlol8wFy+0pGtxnyB6PjyrIRjGHrZJA7grZPvy7MOK6PqihqTZh6SO7tX9StxVmTQo+PuibAY/p2i08UxkIBUcucHVvHN8gkM3GBFBqD0uJgUc03cerEI7gNeaKYfCVs0/hMo6CKbdXVKqaE987kXYK209uFcte+Y8YofQ2AYamImpzSf7pXomAu+8D98HIOs5bKITHTk30vPdNhrQdpDRO1TuX0x8bwhCykcwAEdB/Z9YGXkLU5S3QJY2qvCZJY08YdNqIpbDqifSRvOg0sqeKFXPfI2M0GsOh6PArTEmh0QHxDht9xjPPt11aVgh8kgkQIDAQAB';
+
+    private function host()
+    {
+    	return $this->host;
+    }
+
+	public function notify_api()
+	{
+		$msg = Dever::input();
+		Dever::log($msg, 'yspay');
+		$order = $msg['order'];
+
+        if (!$order) {
+            echo 'FAILED';die;
+        }
+        if (strstr($order, 'TX')) {
+             $log = Dever::db('pay/yspay_tixian_log')->one(array('order_num' => $order));
+
+             if ($log) {
+                Dever::db('pay/yspay_tixian_log')->update(array('where_id' => $log['id'], 'status' => 2, 'response' => Dever::json_encode($msg)));
+
+                $account = Dever::db('pay/yspay_merchant')->one($log['merchant_id']);
+                if ($account) {
+                    Dever::db('pay/yspay_merchant')->dec(array('where_id' => $account['id'], 'set_yue' => $log['cash']));
+                }
+            }
+            echo 'SUCCESS';die;
+        }
+		$where['order_num'] = $order;
+		$order = Dever::db('yspay/sell_order')->find($where);
+		$class = new Chinaums();
+
+		if ($order && $order['withdraw'] == 1) {
+			$content = $msg['content'];
+
+			$content = $class->privateDecrypt($content);
+
+            $log = Dever::db('pay/yspay_tixian_log')->one(array('order_num' => $order, 'shop_id' => $order['shop_id']));
+			if ($content && isset($content['responseCode']) && ($content['responseCode'] == '000000' || $content['responseCode'] == '000001')) {
+				Dever::db('shop/sell_order')->update(array('where_id' => $order['id'], 'withdraw' => 2));
+                if ($log) {
+                    Dever::db('pay/yspay_tixian_log')->update(array('where_id' => $log['id'], 'status' => 2, 'response' => Dever::json_encode($content)));
+
+                    $account = Dever::db('shop/yspay_account')->one(array('shop_id' => $log['shop_id']));
+                    if ($account) {
+                        Dever::db('pay/yspay_account')->dec(array('where_id' => $account['id'], 'set_cash' => $log['cash']));
+                    }
+                }
+                echo 'SUCCESS';die;
+			} else {
+				Dever::load('shop/lib/cron')->yspayOne($order);
+			}
+		}
+
+        echo 'FAILED';die;
+	}
+
+    public function shop_host($type,$content=false)
+    {
+        if ($type == 1) {
+            return $this->host;
+        } elseif($type == 2){
+            return $this->mch_id;
+        } elseif($type == 3){
+            return $this->sys_id;
+        } elseif($type == 4 && $content){
+            return $this->createSignature($content);
+        } elseif($type == 5 && $content){
+            return $this->privateDecrypt($content);
+        }
+    }
+    # 查询余额
+    public function query($mid)
+    {
+    	$url = $this->host() . 'uisouterfront/qrywithdrawbalance/process';
+
+        $mid = $mid ? $mid : $this->mch_id;
+    	//整理内容信息
+        $content = [
+            'sysId' => $this->sys_id,
+            'mchntNo' => $mid,
+            'timestamp' => date('YmdHis'),
+        ];
+        //设置签名并加密
+        $body['content'] = $this->createSignature($content);
+
+        $result = Dever::curl($url, $body, 'post');
+
+        $decryptData = $this->privateDecrypt($result);
+        if (isset($decryptData['tzWithdrawAmtPublic'])) {
+        	return $decryptData['tzWithdrawAmtPublic'];
+        } elseif (isset($decryptData['t0WithdrawAmtPublic'])) {
+        	return $decryptData['t0WithdrawAmtPublic'];
+        }
+
+        return 0;
+    }
+
+    # 查询提现记录
+    public function record($mid, $start, $end, $page = '1')
+    {
+        $url = $this->host() . 'uisouterfront/withdraw/qryWithDrawLog';
+
+        $mid = $mid ? $mid : $this->mch_id;
+        //整理内容信息
+        $content = [
+            'sysId' => $this->sys_id,
+            'mchntNo' => $mid,
+            'timestamp' => date('YmdHis'),
+            'page' =>  (string) $page,
+            'beginDate' => $start,
+            'endDate' => $end,
+        ];
+        //设置签名并加密
+        $body['content'] = $this->createSignature($content);
+        $result = Dever::curl($url, $body, 'post');
+        $result = Dever::json_decode($result);
+        $decryptData = $this->privateDecrypt($result['result']);
+        if (isset($decryptData['recordList']) && $decryptData['recordList']) {
+            $data = Dever::json_decode($decryptData['recordList']);
+            if ($page == 1 && isset($decryptData['totalPage']) && $decryptData['totalPage'] > 1) {
+                for ($i = 2; $i <= $decryptData['totalPage']; $i++) {
+                    $temp = $this->record($mid, $start, $end, $i);
+                    if ($temp) {
+                        $data = array_merge($data, $temp);
+                    }
+                }
+            }
+            return $data;
+        }
+        return array();
+    }
+
+    # 提现
+    public function tixian($config, $merchant, $info, $auto = 1)
+    {
+    	$url = $this->host() . 'uisouterfront/withdrawback/process';
+
+    	$mid = $merchant['mid'];
+    	$order_num = $info['order_num'];
+		$cash = $info['cash'];
+		$notify = Dever::url('yspay/single.notify?order=' . $info['order_num'], 'pay');
+
+    	//整理内容信息
+        $content = [
+            'sysId' => $this->sys_id,
+            'mchntNo' => $mid,
+            'timestamp' => date('YmdHis'),
+            'sysOrderId' => $order_num
+            'responseUrl' => $notify,
+            'withdrawType' => 2,
+            'withdrawAmt' => $cash,
+        ];
+        Dever::log($content, 'yspay_single_tixian');
+        $data['merchant_id'] = $merchant['id'];
+        $data['mid'] = $mid;
+        $data['order_num'] = $order_num;
+        $data['type'] = 2;
+        $data['cash'] = $cash;
+        $data['tdate'] = time();
+        $data['status'] = 1;
+        $data['desc'] = '';
+        $data['mtype'] = $auto;
+        Dever::db('pay/yspay_tixian_log')->insert($data);
+        //设置签名并加密
+        $body['content'] = $this->createSignature($content);
+
+        $result = Dever::curl($url, $body, 'post');
+        $decryptData = $this->privateDecrypt($result);
+        if (isset($decryptData['responseCode']) && ($decryptData['responseCode'] == '000000' || $decryptData['responseCode'] == '000001')) {
+        	return 'ok';
+        } else {
+            if ($decryptData['responseDesc'] == '订单号已存在' && $info && isset($info['id'])) {
+                Dever::db('pay/yspay_cash')->update(array('where_id' => $info['id'], 'status' => 3));
+            }
+        	return $decryptData['responseDesc'];
+        }
+    }
+
+    /**
+     * 私钥解密
+     * @Author Abnermouke <abnermouke@gmail.com>
+     * @Originate in Abnermouke's MBP
+     * @Time 2021-08-26 16:36:58
+     * @param $encryptData
+     * @return string
+     */
+    public function privateDecrypt($encryptData)
+    {
+        $content = pack('H*', $encryptData);
+        $result = '';
+        foreach (str_split($content, 256) as $block) {
+            openssl_private_decrypt($block, $dataDecrypt, $this->formatRsaKey($this->private_key_pkcs1), OPENSSL_PKCS1_PADDING);
+            $result .= $dataDecrypt;
+        }
+        $result = Dever::json_decode($result);
+        return $result;
+    }
+
+    /**
+     * 创建签名
+     * @Author Abnermouke <abnermouke@gmail.com>
+     * @Originate in Abnermouke's MBP
+     * @Time 2021-08-26 16:34:49
+     * @param $body
+     * @return false|string
+     */
+    private function createSignature($body)
+    {
+        //重新排序信息
+        ksort($body);
+        //整理加密字符串
+        $signature_string = '';
+        //循环数据
+        foreach ($body as $key => $value) {
+            //整合字符串
+            $signature_string .= $key.'='.$value.'&';
+        }
+        //整理加密字符串
+        $signature_string = rtrim($signature_string, '&');
+        //echo $signature_string;
+        //获取加密数组
+        $array_json = $this->rsaEncrypt($signature_string);
+        //设置签名
+        $body['sign'] = bin2hex($array_json);
+
+        //print_r($body);
+        //json序列化
+        $json_data = json_encode($body);
+        //加密RSA
+        $json_rsa = $this->publicRsa($json_data);
+        //返回结果
+        return $json_rsa;
+    }
+
+    /**
+     * 私钥加密
+     * @Author Abnermouke <abnermouke@gmail.com>
+     * @Originate in Abnermouke's MBP
+     * @Time 2021-08-26 16:35:08
+     * @param string $str
+     * @return false
+     */
+    private function rsaEncrypt($str=''){
+        $charSet = mb_detect_encoding($str, ["UTF-8", "GB2312", "GBK"]);
+        $str = mb_convert_encoding($str, "UTF-8", $charSet);
+        $pri_key = $this->private_key;
+        $pri_key = $this->formatRsaKey($pri_key, 'RSA PRIVATE');
+        $pi_key = openssl_pkey_get_private($pri_key);
+        if(!$pi_key) return false;
+        $algo = "SHA256";
+        openssl_sign($str, $binary_signature, $pi_key, $algo);
+        return $binary_signature;
+    }
+
+    /**
+     * 公钥加密
+     * @Author Abnermouke <abnermouke@gmail.com>
+     * @Originate in Abnermouke's MBP
+     * @Time 2021-08-26 16:35:14
+     * @param string $str
+     * @return false|string
+     */
+    private function publicRsa($str='')
+    {
+        $charSet = mb_detect_encoding($str, ["UTF-8", "GB2312", "GBK"]);
+        $str = mb_convert_encoding($str, "UTF-8", $charSet);
+        $pub_key = $this->public_key;
+        $pub_key = $this->formatRsaKey($pub_key, 'PUBLIC');
+        $pu_key = openssl_pkey_get_public($pub_key);
+        if(!$pu_key)  return false;
+        $result = '';
+        foreach (str_split($str,245) as $chunk) {
+            if(openssl_public_encrypt($chunk,$encryptData, $pub_key)){
+                $result .= $encryptData;
+            }
+        }
+        $result = bin2hex($result);
+        openssl_free_key($pu_key);
+        return $result;
+    }
+
+    /**
+     * 格式化密钥
+     * @Author Abnermouke <abnermouke@gmail.com>
+     * @Originate in Abnermouke's MBP
+     * @Time 2021-08-26 16:36:36
+     * @param $key
+     * @param string $alias
+     * @param int $length
+     * @return string
+     */
+    private function formatRsaKey($key, $alias = 'RSA PRIVATE', $length = 64)
+    {
+        //拆分格式
+        $key = chunk_split($key, (int)$length, "\n");
+        //生成pem
+        $pem = "-----BEGIN $alias KEY-----\n".$key."-----END $alias KEY-----";
+        //返回pem
+        return $pem;
+    }
+
+}

+ 82 - 0
yspay/Cash.php

@@ -0,0 +1,82 @@
+<?php namespace Pay\Yspay;
+use Dever;
+
+class Cash
+{
+	# 入账:待确认
+    public function add($order_id, $order, $info)
+    {
+    	$mid = $info['mid'];
+    	$merchant = Dever::db('pay/yspay_merchant')->one(array('mid' => $mid));
+    	if ($merchant) {
+    		$per = $merchant['per'];
+    		if (!$per) {
+    			$yspay = Dever::db('pay/yspay')->one(array('account_id' => $merchant['account_id']));
+    			if ($yspay && $yspay['per']) {
+    				$per = $yspay['per'];
+    			}
+    		}
+    		if (!$per || $per <= 0) {
+    			$per = 0;
+    		} else {
+    			$per = $per/100;
+    		}
+    		
+			$data['merchant_id'] = $merchant['id'];
+    		$data['order_num'] = $info['merOrderId'];
+	        $data['source_order_num'] = $order_id;
+	        $data['cash'] = $info['amount'];
+	        $data['fz_cash'] = round($data['cash']*$per, 2);
+	        $data['hf_cash'] = round($data['cash'] - $data['fz_cash'], 2);
+	        $data['status'] = 1;
+	        $id = Dever::db('pay/yspay_cash')->insert($data);
+	        return $id;
+    	}
+    	return false;
+    }
+
+    # 修改状态
+    public function up($order_id, $status = 2)
+    {
+    	$where['source_order_num'] = $order_id;
+    	$info = Dever::db('pay/yspay_cash')->find($where);
+    	if ($info) {
+    		$update = array('status' => $status, 'where_id' => $info['id']);
+    		if ($status == 3) {
+    			# 开始分账和划付
+    			$state = $this->tixian($info);
+    			if ($state != 'ok') {
+    				return false;
+    			}
+    			$update['rdate'] = time();
+    		}
+    		$state = Dever::db('pay/yspay_cash')->update($update);
+    		if ($state) {
+    			if ($status == 3) {
+    				$total = Dever::db('pay/yspay_cash')->getTotal(array('status' => 3, 'merchant_id' => $info['merchant_id']));
+    				if ($total) {
+    					Dever::db('pay/yspay_merchant')->update(array('where_id' => $info['merchant_id'], 'cash' => $total['cash'], 'hf_cash' => $total['hf_cash'], 'fz_cash' => $total['fz_cash']));
+    				}
+    			}
+    			return $state;
+    		}
+    	}
+    	return false;
+    }
+
+    private function tixian($info)
+    {
+    	$merchant = Dever::db('pay/yspay_merchant')->one($info['merchant_id']);
+    	if ($merchant) {
+    		$config = Dever::db('pay/yspay')->one(array('account_id' => $merchant['account_id']));
+    		if ($config) {
+    			return Dever::load('pay/yspay/multi')->huafu($config, $merchant, $info);
+    		}
+    	}
+
+    	return false;
+    }
+
+    # 定时获取总额
+
+}

+ 43 - 0
yspay/Merchant.php

@@ -0,0 +1,43 @@
+<?php namespace Pay\Yspay;
+use Dever;
+
+class Merchant
+{
+    public function selectRelate_api()
+    {
+        $value = Dever::input('value');
+        $id = Dever::input('id');
+        $data = array();
+        if ($id) {
+            $data = Dever::db('pay/yspay_merchant')->find($id);
+            if ($value != $data['project_id']) {
+                $data['relate_id'] = -1;
+            }
+        }
+        
+        $config['relate_id'] = Dever::db('pay/yspay_merchant')->config['struct']['relate_id'];
+        $config['relate_id']['update'] = 'select';
+        $config['relate_id']['update_search'] = 'pay/yspay/merchant.search?project_id=' . $value;
+
+        $result = Dever::load('manage/database')->update_struct(array('struct' => $config), false, $data, -1, '', true);
+
+        return $result;
+    }
+
+    public function search_api()
+    {
+        $id = Dever::input('id');
+        $keyword = Dever::input('keyword');
+        $where = array();
+        if ($keyword) {
+            $where['name'] = $keyword;
+        }
+        $id = Dever::input('where_id');
+        if ($id) {
+            $where['id_no'] = $id;
+        }
+        $project_id = Dever::input('project_id', 1);
+        $project = Dever::db('pay/yspay_project')->find($project_id);
+        return Dever::search($project['table'], $where);
+    }
+}

+ 190 - 0
yspay/Multi.php

@@ -0,0 +1,190 @@
+<?php namespace Pay\Yspay;
+use Dever;
+use Dever\Http\Curl;
+# 银联商务商户资金自主管理系统
+class Multi
+{
+	static $test_host = 'https://mobl-test.chinaums.com/channel/Business/UnifyMulti/';
+	static $host = 'https://cloudpay.chinaums.com/channel/Business/UnifyMulti/';
+
+	# 划付
+    public function huafu($config, $merchant, $info, $auto = 1)
+    {
+    	$this->config = $config;
+
+    	$mid = $merchant['mid'];
+    	$cash = $info['tx_cash'];
+    	$order_num = $info['order_num'];
+
+    	//整理内容信息
+        $content = [
+            'merNo' => $mid,
+            'merOrderNo' => $order_num,
+            'payAmt' => $cash,
+        ];
+        Dever::log($content, 'yspay_huafu');
+        $result = $this->curl('202001', $content);
+        if ($result == 'ok') {
+        	$data['status'] = 1;
+        } else {
+        	$data['status'] = 3;
+        	$data['error'] = $result; 
+        }
+
+        $data['merchant_id'] = $merchant['id'];
+        $data['mid'] = $mid;
+        $data['order_num'] = $order_num;
+        $data['type'] = 1;
+        $data['cash'] = $cash;
+        $data['tdate'] = time();
+        $data['desc'] = $content['ps'];
+        $data['auto'] = $auto;
+        Dever::db('pay/yspay_cash_log')->insert($data);
+
+        $this->fenzhang($config, $merchant, $info, $auto);
+
+        return 'ok';
+    }
+
+    # 分账
+    public function fenzhang($config, $merchant, $info, $auto = 1)
+    {
+    	$this->config = $config;
+
+    	$mid = $this->config['mid'];
+    	$cash = $info['fz_cash'];
+    	if (!$cash || $cash <= 0) {
+    		return;
+    	}
+    	$order_num = $info['order_num'];
+
+    	//整理内容信息
+        $content = [
+            'merNo' => $mid,
+            'merOrderNo' => $order_num,
+            'payAmt' => $cash,
+            'cardNo' => hash("sha256",$this->config['card']),
+            'ps' => $merchant['name'] . '分账',
+        ];
+        Dever::log($content, 'yspay_fenzhang');
+        $result = $this->curl('202003', $content);
+        if ($result == 'ok') {
+        	$data['status'] = 1;
+        } else {
+        	$data['status'] = 3;
+        	$data['error'] = $result; 
+        }
+
+        $data['merchant_id'] = $merchant['id'];
+        $data['mid'] = $mid;
+        $data['order_num'] = $order_num;
+        $data['type'] = 2;
+        $data['cash'] = $cash;
+        $data['tdate'] = time();
+        $data['desc'] = $content['ps'];
+        $data['auto'] = $auto;
+        Dever::db('pay/yspay_cash_log')->insert($data);
+    }
+
+	protected function header($code)
+    {
+        $header = array(
+            'transCode' => $code,
+            'verNo' => '100',
+            'srcReqDate' => date("Ymd"),
+            'srcReqTime' => date("His"),
+            'srcReqId' => Dever::uuid(),
+            'channelId' => '043',
+            'groupId' => config('param.groupId'),
+        );
+
+        return $header;
+    }
+
+	protected function curl($code, $param, $state = true)
+	{
+		$url = $this->config['box'] == 1 ? self::$host : self::$test_host;
+		$url .= $code;
+
+    	$header = $this->header($code);
+    	$header['signature'] = $this->sign($param);
+    	$curl = Curl::getInstance($url, $param, 'post', true, $header)->setResultHeader(true);
+    	$header = $curl->header();
+		$body = $curl->result();
+
+		if (strstr($body, '<html><head>')) {
+			return 'error';
+		}
+		$body = Dever::json_decode($body);
+		if (isset($header['respCode'])) {
+			if ($header['respCode'] == '99999999') {
+				return $state ? 'ok' : $body;
+			} else {
+				return $header['respMsg'];
+			}
+		} else {
+			return 'error';
+		}
+	}
+
+	protected function sign($data)
+	{
+		$data = $this->getParams($data);
+		$file = $this->config['file_cert'];
+		if(!file_exists($file)) {
+            Dever::alert('private_key not exit');
+        }
+		$pkcs12 = file_get_contents($file);
+		openssl_pkcs12_read($pkcs12, $certs, $this->config['key']);
+		if (!$certs) {
+            Dever::alert('private_key error');
+        }
+        $privateKey = $certs['pkey']; 
+		if (openssl_sign(utf8_encode($data), $binarySignature, $privateKey, OPENSSL_ALGO_SHA256)) {
+            return bin2hex($binarySignature);
+        } else {
+            return '';
+        }
+	}
+
+	protected function checkSign($data, $signature)
+	{
+		$file = $this->config['file_key'];
+		if(!file_exists($file)) {
+            Dever::alert('public_key not exit');
+        }
+		$cert = file_get_contents($file);
+        $cert = '-----BEGIN CERTIFICATE-----' . PHP_EOL
+            . chunk_split(base64_encode($cert), 64, PHP_EOL)
+            . '-----END CERTIFICATE-----' . PHP_EOL;
+        $pubKeyId = openssl_get_publickey($cert);
+        $signature = hex2bin($signature);
+        $ok = openssl_verify($data, $signature, $pubKeyId, OPENSSL_ALGO_SHA256);
+
+        if ($ok == 1) {
+            openssl_free_key($pubKeyId);
+            return true;
+        }
+        return false;
+	}
+
+	protected function getParams($param)
+	{
+		ksort($param);
+		$result = array();
+		foreach ($param as $k => $v) {
+			if (is_array($v)) {
+                $v = json_encode($v, JSON_UNESCAPED_UNICODE);
+            } elseif(trim($v) == ""){
+                continue;
+            }
+            if (is_bool($v)) {
+                $result[] = $v ? "$k=true" : "$k=false";
+            } else {
+                $result[] = $k . '=' . $v;
+            }
+		}
+		$result = implode('&', $result);
+        return $result;
+	}
+}

+ 552 - 0
yspay/Sign.php

@@ -0,0 +1,552 @@
+<?php
+namespace Pay\Yspay;
+use Dever;
+header("Content-Type:text/html;charset=utf-8");
+Class Sign
+{
+	static $key = "o5ho739mgrphdm28g5rwx1nw";
+	static $accesser_id = '2d9081bd7db8ad75017dbbe68981314f';
+	private $url = 'https://yinshangpai.chinaums.com/self-contract-nmrs/interface/autoReg/';
+
+	static $sign_type = 'SHA-256';
+	private $test = 2;
+	
+	//private $product_id = array('0','1','in1','in2','in3','in4');
+	private $product_id = array('0');
+	private $document_type = array
+	(
+		'idcard_front' => ['document_type' => '0001','document_name' => '身份证正面'],
+		'idcard_back' => ['document_type' => '0011','document_name' => '身份证反面'],
+		'license' => ['document_type' => '0002','document_name' => '营业执照'],
+		'tax' => ['document_type' => '0003','document_name' => '税务登记证'],
+		'door' => ['document_type' => '0005','document_name' => '门头照'],
+		'hand_idcard' => ['document_type' => '0007','document_name' => '手持身份证自拍照'],
+		'open' => ['document_type' => '0006','document_name' => '开户许可证'],
+		'bank_fount' => ['document_type' => '0025','document_name' => '银行卡正面照'],
+		'bank_back' => ['document_type' => '0026','document_name' => '银行卡反面照'],
+		'house_pic' => ['document_type' => '0015','document_name' => '室内照片'],
+		'screen_pic' => ['document_type' => '0034','document_name' => '商户网站/APP截图'],
+	);
+
+	public function update($id, $name, $data)
+    {
+        $cash = Dever::param('cash', $data);
+        $sign = Dever::db('pay/yspay_sign')->find($id);
+        if ($cash && $cash > 0) {
+            $this->account_check($sign, $cash);
+        }
+    }
+
+	# 计划任务
+	public function cron_api()
+	{
+		$where['step'] = '4,5';
+		$data = Dever::db('pay/yspay_sign')->getData($where);
+		if ($data) {
+			foreach ($data as $k => $v) {
+				$this->check($v);
+			}
+		}
+		return 'ok';
+	}
+
+	# 获取合同链接
+	public function getAgreement_api($sign_id)
+	{
+		$sign = Dever::db('pay/yspay_sign')->find($sign_id);
+		return $this->agreement($sign, false);
+	}
+
+	# 获取当前状态
+	public function getStatus_api($sign_id)
+	{
+		$sign = Dever::db('pay/yspay_sign')->find($sign_id);
+		return $this->check($sign);
+	}
+
+	# 获取最新一条日志
+	public function getLog($sign_id, $status)
+	{
+		if ($status == 1) {
+			return '签约已完成';
+		}
+		$sign = Dever::db('pay/yspay_sign')->find($sign_id);
+		$log = Dever::db('pay/yspay_sign_log')->find(array('merchant_id' => $sign['merchant_id']));
+		if ($log) {
+			$date = date('Y-m-d H:i', $log['cdate']);
+			$step = Dever::db('pay/yspay_sign_log')->config['step'][$log['step']];
+			return $date . '<br />' . $step . '<br />' . $log['desc'];
+		} else {
+			return '待提交资料';
+		}
+	}
+
+	# 获取日志列表
+	public function getLogList($sign_id)
+	{
+		$sign = Dever::db('pay/yspay_sign')->find($sign_id);
+		if (!$sign) {
+			return Dever::timeline('填写资料');
+		}
+		$result = array();
+		
+		$log = Dever::db('pay/yspay_sign_log')->select(array('merchant_id' => $sign['merchant_id']));
+		if ($log) {
+			foreach ($log as $k => $v) {
+				if ($v['step'] == 4) {
+					//$v['response'] = Dever::json_decode($v['response']);
+					$url = $this->agreement($sign, false);
+					$v['desc'] .= '  <a href="'.$url.'" target="_blank">点此打开</a>  <a style="cursor:pointer" data-clipboard-text="'.$url.'" class="clipboard">复制链接</a>';
+				}
+				$date = date('Y-m-d H:i', $v['cdate']);
+				$name = '';
+				if ($v['admin_id'] > 0) {
+					$admin = Dever::db('manage/admin')->find($v['admin_id']);
+					if ($admin) {
+						$name = '[' . $admin['username'] . ']&nbsp;&nbsp;';
+					}
+				}
+				$result[] = $date . '&nbsp;&nbsp;' . $name . ''. $v['desc'];
+			}
+		}
+
+		if ($sign['step'] == -1) {
+			$url = Dever::url('pay/yspay/sign.handle?sign_id=' . $sign['id'] . '&json=1');
+			$result[] = '<a href="javascript:;" onclick="load(\''.$url.'\')">点此上传资料</a>';
+		}
+
+		$result = Dever::timeline('签约记录', $result);
+		return $result;
+	}
+
+	# 统一处理接口
+	public function handle_api($sign_id)
+	{
+		$sign = Dever::db('pay/yspay_sign')->find($sign_id);
+		if (!$sign) {
+			Dever::alert('档案资料未上传');
+		}
+		$sign['bank_acct_no'] = str_replace(' ', '', $sign['bank_acct_no']);
+		switch($sign['step']) {
+			case -1:
+				# 提交资料
+				return $this->up($sign);
+				break;
+			case 1:
+			case 6:
+				if ($sign['bank_acct_type'] == 1) {
+					# 对公打款
+					return $this->account($sign);
+				} else {
+					# 签约
+					return $this->agreement($sign);
+				}
+				break;
+			case 2:
+				# 打款验证
+				return $this->account_check($sign);
+				break;
+			case 4:
+			case 5:
+				# 验证签约
+				return $this->check($sign);
+				break;
+			case 6:
+				# 签约成功,变更签约?
+				return '签约已成功,后续可以变更签约';
+				return $this->up($sign);
+				break;
+		}
+		return 'ok';
+	}
+
+	# 上传图片
+	public function upload_api()
+	{
+		$document_type = $this->document_type;
+		$key = Dever::input('key');
+		$upload = Dever::json_decode(Dever::input('upload'));
+		if ($upload && isset($document_type[$key]) && isset($upload['url'])) {
+			$url = md5($upload['url']);
+			$sign_pic = Dever::db('pay/yspay_sign_pic')->find(array('key' => $key, 'url' => $url));
+			if (!$sign_pic) {
+				$pic = $this->pic($upload['url']);
+				if ($pic && isset($pic['data']['file_path']) && $pic['data']['file_path']) {
+					$insert = array();
+					$insert['url'] = $url;
+					$insert['document_type'] = $document_type[$key]['document_type'];
+					$insert['document_name'] = $document_type[$key]['document_name'];
+					$insert['key'] = $key;
+					$insert['path'] = Dever::json_encode($pic['data']);
+					Dever::db('pay/yspay_sign_pic')->insert($insert);
+				}
+			}
+		}
+		return 'ok';
+	}
+
+	#3.2  详细采集档案资料上传接口
+	private function up($sign)
+	{
+		$service = 'complex_upload';
+		$data['remark'] = '线上支付商户';
+		$data['accesser_user_id'] = $sign['id'];
+		if ($sign['reg_mer_type'] == 1) {
+			$sign['reg_mer_type'] = '00';
+		} elseif ($sign['reg_mer_type'] == 2) {
+			$sign['reg_mer_type'] = '01';
+		} elseif ($sign['reg_mer_type'] == 3) {
+			$sign['reg_mer_type'] = '02';
+		}
+		$data['reg_mer_type'] = $sign['reg_mer_type'];#注册类型
+		$data['legal_name'] = $sign['name'];#法人姓名
+		$data['legal_idcard_no'] = $sign['idcard'];#法人身份证号
+		$data['legal_mobile'] = $sign['mobile'];#法人手机号
+		$data['legal_card_deadline'] = $sign['card_deadline'] == '长期' ? '9999-12-31' : date('Y-m-d',$sign['card_deadline']);#证件截止代表日期
+		$data['shop_name'] = $sign['name'];#店铺名称
+		if ($sign['bank_acct_type'] == -1) {
+			$data['bank_acct_type'] = 0;
+			$data['bank_acct_name'] = $sign['name'];#开户账号名称
+		} else {
+			$data['bank_acct_type'] = 1;
+			$data['bank_acct_name'] = $sign['company_name'];#开户账号名称
+		}
+
+		$data['bank_acct_no'] = $sign['bank_acct_no'];#开户行账号
+		$data['mccCode'] = $sign['mccCode'];
+
+		$area = explode(',', $sign['area']);
+		$data['shop_province_id'] = $area[0]/10000;
+		$data['shop_city_id'] = $area[1]/100;
+		$data['shop_country_id'] = $area[2];
+		$sign_area = explode(',',$sign['area']);
+		$data['shop_lic'] = $sign['license_number'];#营业执照号
+		$bank = $this->bank_list($sign_area[0]/10000, $sign['bank_acct_noname']);
+		if($bank && isset($bank['branchBankList']) && $bank['branchBankList']){
+			$bank['branchBankList'] = $bank['branchBankList'][0];
+			$in['where_id'] = $sign['id'];
+			$in['bank_no'] = $bank['branchBankList']['code'];
+			$in['shop_addr_ext'] =  $bank['branchBankList']['bankBranchName'];
+			Dever::db('pay/yspay_sign')->update($in);
+			$data['bank_no'] = $bank['branchBankList']['code'];
+			$data['shop_addr_ext'] = $bank['branchBankList']['bankBranchName'];
+		} else {
+			return $this->log(1, $sign, '开户行行号不存在');
+		}
+		if ($sign['reg_mer_type'] == '00' && $sign['bank_acct_type'] != '1') {
+			return $this->log(1, $sign, '账户类型不正确1');
+		}
+		if ($sign['legalmanHomeAddr']) { 
+			$data['legalmanHomeAddr'] = $sign['legalmanHomeAddr'];
+		} 
+		$document_type = $this->document_type;
+
+		foreach ($document_type as $k => $v) {
+			if (isset($sign[$k]) && $sign[$k]) {
+				$sign[$k] = Dever::pic($sign[$k]);
+				$url = md5($sign[$k]);
+				$sign_pic = Dever::db('pay/yspay_sign_pic')->find(array('key' => $k, 'url' => $url));
+				if (!$sign_pic) {
+					$pic = $this->pic($sign[$k]);
+					if ($pic && isset($pic['data']['file_path']) && $pic['data']['file_path']) {
+						$insert = array();
+						$insert['url'] = $url;
+						$insert['document_type'] = $v['document_type'];
+						$insert['document_name'] = $v['document_name'];
+						$insert['key'] = $k;
+						$insert['path'] = Dever::json_encode($pic['data']);
+						Dever::db('pay/yspay_sign_pic')->insert($insert);
+						$data['pic_list'][] = array('document_name' => $v['document_name'], 'document_type' => $v['document_type'] , 'file_path'=> $pic['data']['file_path'], 'file_size'=>$pic['data']['file_size']);
+					}
+				} else {
+					$pic = Dever::json_decode($sign_pic['path']);
+					$data['pic_list'][] = array('document_name' => $sign_pic['document_name'], 'document_type' => $sign_pic['document_type'] , 'file_path'=> $pic['file_path'], 'file_size'=>$pic['file_size']);
+				}
+			}
+		}
+		$ids = $this->product_id;
+		$data['product'] = array();
+		foreach ($ids as $k => $v) {
+			$data['product'][$k] = ['product_id' => $v]; 
+		}
+		$result = $this->get($service, $data);
+		if ($result && $result['code'] == 1 && isset($result['data']['ums_reg_id']) && $result['data']['ums_reg_id']) {
+			$update = array();
+			$update['where_id'] = $sign['id'];
+			$sign['ums_reg_id'] = $update['ums_reg_id'] = $result['data']['ums_reg_id'];
+			Dever::db('pay/yspay_sign')->update($update);
+			$this->log(1, $sign, '资料上传成功', $data, $result['data'], $result['request_seq']);
+			if ($data['bank_acct_type'] == 1) {
+				return $this->account($sign);
+			} else {
+				return $this->agreement($sign);
+			}
+		} else {
+			$this->log(1, $sign, $result['msg'], $data, $result['data'], $result['request_seq']);
+		}
+		return Dever::input('json') == 1 ? 'reload' : $result;
+	}
+
+	# 3.7  发起对公账户验证交易接口
+	public function account($sign)
+	{
+		$step = 2;
+		$service = 'request_account_verify';
+		$data['ums_reg_id'] = $sign['ums_reg_id'];
+		$data['company_account'] = $sign['bank_acct_no'];
+		$result = $this->get($service, $data);
+		if ($result && $result['code'] == 1 && isset($result['data']['request_seq']) && $result['data']['request_seq']) {
+			$update = array();
+			$update['where_id'] = $sign['id'];
+			$update['step'] = $step;
+			$update['clear'] = true;
+			Dever::db('pay/yspay_sign')->update($update);
+			$this->log($update['step'], $sign, '公户打款成功', $data, $result['data'], $result['request_seq']);
+		} else {
+			$this->log($step, $sign, $result['msg'], $data, $result['data'], $result['request_seq']);
+		}
+		return Dever::input('json') == 1 ? 'reload' : $result;
+	}
+
+	# 3.6  对公账户认证接口
+	public function account_check($sign, $num)
+	{
+		$step = 3;
+		$trans_amt = $num;
+		$service = 'company_account_verify';
+		$data['ums_reg_id'] = $sign['ums_reg_id'];
+		$data['company_account'] = $sign['bank_acct_no'];
+		$data['trans_amt'] = $trans_amt;
+		$result = $this->get($service, $data, $sign['ums_reg_id']);
+		if ($result && $result['code'] == 1 && isset($result['data']['request_seq']) && $result['data']['request_seq']) {
+			$update = array();
+			$update['where_id'] = $sign['id'];
+			$update['step'] = $step;
+			$update['clear'] = true;
+			Dever::db('pay/yspay_sign')->update($update);
+			$this->log($update['step'], $sign, '公户对账成功', $data, $result['data'], $result['request_seq']);
+			return $this->agreement($sign);
+		} else {
+			$this->log($step, $sign, $result['msg'], $data, $result['data'], $result['request_seq']);
+		}
+		return $result;
+	}
+
+	# 3.3  前台签约接口
+	public function agreement($sign, $log = true)
+	{
+		$step = 4;
+		$service = 'agreement_sign';
+		$data['ums_reg_id'] = $sign['ums_reg_id'];
+		$data['pcOrH5'] = 'H5';
+		$result = $this->get($service, $data);
+		if ($result && $result['code'] == 1 && isset($result['data']['url']) && $result['data']['url']) {
+			
+			$update = array();
+			$update['where_id'] = $sign['id'];
+			$update['step'] = $step;
+			$update['url'] = $result['data']['url'];
+			$update['clear'] = true;
+			Dever::db('pay/yspay_sign')->update($update);
+			if ($log) {
+				$this->log($update['step'], $sign, '请复制链接进行合同签署', $data, $result['data'], $result['request_seq']);
+			} else {
+				return $update['url'];
+			}
+		} else {
+			$this->log($step, $sign, $result['msg'], $data, $result['data'], $result['request_seq']);
+		}
+		return Dever::input('json') == 1 ? 'reload' : $result;
+	}
+
+	# 3.4  入网状态查询接口
+	public function check($sign)
+	{
+		$step = 5;
+		$service = 'apply_qry';
+		$data['ums_reg_id'] = $sign['ums_reg_id'];
+		$result = $this->get($service, $data, $sign['ums_reg_id']);
+		if ($result && $result['code'] == 1 && isset($result['data']['apply_status'])) {
+			if ($result['data']['apply_status'] == '03') {
+				$step = 6;
+			}
+			$update = array();
+			$update['where_id'] = $sign['id'];
+			$update['step'] = $step;
+			$update['clear'] = true;
+			if ($result['data']['apply_status'] == '03' && isset($result['data']['mer_no']) && $result['data']['mer_no']) {
+				$update['mid'] = $result['data']['mer_no'];
+			}
+			Dever::db('pay/yspay_sign')->update($update);
+			$this->log($update['step'], $sign, $result['data']['apply_status_msg'], $data, $result['data'], $result['request_seq']);
+		} else {
+			$this->log($step, $sign, $result['data']['apply_status_msg'], $data, $result['data'], $result['request_seq']);
+		}
+		return $result;
+	}
+
+	private function encrypt($data='', $key='', $use3des = true)
+	{
+		$key = self::$key;
+		$res = bin2hex(openssl_encrypt($data, 'DES-EDE3', $key, OPENSSL_RAW_DATA));
+		return $res;
+	}
+
+	private function decrypt($data='', $key='', $use3des = true)
+	{
+		$key = self::$key;
+		return openssl_decrypt(pack('H*',$data), 'DES-EDE3', $key, OPENSSL_RAW_DATA);
+	}
+
+	private function get($service, $data)
+	{
+		$accesser_id = self::$accesser_id;
+		$sign_type = self::$sign_type;
+		$param = $data;
+		$param['service'] = $service;
+		$param['sign_type'] = $sign_type;
+		$param['accesser_id'] = $accesser_id;
+		$param['request_date'] = date('YmdHis');
+		$param['request_seq'] = Dever::order();
+		$sign_data = json_encode($param, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
+		$send['json_data'] = $this->encrypt($sign_data);
+		$send['sign_data'] = hash('sha256', $sign_data);
+		$send['accesser_id'] = $accesser_id;
+		$url = $this->url;
+
+		$result = array();
+		$result['request_seq'] = $param['request_seq'];
+		$result['code'] = 2;
+		$result['msg'] = '请求失败';
+		$result['data'] = array();
+
+		if ($service == 'agreement_sign') {
+			$result['code'] = 1;
+			$result['msg'] = '请求成功';
+			$result['data']['url'] = $url . '?' . http_build_query($send);
+			return $result;
+		}
+		if ($this->test != 1) {
+			$response = Dever::curl($url, $send, 'post');
+		} else {
+			# 数据模拟
+			$response = $this->data($service, $param);
+		}
+		$result['data'] = $response;
+
+		if ($response) {
+			$response = Dever::json_decode($response);
+			if (isset($response['res_code']) && ($response['res_code'] == '0000' || $response['res_code'] == '1446')) {
+				$result['code'] = 1;
+				$result['msg'] = '请求成功';
+				$result['data'] = $response;
+			} elseif (isset($response['res_msg']) && $response['res_msg']) {
+				$result['code'] = 2;
+				$result['msg'] = $response['res_msg'];
+				$result['data'] = $response;
+			} elseif (isset($response['apply_status_msg']) && $response['apply_status_msg']) {
+				$result['code'] = 2;
+				$result['msg'] = $response['apply_status_msg'];
+				$result['data'] = $response;
+			}
+		}
+		
+		return $result;
+	}
+
+	private function data($service, $data)
+	{
+		$result = array();
+		$result['res_code'] = '0000';
+		$result['res_msg'] = 'ok';
+		$result['request_seq'] = $data['request_seq'];
+
+		if ($service == 'pic_upload') {
+			$result['file_path'] = $data['request_seq'];
+			$result['file_type'] = 'jpg';
+			$result['file_size'] = strlen($result['file_path']);
+		} elseif ($service == 'complex_upload') {
+			$result['ums_reg_id'] = $data['request_seq'];
+		} elseif ($service == 'agreement_sign') {
+			$result['url'] = 'https://www.baidu.com/';
+		} elseif ($service == 'apply_qry') {
+			$result['apply_status'] = '03';
+			$result['apply_status_msg'] = '入网成功(最终成功状态)';
+		} elseif ($service == 'branch_bank_list') {
+			$result['branchBankList'][] = array('code' => '308100005607', 'bankBranchName' => '招商银行股份有限公司北京天通苑支行');
+		}
+
+		return Dever::json_encode($result);
+	}
+
+	private function pic($pic)
+	{
+		$service = 'pic_upload';
+		if ($pic) {
+			$pic_base64 = $this->test != 1 ? file_get_contents($pic) : 'content';
+
+			if ($pic_base64) {
+				$temp = explode('?', $pic);
+				if ($temp) {
+					$one = pathinfo($temp[0]);
+				} else {
+					$one = pathinfo($pic);
+				}
+				$data['pic_base64'] = "data:image/".$one['extension'].";base64,".base64_encode($pic_base64);
+				$result = $this->get($service, $data);
+				return $result;
+			}
+		}
+		return false;
+	}
+
+	# 查询支行
+	private function bank_list($areaCode, $key)
+	{
+		$service = 'branch_bank_list';
+		$data['areaCode'] = $areaCode;
+		$data['key'] = $key;
+		$result = $this->get($service,$data);
+		return $result['data'];
+	}
+
+	# 记录日志
+	private function log($step, $sign, $msg, $request = array(), $response = array(), $request_seq = '')
+	{
+		if (!$sign) {
+			return $msg;
+		}
+		$data['step'] = $step;
+		$data['merchant_id'] = $sign['merchant_id'];
+		$data['desc'] = $msg;
+		$info = false;
+		if ($step == 4 || $step == 5) {
+			$info = Dever::db('pay/yspay_sign_log')->find($data);
+		}
+		
+		$admin = Dever::load('manage/auth.info');
+		if ($admin) {
+			$data['admin_id'] = $admin['id'];
+		}
+		if ($request_seq) {
+			$data['request_seq'] = $request_seq;
+		}
+		if ($request) {
+			$data['request'] = Dever::json_encode($request);
+		}
+		if ($response) {
+			if (is_array($response)) {
+				$response = Dever::json_encode($response);
+			}
+			$data['response'] = $response;
+		}
+		if ($info) {
+			$data['where_id'] = $info['id'];
+			Dever::db('pay/yspay_sign_log')->update($data);
+		} else {
+			Dever::db('pay/yspay_sign_log')->insert($data);
+		}
+		
+		return $msg;
+	}
+}

+ 62 - 0
yspay/Tixian.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace Pay\Yspay;
+
+use Dever;
+
+class Tixian
+{
+    #生成订单号
+    public function getOrderId()
+    {
+        $where['order_num'] = Dever::order('TX');
+        $where['clear'] = true;
+        $state = Dever::db('pay/yspay_tixian_log')->one($where);
+        if (!$state) {
+            return $where['order_num'];
+        } else {
+            return $this->getOrderId();
+        }
+    }
+
+    public function insert($id, $name, $data)
+    {
+        $merchant_id = Dever::param('merchant_id',$data);
+        $cash = Dever::param('cash',$data);
+        $desc = Dever::param('desc',$data);
+        $account = Dever::db('shop/yspay_merchant')->one($merchant_id);
+        if (!$account) {
+        	Dever::alert('账户不存在');
+        }
+        if ($cash <= 0) {
+        	Dever::alert('提现金额不能小于0');
+        }
+        $cash = $cash * 100;
+        if ($cash > $account['yue']) {
+        	Dever::alert('账户余额不足');
+        }
+    }
+
+    public function update($id, $name, $data)
+    {
+    	$merchant_id = Dever::param('merchant_id',$data);
+        $cash = Dever::param('cash',$data);
+        $desc = Dever::param('desc',$data);
+
+        $account = Dever::db('shop/yspay_merchant')->one($merchant_id);
+        if (!$account) {
+        	Dever::alert('账户不存在');
+        }
+        if ($cash <= 0) {
+        	Dever::alert('提现金额不能小于0');
+        }
+        $cash = $cash * 100;
+        if ($cash > $account['yue']) {
+        	Dever::alert('账户余额不足');
+        }
+        $order_num = $this->getOrderId();
+        $account['desc'] = $desc;
+        $account['mtype'] = 2;
+        Dever::load('pay/yspay/account')->action($account['mid'], $order_num, -1, 2, $cash, $account);
+    }
+}