设置付款处理
这才是“真正的”工作。之所以用引号,是因为一旦你知道怎么做,它就很简单了。我一会儿会一步一步讲解。现在,只需粘贴以下内容:
1. 将此代码添加到您的 HTML 页面
将其粘贴到 Pi.init 代码后面:
Javascript
<script>
// we're doing payments
const Pi = window.Pi;
// main payments function
function createPayment() {
const paymentData = {
amount: .01,
memo: "This buys you three more insults! What a deal!!!",
metadata: { insultid: 123456 }
};
// the SDK does all this like magic
const paymentCallbacks = {
onReadyForServerApproval: (paymentDTO) => {
paymentId = paymentDTO
$.post('/payment/approve', {
paymentId: paymentId,
accessToken: accessToken
})
},
onReadyForServerCompletion: (paymentDTO, txid) => {
paymentId = paymentDTO
txid = txid
$.post('/payment/complete',
{
paymentId: paymentId,
txid: txid,
debug: 'complete'
}
)
},
onCancel: (paymentDTO) => {
paymentId = paymentDTO.identifier
$.post('/payment/complete',
{
paymentId: paymentId,
debug: 'cancel'
}
)
},
onError: (paymentDTO) => {
console.log('There was an error ', paymentDTO)
paymentId = paymentDTO.identifier
$.post('/payment/error',
{
paymentDTO: paymentDTO,
paymentId: paymentId,
debug: 'error'
}
)
},
onIncompletePaymentFound: function(paymentDTO)
{
paymentId = paymentDTO.identifier
console.log('onIncompletePaymentFound', paymentId)
$.post('/payment/complete',
{
paymentId: paymentId,
txid: paymentDTO.transaction.txid
}
)
}
};
Pi.createPayment(paymentData, paymentCallbacks);
}
</script>
2.将此代码添加到app.py
这样就设置好了之前提到的 Flask 路由。这些只是 Pi 的路由。你需要设置一些应用特定的路由。对我来说,这些是get_quote和back 。或者直接下载整个仓库。
Python
@app.route('/payment/approve', methods=['POST'])
def approve():
# Build the header for user authentication
accessToken = request.form.get('accessToken')
userheader = {
'Authorization': f"Bearer {accessToken}"
}
paymentId = request.form.get('paymentId')
approveurl = f"https://api.minepi.com/v2/payments/{paymentId}/approve"
response = requests.post(approveurl, headers=header)
userurl = "https://api.minepi.com/v2/me"
userresponse = requests.get(userurl, headers=userheader)
userjson = json.loads(userresponse.text)
return(response.text)
@app.route('/payment/complete', methods=['POST'])
def complete():
# Build the header for user authentication
accessToken = request.form.get('accessToken')
userheader = {
'Authorization': f"Bearer {accessToken}"
}
paymentId = request.form.get('paymentId')
txid = request.form.get('txid')
userurl = "https://api.minepi.com/v2/me"
userresponse = requests.get(userurl, headers=userheader)
data = {'txid': txid}
approveurl = f"https://api.minepi.com/v2/payments/{paymentId}/complete"
response = requests.post(approveurl, headers=header, data=data)
return(response.text)
@app.route('/payment/cancel', methods=['POST'])
def cancel():
paymentId = request.form.get('paymentId')
approveurl = f"https://api.minepi.com/v2/payments/{paymentId}/cancel"
response = requests.post(approveurl, headers=header)
return(response.text)
@app.route('/payment/error', methods=['POST'])
def error():
paymentId = request.form.get('paymentId')
approveurl = f"https://api.minepi.com/v2/payments/{paymentId}/cancel"
response = requests.post(approveurl, headers=header)
return(response.text)
@app.route('/me', methods=['POST'])
def getme():
userurl = "https://api.minepi.com/v2/me"
response = requests.post(userurl, headers=header)
return(response.text)
这些新路线具有以下功能:
- /payment/approve连接到 Pi SDK,并启动整个支付/审批流程。当用户点击“支付”时,JavaScript createPayment 函数会触发该函数。此时,Pi 平台上会发生各种神奇的事情。如果付款获得批准,SDK 会调用完整的路由
- /payment/complete获取交易 ID(唯一交易字符串),并触发 me 路由
- /payment/cancel和error听起来就是这样,只是我比较懒,所以两个路由都会向 SDK 的取消 URL 发送请求
3.确保它们连接
要将你的应用连接到 Pi SDK,你只需要调用 createPayment 函数即可。对我来说,就是“支付”按钮:
Javascript
<a href="#" id="resetBtn" class="btn btn-primary mt-3" OnClick='javascript:createPayment();'>Pay</a>
当有人点击“支付”时,会调用createPayment,后者会调用 Flask 路由 /payments/approve。然后,奇迹发生了。
到目前为止的时间:< 4 小时,减去愚蠢的时间
至此,我的应用已经可以正常运行了。它能显示辱骂内容,给 Pi 充值,还能处理所有相关的操作。
这花了大约 4 个小时,还有一些额外的时间用于:
- 括号不匹配,因为我就是那个开发人员
- 我的猫和狗之间发生了一场持久战,其中一只猫在咖啡桌上,在阿尔弗雷德面前晃着尾巴,然后阿尔弗雷德疯狂地试图抓住它的尾巴
- 我完全没理解这个 SDK 到底在做什么。如果我当时稍微考虑一下,就能更快地完成。
我会帮你省去这些麻烦。阅读下一部分,了解这一切是如何运作的:
这一切在做什么
看到这里,你可能已经晕了。这需要大量的剪切粘贴,或者(希望如此)查看代码库。但却无法深入了解它的实际工作原理。以下是分步演示:
- 首次访问。页面打开后,SDK 会加载Pi.init
- 应用程序会调用Pi.authenticate来检查我们是否已通过身份验证。如果没有,Pi 会显示安全警告,并请求用户允许继续操作。
- 假设一切顺利,并且用户授予权限,Pi.authenticate将获取user.username并将其写入页面,以获得良好、个性化的感觉
- 用户点击了几次“Gimme an Insult”。每次点击都会调用/get_quote路由
- 如果用户点击超过三次,应用程序就会显示一个带有付款请求的模式(是的,这很可悲,而且很容易用弹出窗口阻止程序来规避——这是为了科学,好吗?)
- 用户对侮辱的质量感到非常兴奋,他们点击“支付”同意付款
- 当他们这样做时,模态框会调用createPayment
- createPayment调用onReadyForServerApproval ,这会触发Flask 应用中的/payment/approve路由,并向 Flask 发送paymentId和accessToken
- /payment/approve路由向 API 发送包含付款 ID 和访问令牌的请求
- 作为回应,API(希望)说,“好的,一切顺利”,此时 SDK 调用onReadyForServerCompletion
- 这会调用/payment/complete Flask 路由,并向其传递paymentId 以及最重要的txid (交易 ID)
- / payment /complete Flask 路由处理付款
关于 onIncompletePaymentFound
这个小函数差点把我逼疯了。它是个很棒的工具,可以检查未完成的交易,还能调用其他函数。我一开始没明白这个道理。
有几次我把系统搞坏了,交易提交了却没完成。这导致我陷入了错误百出的死循环:我尝试调试,尝试提交另一笔付款,失败了,又尝试调试……结果很糟糕。
为了达到我的目的,我让 onIncompletePaymentFound 调用 /payment/complete。这样一来,只要交易进行到一半,用户下次加载应用时,系统就会完成交易,让他们继续辱骂。
这些都是小额交易,而且是测试,所以我宁愿先完成交易,然后继续测试。另外,我想确保全球经济能持续受到冲击。
在生产中,您可能想要取消交易或做一些更花哨的事情。