stanley-king 8 роки тому
батько
коміт
bb43c56b26
42 змінених файлів з 1545 додано та 34 видалено
  1. 2 2
      mobile/api/payment/alipay/alipay.config.php
  2. 0 0
      data/api/alipay/alipay.php
  3. 0 0
      data/api/alipay/alipayapi.php
  4. 0 0
      data/api/alipay/cacert.pem
  5. 1 1
      mobile/api/payment/alipay/call_back_url.php
  6. 0 0
      data/api/alipay/images/alipay.gif
  7. 0 0
      data/api/alipay/images/new-btn-fixed.png
  8. 0 0
      data/api/alipay/index.php
  9. 0 0
      data/api/alipay/key/alipay_public_key.pem
  10. 0 0
      data/api/alipay/key/rsa_private_key.pem
  11. 0 0
      data/api/alipay/lib/alipay_core.function.php
  12. 0 0
      data/api/alipay/lib/alipay_md5.function.php
  13. 0 0
      data/api/alipay/lib/alipay_notify.class.php
  14. 0 0
      data/api/alipay/lib/alipay_rsa.function.php
  15. 0 0
      data/api/alipay/lib/alipay_submit.class.php
  16. 0 0
      data/api/alipay/log.txt
  17. 1 1
      mobile/api/payment/alipay/notify_url.php
  18. 0 0
      data/api/alipay/readme.txt
  19. 585 0
      data/api/cmbpay/Cmb.class.php
  20. 29 0
      data/api/cmbpay/CmbConfig.php
  21. BIN
      data/api/cmbpay/M000001269.jks
  22. 1 0
      data/api/cmbpay/REDME.txt
  23. 9 0
      data/api/cmbpay/cmcx.php
  24. 8 0
      data/api/cmbpay/cmqx.php
  25. 10 0
      data/api/cmbpay/querySettledOrderByMerchantDate.php
  26. 10 0
      data/api/cmbpay/querySettledOrderBySettledDate.php
  27. 10 0
      data/api/cmbpay/queryTransact.php
  28. 9 0
      data/api/cmbpay/refundNoDup.php
  29. 8 0
      data/api/cmbpay/searchOneOrder.php
  30. 234 0
      data/api/cmbpay/招商一网通支付接口调用+验签.php
  31. 5 2
      data/logic/buy_1.logic.php
  32. 37 11
      helper/buy_first.php
  33. 1 1
      helper/fcgi_server.php
  34. 18 0
      helper/pay/IPay.php
  35. 63 0
      helper/pay/alipay.php
  36. 123 0
      helper/pay/cmbpay.php
  37. 98 0
      helper/pay/wxpay.php
  38. 78 1
      helper/pay_helper.php
  39. 2 2
      mobile/alipay_notify_url.php
  40. 125 0
      mobile/cmbpay.php
  41. 77 12
      mobile/control/member_buy.php
  42. 1 1
      mobile/wxnotify.php

+ 2 - 2
mobile/api/payment/alipay/alipay.config.php

@@ -28,11 +28,11 @@ $alipay_config['key']			= '';
 
 //商户的私钥(后缀是.pen)文件相对路径
 //如果签名方式设置为“0001”时,请设置该参数
-$alipay_config['private_key_path']	= BASE_MOBILE_PATH.'/api/payment/alipay/'.'key/rsa_private_key.pem';
+$alipay_config['private_key_path']	= BASE_DATA_PATH.'/api/payment/alipay/'.'key/rsa_private_key.pem';
 
 //支付宝公钥(后缀是.pen)文件相对路径
 //如果签名方式设置为“0001”时,请设置该参数
-$alipay_config['ali_public_key_path']= BASE_MOBILE_PATH.'/api/payment/alipay/'.'key/alipay_public_key.pem';
+$alipay_config['ali_public_key_path']= BASE_DATA_PATH.'/api/payment/alipay/'.'key/alipay_public_key.pem';
 
 
 //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

mobile/api/payment/alipay/alipay.php → data/api/alipay/alipay.php


mobile/api/payment/alipay/alipayapi.php → data/api/alipay/alipayapi.php


mobile/api/payment/alipay/cacert.pem → data/api/alipay/cacert.pem


+ 1 - 1
mobile/api/payment/alipay/call_back_url.php

@@ -6,5 +6,5 @@
 $_GET['act'] = 'payment';
 $_GET['op']	= 'return';
 $_GET['payment_code']	= 'alipay';
-require_once(dirname(__FILE__).'/../../../index.php');
+require_once(dirname(__FILE__) . '/../../../index.php');
 ?>

mobile/api/payment/alipay/images/alipay.gif → data/api/alipay/images/alipay.gif


mobile/api/payment/alipay/images/new-btn-fixed.png → data/api/alipay/images/new-btn-fixed.png


mobile/api/payment/alipay/index.php → data/api/alipay/index.php


mobile/api/payment/alipay/key/alipay_public_key.pem → data/api/alipay/key/alipay_public_key.pem


mobile/api/payment/alipay/key/rsa_private_key.pem → data/api/alipay/key/rsa_private_key.pem


mobile/api/payment/alipay/lib/alipay_core.function.php → data/api/alipay/lib/alipay_core.function.php


mobile/api/payment/alipay/lib/alipay_md5.function.php → data/api/alipay/lib/alipay_md5.function.php


mobile/api/payment/alipay/lib/alipay_notify.class.php → data/api/alipay/lib/alipay_notify.class.php


mobile/api/payment/alipay/lib/alipay_rsa.function.php → data/api/alipay/lib/alipay_rsa.function.php


mobile/api/payment/alipay/lib/alipay_submit.class.php → data/api/alipay/lib/alipay_submit.class.php


mobile/api/payment/alipay/log.txt → data/api/alipay/log.txt


+ 1 - 1
mobile/api/payment/alipay/notify_url.php

@@ -7,5 +7,5 @@
 $_GET['act'] = 'payment';
 $_GET['op']	= 'notify';
 $_GET['payment_code']	= 'alipay';
-require_once(dirname(__FILE__).'/../../../index.php');
+require_once(dirname(__FILE__) . '/../../../index.php');
 ?>

mobile/api/payment/alipay/readme.txt → data/api/alipay/readme.txt


+ 585 - 0
data/api/cmbpay/Cmb.class.php

@@ -0,0 +1,585 @@
+<?php
+/**
+ * 招行银行一网通测试类
+ * 1.测试查询协议
+ * 2.测试取消协议
+ */
+class Cmb
+{
+    const pfx_path = BASE_DATA_PATH . "/api/cmbpay/m000001269.pfx";
+
+    /**
+     * 初始化方法
+     * 加载配置文件
+     */
+    public function __construct()
+    {
+        $this->config = self::config();
+    }
+
+
+    static public function config()
+    {
+        return array(
+            'CMCX_URL'         => 'http://58.61.30.110/CmbBank_B2B/UI/DIDI/DoBusiness.ashx', //签约协议查询接口
+            'NTBNBR'           => 'P0026365',//协议商户企业编号 //请填写自己的商户企业编号
+            'MchNo'            => 'P0026365',//协议商户企业编号 //请填写自己的商户企业编号
+            'pfxFile'          => self::pfx_path, //pfx格式证书 通过jks转换 用于openssl签名
+            'password'         => '12345678',//pfx证书密码
+            'BranchID'         => '0021',//开户分行号 4位 请自己配置
+            'CoNo'             => '000140', //商户号 6位 请自己配置
+            'singKey'          => '',//签名密钥 查询单笔订单需要 测试环境为空
+            'DirectRequestX'   => 'http://218.17.27.197/netpayment/basehttp.dll?DirectRequestX',//查询订单接口
+            'RefundNoDupOperator' => '9999',//退款操作员编号
+            'RefundNoDupPassword' => '000111', //测试环境密码和商户号相同
+        );
+    }
+    
+    /**
+     *  支付协议查询
+     *  查询成功 BUSDATA 字段返回数据描述
+     *  merch_date 	String 	8 	可选 	商户交易日期(YYYYMMDD), 成功交易返回 	
+     *  merch_time 	String 	6 	可选 	商户交易时间(HHmmSS), 成功交易返回 	
+     *  merch_serial 	String 	24 	必填 	商户交易流水号 	
+     *  respcod 	String 	7 	必填 	交易结果 CMBMB99表示成功,其他为失败 	
+     *  respmsg 	String 	80 	必填 	返回交易信息 	
+     *  cust_argno 	String 	32 	可选 	客户协议号,成功交易返回 	
+     *  bank_name 	String 	40 	可选 	签约银行名称,成功交易返回 	
+     *  open_time 	String 	14 	可选 	签约时间 YYYYMMDD HHmmSS,成功交易返回 	
+     *  cust_open_d_pay 	String 	1 	可选 	保留使用:”N”,成功交易返回 	
+     *  cust_pidty 	String 	1 	可选 	证件类型 目前只有’1’,表示身份证,成功交易返回 	
+     *  cust_pid_v 	String 	30 	可选 	证件号映射的30位hash值,成功交易返回
+     */
+    public function cmcx($data)
+    {
+        $xmlBusData = "<xml><merch_date>{$data['merch_date']}</merch_date><merch_time>{$data['merch_time']}</merch_time><merch_serial>{$data['merch_serial']}</merch_serial><cust_argno>{$data['cust_argno']}</cust_argno></xml>";
+        $BUSDAT = base64_encode($xmlBusData);//业务数据包 报文数据必须经过base64编
+        $NTBNBR = $this->config['NTBNBR'];//企业网银编号
+        $TRSCOD = 'CMCX';//交易码
+        $DATLEN = strlen($BUSDAT);// 字段BUSDAT长度
+        $COMMID = date("YmdHis",time()).mt_rand(100000, 999999);//返回的报文头会包含该信息,仅用作单次通讯的请求和响应报文的对应。银行业务数据不存储该ID。
+        $SIGTIM = date("YmdHis",time()).'0000';//签名时间
+        $signOrigin = "NTBNBR={$NTBNBR}&TRSCOD={$TRSCOD}&COMMID={$COMMID}&SIGTIM={$SIGTIM}&BUSDAT={$BUSDAT}";
+        $SIGDAT = $this->opensslSign($signOrigin);
+        $requestData = array(
+            'NTBNBR' => $NTBNBR,
+            'TRSCOD' => $TRSCOD,
+            'COMMID' => $COMMID,
+            'DATLEN' => $DATLEN,
+            'BUSDAT' => $BUSDAT,
+            'SIGTIM' => $SIGTIM,
+            'SIGDAT' => $SIGDAT,
+        );
+        $jsonData = json_encode($requestData);
+        $url = $this->config['CMCX_URL'];
+        $postArray = array();
+        $postArray[0] = $url;
+        $postArray[1]['data'] = array('RequestData' => $jsonData);
+        $json = $this->execCurl("post",$postArray);
+        $cmcxData = json_decode($json,true);
+        $xml = base64_decode($cmcxData['BUSDAT']);
+        $xmlArray = (array)simplexml_load_string($xml);
+        
+        //查询协议日志
+        $dateTime = date("Y-m-d H:i:s",time());
+        $logContent = "日志时间:{$dateTime} 请求原文JSON:{$jsonData} 请求XML:{$xmlBusData} 响应原文json:{$json} 响应XML:{$xml}".PHP_EOL.PHP_EOL;
+        $this->writeLog('cmcx',$logContent);
+        return $xmlArray;
+    }
+    
+    /**
+     * 获取查询协议数据
+     * 模拟查询协议用的数据
+     * 查询不同的协议请使用不同的数据进行模拟
+     * 这些模拟数据都是真实存在银行系统内的数据不能乱写
+     */
+    public function getTestCmcxInfo()
+    {
+        $data = array();
+        $data['merch_date'] = '20160811';//签约协议日期 年月日
+        $data['merch_time'] = '154021';//签约协议时间 时分秒
+        $data['merch_serial'] = '2016081143751'; //签约协议流水号
+        $data['cust_argno'] = '20160811154059441120';//协议号
+        return $data;
+    }
+    
+    
+    /**
+     *  支付协议查询
+     *  查询成功 BUSDATA 字段返回数据描述
+     *  merch_date 	String 	8 	必填 	商户交易日期(YYYYMMDD) 	
+     *  merch_time 	String 	6 	必填 	商户交易时间(HHmmSS) 	
+     *  merch_serial 	String 	24 	必填 	商户交易流水号,全局唯一 	
+     *  bank_serial 	String 	30 	必填 	银行交易流水号,全局唯一 	
+     *  respcod 	String 	7 	必填 	交易结果 CMBMB99表示成功,其他为失败 	
+     *  respmsg 	String 	80 	必填 	返回交易信息
+     */
+    public function cmqx($data)
+    {
+        $xmlBusData = "<xml><merch_date>{$data['merch_date']}</merch_date><merch_time>{$data['merch_time']}</merch_time><merch_serial>{$data['merch_serial']}</merch_serial><cust_argno>{$data['cust_argno']}</cust_argno></xml>";
+        $BUSDAT = base64_encode($xmlBusData);//业务数据包 报文数据必须经过base64编
+        $NTBNBR = $this->config['NTBNBR'];//企业网银编号
+        $TRSCOD = 'CMQX';//交易码
+        $DATLEN = strlen($BUSDAT);// 字段BUSDAT长度
+        $COMMID = date("YmdHis",time()).mt_rand(100000, 999999);//返回的报文头会包含该信息,仅用作单次通讯的请求和响应报文的对应。银行业务数据不存储该ID。
+        $SIGTIM = date("YmdHis",time()).'0000';//签名时间
+        $signOrigin = "NTBNBR={$NTBNBR}&TRSCOD={$TRSCOD}&COMMID={$COMMID}&SIGTIM={$SIGTIM}&BUSDAT={$BUSDAT}";
+        $SIGDAT = $this->opensslSign($signOrigin);
+        $requestData = array(
+            'NTBNBR' => $NTBNBR,
+            'TRSCOD' => $TRSCOD,
+            'COMMID' => $COMMID,
+            'DATLEN' => $DATLEN,
+            'BUSDAT' => $BUSDAT,
+            'SIGTIM' => $SIGTIM,
+            'SIGDAT' => $SIGDAT,
+        );
+        $jsonData = json_encode($requestData);
+        $url = $this->config['CMCX_URL'];//查询和取消走的都是同一个接口
+        $postArray = array();
+        $postArray[0] = $url;
+        $postArray[1]['data'] = array('RequestData' => $jsonData);
+        $json = $this->execCurl("post",$postArray);
+        $cmcxData = json_decode($json,true);
+        $xml = base64_decode($cmcxData['BUSDAT']);
+        $xmlArray = (array)simplexml_load_string($xml);
+        
+        //取消协议日志
+        $dateTime = date("Y-m-d H:i:s",time());
+        $logContent = "日志时间:{$dateTime} 请求原文JSON:{$jsonData} 请求XML:{$xmlBusData} 响应原文json:{$json} 响应XML:{$xml}".PHP_EOL.PHP_EOL;
+        $this->writeLog('cmqx',$logContent);
+        return $xmlArray;
+    }
+    
+    /**
+     * 获取查询协议数据
+     * 模拟查询协议用的数据
+     * 如果提供的数据不存在于银行系统内,返回错误提示
+     */
+    public function getTestCmqxInfo()
+    {
+        $data = array();
+        $data['merch_date'] = '20160811';//签约协议日期 年月日
+        $data['merch_time'] = '151709';//签约协议时间 时分秒
+        $data['merch_serial'] = '2016081132532'; //签约协议流水号
+        $data['cust_argno'] = '20160811151403121298';//协议号
+        return $data;
+    }
+    
+    
+    /**
+     * 查询支付协议签名
+     * php基于sha1withRSA算法的签名(pfx证书)
+     * @param type $data
+     * @return type
+     */
+    public function opensslSign($data) 
+    {
+        $certs = array();
+        //其中password为证书密码
+        openssl_pkcs12_read(file_get_contents($this->config['pfxFile']), $certs, $this->config['password']); 
+        if(!$certs) return ;
+        $signature = '';  
+        openssl_sign($data, $signature, $certs['pkey']);
+        return base64_encode($signature);//返回base64编码的密钥
+    }
+
+	/**
+     * 获取银行订单信息
+     */
+    public function getOneOrderInfo($data)
+    {
+        $startTime   = strtotime("2000-01-01 00:00:00");
+        $currentTime = time();
+        $diffTime    = $currentTime - $startTime;
+        $BranchNo    = $this->config['BranchID'];//开户分行号
+        $MerchantNo  = $this->config['CoNo'];//商户号
+        $TimeStamp   = $diffTime * 1000;//请求发起的时间,精确到毫秒
+        $Date        = $data['Date'];//商户定单日期 年月日 YYYYMMDD
+        $BillNo      = $data['BillNo'];//订单号 6位或10位订单号 
+        $singKey     = $this->config['singKey'];//签名密钥 测试情况下为空
+        //SHA1 哈希签名
+        $HashOrigin = "{$singKey}<BranchNo>{$BranchNo}</BranchNo><MerchantNo>{$MerchantNo}</MerchantNo><TimeStamp>{$TimeStamp}</TimeStamp><Command>QuerySingleOrder</Command><Date>{$Date}</Date><BillNo>{$BillNo}</BillNo>";
+        $Hash = sha1($HashOrigin);//使用sha1加密
+        //单笔订单请求报文
+        $postData = "<Request><Head><BranchNo>{$BranchNo}</BranchNo><MerchantNo>{$MerchantNo}</MerchantNo><TimeStamp>{$TimeStamp}</TimeStamp><Command>QuerySingleOrder</Command></Head><Body><Date>{$Date}</Date><BillNo>{$BillNo}</BillNo></Body><Hash>{$Hash}</Hash></Request>";
+
+        //接口地址
+        $array = array();
+        $array[0] = $this->config['DirectRequestX'];
+        $array[1]['data'] = array(
+            'Request' => $postData,
+        );
+        $xmlString = $this->execCurl('post',$array);
+        
+        //查询单笔订单日志
+        $dateTime = date("Y-m-d H:i:s",time());
+        $logContent = "日志时间:{$dateTime} 请求原文:{$postData} 响应原文:{$xmlString}".PHP_EOL.PHP_EOL;
+        $this->writeLog('singleOrder',$logContent);
+        $xmlArray = simplexml_load_string($xmlString);
+        return $this->objectToArray($xmlArray);
+    }
+    
+    /**
+     * 模拟获取订单信息
+     */
+    public function getTestOneOrder()
+    {
+        $BillNo = '0003041211'; //银行订单号
+        $Date   = '20160812'; //订单日期 
+        return array('BillNo'=>$BillNo,'Date'=>$Date);
+    }
+
+    /**
+     * 订单查询 共用接口 该方法可以接受三个接口参数调用
+     * 通过Command字段区分调用
+     * 1.商户入账查询接口 QueryTransact
+     * 2.按商户日期查询已结账订单接口 QuerySettledOrderByMerchantDate
+     * 3.按结账日期查询已结账订单接口 QuerySettledOrderBySettledDate
+     */
+    public function getQueryOrderData($data)
+    {
+        $startTime   = strtotime("2000-01-01 00:00:00");
+        $currentTime = time();
+        $diffTime    = $currentTime - $startTime;
+        $BranchNo    = $this->config['BranchID'];//开户分行号
+        $MerchantNo  = $this->config['CoNo'];//商户号
+        $TimeStamp   = $diffTime * 1000;//请求发起的时间,精确到毫秒
+        $BeginDate   = $data['BeginDate'];//起始日期
+        $EndDate     = $data['EndDate'];//结束日期
+        $Count       = $data['Count'];//查询条数
+        $Operator    = $data['Operator'];//操作员号
+        $pos         = $data['Pos']; //续传包
+        $singKey     = $this->config['singKey'];//签名密钥 测试情况下为空
+        $Command     = $data['Command']; //接口名称 说明见注释
+
+        //SHA1 哈希签名
+        $HashOrigin = "{$singKey}<BranchNo>{$BranchNo}</BranchNo><MerchantNo>{$MerchantNo}</MerchantNo><TimeStamp>{$TimeStamp}</TimeStamp><Command>{$Command}</Command><BeginDate>{$BeginDate}</BeginDate><EndDate>{$EndDate}</EndDate><Count>{$Count}</Count><Operator>{$Operator}</Operator><pos>{$pos}</pos>";
+        $Hash = sha1($HashOrigin);
+        //商户入账查询请求报文
+        $postData = "<Request><Head><BranchNo>{$BranchNo}</BranchNo><MerchantNo>{$MerchantNo}</MerchantNo><TimeStamp>{$TimeStamp}</TimeStamp><Command>{$Command}</Command></Head><Body><BeginDate>{$BeginDate}</BeginDate><EndDate>{$EndDate}</EndDate><Count>{$Count}</Count><Operator>{$Operator}</Operator><pos>{$pos}</pos></Body><Hash>{$Hash}</Hash></Request>";
+        //接口地址
+        $array = array();
+        $array[0] = $this->config['DirectRequestX'];
+        $array[1]['data'] = array(
+            'Request' => $postData,
+        );
+        $xmlString = $this->execCurl('post',$array);
+        
+        //接口命令
+        $CommandArray = array(
+            'QuerySettledOrderByMerchantDate' => '商户日期查询已结账订单接口',
+            'QuerySettledOrderBySettledDate' => '结账日期查询已结账订单接口',
+            'QueryTransact' => '商户入账查询接口',
+        );
+        //入账 已结账日志 
+        $dateTime = date("Y-m-d H:i:s",time());
+        $logContent = "日志时间:{$dateTime} 请求命令:{$Command} 接口名称:{$CommandArray[$Command]} 请求原文:{$postData} 响应原文:{$xmlString}".PHP_EOL.PHP_EOL;
+        $this->writeLog('querySettledOrder',$logContent);
+        $xmlArray = simplexml_load_string($xmlString);
+        return $this->objectToArray($xmlArray);
+    }
+    
+    /**
+     * 模拟获取商户入账数据
+     * 模拟测试数据 生产环境请用正式数据代替
+     */
+    public function getTestQueryTransact()
+    {
+        $BeginDate   = '20150923';//起始日期
+        $EndDate = '20160924';//结束日期
+        $Count   = '10';//查询条数
+        $Operator = '9999';//操作员号
+        $pos = ''; //续传包
+        $Command = 'QueryTransact';//接口命令 不同的命令
+        $data = array(
+            'BeginDate' => $BeginDate,
+            'EndDate' => $EndDate,
+            'Count'   => $Count,
+            'Operator' => $Operator,
+            'pos'     => $pos,
+            'Command' => $Command,
+        );
+        return $data;
+    }
+    
+    /**
+     * 按结账日期查询已结账订单接口
+     * 模拟测试数据 生产环境请用正式数据代替
+     */
+    public function getTestQuerySettledOrderBySettledDate()
+    {
+        $BeginDate   = '20160801';//起始日期
+        $EndDate = '20160810';//结束日期
+        $Count   = '20';//查询条数
+        $Operator = '9999';//操作员号
+        $pos = ''; //续传包
+        $Command = 'QuerySettledOrderBySettledDate';//接口命令 不同的命令
+        $data = array(
+            'BeginDate' => $BeginDate,
+            'EndDate' => $EndDate,
+            'Count'   => $Count,
+            'Operator' => $Operator,
+            'pos'     => $pos,
+            'Command' => $Command,
+        );
+        return $data;
+    }
+    
+    /**
+     * 按商户日期查询已结账订单接口
+     * 模拟测试数据 生产环境请用正式数据代替
+     */
+    public function getTestQuerySettledOrderByMerchantDate()
+    {
+        $BeginDate   = '20150923';//起始日期
+        $EndDate = '20160924';//结束日期
+        $Count   = '10';//查询条数
+        $Operator = '9999';//操作员号
+        $pos = ''; //续传包
+        $Command = 'QuerySettledOrderByMerchantDate';//接口命令 不同的命令
+        $data = array(
+            'BeginDate' => $BeginDate,
+            'EndDate' => $EndDate,
+            'Count'   => $Count,
+            'Operator' => $Operator,
+            'pos'     => $pos,
+            'Command' => $Command,
+        );
+        return $data;
+    }
+    
+    /**
+     * 执行退款操作
+     */
+    public function getRefundNoDupData($data)
+    {
+        $startTime   = strtotime("2000-01-01 00:00:00");
+        $currentTime = time();
+        $diffTime    = $currentTime - $startTime;
+        $BranchNo    = $this->config['BranchID'];//开户分行号
+        $MerchantNo  = $this->config['CoNo'];//商户号
+        $TimeStamp   = $diffTime * 1000;//请求发起的时间,精确到毫秒
+        $Date        = $data['Date'];//原订单日期
+        $BillNo      = $data['BillNo']; //原订单号
+        $RefundNo    = $data['RefundNo'];//退款流水号
+        $Operator    = $this->config['RefundNoDupOperator'];//操作员号
+        $Password    = $this->config['RefundNoDupPassword'];//操作员密码
+        $Amount      = $data['Amount'];//退款金额
+        $Desc        = $data['Desc'];//退款描述
+        $singKey     = $this->config['singKey'];//签名密钥 测试情况下为空
+        $Command     = 'Refund_No_Dup'; //接口名称 说明见注释
+
+        //SHA1 哈希签名
+        $HashOrigin = "{$singKey}<BranchNo>{$BranchNo}</BranchNo><MerchantNo>{$MerchantNo}</MerchantNo><Operator>{$Operator}</Operator><Password>{$Password}</Password><TimeStamp>{$TimeStamp}</TimeStamp><Command>{$Command}</Command><Date>{$Date}</Date><BillNo>{$BillNo}</BillNo><RefundNo>{$RefundNo}</RefundNo><Amount>{$Amount}</Amount><Desc>{$Desc}</Desc>";
+        $Hash = sha1($HashOrigin);
+
+        //商户入账查询请求报文
+        $postData = "<Request><Head><BranchNo>{$BranchNo}</BranchNo><MerchantNo>{$MerchantNo}</MerchantNo><Operator>{$Operator}</Operator><Password>{$Password}</Password><TimeStamp>{$TimeStamp}</TimeStamp><Command>{$Command}</Command></Head><Body><Date>{$Date}</Date><BillNo>{$BillNo}</BillNo><RefundNo>{$RefundNo}</RefundNo><Amount>{$Amount}</Amount><Desc>{$Desc}</Desc></Body><Hash>{$Hash}</Hash></Request>";
+
+        //接口地址
+        $array = array();
+        $array[0] = $this->config['DirectRequestX'];
+        $array[1]['data'] = array(
+            'Request' => $postData,
+        );
+        $xmlString = $this->execCurl('post',$array);
+        
+
+        //入账 已结账日志 
+        $dateTime = date("Y-m-d H:i:s",time());
+        $logContent = "日志时间:{$dateTime} 请求命令:Refund_No_Dup 接口名称:直连退款 请求原文:{$postData} 响应原文:{$xmlString}".PHP_EOL.PHP_EOL;
+        $this->writeLog('refundNoDup',$logContent);
+        $xmlArray = simplexml_load_string($xmlString);
+        return $this->objectToArray($xmlArray);
+    }
+    
+    
+    /**
+     * 模拟退款数据
+     */
+    public function getTestRefundNoDup()
+    {
+        $Date   = '20160812';//订单日期
+        $BillNo = '0001416027';//订单号
+        $RefundNo = 'TK'.date("YmdHis",time()).  mt_rand(1000,9999);//退款流水号
+        $Amount = '98.00';//退款金额
+        $Desc = 'tuikuan desc';//
+        $data = array(
+            'Date'     => $Date,
+            'BillNo'   => $BillNo,
+            'RefundNo' => $RefundNo,
+            'Amount'   => $Amount,
+            'Desc'     => $Desc,
+        );
+        return $data;
+    }
+    
+    
+    /**
+     * 递归转换XML为数组
+     * @param type $data
+     * @return type
+     */
+    public function objectToArray($e) 
+    { 
+        $_arr = is_object($e) ? get_object_vars($e) : $e; 
+        foreach ($_arr as $key => $val) { 
+          $val = (is_array($val) || is_object($val)) ? $this->objectToArray($val) : $val; 
+          $arr[$key] = !$val ? (string)$val : $val; 
+        } 
+        return $arr; 
+    }
+
+    
+    /**
+     * CURL函数
+     * @param type $method
+     * @param type $args
+     * @return type
+     * @throws \Exception
+     */
+    public function execCurl($method, $args)
+    {
+        //解析参数
+        $url       = isset($args[0])            ? $args[0]            : "";
+        $multi     = isset($args[1]['multi'])   ? $args[1]['multi']   : "";
+        $data      = isset($args[1]['data'])    ? $args[1]['data']    : "";
+        $ajax      = isset($args[1]['ajax'])    ? $args[1]['ajax']    : "";
+        $timeout   = isset($args[1]['timeout']) ? $args[1]['timeout'] : 30;
+        $files     = isset($args[1]['files'])   ? $args[1]['files']   : "";
+        $referer   = isset($args[1]['referer']) ? $args[1]['referer'] : "";
+        $proxy     = isset($args[1]['proxy'])   ? $args[1]['proxy']   : "";
+        $headers   = isset($args[1]['headers']) ? $args[1]['headers'] : "";
+        
+        //如果环境变量的浏览器信息不存在,就是用手动设置的浏览器信息
+        $userAgent = isset($_SERVER['HTTP_USER_AGENT'])?
+            $_SERVER['HTTP_USER_AGENT']:
+                'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:23.0) 
+                    Gecko/20100101 Firefox/23.0';
+        
+        //检测url必须参数 不能为空
+        if (!$url) {
+            throw new \Exception("错误:curl请求地址不能为空");
+        }
+        
+        //设置curl选项
+        $options = array(
+                        CURLOPT_URL            => $url,      //目标url
+                        CURLOPT_TIMEOUT        => $timeout,  //超时
+                        CURLOPT_RETURNTRANSFER => 1,         //输出数据流
+                        CURLOPT_FOLLOWLOCATION => 1,         //自动跳转追踪
+                        CURLOPT_AUTOREFERER    => 1,         //自动设置来路信息
+                        CURLOPT_SSL_VERIFYPEER => 0,         //认证证书检查
+                        CURLOPT_SSL_VERIFYHOST => 0,         //检查SSL加密算法
+                        CURLOPT_HEADER         => 0,         //禁止头文件输出
+                        CURLOPT_NOSIGNAL       => 1,         //忽略所有传递的信号
+                        CURLOPT_USERAGENT      => $userAgent,//浏览器环境字符串
+                        CURLOPT_IPRESOLVE      => CURL_IPRESOLVE_V4, //ipv4寻址方式
+                        CURLOPT_ENCODING       => 'gzip',    //解析使用gzip压缩的网页    
+                   );  
+        
+  
+        
+        //设置代理 必须是数组并且非空
+        if (is_array($proxy) && !empty($proxy)) {   
+            $options[CURLOPT_PROXY]        = $proxy['host'];
+            $options[CURLOPT_PROXYPORT]    = $proxy['port'];   
+            $options[CURLOPT_PROXYUSERPWD] = 
+                                        $proxy['user'] . ':' . $proxy['pass'];
+        }
+        
+        //检测是否未启用自定义urlencode编码
+        if (!isset($args[1]['build'])) { 
+            if ($data && $method == "post" && is_array($data)) {
+                $data = http_build_query($data, '', '&');
+            }
+        }
+        
+        //检测是否含有上传文件
+        if ($files && $method == "post" && is_array($files)) {
+            foreach ($files as $k => $v) {
+                $files[$k] = '@' . $v;
+            }
+
+            parse_str($data, $data);
+            $data = $data + $files;
+        }
+        
+        //检测判断是否是post请求
+        if ($method == 'post') {
+            //发送一个常规的POST请求
+            $options[CURLOPT_POST]       = 1; 
+            
+            //使用HTTP协议中的"POST"操作来发送数据,支持键值对数组定义
+            $options[CURLOPT_POSTFIELDS] = $data; 
+        }
+        
+        //初始化header数组
+        $headerOptions = array();
+        
+        //检测是否是ajax提交
+        if ($ajax) {
+            $headerOptions['X-Requested-With']  = 'XMLHttpRequest';
+        }
+        
+        //设置来路
+        if ($referer) {
+            $options[CURLOPT_REFERER] = $referer;
+        }
+        
+        //合并header
+        if (!empty($headers) && is_array($headers)) {
+            foreach ($headers as $k => $v) {
+                $headerOptions[$k] = $v;
+            }
+        }
+        
+        //转换header选项为浏览器header格式
+        if (!empty($headerOptions) && is_array($headerOptions)) {
+            $array = array();
+            
+            foreach($headerOptions as $k => $v) {
+                $array[] = $k . ": " . $v;
+            }
+            
+            $options[CURLOPT_HTTPHEADER] = $array;
+        }
+        
+        //创建curl句柄
+        $ch = curl_init();
+        
+        //设置curl选项
+        curl_setopt_array($ch, $options);
+        
+        //获取返回内容
+        $content = curl_exec($ch);
+        
+        //关闭curl句柄
+        curl_close($ch);
+        
+        //返回内容
+        return $content;
+
+    }
+    
+
+    
+    /**
+     * 写日志
+     * @param type $fileName 文件名
+     * @param type $filePath 文件路径
+     * @param type $logContent 日志内容
+     */
+    public function writeLog($dirName, $logContent)
+    {
+        $currentPath = dirname(__FILE__) .'/log/' .  $dirName ;
+        if (!file_exists($currentPath)) {
+            @mkdir($currentPath,0777,true);
+        }
+        $filename = date("dmY",time()) . '.log';
+        $writeFileName = $currentPath . '/' . $filename;
+        file_put_contents($writeFileName, $logContent,FILE_APPEND);
+    }
+    
+}

+ 29 - 0
data/api/cmbpay/CmbConfig.php

@@ -0,0 +1,29 @@
+<?php
+return array(
+    'CMCX_URL'         => 'http://58.61.30.110/CmbBank_B2B/UI/DIDI/DoBusiness.ashx', //签约协议查询接口
+    'NTBNBR'           => '',//协议商户企业编号 //请填写自己的商户企业编号
+    'pfxFile'          => dirname(__FILE__) . '/m000001269.pfx',//pfx格式证书 通过jks转换 用于openssl签名
+    'password'         => '12345678',//pfx证书密码
+    'BranchID'         => '',//开户分行号 4位 请自己配置
+    'CoNo'             => '', //商户号 6位 请自己配置
+    'singKey'          => '',//签名密钥 查询单笔订单需要 测试环境为空
+    'DirectRequestX'   => 'http://218.17.27.197/netpayment/basehttp.dll?DirectRequestX',//查询订单接口
+    'RefundNoDupOperator' => '9999',//退款操作员编号
+    'RefundNoDupPassword' => '000111', //测试环境密码和商户号相同
+);
+
+return array(
+    'CMCX_URL'         => 'http://58.61.30.110/CmbBank_B2B/UI/DIDI/DoBusiness.ashx', //签约协议查询接口
+    'NTBNBR'           => 'P0026365',//协议商户企业编号 //请填写自己的商户企业编号
+    'pfxFile'          => dirname(__FILE__) . '/m000001269.pfx',//pfx格式证书 通过jks转换 用于openssl签名
+    'password'         => '12345678',//pfx证书密码
+    'BranchID'         => '0021',//开户分行号 4位 请自己配置
+    'CoNo'             => '000140', //商户号 6位 请自己配置
+    'singKey'          => '',//签名密钥 查询单笔订单需要 测试环境为空
+    'DirectRequestX'   => 'http://218.17.27.197/netpayment/basehttp.dll?DirectRequestX',//查询订单接口
+    'RefundNoDupOperator' => '9999',//退款操作员编号
+    'RefundNoDupPassword' => '000111', //测试环境密码和商户号相同
+    'sign_url'         => 'http://172.30.0.184:8081/test2/cmb/cmbpay_resul.php',
+    'result_url'       => 'http://172.30.0.184:8081/test2/cmb/cmbpay_sign.php',
+    'pay_url'          => 'http://61.144.248.29:801/netpayment/BaseHttp.dll?PrePayEUserP'
+);

BIN
data/api/cmbpay/M000001269.jks


+ 1 - 0
data/api/cmbpay/REDME.txt

@@ -0,0 +1 @@
+打开CmbConfig.php 配置 自己的商户资料

+ 9 - 0
data/api/cmbpay/cmcx.php

@@ -0,0 +1,9 @@
+<?php
+header("Content-type:text/html;charset=utf8");
+//查询支付签约协议
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->cmcx($cmb->getTestCmcxInfo());//执行查询
+echo '<pre>';
+print_r($res);
+

+ 8 - 0
data/api/cmbpay/cmqx.php

@@ -0,0 +1,8 @@
+<?php
+header("Content-type:text/html;charset=utf8");
+//取消支付签约协议
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->cmqx($cmb->getTestCmqxInfo());//执行取消 
+echo '<pre>';
+print_r($res);

+ 10 - 0
data/api/cmbpay/querySettledOrderByMerchantDate.php

@@ -0,0 +1,10 @@
+<?php
+//按商户日期查询已结账订单接口
+header("Content-type:text/html;charset=utf8");
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->getQueryOrderData($cmb->getTestQuerySettledOrderByMerchantDate());
+echo '<pre>';
+print_r($res);
+
+

+ 10 - 0
data/api/cmbpay/querySettledOrderBySettledDate.php

@@ -0,0 +1,10 @@
+<?php
+//按结账日期查询已结账订单接口
+header("Content-type:text/html;charset=utf8");
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->getQueryOrderData($cmb->getTestQuerySettledOrderBySettledDate());
+echo '<pre>';
+print_r($res);
+
+

+ 10 - 0
data/api/cmbpay/queryTransact.php

@@ -0,0 +1,10 @@
+<?php
+//商户入账查询接口
+header("Content-type:text/html;charset=utf8");
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->getQueryOrderData($cmb->getTestQueryTransact());
+echo '<pre>';
+print_r($res);
+
+

+ 9 - 0
data/api/cmbpay/refundNoDup.php

@@ -0,0 +1,9 @@
+<?php
+//商户入账查询接口
+header("Content-type:text/html;charset=utf8");
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->getRefundNoDupData($cmb->getTestRefundNoDup());
+echo '<pre>';
+print_r($res);
+

+ 8 - 0
data/api/cmbpay/searchOneOrder.php

@@ -0,0 +1,8 @@
+<?php
+//单笔定单查询接口
+header("Content-type:text/html;charset=utf8");
+require 'Cmb.class.php';//引入招商银行类
+$cmb = new Cmb();//实例化
+$res = $cmb->getOneOrderInfo($cmb->getTestOneOrder());
+echo '<pre>';
+print_r($res);

Різницю між файлами не показано, бо вона завелика
+ 234 - 0
data/api/cmbpay/招商一网通支付接口调用+验签.php


+ 5 - 2
data/logic/buy_1.logic.php

@@ -577,7 +577,8 @@ class buy_1Logic
             $data_pd['amount'] = $order_amount;
             $data_pd['order_sn'] = $order_info['order_sn'];
 
-            if ($available_pd_amount >= $order_amount) {
+            if ($available_pd_amount >= $order_amount)
+            {
                 //预存款立即支付,订单支付完成
                 $model_pd->changePd('order_pay',$data_pd);
                 $available_pd_amount -= $order_amount;
@@ -622,7 +623,9 @@ class buy_1Logic
                         'order_sn' => $order_info['order_sn']
                 );
                 QueueClient::push('sendStoreMsg', $param);
-            } else {
+            }
+            else
+            {
                 //暂冻结预存款,后面还需要 API彻底完成支付
                 if ($available_pd_amount > 0) {
                     $data_pd['amount'] = $available_pd_amount;

+ 37 - 11
helper/buy_first.php

@@ -27,7 +27,6 @@ class buy_first
         foreach ($store_goods_total as $store_id => $value) {
             $goods_amount += doubleval($value);
         }
-
         $result['goods_amount'] = $goods_amount;
 
         //满送
@@ -43,7 +42,15 @@ class buy_first
         $result['full_goods'] = $this->full_goods();
 
         //运费
-        $result['freight'] = $this->freight();
+        if($this->freight($freight,$offpay_hash,$offpay_hash_batch) == true) {
+            $result['freight'] = $freight;
+            $result['offpay_hash_batch'] = $offpay_hash_batch;
+            $result['offpay_hash'] = $offpay_hash;
+        } else {
+            $result['freight'] = 0;
+            $result['offpay_hash_batch'] = "";
+            $result['offpay_hash'] = "";
+        }
         $result['freight_hash'] = $this->mLogicOut['freight_list'];
 
         //红包信息
@@ -51,7 +58,9 @@ class buy_first
         $result['available_pred']  = $this->available_pred($goods_amount);
         $result['usable_pred'] = true;
 
+        //是否可以开增值税发票
         $result['vat_deny'] = $this->mLogicOut['vat_deny'];
+        //发票
         $result['vat_hash'] = $this->mLogicOut['vat_hash'];
 
         return $result;
@@ -76,31 +85,48 @@ class buy_first
             return intval($address_info['city_id']);
         }
     }
+    private function area_id()
+    {
+        $address_info = $this->mLogicOut['address_info'];
+        if(empty($address_info)) {
+            return false;
+        } else {
+            return intval($address_info['area_id']);
+        }
+    }
     private function paytype()
     {
         //支付宝,微信,招商银行,各自的描述语
         $types = [];
         $types[] = array("payment" => "wxpay","desc" => "");
         $types[] = array("payment" => "alipay","desc" => "");
-        $types[] = array("payment" => "cmbchina","desc" => "");
+        $types[] = array("payment" => "cmbpay","desc" => "");
         return $types;
     }
     //运费相关信息
-    private function freight()
+    private function freight(&$freight,&$offpay_hash,&$offpay_hash_batch)
     {
-        $logic_buy_1 = Logic('buy_1');
         $logic_buy = Logic("buy");
         $freight_hash = $this->mLogicOut['freight_list'];
-        $freight_list = $logic_buy->buyDecrypt($freight_hash, $_SESSION['member_id']);
         $city_id = $this->city_id();
-        $store_freight_total = $logic_buy_1->calcStoreFreight($freight_list,$city_id);
+        $area_id = $this->area_id();
+        $data = $logic_buy->changeAddr($freight_hash, $city_id, $area_id, $_SESSION['member_id']);
+        if (!empty($data) && $data['state'] == 'success')
+        {
+            $offpay_hash = $data['offpay_hash'];
+            $offpay_hash_batch = $data['offpay_hash_batch'];
 
-        $freight = 0.00;
-        foreach ($store_freight_total as $key => $value) {
-            $freight += doubleval($value);
+            $freight = 0.00;
+            foreach ($data['content'] as $value) {
+                $freight += $value['value'];
+            }
+            return true;
+        }
+        else {
+            return false;
         }
-        return $freight;
     }
+
     private function goods_ids()
     {
         $ids = [];

+ 1 - 1
helper/fcgi_server.php

@@ -20,7 +20,7 @@ class fcgi_server
 
     private function is_exclude($file)
     {
-        static $exfiles = array('wxnotify.php','alipay_notify_url.php','dispatch_notify.php','kdniao_notify.php','test.php');
+        static $exfiles = array('wxnotify.php','alipay_notify_url.php','dispatch_notify.php','kdniao_notify.php','test.php','cmbpay.php');
         $name = basename($file);
         return in_array($name,$exfiles);
     }

+ 18 - 0
helper/pay/IPay.php

@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/9/21
+ * Time: 下午6:03
+ */
+namespace Pay;
+
+interface IPay
+{
+    public function gen_pay($pay_sn, $fee,$order_sn,$subject);
+}
+
+
+
+

+ 63 - 0
helper/pay/alipay.php

@@ -0,0 +1,63 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/9/21
+ * Time: 下午7:54
+ */
+
+namespace Pay;
+
+define(ALIPAY_PATH, BASE_DATA_PATH . '/api/alipay');
+
+require_once (ALIPAY_PATH . '/lib/alipay_rsa.function.php');
+require_once (ALIPAY_PATH . '/lib/alipay_submit.class.php');
+
+
+
+class alipay implements IPay
+{
+    const pri_key_path = BASE_DATA_PATH.'/api/alipay/'.'key/rsa_private_key.pem';
+    const ali_notifyurl = BASE_SITE_URL . '/mobile/alipay_notify_url.php';
+
+    public function gen_pay($pay_sn, $fee,$order_sn,$subject)
+    {
+        $param = $this->getParam($pay_sn, $fee, $order_sn, $subject);
+        $para_filter = paraFilter($param);
+        $para_sort = argSort($para_filter);
+        $prestr = createLinkstring($para_sort);
+        $sign = rsaSign($prestr,self::pri_key_path);
+
+        $para_sort['sign'] = $sign;
+        $para_sort['sign_type'] = "RSA";
+        $req_param = createLinkstringUrlencode($para_sort);
+
+        return array("data" => $req_param);
+    }
+
+    /**
+     * @param $pay_sn
+     * @param $fee
+     * @param $order_sn
+     * @param $subject
+     * @param $ret
+     */
+    private function getParam($pay_sn, $fee, $order_sn, $subject)
+    {
+        $ret['partner'] = '2088121219613123';                           // 合作者身份ID
+        $ret['seller_id'] = 'napheir.ao@lrlz.com';                      // 签约卖家支付宝账号
+        $ret['out_trade_no'] = $pay_sn;   // 商户网站唯一订单号
+        $ret['subject'] = $subject;                                     // 商品名称
+        $ret['body'] = "order_sn={$order_sn}";                          // 商品详情
+        $total_fee = $fee / 100;
+        $ret['total_fee'] = "{$total_fee}";// 商品金额
+        $ret['notify_url'] = self::ali_notifyurl;                       // 服务器异步通知页面路径
+        $ret['service'] = 'mobile.securitypay.pay';                     // 服务器接口名称,固定值
+        $ret['payment_type'] = '1';                                     // 支付类型,固定值
+        $ret['_input_charset'] = 'utf-8';                               // 参数编码,固定值
+        $ret['it_b_pay'] = '30m';                                       // 设置未付款交易的超时时间 30min
+        $ret['return_url'] = 'http://';                                 // 支付宝完成请求后,当前页面跳转到商户指定页面的路径,可空
+
+        return $ret;
+    }
+}

+ 123 - 0
helper/pay/cmbpay.php

@@ -0,0 +1,123 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/9/21
+ * Time: 下午7:54
+ */
+
+namespace Pay;
+
+require_once (BASE_DATA_PATH . "/api/cmbpay/Cmb.class.php");
+
+use \Cmb;
+
+class cmbpay implements IPay
+{
+    const pay_url = 'http://61.144.248.29:801/netpayment/BaseHttp.dll?PrePayEUserP';
+    const notify_signurl = 'http://172.30.0.184:8081/test2/cmb/cmbpay_sign.php';
+    const notify_payurl = 'http://172.30.0.184:8081/test2/cmb/cmbpay_resul.php';
+
+    public function gen_pay($pay_sn, $cents,$order_sn,$subject)
+    {
+        $config = Cmb::config();
+
+        $bill_no = mt_rand(1000000000, 9999999999);
+        $payprice = $cents / 100;
+        $time = time();
+        $date = date('Ymd', $time);
+
+        $param = $this->gen_param($time,$payprice,$pay_sn,$order_sn,$bill_no);
+        $code = $this->genMerchantCode($param);
+
+        $user_id = $_SESSION['member_id'];
+        $data = [
+            'BranchID' => $config['BranchID'],
+            'CoNo' => $config['CoNo'],
+            'BillNo' => $bill_no,
+            'Amount' => $payprice,
+            'Date' => $date,
+            'ExpireTimeSpan' => '30',
+            'MerchantUrl' => $config['result_url'],
+            'MerchantPara' => "pay_sn={$pay_sn}#order_sn={$order_sn}#member_id={$user_id}",
+            'MerchantCode' => $code,
+            'MerchantRetUrl' => "http://127.0.0.1/success",
+        ];
+
+        $count = count($data);
+        $strParam = '';
+        $index = 0;
+        foreach ($data as $key => $value) {
+            $strParam .= "{$key}=" . urlencode($value);
+            if($index != $count - 1) {
+                $strParam .= "&";
+            }
+            ++$index;
+        }
+
+        return array("req_url" => self::pay_url,"data" => $strParam);
+    }
+
+    private function gen_param($time,$payprice,$pay_sn,$order_sn,$bill_no)
+    {
+        $date = date('Ymd', $time);
+        $seq = $date . $bill_no;
+
+        $user_id = $_SESSION['member_id'];
+        $config = Cmb::config();
+        $param = [
+            'strKey' => $config['singKey'],
+            'strDate' => $date,
+            'strBranchID' => $config['BranchID'],
+            'strCono' => $config['CoNo'],
+            'strBillNo' => $bill_no,
+            'strAmount' => "{$payprice}",
+            'strMerchantPara' => "pay_sn={$pay_sn}#order_sn={$order_sn}#member_id={$user_id}",
+            'strMerchantUrl' => $config['result_url'],
+            'strPayerID' => "{$user_id}",
+            'strPayeeID' => '',
+            'strClientIP' => $_SERVER['REMOTE_ADDR'],
+            'strGoodsType' => '54011600',
+            'strReserved' => join('', [
+                '<Protocol>',
+                '<PNo>' . $user_id . '</PNo>',
+                '<TS>' . date('YmdHis', $time) . '</TS>',
+                '<MchNo>' . $config['MchNo'] . '</MchNo>',
+                '<Seq>' . $seq . '</Seq>',
+                '<URL>' . self::notify_signurl . '</URL>',
+                '</Protocol>',
+            ])
+        ];
+
+        return $param;
+    }
+
+    private function genMerchantCode($param)
+    {
+        $str = '';
+        if (!empty($param['strClientIP'])) {
+            $str .= '<$ClientIP$>' . $param['strClientIP'] . '</$ClientIP$>';
+        }
+        if (!empty($param['strGoodsType'])) {
+            $str .= '<$GoodsType$>' . $param['strGoodsType'] . '</$GoodsType$>';
+        }
+        if (!empty($param['strReserved'])) {
+            $str .= '<$Reserved$>' . $param['strReserved'] . '</$Reserved$>';
+        }
+
+        $rnd = mt_rand();
+        $str = $rnd . '|' . $param['strPayerID'] . '<$CmbSplitter$>' . $param['strPayeeID'] . $str;
+        $rc4Key = md5($param['strKey']);
+        $rc4Key = pack('H*', $rc4Key);
+        $rc4Val = openssl_encrypt($str, "RC4", $rc4Key, true);
+        $rc4Val = base64_encode($rc4Val);
+        $rc4Val = str_replace('+', '*', $rc4Val);
+
+        $sha1Val = $param['strKey'] . $rc4Val . $param['strDate']
+            . $param['strBranchID'] . $param['strCono'] . $param['strBillNo']
+            . $param['strAmount'] . $param['strMerchantPara'] . $param['strMerchantUrl'];
+        $sha1Val = sha1($sha1Val);
+
+        return "|{$rc4Val}|{$sha1Val}";
+    }
+}

+ 98 - 0
helper/pay/wxpay.php

@@ -0,0 +1,98 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: stanley-king
+ * Date: 16/9/21
+ * Time: 下午7:53
+ */
+
+namespace Pay;
+
+define(WXPAY_PATHEX, BASE_DATA_PATH . '/api/wxpay');
+require_once(WXPAY_PATHEX . '/lib/WxPay.Api.php');
+require_once(WXPAY_PATHEX . '/lib/WxPay.Config.php');
+require_once(WXPAY_PATHEX . '/lib/WxPay.Data.php');
+require_once(WXPAY_PATHEX . '/lib/WxPay.Exception.php');
+require_once(WXPAY_PATHEX . '/lib/WxPay.Notify.php');
+
+use \WxPayUnifiedOrder;
+use \WxPayApi;
+use \Log;
+use \WxPayConfig;
+
+class wxpay implements IPay
+{
+    const wx_notifyurl  = BASE_SITE_URL . '/mobile/wxnotify.php';
+    const wx_orderquery = 'https://api.mch.weixin.qq.com/pay/orderquery';
+
+    public function gen_pay($pay_sn,$fee,$order_sn,$subject)
+    {
+        $input = new WxPayUnifiedOrder();
+        $input->SetBody($subject); //商品或支付单简要描述
+        $input->SetAttach($pay_sn); //附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
+        $out_trade_no = $pay_sn . sprintf("%03d",mt_rand(0,999)); //给微信用的每次重新生成的商户订单SN, 避免二次支付, 数额修改导致支付失败
+        $input->SetOut_trade_no($out_trade_no);//商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
+
+        $input->SetTotal_fee("{$fee}");//订单总金额,单位为分,详见支付金额
+        $input->SetTime_start(date("YmdHis")); //订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
+        $input->SetTime_expire(date("YmdHis", time() + 600));//订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
+        $input->SetNotify_url(self::wx_notifyurl);
+        $input->SetTrade_type("APP");//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里,MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口
+        $order = WxPayApi::unifiedOrder($input);
+
+        $sorder = $this->toString($order);
+        Log::record($sorder, Log::DEBUG);
+
+        if (array_key_exists('err_code', $order)) {
+            return false;
+        }
+
+        $ret['appid'] = $order["appid"];
+        $ret['noncestr'] = WxPayApi::getNonceStr();
+        $ret['package'] = 'Sign=WXPay';
+        $ret['partnerid'] = WxPayConfig::MCHID;
+        $ret['prepayid'] = $order['prepay_id'];
+        $timeStamp = time();
+        $ret['timestamp'] = "{$timeStamp}";
+        $ret['sign'] = $this->make_sign($ret);
+
+        return array("data" => $ret);
+    }
+
+    private function toString($order)
+    {
+        $ret = '';
+        foreach ($order as $key => $val) {
+            $ret .= $key . "=" . $val;
+            $ret .= '&';
+        }
+
+        return $ret;
+    }
+    private function make_sign($values)
+    {
+        //签名步骤一:按字典序排序参数
+        ksort($values);
+        $string = $this->to_url_params($values);
+        //签名步骤二:在string后加入KEY
+        $string = $string . "&key=" . WxPayConfig::KEY;
+        //签名步骤三:MD5加密
+        $string = md5($string);
+        //签名步骤四:所有字符转为大写
+        $result = strtoupper($string);
+        return $result;
+    }
+
+    private function to_url_params($values)
+    {
+        $buff = "";
+        foreach ($values as $k => $v) {
+            if ($k != "sign" && $v != "" && !is_array($v)) {
+                $buff .= $k . "=" . $v . "&";
+            }
+        }
+
+        $buff = trim($buff, "&");
+        return $buff;
+    }
+}

+ 78 - 1
helper/pay_helper.php

@@ -6,9 +6,17 @@
  * Time: 上午11:12
  */
 
+
+
+
 require_once (BASE_ROOT_PATH . "/helper/session_helper.php");
 require_once (BASE_ROOT_PATH . '/helper/bonus_helper.php');
 
+require_once (BASE_ROOT_PATH . '/helper/pay/IPay.php');
+require_once (BASE_ROOT_PATH . '/helper/pay/alipay.php');
+require_once (BASE_ROOT_PATH . '/helper/pay/wxpay.php');
+require_once (BASE_ROOT_PATH . '/helper/pay/cmbpay.php');
+
 class pay_helper
 {
     const store_user_id = 36429;
@@ -18,9 +26,78 @@ class pay_helper
     const def_bless = '熊猫美妆与你分享美丽的秘密~';
 
     public function __construct() {
+
+    }
+
+    static public function pay_bonus($pay_sn)
+    {
+        $member_info = array('member_id' => $_SESSION['member_id'], 'member_name'  => $_SESSION['member_name']);
+
+        $logic_payment = Logic('payment');
+        $logic_payment->payPredepositEx($pay_sn,$member_info);
+    }
+
+    static public function pay($pay_sn, $payment,$usebonus,&$err)
+    {
+        if($usebonus) {
+            self::pay_bonus($pay_sn);
+        }
+        $logic_payment = Logic('payment');
+        $payinfo = $logic_payment->getRealOrderInfo($pay_sn, $_SESSION['member_id']);
+        if (intval($payinfo['data']['api_pay_state']) != 0) {
+            $err = array('code' => errcode::ErrPayment, 'msg' => $payinfo['msg']);
+            return false;
+        }
+
+        $left_cents = intval(floatval($payinfo['data']['api_pay_amount']) * 100 + 0.5);
+        if($left_cents == 0)
+        {
+            $output['need_pay'] = false;
+            $payinfo = self::update_order($pay_sn, $pay_sn, 'bonus');  // 更新订单
+            // 推送到oms
+            if (isset($payinfo) && $payinfo['state'])
+            {
+                if(is_pushoms())
+                {
+                    $logic_delivery = Logic('delivery');
+                    $ret = $logic_delivery->putOrder($pay_sn, $pay_sn);
+                    if(empty($ret)) { //todo must add to 定时任务
+                        Log::record("Put order to oms error: pay_sn={$pay_sn},bonus pay.",Log::ERR);
+                    }
+                }
+            }
+            return $output;
+        }
+        else
+        {
+            $pay = null;
+            if($payment == "wxpay") {
+                $pay = new Pay\wxpay();
+            }
+            else if($payment == "alipay") {
+                $pay = new Pay\alipay();
+            }
+            else if($payment == "cmbpay") {
+                $pay = new Pay\cmbpay();
+            }
+            else {
+                $err = array('code' => errcode::ErrPayment, 'msg' => $payinfo['msg']);
+                return false;
+            }
+
+            $subject = $payinfo['data']['subject'];
+            $pay_sn = $payinfo['data']['pay_sn'];
+            $order_sn = $payinfo['data']['order_list'][0]['order_sn'];
+
+            $output['need_pay'] = true;
+            $third_param = $pay->gen_pay($pay_sn,$left_cents,$order_sn,$subject);
+            $output['param'] = $third_param;
+
+            return $output;
+        }
     }
 
-    public function success($pay_sn)
+    public function OnSuccess($pay_sn)
     {
         $logic_payment = Logic('payment');
         $result = $logic_payment->getRealOrderInfo($pay_sn);

+ 2 - 2
mobile/alipay_notify_url.php

@@ -1,6 +1,6 @@
 <?php
 
-define('ALIPAY_PATH', BASE_MOBILE_PATH . '/api/payment/alipay');
+define(ALIPAY_PATH, BASE_DATA_PATH . '/api/alipay');
 
 require_once(ALIPAY_PATH . '/alipay.config.php');
 require_once(ALIPAY_PATH . '/lib/alipay_notify.class.php');
@@ -51,7 +51,7 @@ if ($verify_result)
                     Log::record("update_order success: pay_sn={$pay_sn}", Log::DEBUG);
                 }
                 $pay = new pay_helper();
-                $pay->success($pay_sn);
+                $pay->OnSuccess($pay_sn);
 
                 echo('success');
                 return;

+ 125 - 0
mobile/cmbpay.php

@@ -0,0 +1,125 @@
+<?php
+
+
+
+/**
+ * 开启支付
+ */
+
+/**
+ * 产生 招商银行一网通 商户校验码
+ * @param  [type]  $strKey          [商户密钥]
+ * @param  [type]  $strDate         [订单日期]
+ * @param  [type]  $strBranchID     [开户分行号]
+ * @param  [type]  $strCono         [商户号]
+ * @param  [type]  $strBillNo       [订单号]
+ * @param  [type]  $strAmount       [订单金额]
+ * @param  [type]  $strMerchantPara [商户自定义参数]
+ * @param  [type]  $strMerchantUrl  [商户接受通知的URL]
+ * @param  [type]  $strPayerID      [付款方用户标识。用来唯一标识商户的一个用户。长度限制为40字节以内。]
+ * @param  [type]  $strPayeeID      [收款方的用户标识。生成规则同上。不要求商户提供用户的注册名称,但需要保证一个用户对应一个UserID。]
+ * @param  [type]  $strClientIP     [商户取得的客户端IP,如果有多个IP用逗号','分隔。长度限制为64字节。]
+ * @param  integer $strGoodsType [商品类型编码,长度限制为8字节。]
+ * @param  string $strReserved [保留字段,长度限制为1024字节。]
+ * @return [type]                   [商户校验码]
+ */
+function genMerchantCode($param)
+{
+    $str = '';
+    if (!empty($param['strClientIP'])) {
+        $str .= '<$ClientIP$>' . $param['strClientIP'] . '</$ClientIP$>';
+    }
+    if (!empty($param['strGoodsType'])) {
+        $str .= '<$GoodsType$>' . $param['strGoodsType'] . '</$GoodsType$>';
+    }
+    if (!empty($param['strReserved'])) {
+        $str .= '<$Reserved$>' . $param['strReserved'] . '</$Reserved$>';
+    }
+
+    $rnd = mt_rand();
+    $str = $rnd . '|' . $param['strPayerID'] . '<$CmbSplitter$>' . $param['strPayeeID'] . $str;
+    $rc4Key = md5($param['strKey']);
+    $rc4Key = pack('H*', $rc4Key);
+    $rc4Val = openssl_encrypt($str, "RC4", $rc4Key, true);
+    $rc4Val = base64_encode($rc4Val);
+    $rc4Val = str_replace('+', '*', $rc4Val);
+
+    $sha1Val = $param['strKey'] . $rc4Val . $param['strDate'] . $param['strBranchID'] . $param['strCono'] . $param['strBillNo'] . $param['strAmount'] . $param['strMerchantPara'] . $param['strMerchantUrl'];
+    $sha1Val = sha1($sha1Val);
+    // $sha1Val = bin2hex($sha1Val);
+
+    return "|{$rc4Val}|{$sha1Val}";
+}
+
+$time = time();
+$date = date('Ymd', $time);
+$bill_no = mt_rand(1000000000, 9999999999);
+$payprice = "0.01";
+$user_id = 1234;
+
+$config['mch_mo'] = 'P0021553';
+$config['branch_id'] = '0021';
+$config['co_no'] = '000100';
+$config['str_key'] = '';
+$config['pay_url'] = 'http://61.144.248.29:801/netpayment/BaseHttp.dll?PrePayEUserP';
+$config['result_url'] = 'http://127.0.0.1/pay/cmb-result';
+$config['sign_url'] = 'http://127.0.0.1/pay/cmb-sign';
+
+//商户校验码 数据
+$seq = $date . $bill_no;
+$param = [
+    'strKey' => $config['str_key'],
+    'strDate' => $date,
+    'strBranchID' => $config['branch_id'],
+    'strCono' => $config['co_no'],
+    'strBillNo' => $bill_no,
+    'strAmount' => $payprice,
+    'strMerchantPara' => "oid={$id}",
+    'strMerchantUrl' => $config['result_url'],
+    'strPayerID' => (string) $user_id,
+    'strPayeeID' => '',
+    'strClientIP' => '127.0.0.1',
+    'strGoodsType' => '54011600',
+    'strReserved' => join('', [
+        '<Protocol>',
+        '<PNo>' . $user_id . '</PNo>',
+        '<TS>' . date('YmdHis', $time) . '</TS>',
+        '<MchNo>' . $config['mch_mo'] . '</MchNo>',
+        '<Seq>' . $seq . '</Seq>',
+        '<URL>' . $config['sign_url'] . '</URL>',
+        '<Para>' . "id={$id}|seq={$$seq}" . '</Para>',
+        '</Protocol>',
+    ]),
+];
+
+//提交 数据
+$data = [
+    'BranchID' => $config['branch_id'],
+    'CoNo' => $config['co_no'],
+    'BillNo' => $bill_no,
+    'Amount' => $payprice,
+    'Date' => $date,
+    'ExpireTimeSpan' => '30',
+    'MerchantUrl' => $config['result_url'],
+    'MerchantPara' => "oid={$id}",
+    'MerchantCode' => genMerchantCode($param),
+    'MerchantRetUrl' => "http://127.0.0.1/success",
+    'MerchantRetPara' => "id={$id}|price={$payprice}",
+];
+
+echo "<pre>";
+var_dump($param, $data);
+echo "<\pre>";
+
+echo '正在努力跳转到一网通支付哦~';
+echo "<form action='{$config['pay_url']}' method='post' name='fm'>";
+foreach ($data as $k => $v) {
+    echo "<input type='hidden' name='" . htmlentities($k) . "' value='" . htmlentities($v) . "'/>";
+}
+echo "<input type='submit' value='付款'/>";
+echo "</form>";
+echo <<<END
+<script language="JavaScript">
+//    document.fm.submit();
+</script>
+END;

+ 77 - 12
mobile/control/member_buy.php

@@ -14,6 +14,7 @@ defined('InShopNC') or exit('Access Invalid!');
 
 require_once (BASE_ROOT_PATH . '/helper/predeposit_helper.php');
 require_once (BASE_ROOT_PATH . '/helper/buy_first.php');
+require_once (BASE_ROOT_PATH . '/helper/pay_helper.php');
 
 class member_buyControl extends mbMemberControl
 {
@@ -27,20 +28,9 @@ class member_buyControl extends mbMemberControl
         if(empty($cart_ids)) {
             return self::outerr(errcode::ErrParamter);
         }
-        else
-        {
-            $mod_cart = Model('cart');
-            $items = $mod_cart->listCart('db',array('cart_id' => array('in',$cart_ids)),false);
-            $id_num = [];
-            foreach ($items as $val)
-            {
-                $cart_id = $val['cart_id'];
-                $goods_num = $val['goods_num'];
-                $id_num[] = "{$cart_id}|{$goods_num}";
-            }
-        }
 
         $logic_buy = logic('buy');
+        $id_num = $this->pay_goods($cart_ids);
         //得到购买数据
         $result = $logic_buy->buyStep1($id_num, $_POST['ifcart'], $_SESSION['member_id'], $_SESSION['store_id']);
         if (!$result['state']) {
@@ -55,6 +45,57 @@ class member_buyControl extends mbMemberControl
         return self::outsuccess($result);
     }
 
+    public function step_secondOp()
+    {
+        $cart_ids = explode(',', urldecode($_POST['cart_id']));
+        if(empty($cart_ids)) {
+            return self::outerr(errcode::ErrParamter);
+        }
+
+        $param = array();
+        $param['ifcart'] = $_POST['ifcart'];
+        $param['cart_id'] = $this->pay_goods($cart_ids);
+        $param['address_id'] = $_POST['address_id'];
+        $param['invoice_id'] = $_POST['invoice_id'];
+
+        $param['vat_hash'] = $_POST['vat_hash'];
+        $param['offpay_hash'] = $_POST['offpay_hash'];
+        $param['offpay_hash_batch'] = $_POST['offpay_hash_batch'];
+
+        $param['voucher'] = array();
+        //手机端暂时不做支付留言,页面内容太多了
+        //$param['pay_message'] = json_decode($_POST['pay_message']);
+        $param['pd_pay'] = 0;
+        $param['rcb_pay'] = 0;
+        $param['password'] = "";
+        $param['fcode'] = "";
+        $param['order_from'] = 2; //从手机来
+        $param['pay_name'] = "online";
+
+        $logic_buy = logic('buy');
+
+        $result = $logic_buy->buyStep2($param, $_SESSION['member_id'], $_SESSION['member_name'], $_SESSION['member_email']);
+        if (!$result['state']) {
+            return self::outerr(errcode::ErrOrder, $result['msg']);
+        }
+        else
+        {
+            $pay_sn = $result['data']['pay_sn'];
+            $payment = $_POST['payment'];
+            $usebonus = $_POST['usebonus'];
+
+            $out_put = pay_helper::pay($pay_sn,$payment,$usebonus,$err);
+            if($out_put == false) {
+//                $out_put['payment'] = $payment;
+//                $out_put['pay_sn'] = $pay_sn;
+                return self::outerr($err['code'],$err['msg']);
+            } else {
+                $out_put['payment'] = $payment;
+                return self::outsuccess($out_put);
+            }
+        }
+    }
+
     /**
      * 购物车、直接购买第一步:选择收获地址和配置方式
      */
@@ -117,6 +158,7 @@ class member_buyControl extends mbMemberControl
         $param['ifcart'] = $_POST['ifcart'];
         $param['cart_id'] = explode(',', urldecode($_POST['cart_id']));
         $param['address_id'] = $_POST['address_id'];
+
         $param['vat_hash'] = $_POST['vat_hash'];
         $param['offpay_hash'] = $_POST['offpay_hash'];
         $param['offpay_hash_batch'] = $_POST['offpay_hash_batch'];
@@ -183,5 +225,28 @@ class member_buyControl extends mbMemberControl
             return self::outerr(errcode::ErrOrder, '地址修改失败');
         }
     }
+
+    /**
+     * @param $cart_ids
+     * @return array
+     */
+    private function pay_goods($cart_ids)
+    {
+        if ($_POST['ifcart'] == true)
+        {
+            $mod_cart = Model('cart');
+            $items = $mod_cart->listCart('db', array('cart_id' => array('in', $cart_ids)), false);
+            $id_num = [];
+            foreach ($items as $val) {
+                $cart_id = $val['cart_id'];
+                $goods_num = $val['goods_num'];
+                $id_num[] = "{$cart_id}|{$goods_num}";
+            }
+            return $id_num;
+        } else {
+            $id_num = $cart_ids;
+            return $id_num;
+        }
+    }
 }
 

+ 1 - 1
mobile/wxnotify.php

@@ -67,7 +67,7 @@ try
                 $ret = $logic_delivery->putOrder($pay_sn, $trade_no);
             }
             $pay = new pay_helper();
-            $pay->success($pay_sn);
+            $pay->OnSuccess($pay_sn);
         }
 
         $ret_wx['return_code'] = 'SUCCESS';