logdir = Yii::getAlias('@runtime').DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'pay'.DIRECTORY_SEPARATOR; dir_create($this->logdir); $this->userInfo = Identify::getUserInfo(); $this->payconfig = Yii::$app->params['pay']; $this->coinconfig = Yii::$app->params['coin']; if($this->payconfig['weixin_pay']) { // 商户号 $merchantId = $this->payconfig['weixin_mchid']; // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名 $merchantPrivateKeyFilePath = 'file://'.$this->payconfig['weixin_apiclient_key']; $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE); // 「商户API证书」的「证书序列号」 $merchantCertificateSerial = $this->payconfig['weixin_serialnumber']; // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名 $platformCertificateFilePath = 'file://'.$this->payconfig['weixin_cert']; $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC); // 从「微信支付平台证书」中获取「证书序列号」 $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath); // 构造一个 APIv3 客户端实例 $this->wechatPay = Builder::factory([ 'mchid' => $merchantId, 'serial' => $merchantCertificateSerial, 'privateKey' => $merchantPrivateKeyInstance, 'certs' => [ $platformCertificateSerial => $platformPublicKeyInstance, ], ]); } } public function actionDo() { } //处理来自手机端的支付请求 public function actionDowap() { $initData = $_POST; extract($initData); //解决微信跳转后参数传递问题 $state = Yii::$app->request->get('state'); if(!empty($state)&&$state=='MR8888') { $initData = $_GET; extract($initData); } //购买文档时候,调整回跳地址 if($act=='buydoc') { $doc = DocReal::findOne($id); if($doc->doc_type==2) { $return_url = SiteUrl::colDetail($id,$order_sn); } else { $return_url = SiteUrl::docDetail($id,$order_sn); } } //支付宝 if($pay_method=='apw_pay') { require_once(Yii::getAlias('@payerdrivers').'/alipaywap/wappay/service/AlipayTradeService.php'); require_once(Yii::getAlias('@payerdrivers').'/alipaywap/wappay/buildermodel/AlipayTradeWapPayContentBuilder.php'); $order = $this->_initOrder($initData); $config = array ( //应用ID,您的APPID。 'app_id' => $this->payconfig['apw_appid'], //商户私钥,您的原始格式RSA私钥 'merchant_private_key' => $this->payconfig['apw_merchant_private_key'], //异步通知地址 'notify_url' => $this->payconfig['apw_notify_url'], //同步跳转 'return_url' => $return_url, //编码格式 'charset' => "UTF-8", //签名方式 'sign_type'=>"RSA2", //支付宝网关 'gatewayUrl' => "https://openapi.alipay.com/gateway.do", //支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 'alipay_public_key' => $this->payconfig['apw_alipay_public_key'], //日志路径 'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt', ); //商户订单号,商户网站订单系统中唯一订单号,必填 $out_trade_no = trim($order_sn); //订单名称,必填 $subject = $order->remark; //付款金额,必填 $total_amount = trim($total_price); //商品描述,可空 $body = ''; //超时时间 $timeout_express="1m"; $payRequestBuilder = new \AlipayTradeWapPayContentBuilder(); $payRequestBuilder->setBody($body); $payRequestBuilder->setSubject($subject); $payRequestBuilder->setOutTradeNo($out_trade_no); $payRequestBuilder->setTotalAmount($total_amount); $payRequestBuilder->setTimeExpress($timeout_express); $payResponse = new \AlipayTradeService($config); $result=$payResponse->wapPay($payRequestBuilder,$config['return_url'],$config['notify_url']); return ; } //微信公众号支付 if($pay_method=='weixin_pay'){ $args = array( 'appId'=>$this->payconfig['weixin_appid'], 'appSecret'=>$this->payconfig['weixin_appsecret'], 'token'=>$this->payconfig['weixin_token'], ); $weixin = new WeiXin($args); $weixin->init(); //JS API接口支付(仅在微信里面) if(isset($_GET['code'])&&$_GET['code']!='') { $order = $this->_initOrder($initData); $result = $weixin->getOauthAccessToken($_GET['code']); try { $pay_money = max($total_price, 0.01); $resp = $this->wechatPay->chain('v3/pay/transactions/jsapi') ->post(['json' => [ 'appid' => $this->payconfig['weixin_appid'], 'mchid' => $this->payconfig['weixin_mchid'], 'out_trade_no' => $order_sn, 'description' => $order->remark, 'notify_url' => $this->payconfig['weixin_notify_url'], 'amount' => [ 'total' => $pay_money*100, 'currency' => 'CNY' ], 'payer' => [ 'openid'=>$result['openid'] ], ]]); if($resp->getStatusCode()==200) { $respBody = json_decode($resp->getBody(),true); $prepay_id = $respBody['prepay_id']; if($prepay_id) { $timestamp = TIMESTAMP; $noncestr = TIMESTAMP; $signstr = $this->getWechartSign($this->payconfig['weixin_appid'], strval($timestamp), strval($noncestr), 'prepay_id='.$prepay_id); $jsApiParameters = json_encode([ 'appId' => $this->payconfig['weixin_appid'], 'timeStamp' => strval($timestamp) , 'package' => 'prepay_id=' . $respBody['prepay_id'], 'paySign' => $signstr, 'nonceStr' => strval($noncestr) ]); ob_clean(); require_once(Yii::getAlias('@app/views').DIRECTORY_SEPARATOR.'pay'.DIRECTORY_SEPARATOR.$pay_method.'.php'); exit; } else { exit('支付失败'); } } else { exit('支付失败'); } } catch (\Exception $e) { exit($e->getMessage()); } } else { $redirectUrl = get_url(); $queryParams = http_build_query($initData); if(strpos($redirectUrl,'?')===false) { $redirectUrl = $redirectUrl.'?'.urldecode($queryParams); } else { $redirectUrl = $redirectUrl.'&'.urldecode($queryParams); } $codeUrl = $weixin->getWebAuthUrl(urlencode($redirectUrl),'snsapi_base','MR8888'); echo ""; } } //微信H5支付 if($pay_method=='wxh5_pay'){ $order = $this->_initOrder($initData); // 官方提供网址 $url = "https://api.mch.weixin.qq.com/v3/pay/transactions/h5"; //拆解为:[scheme=>https,host=>api.mch.weixin.qq.com,path=>/v3/pay/transactions/native] $urlarr = parse_url($url); $time = time(); //时间戳 $noncestr = $time; $appid = $this->payconfig['wxh5_appid'];//appID $mchid = $this->payconfig['wxh5_mchid'];//商户ID //秘钥序列号 可在这个网址中查询 https://myssl.com/cert_decode.html $xlid = $this->payconfig['wxh5_serialnumber']; $data = []; $data['appid'] = $appid; $data['mchid'] = $mchid; $data['description'] = $order->remark;//商品描述 $data['out_trade_no'] = $order_sn;//订单编号,订单号在微信支付里是唯一的 $data['notify_url'] = $this->payconfig['wxh5_notify_url'];//需根据自己的情况修改回调接口,也可以为空 $data['amount']['total'] = max($total_price, 0.01)*100;//金额 单位 分 $data['scene_info']['payer_client_ip'] = $_SERVER['REMOTE_ADDR'];//场景 $data['scene_info']['h5_info']['type'] = "Wap";//场景 $data = json_encode($data); //变为json格式 // echo "
";
// print_r($data);
// echo "";die;
//签名,包含了$data数据、微信指定地址、随机数和时间
$key = $this->getSign($data,$urlarr['path'],$noncestr,$time);
//头部信息
$token = sprintf('mchid="%s",serial_no="%s",nonce_str="%s",timestamp="%d",signature="%s"',$mchid,$xlid,$noncestr,$time,$key);
// echo $token;die;
$header = array(
'Content-Type:'.'application/json; charset=UTF-8',
'Accept:application/json',
'User-Agent:*/*',
'Authorization: WECHATPAY2-SHA256-RSA2048 '.$token
);
//向微信接口地址提交json格式的$data和header的头部信息,得到返回值
$ret = $this->curl_post_https($url,$data,$header);
//如果是个code_url网址,则说明成功了。在浏览器里打开该地址测试是否能付钱。
// echo $ret;
$resInfo = json_decode($ret, true);
// var_dump($resInfo['h5_url']);die;
// header("Location: ".$resInfo['h5_url']);
echo "";
exit;
}
//虎皮椒
if($pay_method=='hpwx_pay'||$pay_method=='hpali_pay')
{
require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
$order = $this->_initOrder($initData);
if($pay_method=='hpwx_pay')
{
$appid = Yii::$app->params['pay']['hpwx_appid'];
$appsecret = Yii::$app->params['pay']['hpwx_appsecret'];
$my_plugin_id = Yii::$app->params['pay']['hpwx_pluginid'];
$subject = $order->remark;
$notify_url = Yii::$app->params['pay']['hpwx_notify_url'];
//$return_url = Yii::$app->params['pay']['hpwx_return_url'];
}
else if($pay_method=='hpali_pay')
{
$appid = Yii::$app->params['pay']['hpali_appid'];
$appsecret = Yii::$app->params['pay']['hpali_appsecret'];
$my_plugin_id = Yii::$app->params['pay']['hpali_pluginid'];
$subject = $order->remark;
$notify_url = Yii::$app->params['pay']['hpali_notify_url'];
//$return_url = Yii::$app->params['pay']['hpali_return_url'];
}
$data=array(
'version' => '1.1',//固定值,api 版本,目前暂时是1.1
'lang' => 'zh-cn', //必须的,zh-cn或en-us 或其他,根据语言显示页面
'plugins' => $my_plugin_id,//必须的,根据自己需要自定义插件ID,唯一的,匹配[a-zA-Z\d\-_]+
'appid' => $appid, //必须的,APPID
'trade_order_id'=> $order_sn, //必须的,网站订单ID,唯一的,匹配[a-zA-Z\d\-_]+
'payment' => $pay_method=='hpwx_pay'?'wechat':'alipay',//必须的,支付接口标识:wechat(微信接口)|alipay(支付宝接口)
'total_fee' => max(0,$total_price),//人民币,单位精确到分(测试账户只支持0.1元内付款)
'title' => $subject, //必须的,订单标题,长度32或以内
'time' => TIMESTAMP,//必须的,当前时间戳,根据此字段判断订单请求是否已超时,防止第三方攻击服务器
'notify_url'=> $notify_url, //必须的,支付成功异步回调接口
'return_url'=> $return_url,//必须的,支付成功后的跳转地址
'callback_url'=> APP_URL,//必须的,支付发起地址(未支付或支付失败,系统会会跳到这个地址让用户修改支付信息)
'modal'=>null, //可空,支付模式 ,可选值( full:返回完整的支付网页; qrcode:返回二维码; 空值:返回支付跳转链接)
'nonce_str' => str_shuffle(TIMESTAMP)//必须的,随机字符串,作用:1.避免服务器缓存,2.防止安全密钥被猜测出来
);
$hashkey = $appsecret;
$data['hash'] = \XH_Payment_Api::generate_xh_hash($data,$hashkey);
$url = 'https://api.xunhupay.com/payment/do.html';
try {
$response = \XH_Payment_Api::http_post($url, json_encode($data));
$result = $response?json_decode($response,true):null;
if(!$result){
echo_json([
'error' => 1,
'msg' => 'Internal server error',
'code'=>500
]);
}
$hash = \XH_Payment_Api::generate_xh_hash($result,$hashkey);
if(!isset( $result['hash'])|| $hash!=$result['hash']){
echo_json([
'error' => 1,
'msg' => 'Invalid sign!',
'code'=>500
]);
}
if($result['errcode']!=0){
echo_json([
'error' => 1,
'msg' => $result['errmsg'],
'code'=>$result['errcode']
]);
}
$pay_url = $result['url'];
header("Location: $pay_url");
exit;
} catch (\Exception $e) {
$result = [
'error' => 1,
'msg' => $e->getMessage(),
'data' => [],
'code'=>200
];
echo_json($result);
}
}
}
//生成二维码付款图片
public function actionCodeimg()
{
$initData = $_POST;
extract($initData);
//微信支付
if($paymethod=='weixin_pay')
{
if($this->_checkOrder($order_sn,$paymethod))
{
$order_sn = getUniOrderNo();
$result = [
'error' => 2,
'msg' => '需要生成新订单',
'data' => ['order_sn'=>$order_sn],
'code'=>200
];
echo_json($result);
}
$order = $this->_initOrder($initData);
try {
$pay_money = max($total_price, 0.01);
$resp = $this->wechatPay->chain('v3/pay/transactions/native')
->post(['json' => [
'mchid' => $this->payconfig['weixin_mchid'],
'out_trade_no' => $order_sn,
'appid' => $this->payconfig['weixin_appid'],
'description' => $order->remark,
'notify_url' => $this->payconfig['weixin_notify_url'],
'amount' => [
'total' => $pay_money*100,
'currency' => 'CNY'
],
]]);
if($resp->getStatusCode()==200)
{
$respBody = json_decode($resp->getBody(),true);
$code_url = APP_URL.'ajax/qrcode/?url='.$respBody['code_url'];
$result = [
'error' => 0,
'msg' => '操作成功',
'data' => ['code_url'=>$code_url,'order_sn'=>$order_sn],
'code'=>200
];
echo_json($result);
}
} catch (\Exception $e) {
$result = [
'error' => 1,
'msg' => $e->getMessage(),
'data' => [],
'code'=>200
];
echo_json($result);
// 进行错误处理
/*echo $e->getMessage(), PHP_EOL;
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
}
echo $e->getTraceAsString(), PHP_EOL;*/
}
}
//支付宝PC
if($paymethod=='apd_pay')
{
require_once(Yii::getAlias('@payerdrivers').'/alipaypage/pagepay/service/AlipayTradeService.php');
require_once(Yii::getAlias('@payerdrivers').'/alipaypage/pagepay/buildermodel/AlipayTradePagePayContentBuilder.php');
if($this->_checkOrder($order_sn,$paymethod))
{
$order_sn = getUniOrderNo();
$result = [
'error' => 2,
'msg' => '需要生成新订单',
'data' => ['order_sn'=>$order_sn],
'code'=>200
];
echo_json($result);
}
$order = $this->_initOrder($initData);
$config = array (
//应用ID,您的APPID。
'app_id' => $this->payconfig['apd_appid'],
//商户私钥
'merchant_private_key' => $this->payconfig['apd_merchant_private_key'],
//异步通知地址
'notify_url' => $this->payconfig['apd_notify_url'],
//同步跳转
'return_url' => $this->payconfig['apd_return_url'],
//编码格式
'charset' => "UTF-8",
//签名方式
'sign_type'=>"RSA2",
//支付宝网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
'alipay_public_key' => $this->payconfig['apd_alipay_public_key'],
//日志路径
'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt',
);
//商户订单号,商户网站订单系统中唯一订单号,必填
$out_trade_no = trim($order_sn);
//订单名称,必填
$subject = $order->remark;
//付款金额,必填
$total_amount = trim($total_price);
//商品描述,可空
$body = '';
//构造参数
$payRequestBuilder = new \AlipayTradePagePayContentBuilder();
$payRequestBuilder->setBody($body);
$payRequestBuilder->setSubject($subject);
$payRequestBuilder->setTotalAmount($total_amount);
$payRequestBuilder->setOutTradeNo($out_trade_no);
$payRequestBuilder->setQrPayMode(4);
$payRequestBuilder->setQrPayWidth(110);
$aop = new \AlipayTradeService($config);
$response = $aop->pagePay($payRequestBuilder,$config['return_url'],$config['notify_url']);
//输出表单
$result = [
'error' => 0,
'msg' => '操作成功',
'data' => ['code_url'=>APP_URL.'pay/alicode/?response='.urlencode($response),'order_sn'=>$order_sn],
'code'=>200
];
echo_json($result);
}
//虎皮椒
if($paymethod=='hpwx_pay'||$paymethod=='hpali_pay')
{
require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
if($this->_checkOrder($order_sn,$paymethod))
{
$order_sn = getUniOrderNo();
$result = [
'error' => 2,
'msg' => '需要生成新订单',
'data' => ['order_sn'=>$order_sn],
'code'=>200
];
echo_json($result);
}
$order = $this->_initOrder($initData);
if($paymethod=='hpwx_pay')
{
$appid = Yii::$app->params['pay']['hpwx_appid'];
$appsecret = Yii::$app->params['pay']['hpwx_appsecret'];
$my_plugin_id = Yii::$app->params['pay']['hpwx_pluginid'];
$subject = $order->remark;
$notify_url = Yii::$app->params['pay']['hpwx_notify_url'];
$return_url = Yii::$app->params['pay']['hpwx_return_url'];
}
else if($paymethod=='hpali_pay')
{
$appid = Yii::$app->params['pay']['hpali_appid'];
$appsecret = Yii::$app->params['pay']['hpali_appsecret'];
$my_plugin_id = Yii::$app->params['pay']['hpali_pluginid'];
$subject = $order->remark;
$notify_url = Yii::$app->params['pay']['hpali_notify_url'];
$return_url = Yii::$app->params['pay']['hpali_return_url'];
}
$data=array(
'version' => '1.1',//固定值,api 版本,目前暂时是1.1
'lang' => 'zh-cn', //必须的,zh-cn或en-us 或其他,根据语言显示页面
'plugins' => $my_plugin_id,//必须的,根据自己需要自定义插件ID,唯一的,匹配[a-zA-Z\d\-_]+
'appid' => $appid, //必须的,APPID
'trade_order_id'=> $order_sn, //必须的,网站订单ID,唯一的,匹配[a-zA-Z\d\-_]+
'payment' => $paymethod=='hpwx_pay'?'wechat':'alipay',//必须的,支付接口标识:wechat(微信接口)|alipay(支付宝接口)
'total_fee' => max(0,trim($total_price)),//人民币,单位精确到分(测试账户只支持0.1元内付款)
'title' => $subject, //必须的,订单标题,长度32或以内
'time' => TIMESTAMP,//必须的,当前时间戳,根据此字段判断订单请求是否已超时,防止第三方攻击服务器
'notify_url'=> $notify_url, //必须的,支付成功异步回调接口
'return_url'=> $return_url,//必须的,支付成功后的跳转地址
'callback_url'=> APP_URL,//必须的,支付发起地址(未支付或支付失败,系统会会跳到这个地址让用户修改支付信息)
'modal'=>null, //可空,支付模式 ,可选值( full:返回完整的支付网页; qrcode:返回二维码; 空值:返回支付跳转链接)
'nonce_str' => str_shuffle(TIMESTAMP)//必须的,随机字符串,作用:1.避免服务器缓存,2.防止安全密钥被猜测出来
);
$hashkey = $appsecret;
$data['hash'] = \XH_Payment_Api::generate_xh_hash($data,$hashkey);
$url = 'https://api.xunhupay.com/payment/do.html';
try {
$response = \XH_Payment_Api::http_post($url, json_encode($data));
$result = $response?json_decode($response,true):null;
if(!$result){
echo_json([
'error' => 1,
'msg' => 'Internal server error',
'code'=>500
]);
}
$hash = \XH_Payment_Api::generate_xh_hash($result,$hashkey);
if(!isset( $result['hash'])|| $hash!=$result['hash']){
echo_json([
'error' => 1,
'msg' => 'Invalid sign!',
'code'=>500
]);
}
if($result['errcode']!=0){
echo_json([
'error' => 1,
'msg' => $result['errmsg'],
'code'=>$result['errcode']
]);
}
if($paymethod=='hpwx_pay'){
echo_json( [
'error' => 0,
'msg' => '操作成功',
'data' => ['code_url'=>$result['url_qrcode'],'order_sn'=>$order_sn],
'code'=>200
]);
}else{
echo_json([
'error' => 0,
'msg' => '操作成功',
'data' => ['code_url'=>APP_URL.'pay/paycode/?response='.urlencode($result['url_qrcode']),'order_sn'=>$order_sn],
'code'=>200
]);
}
} catch (\Exception $e) {
$result = [
'error' => 1,
'msg' => $e->getMessage(),
'data' => [],
'code'=>200
];
echo_json($result);
}
}
}
//生成支付宝二维码
public function actionAlicode()
{
echo $_GET['response'];
}
//对支付二维码做缩略图
public function actionPaycode()
{
$fileHash = md5($_GET['response']);
$dstrootdir = THUMB_PATH.'paycode'.DIRECTORY_SEPARATOR;
dir_create($dstrootdir);
$resize = new \app\common\components\ResizeImage($_GET['response'], 110, 110,$fileHash, 0,0,$dstrootdir);
$dstimg = $resize->dstimg;
ob_clean();
header('Content-type: image/jpeg');
echo file_get_contents($dstimg);
exit;
}
//微信支付回调
public function actionWeixincallback(){
$headers = $this->_getAllHeader();
//$this->payLog(var_export($headers,true));
$inWechatpaySignature = $headers['wechatpay-signature'];
$inWechatpayTimestamp = $headers['wechatpay-timestamp'];
$inWechatpaySerial = $headers['wechatpay-serial'];
$inWechatpayNonce = $headers['wechatpay-nonce'];
$inBody = file_get_contents('php://input');
$apiv3Key = $this->payconfig['weixin_v3secret'];// 在商户平台上设置的APIv3密钥
$platformPublicKeyInstance = Rsa::from('file://'.$this->payconfig['weixin_cert'], Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量,允许5分钟之内的偏移
$timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
$verifiedStatus = Rsa::verify(
// 构造验签名串
Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
$inWechatpaySignature,
$platformPublicKeyInstance
);
if ($timeOffsetStatus && $verifiedStatus) {
// 转换通知的JSON文本消息为PHP Array数组
$inBodyArray = (array)json_decode($inBody, true);
// 使用PHP7的数据解构语法,从Array中解构并赋值变量
['resource' => [
'ciphertext' => $ciphertext,
'nonce' => $nonce,
'associated_data' => $aad
]] = $inBodyArray;
// 加密文本消息解密
$inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
// 把解密后的文本转换为PHP Array数组
$inBodyResourceArray = (array)json_decode($inBodyResource, true);
//$this->payLog(var_export($inBodyResourceArray,true));
if ($inBodyResourceArray['trade_state'] == 'SUCCESS') {
// 这里写业务逻辑
if($this->_processOrder($inBodyResourceArray['out_trade_no'],($inBodyResourceArray['amount']['payer_total']/100),1,
$inBodyResourceArray['payer']['openid']))
{
$result = ['code'=>'SUCCESS','message'=>'成功',];
echo_json($result);
}
}
}
}
//支付宝PC扫码支付回调
public function actionAlipaydirectnotify()
{
require_once(Yii::getAlias('@payerdrivers').'/alipaypage/pagepay/service/AlipayTradeService.php');
$config = array (
//应用ID,您的APPID。
'app_id' => $this->payconfig['apd_appid'],
//商户私钥
'merchant_private_key' => $this->payconfig['apd_merchant_private_key'],
//异步通知地址
'notify_url' => $this->payconfig['apd_notify_url'],
//同步跳转
'return_url' => $this->payconfig['apd_return_url'],
//编码格式
'charset' => "UTF-8",
//签名方式
'sign_type'=>"RSA2",
//支付宝网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
'alipay_public_key' => $this->payconfig['apd_alipay_public_key'],
//日志路径
'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt',
);
$arr=$_POST;
$alipaySevice = new \AlipayTradeService($config);
$alipaySevice->writeLog(var_export($_POST,true));
$result = $alipaySevice->check($arr);
/* 实际验证过程建议商户添加以下校验。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if($result) {//验证成功
//请在这里加上商户的业务逻辑程序代
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
//商户订单号
$out_trade_no = $_POST['out_trade_no'];
//支付宝交易号
$trade_no = $_POST['trade_no'];
//交易状态
$trade_status = $_POST['trade_status'];
$total_amount = $_POST['total_amount'];
if($_POST['trade_status'] == 'TRADE_FINISHED') {
$this->_processOrder($out_trade_no,$total_amount,3);
}
else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
$this->_processOrder($out_trade_no,$total_amount,3);
}
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
echo "success"; //请不要修改或删除
}else {
//验证失败
echo "fail";
}
}
//支付成功之后的虎皮椒回调处理(微信)
public function actionHpwxnotify()
{
try
{
require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
$appid = Yii::$app->params['pay']['hpwx_appid'];
$appsecret = Yii::$app->params['pay']['hpwx_appsecret'];
$my_plugin_id = Yii::$app->params['pay']['hpwx_pluginid'];
$data = $_POST;
foreach ($data as $k=>$v){
$data[$k] = stripslashes($v);
}
if(!isset($data['hash'])||!isset($data['trade_order_id'])){
echo 'failed';exit;
}
//自定义插件ID,请与支付请求时一致
if(isset($data['plugins'])&&$data['plugins']!=$my_plugin_id){
echo 'failed';exit;
}
//APP SECRET
$appkey =$appsecret;
$hash =\XH_Payment_Api::generate_xh_hash($data,$appkey);
if($data['hash']!=$hash){
//签名验证失败
echo 'failed';exit;
}
//商户订单ID
$trade_order_id =$data['trade_order_id'];
$total_fee = $data['total_fee'];
if($data['status']=='OD'){
$this->_processOrder($trade_order_id,$total_fee,88);
echo 'success';
exit;
}else{
echo 'failed';exit;
}
}
catch(\Exception $e)
{
$this->payLog($e->getMessage());exit;
}
}
//支付成功之后的虎皮椒回调处理(支付宝)
public function actionHpalinotify()
{
try
{
require_once(Yii::getAlias('@payerdrivers').'/xunhupay/api.php');
$appid = Yii::$app->params['pay']['hpali_appid'];
$appsecret = Yii::$app->params['pay']['hpali_appsecret'];
$my_plugin_id = Yii::$app->params['pay']['hpali_pluginid'];
$data = $_POST;
foreach ($data as $k=>$v){
$data[$k] = stripslashes($v);
}
if(!isset($data['hash'])||!isset($data['trade_order_id'])){
echo 'failed';exit;
}
//自定义插件ID,请与支付请求时一致
if(isset($data['plugins'])&&$data['plugins']!=$my_plugin_id){
echo 'failed';exit;
}
//APP SECRET
$appkey =$appsecret;
$hash =\XH_Payment_Api::generate_xh_hash($data,$appkey);
if($data['hash']!=$hash){
//签名验证失败
echo 'failed';exit;
}
//商户订单ID
$trade_order_id =$data['trade_order_id'];
$total_fee = $data['total_fee'];
if($data['status']=='OD'){
$this->_processOrder($trade_order_id,$total_fee,99);
echo 'success';
exit;
}else{
echo 'failed';exit;
}
}
catch(\Exception $e)
{
$this->payLog($e->getMessage());exit;
}
}
//手机端支付宝回调
public function actionAlipaywapnotify()
{
require_once(Yii::getAlias('@payerdrivers').'/alipaywap/wappay/service/AlipayTradeService.php');
$config = array (
//应用ID,您的APPID。
'app_id' => $this->payconfig['apw_appid'],
//商户私钥,您的原始格式RSA私钥
'merchant_private_key' => $this->payconfig['apw_merchant_private_key'],
//异步通知地址
'notify_url' => $this->payconfig['apw_notify_url'],
//同步跳转
'return_url' => $this->payconfig['apw_return_url'],
//编码格式
'charset' => "UTF-8",
//签名方式
'sign_type'=>"RSA2",
//支付宝网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
'alipay_public_key' => $this->payconfig['apw_alipay_public_key'],
//日志路径
'log_path' => $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt',
);
$arr=$_POST;
$alipaySevice = new \AlipayTradeService($config);
$alipaySevice->writeLog(var_export($_POST,true));
$this->payLog(var_export($_POST,true));
$result = $alipaySevice->check($arr);
/* 实际验证过程建议商户添加以下校验。
1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
4、验证app_id是否为该商户本身。
*/
if($result) {//验证成功
//请在这里加上商户的业务逻辑程序代
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
//商户订单号
$out_trade_no = $_POST['out_trade_no'];
//支付宝交易号
$trade_no = $_POST['trade_no'];
//交易状态
$trade_status = $_POST['trade_status'];
$total_amount = $_POST['total_amount'];
if($_POST['trade_status'] == 'TRADE_FINISHED') {
$this->_processOrder($out_trade_no,$total_amount,3);
}
else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
$this->_processOrder($out_trade_no,$total_amount,3);
}
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
echo "success"; //请不要修改或删除
}else {
//验证失败
echo "fail";
}
}
//检测订单是否存在
private function _checkOrder($order_sn,$pay_method)
{
$exist = ShoppingPaycode::find()->where("order_sn='".$order_sn."' and pay_method='".$pay_method."'")->exists();
if($exist)
{
return true;
}
else
{
$paycode = new ShoppingPaycode();
$paycode->order_sn = $order_sn;
$paycode->pay_method = $pay_method;
$paycode->create_time = TIMESTAMP;
$paycode->save();
return false;
}
}
//初始化订单
private function _initOrder($initData)
{
extract($initData);
$order = ShoppingOrder::find()->where("order_sn='".$order_sn."'")->one();
if($order)
{
return $order;
}
else
{
//充值金币
if($act=='coinrecharge'){
$pay_credit = $act.'_'.$coin_num;
$order_type = 2;
$remark = '充值'.Yii::$app->params['coin']['coin_name'];
}
//开通VIP
if($act=='buyvip'){
$userVipType = UserVipType::findOne($vip_type);
$pay_credit = $act.'_'.$vip_type;
$order_type = 3;
$remark = '开通VIP-'.$userVipType->title;
}
//购买文档
if($act=='buydoc'){
$pay_credit = $act.'_'.$id;
$order_type = 1;
$remark = '购买文档';
}
//百度搜索词
$baidukw = \app\common\helpers\Cookie::getCookie(Yii::$app->params['baidukwName']);
$order = new ShoppingOrder();
$order->user_id = intval($this->userInfo['user_id']);
$order->order_sn = $order_sn;
$order->pay_credit = $pay_credit;
$order->total_price = $total_price;
$order->discount_price = $discount_price;
$order->remark = $remark;
$order->order_type = $order_type;
$order->status = 0;
$order->ad_words = $baidukw?urldecode($baidukw):'';
$order->request_from = REQUEST_FROM;
$order->create_time = TIMESTAMP;
$order->save();
return $order;
}
}
// 获取header头的方法
private function _getAllHeader()
{
// 忽略获取的header数据。这个函数后面会用到。主要是起过滤作用
$ignore = array('host','accept','content-length','content-type','connection','accept-encoding');
$headers = array(); //这里大家有兴趣的话,可以打印一下。会出来很多的header头信息。咱们想要的部分,都是‘http_'开头的。所以下面会进行过滤输出。
foreach($_SERVER as $key=>$value){
if(substr($key, 0, 5)==='HTTP_'){ //这里取到的都是'http_'开头的数据。
//前去开头的前5位
$key = substr($key, 5); //把$key中的'_'下划线都替换为空字符串
$key = str_replace('_', ' ', $key); //再把$key中的空字符串替换成‘-’
$key = str_replace(' ', '-', $key); //把$key中的所有字符转换为小写
$key = strtolower($key); //这里主要是过滤上面写的$ignore数组中的数据
if(!in_array($key, $ignore)){
$headers[$key] = $value;
}
}
}//输出获取到的header
return $headers;
}
// 记录日志
public function payLog($word) {
$logFile = $this->logdir.get_date(TIMESTAMP, "Y-m").'.txt';
$fp = fopen($logFile, "a");
flock($fp, LOCK_EX) ;
fwrite($fp, get_date(TIMESTAMP, "Y-m-d H:i:s").' | '.$word."\r\n");
flock($fp, LOCK_UN);
fclose($fp);
}
//支付成功后处理业务逻辑
public function _processOrder($order_sn,$total_price,$pay_method,$openid='')
{
$order = ShoppingOrder::find()->where("order_sn='".$order_sn."'")->one();
if($order&&$order->status==0)
{
$order->status = $order->is_virtual==1?9:1;
$order->pay_time = strval(TIMESTAMP);
$order->pay_method = $pay_method;
if($order->save())
{
//充值金币
if(strpos($order->pay_credit,'coinrecharge')!==false)
{
$coin_num = str_replace('coinrecharge_','',$order->pay_credit);
Wallet::coinChange($order->user_id,$coin_num,$order->remark,1);
}
//开通VIP
if(strpos($order->pay_credit,'buyvip')!==false)
{
$vip_type = str_replace('buyvip_','',$order->pay_credit);
$userVipType = UserVipType::findOne($vip_type);
$userVipOrder = UserVipOrder::findOne($order->order_id);
//付款金额校验
if($userVipType&&$order->total_price==$userVipType->price)
{
//判断是否是续费
$vipInfo = UserVipOrder::find()->where("user_id='".$order->user_id."' and vip_type=$vip_type and status=1 and (expire_time>=".TIMESTAMP." or expire_time=0) and order_id!='".$order->order_id."'")->orderBy(['order_id'=>SORT_DESC])->limit(1)->one();
if($vipInfo)
{
$startTime = $vipInfo->expire_time;
}
else
{
$startTime = TIMESTAMP;
}
if(empty($userVipOrder))
{
$userVipOrder = new UserVipOrder();
}
$userVipOrder->order_id = $order->order_id;
$userVipOrder->user_id = $order->user_id;
$userVipOrder->vip_type = $vip_type;
$userVipOrder->money = $total_price;
$userVipOrder->days = $userVipType->days;
$userVipOrder->settings = $userVipType->settings;
$userVipOrder->expire_time = $userVipType->forever==1?0:$startTime+$userVipType->days*24*3600;
$userVipOrder->create_time = TIMESTAMP;
$userVipOrder->status = 1;
if($userVipOrder->save())
{
$vipSettings = string2array($userVipType->settings);
//如果有赠送金币
if(intval($vipSettings['coin_num'])>0)
{
Wallet::coinChange($order->user_id,$vipSettings['coin_num'],'开通会员赠送金币',1);
}
//处理分销
Wallet::vipCommission($order->user_id,$userVipOrder);
}
}
}
//购买文档
if(strpos($order->pay_credit,'buydoc')!==false)
{
$id = str_replace('buydoc_','',$order->pay_credit);
$this->addDownCode($id,$order);
}
//百度竞价跟踪
$bd_vid = \app\common\helpers\Cookie::getCookie('bd_vid');
if(!empty($bd_vid))
{
$higherconfigResult = \app\modules\admin\models\Config::find()->where("name='higherconfig'")->one();
$higherconfig = string2array($higherconfigResult->value);
$token = $higherconfig['cpc_token'];
if(!empty($token))
{
$cv = array(
'logidUrl' => APP_URL.'?bd_vid='.$bd_vid, // 您的落地页url
'newType' => 10 // 转化类型请按实际情况填写
);
$conversionTypes = array($cv);
$baiducpc = new \app\common\components\BaiduCpc();
$baiducpc->sendConvertData($token, $conversionTypes);
}
}
}
return true;
}
else
{
return false;
}
}
//获取订单状态
public function actionOrderstatus()
{
$order_sn = Yii::$app->request->get('order_sn');
if($order_sn)
{
$order = ShoppingOrder::find()->where("order_sn='".$order_sn."'")->one();
if(!empty($order))
{
if($order->status==1||$order->status==9)
{
$data = [];
//购买文档
if(strpos($order->pay_credit,'buydoc')!==false)
{
$downCode = DocDowncode::find()->where("openid='".$order_sn."'")->one();
$data['downurl'] = SiteUrl::docDownByCode($downCode->downcode,1);
$data['downcode'] = $downCode->downcode;
}
$result = [
'error' => 0,
'msg' => '支付成功',
'data' => $data,
'code'=>200
];
echo_json($result);
}
}
else
{
$result = [
'error' => 1,
'msg' => '订单不存在',
'code'=>200
];
echo_json($result);
}
}
else
{
$result = [
'error' => 1,
'msg' => '缺少参数',
'code'=>200
];
echo_json($result);
}
}
//购买文档
public function addDownCode($doc_id,$order)
{
try
{
$doc = DocReal::findOne($doc_id);
$downCode = new \app\modules\doc\models\DocDowncode();
$downCode->doc_id = $doc_id;
$downCode->user_id = intval($order->user_id);
$downCode->openid = $order->order_sn;
$downCode->downcode = strval(getDowncode($doc->id));
$downCode->doc_user_id = $doc->user_id;
$downCode->type = 2;
$downCode->create_time = TIMESTAMP;
$downCode->save();
//判断用户VIP权限情况
if($order->user_id) $vipSettings = User::findOne($order->user_id)->vipSettings();
//如果是机构推广文档,标记推广文档订单
if($doc->is_ad)
{
$store = \app\modules\shopping\models\ShoppingStore::find()->where("user_id=".$doc->user_id)->one();
if($store)
{
$order->store_id = $store->store_id;
$order->save();
}
}
//将价格转成金币数量
$coin_num = $order->total_price*Yii::$app->params['coin']['coin_recharge_rate'];
//生成支付记录
$paylog = new \app\modules\doc\models\DocPaylog();
$paylog->user_id = intval($order->user_id);
$paylog->doc_user_id = intval($doc->user_id);
$paylog->doc_id = $doc->id;
$paylog->cat_id = $doc->cat_id;
$paylog->cat_ids = $doc->cat_ids;
$paylog->doc_type = $doc->doc_type;
$paylog->is_vip = ($doc->is_vip||$vipSettings['buy_doc_discount']<100)?1:0;
$paylog->coin_price = $doc->coin_price;
$paylog->coin_num = $coin_num;
$paylog->agent_id = intval($order->user->referer_id);
$paylog->agent_ids = strval($order->user->referer_ids);
$paylog->create_time = TIMESTAMP;
if($paylog->save())
{
$doc->updateCounters(['sales'=>1]);
$left_coin = $coin_num;
$point_num = intval($order->total_price*Yii::$app->params['point']['rmb_price_rate']);
//购买方
$logTitleBuy = '购买'.DocReal::typeOptions($doc->doc_type);
if($order->user_id)
{
Wallet::pointChange($order->user_id,$point_num,$logTitleBuy,1,'point',DocReal::shortTableName(),$doc->id);
//处理分销
$left_coin = Wallet::docCommission($order->user_id,$doc,$paylog,$left_coin);
}
//出售方
$logTitleSell = '出售'.DocReal::typeOptions($doc->doc_type);
if($left_coin>0&&$doc->user_id)
{
//金币变化
Wallet::coinChange($doc->user_id,$left_coin,$logTitleSell,1,'coin_income',DocReal::shortTableName(),$doc->id);
//消息通知
MessageOne::soldDoc($logTitleSell,$doc,$left_coin);
}
return true;
}
else
{
$this->payLog($paylog->returnFirstError());
}
}
catch(\Exception $e)
{
$this->payLog($e->getMessage());exit;
}
}
//初始化视图
public function initForm($pay_method)
{
$view = $pay_method;
$this->setView($view);
$this->setData(array("return_url"=>$this->return_url));
$this->getFormHtml();
}
//微信支付签名
public function getSign($data = [], $url, $randstr, $time)
{
$str = "POST" . "\n" . $url . "\n" . $time . "\n" . $randstr . "\n" . $data . "\n";
$key = file_get_contents($this->payconfig['weixin_apiclient_key']);//在商户平台下载的秘钥
$str = $this->getSha256WithRSA($str, $key);
return $str;
}
//调起支付的签名
public function getWechartSign($appid, $timeStamp, $noncestr, $prepay_id)
{
$str = $appid . "\n" . $timeStamp . "\n" . $noncestr . "\n" . $prepay_id . "\n";
$key = file_get_contents($this->payconfig['weixin_apiclient_key']);
$str = $this->getSha256WithRSA($str, $key);
return $str;
}
public function getSha256WithRSA($content, $privateKey)
{
$binary_signature = "";
$algo = "SHA256";
openssl_sign($content, $binary_signature, $privateKey, $algo);
$sign = base64_encode($binary_signature);
return $sign;
}
function curl_post_https($url,$data,$header){ // 模拟提交数据函数
$curl = curl_init(); // 启动一个CURL会话
curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0); // 从证书中检查SSL加密算法是否存在,如果出错则修改为0,默认为1
curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
$tmpInfo = curl_exec($curl); // 执行操作
if (curl_errno($curl)) {
echo 'Errno'.curl_error($curl);//捕抓异常
}
curl_close($curl); // 关闭CURL会话
return $tmpInfo; // 返回数据,json格式
}
}