前言:
因公司业务是加盟平台,入驻商户需要到账到商户自己账户。所以就出现了服务商模式的支付宝支付。
1.准备工作
- 文件准备,当面付SDK下载地址:网页&移动应用学习路径 | 网页&移动应用
文件大概内容就是这样子,保存到thinkphp/vendor
2.创建第三方应用,支付宝有现成的创建流程。
地址:创建第三方应用 | 第三方应用,和正常的自研应用的生活号配置基本相同。需要
2.开始工作
1.配置当面付三方应用配置信息
目录:thinkphp/vendor/alipaydmf/f2fpay/config/config.php
已经明确以下信息的直接配置
<?php
$config = array (
//签名方式,默认为RSA2(RSA2048)
'sign_type' => "RSA2",
//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
'alipay_public_key' => "",//填写支付宝开放平台中,第三方应用的支付宝公钥
//商户私钥
'merchant_private_key' => "",//第三方应用商户私钥
//编码格式
'charset' => "UTF-8",
//支付宝网关
'gatewayUrl' => "https://openapi.alipay.com/gateway.do",
//应用ID
'app_id' => "",//第三方应用的APPID
//异步通知地址,只有扫码支付预下单可用
'notify_url' => "",//第三方应用中的配置的回调地址
//最大查询重试次数
'MaxQueryRetry' => "10",//默认即可
//查询间隔
'QueryDuration' => "3"//默认即可
);
在不明确以上配置时候,重新生成,再进行配置
小提示:商户私钥在支付宝开放平台找不到的,只有公钥和支付宝公钥。如果第三方应用是新创建的没有涉及任何业务。可以通过“支付宝开放平台开发助手”重新生成就可以了。
红框区域一定要按照图上去选择,之后再点击生成密钥。RSA2、PKCS1 ,生成好之后配置到 支付宝开发平台的第三方应用的开发设置模块中,和thinkphp项目当面付SDK的config.php中。
2.开始授权
2.1参考地址:第三方应用授权 | 第三方应用
//自助收银商户授权 $shop_id 店铺ID
function alipay_auth($shop_id)
{
//链接拼接的app_id为第三方应用的APPID
$auth_url = "https://openauth.alipay.com/oauth2/appToAppAuth.htm?shop_id=" . $shop_id . "&app_id=" . $this->appid . "&redirect_uri=" . urlencode($this->redirect_uri);
$this->redirect($auth_url);
}
注意:这个链接中的app_id为第三方应用的APPID
这个入口是通过店铺列表,传参店铺ID,方便回调时候保存令牌信息 app_auth_token
链接打开,如果浏览器没有登录支付宝账号。会提示扫码登录,登录用户是商户的支付宝用户
2.2确认授权后,回调处理。
//第三方应用授权回调处理
function auth_notify(){
if(!empty(input('get.app_id')) && !empty(input('get.app_auth_code'))){
//获取令牌方法的控制器
$payApi=controller('api/Alipay');
//第三方应用ID
$app_id = input('get.app_id');
//店铺ID
$shop_id = input('get.shop_id');
//使用 app_auth_code 换取 app_auth_token
$app_auth_code = input('get.app_auth_code');
$payApi->get_auth_token($app_id,$app_auth_code,$shop_id);
}
}
2.3使用 app_auth_code 换取 app_auth_token(上图get_auth_token方法)
//换取应用授权令牌 $app_id $app_auth_code $shop_id
function get_auth_token($app_id, $app_auth_code, $shop_id)
{
//因为以下文件只使用一次,require_once就可以满足使用
$config = [];
require_once '../vendor/alipaydmf/aop/AopClient.php';
require_once '../vendor/alipaydmf/aop/request/AlipayOpenAuthTokenAppRequest.php';
require_once '../vendor/alipaydmf/f2fpay/config/config.php';
$aop = new \AopClient ();
$aop->gatewayUrl = $config['gatewayUrl'];
$aop->appId = $config['app_id'];
$aop->rsaPrivateKey = $config['merchant_private_key'];
$aop->alipayrsaPublicKey = $config['alipay_public_key'];
$aop->apiVersion = '1.0';
$aop->signType = $config['sign_type'];
$aop->postCharset = $config['charset'];
$aop->format = 'json';
$request = new \AlipayOpenAuthTokenAppRequest ();
$params = array(
'grant_type' => 'authorization_code',
'code' => $app_auth_code,
'refresh_token' => ''
);
$request->setBizContent(json_encode($params));
$result = $aop->execute($request);
$responseNode = str_replace(".", "_", $request->getApiMethodName()) . "_response";
$resultObj = $result->$responseNode;
$resultCode = $resultObj->code;
if (!empty($resultCode) && $resultCode == 10000) {
//授权成功,保存店铺对应的app_auth_token
$auth_info = json_decode(json_encode($result), true);
$dataInfo['app_auth_token'] = $auth_info['alipay_open_auth_token_app_response']['app_auth_token'];
$rs = Db::name('shop')->where('id', $shop_id)->update($dataInfo);
//授权成功,并保存app_auth_token
echo "success";
} else {
//授权失败
echo $result->$responseNode->msg;
}
}
以上步骤走完之后,商户的授权信息基本已经完成了。
总结一点,不要让第三方应用和商户应用混淆。在授权的时候只需要第三方应用的信息就可以(可能是菜,因为这个浪费了好多时间)
3.当面付使用ISV模式进行扣款
当面付接入参考地址:当面付产品介绍 | 网页&移动应用
//付款码扣款 $out_trade_no 订单,$subject 订单标题,$total_amount 总金额,$pay_code 付款码
function unifiedorder_codepay($out_trade_no, $subject, $total_amount, $pay_code)
{
require_once '../vendor/alipaydmf/f2fpay/service/AlipayTradeService.php';
require_once '../vendor/alipaydmf/f2fpay/model/builder/AlipayTradePayContentBuilder.php';
require_once '../vendor/alipaydmf/f2fpay/config/config.php';
//商品描述,可空
$body = '';
$barPayRequestBuilder = new \AlipayTradePayContentBuilder();
$barPayRequestBuilder->setOutTradeNo($out_trade_no);
$barPayRequestBuilder->setTotalAmount($total_amount);
$barPayRequestBuilder->setAuthCode($pay_code);
$barPayRequestBuilder->setTimeExpress("5m");
$barPayRequestBuilder->setSubject($subject);
$barPayRequestBuilder->setBody($body);
//$arr是在生成订单时候缓存的数据,查询了店铺列表把该店铺的app_auth_token传递了过来
$arr = cache('txm_' . $out_trade_no);
//AlipayTradePayContentBuilder类中自带setAppAuthToken方法
$barPayRequestBuilder->setAppAuthToken($arr['app_auth_token']);
// 调用barPay方法获取当面付应答
$qrPay = new \AlipayTradeService($config);
$qrPayResult = $qrPay->barPay($barPayRequestBuilder);
$data = [];
$data["status"] = $qrPayResult->getTradeStatus(); // SUCCESS/FAILED/UNKNOWN
$response = json_decode(json_encode($qrPayResult->getResponse()), true);
$arr = cache('txm_' . $out_trade_no);
//错误信息记录
//file_put_contents('../runtime/busalicodepay.txt', json_encode($response) . "\r\n", FILE_APPEND);
if ($data["status"] == "SUCCESS") { //通信成功
if ($response["code"] == "10000") {//支付成功
//执行系统订单业务逻辑
$order_arr['msg'] = "支付成功";
$order_arr['order_sn'] = $out_trade_no;
$order_arr['code'] = 1;
return $order_arr;
} else {
json_data_return(0, $data["msg"]);
}
} else {
//错误信息记录
//file_put_contents('../runtime/busalicodepayerr.txt', json_encode($response) . "\r\n", FILE_APPEND);
$order_arr['msg'] = "失败";
$order_arr['order_sn'] = $out_trade_no;
$order_arr['code'] = 0;
return $order_arr;
}
}
小提示:如果不走ISV模式,把下图代码更换注释掉就可以。(个人建议如果需要服务商模式,最好新建一个控制器去处理业务,在提交订单的时候判断店铺中是否有授权的app_auth_token,走对应的控制器)
//把代码中这个配置文件的引用换为自研应用的配置文件
require_once '../vendor/alipaydmf/f2fpay/config/config.php';
//这两行注释掉
$arr = cache('txm_' . $out_trade_no);
$barPayRequestBuilder->setAppAuthToken($arr['app_auth_token']);
以上就是ISV服务商模式下的当面付支付代码。菜鸟一枚,记录一下~