In the area of mobile payments, Alipay pays a huge share, according to the report published by Eric Consulting: 2014Q3, Alipay has won 82.6% of the market share, the dominance of mobile payments is increasingly stable. Tenpay paid the force point in the micro-letter payment and Hand Q payment, in the mobile payment pattern achieved 10% of the market share, ranked second.
Alipay's dominance in the field of mobile payment makes it necessary for us to comb the flow of Alipay mobile development. The purpose of this paper is to comb the payment process, to explain how to embed Alipay payment function in mobile applications from the architecture level, and to indicate where development traps exist.
Ready to
According to the instructions, first need to apply for Alipay payment account. This is based on the site description of the application can be. It usually takes about 2 weeks to approve it.
After the successful application, the account information includes the Partner ID partner, the seller pays the treasure account seller_id, and the private key Privatekey. These three items will be used in the development process.
Download the mobile Payment Integration development package on the official web. After decompression, found under its three folders (under the English Mac system file name displayed as garbled):
- "Merchant access to pay Treasure Cashier interface display Standard": Talk about how to use Alipay logo.
- "Alipay Wallet Payment Interface Development Package 2.0 Standard Edition": for payment, including client and server-side development.
- "Instant to account volume refund has a secret interface Refund_fastpay_by_platform_pwd": for the account and bulk refund, only need server-side operations.
The latter two folders include 4 aspects: interface documentation, access and usage rules, demo code, and version update instructions.
Schema Design
First, for a real app application, it may include a variety of payment methods, so you can design the payment function module with the strategy strategy pattern in the design pattern, Alipay payment as one of the strategies, The pay method is the payment algorithm.
If, in addition to the way payment method changes, order orders may also have different forms, such as format may be different, some support can be refunded, some do not allow refunds, etc., in this multi-dimensional variable case, the Payment module architecture can be based on bridging mode.
Second, you can pay Alipay to pay the various operating procedures, such as obtaining order number, generate order data, to pay, to obtain payment results, handling anomalies and other operations, according to the state of the division. This takes the state pattern and provides the flexibility and scalability of the design. In addition, the state machine can be designed for unified State switching management. The following is the reference code:
public class Paystatemachine {/* All possible state of payment */public enum Paystate {pay_init, Pay_got_context, Pay_updated_order, Pay_applied_ ID, pay_order_created, Pay_succeed, error_occurred}/* Errors May Occurre
D during payment */public enum Payerror {pay_get_context_fail, Pay_update_order_fail, Pay_apply_id_fail, Pay_fail
private static Paystatemachine instance;
Private paystate State;
private Iorder order;
Private ipayment Payment;
Private Paystatemachine () {} public static Paystatemachine getinstance () {if (instance = = null) {
Instance = new Paystatemachine ();
return instance;
The public void Initpayment (iorder order, ipayment payment) is {This.order =;
This.payment = Payment;
This.state = Paystate.pay_init;
public void Startpay () {changestate (paystate.pay_init); } public void Changestate(Paystate State)
{onstatechanged (this.state, state); } public void ReportError (payerror error, String detail) {logutil.printpaylog ("The error ID is:" + Erro
R + "" + detail);
Changestate (paystate.error_occurred); } private void Onstatechanged (Paystate oldstate, paystate newstate) {logutil.printpaylog ("oid State:" +
Oldstate + "new state:" + newstate);
This.state = newstate;
Handlepaystatechange (); private void Handlepaystatechange () {if (This.order = null | | | this.payment = NULL) {Logutil.
Printpaylog ("Have not initiated payment");
Return
Switch (this.state) {case PAY_INIT:order.getPayContext ();
Break
Case PAY_GOT_CONTEXT:order.createOrder ();
Break
Case Pay_updated_order:case Pay_applied_id:case PAY_ORDER_CREATED:payment.pay (order);
Break
Case Pay_succeed: Case Error_occurred:finishprocess ();
Break
Default:LogUtil.printPayLog ("state isn't correct!");
Finishprocess ();
} private void Finishprocess () {this.order = null;
This.payment = null;
This.state = Paystate.pay_init;
}
}
Finally, the order class hierarchy can be designed by reference to template patterns, such as the abstract base class, which is responsible for defining the Order's operational framework and processes, and the production of specific order data is deferred to subclasses.
Payment process
This article explains the main payment process for the Android version, and the iOS version process is similar.
1. Client implementation
This article combines the operation process and the data flow, narrates the main realization plan.
First, assume that the order data is already stored in the Orderpaymodel.
The first step: the app client accesses the application server, which generates the order number and returns the client.
private void Getorderidrequest () {jsonobject OB = new Jsonobject ();
Ob.put ("Amount", orderpaymodel.getorderpricetotal ());
Ob.put ("ProductDescription", Orderpaymodel.getordername ());
Ob.put ("UserId", Orderpaymodel.getuserid ());
Ob.put ("Barcoupon", Orderpaymodel.getorderid ());
Ob.put ("Barid", Orderpaymodel.getbarid ());
Ob.put ("Count", Orderpaymodel.getordernums ());
Logutil.printpaylog ("Get Order ID Request data:" + orderpaymodel.tostring ());
Httprequestfactory.getinstance (). Dopostrequest (Urls.ali_pay_apply, OB, New Asynchttpresponsehandler () {
@Override public void onsuccess (String content) {super.onsuccess (content);
Logutil.printpaylog ("Get Order ID request is handled");
Paynewordermodel rm = new Paynewordermodel ();
RM = Json.parseobject (content, Paynewordermodel.class); if (Rm.getcode ()!= null && equalsignorecase (rm. GetCode ())) {Tradeno = Rm.getresult (). Gettrade_no ();
Logutil.printpaylog ("Succeed to get Order ID:" + tradeno);
Orderstr = Generateorder ();
Paystatemachine.getinstance (). Changestate (paystate.pay_applied_id);
else {paystatemachine.getinstance (). ReportError (Payerror.pay_apply_id_fail, "code isn't right"); @Override public void OnFailure (throwable error, String content) {Paystatemachine.getin
Stance (). ReportError (Payerror.pay_apply_id_fail, "failed to get order ID");
};
@Override public void OnFinish () {logutil.logdebug ("Payment", "On Get Order ID finish", null);
};
});
}
Step Two: Assemble the order data, including the following steps:
Create order data.
private String GetOrderInfo (string partner, string seller) {string orderInfo;
Partner ID orderInfo = "partner=" + "\" "+ Partner +" "";
Seller Alipay Account OrderInfo = "&seller_id=" + "" "+ Seller +" "";
Merchant website Unique Order number OrderInfo + + "&out_trade_no=" + "" + Tradeno + "" ";
Product Name OrderInfo + + "&subject=" + "" "+ Ordername +" "";
Product Details OrderInfo + + "&body=" + "" "+ OrderDetail +" "";
The amount of merchandise OrderInfo + + "&total_fee=" + "" "+ Totalprice +" "";
OrderInfo + + "&total_fee=" + "" "+" 0.01 "+" "";
Server Asynchronous Notification page path OrderInfo + + "¬ify_url=" + "" + urls.ali_pay_notify + "" ";
Interface name, fixed value orderInfo + = "&service=\" mobile.securitypay.pay\ "";
Payment type, fixed value orderInfo + = "&payment_type=\" 1\ ""; parameter coding, fixed value orderInfo + = "&_input_charset=\" utf-8\ "";
Set the timeout for an unpaid transaction/default of 30 minutes, and the transaction is automatically closed once the timeout is exceeded.
Value range: 1m~15d.
M-Minute, H-hour, D-Day, 1c-day (regardless of when the transaction was created, closed at 0 points).
This parameter value does not accept decimal points, such as 1.5h, and can be converted to 90m.
OrderInfo = "&it_b_pay=\" 30m\ "";
After Alipay has finished processing the request, the current page jumps to the path of the merchant's specified page.
OrderInfo = "&return_url=\" m.alipay.com\ ""; Bill:this item must not is empty!
Though the API demo said it//can be.
OrderInfo = "&return_url=\" m.alipay.com\ "";
Call the bank card payment, need to configure this parameter, participate in the signature, fixed value//OrderInfo + = "&paymethod=\" expressgateway\ "";
return orderInfo;
}
- RSA Signature on Order: Demo Code provides singutils class to implement this function, namely signutils.sign (content, rsa_private);
- URL encoding of the signature: Invoke Java Class Library interface, that is, urlencoder.encode to implement.
- Combine order data and signature information to generate data that conforms to the Alipay parameter specification:
Final String payinfo = orderInfo + "&sign=\" "+ sign +" \ "&" + Getsigntype ();
Step three: Call the Paytask pay interface in the child thread and send the request data out
Paytask Alipay = new Paytask (paydemoactivity.this);
Call the payment interface to get the payment results
String result = Alipay.pay (payinfo);
Fourth step: Receive the payment processing results of the message. The meaning of the status code of the payment result is as follows:
- The value is "9000", the representative pays successfully;
- The value is "8000" and the representative waits for a confirmation of the payment result, which may be due to a system or channel payment. The end result of the payment is subject to the server-side asynchronous notification (Alipay will be).
- Value is another, the representative fails. The client needs to prompt the user.
Precautions:
1, this article particularly needs to point out, that is, the most likely problem is the production of order data. In the Paydemoactivity class of the demo code, the GetOrderInfo method is defined. Which "OrderInfo + +" &return_url=\ "m.alipay.com\" ";" In the comment for the demo code, although it is said to be nullable, the actual situation, if empty, will cause the payment to fail. And with the failure status code, it is difficult to identify the specific reason.
2, payment results, in addition to the Alipay server sent notification to the client, the application server will also be asynchronously notified. Considering the security, the client can according to the payment Treasure Server's notice, carries on the business logic processing, for instance the order renewal and so on, but the payment data warehousing, needs the application server side according to the asynchronous notification to carry on the operation.
2, service-side implementation
service-side basic operations include: Get Alipay account information (for security, the information placed on the server, not the client), create orders, pay the results of the asynchronous callback, request refunds and other basic operations. In addition, it may include: Update orders (for support orders can be modified applications), verify the consumer code, query order records, delete orders and other operations.
This article describes a server scenario based on the Java platform. At present, the more popular frame combination is spingmvc+mybatis+mysql.
The creation of the order. When a user orders a new order (the requested data does not include the order number information), it needs to be created and the order number returned to the client. Order Class Example:
public class Payorder {public String Tradeno; Random numbered public String amount; Payment amount public String status; Operation state public String StatusCode; Operation status Code, 0-unpaid, 10-paid, 4000-refund, 5000-has been refunded, 6000-payment failed, 6001-Cancel payment, 7000-has consumed public String orderNo; Pay PO serial number public String productdescription; Commodity name public String Payno; Consumption code public String Isrefund; Whether to request a refund public String createtime; Create time public String modifytime; Modify time public String userId; User ID public Integer ID; Primary key public String pId; Commodity ID public int buynumber; Store purchase quantity public int vendorid; Merchant ID} Tradeno code order number. Payno code consumption number (consumption code).
OrderNo is the order number generated by the Alipay server side. @RequestMapping (value = "/payorder") @ResponseBody public map<string, object> Pay (HttpServletRequest request,
HttpServletResponse response) {map<string, object> Map = jsonputil.ptomap (request);
map<string, object> msgmap = new hashmap<string, object> ();
if (!map.isempty ()) {try {log.info ("Confirm action before Purchase:" + map); String now = string.valueof (System.currenttimemillis ()); String trade_no = Map.get ("Barid"). ToString () + "-" + map.get ("Barcoupon"). ToString () + "-" + map.get ("Count"). ToString ()
+ "-" + now.substring (Now.length ()-6);
Payorder Alipay = new Payorder ();
Alipay.setamount (Map.get ("Amount"). toString ());
Alipay.settradeno (TRADE_NO);
Alipay.setproductdescription (Map.get ("ProductDescription"). toString ());
Alipay.setcreatetime (now);
Alipay.setstatus ("pending payment");
Alipay.setstatuscode ("0");
Alipay.setextint1 (Integer.parseint (Map.get ("Count"). ToString ());
Alipay.setuserid (Map.get ("UserId"). toString ());
Alipay.setpid (Map.get ("Barcoupon"). toString ());
Alipay.setextint2 (Integer.parseint (Map.get ("Barid"). toString ());
int flag = Alipayserviceimpl.pay (Alipay);
Log.info ("Confirm Operation execution Result:" + flag);
Map<string, object> m = new hashmap<string, object> ();
M.put ("Trade_no", trade_no); M.put ("seller", New String (Base64.encode) (AlipayConfig.SELLER.getBytes ())));
M.put ("partner", New String (Base64.encode (AlipayConfig.partner.getBytes ()));
M.put ("Privatekey", New String (Base64.encode (AlipayConfig.ios_private_key.getBytes ()));
if (Flag > 0) msgmap = responsemessageutil.respmsg (Constance.base_success_code, "SUCCESS", m);
else Msgmap = responsemessageutil.respmsg (Constance.base_server_wrong_code, "fail");
catch (Exception e) {e.printstacktrace ();
Msgmap = responsemessageutil.respmsg (Constance.base_server_wrong_code, "fail");
Log.error ("Pre-purchase confirmation failure", e);
} else {Log.info ("Incomplete request parameters");
Msgmap = responsemessageutil.respmsg (constance.illegal_operate, "fail");
return msgmap;
}
The
Alipay server backs up the app server and notifies the payment results. App server will be the corresponding data warehousing, notify the Alipay server "success" or "fail".
@RequestMapping (value = "/payover") @ResponseBody public String payover (httpservletrequest request, httpservletrespons
E response) {map<string, string> Map = jsonputil.buildmap (request);
String result_str = "fail"; if (!map.isempty ()) {if (Alipayutils.checkalipay (map, False) > 0) {//Validate the try {Log.info by Alipay ("Pass parameters for the callback function that performs the payment:" +
MAP);
String now = string.valueof (System.currenttimemillis ());
String status = Map.get ("Trade_status"). ToString ();
Payorder Alipay = new Payorder ();
Alipay.settradeno (string.valueof) (Map.get ("Out_trade_no"));
Log.info ("Payment Status:" + status); if (Constance.ALIPAY_SUCCESS_CODE.equals (status) | |
Constance.ALIPAY_FINISHED_CODE.equals (status)) {//successful payment list<alipay> Ali = Alipayserviceimpl.search (ALIPAY); if (ali.size () = = 1 && (ali.get (0). Getpayno () = = NULL | | ali.get (0). Getpayno (). Equals ("")) {//Message not processed Alipay p
ay = new Alipay ();
Pay.settradeno (string.valueof) (Map.get ("Out_trade_no")); Pay.setstatus ("hasPayment ");
Pay.setstatuscode ("10");
Pay.setisrefund ("0");
Pay.setmodifytime (String.valueof (System.currenttimemillis ()));
Pay.setpayno (New String (Base64.encode (now.substring (Now.length ()-). GetBytes ()));
Pay.setorderno (string.valueof) (Map.get ("Trade_no"));
int flag = Alipayserviceimpl.payover (pay);
Log.info ("User Payment Success" + map);
if (Flag > 0) result_str = "Success";
} else {return result_str;
} catch (Exception e) {e.printstacktrace ();
Log.error ("Callback function Fetch parameter failed", E);
return result_str;
}} return result_str; }
The above is based on the Android Alipay payment design and development program, I hope to learn more about Android software programming help.