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.