paypal支付(Java)
参考文档:https://blog.csdn.net/weixin_41500775/article/details/118580295?spm=1001.2014.3001.5501
https://blog.csdn.net/change_on/article/details/73881791
官方文档:https://developer.paypal.com/docs/?countries=C2
一:pom文件
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>checkout-sdk</artifactId>
<version>1.0.2</version>
</dependency>
二:代码示例
// 1.创建订单
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.json.JSONException;
import org.json.JSONObject;
import com.paypal.http.HttpResponse;
import com.paypal.http.serializer.Json;
import com.paypal.orders.AddressPortable;
import com.paypal.orders.AmountBreakdown;
import com.paypal.orders.AmountWithBreakdown;
import com.paypal.orders.ApplicationContext;
import com.paypal.orders.Item;
import com.paypal.orders.LinkDescription;
import com.paypal.orders.Money;
import com.paypal.orders.Name;
import com.paypal.orders.Order;
import com.paypal.orders.OrderRequest;
import com.paypal.orders.OrdersCreateRequest;
import com.paypal.orders.PurchaseUnitRequest;
import com.paypal.orders.ShippingDetail;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CreateOrder {
private String clientId = "";
private String clientSecret = "";
private String mode = "sandbox";
public static final String CAPTURE = "CAPTURE";
/**
* 该标签将覆盖PayPal网站上PayPal帐户中的公司名称
*/
public static final String BRANDNAME = "Supernote";
/**
* LOGIN。当客户单击PayPal Checkout时,客户将被重定向到页面以登录PayPal并批准付款。
* BILLING。当客户单击PayPal Checkout时,客户将被重定向到一个页面,以输入信用卡或借记卡以及完成购买所需的其他相关账单信息
* NO_PREFERENCE。当客户单击“ PayPal Checkout”时,将根据其先前的交互方式将其重定向到页面以登录PayPal并批准付款,或重定向至页面以输入信用卡或借记卡以及完成购买所需的其他相关账单信息使用PayPal。
* 默认值:NO_PREFERENCE
*/
public static final String LANDINGPAGE = "NO_PREFERENCE";
/**
* CONTINUE。将客户重定向到PayPal付款页面后,将出现“ 继续”按钮。当结帐流程启动时最终金额未知时,请使用此选项,并且您想将客户重定向到商家页面而不处理付款。
* PAY_NOW。将客户重定向到PayPal付款页面后,出现“ 立即付款”按钮。当启动结帐时知道最终金额并且您要在客户单击“ 立即付款”时立即处理付款时,请使用此选项。
*/
// public static final String USERACTION = "PAY_NOW";
public static final String USERACTION = "CONTINUE";
/**
* GET_FROM_FILE。使用贝宝网站上客户提供的送货地址。
* NO_SHIPPING。从PayPal网站编辑送货地址。推荐用于数字商品
* SET_PROVIDED_ADDRESS。使用商家提供的地址。客户无法在PayPal网站上更改此地址
*/
public static final String SHIPPINGPREFERENCE = "SET_PROVIDED_ADDRESS";
/**
* 生成订单主体信息
*/
private OrderRequest buildRequestBody() {
OrderRequest orderRequest = new OrderRequest();
orderRequest.checkoutPaymentIntent(CAPTURE);
ApplicationContext applicationContext = new ApplicationContext()
.brandName(BRANDNAME)
.landingPage(LANDINGPAGE)
.cancelUrl("https://www.jd.com").returnUrl("https://www.baidu.com")
.userAction(USERACTION)
.shippingPreference(SHIPPINGPREFERENCE);
orderRequest.applicationContext(applicationContext);
List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<PurchaseUnitRequest>();
@SuppressWarnings("serial")
PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest()
.description("<p>多规格</p>")
.customId("13")
// .invoiceId("")
.invoiceId("")
.amountWithBreakdown(new AmountWithBreakdown()
.currencyCode("USD")
.value("1.0")// value = itemTotal + shipping + handling + taxTotal + shippingDiscount;
.amountBreakdown(new AmountBreakdown()
.itemTotal(new Money().currencyCode("USD").value("1.0")) // itemTotal = Item[Supernote A6](value × quantity) + Item[帆布封套](value × quantity)
.shipping(new Money().currencyCode("USD").value("0.00"))
.handling(new Money().currencyCode("USD").value("0.00"))
.taxTotal(new Money().currencyCode("USD").value("0.00"))
.shippingDiscount(new Money().currencyCode("USD").value("0.00"))))
.items(new ArrayList<Item>() {
{
add(new Item().name("Supernote A6").description("丝滑般流畅的书写体验")
.unitAmount(new Money()
.currencyCode("USD")
.value("1.0"))
.quantity("1"));
/*add(new Item().name("帆布封套").description("黑色帆布保护封套")
.unitAmount(new Money()
.currencyCode("USD")
.value("20.00"))
.quantity("1"));*/
}
})
.shippingDetail(new ShippingDetail()
.name(new Name().fullName("RATTA"))
.addressPortable(new AddressPortable()
.addressLine1("梅陇镇")
// .addressLine2("集心路168号")
.adminArea2("闵行区")
// .adminArea1("上海市")
.postalCode("20000")
.countryCode("CN")));
purchaseUnitRequests.add(purchaseUnitRequest);
orderRequest.purchaseUnits(purchaseUnitRequests);
return orderRequest;
}
/**
* 创建订单的方法
* @throws 收银台地址
*/
public String createOrder() throws IOException, JSONException {
OrdersCreateRequest request = new OrdersCreateRequest();
request.header("prefer","return=representation");
request.requestBody(buildRequestBody());
PayPalClient payPalClient = new PayPalClient();
HttpResponse<Order> response = null;
try {
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (IOException e1) {
try {
log.error("第1次调用paypal订单创建失败");
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (Exception e) {
try {
log.error("第2次调用paypal订单创建失败");
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (Exception e2) {
log.error("第3次调用paypal订单创建失败,失败原因:{}", e2.getMessage());
}
}
}
String approve = "";
if (response.statusCode() == 201) {
System.out.println("Status Code: " + response.statusCode());
System.out.println("Status: " + response.result().status());
//需要进行扣款的orderId
System.out.println("Order ID: " + response.result().id());
log.info("Status Code = {}, Status = {}, OrderID = {}, Intent = {}", response.statusCode(), response.result().status(), response.result().id(), response.result().checkoutPaymentIntent());
for (LinkDescription link : response.result().links()) {
log.info("Links-{}: {} \tCall Type: {}", link.rel(), link.href(), link.method());
if(link.rel().equals("approve")) {
approve = link.href();
}
}
String totalAmount = response.result().purchaseUnits().get(0).amountWithBreakdown().currencyCode() + ":" + response.result().purchaseUnits().get(0).amountWithBreakdown().value();
log.info("Total Amount: {}", totalAmount);
String json= new JSONObject(new Json().serialize(response.result())).toString(4);
log.info("createOrder response body: {}", json);
}
return approve;
}
public static void main(String args[]) {
try {
String approveUrl = new CreateOrder().createOrder();
System.out.println("approveUrl = "+ approveUrl);
} catch (com.paypal.http.exceptions.HttpException e) {
System.out.println(e.getLocalizedMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
//2.执行扣款
import java.io.IOException;
import com.paypal.orders.*;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.json.JSONObject;
import com.paypal.http.HttpResponse;
import com.paypal.http.serializer.Json;
@Slf4j
public class CaptureOrder extends PayPalClient {
private String clientId = "";
private String clientSecret = "e";
private String mode = "sandbox";
public OrderRequest buildRequestBody() {
return new OrderRequest();
}
/**
* 用户授权支付成功,进行扣款操作
*/
public HttpResponse<Order> captureOrder(String orderId) throws IOException, JSONException {
OrdersCaptureRequest request = new OrdersCaptureRequest(orderId);
request.requestBody(new OrderRequest());
PayPalClient payPalClient = new PayPalClient();
HttpResponse<Order> response = null;
try {
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (IOException e1) {
try {
log.error("第1次调用paypal扣款失败");
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (Exception e) {
try {
log.error("第2次调用paypal扣款失败");
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (Exception e2) {
log.error("第3次调用paypal扣款失败,失败原因 {}", e2.getMessage() );
}
}
}
log.info("Status Code = {}, Status = {}, OrderID = {}", response.statusCode(), response.result().status(), response.result().id());
for (LinkDescription link : response.result().links()) {
log.info("Links-{}: {} \tCall Type: {}", link.rel(), link.href(), link.method());
}
for (PurchaseUnit purchaseUnit : response.result().purchaseUnits()) {
for (Capture capture : purchaseUnit.payments().captures()) {
log.info("Capture id: {}", capture.id());
log.info("status: {}", capture.status());
log.info("invoice_id: {}", capture.invoiceId());
if("COMPLETED".equals(capture.status())) {
//进行数据库操作,修改订单状态为已支付成功,尽快发货(配合回调和CapturesGet查询确定成功)
log.info("支付成功,状态为=COMPLETED");
}
if("PENDING".equals(capture.status())) {
log.info("status_details: {}", capture.captureStatusDetails().reason());
String reason = "PENDING";
if(capture.captureStatusDetails() != null && capture.captureStatusDetails().reason() != null) {
reason = capture.captureStatusDetails().reason();
}
//进行数据库操作,修改订单状态为已支付成功,但触发了人工审核,请审核通过后再发货(配合回调和CapturesGet查询确定成功)
log.info("支付成功,状态为=PENDING : {}", reason);
}
}
}
Payer buyer = response.result().payer();
log.info("Buyer Email Address: {}", buyer.email());
log.info("Buyer Name: {} {}", buyer.name().givenName(), buyer.name().surname());
String json = new JSONObject(new Json().serialize(response.result())).toString(4);
log.info("captureOrder response body: {}", json);
return response;
}
public static void main(String[] args) {
try {
new CaptureOrder().captureOrder("");
} catch (Exception e) {
e.printStackTrace();
}
}
}
//3.退款
import java.io.IOException;
import org.json.JSONException;
import org.json.JSONObject;
import com.paypal.http.HttpResponse;
import com.paypal.http.serializer.Json;
import com.paypal.orders.OrdersGetRequest;
import com.paypal.payments.CapturesRefundRequest;
import com.paypal.payments.Money;
import com.paypal.payments.Refund;
import com.paypal.payments.RefundRequest;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class RefundOrder extends PayPalClient {
private String clientId = "";
private String clientSecret = "";
private String mode = "sandbox";
/**
* 创建退款请求体
*/
public RefundRequest buildRequestBody() {
RefundRequest refundRequest = new RefundRequest();
Money money = new Money();
money.currencyCode("USD");
money.value("40.00");
refundRequest.amount(money);
refundRequest.invoiceId("");
refundRequest.noteToPayer("7天无理由退款");
return refundRequest;
}
/**
* 申请退款
*/
public HttpResponse<Refund> refundOrder(String orderId) throws IOException, JSONException {
OrdersGetRequest ordersGetRequest = new OrdersGetRequest(orderId);
PayPalClient payPalClient = new PayPalClient();
HttpResponse<com.paypal.orders.Order> ordersGetResponse = null;
try {
ordersGetResponse = payPalClient.client(mode, clientId, clientSecret).execute(ordersGetRequest);
} catch (Exception e) {
try {
log.error("第1次调用paypal订单查询失败");
ordersGetResponse = payPalClient.client(mode, clientId, clientSecret).execute(ordersGetRequest);
} catch (Exception e2) {
try {
log.error("第2次调用paypal订单查询失败");
ordersGetResponse = payPalClient.client(mode, clientId, clientSecret).execute(ordersGetRequest);
} catch (Exception e3) {
log.error("第3次调用paypal订单查询失败,失败原因:{}", e3.getMessage());
}
}
}
String captureId = ordersGetResponse.result().purchaseUnits().get(0).payments().captures().get(0).id();
CapturesRefundRequest request = new CapturesRefundRequest(captureId);
request.prefer("return=representation");
request.requestBody( buildRequestBody());
HttpResponse<Refund> response = null;
try {
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (IOException e) {
try {
log.error("第1次调用paypal退款申请失败");
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (Exception e1) {
try {
log.error("第2次调用paypal退款申请失败");
response = payPalClient.client(mode, clientId, clientSecret).execute(request);
} catch (Exception e2) {
log.error("第3次调用paypal退款申请失败,失败原因 {}", e2.getMessage());
}
}
}
log.info("Status Code = {}, Status = {}, RefundID = {}", response.statusCode(), response.result().status(), response.result().id());
if("COMPLETED".equals(response.result().status())) {
//进行数据库操作,修改状态为已退款(配合回调和退款查询确定退款成功)
log.info("退款成功");
}
for (com.paypal.payments.LinkDescription link : response.result().links()) {
log.info("Links-{}: {} \tCall Type: {}", link.rel(), link.href(), link.method());
}
String json = new JSONObject(new Json().serialize(response.result())).toString(4);
log.info("refundOrder response body: {}", json);
return response;
}
public static void main(String[] args) {
try {
new RefundOrder().refundOrder("");
} catch (Exception e) {
e.printStackTrace();
}
}
}