Android Development: App Engineering integrated UnionPay-return refund function

Source: Internet
Author: User
Tags http 200

I. Preface

The UnionPay payment function has been integrated (server side stamp here, client stamp here), temporarily put the refund function put aside, today smoked a little time to fill up the hole.
In fact, with the experience of the last integrated payment function, the integration of return refunds is easy to achieve. This article only talk about server-side processing, the client according to the requirements of writing good.
UnionPay official provides a return refund flowchart:

So the process is mainly: server-side organization of the request message--UnionPay system processing, the results and processing results returned to the server.

Two. Implement

I've made some comments in the code, so it's no problem to read the code and comments basically. The prerequisites are still, complete the configuration work, you can refer to the server-side blog post.
Just note that the success of UnionPay will return a serial number, which is the input of subsequent operations (return, refund, query payment status, etc.) instead of the order number (the reason is very simple Ah, the order number is we according to certain rules generated, the UnionPay system is definitely not recognized), So we have to bind the serial number to the order we need to manipulate, and the best way is to add a serial number field to the Order table.

1. The first step

Organize the request message and initiate a return refund request to UnionPay backend.

/** * Refund process * @param orderId//order ID that requires a return refund * @param request * @param respon SE * @throws unsupportedencodingexception */    @RequestMapping(Value ="/pay/refund/{orderid}")@ResponseBody     PublicJsonobjectRefund(@pathvariable("OrderId") String orderid,httpservletrequest request, httpservletresponse response)throwsunsupportedencodingexception {//Prevent garbled, according to business needs, these two sentences dispensableRequest.setcharacterencoding (Demobase.encoding_utf8); Response.setcontenttype ("text/html; Charset= "+ Demobase.encoding_utf8);//json used to return data to the clientJsonobject JSON =NewJsonobject (); System.out.println ("Refund Start");//Get information on this orderOrder order = Orderdao.getorder (orderId);if(order==NULL) {Json.put ("Result","0");returnJson }//Get the serial number of the orderString Orderqueryid = Order.getorderqueryid ();//Get the total price of the orderString Orderoiltotalprice = Order.getorderoiltotalprice (); map<string, string> data =NewHashmap<string, string> ();/*** UnionPay omni-channel system, product parameters, in addition to encoding self-choice other than the need to modify ***/Data.put ("Version", demobase.version);//Version numberData.put ("Encoding", Demobase.encoding_utf8);//Character set encoding can be used UTF-8,GBK two different waysData.put ("Signmethod"," the");//Signature method currently only supports 01-RSA-mode certificate EncryptionData.put ("Txntype"," ");//transaction type 04-ReturnsData.put ("Txnsubtype","XX");//Trading sub-type default XXData.put ("BizType","000201");//Business typeData.put ("Channeltype","the");//channel type, 07-pc,08-phone        /*** Merchant Access Parameters ***/Data.put ("Merid", Demobase.merid);//Merchant number, please change to your application's merchant number or open on the registered 777 merchant number testData.put ("AccessType","0");//access type, merchant access fixed 0, no modification required        //Be sure to note that the OrderID is not our own order ID, but rather the ID of the refund application, and the Demobase.getorderid () provided by UnionPay is generated based on the system time. Data.put ("OrderId", Demobase.getorderid ());//Merchant order number, 8-40 digit letters, cannot contain "-" or "_", can customize the rules, re-generated, different from the original consumptionData.put ("Txntime", Demobase.getcurrenttime ());//Order send time, format is YYYYMMDDHHMMSS, must take the current time, otherwise it will be reported txntime invalidData.put ("CurrencyCode","156");//Transaction currency (domestic merchant is generally 156 RMB)        //Be sure to note that the refund amount must be an integer and the unit is a cent. Data.put ("Txnamt", Double.valueof (Orderoiltotalprice). Intvalue () * -+"");//**** return amount, Unit points, do not bring decimal points. Return amount less than or equal to the original consumption amount, when less than the time can be returned to the return of the cumulative amount equal to the original consumption amount        //data.put ("Txnamt", orderoiltotalprice);        //This pass-through field is very useful, because the previous OrderID is not our own order ID, and we will definitely need this order ID in the background notice, because we need to modify the status of the order, but the data can not put our own order ID, Then this field is used to store some of the data we want to pass to the background notification, because the data in the full return to the background notice, I just put a OrderID in the Pass field, if there is more data to pass, only need to use map or JSON to store the data, And then turn it into a string.Data.put ("Reqreserved", orderId);//requester-reserved domain, pass-through fields (can be tracked by the merchant's custom parameters) the background notice of the transaction, the transaction status of the transaction inquiry transactions, reconciliation documents are returned as is, the merchant can upload on demand, the length of 1-1024 bytes        The //background notification address must be a real IP, as the UnionPay backend will post the notification to this backend address. Data.put ("Backurl", Demobase.backurl);//Background notification address, background notification parameters see open.unionpay.com Help Center Download Product Interface Specification Gateway Payment product Interface Specification return transaction merchant notification, other instructions with the consumer transaction background notice        /*** to tune the transaction the following fields must be modified ***/        //serial number, this is the ID of the UnionPay background, the serial number is obtained after successful payment. Data.put ("Origqryid", Orderqueryid);//**** The original consumption transaction returned Queryid, can be obtained from the consumer trade background notification interface or the transaction status query interface        /** The request parameter is set, the following signs the request parameter and sends the HTTP POST request, receives the synchronous reply message------------->**/map<string, string> reqdata = Acpservice.sign (Data,demobase.encoding_utf8);The value of certid,signature in the message is obtained in the SignData method and automatically assigned, as long as the certificate is configured correctly. String URL = sdkconfig.getconfig (). Getbackrequesturl ();//Trade request URL read from the configuration file Acpsdk.backtransurl in the corresponding properties file Acp_sdk.propertiesmap<string, string> rspdata = Acpservice.post (Reqdata, Url,demobase.encoding_utf8);//After calling SignData, you cannot make any changes to the key-value pairs in Submitfromdata before calling Submiturl, and if the modifications will cause the check to fail        /** The processing of the answer code, write the program according to your business logic, the following answer code processing logic is for reference only------------->**/        //Answer Code specification Reference open.unionpay.com Help Center Download Product Interface Specification "Platform Access Interface Specification-part 5th-Appendix"        if(!rspdata.isempty ()) {if(Acpservice.validate (Rspdata, Demobase.encoding_utf8)) {Logutil.writelog ("Verify signature succeeded"); String Respcode = Rspdata.get ("Respcode") ;if(("XX"). Equals (Respcode)) {//transaction has been accepted (does not represent the success of the transaction), waiting to receive background notification update order status, can also proactively initiate inquiry transactions to determine the transaction status.                     //todoJson.put ("Result","1");returnJson }Else if((" the"). Equals (Respcode) | | (" "). Equals (Respcode) | | ("a"). Equals (Respcode)) {//Follow-up transaction status Enquiry transaction confirmation transaction status                    //todo}Else{//Other answer code for failure Please check the reason                    //todo}            }Else{Logutil.writeerrorlog ("Verify signature Failed");//todo Check the reason for verifying that the signature failed}        }Else{//did not return the correct HTTP statusLogutil.writeerrorlog ("No return message returned or HTTP status code not available"); } json.put ("Result","0");returnJson }
2. Step Two

Background notification address to receive UnionPay backstage processing results Notice, in the previous article has written a background notification processing, this time plus the refund function after a slightly modified.

/** * Background notification processing * @param request * @param Response */    @RequestMapping(Value ="/pay/backrcvresponse")@ResponseBody     Public void Backrcvresponse(HttpServletRequest request, httpservletresponse response) {System.out.println ("background notification verification start");//return acpservice.validateappresponse (sign, Demobase.encoding_utf8);        //system.out.println ("Verification Start");String encoding = Request.getparameter (sdkconstants.param_encoding);//Get background notification parameters sent by UnionPay notification Servermap<string, string> Reqparam = Tool.getallrequestparam (request);        Logutil.printrequestlog (Reqparam); map<string, string> validedata =NULL;Try{if(NULL! = Reqparam &&!reqparam.isempty ()) {iterator<entry<string, string>> it = reqparam.ent                Ryset (). iterator (); Validedata =NewHashmap<string, String> (Reqparam.size ()); while(It.hasnext ())                    {entry<string, string> e = It.next ();                    String key = (string) e.getkey ();                    String value = (string) e.getvalue (); Value =NewString (value.getbytes (encoding), encoding);                Validedata.put (key, value); }            }//Important! Do not modify the contents of the key-value pairs in the Reqparam before verifying the signature, otherwise it will be checked .            if(! Acpservice.validate (Validedata, encoding)) {Logutil.writelog ("Verify signature result [failed].");//verification failure, need to resolve the issue of the check}Else{Logutil.writelog ("Verify signature results [succeeded].");//"NOTE: The successful processing logic of the merchant should be written for the successful verification of the business success, update the merchant order status                //string orderId =validedata.get ("orderId");//Get data for background notifications                //order Order = Orderdao.getorder (orderId);                //Get transaction type, refer to official documentationString Txntype = Validedata.get ("Txntype");                System.out.println (integer.valueof (Txntype)); Order order;Switch(Integer.valueof (Txntype))//transaction type{ Case  on://ConsumptionString orderId =validedata.get ("OrderId");//Get data for background notifications, and other fields can be obtained in a similar wayString paytime = Validedata.get ("Txntime"); String Orderqueryid = Validedata.get ("Queryid");//string respcode =validedata.get ("Respcode");//Get Answer code, receive background notification the value of Respcode is generally 00, can not be judged according to this answer code.                         //if (orderid!=null&&! "". Equals (orderId))                        //{Order = Orderdao.getorder (orderId);if(order!=NULL) {System.out.println ("Update payment status:"+orderid); System.out.println ("Paytime"+paytime); Order.setorderpaystatus (1); Order.setorderpaytime (paytime+". 0"); Order.setorderqueryid (Orderqueryid);//order.setorderpaytime (New SimpleDateFormat ("Yyyy-mm-dd HH:mm:ss"). Parse (paytime));                                Booleansucess = orderdao.update (order); System.out.println ("sucess"+sucess); }//}                         Break; Case Geneva://Returns & Refunds                    //Get data from the pass-through field, I'm here for the order IDOrder = Orderdao.getorder (Validedata.get ("Reqreserved"));if(order!=NULL)                        {//Update order statusOrder.setorderpaystatus (2); Order.setorderstatus (2);                        Orderdao.update (order); } Break;default: Break; }} logutil.writelog ("Backrcvresponse Receive background notification end");//Return to UnionPay server HTTP 200 status codeResponse.getwriter (). Print ("OK"); }Catch(Exception e) {}    }

OK, let's take a look at the effect. Respcode = 00 indicates success.

Three. Questions

Will not encounter the problem is impossible, of course, according to the implementation of my above code is only able to run the basic process, from the security, too much worse ...
1. The refund amount must be an integer
For example, the picture below:

The OrderID in 2.data is not your own OrderID, but the ID of this refund transaction.
3. Background notification address must be really ip,localhost not, loop address also not.

Android Development: App Engineering integrated UnionPay-return refund function

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.