Half a year ago, when I was working on a project with my teacher, I encountered the need to access Alipay for payment. This year, I feel that I have dabbled in too many things, and now I don’t seem to know anything… The actual access scenarios may vary according to services. Here, the previous projects are used as an example. The content of services does not need to be tangled, but only needs to be understood from the usage. Example (Front-end with PC Web and mobile RN(Android), back-end with KOA2 + leanCloud)
Access to alipay payment preconditions
Individuals cannot apply; currently, only businesses can apply
1. Register an enterprise account on Alipay 2. Apply for an application on ant Financial’s open platform
15020699174012.jpg
Improve the data – including the address for authorization callback and the gateway and interface signing mode of the application, the generated certificate needs to be well kept, which is not only needed for the subsequent development, but also related to the data security of the application. After signing and submit for review
15020699713243.jpg
PS: When signing a contract, there are different requirements for different ways, including mobile app payment, you need to upload documents about the app (including app interface screenshots! Or you’ll be called back.)
Access Alipay
Business ideas
Both Alipay and third-party payment are based on this
111 -3-.png
access
It can be accessed quickly through the third party, or it can be accessed using the native interface /SDK. Beecloud is still used in webpage H5 only for enterprise users, not for individuals. The advantage of third-party payment is unified entrance, supporting a large number of payment channels such as
15020707996912.jpg
However, it is still necessary for each channel to open relevant applications.
Beecloud H5 seconds to pay
Beecloud second payment works by rendering data on a template page provided by beecloud. The template page verifies the data and then redirects to the Alipay payment page, and finally notifies the background by calling back. The official documentation
The second payment button of Beecloud can be directly adapted to H5 payment on PC and mobile phone. (In the preconditions, you must sign up for PC payment before you can continue to use it.) You will get the following contents after opening the quick Payment service
const appid='';
const secret='';
const masterSecret = '';
Copy the code
After filling in the callback address in beecloud, the address will be notified of the successful payment, i.e. the request will be sent to the URL with data.
Start from the user access page and look at the code. Since the data is stored in leanCloud’s cloud database, you will see AV(😵 is not what you think!). Class, just know that the class is used for data storage retrieval, the following is the route to access the recharge page.
var fun_payBalance = async(ctx, next) => { var user = await AV.User.current(); var requestData = ctx.request.query; var amount = requestData.amount; if (user == null) { ctx.response.redirect('/personal/recharge'); } else { if (! amount) { ctx.response.redirect('/personal/recharge'); }} var result = pay. rechargeBalance(amount, 'recharge '); If (result) {var signStr = result.signstr; var signStr = result.signstr; var outTradeNo = result.outTradeNo; CTX. Render ('paytest.html', {title: 'balance top up ', OutTradeNo: OutTradeNo, Sign: signStr, amount: amount}); } else { console.log('error'); ctx.response.redirect('/personal/recharge'); }}Copy the code
The content of the Pay. RechargeBalance
rechargeBalance:(amount,title)=>{ var user = AV.User.current(); if(! user){ return ; } var pay = new pays(); var outTradeNo=uuid.v4(); outTradeNo = outTradeNo.replace(/-/g, ''); amount = parseFloat(amount); var data = appid + title + amount + outTradeNo + secret; pay.set('orderNumber',outTradeNo); pay.set('lines',amount); pay.set('info',title); pay.set('user',user); // Save the order to the database pay.save(); return { signStr:sign.createHash('md5').update(data, 'utf8').digest("hex"), 'outTradeNo':outTradeNo, }; },Copy the code
Pay page template content, the core is the BC.click method
<! DOCTYPE html> <html> <head> <meta name="viewport" The content = "width = device - width, initial - scale = 1.0, the minimum - scale = 1.0, the maximum - scale = 1.0, user - scalable = no" > < title > {{title </title> <link rel='stylesheet' href='stylesheets/style.css' /> </head> <body> <div class="description"> {{OutTradeNo}} Payment content: {{title}} Payment amount: {{amount}} {% if card %} Card type: {{card.typeinfo.get ('cardName')}} Card number: {{card. Get (" cardId ")}} {% endif %} < p > < center > < button id = "test" class = "button" > click payment < / button > < / center > < / p > < / div > < script id='spay-script' src='https://jspay.beecloud.cn/1/pay/jsbutton/returnscripts?appId=af1df3a3-ab4b-48d8-b71a-8dbd60a92451'></script> <script> document.getElementById("test").onclick = function() { asyncPay(); }; function bcPay() { var out_trade_no = "{{ OutTradeNo}}"; var sign = "{{ Sign }}"; console.log(sign); console.log(out_trade_no); Console. log(err) */ bc. err = function(data) {// Register ERROR message accept alert(data["ERROR"]); } / * * * 3. Call the BC. Click interface pass parameters * / BC. Click ({" title ":" {{title}} ", "amount" : "{{amount}}", "out_trade_no" : Out_trade_no, // unique order number "sign" : sign, /** * optional is a custom parameter object. Currently, only basic types of key = value are supported. Nested objects are not supported. */ "optional": {"test": "willReturn "}}); } function asyncPay() { if (typeof BC == "undefined"){ if( document.addEventListener ){ document.addEventListener('beecloud:onready', bcPay, false); }else if (document.attachEvent){ document.attachEvent('beecloud:onready', bcPay); } }else{ bcPay(); } } </script> </body> </html>Copy the code
Pay successful callback, callback route
'use strict'; const AV = require('leanengine'); const Pay = require('.. /pay-service') var beecloudWebhook = async(ctx,next)=>{ var data = ctx.request.body; Pay.webhook(data); } module.exports={ 'POST /webhook/back':beecloudWebhook, }Copy the code
The callback business function
webhook:async(data)=>{ var signKey = data.signature; var signData = appid+data.transaction_id+data.transaction_type + data.channel_type + data.transaction_fee + masterSecret; Var signStr = sign.createHash('md5').update(signData, 'utf8').digest("hex") =signKey){console.log("key failure"); Var query = new av. query ('pays'); query.equalTo('orderNumber',data.transaction_id); Var pay = await query.first(); If (pay&&pay.get('status')===1){return {"result":-1, "message":"had been finished"}; Return {"result":-1, "message":"pay do not exit"} else{// Exit if(typeof pay ==="undefined"){return{"result":-1, "message":"pay do not exit"}; } //check the transaction_fee orz // about the pay result if(data.transaction_type == "PAY"){ var user = await AV.User.current(); Var status = data.trade_success; If (status){pay. Set ('status',1); var payId = pay.id; await pay.save(); var pay_record =null; let card_Id = pay.get('cardId'); If (card_Id){pay_record = new rechargeCard(); pay_record.set('cardId',pay.cardId); let card = new AV.Query('Cards'); var fee = data.transaction_fee; If (envMode=="test"){fee*=1000; } card.get(card_Id).then(function(findedCard){ findedCard.set(findedcard.get('cardBalance')+fee); findedCard.save(); console.log(findedCard); }) }else{ pay_record = new rechargeBalance(); var fee = data.transaction_fee; // if the test mode the fee * 1000 if(envMode=="test"){ fee*=100; } console.log("before"+user.get('balance')); user.set('balance',user.get('balance')+fee); user.save(); console.log("after"+user.get('balance')); } if(pay_record){ pay_record.set('user',user); pay_record.set('payLines',data.transaction_fee); pay_record.set('payId',payId); pay_record.save(); } return { "result":1, "message":"success" }; }else{ console.log("status failure"); }}}},Copy the code
So far the 🌰 of third-party payment has ended, which may include some business logic in it, but the overall idea is consistent with the figure above.
15021724010967.jpg
15021724250679.jpg
15021724623938.jpg
15021725041931.jpg
React-native (Android) Access native payment
The core content of this part is to integrate the native Android module and use Ali Sdk NodeJS third-party package. The above part is more detailed. The problems encountered in this part are only Ali may appear when signStr is incorrect 40247 There is a problem with signStr on the server side and cannot get order information temporarily — no amount was passed
123.png
The program must print “success” (without quotes) after execution. If the merchant feedback to Alipay is not the seven characters of SUCCESS, the Alipay server will continuously re-send the notification until it exceeds 24 hours and 22 minutes. Generally, 8 notifications are completed within 25 hours (the interval frequency is 4m,10m,10m,1h,2h,6h, and 15h). After the program is executed, the page cannot be redirected. If the page jump is performed, Alipay will not receive the SUCCESS character, which will be judged by alipay server as abnormal operation of the page program and resend the notification of processing results;
Attention should be paid to the problem of returning information when dealing with Alipay Webhook. Success should be returned when verifying information, otherwise messages will be sent all the time. Using the Ali Sdk NodeJS third-party package mentioned above in KOA2, you can store this Ali object in ctx.state.
Writing here for the moment, in practical applications, the part involving payment business must be checked daily to ensure security.