public static Payment CreatePayment(string baseUrl, string intent)
{
// ### Api Context
// Pass in a `APIContext` object to authenticate
// the call and to send a unique request id
// (that ensures idempotency). The SDK generates
// a request id if you do not pass one explicitly.
var apiContext = PayPalConfiguration.GetAPIContext();
// Payment Resource
var payment = new Payment()
{
intent = intent, // `sale` or `authorize`
payer = new Payer() { payment_method = "paypal" },
transactions = GetTransactionsList(),
redirect_urls = GetReturnUrls(baseUrl, intent)
};
// Create a payment using a valid APIContext
var createdPayment = payment.Create(apiContext);
return createdPayment;
}
private static List<Transaction> GetTransactionsList()
{
// A transaction defines the contract of a payment
// what is the payment for and who is fulfilling it.
var transactionList = new List<Transaction>();
// The Payment creation API requires a list of Transaction;
// add the created Transaction to a List
transactionList.Add(new Transaction()
{
description = "Transaction description.",
invoice_number = GetRandomInvoiceNumber(),
amount = new Amount()
{
currency = "USD",
total = "100.00", // Total must be equal to sum of shipping, tax and subtotal.
details = new Details() // Details: Let's you specify details of a payment amount.
{
tax = "15",
shipping = "10",
subtotal = "75"
}
},
item_list = new ItemList()
{
items = new List<Item>()
{
new Item()
{
name = "Item Name",
currency = "USD",
price = "15",
quantity = "5",
sku = "sku"
}
}
}
});
return transactionList;
}
private static RedirectUrls GetReturnUrls(string baseUrl, string intent)
{
var returnUrl = intent == "sale" ? "/Home/PaymentSuccessful" : "/Home/AuthorizeSuccessful";
// Redirect URLS
// These URLs will determine how the user is redirected from PayPal
// once they have either approved or canceled the payment.
return new RedirectUrls()
{
cancel_url = baseUrl + "/Home/PaymentCancelled",
return_url = baseUrl + returnUrl
};
}
public static Payment ExecutePayment(string paymentId, string payerId)
{
// ### Api Context
// Pass in a `APIContext` object to authenticate
// the call and to send a unique request id
// (that ensures idempotency). The SDK generates
// a request id if you do not pass one explicitly.
var apiContext = PayPalConfiguration.GetAPIContext();
var paymentExecution = new PaymentExecution() { payer_id = payerId };
var payment = new Payment() { id = paymentId };
// Execute the payment.
var executedPayment = payment.Execute(apiContext, paymentExecution);
return executedPayment;
}
public static Capture CapturePayment(string paymentId)
{
var apiContext = PayPalConfiguration.GetAPIContext();
var payment = Payment.Get(apiContext, paymentId);
var auth = payment.transactions[0].related_resources[0].authorization;
// Specify an amount to capture. By setting 'is_final_capture' to true, all remaining funds held by the authorization will be released from the funding instrument.
var capture = new Capture()
{
amount = new Amount()
{
currency = "USD",
total = "4.54"
},
is_final_capture = true
};
// Capture an authorized payment by POSTing to
// URI v1/payments/authorization/{authorization_id}/capture
var responseCapture = auth.Capture(apiContext, capture);
return responseCapture;
}
然後,我在 HomeController 中新增了兩個新操作來顯示此類付款:
public IActionResult AuthorizePayment()
{
var payment = PayPalPaymentService.CreatePayment(GetBaseUrl(), "authorize");
return Redirect(payment.GetApprovalUrl());
}
public IActionResult AuthorizeSuccessful(string paymentId, string token, string PayerID)
{
// Capture Payment
var capture = PayPalPaymentService.CapturePayment(paymentId);
return View();
}
// Define the plan and attach the payment definitions and merchant preferences.
// More Information: https://developer.paypal.com/webapps/developer/docs/api/#create-a-plan
var billingPlan = new Plan
{
name = "Tuts+ Plus",
description = "Monthly plan for courses.",
type = "fixed",
// Define the merchant preferences.
// More Information: https://developer.paypal.com/webapps/developer/docs/api/#merchantpreferences-object
merchant_preferences = new MerchantPreferences()
{
setup_fee = GetCurrency("0"), // $0
return_url = "returnURL", // Retrieve from config
cancel_url = "cancelURL", // Retrieve from config
auto_bill_amount = "YES",
initial_fail_amount_action = "CONTINUE",
max_fail_attempts = "0"
},
payment_definitions = new List<PaymentDefinition>
{
// Define a trial plan that will only charge $9.99 for the first
// month. After that, the standard plan will take over for the
// remaining 11 months of the year.
new PaymentDefinition()
{
name = "Trial Plan",
type = "TRIAL",
frequency = "MONTH",
frequency_interval = "1",
amount = GetCurrency("0"), // Free for the 1st month
cycles = "1",
charge_models = new List<ChargeModel>
{
new ChargeModel()
{
type = "TAX",
amount = GetCurrency("1.65") // If we need to charge Tax
},
new ChargeModel()
{
type = "SHIPPING",
amount = GetCurrency("9.99") // If we need to charge for Shipping
}
}
},
// Define the standard payment plan. It will represent a monthly
// plan for $19.99 USD that charges once month for 11 months.
new PaymentDefinition
{
name = "Standard Plan",
type = "REGULAR",
frequency = "MONTH",
frequency_interval = "1",
amount = GetCurrency("15.00"),
// > NOTE: For `IFNINITE` type plans, `cycles` should be 0 for a `REGULAR` `PaymentDefinition` object.
cycles = "11",
charge_models = new List<ChargeModel>
{
new ChargeModel
{
type = "TAX",
amount = GetCurrency("2.47")
},
new ChargeModel()
{
type = "SHIPPING",
amount = GetCurrency("9.99")
}
}
}
}
};
// Get PayPal Config
var apiContext = PayPalConfiguration.GetAPIContext();
// Create Plan
plan.Create(apiContext);
新创建的结算计划处于 CREATED 状态。将其激活为“活动”状态,以便您的客户可以订阅该计划。要激活该计划,我们需要发出 PATCH 请求:
// Activate the plan
var patchRequest = new PatchRequest()
{
new Patch()
{
op = "replace",
path = "/",
value = new Plan() { state = "ACTIVE" }
}
};
plan.Update(apiContext, patchRequest);
如您所见,PayPal 库是其 REST API 的直接包装器,这很好,但与 Stripe 等其他 API 相比,该 API 也非常复杂。因此,将所有 PayPal 通信包装在对象中,为我们的应用程序提供更清晰、更简单的 API,这确实是一个不错的选择。在这里您可以看到封装在多个带有参数的函数中的代码的样子:
public static Plan CreatePlanObject(string planName, string planDescription, string returnUrl, string cancelUrl,
string frequency, int frequencyInterval, decimal planPrice,
decimal shippingAmount = 0, decimal taxPercentage = 0, bool trial = false, int trialLength = 0, decimal trialPrice = 0)
{
// Define the plan and attach the payment definitions and merchant preferences.
// More Information: https://developer.paypal.com/docs/rest/api/payments.billing-plans/
return new Plan
{
name = planName,
description = planDescription,
type = PlanType.Fixed,
// Define the merchant preferences.
// More Information: https://developer.paypal.com/webapps/developer/docs/api/#merchantpreferences-object
merchant_preferences = new MerchantPreferences()
{
setup_fee = GetCurrency("1"),
return_url = returnUrl,
cancel_url = cancelUrl,
auto_bill_amount = "YES",
initial_fail_amount_action = "CONTINUE",
max_fail_attempts = "0"
},
payment_definitions = GetPaymentDefinitions(trial, trialLength, trialPrice, frequency, frequencyInterval, planPrice, shippingAmount, taxPercentage)
};
}
private static List<PaymentDefinition> GetPaymentDefinitions(bool trial, int trialLength, decimal trialPrice,
string frequency, int frequencyInterval, decimal planPrice, decimal shippingAmount, decimal taxPercentage)
{
var paymentDefinitions = new List<PaymentDefinition>();
if (trial)
{
// Define a trial plan that will charge 'trialPrice' for 'trialLength'
// After that, the standard plan will take over.
paymentDefinitions.Add(
new PaymentDefinition()
{
name = "Trial",
type = "TRIAL",
frequency = frequency,
frequency_interval = frequencyInterval.ToString(),
amount = GetCurrency(trialPrice.ToString()),
cycles = trialLength.ToString(),
charge_models = GetChargeModels(trialPrice, shippingAmount, taxPercentage)
});
}
// Define the standard payment plan. It will represent a 'frequency' (monthly, etc)
// plan for 'planPrice' that charges 'planPrice' (once a month) for #cycles.
var regularPayment = new PaymentDefinition
{
name = "Standard Plan",
type = "REGULAR",
frequency = frequency,
frequency_interval = frequencyInterval.ToString(),
amount = GetCurrency(planPrice.ToString()),
// > NOTE: For `IFNINITE` type plans, `cycles` should be 0 for a `REGULAR` `PaymentDefinition` object.
cycles = "11",
charge_models = GetChargeModels(trialPrice, shippingAmount, taxPercentage)
};
paymentDefinitions.Add(regularPayment);
return paymentDefinitions;
}
private static List<ChargeModel> GetChargeModels(decimal planPrice, decimal shippingAmount, decimal taxPercentage)
{
// Create the Billing Plan
var chargeModels = new List<ChargeModel>();
if (shippingAmount > 0)
{
chargeModels.Add(new ChargeModel()
{
type = "SHIPPING",
amount = GetCurrency(shippingAmount.ToString())
});
}
if (taxPercentage > 0)
{
chargeModels.Add(new ChargeModel()
{
type = "TAX",
amount = GetCurrency(String.Format("{0:f2}", planPrice * taxPercentage / 100))
});
}
return chargeModels;
}
更新结算计划
您可以通过提出“PATCH”请求来更新现有结算方案的信息。这是一个包装该调用的函数:
public static void UpdateBillingPlan(string planId, string path, object value)
{
// PayPal Authentication tokens
var apiContext = PayPalConfiguration.GetAPIContext();
// Retrieve Plan
var plan = Plan.Get(apiContext, planId);
// Activate the plan
var patchRequest = new PatchRequest()
{
new Patch()
{
op = "replace",
path = path,
value = value
}
};
plan.Update(apiContext, patchRequest);
}
要更新计费计划描述,我们可以调用此函数并传递正确的参数:
UpdateBillingPlan(
planId: "P-5FY40070P6526045UHFWUVEI",
path: "/",
value: new Plan { description = "new description" });
public static void ExecuteBillingAgreement(string token)
{
// PayPal Authentication tokens
var apiContext = PayPalConfiguration.GetAPIContext();
var agreement = new Agreement() { token = token };
var executedAgreement = agreement.Execute(apiContext);
}
暂停计费协议
使用此方法暂停协议:
public static void SuspendBillingAgreement(string agreementId)
{
var apiContext = PayPalConfiguration.GetAPIContext();
var agreement = new Agreement() { id = agreementId };
agreement.Suspend(apiContext, new AgreementStateDescriptor()
{ note = "Suspending the agreement" });
}
重新激活计费协议
这个与上一个非常相似:
public static void ReactivateBillingAgreement(string agreementId)
{
var apiContext = PayPalConfiguration.GetAPIContext();
var agreement = new Agreement() { id = agreementId };
agreement.ReActivate(apiContext, new AgreementStateDescriptor()
{ note = "Reactivating the agreement" });
}
取消计费协议
使用此功能取消计划:
public static void CancelBillingAgreement(string agreementId)
{
var apiContext = PayPalConfiguration.GetAPIContext();
var agreement = new Agreement() { id = agreementId };
agreement.Cancel(apiContext, new AgreementStateDescriptor()
{ note = "Cancelling the agreement" });
}