文档地址:https://global.alipay.com/service/app_cn/1
1.配置文件,本地生成公钥私钥对,把本地的公钥提交给支付宝,换取支付宝公钥,私钥保留本地
<?php
/* *
* 配置文件
* 版本:1.0
* 日期:2016-06-06
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//合作身份者ID,签约账号,以2088开头由16位纯数字组成的字符串,查看地址:https://openhome.alipay.com/platform/keyManage.htm?keyType=partner
$alipay_config['partner'] = '20887215xxxxxxxx';
//商户的私钥,此处填写原始私钥去头去尾,RSA公私钥生成:https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.nBDxfy&treeId=58&articleId=103242&docType=1
$alipay_config['private_key'] = '-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQCcstHVkCeNFDoEY/mArNkBiktYrlVYECjuugk5a01mCCY/Ts6S
gRWryoRiMUASBHgVmYAKm2sxu+0HoDhqH+/tcURo/86NgOBECC+Y0GyKX2AcFS1T
D89GzMAcnmygbpwTMQzTd3tQWy70hQ3PjOd2lhIxPTzUn1jbvSAIHTTu2QIDAQAB
AoGAK2iSHnJXsopW5B554L6BQx73bnKk68dWP4PDyGdEQq6hQcpoCUe/JB7u+3Cf
Sh540ar7QHT7hgSETieBWUzNnu9Y3pLkuP5J5/KY7FeoEJ1C7fjq+WQQ6cVmbX2y
vzJVjnekyGiU8zi/mx1K/oU+Ijc8jHRsetobhxdiP1X3RwECQQDIaB8+E/egbd9M
yN87HhNqHW4R2L7sUS2inbiYFYGccTsAeAX2WQ0feprAKde+jW4Hu/U5XTGLjTCJ
eanbk7thAkEAyCrCmpvq9fdRgWus1493LdbcmqzNkhSydswuEsYb+LG4r44wUVO7
IvXEJZ7Vm7h5XwvM+MNY0HHfP8H3p+weeQJBAKoBQfecYqUyb4oooM36noeXPadg
Ed5QowDfARfqro+yslWce5pWQr6geCRpmn4oZd2jwcwO1ZfHhxQoJEKD2SECQQCf
zhOjn8tMJ/F4Y+CQEEfT3vAsxL0yXTfFxGkcL/Hw8OJDtj85DqIe3RuF9XMQaYzs
pt0z1bG4aNEVc+QmuknxAkEAnZ6BKuIIXDYE2h6gO5pAykExovmW5wBjgmB6y7gg
LLJVuMctgLiJl6zxJ7qe7DgLboHYgJGRB20GhS2xb9n3Qw==
-----END RSA PRIVATE KEY-----';
//支付宝的公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm?keyType=partner
$alipay_config['alipay_public_key']= 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB';
//异步通知接口
$alipay_config['service']= 'mobile.securitypay.pay';
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
//签名方式 不需修改
$alipay_config['sign_type'] = strtoupper('RSA');
//字符编码格式 目前支持 gbk 或 utf-8
$alipay_config['input_charset']= strtolower('utf-8');
//ca证书路径地址,用于curl中ssl校验
//请保证cacert.pem文件在当前文件夹目录中
$alipay_config['cacert'] = getcwd().'/cacert.pem';
//访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
$alipay_config['transport'] = 'http';
?>
2.拼接参数字段,调用签名方法进行签名,拼接完整支付链接接口
<?php
/*
* 积分接口
*/
namespace Apis\Controller;
use Common\Controller\AppframeController;
class ZfbController extends AppframeController {
protected $order_model;
public function _initialize() {
parent::_initialize();
$this->order_model = D("Common/Order");
}
// 积分主页
public function index() {
$return = array();
$oid = sp_checkparam("oid", true, 'int', "缺少订单号");
$info = $this->order_model
->where("id='{$oid}'")
->find();
if (!$info) {
sp_error("获取失败");
}
$prolist = sp_projson($info['projson']);
$array_query = array();
$array_query['service'] = "\"mobile.securitypay.pay\"";
$array_query['partner'] = "\"2088721528654455\"";
$array_query['_input_charset'] = "\"utf-8\"";
$array_query['notify_url'] = "\"http://".$_SERVER['HTTP_HOST']."/zfb/notify_url.php\"";
$array_query['out_trade_no'] = "\"".$info['sn']."\"";
$array_query['subject'] = "\"".$prolist[0]['product_name']."\"";
$array_query['payment_type'] = "\"1\"";
$array_query['seller_id'] = "\"careline_ting@hotmail.com\"";
$array_query['total_fee'] = "\"".$info['total']."\"";
$array_query['currency'] = "\"AUD\"";
$array_query['body'] = "\"".$prolist[0]['product_name']."\"";
$array_query['forex_biz'] = "\"FP\"";
$array_query['it_b_pay'] = "\"30m\"";
$url = "http://aus.palmtrends.com/zfb/signatures_url.php";
$sign = sp_file_get_contents_safe($url,$array_query,'POST');
sp_api($sign);
}
}
3.支付链接拼接
<?php
/* *
* 功能:支付宝移动支付服务端签名页面
* 版本:1.0
* 日期:2016-06-06
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要编写。
* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*************************页面功能说明*************************
* 本页面代码示例用于处理客户端使用http(s) post传输到此服务端的移动支付请求参数待签名字符串。
* 本页面代码示例采用客户端创建订单待签名的请求字符串传输到服务端的这里进行签名操作并返回。
*/
require_once("alipay.config.php");
require_once("lib/alipay_notify.class.php");
require_once("lib/alipay_rsa.function.php");
require_once("lib/alipay_core.function.php");
//确认PID和接口名称是否匹配。
date_default_timezone_set("PRC");
if (str_replace('"','',$_POST['partner'])==$alipay_config['partner']&&str_replace('"','',$_POST['service'])==$alipay_config['service']) {
//将post接收到的数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串。
$data=createLinkstring($_POST);
//打印待签名字符串。工程目录下的log文件夹中的log.txt。
//logResult($data);
//将待签名字符串使用私钥签名,且做urlencode. 注意:请求到支付宝只需要做一次urlencode.
$rsa_sign=urlencode(rsaSign($data, $alipay_config['private_key']));
//把签名得到的sign和签名类型sign_type拼接在待签名字符串后面。
$data = $data.'&sign='.'"'.$rsa_sign.'"'.'&sign_type='.'"'.$alipay_config['sign_type'].'"';
//返回给客户端,建议在客户端使用私钥对应的公钥做一次验签,保证不是他人传输。
echo $data;
//echo $rsa_sign;
}
else{
echo "不匹配或为空!";
logResult(createLinkstring($_POST));
}
?>
4.签名方法rsa
/**
* RSA签名
* @param $data 待签名数据
* @param $private_key 商户私钥字符串
* return 签名结果
*/
function rsaSign($data, $private_key) {
//以下为了初始化私钥,保证在您填写私钥时不管是带格式还是不带格式都可以通过验证。
//$private_key=str_replace("-----BEGIN RSA PRIVATE KEY-----","",$private_key);
//$private_key=str_replace("-----END RSA PRIVATE KEY-----","",$private_key);
//$private_key=str_replace("\n","",$private_key);
//$private_key="-----BEGIN RSA PRIVATE KEY-----".PHP_EOL .wordwrap($private_key, 64, "\n", true). PHP_EOL."-----END RSA PRIVATE KEY-----";
$res=openssl_get_privatekey($private_key);
if($res)
{
openssl_sign($data, $sign,$res);
}
else {
echo "您的私钥格式不正确!"."<br/>"."The format of your private_key is incorrect!";
exit();
}
openssl_free_key($res);
//base64编码
$sign = base64_encode($sign);
return $sign;
}
5.回调函数验证签名,处理数据
<?php
/* *
* 功能:支付宝服务器异步通知页面
* 版本:1.0
* 日期:2016-06-06
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
* ************************页面功能说明*************************
* 创建该页面文件时,请留心该页面文件中无任何HTML代码及空格。
* 该页面不能在本机电脑测试,请到服务器上做测试。请确保外部可以访问该页面。
* 该页面调试工具请使用写文本函数logResult,该函数已被默认关闭,见alipay_notify_class.php中的函数verifyNotify
* 如果没有收到该页面返回的 success 信息,支付宝会在24小时内按一定的时间策略重发通知
*/
require_once("alipay.config.php");
require_once("lib/alipay_notify.class.php");
require_once("lib/alipay_rsa.function.php");
require_once("lib/alipay_core.function.php");
$mysql_server_name='localhost'; //改成自己的mysql数据库服务器
$mysql_username='root'; //改成自己的mysql数据库用户名
$mysql_password='Pa1mtrends'; //改成自己的mysql数据库密码
$mysql_database='daigou'; //
$conn=mysql_connect($mysql_server_name,$mysql_username,$mysql_password) or die("error connecting") ; //连接数据库
mysql_query("set names 'utf8'"); //数据库输出编码 应该与你的数据库编码保持一致.南昌网站建设公司百恒网络PHP工程师建议用UTF-8 国际标准编码.
mysql_select_db($mysql_database); //打开数据库
//$_POST['notify_type'] = "trade_status_sync";
//$_POST['trade_no'] = "2017082821001003060249667133";
//$_POST['total_fee'] = "0.01";
//$_POST['out_trade_no'] = "201708281352125846";
//$_POST['notify_time'] = "2017-08-28 13:52:38";
//$_POST['currency'] = "AUD";
//$_POST['trade_status'] = "TRADE_FINISHED";
//$_POST['sign_type'] = "RSA";
//$_POST['notify_id'] = "8d0b75dad481c9ca1d925d316ef433eggq";
//$_POST['sign'] = "dgjUACWxfC96+1ZbG8gBiP7LitEoP048lOhsfvyEsL4pQ0b90vr2q+SQ5Ggeq5jWngCOcfirOVcFwsCXc8Ey2b8k7LoL/4M403tbV4wulO1ROOIzfsA0ZU7MoAVoGkPiyofghSSAMDeNz+GXmLto4mCz8ahRre9Nh3gDmGfcayE=";
//计算得出通知验证结果
$alipayNotify = new AlipayNotify($alipay_config);
if ($alipayNotify->getResponse($_POST['notify_id'])) {//判断成功之后使用getResponse方法判断是否是支付宝发来的异步通知。
if ($alipayNotify->getSignVeryfy($_POST, $_POST['sign'])) {//使用支付宝公钥验签
//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表
//商户订单号
$out_trade_no = $_POST['out_trade_no'];
//支付宝交易号
$trade_no = $_POST['trade_no'];
//交易状态
$trade_status = $_POST['trade_status'];
if ($_POST['trade_status'] == 'TRADE_FINISHED') {
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
$time = time();
$sql = "update cmf_order set payway=1,zfb_trade_no='{$trade_no}',status=1,paytime='{$time}' where sn='{$out_trade_no}'";
$res = mysql_query($sql,$conn);
$has = "select id from cmf_order_zfb where out_trade_no='{$_POST['out_trade_no']}'";
$r = mysql_query($has,$conn);
$has_res = mysql_fetch_array($r);
if (!$has_res) {
//插入记录表
$ins = array();
$ins['notify_type'] = $_POST['notify_type'];
$ins['trade_no'] = $_POST['trade_no'];
$ins['total_fee'] = $_POST['total_fee'];
$ins['out_trade_no'] = $_POST['out_trade_no'];
$ins['currency'] = $_POST['currency'];
$ins['sign_type'] = $_POST['sign_type'];
$ins['addtime'] = time();
$ins['notify_time'] = $_POST['notify_time'];
$sql_ins = "insert into cmf_order_zfb (notify_type,trade_no,total_fee,out_trade_no,currency,sign_type,addtime,notify_time) values('{$ins['notify_type']}','{$ins['trade_no']}','{$ins['total_fee']}','{$ins['out_trade_no']}','{$ins['currency']}','{$ins['sign_type']}','{$ins['addtime']}','{$ins['notify_time']}')";
mysql_query($sql_ins,$conn);
}
} else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序
//注意:
//付款完成后,支付宝系统发送该交易状态通知
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
$time = time();
$sql = "update cmf_order set payway=1,zfb_trade_no='{$trade_no}',status=1,paytime='{$time}' where sn='{$out_trade_no}'";
$res = mysql_query($sql,$conn);
$has = "select id from cmf_order_zfb where out_trade_no='{$_POST['out_trade_no']}'";
$r = mysql_query($has,$conn);
$has_res = mysql_fetch_array($r);
if (!$has_res) {
//插入记录表
$ins = array();
$ins['notify_type'] = $_POST['notify_type'];
$ins['trade_no'] = $_POST['trade_no'];
$ins['total_fee'] = $_POST['total_fee'];
$ins['out_trade_no'] = $_POST['out_trade_no'];
$ins['currency'] = $_POST['currency'];
$ins['sign_type'] = $_POST['sign_type'];
$ins['addtime'] = time();
$ins['notify_time'] = $_POST['notify_time'];
$sql_ins = "insert into cmf_order_zfb (notify_type,trade_no,total_fee,out_trade_no,currency,sign_type,addtime,notify_time) values('{$ins['notify_type']}','{$ins['trade_no']}','{$ins['total_fee']}','{$ins['out_trade_no']}','{$ins['currency']}','{$ins['sign_type']}','{$ins['addtime']}','{$ins['notify_time']}')";
mysql_query($sql_ins,$conn);
}
}
//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
echo "success"; //请不要修改或删除
} else { //验证签名失败
echo "sign fail";
}
} else { //验证是否来自支付宝的通知失败
echo "response fail";
}
?>
6.验签函数
/**
* 获取返回时的签名验证结果
* @param $para_temp 通知返回来的参数数组
* @param $sign 返回的签名结果
* @return 签名验证结果
*/
function getSignVeryfy($para_temp, $sign) {
//除去待签名参数数组中的空值和签名参数
$para_filter = paraFilter($para_temp);
//对待签名参数数组排序
$para_sort = argSort($para_filter);
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
$prestr = createLinkstring($para_sort);
$isSgin = false;
switch (strtoupper(trim($this->alipay_config['sign_type']))) {
case "RSA" :
$isSgin = rsaVerify($prestr, trim($this->alipay_config['alipay_public_key']), $sign);
break;
default :
$isSgin = false;
}
return $isSgin;
}