| <?php
|
|
|
| class sandpay_plugin
|
| {
|
| static public $info = [
|
| 'name' => 'sandpay',
|
| 'showname' => '杉德支付',
|
| 'author' => '杉德',
|
| 'link' => 'https://www.sandpay.com.cn/',
|
| 'types' => ['alipay','wxpay','bank'],
|
| 'transtypes' => ['bank'],
|
| 'inputs' => [
|
| 'appid' => [
|
| 'name' => '商户编号',
|
| 'type' => 'input',
|
| 'note' => '',
|
| ],
|
| 'appkey' => [
|
| 'name' => '私钥证书密码',
|
| 'type' => 'input',
|
| 'note' => '',
|
| ],
|
| 'appswitch' => [
|
| 'name' => '环境选择',
|
| 'type' => 'select',
|
| 'options' => [0=>'生产环境',1=>'测试环境'],
|
| ],
|
| ],
|
| 'select_bank' => [
|
| '1' => '银联支付',
|
| '2' => '快捷支付',
|
| ],
|
| 'select' => null,
|
| 'note' => '将私钥证书命名为client.pfx(或商户编号.pfx)上传到 /plugins/sandpay/cert/',
|
| 'bindwxmp' => true,
|
| 'bindwxa' => true,
|
| ];
|
|
|
| static public function submit(){
|
| global $siteurl, $channel, $order, $sitename;
|
|
|
| if($order['typename']=='alipay'){
|
| return ['type'=>'jump','url'=>'/pay/alipay/'.TRADE_NO.'/'];
|
| }elseif($order['typename']=='wxpay'){
|
| if(strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger')!==false && $channel['appwxmp']>0){
|
| return ['type'=>'jump','url'=>'/pay/wxjspay/'.TRADE_NO.'/?d=1'];
|
| }elseif(checkmobile()==true && $channel['appwxa']>0){
|
| return ['type'=>'jump','url'=>'/pay/wxwappay/'.TRADE_NO.'/'];
|
| }else{
|
| return ['type'=>'jump','url'=>'/pay/wxpay/'.TRADE_NO.'/'];
|
| }
|
| }elseif($order['typename']=='bank'){
|
| if(in_array('2',$channel['apptype'])){
|
| return ['type'=>'jump','url'=>'/pay/fastpay/'.TRADE_NO.'/'];
|
| }else{
|
| return ['type'=>'jump','url'=>'/pay/bank/'.TRADE_NO.'/'];
|
| }
|
| }
|
| }
|
|
|
| static public function mapi(){
|
| global $siteurl, $channel, $order, $conf, $device, $mdevice;
|
|
|
| if($order['typename']=='alipay'){
|
| return self::alipay();
|
| }elseif($order['typename']=='wxpay'){
|
| if($mdevice=='wechat' && $channel['appwxmp']>0){
|
| return ['type'=>'jump','url'=>$siteurl.'/pay/wxjspay/'.TRADE_NO.'/?d=1'];
|
| }elseif($device=='mobile' && $channel['appwxa']>0){
|
| return ['type'=>'jump','url'=>$siteurl.'/pay/wxwappay/'.TRADE_NO.'/'];
|
| }else{
|
| return self::wxpay();
|
| }
|
| }elseif($order['typename']=='bank'){
|
| if(in_array('2',$channel['apptype'])){
|
| return self::fastpay();
|
| }else{
|
| return self::bank();
|
| }
|
| }
|
| }
|
|
|
|
|
| static private function qrcode($productId, $payTool){
|
| global $channel, $order, $ordername, $conf, $clientip;
|
|
|
| require(PAY_ROOT."inc/Build.class.php");
|
|
|
| $client = new SandpayCommon($channel['appid'], $channel['appkey'], $channel['appswitch']);
|
| $client->productId = $productId;
|
| $client->body = array(
|
| 'payTool' => $payTool,
|
| 'orderCode' => TRADE_NO,
|
| 'totalAmount' => str_pad(strval($order['realmoney']*100),12,'0',STR_PAD_LEFT),
|
| 'subject' => $ordername,
|
| 'body' => $ordername,
|
| 'notifyUrl' => $conf['localurl'].'pay/notify/'.TRADE_NO.'/',
|
| );
|
|
|
| return \lib\Payment::lockPayData(TRADE_NO, function() use($client) {
|
| $ret = $client->request('orderCreate');
|
| return $ret['qrCode'];
|
| });
|
| }
|
|
|
|
|
| static private function cashier(){
|
| global $siteurl, $channel, $order, $ordername, $conf, $clientip;
|
|
|
| require(PAY_ROOT."inc/Build.class.php");
|
|
|
| $client = new SandpayCommon($channel['appid'], $channel['appkey'], $channel['appswitch']);
|
| $client->productId = '00002000';
|
| $client->body = array(
|
| 'orderCode' => TRADE_NO,
|
| 'totalAmount' => str_pad(strval($order['realmoney']*100),12,'0',STR_PAD_LEFT),
|
| 'subject' => $ordername,
|
| 'body' => $ordername,
|
| 'notifyUrl' => $conf['localurl'].'pay/notify/'.TRADE_NO.'/',
|
| 'frontUrl' => $siteurl.'pay/return/'.TRADE_NO.'/',
|
| );
|
| $html_text = $client->form('cashierPay');
|
| return ['type'=>'html','data'=>$html_text];
|
| }
|
|
|
|
|
| static private function newh5($product_code, $pay_extra = []){
|
| global $siteurl, $channel, $order, $ordername, $conf, $clientip;
|
|
|
| require(PAY_ROOT."inc/Build.class.php");
|
| $client = new SandpayCommon($channel['appid'], $channel['appkey'], $channel['appswitch']);
|
|
|
| $param = [
|
| 'version' => '10',
|
| 'mer_no' => $channel['appid'],
|
| 'mer_order_no' => TRADE_NO,
|
| 'create_time' => date('YmdHis'),
|
| 'order_amt' => $order['realmoney'],
|
| 'notify_url' => $conf['localurl'].'pay/notify/'.TRADE_NO.'/',
|
| 'return_url' => $siteurl.'pay/return/'.TRADE_NO.'/',
|
| 'create_ip' => str_replace('.','_',$clientip),
|
| 'pay_extra' => json_encode($pay_extra),
|
| 'accsplit_flag' => 'NO',
|
| 'sign_type' => 'RSA',
|
| 'store_id' => '000000',
|
| ];
|
| $param['sign'] = $client->getSign($param);
|
| $param += [
|
| 'expire_time' => date('YmdHis', time()+30*60),
|
| 'goods_name' => $ordername,
|
| 'product_code' => $product_code,
|
| 'clear_cycle' => '1',
|
| 'jump_scheme' => 'sandcash://scpay',
|
| 'meta_option' => json_encode([["s" => "Android","n" => "wxDemo","id" => "com.pay.paytypetest","sc" => "com.pay.paytypetest"]]),
|
| ];
|
|
|
| $query = http_build_query($param);
|
|
|
| if($product_code == '02010006'){
|
| $attr = 'applet';
|
| }elseif($product_code == '02020005'){
|
| $attr = 'alipaycode';
|
| }elseif($product_code == '02010002'){
|
| $attr = 'wechatpay';
|
| }elseif($product_code == '02020002'){
|
| $attr = 'alipay';
|
| }elseif($product_code == '02000001'){
|
| $attr = 'qrcode';
|
| }elseif($product_code == '05030001'){
|
| $attr = 'fastpayment';
|
| }elseif($product_code == '06030001'){
|
| $attr = 'unionpayh5';
|
| }
|
|
|
| if($channel['appswitch'] == 1){
|
| $payurl = "https://sandcash-uat01.sand.com.cn/pay/h5/".$attr."?".$query;
|
| }else{
|
| $payurl = "https://sandcash.mixienet.com.cn/pay/h5/".$attr."?".$query;
|
| }
|
| return $payurl;
|
| }
|
|
|
|
|
| static public function alipay(){
|
| |
| |
| |
| |
|
|
| try{
|
| $code_url = self::qrcode('00000006','0401');
|
| }catch(Exception $ex){
|
| return ['type'=>'error','msg'=>'支付宝支付下单失败!'.$ex->getMessage()];
|
| }
|
|
|
| return ['type'=>'qrcode','page'=>'alipay_qrcode','url'=>$code_url];
|
|
|
| }
|
|
|
|
|
| static public function wxpay(){
|
| try{
|
| $code_url = self::qrcode('00000005','0402');
|
| }catch(Exception $ex){
|
| return ['type'=>'error','msg'=>'微信支付下单失败!'.$ex->getMessage()];
|
| }
|
|
|
| if (checkmobile()==true) {
|
| return ['type'=>'qrcode','page'=>'wxpay_wap','url'=>$code_url];
|
| }else{
|
| return ['type'=>'qrcode','page'=>'wxpay_qrcode','url'=>$code_url];
|
| }
|
| }
|
|
|
|
|
| static public function bank(){
|
| try{
|
| $code_url = self::qrcode('00000012','0403');
|
| }catch(Exception $ex){
|
| return ['type'=>'error','msg'=>'云闪付下单失败!'.$ex->getMessage()];
|
| }
|
|
|
| return ['type'=>'qrcode','page'=>'bank_qrcode','url'=>$code_url];
|
| }
|
|
|
|
|
| static public function fastpay(){
|
| if(checkmobile())
|
| $payurl = self::newh5('06030001');
|
| else
|
| $payurl = self::newh5('05030001');
|
| return ['type'=>'jump','url'=>$payurl];
|
| }
|
|
|
|
|
| static public function wxjspay(){
|
| global $siteurl, $channel, $order, $ordername, $conf, $clientip;
|
|
|
| $wxinfo = \lib\Channel::getWeixin($channel['appwxmp']);
|
| if(!$wxinfo) return ['type'=>'error','msg'=>'支付通道绑定的微信公众号不存在'];
|
|
|
| try{
|
| $tools = new \WeChatPay\JsApiTool($wxinfo['appid'], $wxinfo['appsecret']);
|
| $openid = $tools->GetOpenid();
|
| }catch(Exception $e){
|
| return ['type'=>'error','msg'=>$e->getMessage()];
|
| }
|
| $blocks = checkBlockUser($openid, TRADE_NO);
|
| if($blocks) return $blocks;
|
|
|
| $payurl = self::newh5('02010002', ["mer_app_id"=>$wxinfo['appid'],"openid"=>$openid]);
|
|
|
| return ['type'=>'jump','url'=>$payurl];
|
| }
|
|
|
|
|
| static public function wxwappay(){
|
| global $siteurl, $channel, $order, $ordername, $conf, $clientip;
|
|
|
| $wxinfo = \lib\Channel::getWeixin($channel['appwxa']);
|
| if(!$wxinfo) return ['type'=>'error','msg'=>'支付通道绑定的微信小程序不存在'];
|
|
|
| $payurl = self::newh5('02010006', ["resourceAppid"=>$wxinfo['appid'],"resourceEnv"=>""]);
|
|
|
| return ['type'=>'jump','url'=>$payurl];
|
| }
|
|
|
|
|
| static public function notify(){
|
| global $channel, $order;
|
|
|
| $sign = $_POST['sign'];
|
| $data = stripslashes($_POST['data']);
|
|
|
|
|
|
|
| require(PAY_ROOT."inc/Build.class.php");
|
|
|
| $client = new SandpayCommon($channel['appid'], $channel['appkey'], $channel['appswitch']);
|
| $verifyFlag = $client->verify($data, $sign);
|
|
|
| if($verifyFlag){
|
| $array = json_decode($data, true);
|
| if($array['head']['respCode'] == '000000'){
|
| $out_trade_no = $array['body']['orderCode'];
|
| $trade_no = $array['body']['tradeNo'];
|
| $money = $array['body']['totalAmount'];
|
| $buyer = $array['body']['accLogonNo'];
|
| if($out_trade_no == TRADE_NO){
|
| processNotify($order, $trade_no, $buyer);
|
| }
|
| return ['type'=>'html','data'=>'respCode=000000'];
|
| }
|
| }
|
| return ['type'=>'html','data'=>'respCode=020002'];
|
| }
|
|
|
|
|
| static public function return(){
|
| return ['type'=>'page','page'=>'return'];
|
| }
|
|
|
|
|
| static public function refund($order){
|
| global $channel, $conf;
|
| if(empty($order))exit();
|
|
|
| require(PAY_ROOT."inc/Build.class.php");
|
|
|
| $client = new SandpayCommon($channel['appid'], $channel['appkey'], $channel['appswitch']);
|
| $client->body = array(
|
| 'orderCode' => $order['api_trade_no'],
|
| 'oriOrderCode' => $order['trade_no'],
|
| 'refundAmount' => str_pad(strval($order['refundmoney']*100),12,'0',STR_PAD_LEFT),
|
| 'notifyUrl' => $conf['localurl'].'pay/refundnotify/'.TRADE_NO.'/',
|
| );
|
| try{
|
| $ret = $client->request('orderRefund');
|
| return ['code'=>0, 'trade_no'=>$ret['orderCode'], 'refund_fee'=>$ret['refundAmount']];
|
| }catch(Exception $ex){
|
| return ['code'=>-1,'msg'=>$ex->getMessage()];
|
| }
|
| }
|
|
|
|
|
| static public function refundnotify(){
|
| global $channel, $order;
|
|
|
| $sign = $_POST['sign'];
|
| $data = stripslashes($_POST['data']);
|
|
|
| require(PAY_ROOT."inc/Build.class.php");
|
|
|
| $client = new SandpayCommon($channel['appid'], $channel['appkey'], $channel['appswitch']);
|
| $verifyFlag = $client->verify($data, $sign);
|
|
|
| if($verifyFlag){
|
| $array = json_decode($data, true);
|
| if($array['head']['respCode'] == '000000'){
|
| $out_trade_no = $array['body']['orderCode'];
|
| $trade_no = $array['body']['tradeNo'];
|
| $money = $array['body']['totalAmount'];
|
| return ['type'=>'html','data'=>'respCode=000000'];
|
| }
|
| }
|
| return ['type'=>'html','data'=>'respCode=020002'];
|
| }
|
|
|
|
|
| static public function transfer($channel, $bizParam){
|
| if(empty($channel) || empty($bizParam))exit();
|
|
|
| require(PAY_ROOT."inc/Transfer.class.php");
|
|
|
| $client = new SandpayTransfer($channel['appid'], $channel['appkey']);
|
| try{
|
| $result = $client->agentpay($bizParam['out_biz_no'], $bizParam['payee_account'], $bizParam['payee_real_name'], $bizParam['money'], $bizParam['transfer_desc']);
|
| if (isset($result['respCode']) && $result['respCode']=='0000') {
|
| $status = $result['resultFlag'] == 0 ? 1 : 0;
|
| return ['code'=>0, 'status'=>$status, 'orderid'=>$result['sandSerial'], 'paydate'=>$result['tranDate']];
|
| }else{
|
| return ['code'=>-1, 'errcode'=>$result['respCode'], 'msg'=>'['.$result['respCode'].']'.$result['respDesc']];
|
| }
|
| }catch(Exception $ex){
|
| return ['code'=>-1, 'msg'=>$ex->getMessage()];
|
| }
|
| }
|
|
|
|
|
| static public function transfer_query($channel, $bizParam){
|
| if(empty($channel) || empty($bizParam))exit();
|
|
|
| require(PAY_ROOT."inc/Transfer.class.php");
|
|
|
| $client = new SandpayTransfer($channel['appid'], $channel['appkey']);
|
| try{
|
| $result = $client->queryOrder($bizParam['out_biz_no']);
|
| if (isset($result['respCode']) && $result['respCode']=='0000') {
|
| $status = $result['resultFlag'] == 0 ? 1 : 0;
|
| return ['code'=>0, 'status'=>$status];
|
| }else{
|
| return ['code'=>-1, 'msg'=>'['.$result['respCode'].']'.$result['respDesc']];
|
| }
|
| }catch(Exception $ex){
|
| return ['code'=>-1, 'msg'=>$ex->getMessage()];
|
| }
|
| }
|
|
|
|
|
| static public function balance_query($channel, $bizParam){
|
| if(empty($channel))exit();
|
|
|
| require(PAY_ROOT."inc/Transfer.class.php");
|
|
|
| $client = new SandpayTransfer($channel['appid'], $channel['appkey']);
|
| $out_biz_no = date("YmdHis").rand(11111,99999);
|
| try{
|
| $result = $client->queryBalance($out_biz_no);
|
| if (isset($result['respCode']) && $result['respCode']=='0000') {
|
| return ['code'=>0, 'ammount'=>$result['balance'], 'msg'=>'当前账户余额:'.$result['balance'].' 元,可用额度:'.$result['creditAmt']];
|
| }else{
|
| return ['code'=>-1, 'msg'=>'['.$result['respCode'].']'.$result['respDesc']];
|
| }
|
| }catch(Exception $ex){
|
| return ['code'=>-1, 'msg'=>$ex->getMessage()];
|
| }
|
| }
|
| } |