8 Payment system

Pico payment is a game currency payment system based on the Pico account system, and the settlement method is based on the current game currency unit under Pico (P currency).

8.1 Preparations

8.1.1 Get the string used for payment

Accesses the payment SDK, an application needs to be created on the developer platform and the corresponding string should be gotten. The application process is as follows:

  1. Log in to the developer platform and register a Pico member (http://developer.pico-interactive.com/)

  2. Apply to become a developer

The developers are divided into individual developers and enterprise developers, please apply according to the actual situations. After the review is submitted, we will provide feedback within 3 working days, please view the status of the developer platform in time.

  1. View merchant ID

Once you’ve applied to become a developer, you can view the developer ID after click on the nickname in the top right corner, i.e. the merchant ID:

_images/8.1.png

Figure 8.1 Developer ID

Note: Before applying for a developer, you need to become a member of Pico.

4.Get the corresponding string

The developers can enter from “Application Management” to the “Creation Application” phase:

_images/8.2.png

Figure 8.2 Application creation

After clicking creation application, the information about the application can be improved, including whether the application is free or paid, and how much P currency you need to pay when you pay:

_images/8.3.png

Figure 8.3 Information about application

Note: Please pay key attention to the red position of the above figure, please fill out the application type carefully, and it can’t be modified once you fill it out! After the application is successfully created, the developer platform will assign a string to it, including APPKEY, APPID, APP SECRET:

_images/8.4.png

Figure 8.4 APP ID, APP KEY, APP Secret

  1. Fill in the strings

Go to Edit->Project Settings…, expand PicoMobile under the Plugins sub-item, check “Enable Payment Module”, then select “Is Foreign” according to the actual situations, and finally get the merchant (developer) ID, APPID, APP KEY., APP secret and fill them in the following location:

_images/8.7.png

Figure 8.5 String filling

8.1.2 Set the callback proxy event

Before using payment, the callback proxy event should be set first, so that you can get the parameters output by the callback functions and set the subsequent execution flow. Here, please use the PicoPaymentSetCallbackDelegates node we provide:

_images/unsigned_7121.png

Among them, On Pico Payment Exception Callback is a callback for various exceptions from payment, and the exact meaning of the other callback function parameters will be introduced in the next section which introduces its related main callback functions.

8.3 Developer server interaction

After the payment is completed, the payment system will send the relevant payment results and user information to the merchant, and the merchant needs to receive and process them and return a response.

When the background notifies the interaction, if the receiving of the merchant’s response by the payment system receives is not successful or overtime, the notification should be considered as failed, and the payment system will periodically re-initiate the notification through certain policies to maximize the success rate of the notification, but it may not guarantee that the notification will be eventually successful.

The same notification may be sent to the merchant system repeatedly and the merchant system must be able to process duplicate notifications correctly. The recommended practice is to firstly check the status of the corresponding service data when it receives and processes the notification, and determine whether the notification has been processed, it should be re-processed if it has not been processed, and the result return will be successful directly if it has been processed. Before the status check and processing of business data, data locks should be used for concurrency control to avoid data confusion caused by function reentry.

The merchant server needs to implement the following interface for receiving the request from the Pico server and get the payment result and user information of the Pico payment system:

Table 8.2 Interfaces that the merchant server needs to implement

Name

Payment results callback interface

Request Type

POST

Request URL

Pay, parameter notify_url transmitted by PayOrder

Request Format

JSON

Return Format

JSON

Is login required

Yes

Request Parameters

For details, see “Table 8.3 Notification parameters in payment results notification”

Return parameter

_images/unsigned_7253.png

For details see “Table 8.4 Return results”

Return parameter example

{ “ret_code”:”SUCCESS”, “ret_msg”:”OK”}

Update instruction

Table 8.3 Notification parameters in payment results notification

Field Name

Param Name

Required

Type

Description

Return Status Code

ret_code

Yes

String

SUCCESS/FAIL This field is the communication identifier, rather than transaction identifier,and if the transaction is successful should be determined based on the check on result_code.

Return Message

ret_msg

No

String

For return information, in case of not empty, it may be caused due to error Signature failure and parameter format check error.

Error Code

sub_code

No

String

Error code

Error code description

sub_msg

No

String

Wrongly returned information error

Pico pay order number

trade_no

Yes

String

Pico payment order number

Merchant order number

out_trade_no

Yes

String

The order number within the merchant system

App ID

app_id

Yes

String

Application APP_ID approved by the platform

Merchant ID

mch_id

Yes

String

Assigned merchant number for payment

User ID

open_id

Yes

String

Unique identifier of the user under the merchant appid

Device ID

device_id

No

String

Terminal device number

Random string

nonce_str

Yes

String

Random string: no longer than 32 bits. Recommended random number generation algorithm

Signature

signature

Yes

String

For signature, see the signature generation algorithm

Business Result

result_code

Yes

String

SUCCESS/FAIL

Transaction type

trade_type

Yes

String

Payment type

Currency Type

fee_type

Yes

String

Currency type

Total amount

total_fee

Yes

String

Total order amount

Paid-in amount

receipt_fee

Yes

String

Paid-in amount

The amount paid by the buyer

buyer_pay_fee

No

String

The amount paid by the buyer

Voucher or Discount

coupon_fee

No

String

Voucher or discount

Merchant data package

attach

No

String

Merchant data package, returned as it is

Payment completion time

pay_time

Yes

String

Payment completion time, in the format: yyyy-MM-dd HH: mm:ss

Table 8.4 Return results

Field Name

Param

Required

Type

Description

Status code returned

ret_code

Yes

String

SUCCESS/FAIL, SUCCESS indicates that the merchant has received and verified the notification successfully.

Return information

ret_msg

No

String

For return information, in case of not empty, it may be caReturn message,if not null, it contains error message: signature failed, parameter format check error

Special remarks: The signature verification must be performed for the contents of the payment result notification in the merchant system to prevent “false notification” due to data leakage and capital loss.

The signature verification rule is as follows:

  1. Remove the signature parameter from the returned list of parameters, and simultaneously add key = “app_secret”, value=paykey, then sort it naturally according to the key value, separate the multiple parameters with &, and finally take MD5 encryption

  2. Compare the encrypted string with the get signature

The signature function is as follows:

/**
* result: Map collection of gotten data
* paykey: i.e. the paykey on the developer platform.
*/

public static String createSign(Map<String, Object> result, String paykey)
{
        if (result == null || result.size() == 0)
                return null;
        result.put("app_secret", paykey);
        String sign = result.get("signature");
        result.remove("signature");
        String[] tmp = new String[result.size()];
        int i = 0;
        for (String key : result.keySet())
        {
                tmp[i++] = key;
        }
        Arrays.sort(tmp);
        String sign = "";
        for (String string : tmp)
        {
                if (m.get(string) == null)
                        continue;
                sign += string + "=" + URLEncoder.encode(m.get(string).toString()
                        , "utf-8") + "&";
        }
        if (sign.endsWith("&"))
                sign = sign.substring(0, sign.length() - 1);
        Log.i(TAG, "createSign: " + sign);
        String localSign = MD5.MD5(sign);
        return localSign.equal(sign);
}