Paypal支付的整体逻辑:
目前由于PayPal支持TSL1.2 ,JDK1.8才全面支持,JDK1.7的开发者,需要额外配置才可以正确使用
1,前端向服务器下单,服务端向PayPal调用下单接口 ,
/payment
resource to create a
sale, an
authorized payment, or an
order. A sale is a direct credit card payment, stored credit card payment, or PayPal payment. An authorized payment places funds on hold to be captured later. An order is a purchase that a customer has approved but for which the funds are not placed on hold. You can also use this resource to execute approved PayPal payments and show details for, update, and list payments. For more information, see also Payments.
intent
to
sale
,
authorize
, or
order
.
Note: TPP Clients (Third Party Providers in the context of PSD2 regulation) are restricted from usingauthorize
andorder
intents.
访问地址如下 https://developer.paypal.com/docs/api/payments/#payment_create
Java代码如下
public Payment getPayUrl(String currency, String goodId) { PayPalRechargeList payPalRechargeList = this.getPayPalRechargeListByGooodId(goodId); Payment createdPayment = null; Details details = new Details(); details.setShipping("0"); details.setSubtotal(payPalRechargeList.getMoney() + ""); details.setTax("0"); // ###Amount // Let's you specify a payment amount. Amount amount = new Amount(); amount.setCurrency(currency); // Total must be equal to sum of shipping, tax and subtotal. amount.setTotal(payPalRechargeList.getMoney() + ""); amount.setDetails(details); // ###Transaction // A transaction defines the contract of a // payment - what is the payment for and who // is fulfilling it. Transaction is created with // a `Payee` and `Amount` types Transaction transaction = new Transaction(); transaction.setAmount(amount); transaction .setDescription("Dobi"); // ### Items Item item = new Item(); item.setName(payPalRechargeList.getCoinNum() + "DoBi").setQuantity("1").setCurrency(currency).setPrice(payPalRechargeList.getMoney() + ""); ItemList itemList = new ItemList(); List- items = new ArrayList<>(); items.add(item); itemList.setItems(items); transaction.setItemList(itemList); // The Payment creation API requires a list of // Transaction; add the created `Transaction` // to a List List
transactions = new ArrayList (); transactions.add(transaction); // ###Payer // A resource representing a Payer that funds a payment // Payment Method // as 'paypal' Payer payer = new Payer(); payer.setPaymentMethod("paypal"); // ###Payment // A Payment Resource; create one using // the above types and intent as 'sale' Payment payment = new Payment(); payment.setIntent("sale"); payment.setPayer(payer); payment.setTransactions(transactions); // ###Redirect URLs RedirectUrls redirectUrls = new RedirectUrls(); String guid = UUID.randomUUID().toString().replaceAll("-", ""); redirectUrls.setCancelUrl("https://hello/error.html?guid=" + guid); redirectUrls.setReturnUrl("https://hello/test?guid=" + guid); payment.setRedirectUrls(redirectUrls); // Create a payment by posting to the APIService // using a valid AccessToken // The return object contains the status; try { createdPayment = payment.create(apiContext); log.info("Created payment with id = " + createdPayment.getId() + " and status = " + createdPayment.getState()); createdPayment.setCart(guid); return createdPayment; } catch (PayPalRESTException e) { log.error(e.getMessage(), e); return null; } }
2,将解析到的数据进行分析,获取到整个payment 返回给前端 payment如下
{
"id": "PAY-1B56960729604235TKQQIYVY",
"create_time": "2017-09-22T20:53:43Z",
"update_time": "2017-09-22T20:53:44Z",
"state": "created",
"intent": "sale",
"payer": {
"payment_method": "paypal"
},
"transactions": [
{
"amount": {
"total": "30.11",
"currency": "USD",
"details": {
"subtotal": "30.00",
"tax": "0.07",
"shipping": "0.03",
"handling_fee": "1.00",
"insurance": "0.01",
"shipping_discount": "-1.00"
}
},
"description": "The payment transaction description.",
"custom": "EBAY_EMS_90048630024435",
"invoice_number": "48787589673",
"item_list": {
"items": [
{
"name": "hat",
"sku": "1",
"price": "3.00",
"currency": "USD",
"quantity": "5",
"description": "Brown hat.",
"tax": "0.01"
},
{
"name": "handbag",
"sku": "product34",
"price": "15.00",
"currency": "USD",
"quantity": "1",
"description": "Black handbag.",
"tax": "0.02"
}
],
"shipping_address": {
"recipient_name": "Brian Robinson",
"line1": "4th Floor",
"line2": "Unit #34",
"city": "San Jose",
"state": "CA",
"phone": "011862212345678",
"postal_code": "95131",
"country_code": "US"
}
}
}
],
"links": [
{
"href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-1B56960729604235TKQQIYVY",
"rel": "self",
"method": "GET"
},
{
"href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-60385559L1062554J",
"rel": "approval_url",
"method": "REDIRECT"
},
{
"href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-1B56960729604235TKQQIYVY/execute",
"rel": "execute",
"method": "POST"
}
]
}
通常web端直接将 links中的 approval_uri返回给web端 web端直接进行跳转即可
3,前端支付完成后,获取到 paymentId 以及 payerId,传递到服务端,服务端调用 execute方法来确认支付,此处非常重要,否则PayPal会默认付款取消,此处为确认支付,商家才可以收到付款
Important: This call works only after a customer has approved the payment. For more information, learn about PayPal payments.
Java代码如下
public Payment validate(String paymentId, String payerId) { Payment payment = new Payment(); Payment resultPayment = null; try { PaymentExecution paymentExecution = new PaymentExecution(); paymentExecution.setPayerId(payerId); payment.setId(paymentId); Payment payment1 = payment.execute(apiContext, new PaymentExecution().setPayerId(payerId)); log.info(payment1.toJSON()); } catch (PayPalRESTException e) { e.printStackTrace(); } return resultPayment; }
4,服务端获取整个payment信息,校验是否已经支付
payment_id
string
required
返回的response如下
{ "id": "PAYID-LMYM6CY95083200HL4543007", "intent": "sale", "payer": { "payment_method": "paypal", "status": "UNVERIFIED", "payer_info": { "email": "[email protected]", "first_name": "耀", "last_name": "于", "payer_id": "4SGL2NWMDBP9Y", "phone": "1233123123", "country_code": "TW", "shipping_address": { "recipient_name": "耀 于", "line1": "天安门", "city": "北京市", "country_code": "TW", "postal_code": "", "state": "" } } }, "cart": "1R9232916G0995838", "transactions": [ { "related_resources": [ { "sale": { "id": "69F380155N7237353", "amount": { "currency": "USD", "total": "5.00", "details": { "subtotal": "5.00", "shipping": "0.00", "tax": "0.00", "handling_fee": "0.00", "shipping_discount": "0.00", "insurance": "0.00" } }, "payment_mode": "INSTANT_TRANSFER", "state": "completed", "protection_eligibility": "ELIGIBLE", "protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE", "transaction_fee": { "currency": "USD", "value": "0.52" }, "receivable_amount": { "currency": "USD", "value": "5.00" }, "exchange_rate": "0.031774777741192", "parent_payment": "PAYID-LMYM6CY95083200HL4543007", "create_time": "2018-06-25T11:17:13Z", "update_time": "2018-06-25T11:17:13Z", "links": [ { "href": "https://api.paypal.com/v1/payments/sale/69F380155N7237353", "rel": "self", "method": "GET" }, { "href": "https://api.paypal.com/v1/payments/sale/69F380155N7237353/refund", "rel": "refund", "method": "POST" }, { "href": "https://api.paypal.com/v1/payments/payment/PAYID-LMYM6CY95083200HL4543007", "rel": "parent_payment", "method": "GET" } ] } } ], "amount": { "currency": "USD", "total": "5.00", "details": { "subtotal": "5.00", "shipping": "0.00", "tax": "0.00", "handling_fee": "0.00", "shipping_discount": "0.00", "insurance": "0.00" } }, "payee": { "email": "[email protected]", "merchant_id": "C383WQ7FC6WW8" }, "description": "Dobi", "soft_descriptor": "PAYPAL *LESDO", "item_list": { "items": [ { "name": "210DoBi", "quantity": "1", "price": "5.00", "currency": "USD", "tax": "0.00" } ], "shipping_address": { "recipient_name": "耀宣 于", "line1": "三民區大豐一路109之15號6樓之5", "city": "高雄市", "country_code": "TW", "postal_code": "", "state": "" } } } ], "state": "approved", "create_time": "2018-06-25T11:16:27Z", "update_time": "2018-06-25T11:17:13Z", "links": [ { "href": "https://api.paypal.com/v1/payments/payment/PAYID-LMYM6CY95083200HL4543007", "rel": "self", "method": "GET" } ] }
state字段来确认是否支付 approved标识支付成功 create 标识还未支付 处于创建状态 failed 支付失败
Java代码如下
public Payment validate(String paymentId, String payerId) { Payment payment = new Payment(); Payment resultPayment = null; try { resultPayment = Payment.get(apiContext, paymentId); log.info(resultPayment.toJSON()); } catch (PayPalRESTException e) { e.printStackTrace(); } return resultPayment; }
5,根据定义的交易ID 来确认支付成功 修改订单状态,返回前端购买成功