Java通過(guò)授權(quán)方式實(shí)現(xiàn)paypal支付的全流程

前言

paypal是目前全球最大的在線支付工具烈涮,就像國(guó)內(nèi)的支付寶一樣伶授,是一個(gè)基于買賣雙方的第三方支付平臺(tái)寿烟。在集成paypal支付接口之前扑毡,首先要有一系列的準(zhǔn)備航夺,開(kāi)發(fā)者賬號(hào)啊身坐、sdk彬檀、測(cè)試環(huán)境等等先要有簇秒,然后再碼代碼。

一擒悬、環(huán)境準(zhǔn)備

  • 注冊(cè)paypal賬號(hào)
  • 注冊(cè)paypal開(kāi)發(fā)者賬號(hào)
  • 創(chuàng)建兩個(gè)測(cè)試用戶
  • 創(chuàng)建應(yīng)用模她,生成用于測(cè)試的clientID 和 密鑰

二、代碼集成

  • pom引進(jìn)checkout-sdk的jar包
  • 碼代碼
  • 后言

注冊(cè)paypal賬號(hào)

(1)在瀏覽器輸入“https://www.paypal.com” 跳轉(zhuǎn)到如下界面懂牧,點(diǎn)擊右上角的注冊(cè)

image.png

(2)選擇侈净,”創(chuàng)建商家用戶”,根據(jù)要求填寫(xiě)信息僧凤,一分鐘的事畜侦,注冊(cè)完得去郵箱激活
image.png

注冊(cè)paypal開(kāi)發(fā)者賬號(hào)

(1)在瀏覽器輸入“https://developer.paypal.com”,點(diǎn)擊右上角的“Log into Dashboard”躯保,用上一步創(chuàng)建好的賬號(hào)登錄

image.png

創(chuàng)建兩個(gè)測(cè)試用戶

(1)登錄成功后旋膳,在左邊的導(dǎo)航欄中點(diǎn)擊 Sandbox 下的 Accounts
image.png

(2)進(jìn)入Acccouts界面后,可以看到系統(tǒng)有兩個(gè)已經(jīng)生成好的測(cè)試賬號(hào)途事,但是我們不要用系統(tǒng)給的測(cè)試賬號(hào)验懊,很卡的,自己創(chuàng)建兩個(gè)
image.png

(3)點(diǎn)擊右上角的“Create Account”尸变,創(chuàng)建測(cè)試用戶

<1> 先創(chuàng)建一個(gè)“ PERSONAL”類型的用戶义图,國(guó)家一定要選“China”,賬戶余額默認(rèn)5000.00 USD

image.png

<2> 接著創(chuàng)建一個(gè)“BUSINESS”類型的用戶召烂,同上
<3>創(chuàng)建好之后可以點(diǎn)擊測(cè)試賬號(hào)下的”View/edit_account“歌溉,可以查看信息,包括用戶的登錄賬號(hào)和密碼及余額骑晶,如果沒(méi)加載出來(lái)痛垛,刷新
image.png

<4>用測(cè)試賬號(hào)(上一步中查看)登錄測(cè)試網(wǎng)站查看,注意桶蛔!這跟paypal官網(wǎng)不同匙头!不是同一個(gè)地址,在瀏覽器輸入:https://www.sandbox.paypal.com 在這里登陸測(cè)試賬戶
image.png

創(chuàng)建應(yīng)用仔雷,生成用于測(cè)試的clientID和密鑰

(1)點(diǎn)擊左邊導(dǎo)航欄Dashboard下的My Apps & Credentials蹂析,創(chuàng)建一個(gè)App,這是我創(chuàng)建好的“Test”App
image.png

(3)點(diǎn)擊剛剛創(chuàng)建好的App“Test”,注意看到”ClientID“ 和”Secret“(Secret如果沒(méi)顯示碟婆,點(diǎn)擊下面的show就會(huì)看到电抚,點(diǎn)擊后show變?yōu)閔ide)
image.png

pom引進(jìn)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用于調(diào)用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;
    }
}
創(chuàng)建訂單,將訂單信息展示在paypal頁(yè)面上
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: ");
                /**
                 * 用戶通過(guò)approve: https://www.sandbox.paypal.com/checkoutnow?token=8GR24834939276359
                 * 認(rèn)證訂單
                 */
                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");

        /**
         * 用戶認(rèn)證完成后竖共,paypal會(huì)通過(guò)returnUrl通知get方式我們
         * 在我們的returnUrl后拼接參數(shù)蝙叛,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();
        }
    }
}
給訂單授權(quán)
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();
        }
    }
}
確認(rèn)收款
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>測(cè)試成功后到https://www.sandbox.paypal.com 登錄測(cè)試賬號(hào)看看余額有沒(méi)有變化
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市公给,隨后出現(xiàn)的幾起案子借帘,更是在濱河造成了極大的恐慌蜘渣,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肺然,死亡現(xiàn)場(chǎng)離奇詭異蔫缸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)际起,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)拾碌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人街望,你說(shuō)我怎么就攤上這事倦沧。” “怎么了它匕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵展融,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我豫柬,道長(zhǎng)告希,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任烧给,我火速辦了婚禮燕偶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘础嫡。我一直安慰自己指么,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布榴鼎。 她就那樣靜靜地躺著伯诬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巫财。 梳的紋絲不亂的頭發(fā)上盗似,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音平项,去河邊找鬼赫舒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛闽瓢,可吹牛的內(nèi)容都是我干的接癌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扣讼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼缺猛!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤枯夜,失蹤者是張志新(化名)和其女友劉穎弯汰,沒(méi)想到半個(gè)月后艰山,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體湖雹,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年曙搬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摔吏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纵装,死狀恐怖征讲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情橡娄,我是刑警寧澤诗箍,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站挽唉,受9級(jí)特大地震影響滤祖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜瓶籽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一匠童、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧塑顺,春花似錦汤求、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至裤唠,卻和暖如春勒奇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背巧骚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工赊颠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人劈彪。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓竣蹦,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親沧奴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子痘括,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容