2011/10/20 11:28 | 閱讀數 : 6355 我要推薦 | Add Comment | 文章分類 : ASP.NET C# PayPal 訂閱

 

PayPal Express Checkout 主要分成三個步驟:

  1. SetExpressCheckout[設定收款金額與明細]
  2. GetExpressCheckoutDetails [取得顧客資料]
  3. DoExpressCheckoutPayment [扣款]

把 2 跟 3 合在一起也可以,在 GetExpressCheckoutDetails 在顯示訂單內容,讓消費者確認後按下Submit
再把原本 DoExpressCheckoutPayment  要執行的動作直接在 GetExpressCheckoutDetails  執行

 

Cart.aspx

void Submit_Click(object sender, ImageClickEventArgs e)
{
    ...
    //將頁面導向SetExpressCheckout
    Response.Redirect("/PayPal/SetExpressCheckout.aspx?paymentType=Sale&oid=" + OrderID);
    ...
}

 

Step1. SetExpressCheckout
Redirect 到 SetExpressCheckout.aspx 就可以開始設定參數
必須傳遞的參數:
USER: API 用戶名稱
PWD: API 密碼
SIGNATURE: 簽名
METHOD: SetExpressCheckout
RETURNURL:當於PayPal 網站完成明細確認後,瀏覽器將帶顧客返回至此網址。
CANCELURL:當顧客選擇終止付款時,瀏覽器將帶顧客返回至此網址。
AMT:交易金額。基本格式為 00.00
 
回傳結果:
ACK:SetExpressCheckout 執行結果。
   *成功的回覆內容為Success、SuccessWithWarning
   *失敗的回覆內容為Failure、FailureWithWarning、 Warning
Token:PayPal 針對這筆交易給你的暫時性鑰匙,此筆交易接下來的所有溝通都必須夾帶此Token
 
官方說明書提到 VERSION 是必須的參數,不過有設跟沒設沒啥感覺,所以我也沒設
如果要在PayPal顯示購買個商品,就必須傳遞 L_NAMEnL_NUMBERnL_DESCnL_AMTnL_QTYn,這五個參數
另外,我在其他說明中有看到
L_PAYMENTREQUEST_m_NAMEn
L_PAYMENTREQUEST_m_NUMBERn
L_PAYMENTREQUEST_m_DESCn
L_PAYMENTREQUEST_m_AMTn
L_PAYMENTREQUEST_m_QTYn
還註明 L_NAMEn ...等參數名稱在 v.63.0 已經廢除
結果根本不用管什麼 VERSION ,L_NAMEn ...等參數也照樣可以用
可能沒看清楚吧,有空再摸
 
PayPal API 可以到這裡下載
 

SetExpressCheckout.aspx

using com.paypal.sdk.services;
using com.paypal.sdk.profiles;
using com.paypal.sdk.util;
using log4net;

public partial class PayPal_SetExpressCheckout : System.Web.UI.Page
{
    protected void Page_Init(object sender, EventArgs e)
    {
        string RETURNURL = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + ResolveUrl("GetExpressCheckoutDetails.aspx") + "?oid=" + oid;
        string CANCELURL = Request.Url.Scheme + "://" + Request.Url.Host + ":" + Request.Url.Port + ResolveUrl("CancelPay.aspx") + "?oid=" + oid;

        NVPCallerServices caller = new NVPCallerServices();
        IAPIProfile profile = ProfileFactory.createSignatureAPIProfile();
        profile.APIUsername = SetAPI.GetAPI("APIUsername");
        profile.APIPassword = SetAPI.GetAPI("APIPassword");
        profile.APISignature = SetAPI.GetAPI("APISignature");
        profile.Environment = SetAPI.GetAPI("Environment");
        caller.APIProfile = profile;

        NVPCodec encoder = new NVPCodec();
        encoder["METHOD"] = "SetExpressCheckout";
        encoder["CANCELURL"] = CANCELURL;
        encoder["RETURNURL"] = RETURNURL;
        encoder["PAYMENTACTION"] = "Sale";
        encoder["CURRENCYCODE"] = "USD";

        //encoder["NAME"] = Request.QueryString["NAME"];
        encoder["SHIPTONAME"] = name;
        encoder["SHIPTOSTREET"] = street;
        //encoder["SHIPTOSTREET2"] = "";
        encoder["SHIPTOCITY"] = city;
        encoder["SHIPTOSTATE"] = state;
        encoder["SHIPTOCOUNTRYCODE"] = module.GetISO3166(country_code);
        encoder["SHIPTOZIP"] = zip;
        encoder["PHONENUM"] = mobile;
        encoder["ADDROVERRIDE"] = "0"; //地址改寫

        double itemAmount = 0.00, shippingAmount = 0.00, shippingDiscAmount = 0.00, taxAmount = 0.00, insuranceAmount = 0.00, amount = 0.00, maxAmount = 0.00;
        for (int i = 0; i < ProductIDList.Count; ++i)
        {
            itemAmount += (Convert.ToDouble(ProductPriceList[i]) * Convert.ToDouble(ProductQtyList[i]));
            encoder["L_NAME" + i] = ProductNameList[i].ToString();
            encoder["L_NUMBER" + i] = ProductIDList[i].ToString();
            encoder["L_DESC" + i] = ProductSizeList[i].ToString();
            encoder["L_AMT" + i] = System.Math.Round(Convert.ToDouble(ProductPriceList[i]), 2).ToString();
            encoder["L_QTY" + i] = ProductQtyList[i].ToString();
        }
        amount = System.Math.Round(itemAmount + shippingAmount + shippingDiscAmount + taxAmount + insuranceAmount, 2);
        maxAmount = System.Math.Round(amount + 25.00f, 2);

        encoder["L_ITEMWEIGHTVALUE1"] = "0.5";
        encoder["L_ITEMWEIGHTUNIT1"] = "lbs";

        encoder["INVNUM"] = oid.ToString(); //order_id
        encoder["ITEMAMT"] = itemAmount.ToString();  // add up all line amount, L_AMTns 
        encoder["TAXAMT"] = taxAmount.ToString();
        encoder["SHIPDISCAMT"] = shippingDiscAmount.ToString(); //運費折扣
        encoder["SHIPPINGAMT"] = shippingAmount.ToString(); //運費
        encoder["AMT"] = amount.ToString(); //amount = itemAmount + shippingAmount + shippingDiscAmount + taxAmount + insuranceAmount(保險費用);
        encoder["MAXAMT"] = maxAmount.ToString();
        encoder["CALLBACK"] = "https://www.ppcallback.com/callback.pl";
        encoder["INSURANCEOPTIONOFFERED"] = "true";
        encoder["INSURANCEAMT"] = insuranceAmount.ToString(); //保險費用

        //運費設定
        encoder["L_SHIPPINGOPTIONISDEFAULT0"] = "true";
        encoder["L_SHIPPINGOPTIONNAME0"] = "Post office (Air+Ground)";
        encoder["L_SHIPPINGOPTIONLABEL0"] = "Post office 14~35 days";
        encoder["L_SHIPPINGOPTIONAMOUNT0"] = shippingAmount.ToString();

        encoder["CALLBACKTIMEOUT"] = "4"; //設置回傳的時間(秒),預設3,範圍: 1~6

        string pStrrequestforNvp = encoder.Encode();
        string pStresponsenvp = caller.Call(pStrrequestforNvp);

        NVPCodec decoder = new NVPCodec();
        decoder.Decode(pStresponsenvp);

        string ACK = decoder["ACK"];

        if (ACK != null && (ACK == "Success" || ACK == "SuccessWithWarning"))
        {
            Session["Token"] = decoder["Token"];
            Session["AMT"] = amount.ToString();
            string host = "www." + SetAPI.GetAPI("Environment") + ".paypal.com";
            string ECURL = "https://" + host + "/cgi-bin/webscr?cmd=_express-checkout" + "&token=" + decoder["TOKEN"];
            Response.Redirect(ECURL);
        }
        else
        {
            Session["errorresult"] = decoder;
            string pStrResQue = "API=" + "Error Detail ";
            Response.Redirect("APIError.aspx?" + pStrResQue);
        }
    }
}

 

 

Step2. GetExpressCheckoutDetails
消費者從 PayPal 登入PayPal帳號並且同意付款時,就會將頁面導向剛才設定的 RETURNURL
然後在 GetExpressCheckoutDetails 顯示訂單的相關明細,並讓消費者同意付款後送到 DoExpressCheckoutPayment
基本上是這樣,不過我把 GetExpressCheckoutDetails  跟 DoExpressCheckoutPayment 合在一起做了
所以只有 GetExpressCheckoutDetails.aspx 一個頁面
 
GetExpressCheckoutDetails 必須傳遞的參數:
Method:GetExpressCheckoutDetails
Token: 你在 SetExpressCheckout 執行時取得的 Token
GetExpressCheckoutDetails 回傳結果:
EMAIL:付款人的電子郵件
PAYERID:唯一的客戶帳戶識別號
PAYERSTATUS:付款人認證狀態, verified/unverified,若為Verified 則代表顧客至少完成了信用卡認證或銀行認證。
SALUTATION:付款人稱呼
FIRSTNAME、MIDDLENAME、LASTNAME:付款人姓名
COUNTRYCODE:付款人所在的地區
BUSINESS:付款人公司名稱
 
DoExpressCheckoutPayment  必須傳遞的參數:
METHOD:DoExpressCheckoutPayment
TOKEN:你在SetExpressCheckout 執行時取得的TOKEN。
PAYERID:唯一的客戶帳戶識別號 (顧客在 PayPal 頁面確認完畢後,PayPal 會將顧客導回你指定頁面時,同時取得Payer ID) 。
AMT:訂單金額總計,包含運費、手續費與稅金。
DoExpressCheckoutPayment  回傳結果:
TRANSACTIONID:付款交易序號。建議你將此序號儲存至資料庫中。
PAYMENTTYPE:交易的類型,內容為即時入帳或是延遲付款
ORDERTIME:付款日期
AMT:付款總額
CURRENCYCODE:貨幣代號,通常為三個英文字組合.如USD (美元),TWD (台幣)
回傳結果有很多參數可以用,可以參考這裡

GetExpressCheckoutDetails.aspx

using com.paypal.sdk.services;
using com.paypal.sdk.profiles;
using com.paypal.sdk.util;
using log4net;

public partial class PayPal_GetExpressCheckoutDetails : System.Web.UI.Page
{
    public string output = "";
    protected void Page_Load(object sender, EventArgs e)
    {
        ....
        NVPCallerServices caller = new NVPCallerServices();
        IAPIProfile profile = ProfileFactory.createSignatureAPIProfile();
        profile.APIUsername = SetAPI.GetAPI("APIUsername");
        profile.APIPassword = SetAPI.GetAPI("APIPassword");
        profile.APISignature = SetAPI.GetAPI("APISignature");
        profile.Environment = SetAPI.GetAPI("Environment");
        caller.APIProfile = profile;

        NVPCodec encoder = new NVPCodec();
        encoder["METHOD"] = "GetExpressCheckoutDetails";
        encoder["TOKEN"] = Session["Token"].ToString();

        string pStrrequestforNvp = encoder.Encode();
        string pStresponsenvp = caller.Call(pStrrequestforNvp);

        NVPCodec decoder = new NVPCodec();
        decoder.Decode(pStresponsenvp);

        string strAck = decoder["ACK"];
        if (strAck != null && (strAck == "Success" || strAck == "SuccessWithWarning"))
        {
            Session["PAYERID"] = decoder["PAYERID"];
            //Success 時在這裡顯示所購買的明細等訊息給消費者確認,確認後才從 Click 送出並扣款
        }
        else
        {
            output = "Error!";
            //失敗時顯示錯誤訊息
        }
    }


    void Pay_Click(object sender, ImageClickEventArgs e)
    {
        NVPCallerServices caller = new NVPCallerServices();
        IAPIProfile profile = ProfileFactory.createSignatureAPIProfile();
        profile.APIUsername = SetAPI.GetAPI("APIUsername");
        profile.APIPassword = SetAPI.GetAPI("APIPassword");
        profile.APISignature = SetAPI.GetAPI("APISignature");
        profile.Environment = SetAPI.GetAPI("Environment");
        caller.APIProfile = profile;

        NVPCodec encoder = new NVPCodec();
        encoder["METHOD"] = "DoExpressCheckoutPayment";
        encoder["TOKEN"] = Session["Token"].ToString();
        encoder["PAYERID"] = Session["PAYERID"].ToString();
        encoder["AMT"] = Session["AMT"].ToString();
        encoder["PAYMENTACTION"] = "Sale";
        encoder["CURRENCYCODE"] = "USD";

        string pStrrequestforNvp = encoder.Encode();
        string pStresponsenvp = caller.Call(pStrrequestforNvp);

        NVPCodec decoder = new NVPCodec();
        decoder.Decode(pStresponsenvp);

        string strAck = decoder["ACK"];
        if (strAck != null && (strAck == "Success" || strAck == "SuccessWithWarning"))
        {
             //把該存入資料庫的訊息存進資料庫
             //也可以順便顯示付款成功的訊息,告訴消費者付款成功,可以返回首頁
        }
        else
        {
            //顯示錯誤訊息
        }
    }
}

裏頭的 SetAPI 是 SetAPI.cs,自己用來設定 API 憑證內容。

 

相關參考

產品整合資源中心
https://www.paypal-apac.com/tw/products/integration-resources.aspx?lng=zh_TW&tab=3694

PayPal 集成資源
http://paypal.ebay.cn/integrationcenter/list_resource.html
https://www.paypal-biz.com/developer/internet/ec/

SDKs and Downloads
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/library_download_sdks#NVP

API Error Codes
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_errorcodes

其他參考
http://www.kaiyuanba.cn/html/1/131/227/4496.htm
http://hoamon.blogspot.com/2011/01/paypal-express-checkout.html
http://zh.wikipedia.org/wiki/ISO_3166-1


回應

    目前沒有回應.
登入後使用進階評論
Please add 8 and 4 and type the answer here: