[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lk90Ar0V-1596707877480)(http://192.168.1.104:8080/server/…/Public/Uploads/2020-05-21/5ec6223b06567.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bohjx4lq-1596707877483)(http://192.168.1.104:8080/server/…/Public/Uploads/2020-05-21/5ec6224b8db20.png)]
更多流程相关的信息可以看这篇文章:跳转
IPN全称是Instant Payment Notification(即时付款通知),当客户向您付款或付款被退回或退款时,PayPal会通过您指定的URL向您的服务器发布通知。此通知中将包含您客户的所有付款信息(例如,客户名称,付款金额)以及一段加密代码。服务器收到通知后,它将把包括加密代码在内的信息发布回安全的PayPal URL。贝宝将对交易进行身份验证并将其有效性确认发送回您的服务器。
PayPal提供了多个API接口供开发者使用。在使用API之前,你必zhidao须先申请一个高级个人账户或者企业账户,同时你必须获取API 凭证供每次调用API 时使用。
一旦你获取了API凭证,您就可以调用相关的API接口专了。目前,我们提供两种API接口方式,NVP和SOAP。一般来说我们推荐您使用 NVP 接口。
Name-Value Pair(NVP)接口 – 请求和响应都是使用简单的HTTP。该接口简单易实现,适合於初级开发者和需要快速完成集成的属人员;
SOAP接口 - 请求和响应都是通过SOAP来完成。该接口适合於面向对象工程的开发;
PayPal API:NVP(名称/值对)接口
通过NVP API接口, 您只需给PayPal发送一个HTTP请求,并通过“名称=值”的形式指定请求参数,即可充分利用PayPal的API功能。
NVP API 是 PayPal 的业务功能、风险管理和业务逻辑的简单接口。NVP API 最基本的使用方法是通过到 PayPal 服务器的 HTTPS 连接发送一个 NVP 字符串,然後处理响应(也是一个 NVP 字符串)。执行 NVP API 调用
假如现在有一个应用要接入PayPal
创建沙盒账号时至少应该建立一个Business的和一个Personal的,这种账号注册方法和Paypal的流程一样,信息可以是假的,包括银行帐号、信用卡(其实Paypal Sandbox会自动生成一些随机的号码)。接下来需要激活Paypal Sandbox的虚拟帐号,注意,这里不管你在Paypal Sanbox注册时填什么邮件地址,有任何发送到虚拟帐号所填邮箱的邮件都存会在开发帐号的管理界面中的Email页(导航栏上有)中。登录Sandbox的虚拟Paypal环境,还需要验证虚拟帐号的银行,这里可以随便填,然后通过Add Funds来给账户充值(想填多少填多少)。
以Laravel团队开发的srmklive/paypal为例子,如果框架是laravel,那配置paypal在config/paypal.php进行,如果不是,则需要在实例化对象时传入配置。文档,这个包所有跟paypal的接口交互方式都是NVP,该包已经全部封装好了,我们直接调用就可以了。
货币代码文档
https://developer.paypal.com/docs/api/reference/currency-codes/
国家代码文档
https://developer.paypal.com/docs/api/reference/country-codes/
州和省代码文档
https://developer.paypal.com/docs/api/reference/state-codes/
区域代码文档
https://developer.paypal.com/docs/api/reference/locale-codes/
沙盒环境下的APPID统一都是APP-80W284485P519543T
https://developer.paypal.com/docs/archive/nvp-soap-api/gs-PayPalAPIs/#the-components-of-an-api-request
详情看这个文档
NVP接口列表
https://developer.paypal.com/docs/archive/nvp-soap-api/#
下单NVP接口文档
https://developer.paypal.com/docs/archive/nvp-soap-api/merchant/set-express-checkout-nvp/
IPN校验结果判断处理文档
https://www.paypal.com/c2/cgi-bin/webscr?cmd=p/acc/ipn-info-outside
https://developer.paypal.com/docs/api-basics/notifications/ipn/IPNandPDTVariables/
cancel_url和return_url的处理调用到的NVP接口相关的文档
https://developer.paypal.com/docs/archive/nvp-soap-api/merchant/get-express-checkout-details-nvp/
https://developer.paypal.com/docs/archive/nvp-soap-api/merchant/do-express-checkout-payment-nvp/
$orderData['items'] = [
[
'name' => 'test',//商品名称
'price' => 1, //商品价格
'qty' => 1 //商品个数
],
];
$orderData['invoice_id'] = 'xxxx'; //订单id
$orderData['invoice_description'] = 'xxxxx';//订单描述
$orderData['return_url'] = 'xxxxx';// 统一下单成功,跳转地址
$orderData['cancel_url'] = 'xxxxx';// 下单失败,跳转地址
$orderData['total'] = 1;// 订单总额
$express = new ExpressCheckout;
$provider->setCurrency('USD'); //设置paypal支付币种(可以使用config中的默认)
$res = $express->setExpressCheckout($orderData);//设置参数,获取paypal链接(及时支付)
$provider = new ExpressCheckout;
$request->merge(['cmd' => '_notify-validate']);
$post = $request->all();
$res = (string)$provider->verifyIPN($post);
$token = $request->input('token', '');
$provider = new ExpressCheckout;
$response = $provider->getExpressCheckoutDetails($token);
if (in_array(strtoupper($response['ACK']), ['SUCCESS', 'SUCCESSWITHWARNING'])) {
if ($response['BILLINGAGREEMENTACCEPTEDSTATUS'] == 0) {
// 用户取消订单
} else {
$payerId = $request->input('PayerID', ''); // 支付者paypalid
$paymentStatus = $provider->doExpressCheckoutPayment($orderData, $token, $payerId);
// 调用NVP接口完成Express Checkout交易
$orderData['items'] = [
[
'name' => 'test',//商品名称
'price' => 1, //商品价格
'qty' => 1 //商品个数
],
];
$orderData['invoice_id'] = 'xxxx'; //订单id
$orderData['invoice_description'] = 'xxxxx';//订单描述
$orderData['return_url'] = 'xxxxx';// 统一下单成功,跳转地址
$orderData['cancel_url'] = 'xxxxx';// 下单失败,跳转地址
$orderData['total'] = 1;// 订单总额
// 完成Express Checkout交易
$paymentStatus = $provider->doExpressCheckoutPayment($orderData, $token, $payerId);
$status = $paymentStatus['PAYMENTINFO_0_PAYMENTSTATUS'];
if (!strcasecmp($status, 'Completed') || !strcasecmp($status, 'Processed')) {
// 订单成功
} else {
// 订单失败
}
}
}