转载请表明出处 https://blog.csdn.net/Amor_Leo/article/details/117959323 谢谢
准备
一、环境准备
-
注册paypal账号
-
注册paypal开发者账号
-
创建两个测试用户
-
创建应用,生成用于测试的clientID 和 密钥
代码
pom
<properties>
<paypal-rest.version>1.14.0</paypal-rest.version>
<paypal-checkout.version>1.0.4</paypal-checkout.version>
<paypal-out.version>1.1.0</paypal-out.version>
<paypal-core.version>1.7.2</paypal-core.version>
</properties>
<!-- PayPal-->
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>rest-api-sdk</artifactId>
<version>${
paypal-rest.version}</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>checkout-sdk</artifactId>
<version>${
paypal-checkout.version}</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>payouts-sdk</artifactId>
<version>${
paypal-out.version}</version>
</dependency>
<dependency>
<groupId>com.paypal.sdk</groupId>
<artifactId>paypal-core</artifactId>
<version>${
paypal-core.version}</version>
</dependency>
yml
paypal:
client:
id: xxxx
secret: xxxx
mode: sandbox
# mode: live
配置
import com.paypal.core.PayPalEnvironment;
import com.paypal.core.PayPalHttpClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.stereotype.Component;
import java.util.Iterator;
/**
* @author LHL
* @since 2021/6/3
*/
@Slf4j
@Component
public class PayPalClient {
public PayPalHttpClient client(String mode, String clientId, String clientSecret) {
log.info("mode={}, clientId={}, clientSecret={}", mode, clientId, clientSecret);
PayPalEnvironment environment = mode.equals("live") ? new PayPalEnvironment.Live(clientId, clientSecret) : new PayPalEnvironment.Sandbox(clientId, clientSecret);
return new PayPalHttpClient(environment);
}
/**
* @param jo
* @param pre
* @return
*/
public String prettyPrint(JSONObject jo, String pre) {
Iterator<?> keys = jo.keys();
StringBuilder pretty = new StringBuilder();
while (keys.hasNext()) {
String key = (String) keys.next();
pretty.append(String.format("%s%s: ", pre, StringUtils.capitalize(key)));
if (jo.get(key) instanceof JSONObject) {
pretty.append(prettyPrint(jo.getJSONObject(key), pre + "\t"));
} else if (jo.get(key) instanceof JSONArray) {
int sno = 1;
for (Object jsonObject : jo.getJSONArray(key)) {
pretty.append(String.format("\n%s\t%d:\n", pre, sno++));
pretty.append(prettyPrint((JSONObject) jsonObject, pre + "\t\t"));
}
} else {
pretty.append(String.format("%s\n", jo.getString(key)));
}
}
return pretty.toString();
}
}
支付结账
import com.paypal.http.HttpResponse;
import com.paypal.http.exceptions.SerializeException;
import com.paypal.http.serializer.Json;
import com.paypal.orders.AmountBreakdown;
import com.paypal.orders.AmountWithBreakdown;
import com.paypal.orders.ApplicationContext;
import com.paypal.orders.Capture;
import com.paypal.orders.LinkDescription;
import com.paypal.orders.Money;
import com.paypal.orders.Order;
import com.paypal.orders.OrderRequest;
import com.paypal.orders.OrdersCreateRequest;
import com.paypal.orders.OrdersGetRequest;
import com.paypal.orders.PurchaseUnitRequest;
import com.paypal.orders.Refund;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 创建订单
* @author LHL
**/
@Slf4j
@Component
public class CreateOrder extends PayPalClient {
@Value("${paypal.client.id}")
private String clientId;
@Value("${paypal.client.secret}")
private String clientSecret;
/**
* sandbox 沙箱/ live 正式环境
**/
@Value("${paypal.client.mode}")
private String mode;
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";
/**
* 当前货币币种简称, 默认为人名币的币种 EUR CNY USD
*/
public static final String CURRENT_CY = "USD";
/**
* GET_FROM_FILE。使用贝宝网站上客户提供的送货地址。
* NO_SHIPPING。从PayPal网站编辑送货地址。推荐用于数字商品
* SET_PROVIDED_ADDRESS。使用商家提供的地址。客户无法在PayPal网站上更改此地址
*/
public static final String SHIPPINGPREFERENCE = "NO_SHIPPING";
/**
* 生成订单主体信息
* @author LHL
*/
private OrderRequest buildOrderRequestBody(String description, String serialNumber, String price, String cancelUrl, String successUrl) {
OrderRequest orderRequest = new OrderRequest();
orderRequest.checkoutPaymentIntent(CAPTURE);
ApplicationContext applicationContext = new ApplicationContext()
//可不要
//.brandName(BRANDNAME)
//.landingPage(LANDINGPAGE)
//.cancelUrl(cancelUrl)
//.returnUrl(successUrl)
.userAction(USERACTION)
.shippingPreference(SHIPPINGPREFERENCE);
orderRequest.applicationContext(applicationContext);
List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<PurchaseUnitRequest>();
PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest()
//支付描述
.description(description)
//(唯一)订单号
.customId(serialNumber)
.invoiceId(serialNumber)
.amountWithBreakdown(new AmountWithBreakdown()
.currencyCode(CURRENT_CY)
//支付金额 value = itemTotal + shipping + handling + taxTotal + shippingDiscount; "220.00"
.value(price)
//可不要
//.amountBreakdown(new AmountBreakdown()
// // itemTotal = Item[Supernote A6](value × quantity) + Item[帆布封套](value × quantity)
// .itemTotal(new Money().currencyCode(CURRENT_CY).value(price))
// .shipping(new Money().currencyCode(CURRENT_CY).value("0.00"))
// .handling(new Money().currencyCode(CURRENT_CY).value("0.00"))
// .taxTotal(new Money().currencyCode(CURRENT_CY).value("0.00"))
// .shippingDiscount(new Money().currencyCode(CURRENT_CY).value("0.00")))
)
;
//可不要
//.items(new ArrayList<Item>() {
// {
// add(new Item().name("Supernote A6").description("丝滑般流畅的书写体验")
// .unitAmount(new Money()
// .currencyCode(CURRENT_CY)
// .value("200.00"))
// .quantity("1"));
// add(new Item().name("帆布封套").description("黑色帆布保护封套")
// .unitAmount(new Money()
// .currencyCode(CURRENT_CY)
// .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;
}
/**
* 创建订单的方法,返回orderId 给移动端; 再由移动端支付 付费后 ipn监听支付成功处理逻辑; 如果ipn监听失败 移动端主动调用服务端捕获captureOrder再处理逻辑
* @author LHL
*/
public String createOrder(String description, String serialNumber, String price, String cancelUrl, String successUrl) {
OrdersCreateRequest request = new OrdersCreateRequest();
request.header("prefer","return=representation");
request.requestBody(buildOrderRequestBody(description, serialNumber, price, cancelUrl, successUrl));
HttpResponse<Order> response = null;
try {
response = client(mode, clientId, clientSecret).execute(request);
} catch (IOException e1) {
try {
log.error("第1次调用paypal订单创建失败: {}", e1.getMessage());
response = client(mode, clientId, clientSecret).execute(request);
} catch (Exception e) {
try {
log.error("第2次调用paypal订单创建失败: {}", e.getMessage());
response = client(mode, clientId, clientSecret).execute(request);
} catch (Exception e2) {
log.error("第3次调用paypal订单创建失败,失败原因:{}", e2.getMessage());
}
}
}
//String approve = cancelUrl;
String orderId = null;
if (response.statusCode() == 201) {
log.info("Status Code = {}, Status = {}, OrderID = {}, Intent = {}", response.statusCode(), response.result().status(), response.result().id(), response.result().checkoutPaymentIntent());
orderId = response.result().id();
//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= null;
try {
json = new JSONObject(new Json().serialize(response.result())).toString(4);
} catch (SerializeException e) {
log.error("json serialize error: {}", e.getMessage());
}
log.info("createOrder response body: {}", json);
return orderId;
}
//return approve;
return orderId;
}
/**
* 查询订单详情
*
* @param orderId 订单id,CreateOrder 生成
* @author LHL
* */
public Map<String, Object> testOrdersGetRequest(String orderId) {
Map<String, Object> map = new HashMap<>(5);
OrdersGetRequest request = new OrdersGetRequest(orderId);
HttpResponse<Order> response = null;
try {
response = client(mode, clientId, clientSecret).execute(request);
} catch (Exception e) {
try {
log.

本文介绍如何使用Java整合PayPal支付功能,包括创建订单、支付捕获、退款操作及支出功能的实现。

6296

被折叠的 条评论
为什么被折叠?



