PayPal支付流程

燕钟展
2023-12-01

PayPal支付流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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是什么?

IPN全称是Instant Payment Notification(即时付款通知),当客户向您付款或付款被退回或退款时,PayPal会通过您指定的URL向您的服务器发布通知。此通知中将包含您客户的所有付款信息(例如,客户名称,付款金额)以及一段加密代码。服务器收到通知后,它将把包括加密代码在内的信息发布回安全的PayPal URL。贝宝将对交易进行身份验证并将其有效性确认发送回您的服务器。

官方IPN文档

NVP和SOAP是什么?

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

  1. 首先创建一个开发者账号(注册链接),注册登录完成之后创建沙盒账号(链接)(沙盒账号是PayPal提供给开发者开发调试的账号,不需要真正的支付)。
  2. 设置IPN,首先登录上Business的沙盒账号(登录链接),点击右上角的设置进入账户设置页面,然后点击通知 -> 即时付款通知 -> 更新
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mqH8uSWt-1596707877484)(http://192.168.1.104:8080/server/…/Public/Uploads/2020-05-21/5ec62b47b1e5d.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D47ptBev-1596707877486)(http://192.168.1.104:8080/server/…/Public/Uploads/2020-05-21/5ec62b98ad87d.png)]
  3. 开发回调处理代码,IPN处理流程见官方文档
  4. 开发cancel_url和return_url的处理,cancel_url是用户取消订单后跳转的链接,return_url是支付成功之后跳转的链接,一般都是跳转到后端的接口上,然后经过逻辑处理,重定向到指定的链接。

沙盒账号详解

创建沙盒账号时至少应该建立一个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/

paypal下单

$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链接(及时支付)

IPN处理

$provider = new ExpressCheckout;
$request->merge(['cmd' => '_notify-validate']);
$post = $request->all();
$res = (string)$provider->verifyIPN($post);

对return_url和cancel_url回来的数据进行校验处理

$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 {
			// 订单失败
		}
	}
}
 类似资料: