App 之 Php Paypal 支付方案(希望开发的小伙伴们能少踩坑)
大家好! 这是我第一次在CSDN上发布开发攻略,在Paypal的APP支付上,本人采坑无数真是辛酸又苦辣,Paypal的SDK文档真是旧、杂、乱、多,然后全是小鱼吐的泡泡了。。。
一言难尽,文档真是谁读谁知道啊!可以神交的小伙伴别忘了在下面给我留言,讲出你的苦吧~~~
好了废话不多说,让我们一起来撸它—Paypal支付
因为Php是世界上最好的开发语言,所以本人也就用她了~~
在做Paypal支付之前大家一定要搞清楚一件事,早在2013年下半年,PayPal就已经收购了Braintree,所以现在PayPal支付v2版本的API接口,废弃了自己的Android跟Ios的SDK,所以大家想接APP的小伙伴只能转头向Braintree,但是但是!!!在中国内陆的公司是不能申请跟使用Braintree的LIVE版(正式服)SDK!现开放的地区只有美国、加拿大。。。
所以我们只能回到最初的Paypal,虽然Android跟Ios的SDK已被自己废弃,但是后端的支付还在,而且还升级到了v2版本!
于是,哈哈开搞:
Paypal 账户注册完善基本资料地址:https://www.paypal.com/c2/signin?locale.x=zh_C2
Paypal 开发配置地址:https://developer.paypal.com/developer/applications
Paypal 收费标准地址:https://www.paypal.com/us/business/pricing
Paypal v2版SDK地址:https://github.com/paypal/Checkout-PHP-SDK
Paypal 沙盒登录地址:https://www.sandbox.paypal.com/c2/signin
PAYPAL 支付图解
整个Paypal支付流程分为三个部分,支付订单的状态也分为CREATE、APPROVE、COMPLETE:
思路:
1、用v2版的后台支付Checkout-PHP-SDK,创建paypal支付订单,得到 href。
$environment = new PayPalCheckoutSdk\Core\SandboxEnvironment(PAYPAL_SANDBOX_CLIENT_ID, PAYPAL_SANDBOX_CLIENT_SECRET);
$client = new PayPalCheckoutSdk\Core\PayPalHttpClient($environment);
$request = new PayPalCheckoutSdk\Orders\OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
"intent" => INTENT, //验证模式
"purchase_units" => [[
"amount" => [
"value" => 10,
"currency_code" => 'USD'
]
]],
"application_context" => [
"cancel_url" => PAYPAL_CANCEL_URL,
"return_url" => PAYPAL_RETURN_URL,
]
];
$response = $client->execute($request);
$url = $response->result->links[1]->href;
2.这个$url长这样:https://www.sandbox.paypal.com/checkoutnow?token=5HR27678Y9684566U
里面的PAYPAL_CANCEL_URL、PAYPAL_RETURN_URL是两个回跳APP用的H5页面地址(后面会讲到)
将$url这个地址给APP端,让前端用webView打开此链接,登录之后就是这样:
然后自己写两个跳转H5,地址分别PAYPAL_CANCEL_URL、PAYPAL_RETURN_URL,在支付成功、支付失败后会被Paypal自动打开,
3.在H5里用js定义回跳Android跟Ios APP的方法(需要跟前端的小伙伴商定好),并设置成钩子函数,打开页面时自动执行,这样两个H5几乎是不会显示出来的,一闪你就又回到APP内部了~~
在支付成功、失败后,Paypal会以Get请求的方式去访问你之前设置的那两个H5地址,并在后面加上token、Payer 两个参数值,
它大概长这样https://XXXX.com/?token=9HR2JH432J4H41U&PayerID=87SDFG8S8SDFG7
然后用js把里面的token参数值提取出来,传给APP前端
下面的js我是粗略写的,修改一下即可
var paramInfo = new Array();
paramInfo= GetRequest();
var token = paramInfo[2];
//接收Paypal
function GetRequest() {
var url=window.location.href.split("?")[1]; /*获取url里"?"后面的值*/
if(url.indexOf("&")>0){ /*判断是否是一个参数还是多个参数*/
urlParamArry=url.split("&"); /*分开每个参数,并放到数组里*/
var arr = new Array();
for(var i=0; i<urlParamArry.length; i++){
var paramerName=urlParamArry[i].split("="); /*把每个参数名和值分开,并放到数组里*/
arr.push(paramerName[1]);
}
return arr;
}
function getType() {
var u = navigator.userAgent;
var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; //android安卓
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios苹果
if (isAndroid) {
Android.saveUnreadMsgCnt(token)
} else if (isiOS) {
let a = {
notReadNum:this.notReadNum
}
window.webkit.messageHandlers.saveUnreadMsgCnt.postMessage(token);
// uni.navigateBack({});
}
},
于是App端的小伙伴就拿到了这个token,恩,很关键!也很nice!
接下来我们前端小伙伴就需要把这个token传给后台,让我们的大后台拿着它去验证支付的订单吧(其实就是将支付订单的状态由“APPROVED”转换成“COMPLETED”):
$environment = new PayPalCheckoutSdk\Core\SandboxEnvironment(PAYPAL_SANDBOX_CLIENT_ID, PAYPAL_SANDBOX_CLIENT_SECRET);
$client = new PayPalCheckoutSdk\Core\PayPalHttpClient($environment);
//先判断订单当前状态-防止订单已经是已完成状态,再次扣款
$request = new \PayPalCheckoutSdk\Orders\OrdersGetRequest($token);
$response = $client->execute($request);
$status = $response->result->status;
switch ($status){
case 'COMPLETED': //订单已经完成
//
break;
case 'APPROVED': //获取支付金额
$captureRequest = new \PayPalCheckoutSdk\Orders\OrdersCaptureRequest($token);
$captureRequest->prefer('return=minimal'); //简洁参数-获取更多参数用return=representation
$captureResponse = $client->execute($captureRequest);
//返回状态不是已完成
if($captureResponse->result->status != 'COMPLETED'){
//报错
}
break;
default: //其他
//报错
break;
}
最后我们用之前在官网配置的“WEBHOOKS”回调地址方法,去接收Paypal支付状态为“COMPLETED”的回调信息,然后就可以各种CURD处理你的业务喽~~~
Paypal纯前端JS SDK开发文档地址:https://developer.paypal.com/docs/checkout/(纯前端傻瓜式对接,参数明文,不推荐!!!)
这种方法是我踩坑走过的路,我也对接了,但是支付整体过程过于明文,实属不推荐!!!