Braintree-国外支付对接(二)

article/2025/8/22 23:25:37

在前文 国外支付对接:Braintree(一)的基础上   已经拿到了相关配置信息,接下来就是码代码了,这里完成的主要功能是支付与退款。

在此之前,先说一下Briantree的支付流程:

    第一步先生成clientToken,一组根据 MerchantId,BraintreePublicKey,BraintreePrivateKey生成的字符串,用于前端生成初始化支付控件。第二步点击支付按钮客户输入用户名密码确定支付之后,Briantree在前端会返回nonce给我们(相当于支付授权凭证)。第三步,将nonce传到后台,我们进行扣款。至此支付完成。

1.项目引用

  •    后端

 从官方下载的demo中可以看到,其实我们的后端需要用的dll就是一个:Braintree.dll,NUGET上也能下载

  

  •   前端

     需要的就是引用官方js,这个需要看个人需求吧,如果你不想麻烦自己写样式,可以直接使用官方的js生成的支付按钮,那么用drop-in UI即可。使用drop-in是最直接便利的方式,我们在前端直接引用:

<script src="https://js.braintreegateway.com/web/dropin/1.9.2/js/dropin.min.js"></script>

 生成的样式长这样:

     如果需要自己设计样式,按照自己的规则来控制前端的话,那就得使用Customer UI。那当然需要引用的js就不同了,前端的写法也就不同了,后面细说。这块主要的js是

<script src="https://js.braintreegateway.com/web/3.29.0/js/client.min.js"></script>

2.代码解析

  •  web.config配置

        API keys 拿到之后需要在程序中使用,我们直接配置在web.config中即可,当然安全着想也可以加密配置到数据库中。

       

  •    前端(这里先介绍使用drop-in UI的写法)

 html:
   form只需要2个参数amount,nonce。最重要的是要定义一个div控件给生成支付控件使用,这里使用的id为bt-dropin的div

<form id="payment-form" method="post" action="/checkouts/Create"><section><label for="amount"><span class="input-label">Amount</span><div class="input-wrapper amount-wrapper"><input id="amount" name="amount" type="tel" min="0.01" placeholder="Amount" value="0.01"></div></label><div class="bt-drop-in-wrapper"><div id="bt-dropin"></div></div></section><input id="nonce" name="payment_method_nonce" type="hidden" /><button class="button"  type="submit"><span>Test Transaction</span></button></form>

js:

<script src="https://js.braintreegateway.com/web/dropin/1.9.2/js/dropin.min.js"></script>
<script>$(function () {var client_token = "@ViewBag.ClientToken";var form = document.querySelector('#payment-form');braintree.dropin.create({//支付控件初始化开始authorization: client_token,//由后端传过来的值,一组根据 MerchantId,BraintreePublicKey,BraintreePrivateKey生成的字符串container: '#bt-dropin',paypal: {flow: 'vault',buttonStyle: {  //可以修改一点点按钮的样式,限制性很多color: 'black',shape: 'rect',size: 'medium'}},//此处与上面的paypal设置不一样,亲么可以自己去尝试一下,不同点在哪//paypal: {//    flow: 'checkout',//    amount: document.querySelector('#amount').value,//    currency: 'USD'//}, card: {//此项选填,干掉也没关系cardholderName: { required: true }, //必填的话,就会多生成一个持卡人姓名的输入框overrides: {fields: {number: {placeholder: 'Card Number',},cvv: {placeholder: 'CVV'},postalCode: {placeholder: 'Postal Code'}},}},//threeDSecure: {//3D安全校验,选填,用于信用卡支付的时候,若改卡的持卡人在开卡的时候启用了额外的身份校验,例如密码,那么点支付的时候则会弹出一个额外的框,输入密码。//    amount: document.querySelector('#amount').value//}}, function (createErr, instance) {form.addEventListener('submit', function (event) {event.preventDefault();instance.requestPaymentMethod(function (err, payload) {//客户输入密码等之后,接收返回的结果,即nonce,支付授权凭证if (err) {console.log('Error', err);return;}// Add the nonce to the form and submitdocument.querySelector('#nonce').value = payload.nonce;form.submit();});});});});
</script>一组根据 MerchantId,BraintreePublicKey,BraintreePrivateKey生成的字符串container: '#bt-dropin',paypal: {flow: 'vault',buttonStyle: {  //可以修改一点点按钮的样式,限制性很多color: 'black',shape: 'rect',size: 'medium'}},//此处与上面的paypal设置不一样,亲么可以自己去尝试一下,不同点在哪//paypal: {//    flow: 'checkout',//    amount: document.querySelector('#amount').value,//    currency: 'USD'//}, card: {//此项选填,干掉也没关系cardholderName: { required: true }, //必填的话,就会多生成一个持卡人姓名的输入框overrides: {fields: {number: {placeholder: 'Card Number',},cvv: {placeholder: 'CVV'},postalCode: {placeholder: 'Postal Code'}},}},//threeDSecure: {//3D安全校验,选填,用于信用卡支付的时候,若改卡的持卡人在开卡的时候启用了额外的身份校验,例如密码,那么点支付的时候则会弹出一个额外的框,输入密码。//    amount: document.querySelector('#amount').value//}}, function (createErr, instance) {form.addEventListener('submit', function (event) {event.preventDefault();instance.requestPaymentMethod(function (err, payload) {//客户输入密码等之后,接收返回的结果,即nonce,支付授权凭证if (err) {console.log('Error', err);return;}// Add the nonce to the form and submitdocument.querySelector('#nonce').value = payload.nonce;form.submit();});});});});
</script>
  •  后端

      1.生成clientToken的规则有2种,根据需要来吧。

       由于braintree平台中虽然只有一个商户ID,即Merchant ID,但是确可以有多个Merchant Accounts,即收账账号,设置的界面:Account-->Merchant Account Info

 

  第一种,使用默认配置:

  每个Merchant ID都会有一个default Merchant Account,所以下面的写法,就是默认将款额收到默认账户上

var config = new BraintreeGateway(environment, merchantId, publicKey, privateKey) ;
var gateway = config.GetGateway();
var clientToken = gateway.ClientToken.generate();

  第二种:指另付款到某一个账号

var clientToken = gateway.ClientToken.generate(new ClientTokenRequest() { MerchantAccountId = "TestAccount" });

  2.综合

   支付功能:一共3个Action:

//生成clientToken 传到前端,用于生成支付控件
public ActionResult New(){        var gateway = config.GetGateway();//var clientToken = gateway.ClientToken.generate();var clientToken = gateway.ClientToken.generate(new ClientTokenRequest() { MerchantAccountId = "TestAccount" });ViewBag.ClientToken = clientToken;return View();}
//form提交,得到nonce之后,在这里进行扣款public ActionResult Create(){var gateway = config.GetGateway();Decimal amount;try{amount = Convert.ToDecimal(Request["amount"]);}catch (FormatException e){TempData["Flash"] = "Error: 81503: Amount is an invalid format.";return RedirectToAction("New");}var nonce = Request["payment_method_nonce"];//得到前端传来的nonce参数var request = new TransactionRequest//新建交易请求{MerchantAccountId = "TestAccount",//注意这里,如果你的clientToken生成的时候设置了MerchantAccountId,那么扣款的时候也必须要加上这个参数,否则是会失败的Amount = amount,PaymentMethodNonce = nonce,Options = new TransactionOptionsRequest{ThreeDSecure = new TransactionOptionsThreeDSecureRequest()//这里注意,如果你前端启用了3D安全,那么这里也需要启用{Required = true},SubmitForSettlement = true}};Result<Transaction> result = gateway.Transaction.Sale(request);//扣款if (result.IsSuccess())//成功{Transaction transaction = result.Target;//transaction.Id是官方生产的此交易的唯一编号,如果要进行查询和退款的话,就必须要将此ID记录数据库.return RedirectToAction("Show", new { id = transaction.Id });}else if (result.Transaction != null){return RedirectToAction("Show", new { id = result.Transaction.Id, mesg = result.Message});}else{string errorMessages = "";foreach (ValidationError error in result.Errors.DeepAll()){errorMessages += "Error: " + (int)error.Code + " - " + error.Message + "\n";}TempData["Flash"] = errorMessages;return RedirectToAction("New3");}}
//支付结果页展示
public ActionResult Show(String id, string mesg){var gateway = config.GetGateway();Transaction transaction = gateway.Transaction.Find(id);if (transactionSuccessStatuses.Contains(transaction.Status)){//成功}else{//失败}ViewBag.Transaction = transaction;return View();}

 退款:

   这里要说明下,即时客户完成了交易,已经进行了扣款,但是如果要立马退款的话,是不行的。因为braintree内部也要进行交易审核,审核过程需要时间,而且是时间不固定,可能十几分钟,可能几个小时。所以这里我们要根据当前退款的订单状态进行是退款还是作废。2种操作的过程是不一样的。退款会在briantree账户上生成退款交易单,但是作废不会,虽然2种操作最都会退款给客户。

 public ActionResult RefundTest(string trId, decimal amount){var gateway = config.GetGateway();try{Transaction transaction = gateway.Transaction.Find(trId);if (transaction.Status == TransactionStatus.SETTLED || transaction.Status == TransactionStatus.SETTLING){//交易状态为以上时,方可进行退款操作Result<Transaction> result = gateway.Transaction.Refund(trId, amount);if (!result.IsSuccess()){//退款失败//Transaction transaction = result.Transaction;//if (transaction.Status == TransactionStatus.SETTLEMENT_DECLINED)//{//    //Console.WriteLine(transaction.ProcessorSettlementResponseCode);//    // e.g. "4001"//    //Console.WriteLine(transaction.ProcessorSettlementResponseText);//    // e.g. "Settlement Declined"//}return RedirectToAction("RefundResponce", new { msg = result.Message });}else{return RedirectToAction("RefundResponce", new { msg = "OK" });}}else if (transaction.Status == TransactionStatus.AUTHORIZED || transaction.Status == TransactionStatus.SUBMITTED_FOR_SETTLEMENT ||(transaction.PaymentInstrumentType == PaymentInstrumentType.PAYPAL_ACCOUNT && transaction.Status == TransactionStatus.SETTLEMENT_PENDING)){//交易状态为此状态时不可退款,但是能void交易,即作废,那么就可同时退款可客户Result<Transaction> result = gateway.Transaction.Void(trId);if (result.IsSuccess()){return RedirectToAction("RefundResponce", new { msg = "transaction successfully voided" });}else{return RedirectToAction("RefundResponce", new { msg = result.Message });//foreach (ValidationError error in result.Errors.DeepAll())//{//    Console.WriteLine(error.Message);//}}}}catch(Exception ex){return RedirectToAction("RefundResponce", new { msg = ex.Message });}return RedirectToAction("RefundResponce");}//扣款结果显示
public ActionResult RefundResponce(string msg){ViewBag.Mesg = msg;return View();}

至此支付和退款功能完成。

其实还有很多需要解说和注意的地方,还是自己去多多摸索的话学到的更多。虽然都是英文的,可以锻炼英文的说。

关于自定义支付控件样式,即Customer UI的使用,下篇谈,官方介绍,有demo,还可以自己编码测试的网站

https://developers.braintreepayments.com/guides/hosted-fields/examples/javascript/v3。

Braintree-国外支付对接(三) 之Customer UI

以上纯属个人独自研究成果,仅供参考,转载请注明出处

    


http://chatgpt.dhexx.cn/article/8uap6h3G.shtml

相关文章

app接入 Paypal BrainTree

BrainTree 是什么 braintree 一开始是一个独立支付网关&#xff08;gateway&#xff09;&#xff0c;后来在2013年左右&#xff08;没记错的话&#xff09;被 Paypal收购。收购之后基本可以看作与paypal是一家。 paypal 收购 braintree 之后 sdk 也转向重点接入 braintree&…

多种方式99.9%解决从PDF复制文字后乱码问题

背景 需要从PDF复制文字出来做笔记&#xff0c;可是谁知道PDF通过adobe打开后复制出来后是乱码&#xff0c;如下图所示&#xff1a; &#xff08;再次感谢guide哥整理的文档&#xff09; 解决 尝试过安装字体&#xff0c;可惜没卵用。 方法1-CAJViewer打开 用该软件打开后…

java word转pdf 在linux转pdf乱码解决方法

word转pdf word转pdf,完美转换 引入依赖 (maven仓库是没有的&#xff0c;需要在项目中引用) 链接: 下载地址. 然后在pom里面引入下面这段&#xff0c;依赖我们就搭建好了 <dependency><groupId>com.aspose</groupId><artifactId>aspose-words</a…

word转pdf公式乱码_MathType转换成pdf符号丢失或乱码怎么办

一般写论文的时候是在Word中编写&#xff0c;在Word中写公式时一般是使用MathType&#xff0c;MathType编辑出来的公式非常标准与美观&#xff0c;很多国际期刊杂志都有这种要求。但是在将编写好的论文进行投稿时需要将Word文档转换成PDF文档&#xff0c;这样论文公式才不会发生…

itextpdf生成pdf中文乱码 (乱码中挣扎的自述)

生成pdf文件的方法有很多&#xff0c;网上也有很多的介绍&#xff0c;本文主要主要是讲生成pdf乱码的问题&#xff0c;而且还十分诡异&#xff0c;具体生成pdf的步骤同学们可以自己百度&#xff0c;也可以参考如下链接&#xff1a; https://www.cnblogs.com/LUA123/p/5108007.…

pdf转换html乱码怎么办,pdf转word后乱码怎么办?

pdf转word后乱码怎么办&#xff1f;网络上面有一些PDF资料你可以对其内容复制&#xff0c;但是粘贴到word或者文本中就是一堆乱码&#xff0c;你用转换软件转换出来&#xff0c;有一些文件不会是乱码&#xff0c;但是还有一些文件依旧是乱码&#xff0c;怎么办呢&#xff1f;今…

表格生成pdf 中字乱码

表格生成pdf及解决中字乱码 npm库表格生成pdf的超简洁小例子(用的是npm导入字体)两种解决乱码方法直接引入npm引入在项目中导入stsong-font在所需的页面上引用最后在生成pdf函数中使用(同上) npm库 两个必备包 jspdf npm i jspdfjspdf-autotable npm i jspdf-autotable在所需…

php生成pdf乱码_ierport 生成pdf出现乱码问题

iReport导出pdf中文乱码问题解决 使用iReport的过程经常遇到一些乱码的问题&#xff0c;最近用iReport导出pdf的时候就遇到中文不能显示的问题。 要使导出的pdf能够显示中文&#xff0c;需要用到iTextAsian.jar包。 1.将显示中文的地方Text属性设置成支持中文的字体。 Pdf font…

PDF文件复制文本为乱码

PDF文件可能会出现复制文本粘贴成乱码的现象。原因是PDF中所用的字体无法在电脑中找到&#xff0c;点击编辑器的”文件-属性“&#xff0c;查看字体&#xff0c;如果字体可以下载&#xff0c;可以在网上下载安装&#xff0c;就可以进行复制粘贴。 但有的PDF为保护内容&#xff…

pdf复制乱码_网站推荐 | 从未见过你这么不单纯的PDF转换器!

点击蓝字 关注我们 之前给大家分享过几期PDF转换器 但是仍然觉得部分线上转换器会出现 格式乱码、甚至字乱码的现象 (字乱码是由于外文网址识别误差) 这次挥挥找到了一个PDF转word 近乎完美保留原格式的在线转换网站&#xff01; 一起来看看叭 Today PDF转换器 http://www.pdfd…

Pdf 解密后复制文字乱码

1、安装cajviewer 这个工具 2、用CAJviewer打开pdf文档 3、选择图像4、点文字识别&#xff0c;这时候就弹窗一个框&#xff0c;里面是可复制的文本&#xff0c;而且准确率比较高 转载于:https://www.cnblogs.com/wangyuelang0526/p/3735398.html

使用latex撰写中文科技论文时,生成的PDF复制中文时乱码(不能查重),解决办法如下

在投稿中文期刊《控制理论与应用》时&#xff0c;期刊要求必须用latex&#xff0c;官方给的编辑器是WinEdt7.0&#xff0c;但是如果用常用的编译方式生成PDF的话&#xff0c;也就是第一个选项PDFTeXify 打开生成的PDF表面上看是没有任何问题的&#xff0c;可以正常阅读。但是如…

Tex导出PDF乱码问题

目录 工作环境错误pdf导出方式正确的pdf导出方式 工作环境 我用的是CTex TexStudio。CTex是为了方便中文字体。 错误pdf导出方式 一般我们都是点上方菜单栏的双箭头的按钮进行Tex文件编译&#xff0c;右边就会实时显示pdf内容。当然此时文件夹内也会产生相应的pdf文件。 我…

pdf复制乱码_SCI必备利器:选中即翻译,PDF文献也能一键翻译了。

来源丨软件通 ← 关注Ta 都是干货&#xff0c;无需引导 请仔细阅读全文。 熟悉小通的童鞋都知道&#xff0c;我们只推荐过一款sci论文翻译软件&#xff0c;那就是&#xff1a;CopyTranslator。复制即翻译&#xff0c;现在又更新了。新版本支持选中即翻译厉害吧&#xff01;选中…

新版macbook,PPT导出PDF复制文字乱码问题的解决

参考资料&#xff1a; 福昕阅读器的文档&#xff1a;https://m.foxitsoftware.cn/company/product/964.html 微软支持(完全一模一样的问题) 先说一下&#xff0c;我的这个PDF复制文字乱码问题确实是被我解决了&#xff0c;但是我的这个PDF是有源文件的&#xff1a;一个PPT演示文…

解决从PDF复制文字后乱码问题

背景 需要从PDF复制文字出来做笔记&#xff0c;可是谁知道PDF通过adobe打开后复制出来后是乱码&#xff0c;如下图所示&#xff1a; 解决 尝试过安装字体&#xff0c;可惜没卵用。 方法1-CAJViewer打开 用该软件打开后复制&#xff0c;可以完美复制&#xff0c;但是有个小问题…

pdf复制乱码_教程如何将公众号文章导出为pdf

0.说明 最近有一些小伙伴在后台问我们文章有没有word版&#xff0c;因为可能对着手机小小的屏幕看这些公式什么的确实有点头疼&#xff0c;而且有的小伙伴还需要上课哈。 其实word文档的doc/docx并不是最佳的&#xff0c;在不同环境可能会出现公式乱码的情况&#xff0c;相比之…

PDF复制乱码 -- 简单解决办法

这里写自定义目录标题 前言步骤1&#xff1a;PDF转Word步骤2&#xff1a;word转回PDF 前言 很多从网上下载的PDF会存在乱码的情况&#xff0c;比如这个&#xff0c;明明可以选中&#xff0c;但是使用 有道词典的划词翻译 或者 复制到别的地方的时候却是乱码&#xff1a; 试了…

pdf复制出乱码解决方案

目录 pdf复制出乱码解决方案一、pdf格式基础二、ttf格式基础三、解决乱码1.提取文字&#xff0c;识别文字a.和原文件比对b.OCR手工辅助识别 2.修改pdf中的文字&#xff0c;使其可复制a.选择pdf开发库b.修改pdfc.完整代码 pdf复制出乱码解决方案 偶然发现有一类pdf文档中的文字…

RK px30 配置GT911 TP触摸流程记录

1.简介 RK px30配置GT911 TP 触摸&#xff0c;流程记录 2.查看原理图 首先&#xff0c;查看原理图的tp座子&#xff0c;然后往下查找连接在主控的哪路i2c上 这里我们可以看见&#xff0c;此路TP是连接在i2c3上&#xff0c;接下来进行dts配置 3.DTS 配置 先查看是否有 i2c3…