<?php
namespace Pn\Controller;
use Think\Controller\RestController;
class PayController extends RestController{
public function __construct(){
import('Vendor.WePay.WeEncryption');
import('Vendor.WePay.Curl');
}
public function Payment(){
$arr['appid'] = $_POST['appid'];//应用id
$arr['userdid'] = $_POST['userdid'];//登录用户id
$arr['paytype'] = $_POST['paytype'];//支付方式
$arr['productid'] = $_POST['productid'];//商品id
$arr['time'] = $_POST['time'];
$sign = $_POST['sign'];//安全验证sign
$vsign = strrank($arr);//签名加密
if($vsign!=$sign){
$return['respCode'] = 1001;
$return['msg'] = "签名错误";
$this -> response($return,'json');//返回数据
exit();
}else{
switch ($_POST["paytype"]){
case 1://支付宝
$data["signdata"] = $this->alipay();
echo json_encode($data);
break;
case 2://微信支付
$data = $this->wechatpay($_POST['appid'],$_POST['userdid'],$_POST['productid']);
echo $data;
break;
default:
$return["respCode"] = "error";
$return['msg'] = "支付方式错误";
$this -> response($return,'json');//返回数据
exit();
}
}
}
/**
* 微信APP客户端支付
*/
public function wechatpay($appid,$userdid,$productid){
$WeEncryption = new \WeEncryption(); //实例化传输类;
switch ($productid){
case 1://季付商品(¥100)
$body = "陪你季付VIP";//商品描述
$total_fee = "100.00";//总金额
break;
case 2://月付商品(¥50)
$body = "陪你月付VIP";//商品描述
$total_fee = "50.00";//总金额
break;
}
$out_trade_no = date("YmdHis").rand(10,100);//商户订单号
$spbill_create_ip = getclientip();//终端IP
$data = array(
'body' => $body,
'out_trade_no' => $out_trade_no,
'total_fee' => $total_fee,
'spbill_create_ip' => $spbill_create_ip,
);
$encpt = $WeEncryption::getInstance(); //实例化签名类
$url = "http://xxxx.com/Pay/wx_notify_verify";
$encpt->setNotifyUrl($url); //设置异步通知地址
$curl = new \Curl(); //实例化传输类;
$xml_data = $encpt->sendRequest($curl, $data); //发送请求
$postObj = $encpt->xmlToObject($xml_data); //解析返回数据
if ($postObj === false) {
echo 'FAIL';
exit;
}
if ($postObj->return_code == 'FAIL') {
echo $postObj->return_msg;
} else {
$resignData = array(
'appid' => $postObj->appid,
'partnerid' => $postObj->mch_id,
'prepayid' => $postObj->prepay_id,
'noncestr' => $postObj->nonce_str,
'timestamp' => time(),
'package' => 'Sign=WXPay'
);
$sign = $encpt->getClientPay($resignData);
$resignData['sign'] = $sign;
return json_encode($resignData);
}
}
/**
* 微信App支付回调
*/
public function wx_notify_verify(){
$WeEncryption = new \WeEncryption(); //实例化传输类;
$encpt = $WeEncryption::getInstance();
$obj = $encpt->getNotifyData();
if ($obj === false) {
exit;
}
if ($obj) {
$data = array(
'appid' => $obj->appid,
'mch_id' => $obj->mch_id,
'nonce_str' => $obj->nonce_str,
'result_code' => $obj->result_code,
'openid' => $obj->openid,
'trade_type' => $obj->trade_type,
'bank_type' => $obj->bank_type,
'total_fee' => $obj->total_fee,
'cash_fee' => $obj->cash_fee,
'transaction_id' => $obj->transaction_id,
'out_trade_no' => $obj->out_trade_no,
'time_end' => $obj->time_end
);
$sign = $encpt->getSign($data);
if ($sign == $obj->sign) {//验签通过
$reply = "<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>";
echo $reply;
exit;
}else{
$reply = "<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[NO]]></return_msg>
</xml>";
echo $reply;
exit;
}
}
}
/**
* https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.NgdeQA&treeId=59&articleId=103663&docType=1
* 服务端生成app支付使用的参数以及签名
* @param $params <Array>
* @return <Array>
*/
public function alipay(){
$ali = array(
'service' => 'mobile.securitypay.pay',
'partner' => 'xxxx',
'_input_charset' => 'utf-8',
'sign_type' => 'RSA',
'sign' => '',
'notify_url' => 'http://xxxxxxxx.com/Pay/alipay_notify_url',//回调地址
'out_trade_no' => date("YmdHis").rand(10,100),//商户网站唯一订单号
'subject' => '测试',//商品名称
'payment_type' => 1,//支付类型
'seller_id' => 'lql@jieku.com',//支付宝账号
'total_fee' => '0.01',//总金额
'body' => 'Iphone6 16G',//商品详情
);
$ali = self::argSort($ali);
$str = '';
foreach($ali as $key=>$val){
if($key == 'sign_type' || $key == 'sign'){
continue;
}else{
if($str == ''){
$str = $key.'='.'"'.$val.'"';
}else{
$str = $str.'&'.$key.'='.'"'.$val.'"';
}
}
}
$sign = urlencode(self::sign($str));
$str = $str.'&sign='.'"'.$sign.'"'.'&sign_type='.'"'.$ali['sign_type'].'"';//传给支付宝接口的数据
return $str;
}
/**
* 准备签名参数
*/
public function argSort($para) {
ksort($para);
reset($para);
return $para;
}
/**
* 生成请求参数的签名
* @param $params <Array>
* @return <String>
*
*/
public function sign($data) {
//读取私钥文件
$priKey = file_get_contents('./Public/key/rsa_private_key.pem');//私钥文件路径
//转换为openssl密钥,必须是没有经过pkcs8转换的私钥
$res = openssl_get_privatekey($priKey);
//调用openssl内置签名方法,生成签名$sign
openssl_sign($data, $sign, $res);
//释放资源
openssl_free_key($res);
//base64编码
$sign = base64_encode($sign);
return $sign;
}
/**
* 支付宝回调地址
*/
public function alipay_notify_url(){
$orderpay = M("orderpay");
$async = empty($_GET);
$data = $async ? $_POST : $_GET;
if (empty($data)) {
return FALSE;
}
$signValid = $this->verifyParameters($data, $data["sign"]);//验签
$notify_id = isset($data['notify_id']) ? $data['notify_id'] : NULL;
//获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)
$responseTxt = 'true';
if (!empty($notify_id)) {
$responseTxt = $this->verifyFromServer($notify_id);
}
if($signValid && preg_match("/true$/i", $responseTxt)){//验证成功
if($_POST['trade_status'] == 'TRADE_FINISHED'){
$_POST["createdatetime"] = time();
if($orderpay->create()){
$orderpay->add();
echo "success";
}else{
echo "fail";//验证失败
}
}
else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
$_POST["createdatetime"] = time();
if($orderpay->create()){
$orderpay->add();
echo "success";
}else{
echo "fail";//验证失败
}
}
}else{
echo "fail";//验证失败
}
}
/**
* 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串
* @param unknown $params
* @param unknown $sign
* @return boolean
*/
function verifyParameters($params, $sign) {
$public_key_path = './Public/key/alipay_public_key.pem';//公钥(合作伙伴)
$params = $this->filterSignParameter($params);
ksort($params);
reset($params);
$content = urldecode(http_build_query($params));
return $this->rsaVerify($content, $public_key_path, $sign);
}
/**
* 过滤参数,去除sign/sign_type参数
* @param $params
* @return <Array>
*/
function filterSignParameter($params) {
$result = array();
foreach ($params as $key => $value) {
if ($key != 'sign' && $key != 'sign_type' && $value) {
$result[$key] = $value;
}
}
return $result;
}
/**
* RSA验签,注意验签的公钥是支付宝的公钥,不是自己生成的rsa公钥,可以在淘宝的demo中获得
* @param $data string 待签名数据
* @param $ali_public_key_path string 支付宝的公钥文件路径
* @param $sign string 要校对的的签名结果
* @return <Boolean> 验证结果
* @throws Exception
*/
function rsaVerify($data, $ali_public_key_path, $sign) {
$pubKey = file_get_contents($ali_public_key_path);
$res = openssl_get_publickey($pubKey);
if(!$res){
throw new \Exception('公钥格式错误');
}
$result = (bool)openssl_verify($data, base64_decode($sign), $res);
openssl_free_key($res);
return $result;
}
function verifyFromServer($notify_id) {
$transport = "http";
$partner = "xxxxxxxxxxx";
$cacert = "./Public/key/cacert.pem";
$transport = strtolower(trim($transport));
$partner = trim($partner);
$veryfy_url = "http://notify.alipay.com/trade/notify_query.do?partner=$partner¬ify_id=$notify_id";
$curl = curl_init($veryfy_url);
curl_setopt($curl, CURLOPT_HEADER, 0); // 过滤HTTP头
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
curl_setopt($curl, CURLOPT_CAINFO, $cacert);//证书地址
$responseText = curl_exec($curl);
// var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容
curl_close($curl);
return $responseText;
}
/**格式化公钥
* $pubKey PKCS#1格式的公钥串
* return pem格式公钥, 可以保存为.pem文件
*/
function formatPubKey($pubKey) {
$fKey = "-----BEGIN PUBLIC KEY-----\n";
$len = strlen($pubKey);
for($i = 0; $i < $len; ) {
$fKey = $fKey . substr($pubKey, $i, 64) . "\n";
$i += 64;
}
$fKey .= "-----END PUBLIC KEY-----";
return $fKey;
}
}
问题咨询QQ1370373713http://blog.csdn.net/apensu/article/details/46945193