Java通过授权方式实现paypal支付的全流程

前言

paypal是目前全球最大的在线支付工具,就像国内的支付宝一样,是一个基于买卖双方的第三方支付平台。在集成paypal支付接口之前,首先要有一系列的准备,开发者账号啊、sdk、测试环境等等先要有,然后再码代码。

一、环境准备

  • 注册paypal账号
  • 注册paypal开发者账号
  • 创建两个测试用户
  • 创建应用,生成用于测试的clientID 和 密钥

二、代码集成

  • pom引进checkout-sdk的jar包
  • 码代码
  • 后言

注册paypal账号

(1)在浏览器输入“https://www.paypal.com” 跳转到如下界面,点击右上角的注册

image.png

(2)选择,”创建商家用户”,根据要求填写信息,一分钟的事,注册完得去邮箱激活
image.png

注册paypal开发者账号

(1)在浏览器输入“https://developer.paypal.com”,点击右上角的“Log into Dashboard”,用上一步创建好的账号登录

image.png

创建两个测试用户

(1)登录成功后,在左边的导航栏中点击 Sandbox 下的 Accounts
image.png

(2)进入Acccouts界面后,可以看到系统有两个已经生成好的测试账号,但是我们不要用系统给的测试账号,很卡的,自己创建两个
image.png

(3)点击右上角的“Create Account”,创建测试用户

<1> 先创建一个“ PERSONAL”类型的用户,国家一定要选“China”,账户余额默认5000.00 USD

image.png

<2> 接着创建一个“BUSINESS”类型的用户,同上
<3>创建好之后可以点击测试账号下的”View/edit_account“,可以查看信息,包括用户的登录账号和密码及余额,如果没加载出来,刷新
image.png

<4>用测试账号(上一步中查看)登录测试网站查看,注意!这跟paypal官网不同!不是同一个地址,在浏览器输入:https://www.sandbox.paypal.com 在这里登陆测试账户
image.png

创建应用,生成用于测试的clientID和密钥

(1)点击左边导航栏Dashboard下的My Apps & Credentials,创建一个App,这是我创建好的“Test”App
image.png

(3)点击刚刚创建好的App“Test”,注意看到”ClientID“ 和”Secret“(Secret如果没显示,点击下面的show就会看到,点击后show变为hide)
image.png

pom引进checkout-sdk的jar包

        <dependency>
            <groupId>com.paypal.sdk</groupId>
            <artifactId>checkout-sdk</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20180813</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.6</version>
        </dependency>

码代码

PayPalClient用于调用PayPal api
import com.paypal.core.PayPalEnvironment;
import com.paypal.core.PayPalHttpClient;

public class PayPalClient {

    /**
     *Set up the PayPal Java SDK environment with PayPal access credentials.
     *This sample uses SandboxEnvironment. In production, use LiveEnvironment.
     */
    private PayPalEnvironment environment = new PayPalEnvironment.Sandbox(
            "<<PAYPAL-CLIENT-ID>>",
            "<<PAYPAL-CLIENT-SECRET>>");

    /**
     *PayPal HTTP client instance with environment that has access
     *credentials context. Use to invoke PayPal APIs.
     */
    PayPalHttpClient client = new PayPalHttpClient(environment);

    /**
     *Method to get client object
     *
     *@return PayPalHttpClient client
     */
    public PayPalHttpClient client() {
        return this.client;
    }
}
创建订单,将订单信息展示在paypal页面上
import com.paypal.http.HttpResponse;
import com.paypal.http.exceptions.HttpException;
import com.paypal.orders.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
*1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.
*This step extends the SDK client. It's not mandatory to extend the client, you can also inject it.
*/
public class CreateOrder extends PayPalClient {

    //2. Set up your server to receive a call from the client
    /**
     *Method to create order
     *
     *@param debug true = print response data
     *@return HttpResponse<Order> response received from API
     *@throws IOException Exceptions from API if any
     */
    public HttpResponse<Order> createOrder(boolean debug) throws IOException {
        OrdersCreateRequest request = new OrdersCreateRequest();
        request.prefer("return=representation");
        request.requestBody(buildRequestBody());
        //3. Call PayPal to set up a transaction
        HttpResponse<Order> response = client().execute(request);
        if (debug) {
            if (response.statusCode() == 201) {
                System.out.println("Status Code: " + response.statusCode());
                System.out.println("Status: " + response.result().status());
                System.out.println("Order ID: " + response.result().id());
                System.out.println("Intent: " + response.result().checkoutPaymentIntent());
                System.out.println("Links: ");
                /**
                 * 用户通过approve: https://www.sandbox.paypal.com/checkoutnow?token=8GR24834939276359
                 * 认证订单
                 */
                for (LinkDescription link : response.result().links()) {
                    System.out.println("\t" + link.rel() + ": " + link.href() + "\tCall Type: " + link.method());
                }
                System.out.println("Total Amount: " + response.result().purchaseUnits().get(0).amountWithBreakdown().currencyCode()
                        + " " + response.result().purchaseUnits().get(0).amountWithBreakdown().value());
            }
        }
        return response;
    }

    /**
     *Method to generate sample create order body with AUTHORIZE intent
     *
     *@return OrderRequest with created order request
     */
    private OrderRequest buildRequestBody() {
        OrderRequest orderRequest = new OrderRequest();
        orderRequest.checkoutPaymentIntent("AUTHORIZE");

        /**
         * 用户认证完成后,paypal会通过returnUrl通知get方式我们
         * 在我们的returnUrl后拼接参数,token及orderId
         * 示例:https://www.example.com/?token=8GR24834939276359&PayerID=V97XV4A6DQ52N
         */
        ApplicationContext applicationContext = new ApplicationContext().brandName("EXAMPLE INC").landingPage("BILLING")
                .cancelUrl("https://www.example.com").returnUrl("https://www.example.com").userAction("CONTINUE")
                .shippingPreference("SET_PROVIDED_ADDRESS");
        orderRequest.applicationContext(applicationContext);
        
        /**
         * 绑定订单信息
         */
        List<PurchaseUnitRequest> purchaseUnitRequests = new ArrayList<>();
        PurchaseUnitRequest purchaseUnitRequest = new PurchaseUnitRequest().referenceId("PUHF")
                .description("Sporting Goods").customId("CUST-HighFashions").softDescriptor("HighFashions")
                .amountWithBreakdown(new AmountWithBreakdown().currencyCode("USD").value("220.00")
                        .amountBreakdown(new AmountBreakdown().itemTotal(new Money().currencyCode("USD").value("180.00"))
                                .shipping(new Money().currencyCode("USD").value("20.00"))
                                .handling(new Money().currencyCode("USD").value("10.00"))
                                .taxTotal(new Money().currencyCode("USD").value("20.00"))
                                .shippingDiscount(new Money().currencyCode("USD").value("10.00"))))
                .items(new ArrayList<Item>() {
                    {
                        add(new Item().name("T-shirt").description("Green XL").sku("sku01")
                                .unitAmount(new Money().currencyCode("USD").value("90.00"))
                                .tax(new Money().currencyCode("USD").value("10.00")).quantity("1")
                                .category("PHYSICAL_GOODS"));
                        add(new Item().name("Shoes").description("Running, Size 10.5").sku("sku02")
                                .unitAmount(new Money().currencyCode("USD").value("45.00"))
                                .tax(new Money().currencyCode("USD").value("5.00")).quantity("2")
                                .category("PHYSICAL_GOODS"));
                    }
                })
                .shippingDetail(new ShippingDetail().name(new Name().fullName("John Doe"))
                        .addressPortable(new AddressPortable().addressLine1("123 Townsend St").addressLine2("Floor 6")
                                .adminArea2("San Francisco").adminArea1("CA").postalCode("94107").countryCode("US")));
        purchaseUnitRequests.add(purchaseUnitRequest);
        orderRequest.purchaseUnits(purchaseUnitRequests);
        return orderRequest;
    }

    /**
     *This driver function invokes the createOrder function to create
     *a sample order.
     */
    public static void main(String args[]) {
        try {
            new CreateOrder().createOrder(true);
        } catch (HttpException e) {
            System.out.println(e.getLocalizedMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
给订单授权
import com.paypal.http.HttpResponse;
import com.paypal.http.serializer.Json;
import com.paypal.orders.LinkDescription;
import com.paypal.orders.Order;
import com.paypal.orders.OrderActionRequest;
import com.paypal.orders.OrdersAuthorizeRequest;
import org.json.JSONObject;

import java.io.IOException;

/**
*1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.
*This step extends the SDK client. It's not mandatory to extend the client, you can also inject it.
*/
public class AuthorizeOrder extends PayPalClient {

    //2. Set up your server to receive a call from the client
    /**
     *Method to authorize order after creation
     *
     *@param orderId Valid Approved Order ID from createOrder response
     *@param debug   true = print response data
     *@return HttpResponse<Order> response received from API
     *@throws IOException Exceptions from API if any
     */
    public HttpResponse<Order> authorizeOrder(String orderId, boolean debug) throws IOException {
        OrdersAuthorizeRequest request = new OrdersAuthorizeRequest(orderId);
        request.requestBody(buildRequestBody());
        // 3. Call PayPal to authorization an order
        HttpResponse<Order> response = client().execute(request);
        // 4. Save the authorization ID to your database. Implement logic to save the authorization to your database for future reference.
        if (debug) {
            System.out.println("Authorization Ids:");
            response.result().purchaseUnits()
                    .forEach(purchaseUnit -> purchaseUnit.payments()
                            .authorizations().stream()
                            .map(authorization -> authorization.id())
                            .forEach(System.out::println));
            System.out.println("Link Descriptions: ");
            for (LinkDescription link : response.result().links()) {
                System.out.println("\t" + link.rel() + ": " + link.href());
            }
            System.out.println("Full response body:");
            System.out.println(new JSONObject(new Json().serialize(response.result())).toString(4));
        }
        return response;
    }

    /**
     *Building empty request body.
     *
     *@return OrderActionRequest with empty body
     */
    private OrderActionRequest buildRequestBody() {
        return new OrderActionRequest();
    }

    /**
     *This driver function invokes the authorizeOrder function to
     *create a sample order.
     *
     *@param args
     */
    public static void main(String[] args) {
        try {
            new AuthorizeOrder().authorizeOrder("8GR24834939276359", true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
确认收款
import com.paypal.http.HttpResponse;
import com.paypal.http.serializer.Json;
import com.paypal.orders.OrderRequest;
import com.paypal.payments.AuthorizationsCaptureRequest;
import com.paypal.payments.Capture;
import com.paypal.payments.LinkDescription;
import org.json.JSONObject;

import java.io.IOException;

/**
*1. Import the PayPal SDK client that was created in `Set up Server-Side SDK`.
*This step extends the SDK client. It's not mandatory to extend the client, you can also inject it.
*/
public class CaptureAuthorization extends PayPalClient {

    //2. Set up your server to receive a call from the client
    /**
     *Method to capture order after authorization
     *
     *@param authId Authorization ID from authorizeOrder response
     *@param debug  true = print response data
     *@return HttpResponse<Capture> response received from API
     *@throws IOException Exceptions from API if any
     */
    public HttpResponse<Capture> captureAuth(String authId, boolean debug) throws IOException {
        AuthorizationsCaptureRequest request = new AuthorizationsCaptureRequest(authId);
        request.requestBody(buildRequestBody());
        //3. Call PayPal to capture an authorization.
        HttpResponse<Capture> response = client().execute(request);
        //4. Save the capture ID to your database for future reference.
        if (debug) {
            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Status: " + response.result().status());
            System.out.println("Capture ID: " + response.result().id());
            System.out.println("Links: ");
            for (LinkDescription link : response.result().links()) {
                System.out.println("\t" + link.rel() + ": " + link.href() + "\tCall Type: " + link.method());
            }
            System.out.println("Full response body:");
            System.out.println(new JSONObject(new Json()
                    .serialize(response.result())).toString(4));
        }
        return response;
    }

    /**
     *Create an empty body for capture request
     *
     *@return OrderRequest request with empty body
     */
    public OrderRequest buildRequestBody() {
        return new OrderRequest();
    }

    /**
     *This function uses the captureOrder function to
     *capture an authorization. Replace the authorization ID with
     *the valid authorization ID.
     *
     *@param args
     */
    public static void main(String[] args) {
        try {
            new CaptureAuthorization().captureAuth("5J830046T71392507", true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

后言

<1>整体流程图
整体流程图.png
<2>测试成功后到https://www.sandbox.paypal.com 登录测试账号看看余额有没有变化
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容